From 1a6fbb3f1c9e2d02f15a9aa0db81d65b1ee953a1 Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Tue, 20 Aug 2024 10:24:27 +0200 Subject: [PATCH 01/14] Add aks support. --- aks.go | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++ aks_test.go | 148 +++++++++++++++++++++++++++++++++++++++ go.mod | 21 ++++-- go.sum | 61 +++++++++++----- kubernetes.go | 55 +++++++++++++++ main.go | 5 +- 6 files changed, 454 insertions(+), 23 deletions(-) create mode 100644 aks.go create mode 100644 aks_test.go diff --git a/aks.go b/aks.go new file mode 100644 index 0000000..0a748e0 --- /dev/null +++ b/aks.go @@ -0,0 +1,187 @@ +package main + +import ( + "context" + "errors" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute" + "github.com/prometheus/client_golang/prometheus" + log "github.com/sirupsen/logrus" + "maps" + "strings" + "time" +) + +var ( + ErrAzureTooManyTags error = errors.New("Only up to 50 tags can be set on an azure resource") + ErrAzureValueToLong error = errors.New("A value can only contain 256 characters") +) + +type DiskTags = map[string]*string +type AzureSubscription = string + +type AzureClient interface { + GetDiskTags(ctx context.Context, subscription AzureSubscription, resourceGroupName string, diskName string) (DiskTags, error) + SetDiskTags(ctx context.Context, subscription AzureSubscription, resourceGroupName string, diskName string, tags DiskTags) error +} + +type azureClient struct { + credentials azcore.TokenCredential + clients map[AzureSubscription]*armcompute.DisksClient +} + +func NewAzureClient() (AzureClient, error) { + creds, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + return nil, err + } + + return azureClient{creds, map[AzureSubscription]*armcompute.DisksClient{}}, err +} + +func (self azureClient) getClient(subscriptionID AzureSubscription) (*armcompute.DisksClient, error) { + if client, ok := self.clients[subscriptionID]; ok { + return client, nil + } + + client, err := armcompute.NewDisksClient(subscriptionID, self.credentials, &arm.ClientOptions{}) + if err != nil { + return nil, err + } + + self.clients[subscriptionID] = client + return client, nil +} + +func (self azureClient) GetDiskTags(ctx context.Context, subscription AzureSubscription, resourceGroupName string, diskName string) (DiskTags, error) { + client, err := self.getClient(subscription) + if err != nil { + return nil, err + } + + disk, err := client.Get(ctx, resourceGroupName, diskName, &armcompute.DisksClientGetOptions{}) + if err != nil { + return nil, fmt.Errorf("could not get the tags for: %w", err) + } + return disk.Tags, nil +} + +func (self azureClient) SetDiskTags(ctx context.Context, subscription AzureSubscription, resourceGroupName string, diskName string, tags DiskTags) error { + client, err := self.getClient(subscription) + if err != nil { + return err + } + + poller, err := client.BeginUpdate(ctx, resourceGroupName, diskName, armcompute.DiskUpdate{Tags: tags}, &armcompute.DisksClientBeginUpdateOptions{}) + if err != nil { + return fmt.Errorf("could not set the tags for: %w", err) + } + + _, err = poller.PollUntilDone(ctx, &runtime.PollUntilDoneOptions{5 * time.Second}) + if err != nil { + return fmt.Errorf("could not set the tags for failed at polling: %w", err) + } + return nil +} + +func parseAzureVolumeID(volumeID string) (subscription string, resourceGroup string, diskName string, err error) { + // '/subscriptions/{subscription}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/disks/{diskname}"' + fields := strings.Split(volumeID, "/") + if len(fields) != 9 { + return "", "", "", errors.New("invalid volume id") + } + subscription = fields[2] + resourceGroup = fields[4] + diskName = fields[8] + return subscription, resourceGroup, diskName, nil +} + +func sanitizeLabelsForAzure(tags map[string]string) (DiskTags, error) { + diskTags := make(DiskTags) + if len(tags) > 50 { + return nil, ErrAzureTooManyTags + } + for k, v := range tags { + k = sanitizeKeyForAzure(k) + value, err := sanitizeValueForAzure(v) + if err != nil { + return nil, err + } + + diskTags[k] = &value + } + + return diskTags, nil +} + +func sanitizeKeyForAzure(s string) string { + // remove forbidden characters + if strings.ContainsAny(s, `<>%&\?/`) { + for _, c := range `<>%&\?/` { + s = strings.ReplaceAll(s, string(c), "") + } + } + + // truncate the key the max length for azure + if len(s) > 512 { + s = s[:512] + } + + return s +} + +func sanitizeValueForAzure(s string) (string, error) { + // the value can contain at most 256 characters + if len(s) > 256 { + return "", fmt.Errorf("%s value is invalid: %w", s, ErrAzureValueToLong) + } + return s, nil +} + +func UpdateAzurePodLabels(ctx context.Context, client AzureClient, volumeID string, tags map[string]string, removedTags []string, storageclass string) error { + sanitizedLabels, err := sanitizeLabelsForAzure(tags) + if err != nil { + return err + } + + log.Debugf("labels to add to PD volume: %s: %v", volumeID, sanitizedLabels) + subscription, resourceGroup, diskName, err := parseAzureVolumeID(volumeID) + if err != nil { + return err + } + + existingTags, err := client.GetDiskTags(ctx, subscription, resourceGroup, diskName) + if err != nil { + return err + } + + // merge existing disk labels with new labels: + updatedTags := make(DiskTags) + if existingTags != nil { + updatedTags = maps.Clone(existingTags) + } + maps.Copy(updatedTags, sanitizedLabels) + + for _, tag := range removedTags { + delete(updatedTags, tag) + } + + if maps.Equal(existingTags, updatedTags) { + log.Debug("labels already set on PD") + return nil + } + + err = client.SetDiskTags(ctx, subscription, resourceGroup, diskName, updatedTags) + if err != nil { + promActionsTotal.With(prometheus.Labels{"status": "error", "storageclass": storageclass}).Inc() + return err + } + + log.Debug("successfully set labels on PD") + promActionsTotal.With(prometheus.Labels{"status": "success", "storageclass": storageclass}).Inc() + return nil +} diff --git a/aks_test.go b/aks_test.go new file mode 100644 index 0000000..571a5ba --- /dev/null +++ b/aks_test.go @@ -0,0 +1,148 @@ +package main + +import ( + "fmt" + "github.com/stretchr/testify/assert" + "strings" + "testing" +) + +func Test_parseAzureVolumeID(t *testing.T) { + type args struct { + volumeID string + } + tests := []struct { + name string + args args + wantSubscription string + wantResourceGroup string + wantDiskName string + wantErr bool + }{ + { + name: "test using a correct volume ID", + args: args{volumeID: "/subscriptions/{subscription}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/disks/{diskname}"}, + wantSubscription: "{subscription}", + wantResourceGroup: "{resourceGroup}", + wantDiskName: "{diskname}", + wantErr: false, + }, + { + name: "test using a correct volume ID", + args: args{volumeID: "/subscriptions/{subscription}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/disks"}, + wantSubscription: "", + wantResourceGroup: "", + wantDiskName: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + gotSubscription, gotResourceGroup, gotDiskName, err := parseAzureVolumeID(tt.args.volumeID) + if (err != nil) != tt.wantErr { + t.Errorf("parseAzureVolumeID() error = %v, wantErr %v", err, tt.wantErr) + return + } + if gotSubscription != tt.wantSubscription { + t.Errorf("parseAzureVolumeID() gotSubscription = %v, want %v", gotSubscription, tt.wantSubscription) + } + if gotResourceGroup != tt.wantResourceGroup { + t.Errorf("parseAzureVolumeID() gotResourceGroup = %v, want %v", gotResourceGroup, tt.wantResourceGroup) + } + if gotDiskName != tt.wantDiskName { + t.Errorf("parseAzureVolumeID() gotDiskName = %v, want %v", gotDiskName, tt.wantDiskName) + } + }) + } +} + +func Test_sanitizeKeyForAzure(t *testing.T) { + type args struct { + s string + } + var tests = []struct { + name string + args args + want string + }{ + { + name: "the key should be trimmed to 512 characters", + args: args{ + s: strings.Repeat("1", 513), + }, + want: strings.Repeat("1", 512), + }, + { + name: "the key should remove all invalid characters", + args: args{ + s: `1<>&\?%/`, + }, + want: "1", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + if got := sanitizeKeyForAzure(tt.args.s); got != tt.want { + t.Errorf("sanitizeKeyForAzure() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_sanitizeValueForAzure(t *testing.T) { + type args struct { + s string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "a valid value", + args: args{strings.Repeat("1", 256)}, + want: strings.Repeat("1", 256), + wantErr: false, + }, + + { + name: "the max value lenght is 256 characters", + args: args{strings.Repeat("1", 257)}, + want: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + got, err := sanitizeValueForAzure(tt.args.s) + if (err != nil) != tt.wantErr { + t.Errorf("sanitizeValueForAzure() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("sanitizeValueForAzure() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_sanitizeLabelsForAzure(t *testing.T) { + t.Run("azure supports up to 50 labels", func(t *testing.T) { + t.Parallel() + tags := map[string]string{} + for x := 0; x < 50; x++ { + v := fmt.Sprintf("%d", x) + tags[v] = v + } + _, err := sanitizeLabelsForAzure(tags) + assert.NoError(t, err) + + tags["51"] = "51" + _, err = sanitizeLabelsForAzure(tags) + assert.ErrorIs(t, err, ErrAzureTooManyTags) + }) +} diff --git a/go.mod b/go.mod index 7d013c0..c3bcd8e 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,14 @@ module github.com/mtougeron/k8s-pvc-tagger go 1.21 require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 github.com/aws/aws-sdk-go v1.49.9 github.com/google/uuid v1.6.0 github.com/prometheus/client_golang v1.17.0 github.com/sirupsen/logrus v1.9.3 + github.com/stretchr/testify v1.9.0 google.golang.org/api v0.180.0 k8s.io/api v0.29.0 k8s.io/apimachinery v0.29.0 @@ -17,6 +21,8 @@ require ( cloud.google.com/go/auth v0.4.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -29,6 +35,7 @@ require ( github.com/go-openapi/jsonreference v0.20.4 // indirect github.com/go-openapi/swag v0.22.6 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt v3.2.1+incompatible // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect @@ -41,27 +48,31 @@ require ( github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/spf13/pflag v1.0.5 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/net v0.25.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/term v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/term v0.22.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 // indirect google.golang.org/grpc v1.63.2 // indirect diff --git a/go.sum b/go.sum index d94fbcf..fefd51f 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,22 @@ cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKF cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0 h1:sVPhtT2qjO86rTUaWMr4WoES4TkjGnzcioXcnHV9s5k= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0 h1:Yoicul8bnVdQrhDMTHxdEckRGX01XvwXDHUT9zYZ3k0= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 h1:/Di3vB4sNeQ+7A8efjUVENvyB945Wruvstucqp7ZArg= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0/go.mod h1:gM3K25LQlsET3QR+4V74zxCsFAy0r6xMNN9n80SZn+4= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0 h1:lMW1lD/17LUA5z1XTURo7LcVG2ICBPlyMHjIUrcFZNQ= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0/go.mod h1:ceIuwmxDWptoW3eCqSXlnPsZFKh4X+R38dWPv7GS9Vs= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.0.0 h1:nBy98uKOIfun5z6wx6jwWLrULcM0+cjBalBFZlEZ7CA= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.0.0/go.mod h1:243D9iHbcQXoFUtgHJwL7gl2zx1aDuDMjvBZVGr2uW0= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 h1:ECsQtyERDVz3NP3kvDOTLvbQhqWp/x9EsGKtb4ogUr8= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0/go.mod h1:s1tW/At+xHqjNFvWU4G0c0Qv33KOhvbGNj0RCTQDV8s= +github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 h1:WVsrXCnHlDDX8ls+tootqRE87/hL9S/g4ewig9RsD/c= +github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aws/aws-sdk-go v1.49.9 h1:4xoyi707rsifB1yMsd5vGbAH21aBzwpL3gNRMSmjIyc= github.com/aws/aws-sdk-go v1.49.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= @@ -18,6 +34,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= +github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -44,6 +62,10 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= +github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -78,6 +100,7 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJY github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -101,6 +124,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= @@ -110,12 +135,15 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -129,8 +157,8 @@ github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lne github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -143,8 +171,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= @@ -160,8 +188,8 @@ go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -177,8 +205,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -193,15 +221,16 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -212,8 +241,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/kubernetes.go b/kubernetes.go index 39a7df0..166bb9f 100644 --- a/kubernetes.go +++ b/kubernetes.go @@ -63,6 +63,9 @@ const ( AWS_EFS_CSI = "efs.csi.aws.com" AWS_FSX_CSI = "fsx.csi.aws.com" + // supported AZURE storage provisioners: + AZURE_DISK_CSI = "disk.csi.azure.com" + // supported GCP storage provisioners: GCP_PD_CSI = "pd.csi.storage.gke.io" GCP_PD_LEGACY = "kubernetes.io/gce-pd" @@ -118,12 +121,19 @@ func watchForPersistentVolumeClaims(ch chan struct{}, watchNamespace string) { var ec2Client *EBSClient var fsxClient *FSxClient var gcpClient GCPClient + var azureClient AzureClient switch cloud { case AWS: efsClient, _ = newEFSClient() ec2Client, _ = newEC2Client() fsxClient, _ = newFSxClient() + case AZURE: + // see how to get the credentials with a service account and the subscription + azureClient, err = NewAzureClient() + if err != nil { + log.Fatalln("failed to create Azure client", err) + } case GCP: gcpClient, err = newGCPClient(context.Background()) if err != nil { @@ -156,6 +166,14 @@ func watchForPersistentVolumeClaims(ch chan struct{}, watchNamespace string) { if provisionedByAwsFsx(pvc) { fsxClient.addFSxVolumeTags(volumeID, tags, *pvc.Spec.StorageClassName) } + case AZURE: + if provisionedByAzureDisk(pvc) { + err = UpdateAzurePodLabels(context.Background(), azureClient, volumeID, tags, []string{}, *pvc.Spec.StorageClassName) + if err != nil { + log.WithFields(log.Fields{"namespace": pvc.GetNamespace(), "pvc": pvc.GetName()}).Error("failed to update persistent volume") + } + } + case GCP: if !provisionedByGcpPD(pvc) { return @@ -223,6 +241,21 @@ func watchForPersistentVolumeClaims(ch chan struct{}, watchNamespace string) { fsxClient.deleteFSxVolumeTags(volumeID, deletedTagsPtr, *oldPVC.Spec.StorageClassName) } } + case AZURE: + if !provisionedByAzureDisk(newPVC) { + var deletedTags []string + oldTags := buildTags(oldPVC) + for k := range oldTags { + if _, ok := tags[k]; !ok { + deletedTags = append(deletedTags, k) + } + } + err := UpdateAzurePodLabels(context.Background(), azureClient, volumeID, tags, deletedTags, *newPVC.Spec.StorageClassName) + if err != nil { + log.WithFields(log.Fields{"namespace": newPVC.GetNamespace(), "pvc": newPVC.GetName()}).Error("failed to update persistent volume") + } + } + return case GCP: if !provisionedByGcpPD(newPVC) { return @@ -252,6 +285,26 @@ func watchForPersistentVolumeClaims(ch chan struct{}, watchNamespace string) { informer.Run(ch) } +func provisionedByAzureDisk(pvc *corev1.PersistentVolumeClaim) bool { + annotations := pvc.GetAnnotations() + if annotations == nil { + return false + } + + provisionedBy, ok := getProvisionedBy(annotations) + if !ok { + log.WithFields(log.Fields{"namespace": pvc.GetNamespace(), "pvc": pvc.GetName()}).Debugln("no volume.kubernetes.io/storage-provisioner annotation") + return false + } + + switch provisionedBy { + case AZURE_DISK_CSI: + log.WithFields(log.Fields{"namespace": pvc.GetNamespace(), "pvc": pvc.GetName()}).Debugln(AWS_EBS_LEGACY + " volume") + return true + } + return false +} + func convertTagsToFSxTags(tags map[string]string) []*fsx.Tag { convertedTags := []*fsx.Tag{} for tagKey, tagValue := range tags { @@ -560,6 +613,8 @@ func processPersistentVolumeClaim(pvc *corev1.PersistentVolumeClaim) (string, ma volumeID = pv.Spec.CSI.VolumeHandle case GCP_PD_LEGACY: volumeID = pv.Spec.GCEPersistentDisk.PDName + case AZURE_DISK_CSI: + volumeID = pv.Spec.CSI.VolumeHandle case GCP_PD_CSI: volumeID = pv.Spec.CSI.VolumeHandle } diff --git a/main.go b/main.go index 5b913e3..32eb2c3 100644 --- a/main.go +++ b/main.go @@ -90,8 +90,9 @@ var ( ) const ( - AWS = "aws" - GCP = "gcp" + AWS = "aws" + AZURE = "azure" + GCP = "gcp" ) func init() { From aa6be98040f6c95a23272af6b99a23089a888cf3 Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Fri, 23 Aug 2024 14:03:26 +0200 Subject: [PATCH 02/14] Update the readme and cli info. --- README.md | 5 ++++- main.go | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4aceceb..ac53c42 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ metadata: ### Multi-cloud support -Currently supported clouds: AWS, GCP. +Currently supported clouds: AWS, GCP, Azure Only one mode is active at a given time. Specify the cloud `k8s-pvc-tagger` is running in with the `--cloud` flag. Either `aws` or `gcp`. @@ -117,6 +117,9 @@ gcloud iam roles create CustomDiskRole \ --stage="GA" ``` +#### Azure rule +The default role `Tag Contributor` can be used to configure the access rights for the pvc-tagger. + #### Install via helm ``` diff --git a/main.go b/main.go index 32eb2c3..73a5dbc 100644 --- a/main.go +++ b/main.go @@ -143,7 +143,7 @@ func main() { flag.StringVar(&statusPort, "status-port", "8000", "The healthz port") flag.StringVar(&metricsPort, "metrics-port", "8001", "The prometheus metrics port") flag.BoolVar(&allowAllTags, "allow-all-tags", false, "Whether or not to allow any tag, even Kubernetes assigned ones, to be set") - flag.StringVar(&cloud, "cloud", AWS, "The cloud provider (aws or gcp)") + flag.StringVar(&cloud, "cloud", AWS, "The cloud provider (aws, gcp or azure)") flag.StringVar(©LabelsString, "copy-labels", "", "Comma-separated list of PVC labels to copy to volumes. Use '*' to copy all labels. (default \"\")") flag.Parse() From d6fdbf363dcac8016950e750b060cb8ab9025d0f Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Fri, 23 Aug 2024 14:03:47 +0200 Subject: [PATCH 03/14] Update the readme and cli info. --- main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main.go b/main.go index 73a5dbc..151a0ae 100644 --- a/main.go +++ b/main.go @@ -182,6 +182,8 @@ func main() { } case GCP: log.Infoln("Running in GCP mode") + case AZURE: + log.Infoln("Running in Azure mode") default: log.Fatalln("Cloud provider must be either aws or gcp") } From 49bb0c04a3e1c230c2dbb8deb976a7c3ff665070 Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Fri, 23 Aug 2024 14:04:31 +0200 Subject: [PATCH 04/14] Add the .idea folder to git ignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2be0ea8..943497a 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ # vendor/ cosign.* +.idea \ No newline at end of file From 61fde97c6023229cf3afe1a29e1c7ee0f8522bda Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Mon, 26 Aug 2024 11:15:19 +0200 Subject: [PATCH 05/14] Azure tagging works --- Dockerfile | 3 ++- aks.go | 58 +++++++++++++++++++-------------------------------- go.mod | 14 ++++++------- go.sum | 48 +++++++++++++++++++----------------------- kubernetes.go | 6 +++--- 5 files changed, 55 insertions(+), 74 deletions(-) diff --git a/Dockerfile b/Dockerfile index c5e0708..1646eb2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,8 @@ RUN addgroup -S k8s-pvc-tagger && adduser -S k8s-pvc-tagger -G k8s-pvc-tagger # Build a small image FROM scratch COPY --from=builder /etc/passwd /etc/passwd -USER k8s-pvc-tagger +ENV APP_NAME=k8s-pvc-tagger + # https://github.com/aws/aws-sdk-go/issues/2322 COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /app/${APP_NAME} / diff --git a/aks.go b/aks.go index 0a748e0..8898c56 100644 --- a/aks.go +++ b/aks.go @@ -4,16 +4,14 @@ import ( "context" "errors" "fmt" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" "github.com/prometheus/client_golang/prometheus" log "github.com/sirupsen/logrus" "maps" "strings" - "time" ) var ( @@ -30,8 +28,7 @@ type AzureClient interface { } type azureClient struct { - credentials azcore.TokenCredential - clients map[AzureSubscription]*armcompute.DisksClient + client *armresources.TagsClient } func NewAzureClient() (AzureClient, error) { @@ -39,52 +36,41 @@ func NewAzureClient() (AzureClient, error) { if err != nil { return nil, err } - - return azureClient{creds, map[AzureSubscription]*armcompute.DisksClient{}}, err -} - -func (self azureClient) getClient(subscriptionID AzureSubscription) (*armcompute.DisksClient, error) { - if client, ok := self.clients[subscriptionID]; ok { - return client, nil - } - - client, err := armcompute.NewDisksClient(subscriptionID, self.credentials, &arm.ClientOptions{}) + client, err := armresources.NewTagsClient("", creds, &arm.ClientOptions{}) if err != nil { return nil, err } - self.clients[subscriptionID] = client - return client, nil + return azureClient{client}, err +} + +func diskScope(subscription string, resourceGroupName string, diskName string) string { + return fmt.Sprintf("subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/disks/%s", subscription, resourceGroupName, diskName) } func (self azureClient) GetDiskTags(ctx context.Context, subscription AzureSubscription, resourceGroupName string, diskName string) (DiskTags, error) { - client, err := self.getClient(subscription) - if err != nil { - return nil, err - } - disk, err := client.Get(ctx, resourceGroupName, diskName, &armcompute.DisksClientGetOptions{}) + tags, err := self.client.GetAtScope(ctx, diskScope(subscription, resourceGroupName, diskName), &armresources.TagsClientGetAtScopeOptions{}) if err != nil { return nil, fmt.Errorf("could not get the tags for: %w", err) } - return disk.Tags, nil + + return tags.Properties.Tags, nil } func (self azureClient) SetDiskTags(ctx context.Context, subscription AzureSubscription, resourceGroupName string, diskName string, tags DiskTags) error { - client, err := self.getClient(subscription) - if err != nil { - return err - } - - poller, err := client.BeginUpdate(ctx, resourceGroupName, diskName, armcompute.DiskUpdate{Tags: tags}, &armcompute.DisksClientBeginUpdateOptions{}) + response, err := self.client.UpdateAtScope( + ctx, + diskScope(subscription, resourceGroupName, diskName), + armresources.TagsPatchResource{ + to.Ptr(armresources.TagsPatchOperationReplace), + &armresources.Tags{Tags: tags}, + }, &armresources.TagsClientUpdateAtScopeOptions{}, + ) if err != nil { return fmt.Errorf("could not set the tags for: %w", err) } - - _, err = poller.PollUntilDone(ctx, &runtime.PollUntilDoneOptions{5 * time.Second}) - if err != nil { - return fmt.Errorf("could not set the tags for failed at polling: %w", err) - } + log.WithFields(log.Fields{"disk": diskName, "resource-group": resourceGroupName}).Debug("updated disk tags to tags=%v", response.Properties.Tags) return nil } @@ -142,7 +128,7 @@ func sanitizeValueForAzure(s string) (string, error) { return s, nil } -func UpdateAzurePodLabels(ctx context.Context, client AzureClient, volumeID string, tags map[string]string, removedTags []string, storageclass string) error { +func UpdateAzureVolumeTags(ctx context.Context, client AzureClient, volumeID string, tags map[string]string, removedTags []string, storageclass string) error { sanitizedLabels, err := sanitizeLabelsForAzure(tags) if err != nil { return err diff --git a/go.mod b/go.mod index c3bcd8e..19c84a4 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/mtougeron/k8s-pvc-tagger go 1.21 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0 - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 github.com/aws/aws-sdk-go v1.49.9 github.com/google/uuid v1.6.0 github.com/prometheus/client_golang v1.17.0 @@ -21,8 +21,8 @@ require ( cloud.google.com/go/auth v0.4.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -35,7 +35,7 @@ require ( github.com/go-openapi/jsonreference v0.20.4 // indirect github.com/go-openapi/swag v0.22.6 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt v3.2.1+incompatible // indirect + github.com/golang-jwt/jwt/v5 v5.0.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect @@ -54,7 +54,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect diff --git a/go.sum b/go.sum index fefd51f..00d20d9 100644 --- a/go.sum +++ b/go.sum @@ -5,22 +5,20 @@ cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKF cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0 h1:sVPhtT2qjO86rTUaWMr4WoES4TkjGnzcioXcnHV9s5k= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0 h1:Yoicul8bnVdQrhDMTHxdEckRGX01XvwXDHUT9zYZ3k0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0 h1:/Di3vB4sNeQ+7A8efjUVENvyB945Wruvstucqp7ZArg= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute v1.0.0/go.mod h1:gM3K25LQlsET3QR+4V74zxCsFAy0r6xMNN9n80SZn+4= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0 h1:lMW1lD/17LUA5z1XTURo7LcVG2ICBPlyMHjIUrcFZNQ= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.0.0/go.mod h1:ceIuwmxDWptoW3eCqSXlnPsZFKh4X+R38dWPv7GS9Vs= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.0.0 h1:nBy98uKOIfun5z6wx6jwWLrULcM0+cjBalBFZlEZ7CA= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.0.0/go.mod h1:243D9iHbcQXoFUtgHJwL7gl2zx1aDuDMjvBZVGr2uW0= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 h1:ECsQtyERDVz3NP3kvDOTLvbQhqWp/x9EsGKtb4ogUr8= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0/go.mod h1:s1tW/At+xHqjNFvWU4G0c0Qv33KOhvbGNj0RCTQDV8s= -github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 h1:WVsrXCnHlDDX8ls+tootqRE87/hL9S/g4ewig9RsD/c= -github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 h1:fb8kj/Dh4CSwgsOzHeZY4Xh68cFVbzXx+ONXGMY//4w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 h1:d81/ng9rET2YqdVkVwkb6EXeRrLJIwyGnJcAlAWKwhs= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2/go.mod h1:FbdwsQ2EzwvXxOPcMFYO8ogEc9uMMIj3YkmCdXdAFmk= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0 h1:pPvTJ1dY0sA35JOeFq6TsY2xj6Z85Yo23Pj4wCCvu4o= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0/go.mod h1:mLfWfj8v3jfWKsL9G4eoBoXVcsqcIUTapmdKy7uGOp0= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aws/aws-sdk-go v1.49.9 h1:4xoyi707rsifB1yMsd5vGbAH21aBzwpL3gNRMSmjIyc= github.com/aws/aws-sdk-go v1.49.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= @@ -34,8 +32,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= -github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -62,10 +60,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -100,7 +96,6 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJY github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -135,15 +130,14 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -221,7 +215,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/kubernetes.go b/kubernetes.go index 166bb9f..735458e 100644 --- a/kubernetes.go +++ b/kubernetes.go @@ -168,9 +168,9 @@ func watchForPersistentVolumeClaims(ch chan struct{}, watchNamespace string) { } case AZURE: if provisionedByAzureDisk(pvc) { - err = UpdateAzurePodLabels(context.Background(), azureClient, volumeID, tags, []string{}, *pvc.Spec.StorageClassName) + err = UpdateAzureVolumeTags(context.Background(), azureClient, volumeID, tags, []string{}, *pvc.Spec.StorageClassName) if err != nil { - log.WithFields(log.Fields{"namespace": pvc.GetNamespace(), "pvc": pvc.GetName()}).Error("failed to update persistent volume") + log.WithFields(log.Fields{"namespace": pvc.GetNamespace(), "pvc": pvc.GetName(), "error": err.Error()}).Error("failed to update persistent volume") } } @@ -250,7 +250,7 @@ func watchForPersistentVolumeClaims(ch chan struct{}, watchNamespace string) { deletedTags = append(deletedTags, k) } } - err := UpdateAzurePodLabels(context.Background(), azureClient, volumeID, tags, deletedTags, *newPVC.Spec.StorageClassName) + err := UpdateAzureVolumeTags(context.Background(), azureClient, volumeID, tags, deletedTags, *newPVC.Spec.StorageClassName) if err != nil { log.WithFields(log.Fields{"namespace": newPVC.GetNamespace(), "pvc": newPVC.GetName()}).Error("failed to update persistent volume") } From 7c583fd8a9dd8fc8534705a79c1c74f43034e97f Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Mon, 26 Aug 2024 11:19:30 +0200 Subject: [PATCH 06/14] Add a unittest for the resourceScope. --- aks.go | 2 +- aks_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/aks.go b/aks.go index 8898c56..6b75575 100644 --- a/aks.go +++ b/aks.go @@ -70,7 +70,7 @@ func (self azureClient) SetDiskTags(ctx context.Context, subscription AzureSubsc if err != nil { return fmt.Errorf("could not set the tags for: %w", err) } - log.WithFields(log.Fields{"disk": diskName, "resource-group": resourceGroupName}).Debug("updated disk tags to tags=%v", response.Properties.Tags) + log.WithFields(log.Fields{"disk": diskName, "resource-group": resourceGroupName}).Debugf("updated disk tags to tags=%v", response.Properties.Tags) return nil } diff --git a/aks_test.go b/aks_test.go index 571a5ba..c1125ea 100644 --- a/aks_test.go +++ b/aks_test.go @@ -146,3 +146,31 @@ func Test_sanitizeLabelsForAzure(t *testing.T) { assert.ErrorIs(t, err, ErrAzureTooManyTags) }) } + +func Test_diskScope(t *testing.T) { + type args struct { + subscription string + resourceGroupName string + diskName string + } + tests := []struct { + name string + args args + want string + }{ + { + "it should generate a valid scope for disks", + args{ + subscription: "sub", + resourceGroupName: "resource-name", + diskName: "disk-name", + }, + "subscriptions/sub/resourceGroups/resource-name/providers/Microsoft.Compute/disks/disk-name", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, diskScope(tt.args.subscription, tt.args.resourceGroupName, tt.args.diskName), "diskScope(%v, %v, %v)", tt.args.subscription, tt.args.resourceGroupName, tt.args.diskName) + }) + } +} From ad171dd071a02b3a26a16c2f6cb14d2ac7476c76 Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Tue, 27 Aug 2024 12:47:24 +0200 Subject: [PATCH 07/14] Increase the azure lib versions. --- go.mod | 15 +++++++-------- go.sum | 36 +++++++++++++++++------------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/go.mod b/go.mod index 19c84a4..e051ac7 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/mtougeron/k8s-pvc-tagger go 1.21 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 github.com/aws/aws-sdk-go v1.49.9 github.com/google/uuid v1.6.0 github.com/prometheus/client_golang v1.17.0 @@ -21,8 +21,8 @@ require ( cloud.google.com/go/auth v0.4.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -35,7 +35,7 @@ require ( github.com/go-openapi/jsonreference v0.20.4 // indirect github.com/go-openapi/swag v0.22.6 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v5 v5.0.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect @@ -54,13 +54,12 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/spf13/pflag v1.0.5 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect diff --git a/go.sum b/go.sum index 00d20d9..0937bd1 100644 --- a/go.sum +++ b/go.sum @@ -5,20 +5,20 @@ cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKF cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0 h1:fb8kj/Dh4CSwgsOzHeZY4Xh68cFVbzXx+ONXGMY//4w= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.0/go.mod h1:uReU2sSxZExRPBAg3qKzmAucSi51+SP1OhohieR821Q= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0/go.mod h1:1fXstnBMas5kzG+S3q8UoJcmyU6nUeunJcMDHcRYHhs= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0 h1:d81/ng9rET2YqdVkVwkb6EXeRrLJIwyGnJcAlAWKwhs= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.0/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2/go.mod h1:FbdwsQ2EzwvXxOPcMFYO8ogEc9uMMIj3YkmCdXdAFmk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.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.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/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0/go.mod h1:LRr2FzBTQlONPPa5HREE5+RjSCTXl7BwOvYOaWTqCaI= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0 h1:pPvTJ1dY0sA35JOeFq6TsY2xj6Z85Yo23Pj4wCCvu4o= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0/go.mod h1:mLfWfj8v3jfWKsL9G4eoBoXVcsqcIUTapmdKy7uGOp0= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw= -github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1 h1:WpB/QDNLpMw72xHJc34BNNykqSOeEJDAWkhf0u12/Jk= -github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aws/aws-sdk-go v1.49.9 h1:4xoyi707rsifB1yMsd5vGbAH21aBzwpL3gNRMSmjIyc= github.com/aws/aws-sdk-go v1.49.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= @@ -32,8 +32,6 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -60,8 +58,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= -github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -136,8 +134,8 @@ github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4 github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -215,8 +213,8 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= From 2ac08083632e39e7645f405c50e21b24c5a84a63 Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Wed, 4 Dec 2024 10:37:11 +0100 Subject: [PATCH 08/14] Add USER back to Dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 1646eb2..35a4f54 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,6 +37,7 @@ RUN addgroup -S k8s-pvc-tagger && adduser -S k8s-pvc-tagger -G k8s-pvc-tagger # Build a small image FROM scratch COPY --from=builder /etc/passwd /etc/passwd +USER k8s-pvc-tagger ENV APP_NAME=k8s-pvc-tagger # https://github.com/aws/aws-sdk-go/issues/2322 From 06829d58b0c043479a97676f9d115fba52bb835d Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Wed, 4 Dec 2024 10:40:12 +0100 Subject: [PATCH 09/14] Fix wrong logger field of AZURE_DISK_CSI --- kubernetes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes.go b/kubernetes.go index 735458e..46153e7 100644 --- a/kubernetes.go +++ b/kubernetes.go @@ -299,7 +299,7 @@ func provisionedByAzureDisk(pvc *corev1.PersistentVolumeClaim) bool { switch provisionedBy { case AZURE_DISK_CSI: - log.WithFields(log.Fields{"namespace": pvc.GetNamespace(), "pvc": pvc.GetName()}).Debugln(AWS_EBS_LEGACY + " volume") + log.WithFields(log.Fields{"namespace": pvc.GetNamespace(), "pvc": pvc.GetName()}).Debugln(AZURE_DISK_CSI + " volume") return true } return false From f7b981ffa2fc73becf81f5efb477b3a820bd9bef Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Wed, 4 Dec 2024 10:40:58 +0100 Subject: [PATCH 10/14] Rename aks files to azure --- aks.go => azure.go | 0 aks_test.go => azure_test.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename aks.go => azure.go (100%) rename aks_test.go => azure_test.go (100%) diff --git a/aks.go b/azure.go similarity index 100% rename from aks.go rename to azure.go diff --git a/aks_test.go b/azure_test.go similarity index 100% rename from aks_test.go rename to azure_test.go From f0927f5e5c4117e6198ecd4720236e9cc0d13ec5 Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Wed, 4 Dec 2024 11:13:55 +0100 Subject: [PATCH 11/14] Make duplicated keys after sanitization an error. --- azure.go | 12 ++++++++---- azure_test.go | 9 +++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/azure.go b/azure.go index 6b75575..236911b 100644 --- a/azure.go +++ b/azure.go @@ -15,8 +15,9 @@ import ( ) var ( - ErrAzureTooManyTags error = errors.New("Only up to 50 tags can be set on an azure resource") - ErrAzureValueToLong error = errors.New("A value can only contain 256 characters") + ErrAzureTooManyTags error = errors.New("Only up to 50 tags can be set on an azure resource") + ErrAzureValueToLong error = errors.New("A value can only contain 256 characters") + ErrAzureDuplicatedTags error = errors.New("There are duplicated keys after sanitization") ) type DiskTags = map[string]*string @@ -92,13 +93,16 @@ func sanitizeLabelsForAzure(tags map[string]string) (DiskTags, error) { return nil, ErrAzureTooManyTags } for k, v := range tags { - k = sanitizeKeyForAzure(k) + sanitizedKey := sanitizeKeyForAzure(k) value, err := sanitizeValueForAzure(v) if err != nil { return nil, err } - diskTags[k] = &value + if _, ok := diskTags[sanitizedKey]; ok { + return nil, fmt.Errorf("tag is duplicated after sanitization colliding tags key=%s sanitized-key=%s: %w", k, sanitizedKey, ErrAzureDuplicatedTags) + } + diskTags[sanitizedKey] = &value } return diskTags, nil diff --git a/azure_test.go b/azure_test.go index c1125ea..def4940 100644 --- a/azure_test.go +++ b/azure_test.go @@ -145,6 +145,15 @@ func Test_sanitizeLabelsForAzure(t *testing.T) { _, err = sanitizeLabelsForAzure(tags) assert.ErrorIs(t, err, ErrAzureTooManyTags) }) + + t.Run("the sanitize lables gives an error when there a duplicated tags after sanitization", func(t *testing.T) { + t.Parallel() + tags := map[string]string{} + tags["Kubernetes/Cluster"] = "foo" + tags["KubernetesCluster"] = "bar" + _, err := sanitizeLabelsForAzure(tags) + assert.ErrorIs(t, err, ErrAzureDuplicatedTags) + }) } func Test_diskScope(t *testing.T) { From fd9cb5535de49ad4e688c307c95d184d52fa7ddc Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Wed, 4 Dec 2024 11:27:43 +0100 Subject: [PATCH 12/14] Document the failure cases when in azure mode and the limits of azure. --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ac53c42..67c4e26 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,18 @@ gcloud iam roles create CustomDiskRole \ ``` #### Azure rule -The default role `Tag Contributor` can be used to configure the access rights for the pvc-tagger. +The [default role `Tag Contributor`](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/management-and-governance#tag-contributor) can be used to configure the access rights for the pvc-tagger. +At the moment this only supports csi-volumes are supported. +Because the kubernetes tags are richer than what you can set in azure we sanitize the tags for you: + +- The invalid characters in key are removed: `<>%&\?/` +This results in `Kubernetes/Cluster` to become `KubernetesCluster`. +- tags longer than to 512 characters are truncated + +We generate an error in case there any of these limits are breached: +- tag values are limited to 256 characters +- the tag count is limted to 50 tags +- when a tag after sanitization collides with another tag, `KubernetesCluster` and `Kubernetes/Cluster` #### Install via helm From 0478f7afdfba2ea5c853aad2fbe48f0ef132d75a Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Wed, 4 Dec 2024 11:51:46 +0100 Subject: [PATCH 13/14] fix typos --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 67c4e26..3d74628 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ Only one mode is active at a given time. Specify the cloud `k8s-pvc-tagger` is r If not specified `--cloud aws` is the default mode. -> NOTE: GCP labels have constraints that do not match the contraints allowed by Kubernetes labels. When running in GCP mode labels will be modified to fit GCP's constraints, if necessary. The main difference is `.` and `/` are not allowed, so a label such as `dom.tld/key` will be converted to `dom-tld_key`. +> NOTE: GCP labels have constraints that do not match the constraints allowed by Kubernetes labels. When running in GCP mode labels will be modified to fit GCP's constraints, if necessary. The main difference is `.` and `/` are not allowed, so a label such as `dom.tld/key` will be converted to `dom-tld_key`. ### Installation @@ -122,14 +122,14 @@ The [default role `Tag Contributor`](https://learn.microsoft.com/en-us/azure/rol At the moment this only supports csi-volumes are supported. Because the kubernetes tags are richer than what you can set in azure we sanitize the tags for you: -- The invalid characters in key are removed: `<>%&\?/` -This results in `Kubernetes/Cluster` to become `KubernetesCluster`. +- The invalid characters in key are replaced with `_`: `<>%&\?/` +This results in `Kubernetes/Cluster` to become `Kubernetes_Cluster`. - tags longer than to 512 characters are truncated We generate an error in case there any of these limits are breached: - tag values are limited to 256 characters -- the tag count is limted to 50 tags -- when a tag after sanitization collides with another tag, `KubernetesCluster` and `Kubernetes/Cluster` +- the tag count is limited to 50 tags +- when a tag after sanitization collides with another tag, `Kubernetes_Cluster` and `Kubernetes/Cluster` #### Install via helm From 0dc6e3b2ab456f78c37b3eab773dc72ba0179543 Mon Sep 17 00:00:00 2001 From: Boris Smidt Date: Wed, 4 Dec 2024 11:54:45 +0100 Subject: [PATCH 14/14] made the azure behavior consistent with the other the other google. --- azure.go | 2 +- azure_test.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/azure.go b/azure.go index 236911b..dbf9e61 100644 --- a/azure.go +++ b/azure.go @@ -112,7 +112,7 @@ func sanitizeKeyForAzure(s string) string { // remove forbidden characters if strings.ContainsAny(s, `<>%&\?/`) { for _, c := range `<>%&\?/` { - s = strings.ReplaceAll(s, string(c), "") + s = strings.ReplaceAll(s, string(c), "_") } } diff --git a/azure_test.go b/azure_test.go index def4940..b3866ad 100644 --- a/azure_test.go +++ b/azure_test.go @@ -78,7 +78,7 @@ func Test_sanitizeKeyForAzure(t *testing.T) { args: args{ s: `1<>&\?%/`, }, - want: "1", + want: "1_______", }, } for _, tt := range tests { @@ -109,7 +109,7 @@ func Test_sanitizeValueForAzure(t *testing.T) { }, { - name: "the max value lenght is 256 characters", + name: "the max value length is 256 characters", args: args{strings.Repeat("1", 257)}, want: "", wantErr: true, @@ -146,11 +146,11 @@ func Test_sanitizeLabelsForAzure(t *testing.T) { assert.ErrorIs(t, err, ErrAzureTooManyTags) }) - t.Run("the sanitize lables gives an error when there a duplicated tags after sanitization", func(t *testing.T) { + t.Run("the sanitize labels gives an error when there a duplicated tags after sanitization", func(t *testing.T) { t.Parallel() tags := map[string]string{} tags["Kubernetes/Cluster"] = "foo" - tags["KubernetesCluster"] = "bar" + tags["Kubernetes_Cluster"] = "bar" _, err := sanitizeLabelsForAzure(tags) assert.ErrorIs(t, err, ErrAzureDuplicatedTags) })