Added base for envtests
This commit is contained in:
		
							parent
							
								
									cb26623f5f
								
							
						
					
					
						commit
						b6bf47b949
					
				
							
								
								
									
										11
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										11
									
								
								Makefile
								
								
								
								
							|  | @ -173,7 +173,7 @@ install: ## Installs the executable | ||||||
| .PHONY: run | .PHONY: run | ||||||
| run: export WATCH_NAMESPACE = $(NAMESPACE) | run: export WATCH_NAMESPACE = $(NAMESPACE) | ||||||
| run: export OPERATOR_NAME = $(NAME) | run: export OPERATOR_NAME = $(NAME) | ||||||
| run: fmt vet manifests install build ## Run the executable, you can use EXTRA_ARGS
 | run: fmt vet manifests install-crds build ## Run the executable, you can use EXTRA_ARGS
 | ||||||
| 	@echo "+ $@" | 	@echo "+ $@" | ||||||
| ifeq ($(KUBERNETES_PROVIDER),minikube) | ifeq ($(KUBERNETES_PROVIDER),minikube) | ||||||
| 	kubectl config use-context $(KUBECTL_CONTEXT) | 	kubectl config use-context $(KUBECTL_CONTEXT) | ||||||
|  | @ -422,7 +422,7 @@ generate-docs: ## Re-generate docs directory from the website directory | ||||||
| ##################### FROM OPERATOR SDK ########################
 | ##################### FROM OPERATOR SDK ########################
 | ||||||
| #TODO rename
 | #TODO rename
 | ||||||
| # Install CRDs into a cluster
 | # Install CRDs into a cluster
 | ||||||
| install: manifests kustomize | install-crds: manifests kustomize | ||||||
| 	$(KUSTOMIZE) build config/crd | kubectl apply -f - | 	$(KUSTOMIZE) build config/crd | kubectl apply -f - | ||||||
| 
 | 
 | ||||||
| # Uninstall CRDs from a cluster
 | # Uninstall CRDs from a cluster
 | ||||||
|  | @ -473,3 +473,10 @@ bundle: manifests kustomize | ||||||
| .PHONY: bundle-build | .PHONY: bundle-build | ||||||
| bundle-build: | bundle-build: | ||||||
| 	docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . | 	docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . | ||||||
|  | 
 | ||||||
|  | #FIXME temporary target for running tests (test used above for go test)
 | ||||||
