github.com/oam-dev/cluster-gateway@v1.9.0/pkg/util/cert/secret.go (about)

     1  package cert
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  
     7  	"github.com/oam-dev/cluster-gateway/pkg/common"
     8  
     9  	"github.com/pkg/errors"
    10  	corev1 "k8s.io/api/core/v1"
    11  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    12  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    13  	"k8s.io/apimachinery/pkg/labels"
    14  	"k8s.io/apimachinery/pkg/selection"
    15  	"k8s.io/client-go/kubernetes"
    16  	corev1lister "k8s.io/client-go/listers/core/v1"
    17  )
    18  
    19  func CopySecret(kubeClient kubernetes.Interface, sourceNamespace string, sourceName string, targetNamespace, targetName string) error {
    20  	sourceSecret, err := kubeClient.CoreV1().
    21  		Secrets(sourceNamespace).
    22  		Get(context.TODO(), sourceName, metav1.GetOptions{})
    23  	if err != nil {
    24  		return errors.Wrapf(err, "failed getting source secret %v/%v: %v", sourceNamespace, sourceName, err)
    25  	}
    26  	shouldCreate := false
    27  	existingTargetSecret, err := kubeClient.CoreV1().
    28  		Secrets(targetNamespace).
    29  		Get(context.TODO(), targetName, metav1.GetOptions{})
    30  	if err != nil {
    31  		if !apierrors.IsNotFound(err) {
    32  			return errors.Wrapf(err, "failed getting target secret %v/%v: %v", targetNamespace, targetName, err)
    33  		}
    34  		shouldCreate = true
    35  	}
    36  	if shouldCreate {
    37  		existingTargetSecret = sourceSecret.DeepCopy()
    38  		existingTargetSecret.Namespace = targetNamespace
    39  		existingTargetSecret.Name = targetName
    40  		existingTargetSecret.UID = ""
    41  		existingTargetSecret.ResourceVersion = ""
    42  		if _, err := kubeClient.CoreV1().Secrets(targetNamespace).
    43  			Create(context.TODO(), existingTargetSecret, metav1.CreateOptions{}); err != nil {
    44  			if !apierrors.IsAlreadyExists(err) {
    45  				return errors.Wrapf(err, "failed creating CA secret")
    46  			}
    47  		}
    48  		return nil
    49  	}
    50  
    51  	if IsSubset(sourceSecret.Data, existingTargetSecret.Data) {
    52  		return nil
    53  	}
    54  	Merge(sourceSecret.Data, existingTargetSecret.Data)
    55  	_, err = kubeClient.CoreV1().
    56  		Secrets(targetNamespace).
    57  		Update(context.TODO(), existingTargetSecret, metav1.UpdateOptions{})
    58  	return err
    59  }
    60  
    61  func IsSubset(subset, superset map[string][]byte) bool {
    62  	for k, v := range subset {
    63  		if !bytes.Equal(v, superset[k]) {
    64  			return false
    65  		}
    66  	}
    67  	return true
    68  }
    69  
    70  func Merge(l, r map[string][]byte) {
    71  	for k, v := range l {
    72  		r[k] = v
    73  	}
    74  }
    75  
    76  type SecretControl interface {
    77  	Get(ctx context.Context, name string) (*corev1.Secret, error)
    78  	List(ctx context.Context) ([]*corev1.Secret, error)
    79  }
    80  
    81  var _ SecretControl = &directApiSecretControl{}
    82  
    83  type directApiSecretControl struct {
    84  	secretNamespace string
    85  	kubeClient      kubernetes.Interface
    86  }
    87  
    88  func (d *directApiSecretControl) Get(ctx context.Context, name string) (*corev1.Secret, error) {
    89  	return d.kubeClient.CoreV1().Secrets(d.secretNamespace).Get(ctx, name, metav1.GetOptions{})
    90  }
    91  
    92  func (d *directApiSecretControl) List(ctx context.Context) ([]*corev1.Secret, error) {
    93  	requirement, err := labels.NewRequirement(
    94  		common.LabelKeyClusterCredentialType,
    95  		selection.Exists,
    96  		nil)
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  	secretList, err := d.kubeClient.CoreV1().Secrets(d.secretNamespace).List(ctx, metav1.ListOptions{
   101  		LabelSelector: labels.NewSelector().Add(*requirement).String(),
   102  	})
   103  	if err != nil {
   104  		return nil, err
   105  	}
   106  	secrets := make([]*corev1.Secret, len(secretList.Items))
   107  	for i := range secretList.Items {
   108  		secrets[i] = &secretList.Items[i]
   109  	}
   110  	return secrets, nil
   111  }
   112  
   113  var _ SecretControl = &cachedSecretControl{}
   114  
   115  type cachedSecretControl struct {
   116  	secretNamespace string
   117  	secretLister    corev1lister.SecretLister
   118  }
   119  
   120  func (c *cachedSecretControl) Get(ctx context.Context, name string) (*corev1.Secret, error) {
   121  	return c.secretLister.Secrets(c.secretNamespace).Get(name)
   122  }
   123  
   124  func (c *cachedSecretControl) List(ctx context.Context) ([]*corev1.Secret, error) {
   125  	requirement, err := labels.NewRequirement(
   126  		common.LabelKeyClusterCredentialType,
   127  		selection.Exists,
   128  		nil)
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  	selector := labels.NewSelector().Add(*requirement)
   133  	return c.secretLister.Secrets(c.secretNamespace).List(selector)
   134  }
   135  
   136  func NewDirectApiSecretControl(secretNamespace string, kubeClient kubernetes.Interface) SecretControl {
   137  	return &directApiSecretControl{
   138  		secretNamespace: secretNamespace,
   139  		kubeClient:      kubeClient,
   140  	}
   141  }
   142  
   143  func NewCachedSecretControl(secretNamespace string, secretLister corev1lister.SecretLister) SecretControl {
   144  	return &cachedSecretControl{
   145  		secretNamespace: secretNamespace,
   146  		secretLister:    secretLister,
   147  	}
   148  }