From bbc7e530212d31c17c5e10ef8208702d43dd5c61 Mon Sep 17 00:00:00 2001 From: "alexey.komyakov" Date: Tue, 5 Nov 2024 13:56:15 +0300 Subject: [PATCH] fixes Signed-off-by: alexey.komyakov --- pkg/providers/amazon/amazon.go | 29 ++++++++++++++++------------- pkg/providers/k8s/k8s.go | 29 +++++++++++++++++++++++++++++ pkg/providers/provider.go | 24 ++++++++++++++++++------ pkg/registry/checker.go | 29 +++++++++++++++-------------- pkg/registry/indexers.go | 13 ++----------- 5 files changed, 80 insertions(+), 44 deletions(-) create mode 100644 pkg/providers/k8s/k8s.go diff --git a/pkg/providers/amazon/amazon.go b/pkg/providers/amazon/amazon.go index e787606..bce0b23 100644 --- a/pkg/providers/amazon/amazon.go +++ b/pkg/providers/amazon/amazon.go @@ -3,51 +3,54 @@ package amazon import ( "context" "encoding/base64" - "fmt" "strings" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/ecr" "github.com/google/go-containerregistry/pkg/authn" + "github.com/sirupsen/logrus" ) -type AwsECRProvider struct{} +type Provider struct{} -func NewECRProvider() *AwsECRProvider { - return &AwsECRProvider{} +func NewProvider() *Provider { + return &Provider{} } -func (p *AwsECRProvider) GetAuthKeychain(ctx context.Context, registryStr string) (authn.Keychain, error) { - ecrClient, err := awsRegionalClient(ctx, parseECRDetails(registryStr)) +func (p Provider) GetAuthKeychain(registryStr string) authn.Keychain { + ecrClient, err := awsRegionalClient(context.TODO(), parseECRDetails(registryStr)) if err != nil { - return nil, fmt.Errorf("error loading AWS config: %w", err) + logrus.Panic(err) } - authTokenOutput, err := ecrClient.GetAuthorizationToken(ctx, &ecr.GetAuthorizationTokenInput{}) + authTokenOutput, err := ecrClient.GetAuthorizationToken(context.TODO(), &ecr.GetAuthorizationTokenInput{}) if err != nil { - return nil, fmt.Errorf("error getting ECR authorization token: %w", err) + logrus.Panic(err) } if len(authTokenOutput.AuthorizationData) == 0 { - return nil, fmt.Errorf("no authorization data received from ECR") + logrus.Panic("no authorization data received from ECR") + return nil } authData := authTokenOutput.AuthorizationData[0] decodedToken, err := base64.StdEncoding.DecodeString(*authData.AuthorizationToken) if err != nil { - return nil, fmt.Errorf("error decoding authorization token: %w", err) + logrus.Panic("error decoding authorization token: %w", err) + return nil } credentials := strings.SplitN(string(decodedToken), ":", 2) if len(credentials) != 2 { - return nil, fmt.Errorf("invalid authorization token format") + logrus.Panic("invalid authorization token format") + return nil } authConfig := authn.AuthConfig{ Username: credentials[0], Password: credentials[1], } auth := authn.FromConfig(authConfig) - return &customKeychain{authenticator: auth}, nil + return &customKeychain{authenticator: auth} } func parseECRDetails(registryStr string) string { diff --git a/pkg/providers/k8s/k8s.go b/pkg/providers/k8s/k8s.go new file mode 100644 index 0000000..2fc012b --- /dev/null +++ b/pkg/providers/k8s/k8s.go @@ -0,0 +1,29 @@ +package k8s + +import ( + "context" + kubeauth "github.com/google/go-containerregistry/pkg/authn/kubernetes" + "github.com/sirupsen/logrus" + corev1 "k8s.io/api/core/v1" + + "github.com/google/go-containerregistry/pkg/authn" +) + +type Provider struct { + pullSecretsGetter func(image string) []corev1.Secret +} + +func NewProvider(pullSecretsGetter func(image string) []corev1.Secret) *Provider { + return &Provider{ + pullSecretsGetter: pullSecretsGetter, + } +} + +func (p Provider) GetAuthKeychain(registryStr string) authn.Keychain { + dereferencedPullSecrets := p.pullSecretsGetter(registryStr) + kc, err := kubeauth.NewFromPullSecrets(context.TODO(), dereferencedPullSecrets) + if err != nil { + logrus.Panic(err) + } + return kc +} diff --git a/pkg/providers/provider.go b/pkg/providers/provider.go index e0535d4..074daf7 100644 --- a/pkg/providers/provider.go +++ b/pkg/providers/provider.go @@ -1,23 +1,35 @@ package providers import ( - "context" - "fmt" + corev1 "k8s.io/api/core/v1" "strings" "github.com/flant/k8s-image-availability-exporter/pkg/providers/amazon" + "github.com/flant/k8s-image-availability-exporter/pkg/providers/k8s" "github.com/google/go-containerregistry/pkg/authn" ) type Provider interface { - GetAuthKeychain(ctx context.Context, registryStr string) (authn.Keychain, error) + GetAuthKeychain(registryStr string) authn.Keychain } -func GetProvider(registryStr string) (Provider, error) { +type ProviderRegistry map[string]Provider + +func NewProviderChain(pullSecretsGetter func(image string) []corev1.Secret) ProviderRegistry { + return map[string]Provider{ + "amazon": amazon.NewProvider(), + "k8s": k8s.NewProvider(pullSecretsGetter), + } +} + +type ImagePullSecretsFunc func(image string) []corev1.Secret + +func (p ProviderRegistry) GetAuthKeychain(registryStr string) authn.Keychain { switch { case strings.Contains(registryStr, "amazonaws.com"): - return amazon.NewECRProvider(), nil + return p["amazon"].GetAuthKeychain(registryStr) + default: - return nil, fmt.Errorf("unsupported registry") + return p["k8s"].GetAuthKeychain(registryStr) } } diff --git a/pkg/registry/checker.go b/pkg/registry/checker.go index 43b7e05..45df139 100644 --- a/pkg/registry/checker.go +++ b/pkg/registry/checker.go @@ -6,18 +6,18 @@ import ( "crypto/x509" "errors" "fmt" - "net/http" - "os" - "regexp" - "strings" - "time" - "github.com/flant/k8s-image-availability-exporter/pkg/providers" "github.com/flant/k8s-image-availability-exporter/pkg/version" "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/v1/remote/transport" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/tools/cache" + "net/http" + "os" + "regexp" + "strings" + "time" "github.com/prometheus/client_golang/prometheus" @@ -69,6 +69,8 @@ type Checker struct { kubeClient *kubernetes.Clientset config registryCheckerConfig + + providerRegistry providers.ProviderRegistry } func NewChecker( @@ -254,6 +256,12 @@ func NewChecker( rc.imageStore.RunGC(rc.controllerIndexers.GetContainerInfosForImage) + pullSecretsGetter := func(image string) []corev1.Secret { + return rc.controllerIndexers.GetImagePullSecrets(image) + } + pc := providers.NewProviderChain(pullSecretsGetter) + rc.providerRegistry = pc + return rc } @@ -291,7 +299,7 @@ imagesLoop: } func (rc *Checker) Check(imageName string) store.AvailabilityMode { - keyChain := rc.controllerIndexers.GetKeychainForImage(imageName) + keyChain := rc.providerRegistry.GetAuthKeychain(imageName) log := logrus.WithField("image_name", imageName) return rc.checkImageAvailability(log, imageName, keyChain) @@ -316,13 +324,6 @@ func (rc *Checker) checkImageAvailability(log *logrus.Entry, imageName string, k if err != nil { return checkImageNameParseErr(log, err) } - p, err := providers.GetProvider(ref.Context().RegistryStr()) - if err == nil { - kChain, err := p.GetAuthKeychain(context.TODO(), ref.Context().RegistryStr()) - if err == nil { - kc = kChain - } - } imgErr := wait.ExponentialBackoff(wait.Backoff{ Duration: time.Second, diff --git a/pkg/registry/indexers.go b/pkg/registry/indexers.go index 086e15e..c79a7a3 100644 --- a/pkg/registry/indexers.go +++ b/pkg/registry/indexers.go @@ -1,14 +1,11 @@ package registry import ( - "context" "fmt" "slices" "strings" "github.com/flant/k8s-image-availability-exporter/pkg/store" - "github.com/google/go-containerregistry/pkg/authn" - kubeauth "github.com/google/go-containerregistry/pkg/authn/kubernetes" "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" batchv1 "k8s.io/api/batch/v1" @@ -257,7 +254,7 @@ func (ci ControllerIndexers) GetContainerInfosForImage(image string) (ret []stor return } -func (ci ControllerIndexers) GetKeychainForImage(image string) authn.Keychain { +func (ci ControllerIndexers) GetImagePullSecrets(image string) []corev1.Secret { objs := ci.GetObjectsByImageIndex(image) var refSet = map[string]struct{}{} @@ -284,11 +281,5 @@ func (ci ControllerIndexers) GetKeychainForImage(image string) authn.Keychain { if len(dereferencedPullSecrets) == 0 { return nil } - - kc, err := kubeauth.NewFromPullSecrets(context.TODO(), dereferencedPullSecrets) - if err != nil { - logrus.Panic(err) - } - - return kc + return dereferencedPullSecrets }