|
|
|
@ -30,6 +30,7 @@ import (
|
|
|
|
|
"github.com/go-kit/log" |
|
|
|
|
"github.com/go-kit/log/level" |
|
|
|
|
"github.com/pkg/errors" |
|
|
|
|
"github.com/prometheus/client_golang/prometheus" |
|
|
|
|
config_util "github.com/prometheus/common/config" |
|
|
|
|
"github.com/prometheus/common/model" |
|
|
|
|
"github.com/prometheus/common/version" |
|
|
|
@ -70,10 +71,17 @@ var (
|
|
|
|
|
AuthenticationMethod: authMethodOAuth, |
|
|
|
|
HTTPClientConfig: config_util.DefaultHTTPClientConfig, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
failuresCount = prometheus.NewCounter( |
|
|
|
|
prometheus.CounterOpts{ |
|
|
|
|
Name: "prometheus_sd_azure_failures_total", |
|
|
|
|
Help: "Number of Azure service discovery refresh failures.", |
|
|
|
|
}) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
func init() { |
|
|
|
|
discovery.RegisterConfig(&SDConfig{}) |
|
|
|
|
prometheus.MustRegister(failuresCount) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// SDConfig is the configuration for Azure based service discovery.
|
|
|
|
@ -279,11 +287,13 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
|
|
|
|
|
|
|
|
|
|
client, err := createAzureClient(*d.cfg) |
|
|
|
|
if err != nil { |
|
|
|
|
failuresCount.Inc() |
|
|
|
|
return nil, errors.Wrap(err, "could not create Azure client") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
machines, err := client.getVMs(ctx, d.cfg.ResourceGroup) |
|
|
|
|
if err != nil { |
|
|
|
|
failuresCount.Inc() |
|
|
|
|
return nil, errors.Wrap(err, "could not get virtual machines") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -292,12 +302,14 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
|
|
|
|
|
// Load the vms managed by scale sets.
|
|
|
|
|
scaleSets, err := client.getScaleSets(ctx, d.cfg.ResourceGroup) |
|
|
|
|
if err != nil { |
|
|
|
|
failuresCount.Inc() |
|
|
|
|
return nil, errors.Wrap(err, "could not get virtual machine scale sets") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for _, scaleSet := range scaleSets { |
|
|
|
|
scaleSetVms, err := client.getScaleSetVMs(ctx, scaleSet) |
|
|
|
|
if err != nil { |
|
|
|
|
failuresCount.Inc() |
|
|
|
|
return nil, errors.Wrap(err, "could not get virtual machine scale set vms") |
|
|
|
|
} |
|
|
|
|
machines = append(machines, scaleSetVms...) |
|
|
|
@ -313,8 +325,8 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
|
|
|
|
|
var wg sync.WaitGroup |
|
|
|
|
wg.Add(len(machines)) |
|
|
|
|
ch := make(chan target, len(machines)) |
|
|
|
|
for i, vm := range machines { |
|
|
|
|
go func(i int, vm virtualMachine) { |
|
|
|
|
for _, vm := range machines { |
|
|
|
|
go func(vm virtualMachine) { |
|
|
|
|
defer wg.Done() |
|
|
|
|
r, err := newAzureResourceFromID(vm.ID, d.logger) |
|
|
|
|
if err != nil { |
|
|
|
@ -346,8 +358,11 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
|
|
|
|
|
for _, nicID := range vm.NetworkInterfaces { |
|
|
|
|
networkInterface, err := client.getNetworkInterfaceByID(ctx, nicID) |
|
|
|
|
if err != nil { |
|
|
|
|
level.Error(d.logger).Log("msg", "Unable to get network interface", "name", nicID, "err", err) |
|
|
|
|
ch <- target{labelSet: nil, err: err} |
|
|
|
|
if errors.Is(err, errorNotFound) { |
|
|
|
|
level.Warn(d.logger).Log("msg", "Network interface does not exist", "name", nicID, "err", err) |
|
|
|
|
} else { |
|
|
|
|
ch <- target{labelSet: nil, err: err} |
|
|
|
|
} |
|
|
|
|
// Get out of this routine because we cannot continue without a network interface.
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
@ -387,7 +402,7 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}(i, vm) |
|
|
|
|
}(vm) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
wg.Wait() |
|
|
|
@ -396,6 +411,7 @@ func (d *Discovery) refresh(ctx context.Context) ([]*targetgroup.Group, error) {
|
|
|
|
|
var tg targetgroup.Group |
|
|
|
|
for tgt := range ch { |
|
|
|
|
if tgt.err != nil { |
|
|
|
|
failuresCount.Inc() |
|
|
|
|
return nil, errors.Wrap(tgt.err, "unable to complete Azure service discovery") |
|
|
|
|
} |
|
|
|
|
if tgt.labelSet != nil { |
|
|
|
@ -561,6 +577,11 @@ func mapFromVMScaleSetVM(vm compute.VirtualMachineScaleSetVM, scaleSetName strin
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var errorNotFound = errors.New("network interface does not exist") |
|
|
|
|
|
|
|
|
|
// getNetworkInterfaceByID gets the network interface.
|
|
|
|
|
// If a 404 is returned from the Azure API, `errorNotFound` is returned.
|
|
|
|
|
// On all other errors, an autorest.DetailedError is returned.
|
|
|
|
|
func (client *azureClient) getNetworkInterfaceByID(ctx context.Context, networkInterfaceID string) (*network.Interface, error) { |
|
|
|
|
result := network.Interface{} |
|
|
|
|
queryParameters := map[string]interface{}{ |
|
|
|
@ -585,6 +606,9 @@ func (client *azureClient) getNetworkInterfaceByID(ctx context.Context, networkI
|
|
|
|
|
|
|
|
|
|
result, err = client.nic.GetResponder(resp) |
|
|
|
|
if err != nil { |
|
|
|
|
if resp.StatusCode == http.StatusNotFound { |
|
|
|
|
return nil, errorNotFound |
|
|
|
|
} |
|
|
|
|
return nil, autorest.NewErrorWithError(err, "network.InterfacesClient", "Get", resp, "Failure responding to request") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|