mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-05-06 16:25:21 -04:00
cli: create backups for CRDs and their resources
These backups could be used in case an upgrade misbehaves after helm declared it as successful. The manual backups are required as helm-rollback won't touch custom resources and changes to CRDs delete resources of the old version.
This commit is contained in:
parent
afbd4a3dc1
commit
e7c7e35f51
11 changed files with 397 additions and 87 deletions
|
@ -1,144 +0,0 @@
|
|||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package kubectl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apiextensionsclientv1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/cli-runtime/pkg/resource"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/client-go/util/retry"
|
||||
)
|
||||
|
||||
// Kubectl implements functionality of the Kubernetes "kubectl" tool.
|
||||
type Kubectl struct {
|
||||
kubernetes.Interface
|
||||
apiextensionClient apiextensionsclientv1.ApiextensionsV1Interface
|
||||
builder *resource.Builder
|
||||
}
|
||||
|
||||
// New returns an empty Kubectl client. Need to call Initialize before usable.
|
||||
func New() *Kubectl {
|
||||
return &Kubectl{}
|
||||
}
|
||||
|
||||
// Initialize sets sets all required fields so the Kubectl client can be used.
|
||||
func (k *Kubectl) Initialize(kubeconfig []byte) error {
|
||||
clientConfig, err := clientcmd.RESTConfigFromKubeConfig(kubeconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating k8s client config from kubeconfig: %w", err)
|
||||
}
|
||||
clientset, err := kubernetes.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating k8s client from kubeconfig: %w", err)
|
||||
}
|
||||
k.Interface = clientset
|
||||
|
||||
apiextensionClient, err := apiextensionsclientv1.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating api extension client from kubeconfig: %w", err)
|
||||
}
|
||||
k.apiextensionClient = apiextensionClient
|
||||
|
||||
restClientGetter, err := newRESTClientGetter(kubeconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating k8s RESTClientGetter from kubeconfig: %w", err)
|
||||
}
|
||||
k.builder = resource.NewBuilder(restClientGetter).Unstructured()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateConfigMap creates the provided configmap.
|
||||
func (k *Kubectl) CreateConfigMap(ctx context.Context, configMap corev1.ConfigMap) error {
|
||||
_, err := k.CoreV1().ConfigMaps(configMap.ObjectMeta.Namespace).Create(ctx, &configMap, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AnnotateNode adds the provided annotations to the node, identified by name.
|
||||
func (k *Kubectl) AnnotateNode(ctx context.Context, nodeName, annotationKey, annotationValue string) error {
|
||||
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
node, err := k.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if node.Annotations == nil {
|
||||
node.Annotations = map[string]string{}
|
||||
}
|
||||
node.Annotations[annotationKey] = annotationValue
|
||||
_, err = k.CoreV1().Nodes().Update(ctx, node, metav1.UpdateOptions{})
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
// ListAllNamespaces returns all namespaces in the cluster.
|
||||
func (k *Kubectl) ListAllNamespaces(ctx context.Context) (*corev1.NamespaceList, error) {
|
||||
return k.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
|
||||
}
|
||||
|
||||
// AddTolerationsToDeployment adds [K8s tolerations] to the deployment, identified
|
||||
// by name and namespace.
|
||||
//
|
||||
// [K8s tolerations]: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
|
||||
func (k *Kubectl) AddTolerationsToDeployment(ctx context.Context, tolerations []corev1.Toleration, name string, namespace string) error {
|
||||
deployments := k.AppsV1().Deployments(namespace)
|
||||
|
||||
// retry resource update if an error occurs
|
||||
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
result, err := deployments.Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get Deployment to add toleration: %w", err)
|
||||
}
|
||||
|
||||
result.Spec.Template.Spec.Tolerations = append(result.Spec.Template.Spec.Tolerations, tolerations...)
|
||||
if _, err = deployments.Update(ctx, result, metav1.UpdateOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddNodeSelectorsToDeployment adds [K8s selectors] to the deployment, identified
|
||||
// by name and namespace.
|
||||
//
|
||||
// [K8s selectors]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
func (k *Kubectl) AddNodeSelectorsToDeployment(ctx context.Context, selectors map[string]string, name string, namespace string) error {
|
||||
deployments := k.AppsV1().Deployments(namespace)
|
||||
|
||||
// retry resource update if an error occurs
|
||||
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
result, err := deployments.Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get Deployment to add node selector: %w", err)
|
||||
}
|
||||
|
||||
for k, v := range selectors {
|
||||
result.Spec.Template.Spec.NodeSelector[k] = v
|
||||
}
|
||||
|
||||
if _, err = deployments.Update(ctx, result, metav1.UpdateOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue