github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/pkg/clients/common/secret.go (about)

     1  package common
     2  
     3  import (
     4  	"context"
     5  	"encoding/base64"
     6  	"errors"
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/redhat-appstudio/e2e-tests/pkg/constants"
    11  	. "github.com/redhat-appstudio/e2e-tests/pkg/constants"
    12  	"github.com/redhat-appstudio/e2e-tests/pkg/utils"
    13  	corev1 "k8s.io/api/core/v1"
    14  	k8sErrors "k8s.io/apimachinery/pkg/api/errors"
    15  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    16  	"k8s.io/apimachinery/pkg/util/wait"
    17  )
    18  
    19  // Creates a new secret in a specified namespace
    20  func (s *SuiteController) CreateSecret(ns string, secret *corev1.Secret) (*corev1.Secret, error) {
    21  	return s.KubeInterface().CoreV1().Secrets(ns).Create(context.Background(), secret, metav1.CreateOptions{})
    22  }
    23  
    24  // Check if a secret exists, return secret and error
    25  func (s *SuiteController) GetSecret(ns string, name string) (*corev1.Secret, error) {
    26  	return s.KubeInterface().CoreV1().Secrets(ns).Get(context.Background(), name, metav1.GetOptions{})
    27  }
    28  
    29  // Deleted a secret in a specified namespace
    30  func (s *SuiteController) DeleteSecret(ns string, name string) error {
    31  	return s.KubeInterface().CoreV1().Secrets(ns).Delete(context.Background(), name, metav1.DeleteOptions{})
    32  }
    33  
    34  // Links a secret to a specified serviceaccount, if argument addImagePullSecrets is true secret will be added also to ImagePullSecrets of SA.
    35  func (s *SuiteController) LinkSecretToServiceAccount(ns, secret, serviceaccount string, addImagePullSecrets bool) error {
    36  	timeout := 20 * time.Second
    37  	return wait.PollUntilContextTimeout(context.Background(), time.Second, timeout, true, func(ctx context.Context) (bool, error) {
    38  		serviceAccountObject, err := s.KubeInterface().CoreV1().ServiceAccounts(ns).Get(context.Background(), serviceaccount, metav1.GetOptions{})
    39  		if err != nil {
    40  			return false, err
    41  		}
    42  		for _, credentialSecret := range serviceAccountObject.Secrets {
    43  			if credentialSecret.Name == secret {
    44  				// The secret is present in the service account, no updates needed
    45  				return true, nil
    46  			}
    47  		}
    48  		serviceAccountObject.Secrets = append(serviceAccountObject.Secrets, corev1.ObjectReference{Name: secret})
    49  		if addImagePullSecrets {
    50  			serviceAccountObject.ImagePullSecrets = append(serviceAccountObject.ImagePullSecrets, corev1.LocalObjectReference{Name: secret})
    51  		}
    52  		_, err = s.KubeInterface().CoreV1().ServiceAccounts(ns).Update(context.Background(), serviceAccountObject, metav1.UpdateOptions{})
    53  		if err != nil {
    54  			return false, nil
    55  		}
    56  		return true, nil
    57  	})
    58  }
    59  
    60  // UnlinkSecretFromServiceAccount unlinks secret from service account
    61  func (s *SuiteController) UnlinkSecretFromServiceAccount(namespace, secretName, serviceAccount string, rmImagePullSecrets bool) error {
    62  	serviceAccountObject, err := s.KubeInterface().CoreV1().ServiceAccounts(namespace).Get(context.Background(), serviceAccount, metav1.GetOptions{})
    63  	if err != nil {
    64  		return err
    65  	}
    66  
    67  	for index, secret := range serviceAccountObject.Secrets {
    68  		if secret.Name == secretName {
    69  			serviceAccountObject.Secrets = append(serviceAccountObject.Secrets[:index], serviceAccountObject.Secrets[index+1:]...)
    70  			break
    71  		}
    72  	}
    73  
    74  	if rmImagePullSecrets {
    75  		for index, secret := range serviceAccountObject.ImagePullSecrets {
    76  			if secret.Name == secretName {
    77  				serviceAccountObject.ImagePullSecrets = append(serviceAccountObject.ImagePullSecrets[:index], serviceAccountObject.ImagePullSecrets[index+1:]...)
    78  				break
    79  			}
    80  		}
    81  	}
    82  	_, err = s.KubeInterface().CoreV1().ServiceAccounts(namespace).Update(context.Background(), serviceAccountObject, metav1.UpdateOptions{})
    83  	if err != nil {
    84  		return err
    85  	}
    86  
    87  	return nil
    88  }
    89  
    90  // CreateRegistryAuthSecret create a docker registry secret in a given ns
    91  func (s *SuiteController) CreateRegistryAuthSecret(secretName, namespace, secretStringData string) (*corev1.Secret, error) {
    92  	rawDecodedTextStringData, err := base64.StdEncoding.DecodeString(secretStringData)
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  
    97  	secret := &corev1.Secret{
    98  		ObjectMeta: metav1.ObjectMeta{
    99  			Name:      secretName,
   100  			Namespace: namespace,
   101  		},
   102  		Type:       corev1.SecretTypeDockerConfigJson,
   103  		StringData: map[string]string{corev1.DockerConfigJsonKey: string(rawDecodedTextStringData)},
   104  	}
   105  	er := s.KubeRest().Create(context.Background(), secret)
   106  	if er != nil {
   107  		return nil, er
   108  	}
   109  	return secret, nil
   110  }
   111  
   112  // CreateRegistryJsonSecret creates a secret for registry repository in namespace given with key passed.
   113  func (s *SuiteController) CreateRegistryJsonSecret(name, namespace, authKey, keyName string) (*corev1.Secret, error) {
   114  	secret := &corev1.Secret{
   115  		ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace},
   116  		Type:       corev1.SecretTypeDockerConfigJson,
   117  		Data:       map[string][]byte{".dockerconfigjson": []byte(fmt.Sprintf("{\"auths\":{\"quay.io\":{\"username\":\"%s\",\"password\":\"%s\",\"auth\":\"dGVzdDp0ZXN0\",\"email\":\"\"}}}", keyName, authKey))},
   118  	}
   119  	err := s.KubeRest().Create(context.Background(), secret)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	return secret, nil
   124  }
   125  
   126  // AddRegistryAuthSecretToSA adds registry auth secret to service account
   127  func (s *SuiteController) AddRegistryAuthSecretToSA(registryAuth, namespace string) error {
   128  	quayToken := utils.GetEnv(registryAuth, "")
   129  	if quayToken == "" {
   130  		return errors.New("failed to get registry auth secret")
   131  	}
   132  
   133  	_, err := s.CreateRegistryAuthSecret(RegistryAuthSecretName, namespace, quayToken)
   134  	if err != nil {
   135  		return err
   136  	}
   137  
   138  	err = s.LinkSecretToServiceAccount(namespace, RegistryAuthSecretName, DefaultPipelineServiceAccount, true)
   139  	if err != nil {
   140  		return err
   141  	}
   142  
   143  	return nil
   144  }
   145  
   146  // copy the quay secret to a user defined namespace
   147  func (s *SuiteController) CreateQuayRegistrySecret(namespace string) error {
   148  	sharedSecret, err := s.GetSecret(constants.QuayRepositorySecretNamespace, constants.QuayRepositorySecretName)
   149  	if err != nil {
   150  		return err
   151  	}
   152  	_, err = s.GetSecret(namespace, constants.QuayRepositorySecretName)
   153  	if err != nil {
   154  		if !k8sErrors.IsNotFound(err) {
   155  			return err
   156  		}
   157  	} else {
   158  		err = s.DeleteSecret(namespace, constants.QuayRepositorySecretName)
   159  		if err != nil {
   160  			return err
   161  		}
   162  	}
   163  
   164  	repositorySecret := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: constants.QuayRepositorySecretName, Namespace: namespace},
   165  		Type: corev1.SecretTypeDockerConfigJson,
   166  		Data: map[string][]byte{corev1.DockerConfigJsonKey: sharedSecret.Data[".dockerconfigjson"]}}
   167  	_, err = s.CreateSecret(namespace, repositorySecret)
   168  	if err != nil {
   169  		return err
   170  	}
   171  
   172  	err = s.LinkSecretToServiceAccount(namespace, constants.QuayRepositorySecretName, constants.DefaultPipelineServiceAccount, true)
   173  	if err != nil {
   174  		return err
   175  	}
   176  
   177  	return nil
   178  }