|  | ENVTEST_ASSETS_DIR=$(shell pwd)/testbin | ||||||
|  | testing: generate fmt vet manifests | ||||||
|  | 	mkdir -p ${ENVTEST_ASSETS_DIR} | ||||||
|  | 	test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.7.0/hack/setup-envtest.sh | ||||||
|  | 	source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out | ||||||
|  | @ -0,0 +1,170 @@ | ||||||
|  | package controllers | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/api/v1alpha2" | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources" | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/pkg/constants" | ||||||
|  | 	corev1 "k8s.io/api/core/v1" | ||||||
|  | 	rbacv1 "k8s.io/api/rbac/v1" | ||||||
|  | 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||||
|  | 	"k8s.io/apimachinery/pkg/util/intstr" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	userConfigurationConfigMapName = "user-config" | ||||||
|  | 	userConfigurationSecretName    = "user-secret" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type seedJobConfig struct { | ||||||
|  | 	v1alpha2.SeedJob | ||||||
|  | 	JobNames   []string `json:"jobNames,omitempty"` | ||||||
|  | 	Username   string   `json:"username,omitempty"` | ||||||
|  | 	Password   string   `json:"password,omitempty"` | ||||||
|  | 	PrivateKey string   `json:"privateKey,omitempty"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	jenkinsCRName     = "jenkins-example" | ||||||
|  | 	namespace         = "default" | ||||||
|  | 	priorityClassName = "" | ||||||
|  | 
 | ||||||
|  | 	mySeedJob = seedJobConfig{ | ||||||
|  | 		SeedJob: v1alpha2.SeedJob{ | ||||||
|  | 			ID:                    "jenkins-operator", | ||||||
|  | 			CredentialID:          "jenkins-operator", | ||||||
|  | 			JenkinsCredentialType: v1alpha2.NoJenkinsCredentialCredentialType, | ||||||
|  | 			Targets:               "cicd/jobs/*.jenkins", | ||||||
|  | 			Description:           "Jenkins Operator repository", | ||||||
|  | 			RepositoryBranch:      "master", | ||||||
|  | 			RepositoryURL:         "https://github.com/jenkinsci/kubernetes-operator.git", | ||||||
|  | 			PollSCM:               "1 1 1 1 1", | ||||||
|  | 			UnstableOnDeprecation: true, | ||||||
|  | 			BuildPeriodically:     "1 1 1 1 1", | ||||||
|  | 			FailOnMissingPlugin:   true, | ||||||
|  | 			IgnoreMissingFiles:    true, | ||||||
|  | 			//AdditionalClasspath: can fail with the seed job agent
 | ||||||
|  | 			GitHubPushTrigger: true, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	groovyScripts = v1alpha2.GroovyScripts{ | ||||||
|  | 		Customization: v1alpha2.Customization{ | ||||||
|  | 			Configurations: []v1alpha2.ConfigMapRef{ | ||||||
|  | 				{ | ||||||
|  | 					Name: userConfigurationConfigMapName, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			Secret: v1alpha2.SecretRef{ | ||||||
|  | 				Name: userConfigurationSecretName, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	casc = v1alpha2.ConfigurationAsCode{ | ||||||
|  | 		Customization: v1alpha2.Customization{ | ||||||
|  | 			Configurations: []v1alpha2.ConfigMapRef{ | ||||||
|  | 				{ | ||||||
|  | 					Name: userConfigurationConfigMapName, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			Secret: v1alpha2.SecretRef{ | ||||||
|  | 				Name: userConfigurationSecretName, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func createJenkinsCR(name, namespace string, seedJob *[]v1alpha2.SeedJob, groovyScripts v1alpha2.GroovyScripts, casc v1alpha2.ConfigurationAsCode, priorityClassName string) *v1alpha2.Jenkins { | ||||||
|  | 	var seedJobs []v1alpha2.SeedJob | ||||||
|  | 	if seedJob != nil { | ||||||
|  | 		seedJobs = append(seedJobs, *seedJob...) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	jenkins := &v1alpha2.Jenkins{ | ||||||
|  | 		TypeMeta: v1alpha2.JenkinsTypeMeta(), | ||||||
|  | 		ObjectMeta: metav1.ObjectMeta{ | ||||||
|  | 			Name:      name, | ||||||
|  | 			Namespace: namespace, | ||||||
|  | 		}, | ||||||
|  | 		Spec: v1alpha2.JenkinsSpec{ | ||||||
|  | 			GroovyScripts:       groovyScripts, | ||||||
|  | 			ConfigurationAsCode: casc, | ||||||
|  | 			Master: v1alpha2.JenkinsMaster{ | ||||||
|  | 				Annotations: map[string]string{"test": "label"}, | ||||||
|  | 				Containers: []v1alpha2.Container{ | ||||||
|  | 					{ | ||||||
|  | 						Name: resources.JenkinsMasterContainerName, | ||||||
|  | 						Env: []corev1.EnvVar{ | ||||||
|  | 							{ | ||||||
|  | 								Name:  "TEST_ENV", | ||||||
|  | 								Value: "test_env_value", | ||||||
|  | 							}, | ||||||
|  | 						}, | ||||||
|  | 						ReadinessProbe: &corev1.Probe{ | ||||||
|  | 							Handler: corev1.Handler{ | ||||||
|  | 								HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 									Path:   "/login", | ||||||
|  | 									Port:   intstr.FromString("http"), | ||||||
|  | 									Scheme: corev1.URISchemeHTTP, | ||||||
|  | 								}, | ||||||
|  | 							}, | ||||||
|  | 							InitialDelaySeconds: int32(80), | ||||||
|  | 							TimeoutSeconds:      int32(4), | ||||||
|  | 							FailureThreshold:    int32(10), | ||||||
|  | 						}, | ||||||
|  | 						LivenessProbe: &corev1.Probe{ | ||||||
|  | 							Handler: corev1.Handler{ | ||||||
|  | 								HTTPGet: &corev1.HTTPGetAction{ | ||||||
|  | 									Path:   "/login", | ||||||
|  | 									Port:   intstr.FromString("http"), | ||||||
|  | 									Scheme: corev1.URISchemeHTTP, | ||||||
|  | 								}, | ||||||
|  | 							}, | ||||||
|  | 							InitialDelaySeconds: int32(80), | ||||||
|  | 							TimeoutSeconds:      int32(4), | ||||||
|  | 							FailureThreshold:    int32(10), | ||||||
|  | 						}, | ||||||
|  | 						VolumeMounts: []corev1.VolumeMount{ | ||||||
|  | 							{ | ||||||
|  | 								Name:      "plugins-cache", | ||||||
|  | 								MountPath: "/usr/share/jenkins/ref/plugins", | ||||||
|  | 							}, | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 					{ | ||||||
|  | 						Name:  "envoyproxy", | ||||||
|  | 						Image: "envoyproxy/envoy-alpine:v1.14.1", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 				Plugins: []v1alpha2.Plugin{ | ||||||
|  | 					{Name: "audit-trail", Version: "3.7"}, | ||||||
|  | 					{Name: "simple-theme-plugin", Version: "0.6"}, | ||||||
|  | 					{Name: "github", Version: "1.32.0"}, | ||||||
|  | 					{Name: "devoptics", Version: "1.1905", DownloadURL: "https://jenkins-updates.cloudbees.com/download/plugins/devoptics/1.1905/devoptics.hpi"}, | ||||||
|  | 				}, | ||||||
|  | 				PriorityClassName: priorityClassName, | ||||||
|  | 				NodeSelector:      map[string]string{"kubernetes.io/os": "linux"}, | ||||||
|  | 				Volumes: []corev1.Volume{ | ||||||
|  | 					{ | ||||||
|  | 						Name: "plugins-cache", | ||||||
|  | 						VolumeSource: corev1.VolumeSource{ | ||||||
|  | 							EmptyDir: &corev1.EmptyDirVolumeSource{}, | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			SeedJobs: seedJobs, | ||||||
|  | 			Service: v1alpha2.Service{ | ||||||
|  | 				Type: corev1.ServiceTypeNodePort, | ||||||
|  | 				Port: constants.DefaultHTTPPortInt32, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	jenkins.Spec.Roles = []rbacv1.RoleRef{ | ||||||
|  | 		{ | ||||||
|  | 			APIGroup: "rbac.authorization.k8s.io", | ||||||
|  | 			Kind:     "Role", | ||||||
|  | 			Name:     resources.GetResourceName(jenkins), | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 	return jenkins | ||||||
|  | } | ||||||
|  | @ -0,0 +1,40 @@ | ||||||
|  | /* | ||||||
|  | Copyright 2021. | ||||||
|  | 
 | ||||||
|  | Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | you may not use this file except in compliance with the License. | ||||||
|  | You may obtain a copy of the License at | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  | Unless required by applicable law or agreed to in writing, software | ||||||
|  | distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | See the License for the specific language governing permissions and | ||||||
|  | limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | package controllers | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 
 | ||||||
|  | 	"github.com/jenkinsci/kubernetes-operator/api/v1alpha2" | ||||||
|  | 	. "github.com/onsi/ginkgo" | ||||||
|  | 	. "github.com/onsi/gomega" | ||||||
|  | 	// +kubebuilder:scaffold:imports
 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // These tests use Ginkgo (BDD-style Go testing framework). Refer to
 | ||||||
|  | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
 | ||||||
|  | var _ = Describe("Jenkins controller", func() { | ||||||
|  | 	Describe("deploying Jenkins CR into a cluster", func() { | ||||||
|  | 		Context("when deploying CR to cluster", func() { | ||||||
|  | 			It("create Jenkins instance", func() { | ||||||
|  | 				ctx := context.Background() | ||||||
|  | 				jenkins := createJenkinsCR(jenkinsCRName, namespace, &[]v1alpha2.SeedJob{mySeedJob.SeedJob}, groovyScripts, casc, priorityClassName) | ||||||
|  | 				Expect(k8sClient.Create(ctx, jenkins)).Should(Succeed()) | ||||||
|  | 			}) | ||||||
|  | 		}) | ||||||
|  | 	}) | ||||||
|  | }) | ||||||
|  | @ -0,0 +1,115 @@ | ||||||
|  | /* | ||||||
|  | Copyright 2021. | ||||||
|  | 
 | ||||||
|  | Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  | you may not use this file except in compliance with the License. | ||||||
|  | You may obtain a copy of the License at | ||||||
|  | 
 | ||||||
|  |     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | 
 | ||||||
|  | Unless required by applicable law or agreed to in writing, software | ||||||
|  | distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  | See the License for the specific language governing permissions and | ||||||
|  | limitations under the License. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | package controllers | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	jenkinsiov1alpha2 "github.com/jenkinsci/kubernetes-operator/api/v1alpha2" | ||||||
|  | 	jenkinsClient "github.com/jenkinsci/kubernetes-operator/pkg/client" | ||||||
|  | 	e "github.com/jenkinsci/kubernetes-operator/pkg/notifications/event" | ||||||
|  | 
 | ||||||
|  | 	. "github.com/onsi/ginkgo" | ||||||
|  | 	. "github.com/onsi/gomega" | ||||||
|  | 	"k8s.io/client-go/kubernetes" | ||||||
|  | 	"k8s.io/client-go/kubernetes/scheme" | ||||||
|  | 	ctrl "sigs.k8s.io/controller-runtime" | ||||||
|  | 	"sigs.k8s.io/controller-runtime/pkg/client" | ||||||
|  | 	"sigs.k8s.io/controller-runtime/pkg/envtest" | ||||||
|  | 	"sigs.k8s.io/controller-runtime/pkg/envtest/printer" | ||||||
|  | 	logf "sigs.k8s.io/controller-runtime/pkg/log" | ||||||
|  | 	"sigs.k8s.io/controller-runtime/pkg/log/zap" | ||||||
|  | 	// +kubebuilder:scaffold:imports
 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // These tests use Ginkgo (BDD-style Go testing framework). Refer to
 | ||||||
|  | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
 | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	//cfg       *rest.Config
 | ||||||
|  | 	k8sClient client.Client | ||||||
|  | 	testEnv   *envtest.Environment | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestAPIs(t *testing.T) { | ||||||
|  | 	RegisterFailHandler(Fail) | ||||||
|  | 
 | ||||||
|  | 	RunSpecsWithDefaultAndCustomReporters(t, | ||||||
|  | 		"Controller Suite", | ||||||
|  | 		[]Reporter{printer.NewlineReporter{}}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var _ = BeforeSuite(func(done Done) { | ||||||
|  | 	logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) | ||||||
|  | 
 | ||||||
|  | 	By("bootstrapping test environment") | ||||||
|  | 	testEnv = &envtest.Environment{ | ||||||
|  | 		CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	cfg, err := testEnv.Start() | ||||||
|  | 	Expect(err).NotTo(HaveOccurred()) | ||||||
|  | 	Expect(cfg).NotTo(BeNil()) | ||||||
|  | 
 | ||||||
|  | 	err = jenkinsiov1alpha2.AddToScheme(scheme.Scheme) | ||||||
|  | 	Expect(err).NotTo(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 	// +kubebuilder:scaffold:scheme
 | ||||||
|  | 
 | ||||||
|  | 	//setup manager
 | ||||||
|  | 	k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ | ||||||
|  | 		Scheme: scheme.Scheme, | ||||||
|  | 	}) | ||||||
|  | 	Expect(err).NotTo(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 	//setup controller
 | ||||||
|  | 	clientSet, err := kubernetes.NewForConfig(cfg) | ||||||
|  | 	Expect(err).NotTo(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 	notificationEvents := make(chan e.Event) | ||||||
|  | 
 | ||||||
|  | 	// validate jenkins API connection
 | ||||||
|  | 	jenkinsAPIConnectionSettings := jenkinsClient.JenkinsAPIConnectionSettings{} | ||||||
|  | 
 | ||||||
|  | 	err = (&JenkinsReconciler{ | ||||||
|  | 		Client:                       k8sManager.GetClient(), | ||||||
|  | 		Scheme:                       k8sManager.GetScheme(), | ||||||
|  | 		JenkinsAPIConnectionSettings: jenkinsAPIConnectionSettings, | ||||||
|  | 		ClientSet:                    *clientSet, | ||||||
|  | 		Config:                       *cfg, | ||||||
|  | 		NotificationEvents:           ¬ificationEvents, | ||||||
|  | 		KubernetesClusterDomain:      "", | ||||||
|  | 	}).SetupWithManager(k8sManager) | ||||||
|  | 	Expect(err).NotTo(HaveOccurred()) | ||||||
|  | 
 | ||||||
|  | 	go func() { | ||||||
|  | 		err = k8sManager.Start(ctrl.SetupSignalHandler()) | ||||||
|  | 		Expect(err).NotTo(HaveOccurred()) | ||||||
|  | 	}() | ||||||
|  | 
 | ||||||
|  | 	k8sClient = k8sManager.GetClient() | ||||||
|  | 	Expect(k8sClient).NotTo(BeNil()) | ||||||
|  | 	close(done) | ||||||
|  | 
 | ||||||
|  | }, 60) | ||||||
|  | 
 | ||||||
|  | var _ = AfterSuite(func() { | ||||||
|  | 	By("tearing down the test environment") | ||||||
|  | 	err := testEnv.Stop() | ||||||
|  | 	Expect(err).NotTo(HaveOccurred()) | ||||||
|  | }) | ||||||
							
								
								
									
										3
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										3
									
								
								go.mod
								
								
								
								
							|  | @ -10,6 +10,8 @@ require ( | ||||||
| 	github.com/go-logr/zapr v0.2.0 | 	github.com/go-logr/zapr v0.2.0 | ||||||
| 	github.com/golang/mock v1.4.1 | 	github.com/golang/mock v1.4.1 | ||||||
| 	github.com/mailgun/mailgun-go/v3 v3.6.4 | 	github.com/mailgun/mailgun-go/v3 v3.6.4 | ||||||
|  | 	github.com/onsi/ginkgo v1.14.1 | ||||||
|  | 	github.com/onsi/gomega v1.10.2 | ||||||
| 	github.com/opencontainers/go-digest v1.0.0 // indirect | 	github.com/opencontainers/go-digest v1.0.0 // indirect | ||||||
| 	github.com/openshift/api v3.9.0+incompatible | 	github.com/openshift/api v3.9.0+incompatible | ||||||
| 	github.com/pkg/errors v0.9.1 | 	github.com/pkg/errors v0.9.1 | ||||||
|  | @ -20,7 +22,6 @@ require ( | ||||||
| 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df | 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df | ||||||
| 	k8s.io/api v0.20.2 | 	k8s.io/api v0.20.2 | ||||||
| 	k8s.io/apimachinery v0.20.2 | 	k8s.io/apimachinery v0.20.2 | ||||||
| 	k8s.io/cli-runtime v0.20.2 // indirect |  | ||||||
| 	k8s.io/client-go v0.20.2 | 	k8s.io/client-go v0.20.2 | ||||||
| 	k8s.io/utils v0.0.0-20201110183641-67b214c5f920 | 	k8s.io/utils v0.0.0-20201110183641-67b214c5f920 | ||||||
| 	sigs.k8s.io/controller-runtime v0.7.0 | 	sigs.k8s.io/controller-runtime v0.7.0 | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ run: generate fmt vet manifests | ||||||
| 	go run ./main.go | 	go run ./main.go | ||||||
| 
 | 
 | ||||||
| # Install CRDs into a cluster
 | # Install CRDs into a cluster
 | ||||||
| install: manifests kustomize | install-crds: manifests kustomize | ||||||
| 	$(KUSTOMIZE) build config/crd | kubectl apply -f - | 	$(KUSTOMIZE) build config/crd | kubectl apply -f - | ||||||
| 
 | 
 | ||||||
| # Uninstall CRDs from a cluster
 | # Uninstall CRDs from a cluster
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue