github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/pkg/k8s/namespace.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: 2021-Present The Jackal Authors 3 4 // Package k8s provides a client for interacting with a Kubernetes cluster. 5 package k8s 6 7 import ( 8 "context" 9 "time" 10 11 "cuelang.org/go/pkg/strings" 12 "github.com/defenseunicorns/pkg/helpers" 13 corev1 "k8s.io/api/core/v1" 14 "k8s.io/apimachinery/pkg/api/errors" 15 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 16 ) 17 18 // GetNamespaces returns a list of namespaces in the cluster. 19 func (k *K8s) GetNamespaces() (*corev1.NamespaceList, error) { 20 metaOptions := metav1.ListOptions{} 21 return k.Clientset.CoreV1().Namespaces().List(context.TODO(), metaOptions) 22 } 23 24 // UpdateNamespace updates the given namespace in the cluster. 25 func (k *K8s) UpdateNamespace(namespace *corev1.Namespace) (*corev1.Namespace, error) { 26 updateOptions := metav1.UpdateOptions{} 27 return k.Clientset.CoreV1().Namespaces().Update(context.TODO(), namespace, updateOptions) 28 } 29 30 // CreateNamespace creates the given namespace or returns it if it already exists in the cluster. 31 func (k *K8s) CreateNamespace(namespace *corev1.Namespace) (*corev1.Namespace, error) { 32 metaOptions := metav1.GetOptions{} 33 createOptions := metav1.CreateOptions{} 34 35 match, err := k.Clientset.CoreV1().Namespaces().Get(context.TODO(), namespace.Name, metaOptions) 36 37 if err != nil || match.Name != namespace.Name { 38 return k.Clientset.CoreV1().Namespaces().Create(context.TODO(), namespace, createOptions) 39 } 40 41 return match, err 42 } 43 44 // DeleteNamespace deletes the given namespace from the cluster. 45 func (k *K8s) DeleteNamespace(ctx context.Context, name string) error { 46 // Attempt to delete the namespace immediately 47 gracePeriod := int64(0) 48 err := k.Clientset.CoreV1().Namespaces().Delete(ctx, name, metav1.DeleteOptions{GracePeriodSeconds: &gracePeriod}) 49 // If an error besides "not found" is returned, return it 50 if err != nil && !errors.IsNotFound(err) { 51 return err 52 } 53 54 // Indefinitely wait for the namespace to be deleted, use context.WithTimeout to limit this 55 for { 56 // Keep checking for the namespace to be deleted 57 _, err := k.Clientset.CoreV1().Namespaces().Get(ctx, name, metav1.GetOptions{}) 58 if errors.IsNotFound(err) { 59 return nil 60 } 61 time.Sleep(1 * time.Second) 62 } 63 } 64 65 // NewJackalManagedNamespace returns a corev1.Namespace with Jackal-managed labels 66 func (k *K8s) NewJackalManagedNamespace(name string) *corev1.Namespace { 67 namespace := &corev1.Namespace{ 68 TypeMeta: metav1.TypeMeta{ 69 APIVersion: corev1.SchemeGroupVersion.String(), 70 Kind: "Namespace", 71 }, 72 ObjectMeta: metav1.ObjectMeta{ 73 Name: name, 74 }, 75 } 76 77 // Merge in common labels so that later modifications to the namespace can't mutate them 78 namespace.ObjectMeta.Labels = helpers.MergeMap[string](k.Labels, namespace.ObjectMeta.Labels) 79 80 return namespace 81 } 82 83 // IsInitialNamespace returns true if the given namespace name is an initial k8s namespace: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/#initial-namespaces 84 func (k *K8s) IsInitialNamespace(name string) bool { 85 if name == "default" { 86 return true 87 } else if strings.HasPrefix(name, "kube-") { 88 return true 89 } 90 91 return false 92 }