feat(inputs.azure_monitor): Add client options parameter (#15519)

This commit is contained in:
Pascal Zimmermann 2024-08-07 21:52:48 +02:00 committed by GitHub
parent 66a042f592
commit ad55f42d53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 177 additions and 66 deletions

6
go.mod
View File

@ -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

12
go.sum
View File

@ -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/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do=
@ -1813,8 +1813,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.35.0 h1:rIhUeCHBLEDlkoRnOTwzSGzljQ3ksXwLxacmXnrV+Do=
github.com/linode/linodego v1.35.0/go.mod h1:JxuhOEAMfSxun6RU5/MgTKH2GGTmFrhKRj3wL1NFin0=
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=

View File

@ -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 = "<<CLIENT_SECRET>>"
# can be found under Azure Active Directory->Properties
tenant_id = "<<TENANT_ID>>"
# Define the optional Azure cloud option e.g. AzureChina, AzureGovernment or AzurePublic. The default is AzurePublic.
# cloud_option = "AzurePublic"
# resource target #1 to collect metrics from
[[inputs.azure_monitor.resource_target]]

View File

@ -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
switch am.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}
default:
return fmt.Errorf("unknown cloud option: %s", am.CloudOption)
}
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() {

View File

@ -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{},
@ -612,51 +614,6 @@ func TestInit_NoSubscriptionID(t *testing.T) {
require.Error(t, am.Init())
}
func TestInit_NoClientID(t *testing.T) {
file, err := os.ReadFile("testdata/toml/init_no_client_id.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{}
require.Error(t, am.Init())
}
func TestInit_NoClientSecret(t *testing.T) {
file, err := os.ReadFile("testdata/toml/init_no_client_secret.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{}
require.Error(t, am.Init())
}
func TestInit_NoTenantID(t *testing.T) {
file, err := os.ReadFile("testdata/toml/init_no_tenant_id.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{}
require.Error(t, am.Init())
}
func TestInit_NoTargets(t *testing.T) {
file, err := os.ReadFile("testdata/toml/init_no_targets.toml")
require.NoError(t, err)
@ -952,22 +909,20 @@ func TestGather_Success(t *testing.T) {
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)
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 +983,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)
}

View File

@ -14,6 +14,8 @@
client_secret = "<<CLIENT_SECRET>>"
# can be found under Azure Active Directory->Properties
tenant_id = "<<TENANT_ID>>"
# Define the optional Azure cloud option e.g. AzureChina, AzureGovernment or AzurePublic. The default is AzurePublic.
# cloud_option = "AzurePublic"
# resource target #1 to collect metrics from
[[inputs.azure_monitor.resource_target]]

View File

@ -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"]

View File

@ -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"]

View File

@ -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"]