diff --git a/cmd/clustertree-operator/app/tree_operator.go b/cmd/clustertree-operator/app/tree_operator.go index 3dbfe7292..14e1bacbf 100644 --- a/cmd/clustertree-operator/app/tree_operator.go +++ b/cmd/clustertree-operator/app/tree_operator.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/spf13/cobra" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/client-go/tools/clientcmd" cliflag "k8s.io/component-base/cli/flag" "k8s.io/klog/v2" @@ -55,9 +56,15 @@ func run(ctx context.Context, opts *options.Options) error { } config.QPS, config.Burst = opts.KubernetesOptions.QPS, opts.KubernetesOptions.Burst + newscheme := scheme.NewSchema() + err = apiextensionsv1.AddToScheme(newscheme) + if err != nil { + panic(err) + } + mgr, err := controllerruntime.NewManager(config, controllerruntime.Options{ Logger: klog.Background(), - Scheme: scheme.NewSchema(), + Scheme: newscheme, LeaderElection: opts.LeaderElection.LeaderElect, LeaderElectionID: opts.LeaderElection.ResourceName, LeaderElectionNamespace: opts.LeaderElection.ResourceNamespace, @@ -76,8 +83,9 @@ func run(ctx context.Context, opts *options.Options) error { } VirtualClusterJoinController := controller.VirtualClusterJoinController{ - Client: mgr.GetClient(), - EventRecorder: mgr.GetEventRecorderFor(constants.JoinControllerName), + Client: mgr.GetClient(), + EventRecorder: mgr.GetEventRecorderFor(constants.JoinControllerName), + KubeconfigPath: opts.KubernetesOptions.KubeConfig, } if err = VirtualClusterJoinController.SetupWithManager(mgr); err != nil { return fmt.Errorf("error starting %s: %v", constants.JoinControllerName, err) diff --git a/deploy/crds/kosmos.io_virtualclusters.yaml b/deploy/crds/kosmos.io_virtualclusters.yaml index 73f0fe5ac..c38cffe04 100644 --- a/deploy/crds/kosmos.io_virtualclusters.yaml +++ b/deploy/crds/kosmos.io_virtualclusters.yaml @@ -75,9 +75,3 @@ spec: type: object served: true storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/pkg/kosmosctl/manifest/manifest_crds.go b/pkg/kosmosctl/manifest/manifest_crds.go index 1174c1550..6e0b0d346 100644 --- a/pkg/kosmosctl/manifest/manifest_crds.go +++ b/pkg/kosmosctl/manifest/manifest_crds.go @@ -420,6 +420,8 @@ spec: properties: clusterLinkOptions: properties: + autodetectionMethod: + type: string bridgeCIDRs: default: ip: 220.0.0.0/8 @@ -652,7 +654,6 @@ spec: storage: true subresources: {} ` - const NodeConfig = `--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition diff --git a/pkg/treeoperator/constants/constant.go b/pkg/treeoperator/constants/constant.go index 37534bc53..c8a18a7ee 100644 --- a/pkg/treeoperator/constants/constant.go +++ b/pkg/treeoperator/constants/constant.go @@ -3,4 +3,9 @@ package constants const ( InitControllerName = "virtual-cluster-init-controller" JoinControllerName = "virtual-cluster-join-controller" + + DefauleImageRepositoryEnv = "IMAGE_REPOSITIRY" + DefauleImageVersionEnv = "IMAGE_VERSION" + VirtualClusterStatusCompleted = "Completed" + VirtualClusterSFinalizerName = "kosmos.io/virtual-cluster-finalizer" ) diff --git a/pkg/treeoperator/controller/virtualcluster_join_controller.go b/pkg/treeoperator/controller/virtualcluster_join_controller.go index 633a32115..7b0d7637b 100644 --- a/pkg/treeoperator/controller/virtualcluster_join_controller.go +++ b/pkg/treeoperator/controller/virtualcluster_join_controller.go @@ -1,16 +1,452 @@ package controller import ( + "context" + "encoding/base64" + "fmt" + "os" + "reflect" + + corev1 "k8s.io/api/core/v1" + extensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" + "k8s.io/apimachinery/pkg/api/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/record" + "k8s.io/klog/v2" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + "github.com/kosmos.io/kosmos/pkg/apis/kosmos/v1alpha1" + "github.com/kosmos.io/kosmos/pkg/cert" + clusterManager "github.com/kosmos.io/kosmos/pkg/clustertree/cluster-manager" + "github.com/kosmos.io/kosmos/pkg/generated/clientset/versioned" + "github.com/kosmos.io/kosmos/pkg/kosmosctl/manifest" + "github.com/kosmos.io/kosmos/pkg/kosmosctl/util" + kosmosctl "github.com/kosmos.io/kosmos/pkg/kosmosctl/util" + "github.com/kosmos.io/kosmos/pkg/treeoperator/constants" + treemanifest "github.com/kosmos.io/kosmos/pkg/treeoperator/manifest" + "github.com/kosmos.io/kosmos/pkg/utils" + "github.com/kosmos.io/kosmos/pkg/version" ) type VirtualClusterJoinController struct { client.Client - EventRecorder record.EventRecorder + EventRecorder record.EventRecorder + KubeconfigPath string + KubeconfigStream []byte } -func (c *VirtualClusterJoinController) SetupWithManager(mgr manager.Manager) error { +func (c *VirtualClusterJoinController) RemoveClusterFinalizer(cluster *v1alpha1.Cluster, kosmosClient versioned.Interface) error { + for _, finalizer := range []string{utils.ClusterStartControllerFinalizer, clusterManager.ControllerFinalizerName} { + if controllerutil.ContainsFinalizer(cluster, finalizer) { + controllerutil.RemoveFinalizer(cluster, finalizer) + } + } + klog.Infof("remove finalizer for cluster %s", cluster.Name) + + _, err := kosmosClient.KosmosV1alpha1().Clusters().Update(context.TODO(), cluster, metav1.UpdateOptions{}) + if err != nil { + klog.Errorf("cluster %s failed remove finalizer: %v", cluster.Name, err) + return err + } + klog.Infof("update cluster after remove finalizer for cluster %s", cluster.Name) + return nil +} + +func (c *VirtualClusterJoinController) UninstallClustertree(ctx context.Context, request reconcile.Request, vc *v1alpha1.VirtualCluster) error { + klog.Info("Start deleting kosmos-clustertree Deployment...") + clustertreeDeploy, err := kosmosctl.GenerateDeployment(treemanifest.ClusterTreeClusterManagerDeployment, treemanifest.DeploymentReplace{ + Namespace: request.Namespace, + ImageRepository: "null", + Version: "null", + Name: request.Name, + FilePath: treemanifest.DefaultKubeconfigPath, + }) + if err != nil { + return err + } + + deleteRequest := types.NamespacedName{ + Namespace: request.Namespace, + Name: clustertreeDeploy.Name, + } + err = c.Get(ctx, deleteRequest, clustertreeDeploy) + if err != nil { + if !apierrors.IsNotFound(err) { + return fmt.Errorf("get clustertree deployment error, deployment deleted failed: %v", err) + } + klog.Infof("clustertree deployment doesn't exist") + } else { + err := c.Delete(ctx, clustertreeDeploy) + if err != nil && !apierrors.IsNotFound(err) { + return fmt.Errorf("delete kosmos-clustertree Deployment error: %v", err) + } + } + + klog.Info("Deployment has been deleted. ") + + klog.Info("Start deleting kosmos-clustertree secret") + clustertreeSecret, err := kosmosctl.GenerateSecret(treemanifest.ClusterTreeClusterManagerSecret, treemanifest.SecretReplace{ + Namespace: request.Namespace, + Cert: cert.GetCrtEncode(), + Key: cert.GetKeyEncode(), + Name: request.Name, + }) + if err != nil { + return err + } + deleteRequest.Name = clustertreeSecret.Name + err = c.Get(ctx, deleteRequest, clustertreeSecret) + if err != nil { + if !apierrors.IsNotFound(err) { + return fmt.Errorf("get clustertree secret error, secret deleted failed: %v", err) + } + klog.Infof("clustertree secret doesn't exist") + } else { + err := c.Delete(ctx, clustertreeSecret) + if err != nil && !apierrors.IsNotFound(err) { + return fmt.Errorf("delete kosmos-clustertree Deployment error: %v", err) + } + } + klog.Info("Deployment has been deleted. ") + + clusterName := fmt.Sprintf("virtualcluster-%s-%s", request.Namespace, request.Name) + klog.Infof("Attempting to delete cluster %s...", clusterName) + + kubeconfigStream, err := base64.StdEncoding.DecodeString(vc.Spec.Kubeconfig) + if err != nil { + return fmt.Errorf("decode target kubernetes kubeconfig %s err: %v", vc.Spec.Kubeconfig, err) + } + err, kosmosClient, _, _ := c.InitTargetKubeclinet(kubeconfigStream) + if err != nil { + return fmt.Errorf("create kubernetes client failed: %v", err) + } + + old, err := kosmosClient.KosmosV1alpha1().Clusters().Get(context.TODO(), + clusterName, metav1.GetOptions{}) + if err != nil { + if !apierrors.IsNotFound(err) { + return fmt.Errorf("get cluster %s failed when we try to del: %v", clusterName, err) + } + } else { + err = c.RemoveClusterFinalizer(old, kosmosClient) + if err != nil { + return fmt.Errorf("removefinalizer %s failed: %v", clusterName, err) + } + err = kosmosClient.KosmosV1alpha1().Clusters().Delete(context.TODO(), clusterName, metav1.DeleteOptions{}) + if err != nil { + return fmt.Errorf("delete cluster %s failed: %v", clusterName, err) + } + } + klog.Infof("Cluster %s has been deleted.", clusterName) + if err := c.RemoveFinalizer(ctx, vc); err != nil { + return fmt.Errorf("remove finalizer error: %v", err) + } + return nil +} + +func (c *VirtualClusterJoinController) InitTargetKubeclinet(kubeconfigStream []byte) (error, versioned.Interface, kubernetes.Interface, extensionsclient.Interface) { + //targetKubeconfig := path.Join(DefaultKubeconfigPath, "kubeconfig") + //config, err := utils.RestConfig(targetKubeconfig, "") + config, err := utils.NewConfigFromBytes(kubeconfigStream) + if err != nil { + return fmt.Errorf("generate kubernetes config failed: %s", err), nil, nil, nil + } + + kosmosClient, err := versioned.NewForConfig(config) + if err != nil { + return fmt.Errorf("generate Kosmos client failed: %v", err), nil, nil, nil + } + + k8sClient, err := kubernetes.NewForConfig(config) + if err != nil { + return fmt.Errorf("generate K8s basic client failed: %v", err), nil, nil, nil + } + + k8sExtensionsClient, err := extensionsclient.NewForConfig(config) + if err != nil { + return fmt.Errorf("generate K8s extensions client failed: %v", err), nil, nil, nil + } + + return nil, kosmosClient, k8sClient, k8sExtensionsClient +} + +func (c *VirtualClusterJoinController) DeployKosmos(ctx context.Context, request reconcile.Request, vc *v1alpha1.VirtualCluster) error { + klog.Infof("Start creating kosmos-clustertree secret") + clustertreeSecret, err := kosmosctl.GenerateSecret(treemanifest.ClusterTreeClusterManagerSecret, treemanifest.SecretReplace{ + Namespace: request.Namespace, + Cert: cert.GetCrtEncode(), + Key: cert.GetKeyEncode(), + Kubeconfig: vc.Spec.Kubeconfig, + Name: request.Name, + }) + if err != nil { + return err + } + err = c.Create(ctx, clustertreeSecret) + if err != nil { + if !apierrors.IsAlreadyExists(err) { + return fmt.Errorf("install clustertree error, secret created failed: %v", err) + } + } + klog.Info("Secret has been created. ") + + klog.Info("Start creating kosmos-clustertree Deployment...") + imageRepository := os.Getenv(constants.DefauleImageRepositoryEnv) + if len(imageRepository) == 0 { + imageRepository = utils.DefaultImageRepository + } + + imageVersion := "v0.3.0" //os.Getenv(constants.DefauleImageVersionEnv) + if len(imageVersion) == 0 { + imageVersion = fmt.Sprintf("v%s", version.GetReleaseVersion().PatchRelease()) + } + clustertreeDeploy, err := kosmosctl.GenerateDeployment(treemanifest.ClusterTreeClusterManagerDeployment, treemanifest.DeploymentReplace{ + Namespace: request.Namespace, + ImageRepository: imageRepository, + Version: imageVersion, + FilePath: treemanifest.DefaultKubeconfigPath, + Name: request.Name, + }) + if err != nil { + return err + } + err = c.Create(ctx, clustertreeDeploy) + if err != nil { + if !apierrors.IsAlreadyExists(err) { + return fmt.Errorf("install clustertree error, deployment created failed: %v", err) + } + } + klog.Info("Deployment has been created. ") + return nil +} + +func (c *VirtualClusterJoinController) CreateCluster(ctx context.Context, request reconcile.Request, vc *v1alpha1.VirtualCluster) error { + klog.Info("Attempting to create kosmos-clustertree CRDs...") + clustertreeCluster, err := util.GenerateCustomResourceDefinition(manifest.Cluster, nil) + if err != nil { + return err + } + + kubeconfigStream, err := base64.StdEncoding.DecodeString(vc.Spec.Kubeconfig) + if err != nil { + return fmt.Errorf("decode target kubernetes kubeconfig %s err: %v", vc.Spec.Kubeconfig, err) + } + err, kosmosClient, _, k8sExtensionsClient := c.InitTargetKubeclinet(kubeconfigStream) + if err != nil { + return fmt.Errorf("crd kubernetes client failed: %v", err) + } + _, err = k8sExtensionsClient.ApiextensionsV1().CustomResourceDefinitions().Create(context.Background(), clustertreeCluster, metav1.CreateOptions{}) + if err != nil { + if apierrors.IsAlreadyExists(err) { + klog.Warningf("CRD %s is existed, creation process will skip", clustertreeCluster.Name) + } else { + return fmt.Errorf("crd create failed: %v", err) + } + } + klog.Info("Create CRD " + clustertreeCluster.Name + " successful.") + + clusterName := fmt.Sprintf("virtualcluster-%s-%s", request.Namespace, request.Name) + klog.Infof("Attempting to create cluster %s ...", clusterName) + + cluster := v1alpha1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterName, + }, + Spec: v1alpha1.ClusterSpec{ + Kubeconfig: c.KubeconfigStream, + Namespace: request.Namespace, + ClusterLinkOptions: &v1alpha1.ClusterLinkOptions{ + Enable: false, + NetworkType: v1alpha1.NetWorkTypeGateWay, + IPFamily: v1alpha1.IPFamilyTypeALL, + }, + ClusterTreeOptions: &v1alpha1.ClusterTreeOptions{ + Enable: true, + }, + }, + } + + hostK8sClient, err := utils.NewClientFromBytes(c.KubeconfigStream) + if err != nil { + return fmt.Errorf("crd kubernetes client failed: %v", err) + } + var leafModels []v1alpha1.LeafModel + for _, nodeName := range vc.Spec.PromoteResources.Nodes { + _, err := hostK8sClient.CoreV1().Nodes().Get(context.Background(), nodeName, metav1.GetOptions{}) + if err != nil { + klog.Errorf("node %s doesn't exits: %v", nodeName, err) + continue + } + leafModel := v1alpha1.LeafModel{ + LeafNodeName: nodeName, + Taints: []corev1.Taint{ + { + Effect: utils.KosmosNodeTaintEffect, + Key: utils.KosmosNodeTaintKey, + Value: utils.KosmosNodeValue, + }, + }, + NodeSelector: v1alpha1.NodeSelector{ + NodeName: nodeName, + }, + } + leafModels = append(leafModels, leafModel) + } + cluster.Spec.ClusterTreeOptions.LeafModels = leafModels + + old, err := kosmosClient.KosmosV1alpha1().Clusters().Get(context.TODO(), clusterName, metav1.GetOptions{}) + if err != nil { + if apierrors.IsNotFound(err) { + _, err = kosmosClient.KosmosV1alpha1().Clusters().Create(context.TODO(), &cluster, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("create cluster %s failed: %v", clusterName, err) + } + } else { + return fmt.Errorf("create cluster %s failed when get it first: %v", clusterName, err) + } + } else { + cluster.ResourceVersion = old.GetResourceVersion() + update, err := kosmosClient.KosmosV1alpha1().Clusters().Update(context.TODO(), &cluster, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("update cluster %s failed: %v", clusterName, err) + } else { + klog.Infof("Cluster %s hase been updated.", clusterName) + } + if !update.DeletionTimestamp.IsZero() { + return fmt.Errorf("cluster %s is deleteting, need requeue", clusterName) + } + } + klog.Infof("Cluster %s has been created.", clusterName) + return nil +} + +func (c *VirtualClusterJoinController) AddFinalizer(ctx context.Context, vc *v1alpha1.VirtualCluster) error { + vcNew := vc.DeepCopy() + if controllerutil.AddFinalizer(vcNew, constants.VirtualClusterSFinalizerName) { + err := c.Update(ctx, vcNew) + if err != nil { + return fmt.Errorf("add finalizer error for virtualcluster %s: %v", vc.Name, err) + } + } + klog.Infof("add finalizer for virtualcluster %s", vc.Name) + return nil +} + +func (c *VirtualClusterJoinController) RemoveFinalizer(ctx context.Context, vc *v1alpha1.VirtualCluster) error { + vcNew := vc.DeepCopy() + if controllerutil.ContainsFinalizer(vcNew, constants.VirtualClusterSFinalizerName) { + controllerutil.RemoveFinalizer(vcNew, constants.VirtualClusterSFinalizerName) + err := c.Update(ctx, vcNew) + if err != nil { + return fmt.Errorf("remove finalizer error for virtualcluster %s: %v", vc.Name, err) + } + } + klog.Infof("remove finalizer for virtualcluster %s", vc.Name) + return nil +} + +func (c *VirtualClusterJoinController) InstallClustertree(ctx context.Context, request reconcile.Request, vc *v1alpha1.VirtualCluster) error { + klog.Infof("Start creating kosmos-clustertree in namespace %s", request.Namespace) + defer klog.Infof("Finish creating kosmos-clustertree in namespace %s", request.Namespace) + if err := c.DeployKosmos(ctx, request, vc); err != nil { + return fmt.Errorf("deploy kosmos error: %v", err) + } + if err := c.CreateCluster(ctx, request, vc); err != nil { + return fmt.Errorf("create cluster error: %v", err) + } + if err := c.AddFinalizer(ctx, vc); err != nil { + return fmt.Errorf("add finalizer error: %v", err) + } return nil } + +func (c *VirtualClusterJoinController) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { + klog.V(4).Infof("============ %s starts to reconcile %s ============", constants.JoinControllerName, request.Name) + defer klog.V(4).Infof("============ %s reconcile finish %s ============", constants.JoinControllerName, request.Name) + var vc v1alpha1.VirtualCluster + + if err := c.Get(ctx, request.NamespacedName, &vc); err != nil { + if errors.IsNotFound(err) { + return reconcile.Result{}, nil + } + klog.Errorf("get %s error: %v", request.NamespacedName, err) + return reconcile.Result{RequeueAfter: utils.DefaultRequeueTime}, nil + } + if vc.DeletionTimestamp.IsZero() { + if vc.Status.Phase != constants.VirtualClusterStatusCompleted { + klog.Infof("cluster's status is %s, skip", vc.Status.Phase) + return reconcile.Result{}, nil + } + err := c.InstallClustertree(ctx, request, &vc) + if err != nil { + klog.Errorf("install %s error: %v", request.NamespacedName, err) + return reconcile.Result{RequeueAfter: utils.DefaultRequeueTime}, nil + } + } else { + err := c.UninstallClustertree(ctx, request, &vc) + if err != nil { + klog.Errorf("uninstall %s error: %v", request.NamespacedName, err) + return reconcile.Result{RequeueAfter: utils.DefaultRequeueTime}, nil + } + } + + return reconcile.Result{}, nil +} + +func (c *VirtualClusterJoinController) SetupWithManager(mgr manager.Manager) error { + if c.Client == nil { + c.Client = mgr.GetClient() + } + + skipFunc := func(obj client.Object) bool { + // skip reservedNS + return obj.GetNamespace() != utils.ReservedNS + } + kubeconfigStream, err := os.ReadFile(c.KubeconfigPath) + if err != nil { + return fmt.Errorf("read kubeconfig file failed: %v", err) + } + c.KubeconfigStream = kubeconfigStream + + return ctrl.NewControllerManagedBy(mgr). + Named(constants.JoinControllerName). + WithOptions(controller.Options{}). + For(&v1alpha1.VirtualCluster{}, builder.WithPredicates(predicate.Funcs{ + CreateFunc: func(createEvent event.CreateEvent) bool { + return skipFunc(createEvent.Object) + }, + UpdateFunc: func(updateEvent event.UpdateEvent) bool { + if !skipFunc(updateEvent.ObjectNew) { + return true + } + newObj := updateEvent.ObjectNew.(*v1alpha1.VirtualCluster) + oldObj := updateEvent.ObjectOld.(*v1alpha1.VirtualCluster) + + if !newObj.DeletionTimestamp.IsZero() { + return true + } + + return !reflect.DeepEqual(newObj.Spec, oldObj.Spec) || + newObj.Status.Phase != oldObj.Status.Phase + }, + DeleteFunc: func(deleteEvent event.DeleteEvent) bool { + return skipFunc(deleteEvent.Object) + }, + GenericFunc: func(genericEvent event.GenericEvent) bool { + // TODO + return false + }, + })). + Complete(c) +} diff --git a/pkg/treeoperator/manifest/manifest_deployments.go b/pkg/treeoperator/manifest/manifest_deployments.go new file mode 100644 index 000000000..b0669e419 --- /dev/null +++ b/pkg/treeoperator/manifest/manifest_deployments.go @@ -0,0 +1,60 @@ +package manifest + +const ( + DefaultKubeconfigPath = "/etc/cluster-tree/cert" + ClusterTreeClusterManagerDeployment = `--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .Name }}-clustertree-cluster-manager + namespace: {{ .Namespace }} + labels: + app: clustertree-cluster-manager +spec: + replicas: 1 + selector: + matchLabels: + app: clustertree-cluster-manager + template: + metadata: + labels: + app: clustertree-cluster-manager + spec: + serviceAccountName: clustertree + containers: + - name: manager + image: {{ .ImageRepository }}/clustertree-cluster-manager:{{ .Version }} + imagePullPolicy: IfNotPresent + env: + - name: APISERVER_CERT_LOCATION + value: {{ .FilePath }}/cert.pem + - name: APISERVER_KEY_LOCATION + value: {{ .FilePath }}/key.pem + - name: LEAF_NODE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + volumeMounts: + - name: credentials + mountPath: "{{ .FilePath }}" + readOnly: true + command: + - clustertree-cluster-manager + - --multi-cluster-service=true + - --v=4 + - --leader-elect-resource-namespace={{ .Namespace }} + - --kubeconfig={{ .FilePath }}/kubeconfig + volumes: + - name: credentials + secret: + secretName: {{ .Name }}-clustertree-cluster-manager +` +) + +type DeploymentReplace struct { + Namespace string + ImageRepository string + Version string + FilePath string + Name string +} diff --git a/pkg/treeoperator/manifest/manifest_secrets.go b/pkg/treeoperator/manifest/manifest_secrets.go new file mode 100644 index 000000000..ae7424a75 --- /dev/null +++ b/pkg/treeoperator/manifest/manifest_secrets.go @@ -0,0 +1,24 @@ +package manifest + +const ( + ClusterTreeClusterManagerSecret = `--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ .Name }}-clustertree-cluster-manager + namespace: {{ .Namespace }} +type: Opaque +data: + cert.pem: {{ .Cert }} + key.pem: {{ .Key }} + kubeconfig: {{ .Kubeconfig }} +` +) + +type SecretReplace struct { + Namespace string + Cert string + Key string + Kubeconfig string + Name string +}