From bc3c17ca5db47cdd3e0174282696f59a975d7286 Mon Sep 17 00:00:00 2001 From: xuezhao Date: Mon, 19 Feb 2024 16:40:02 +0800 Subject: [PATCH] Create Empty Image Pull Secret when no default image pull secret sepcified. (#313) Signed-off-by: GitHub --- pkg/bootstrap/imagepullsecret.go | 26 ++++++--- pkg/bootstrap/imagepullsecret_test.go | 39 ++++++++++---- pkg/bootstrap/render.go | 5 +- pkg/bootstrap/render_test.go | 77 ++++++++++++++++++++++----- 4 files changed, 115 insertions(+), 32 deletions(-) diff --git a/pkg/bootstrap/imagepullsecret.go b/pkg/bootstrap/imagepullsecret.go index e3fc1d8f..d385a6c6 100644 --- a/pkg/bootstrap/imagepullsecret.go +++ b/pkg/bootstrap/imagepullsecret.go @@ -16,6 +16,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +const EmptyImagePullSecret = "empty-image-pull-secret" + func getImagePullSecretConfig(imagePullSecret *corev1.Secret) (ImagePullSecretConfig, error) { useImagePullSecret := false var imagePullSecretType corev1.SecretType @@ -72,17 +74,27 @@ func getImagePullSecret(ctx context.Context, clientHolder *helpers.ClientHolder, func getDefaultImagePullSecret(ctx context.Context, clientHolder *helpers.ClientHolder) (*corev1.Secret, error) { var err error + var secret *corev1.Secret defaultSecretName := os.Getenv(constants.DefaultImagePullSecretEnvVarName) if defaultSecretName == "" { - // Ignore the image pull secret, it can't be found from env DEFAULT_IMAGE_PULL_SECRET - return nil, nil + // If default secret can't be found from env DEFAULT_IMAGE_PULL_SECRET, create an empty image pull secret + secret = &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: EmptyImagePullSecret, + }, + Data: map[string][]byte{ + corev1.DockerConfigJsonKey: []byte("{}"), + }, + Type: corev1.SecretTypeDockerConfigJson, + } + } else { + ns := os.Getenv(constants.PodNamespaceEnvVarName) + secret, err = clientHolder.KubeClient.CoreV1().Secrets(ns).Get(ctx, defaultSecretName, metav1.GetOptions{}) + if err != nil { + return nil, err + } } - ns := os.Getenv(constants.PodNamespaceEnvVarName) - secret, err := clientHolder.KubeClient.CoreV1().Secrets(ns).Get(ctx, defaultSecretName, metav1.GetOptions{}) - if err != nil { - return nil, err - } return secret, nil } diff --git a/pkg/bootstrap/imagepullsecret_test.go b/pkg/bootstrap/imagepullsecret_test.go index 23b4e1f5..e0031151 100644 --- a/pkg/bootstrap/imagepullsecret_test.go +++ b/pkg/bootstrap/imagepullsecret_test.go @@ -19,10 +19,6 @@ import ( clusterv1 "open-cluster-management.io/api/cluster/v1" ) -func init() { - os.Setenv(constants.DefaultImagePullSecretEnvVarName, "test-image-pull-secret-secret") // this is also depend by render_test.go -} - func TestGetImagePullSecret(t *testing.T) { cases := []struct { name string @@ -31,20 +27,21 @@ func TestGetImagePullSecret(t *testing.T) { managedCluster *clusterv1.ManagedCluster klusterletconfigImagePullSecret corev1.ObjectReference expectedSecret *corev1.Secret + defaultImagePullSecret string }{ { name: "no registry", clientObjs: []client.Object{}, secret: &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: os.Getenv("DEFAULT_IMAGE_PULL_SECRET"), - Namespace: os.Getenv("POD_NAMESPACE"), + Name: "test-image-pull-secret", }, Data: map[string][]byte{ ".dockerconfigjson": []byte("fake-token"), }, Type: corev1.SecretTypeDockerConfigJson, }, + defaultImagePullSecret: "test-image-pull-secret", managedCluster: &clusterv1.ManagedCluster{ ObjectMeta: metav1.ObjectMeta{ Name: "test", @@ -53,8 +50,23 @@ func TestGetImagePullSecret(t *testing.T) { klusterletconfigImagePullSecret: corev1.ObjectReference{}, expectedSecret: &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: os.Getenv("DEFAULT_IMAGE_PULL_SECRET"), - Namespace: os.Getenv("POD_NAMESPACE"), + Name: "test-image-pull-secret", + }, + }, + }, + { + name: "no registry, no default secret found in env var", + clientObjs: []client.Object{}, + managedCluster: &clusterv1.ManagedCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + }, + defaultImagePullSecret: "", + klusterletconfigImagePullSecret: corev1.ObjectReference{}, + expectedSecret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: EmptyImagePullSecret, }, }, }, @@ -71,6 +83,7 @@ func TestGetImagePullSecret(t *testing.T) { }, Type: corev1.SecretTypeDockerConfigJson, }, + defaultImagePullSecret: "test-image-pull-secret", managedCluster: &clusterv1.ManagedCluster{ ObjectMeta: metav1.ObjectMeta{ Name: "test", @@ -103,6 +116,7 @@ func TestGetImagePullSecret(t *testing.T) { }, Type: corev1.SecretTypeDockerConfigJson, }, + defaultImagePullSecret: "test-image-pull-secret", managedCluster: &clusterv1.ManagedCluster{ ObjectMeta: metav1.ObjectMeta{ Name: "test", @@ -123,7 +137,14 @@ func TestGetImagePullSecret(t *testing.T) { for _, c := range cases { t.Run(c.name, func(t *testing.T) { - kubeClient := kubefake.NewSimpleClientset(c.secret) + os.Setenv(constants.DefaultImagePullSecretEnvVarName, c.defaultImagePullSecret) + + var kubeClient *kubefake.Clientset + if c.secret != nil { + kubeClient = kubefake.NewSimpleClientset(c.secret) + } else { + kubeClient = kubefake.NewSimpleClientset() + } clientHolder := &helpers.ClientHolder{ KubeClient: kubeClient, ImageRegistryClient: imageregistry.NewClient(kubeClient), diff --git a/pkg/bootstrap/render.go b/pkg/bootstrap/render.go index 76426e23..9ffdf93c 100644 --- a/pkg/bootstrap/render.go +++ b/pkg/bootstrap/render.go @@ -236,9 +236,10 @@ func (b *KlusterletManifestsConfig) Generate(ctx context.Context, clientHolder * return nil, err } - if imagePullSecret != nil { - files = append(files, "manifests/klusterlet/image_pull_secret.yaml") + if imagePullSecret == nil { + return nil, fmt.Errorf("imagePullSecret is nil") } + files = append(files, "manifests/klusterlet/image_pull_secret.yaml") imagePullSecretConfig, err := getImagePullSecretConfig(imagePullSecret) if err != nil { diff --git a/pkg/bootstrap/render_test.go b/pkg/bootstrap/render_test.go index 87608e44..a6475b31 100644 --- a/pkg/bootstrap/render_test.go +++ b/pkg/bootstrap/render_test.go @@ -29,12 +29,59 @@ func TestKlusterletConfigGenerate(t *testing.T) { var tolerationSeconds int64 = 20 testcases := []struct { - name string - clientObjs []runtimeclient.Object - runtimeObjs []runtime.Object - config *KlusterletManifestsConfig - validateFunc func(t *testing.T, objects []runtime.Object) + name string + defaultImagePullSecret string + clientObjs []runtimeclient.Object + runtimeObjs []runtime.Object + config *KlusterletManifestsConfig + validateFunc func(t *testing.T, objects []runtime.Object) }{ + { + name: "default without DEFAULT_IMAGE_PULL_SECRET set", + clientObjs: []runtimeclient.Object{ + &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + }, + }, + defaultImagePullSecret: "", + config: NewKlusterletManifestsConfig( + operatorv1.InstallModeDefault, + "test", // cluster name + "test", // klusterlet namespace + []byte("bootstrap kubeconfig"), + ), + validateFunc: func(t *testing.T, objs []runtime.Object) { + if len(objs) != 10 { + t.Fatalf("Expected 10 objects, but got %d", len(objs)) + } + if len(objs) != 10 { + t.Fatalf("Expected 10 objects, but got %d", len(objs)) + } + _, ok := objs[0].(*corev1.Namespace) + if !ok { + t.Errorf("import secret data %s, the first element is not namespace", constants.ImportSecretImportYamlKey) + } + pullSecret, ok := objs[9].(*corev1.Secret) + if !ok { + t.Errorf("import secret data %s, the last element is not secret", constants.ImportSecretImportYamlKey) + } + if pullSecret.Type != corev1.SecretTypeDockerConfigJson { + t.Errorf("the pull secret type %s is not %s", + pullSecret.Type, corev1.SecretTypeDockerConfigJson) + } + if _, ok := pullSecret.Data[corev1.DockerConfigJsonKey]; !ok { + t.Errorf("the pull secret data %s is not %s", + pullSecret.Data, corev1.DockerConfigJsonKey) + } + // the content of the pull secret is "{}" + if string(pullSecret.Data[corev1.DockerConfigJsonKey]) != "{}" { + t.Errorf("the pull secret data %s is not %s", + pullSecret.Data[corev1.DockerConfigJsonKey], "{}") + } + }, + }, { name: "default", clientObjs: []runtimeclient.Object{ @@ -44,11 +91,11 @@ func TestKlusterletConfigGenerate(t *testing.T) { }, }, }, + defaultImagePullSecret: "test-image-pull-secret", runtimeObjs: []runtime.Object{ &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: os.Getenv("DEFAULT_IMAGE_PULL_SECRET"), - Namespace: os.Getenv("POD_NAMESPACE"), + Name: "test-image-pull-secret", }, Data: map[string][]byte{ corev1.DockerConfigJsonKey: []byte("fake-token"), @@ -93,11 +140,11 @@ func TestKlusterletConfigGenerate(t *testing.T) { }, }, }, + defaultImagePullSecret: "test-image-pull-secret", runtimeObjs: []runtime.Object{ &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: os.Getenv("DEFAULT_IMAGE_PULL_SECRET"), - Namespace: os.Getenv("POD_NAMESPACE"), + Name: "test-image-pull-secret", }, Data: map[string][]byte{ corev1.DockerConfigKey: []byte("fake-token"), @@ -118,7 +165,8 @@ func TestKlusterletConfigGenerate(t *testing.T) { }, }, { - name: "default customized with managed cluster annotations", + name: "default customized with managed cluster annotations", + defaultImagePullSecret: "test-image-pull-secret", clientObjs: []runtimeclient.Object{ &corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ @@ -129,8 +177,7 @@ func TestKlusterletConfigGenerate(t *testing.T) { runtimeObjs: []runtime.Object{ &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: os.Getenv("DEFAULT_IMAGE_PULL_SECRET"), - Namespace: os.Getenv("POD_NAMESPACE"), + Name: "test-image-pull-secret", }, Data: map[string][]byte{ corev1.DockerConfigKey: []byte("fake-token"), @@ -187,11 +234,11 @@ func TestKlusterletConfigGenerate(t *testing.T) { }, }, }, + defaultImagePullSecret: "test-image-pull-secret", runtimeObjs: []runtime.Object{ &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: os.Getenv("DEFAULT_IMAGE_PULL_SECRET"), - Namespace: os.Getenv("POD_NAMESPACE"), + Name: "test-image-pull-secret", }, Data: map[string][]byte{ corev1.DockerConfigKey: []byte("fake-token"), @@ -267,6 +314,8 @@ func TestKlusterletConfigGenerate(t *testing.T) { for _, testcase := range testcases { t.Run(testcase.name, func(t *testing.T) { + os.Setenv(constants.DefaultImagePullSecretEnvVarName, testcase.defaultImagePullSecret) + kubeClient := kubefake.NewSimpleClientset(testcase.runtimeObjs...) clientHolder := &helpers.ClientHolder{ KubeClient: kubeClient,