diff --git a/go.mod b/go.mod index 026f92b62d14c..390207d215a05 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/99designs/keyring v1.2.2 github.com/Azure/azure-event-hubs-go/v3 v3.6.2 github.com/Azure/azure-kusto-go v0.15.3 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 @@ -134,7 +135,7 @@ require ( github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b github.com/leodido/go-syslog/v4 v4.1.0 github.com/linkedin/goavro/v2 v2.13.0 - github.com/logzio/azure-monitor-metrics-receiver v1.0.2 + github.com/logzio/azure-monitor-metrics-receiver v1.1.0 github.com/lxc/incus/v6 v6.2.0 github.com/mdlayher/apcupsd v0.0.0-20220319200143-473c7b5f3c6a github.com/mdlayher/vsock v1.2.1 @@ -247,8 +248,7 @@ require ( github.com/Azure/azure-amqp-common-go/v4 v4.2.0 // indirect github.com/Azure/azure-pipeline-go v0.2.3 // indirect github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 // indirect github.com/Azure/go-amqp v1.0.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect diff --git a/go.sum b/go.sum index 41e9bb432e78f..db04ea531b9c8 100644 --- a/go.sum +++ b/go.sum @@ -646,12 +646,12 @@ github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVt github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0 h1:GJHeeA2N7xrG3q30L2UXDyuWRzDM900/65j70wcM4Ww= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 h1:H+U3Gk9zY56G3u872L82bk4thcsy2Gghb9ExT4Zvm1o= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0/go.mod h1:mgrmMSgaLp9hmax62XQTd0N4aAqSE5E0DulSpVYK7vc= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1 h1:UPeCRD+XY7QlaGQte2EVI2iOcWvUYA2XY8w5T/8v0NQ= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4 v4.2.1/go.mod h1:oGV6NlB0cvi1ZbYRR2UN44QHxWFyGk+iylgD0qaMXjA= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do= @@ -1812,8 +1812,8 @@ github.com/linkedin/goavro/v2 v2.13.0 h1:L8eI8GcuciwUkt41Ej62joSZS4kKaYIUdze+6fo github.com/linkedin/goavro/v2 v2.13.0/go.mod h1:KXx+erlq+RPlGSPmLF7xGo6SAbh8sCQ53x064+ioxhk= github.com/linode/linodego v1.23.0 h1:s0ReCZtuN9Z1IoUN9w1RLeYO1dMZUGPwOQ/IBFsBHtU= github.com/linode/linodego v1.23.0/go.mod h1:0U7wj/UQOqBNbKv1FYTXiBUXueR8DY4HvIotwE0ENgg= -github.com/logzio/azure-monitor-metrics-receiver v1.0.2 h1:1vNuag1MwjTm02BJ9U7w3hCStJug2CgPMmzI8VmEbFA= -github.com/logzio/azure-monitor-metrics-receiver v1.0.2/go.mod h1:yJGdECqN75b4r4SXLwNkeeZoN/rPVKcfJLfixQw1hZc= +github.com/logzio/azure-monitor-metrics-receiver v1.1.0 h1:L2LU/jWTOFibZeSKUeEDBdPY6iFL1gkSE3A/9mnk/Ms= +github.com/logzio/azure-monitor-metrics-receiver v1.1.0/go.mod h1:6J/ZJtFGAuv3XvLWOWTefbi1BBHvnawNjUTGcx2qUG4= github.com/loov/hrtime v1.0.1/go.mod h1:yDY3Pwv2izeY4sq7YcPX/dtLwzg5NU1AxWuWxKwd0p0= github.com/loov/hrtime v1.0.3/go.mod h1:yDY3Pwv2izeY4sq7YcPX/dtLwzg5NU1AxWuWxKwd0p0= github.com/loov/hrtime/hrplot v1.0.2/go.mod h1:9t65xYn4d42ntjv40Wt5lbU72/VC5S0zGDgjC8kD5BU= diff --git a/plugins/inputs/azure_monitor/README.md b/plugins/inputs/azure_monitor/README.md index d294532caaf64..61d3f6c81d73f 100644 --- a/plugins/inputs/azure_monitor/README.md +++ b/plugins/inputs/azure_monitor/README.md @@ -25,6 +25,11 @@ resource target `resource_id` can be found under **Overview**->**Essentials**->**JSON View** (link) in the Azure portal for your application/service. +`cloud_option` defines the optional value for the API endpoints in case you +are using the solution to get the metrics from the Azure Sovereign Cloud +shipment e.g. AzureChina, AzureGovernment or AzurePublic. +The default value is AzurePublic + ## More Information To see a table of resource types and their metrics, please use this link: @@ -77,6 +82,8 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details. client_secret = "<>" # can be found under Azure Active Directory->Properties tenant_id = "<>" + # Define the optional Azure cloud option e.g. AzureChina, AzureGovernment or AzurePublic | DEFAULT AzurePublic + cloud_option = "<>" # resource target #1 to collect metrics from [[inputs.azure_monitor.resource_target]] diff --git a/plugins/inputs/azure_monitor/azure_monitor.go b/plugins/inputs/azure_monitor/azure_monitor.go index 28167ffb1d5cd..e488cd37f73ca 100644 --- a/plugins/inputs/azure_monitor/azure_monitor.go +++ b/plugins/inputs/azure_monitor/azure_monitor.go @@ -4,6 +4,8 @@ package azure_monitor import ( _ "embed" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "sync" @@ -17,6 +19,7 @@ type AzureMonitor struct { ClientID string `toml:"client_id"` ClientSecret string `toml:"client_secret"` TenantID string `toml:"tenant_id"` + CloudOption string `toml:"cloud_option,omitempty"` ResourceTargets []*ResourceTarget `toml:"resource_target"` ResourceGroupTargets []*ResourceGroupTarget `toml:"resource_group_target"` SubscriptionTargets []*Resource `toml:"subscription_target"` @@ -47,7 +50,8 @@ type Resource struct { type azureClientsManager struct{} type azureClientsCreator interface { - createAzureClients(subscriptionID string, clientID string, clientSecret string, tenantID string) (*receiver.AzureClients, error) + createAzureClients(subscriptionID string, clientID string, clientSecret string, tenantID string, + clientOptions azcore.ClientOptions) (*receiver.AzureClients, error) } //go:embed sample.conf @@ -59,8 +63,20 @@ func (am *AzureMonitor) SampleConfig() string { // Init is for setup, and validating config. func (am *AzureMonitor) Init() error { + var clientOptions = azcore.ClientOptions{Cloud: cloud.AzurePublic} + if len(am.CloudOption) != 0 { + switch cloudOption := am.CloudOption; cloudOption { + case "AzureChina": + clientOptions = azcore.ClientOptions{Cloud: cloud.AzureChina} + case "AzureGovernment": + clientOptions = azcore.ClientOptions{Cloud: cloud.AzureGovernment} + case "AzurePublic": + clientOptions = azcore.ClientOptions{Cloud: cloud.AzurePublic} + } + } + var err error - am.azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID) + am.azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID, clientOptions) if err != nil { return err } @@ -150,7 +166,7 @@ func (am *AzureMonitor) setReceiver() error { targets := receiver.NewTargets(resourceTargets, resourceGroupTargets, subscriptionTargets) var err error - am.receiver, err = receiver.NewAzureMonitorMetricsReceiver(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID, targets, am.azureClients) + am.receiver, err = receiver.NewAzureMonitorMetricsReceiver(am.SubscriptionID, targets, am.azureClients) return err } @@ -159,16 +175,18 @@ func (acm *azureClientsManager) createAzureClients( clientID string, clientSecret string, tenantID string, + clientOptions azcore.ClientOptions, ) (*receiver.AzureClients, error) { if clientSecret != "" { - return receiver.CreateAzureClients(subscriptionID, clientID, clientSecret, tenantID) + return receiver.CreateAzureClients(subscriptionID, clientID, clientSecret, tenantID, receiver.WithAzureClientOptions(&clientOptions)) } - token, err := azidentity.NewDefaultAzureCredential(&azidentity.DefaultAzureCredentialOptions{TenantID: tenantID}) + token, err := azidentity.NewDefaultAzureCredential(&azidentity.DefaultAzureCredentialOptions{TenantID: tenantID, + ClientOptions: clientOptions}) if err != nil { return nil, fmt.Errorf("error creating Azure token: %w", err) } - return receiver.CreateAzureClientsWithCreds(subscriptionID, token) + return receiver.CreateAzureClientsWithCreds(subscriptionID, token, receiver.WithAzureClientOptions(&clientOptions)) } func init() { diff --git a/plugins/inputs/azure_monitor/azure_monitor_test.go b/plugins/inputs/azure_monitor/azure_monitor_test.go index 707f78e9e425f..e31fe0db87634 100644 --- a/plugins/inputs/azure_monitor/azure_monitor_test.go +++ b/plugins/inputs/azure_monitor/azure_monitor_test.go @@ -5,6 +5,8 @@ import ( "encoding/json" "errors" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" "os" "testing" @@ -25,7 +27,7 @@ type mockAzureMetricDefinitionsClient struct{} type mockAzureMetricsClient struct{} -func (mam *mockAzureClientsManager) createAzureClients(_ string, _ string, _ string, _ string) (*receiver.AzureClients, error) { +func (mam *mockAzureClientsManager) createAzureClients(_ string, _ string, _ string, _ string, _ azcore.ClientOptions) (*receiver.AzureClients, error) { return &receiver.AzureClients{ Ctx: context.Background(), ResourcesClient: &mockAzureResourcesClient{}, @@ -958,16 +960,15 @@ func TestGather_Success(t *testing.T) { resourceTargets = append(resourceTargets, receiver.NewResourceTarget(target.ResourceID, target.Metrics, target.Aggregations)) } + var clientOptions = azcore.ClientOptions{Cloud: cloud.AzurePublic} + var azureClients *receiver.AzureClients - azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID) + azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID, clientOptions) require.NoError(t, err) require.NotNil(t, azureClients) am.receiver, err = receiver.NewAzureMonitorMetricsReceiver( am.SubscriptionID, - am.ClientID, - am.ClientSecret, - am.TenantID, receiver.NewTargets(resourceTargets, []*receiver.ResourceGroupTarget{}, []*receiver.Resource{}), azureClients, ) @@ -1028,3 +1029,102 @@ func TestGather_Success(t *testing.T) { acc.AssertContainsTaggedFields(t, expectedResource2Metric1Name, expectedResource2Metric1MetricFields, expectedResource2MetricsTags) acc.AssertContainsTaggedFields(t, expectedResource3Metric1Name, expectedResource3Metric1MetricFields, expectedResource3MetricsTags) } + +func TestGather_China_Success(t *testing.T) { + file, err := os.ReadFile("testdata/toml/gather_success_cloud_option_china.toml") + require.NoError(t, err) + require.NotNil(t, file) + require.NotEmpty(t, file) + + var am *AzureMonitor + require.NoError(t, toml.Unmarshal(file, &am)) + + am.Log = testutil.Logger{} + am.azureManager = &mockAzureClientsManager{} + + resourceTargets := make([]*receiver.ResourceTarget, 0, len(am.ResourceTargets)) + for _, target := range am.ResourceTargets { + resourceTargets = append(resourceTargets, receiver.NewResourceTarget(target.ResourceID, target.Metrics, target.Aggregations)) + } + + var clientOptions = azcore.ClientOptions{Cloud: cloud.AzureChina} + + var azureClients *receiver.AzureClients + azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID, clientOptions) + require.NoError(t, err) + require.NotNil(t, azureClients) + + am.receiver, err = receiver.NewAzureMonitorMetricsReceiver( + am.SubscriptionID, + receiver.NewTargets(resourceTargets, []*receiver.ResourceGroupTarget{}, []*receiver.Resource{}), + azureClients, + ) + require.NoError(t, err) + require.NotNil(t, am.receiver) +} + +func TestGather_Government_Success(t *testing.T) { + file, err := os.ReadFile("testdata/toml/gather_success_cloud_option_government.toml") + require.NoError(t, err) + require.NotNil(t, file) + require.NotEmpty(t, file) + + var am *AzureMonitor + require.NoError(t, toml.Unmarshal(file, &am)) + + am.Log = testutil.Logger{} + am.azureManager = &mockAzureClientsManager{} + + resourceTargets := make([]*receiver.ResourceTarget, 0, len(am.ResourceTargets)) + for _, target := range am.ResourceTargets { + resourceTargets = append(resourceTargets, receiver.NewResourceTarget(target.ResourceID, target.Metrics, target.Aggregations)) + } + + var clientOptions = azcore.ClientOptions{Cloud: cloud.AzureGovernment} + + var azureClients *receiver.AzureClients + azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID, clientOptions) + require.NoError(t, err) + require.NotNil(t, azureClients) + + am.receiver, err = receiver.NewAzureMonitorMetricsReceiver( + am.SubscriptionID, + receiver.NewTargets(resourceTargets, []*receiver.ResourceGroupTarget{}, []*receiver.Resource{}), + azureClients, + ) + require.NoError(t, err) + require.NotNil(t, am.receiver) +} + +func TestGather_Public_Success(t *testing.T) { + file, err := os.ReadFile("testdata/toml/gather_success_cloud_option_public.toml") + require.NoError(t, err) + require.NotNil(t, file) + require.NotEmpty(t, file) + + var am *AzureMonitor + require.NoError(t, toml.Unmarshal(file, &am)) + + am.Log = testutil.Logger{} + am.azureManager = &mockAzureClientsManager{} + + resourceTargets := make([]*receiver.ResourceTarget, 0, len(am.ResourceTargets)) + for _, target := range am.ResourceTargets { + resourceTargets = append(resourceTargets, receiver.NewResourceTarget(target.ResourceID, target.Metrics, target.Aggregations)) + } + + var clientOptions = azcore.ClientOptions{Cloud: cloud.AzurePublic} + + var azureClients *receiver.AzureClients + azureClients, err = am.azureManager.createAzureClients(am.SubscriptionID, am.ClientID, am.ClientSecret, am.TenantID, clientOptions) + require.NoError(t, err) + require.NotNil(t, azureClients) + + am.receiver, err = receiver.NewAzureMonitorMetricsReceiver( + am.SubscriptionID, + receiver.NewTargets(resourceTargets, []*receiver.ResourceGroupTarget{}, []*receiver.Resource{}), + azureClients, + ) + require.NoError(t, err) + require.NotNil(t, am.receiver) +} diff --git a/plugins/inputs/azure_monitor/sample.conf b/plugins/inputs/azure_monitor/sample.conf index a0052f2dfb9ea..cebfebbbfac55 100644 --- a/plugins/inputs/azure_monitor/sample.conf +++ b/plugins/inputs/azure_monitor/sample.conf @@ -14,6 +14,8 @@ client_secret = "<>" # can be found under Azure Active Directory->Properties tenant_id = "<>" + # Define the optional Azure cloud option e.g. AzureChina, AzureGovernment or AzurePublic | DEFAULT AzurePublic + cloud_option = "<>" # resource target #1 to collect metrics from [[inputs.azure_monitor.resource_target]] diff --git a/plugins/inputs/azure_monitor/testdata/toml/gather_success_cloud_option_china.toml b/plugins/inputs/azure_monitor/testdata/toml/gather_success_cloud_option_china.toml new file mode 100644 index 0000000000000..ec5a7e98b20bf --- /dev/null +++ b/plugins/inputs/azure_monitor/testdata/toml/gather_success_cloud_option_china.toml @@ -0,0 +1,10 @@ +subscription_id = "subscriptionID" +client_id = "clientID" +client_secret = "clientSecret" +tenant_id = "tenantID" +cloud_option = "AzureChina" + + [[resource_target]] + resource_id = "resourceGroups/resourceGroup1/providers/Microsoft.Test/type1/resource1" + metrics = ["metric1", "metric2"] + aggregations = ["Total", "Maximum"] diff --git a/plugins/inputs/azure_monitor/testdata/toml/gather_success_cloud_option_government.toml b/plugins/inputs/azure_monitor/testdata/toml/gather_success_cloud_option_government.toml new file mode 100644 index 0000000000000..e7b5a31691e2d --- /dev/null +++ b/plugins/inputs/azure_monitor/testdata/toml/gather_success_cloud_option_government.toml @@ -0,0 +1,10 @@ +subscription_id = "subscriptionID" +client_id = "clientID" +client_secret = "clientSecret" +tenant_id = "tenantID" +cloud_option = "AzureGovernment" + + [[resource_target]] + resource_id = "resourceGroups/resourceGroup1/providers/Microsoft.Test/type1/resource1" + metrics = ["metric1", "metric2"] + aggregations = ["Total", "Maximum"] diff --git a/plugins/inputs/azure_monitor/testdata/toml/gather_success_cloud_option_public.toml b/plugins/inputs/azure_monitor/testdata/toml/gather_success_cloud_option_public.toml new file mode 100644 index 0000000000000..b1dd09c3447e0 --- /dev/null +++ b/plugins/inputs/azure_monitor/testdata/toml/gather_success_cloud_option_public.toml @@ -0,0 +1,10 @@ +subscription_id = "subscriptionID" +client_id = "clientID" +client_secret = "clientSecret" +tenant_id = "tenantID" +cloud_option = "AzurePublic" + + [[resource_target]] + resource_id = "resourceGroups/resourceGroup1/providers/Microsoft.Test/type1/resource1" + metrics = ["metric1", "metric2"] + aggregations = ["Total", "Maximum"] \ No newline at end of file