diff --git a/.goreleaser.yml b/.goreleaser.yml index c99a5888..439f75ae 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -63,17 +63,6 @@ builds: - arm64 - ppc64le - s390x - - id: rukpakctl - main: ./cmd/rukpakctl - binary: rukpakctl - tags: "{{.Env.GO_BUILD_TAGS}}" - goos: - - linux - goarch: - - amd64 - - arm64 - - ppc64le - - s390x dockers: - image_templates: - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-amd64" diff --git a/Dockerfile b/Dockerfile index 48e17a25..10e8f465 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,5 @@ COPY core core COPY unpack unpack COPY webhooks webhooks COPY crdvalidator crdvalidator -COPY rukpakctl rukpakctl EXPOSE 8080 diff --git a/Makefile b/Makefile index 369c46d2..b70ac817 100644 --- a/Makefile +++ b/Makefile @@ -80,7 +80,6 @@ generate: $(CONTROLLER_GEN) ## Generate code and manifests paths=./internal/controllers/bundledeployment/... \ paths=./internal/provisioner/plain/... \ paths=./internal/provisioner/registry/... \ - paths=./internal/uploadmgr/... \ output:stdout > ./manifests/base/core/resources/cluster_role.yaml $(Q)$(CONTROLLER_GEN) rbac:roleName=webhooks-admin paths=./internal/webhook/... output:stdout > ./manifests/base/apis/webhooks/resources/cluster_role.yaml $(Q)$(CONTROLLER_GEN) rbac:roleName=helm-provisioner-admin \ @@ -111,7 +110,7 @@ test-e2e: $(GINKGO) ## Run the e2e tests $(GINKGO) --tags $(GO_BUILD_TAGS) $(E2E_FLAGS) --trace $(FOCUS) test/e2e e2e: KIND_CLUSTER_NAME=rukpak-e2e -e2e: rukpakctl run image-registry local-git kind-load-bundles registry-load-bundles test-e2e kind-cluster-cleanup ## Run e2e tests against an ephemeral kind cluster +e2e: run image-registry local-git kind-load-bundles registry-load-bundles test-e2e kind-cluster-cleanup ## Run e2e tests against an ephemeral kind cluster kind-cluster: $(KIND) kind-cluster-cleanup ## Standup a kind cluster $(KIND) create cluster --name ${KIND_CLUSTER_NAME} ${KIND_CLUSTER_CONFIG} @@ -169,7 +168,7 @@ uninstall: ## Remove all rukpak resources from the cluster ##@ build/load: -BINARIES=core helm unpack webhooks crdvalidator rukpakctl +BINARIES=core helm unpack webhooks crdvalidator LINUX_BINARIES=$(join $(addprefix linux/,$(BINARIES)), ) .PHONY: build $(BINARIES) $(LINUX_BINARIES) build-container kind-load kind-load-bundles kind-cluster registry-load-bundles diff --git a/api/v1alpha2/bundle_types.go b/api/v1alpha2/bundle_types.go index e32de58a..d9f5734b 100644 --- a/api/v1alpha2/bundle_types.go +++ b/api/v1alpha2/bundle_types.go @@ -20,11 +20,6 @@ import ( corev1 "k8s.io/api/core/v1" ) -var ( - BundleGVK = SchemeBuilder.GroupVersion.WithKind("Bundle") - BundleKind = BundleGVK.Kind -) - type SourceType string const ( @@ -58,11 +53,6 @@ type BundleSource struct { // ConfigMaps is a list of config map references and their relative // directory paths that represent a bundle filesystem. ConfigMaps []ConfigMapSource `json:"configMaps,omitempty"` - // Upload is a source that enables this Bundle's content to be uploaded - // via Rukpak's bundle upload service. This source type is primarily useful - // with bundle development workflows because it enables bundle developers - // to inject a local bundle directly into the cluster. - Upload *UploadSource `json:"upload,omitempty"` // HTTP is the remote location that backs the content of this Bundle. HTTP *HTTPSource `json:"http,omitempty"` } @@ -131,6 +121,4 @@ type Authorization struct { InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"` } -type UploadSource struct{} - type ProvisionerID string diff --git a/api/v1alpha2/bundledeployment_types.go b/api/v1alpha2/bundledeployment_types.go index e0b75a3a..eb67eb9a 100644 --- a/api/v1alpha2/bundledeployment_types.go +++ b/api/v1alpha2/bundledeployment_types.go @@ -30,8 +30,6 @@ const ( TypeHasValidBundle = "HasValidBundle" TypeHealthy = "Healthy" TypeInstalled = "Installed" - // TypeUploadStatus indicates the status of the bundle content upload by the uploadmgr. - TypeUploadStatus = "UploadStatus" ReasonBundleLoadFailed = "BundleLoadFailed" ReasonCreateDynamicWatchFailed = "CreateDynamicWatchFailed" @@ -47,8 +45,6 @@ const ( ReasonReconcileFailed = "ReconcileFailed" ReasonUnhealthy = "Unhealthy" ReasonUpgradeFailed = "UpgradeFailed" - ReasonUploadSuccessful = "UploadSuccessful" - ReasonUploadFailed = "UploadFailed" ) // BundleDeploymentSpec defines the desired state of BundleDeployment diff --git a/api/v1alpha2/zz_generated.deepcopy.go b/api/v1alpha2/zz_generated.deepcopy.go index 39672b3c..5ee6182a 100644 --- a/api/v1alpha2/zz_generated.deepcopy.go +++ b/api/v1alpha2/zz_generated.deepcopy.go @@ -163,11 +163,6 @@ func (in *BundleSource) DeepCopyInto(out *BundleSource) { *out = make([]ConfigMapSource, len(*in)) copy(*out, *in) } - if in.Upload != nil { - in, out := &in.Upload, &out.Upload - *out = new(UploadSource) - **out = **in - } if in.HTTP != nil { in, out := &in.HTTP, &out.HTTP *out = new(HTTPSource) @@ -263,18 +258,3 @@ func (in *ImageSource) DeepCopy() *ImageSource { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *UploadSource) DeepCopyInto(out *UploadSource) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UploadSource. -func (in *UploadSource) DeepCopy() *UploadSource { - if in == nil { - return nil - } - out := new(UploadSource) - in.DeepCopyInto(out) - return out -} diff --git a/cmd/core/main.go b/cmd/core/main.go index 19318344..d4ed680e 100644 --- a/cmd/core/main.go +++ b/cmd/core/main.go @@ -50,7 +50,6 @@ import ( "github.com/operator-framework/rukpak/internal/provisioner/registry" "github.com/operator-framework/rukpak/internal/source" "github.com/operator-framework/rukpak/internal/storage" - "github.com/operator-framework/rukpak/internal/uploadmgr" "github.com/operator-framework/rukpak/internal/util" "github.com/operator-framework/rukpak/internal/version" "github.com/operator-framework/rukpak/pkg/features" @@ -78,10 +77,8 @@ func main() { probeAddr string systemNamespace string unpackImage string - baseUploadManagerURL string rukpakVersion bool provisionerStorageDirectory string - uploadStorageDirectory string uploadStorageSyncInterval time.Duration ) flag.StringVar(&httpBindAddr, "http-bind-address", ":8080", "The address the http server binds to.") @@ -90,13 +87,11 @@ func main() { flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") flag.StringVar(&systemNamespace, "system-namespace", "", "Configures the namespace that gets used to deploy system resources.") flag.StringVar(&unpackImage, "unpack-image", util.DefaultUnpackImage, "Configures the container image that gets used to unpack Bundle contents.") - flag.StringVar(&baseUploadManagerURL, "base-upload-manager-url", "", "The base URL from which to fetch uploaded bundles.") flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+ "Enabling this will ensure there is only one active controller manager.") flag.BoolVar(&rukpakVersion, "version", false, "Displays rukpak version information") flag.StringVar(&provisionerStorageDirectory, "provisioner-storage-dir", storage.DefaultBundleCacheDir, "The directory that is used to store bundle contents.") - flag.StringVar(&uploadStorageDirectory, "upload-storage-dir", uploadmgr.DefaultBundleCacheDir, "The directory that is used to store bundle uploads.") flag.DurationVar(&uploadStorageSyncInterval, "upload-storage-sync-interval", time.Minute, "Interval on which to garbage collect unused uploaded bundles") opts := zap.Options{ Development: true, @@ -115,7 +110,7 @@ func main() { ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) setupLog.Info("starting up the core controllers and servers", "git commit", version.String(), "unpacker image", unpackImage) - dependentRequirement, err := labels.NewRequirement(util.CoreOwnerKindKey, selection.In, []string{rukpakv1alpha2.BundleKind, rukpakv1alpha2.BundleDeploymentKind}) + dependentRequirement, err := labels.NewRequirement(util.CoreOwnerKindKey, selection.In, []string{rukpakv1alpha2.BundleDeploymentKind}) if err != nil { setupLog.Error(err, "unable to create dependent label selector for cache") os.Exit(1) @@ -195,14 +190,6 @@ func main() { setupLog.Error(err, "unable to add bundles http handler to manager") os.Exit(1) } - if err := mgr.AddMetricsExtraHandler("/uploads/", httpLogger(uploadmgr.NewUploadHandler(mgr.GetClient(), uploadStorageDirectory))); err != nil { - setupLog.Error(err, "unable to add uploads http handler to manager") - os.Exit(1) - } - if err := mgr.Add(uploadmgr.NewBundleGC(mgr.GetCache(), uploadStorageDirectory, uploadStorageSyncInterval)); err != nil { - setupLog.Error(err, "unable to add bundle garbage collector to manager") - os.Exit(1) - } // This finalizer logic MUST be co-located with this main // controller logic because it deals with cleaning up bundle data @@ -223,7 +210,7 @@ func main() { os.Exit(1) } - unpacker, err := source.NewDefaultUnpacker(systemNsCluster, systemNamespace, unpackImage, baseUploadManagerURL, rootCAs) + unpacker, err := source.NewDefaultUnpacker(systemNsCluster, systemNamespace, unpackImage, rootCAs) if err != nil { setupLog.Error(err, "unable to setup bundle unpacker") os.Exit(1) @@ -236,13 +223,12 @@ func main() { bundledeployment.WithActionClientGetter(acg), bundledeployment.WithFinalizers(bundleFinalizers), bundledeployment.WithStorage(bundleStorage), + bundledeployment.WithUnpacker(unpacker), } if err := bundledeployment.SetupWithManager(mgr, systemNsCluster.GetCache(), systemNamespace, append( commonBDProvisionerOptions, - bundledeployment.WithUnpacker(unpacker), bundledeployment.WithProvisionerID(plain.ProvisionerID), - bundledeployment.WithBundleDeplymentProcessor(bundledeployment.ProcessorFunc(plain.ProcessBundleDeployment)), bundledeployment.WithHandler(bundledeployment.HandlerFunc(plain.HandleBundleDeployment)), )...); err != nil { setupLog.Error(err, "unable to create controller", "controller", rukpakv1alpha2.BundleDeploymentKind, "provisionerID", plain.ProvisionerID) @@ -251,12 +237,10 @@ func main() { if err := bundledeployment.SetupWithManager(mgr, systemNsCluster.GetCache(), systemNamespace, append( commonBDProvisionerOptions, - bundledeployment.WithUnpacker(unpacker), bundledeployment.WithProvisionerID(registry.ProvisionerID), - bundledeployment.WithBundleDeplymentProcessor(bundledeployment.ProcessorFunc(registry.ProcessBundleDeployment)), - bundledeployment.WithHandler(bundledeployment.HandlerFunc(plain.HandleBundleDeployment)), + bundledeployment.WithHandler(bundledeployment.HandlerFunc(registry.HandleBundleDeployment)), )...); err != nil { - setupLog.Error(err, "unable to create controller", "controller", rukpakv1alpha2.BundleDeploymentKind, "provisionerID", plain.ProvisionerID) + setupLog.Error(err, "unable to create controller", "controller", rukpakv1alpha2.BundleDeploymentKind, "provisionerID", registry.ProvisionerID) os.Exit(1) } //+kubebuilder:scaffold:builder diff --git a/cmd/helm/main.go b/cmd/helm/main.go index 904093a7..e7f32302 100644 --- a/cmd/helm/main.go +++ b/cmd/helm/main.go @@ -68,7 +68,6 @@ func main() { probeAddr string systemNamespace string unpackImage string - baseUploadManagerURL string rukpakVersion bool storageDirectory string ) @@ -77,7 +76,6 @@ func main() { flag.StringVar(&bundleCAFile, "bundle-ca-file", "", "The file containing the certificate authority for connecting to bundle content servers.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") flag.StringVar(&unpackImage, "unpack-image", util.DefaultUnpackImage, "Configures the container image that gets used to unpack Bundle contents.") - flag.StringVar(&baseUploadManagerURL, "base-upload-manager-url", "", "The base URL from which to fetch uploaded bundles.") flag.StringVar(&systemNamespace, "system-namespace", "", "Configures the namespace that gets used to deploy system resources.") flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+ @@ -197,7 +195,7 @@ func main() { os.Exit(1) } - unpacker, err := source.NewDefaultUnpacker(systemNsCluster, systemNamespace, unpackImage, baseUploadManagerURL, rootCAs) + unpacker, err := source.NewDefaultUnpacker(systemNsCluster, systemNamespace, unpackImage, rootCAs) if err != nil { setupLog.Error(err, "unable to setup bundle unpacker") os.Exit(1) @@ -210,13 +208,12 @@ func main() { bundledeployment.WithFinalizers(bundleFinalizers), bundledeployment.WithActionClientGetter(acg), bundledeployment.WithStorage(bundleStorage), + bundledeployment.WithUnpacker(unpacker), } if err := bundledeployment.SetupWithManager(mgr, systemNsCluster.GetCache(), systemNamespace, append( commonBDProvisionerOptions, bundledeployment.WithProvisionerID(helm.ProvisionerID), - bundledeployment.WithUnpacker(unpacker), - bundledeployment.WithBundleDeplymentProcessor(bundledeployment.ProcessorFunc(helm.ProcessBundleDeployment)), bundledeployment.WithHandler(bundledeployment.HandlerFunc(helm.HandleBundleDeployment)), )...); err != nil { setupLog.Error(err, "unable to create controller", "controller", rukpakv1alpha2.BundleDeploymentKind, "provisionerID", helm.ProvisionerID) diff --git a/cmd/rukpakctl/LICENSE b/cmd/rukpakctl/LICENSE deleted file mode 100644 index e69de29b..00000000 diff --git a/cmd/rukpakctl/cmd/alpha.go b/cmd/rukpakctl/cmd/alpha.go deleted file mode 100644 index 1d103092..00000000 --- a/cmd/rukpakctl/cmd/alpha.go +++ /dev/null @@ -1,39 +0,0 @@ -package cmd - -import "github.com/spf13/cobra" - -func newAlphaCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "alpha", - Short: "unstable or experimental subcommands", - Hidden: false, - } - - cmd.AddCommand( - newAlphaBootstrapCmd(), - ) - - if !cmd.HasSubCommands() { - return nil - } - - // If all of the 'alpha' subcommands are hidden, hide the alpha command - // and unhide the alpha subcommands. - if allHidden(cmd.Commands()) { - cmd.Hidden = true - for _, c := range cmd.Commands() { - c.Hidden = false - } - } - - return cmd -} - -func allHidden(cs []*cobra.Command) bool { - for _, c := range cs { - if !c.Hidden { - return false - } - } - return true -} diff --git a/cmd/rukpakctl/cmd/alpha_bootstrap.go b/cmd/rukpakctl/cmd/alpha_bootstrap.go deleted file mode 100644 index f624310c..00000000 --- a/cmd/rukpakctl/cmd/alpha_bootstrap.go +++ /dev/null @@ -1,119 +0,0 @@ -package cmd - -import ( - "bytes" - "fmt" - "log" - "testing/fstest" - - "github.com/spf13/cobra" - "k8s.io/cli-runtime/pkg/resource" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/config" - "sigs.k8s.io/yaml" - - "github.com/operator-framework/rukpak/internal/provisioner/plain" - "github.com/operator-framework/rukpak/internal/rukpakctl" - "github.com/operator-framework/rukpak/internal/util" -) - -func newAlphaBootstrapCmd() *cobra.Command { - var ( - systemNamespace string - uploadServiceName string - caSecretName string - ) - cmd := &cobra.Command{ - Use: "bootstrap ", - Hidden: true, - Short: "Bootstrap or adopt a manifest into rukpak's management.", - Long: `Bootstrap or adopt a manifest into rukpak's management. - -The bootstrap subcommand allows administrators to deploy or update an -existing set of arbitrary kubernetes objects such that they become -managed by rukpak. This is useful for bootstrapping rukpak itself or -in migration scenarios where existing cluster objects need to be moved -under the management of a rukpak BundleDeployment.' -`, - Example: ` - # - # Bootstrap a rukpak release manifest into a BundleDeployment - # - $ curl -sSL https://github.com/operator-framework/rukpak/releases/download//rukpak.yaml | rukpakctl alpha bootstrap rukpak - successfully bootstrapped bundle deployment "rukpak" - - # - # Adopt an existing set of resources into a BundleDeployment - # - $ kubectl apply -f stuff.yaml - $ kubectl get -f stuff.yaml -o yaml | rukpakctl alpha bootstrap stuff - successfully bootstrapped bundle deployment "stuff" -`, - Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { - ctx := cmd.Context() - bundleDeploymentName := args[0] - result := resource.NewLocalBuilder().Unstructured().Flatten().Stdin().Do() - if err := result.Err(); err != nil { - log.Fatal(err) - } - items, err := result.Infos() - if err != nil { - log.Fatal(err) - } - - cfg, err := config.GetConfig() - if err != nil { - log.Fatal(err) - } - cl, err := client.New(cfg, client.Options{}) - if err != nil { - log.Fatal(err) - } - - for _, item := range items { - obj := item.Object.DeepCopyObject().(client.Object) - util.AdoptObject(obj, systemNamespace, bundleDeploymentName) - if err := cl.Patch(ctx, obj, client.Apply, client.ForceOwnership, client.FieldOwner("rukpakctl")); err != nil { - log.Fatal(err) - } - } - - manifest := bytes.Buffer{} - for _, item := range items { - manifest.WriteString("---\n") - data, err := yaml.Marshal(item.Object) - if err != nil { - log.Fatal(err) - } - manifest.Write(data) - } - - bundleFS := &fstest.MapFS{ - "manifests/manifest.yaml": &fstest.MapFile{Data: manifest.Bytes()}, - } - - r := rukpakctl.Run{ - Config: cfg, - SystemNamespace: systemNamespace, - UploadServiceName: uploadServiceName, - CASecretName: caSecretName, - } - modified, err := r.Run(ctx, bundleDeploymentName, bundleFS, rukpakctl.RunOptions{ - BundleDeploymentProvisionerClassName: plain.ProvisionerID, - }) - if err != nil { - log.Fatal(err) - } - if !modified { - fmt.Printf("bundle deployment %q is already up-to-date\n", bundleDeploymentName) - } else { - fmt.Printf("successfully bootstrapped bundle deployment %q\n", bundleDeploymentName) - } - }, - } - cmd.Flags().StringVar(&systemNamespace, "system-namespace", util.DefaultSystemNamespace, "Namespace in which the core rukpak provisioners are running.") - cmd.Flags().StringVar(&uploadServiceName, "upload-service-name", util.DefaultUploadServiceName, "the name of the service of the upload manager.") - cmd.Flags().StringVar(&caSecretName, "ca-secret-name", "rukpak-ca", "the name of the secret in the system namespace containing the root CAs used to authenticate the upload service.") - return cmd -} diff --git a/cmd/rukpakctl/cmd/content.go b/cmd/rukpakctl/cmd/content.go deleted file mode 100644 index 18ba68aa..00000000 --- a/cmd/rukpakctl/cmd/content.go +++ /dev/null @@ -1,209 +0,0 @@ -/* -Copyright © 2022 NAME HERE - -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 cmd - -import ( - "context" - "errors" - "fmt" - "io" - "log" - "os" - "time" - - "github.com/spf13/cobra" - batchv1 "k8s.io/api/batch/v1" - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/kubernetes" - runtimeclient "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/config" - - rukpakv1alpha2 "github.com/operator-framework/rukpak/api/v1alpha2" - "github.com/operator-framework/rukpak/internal/util" -) - -type options struct { - *kubernetes.Clientset - runtimeclient.Client - namespace string -} - -func newContentCmd() *cobra.Command { - var opt options - - contentCmd := &cobra.Command{ - Use: "content ", - Short: "display contents of the specified bundledeployment.", - Long: `display contents of the specified bundledeployment.`, - Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { - sch := runtime.NewScheme() - if err := rukpakv1alpha2.AddToScheme(sch); err != nil { - log.Fatalf("failed to add rukpak types to scheme: %v", err) - } - - cfg, err := config.GetConfig() - if err != nil { - log.Fatalf("failed to load kubeconfig: %v", err) - } - - opt.Client, err = runtimeclient.New(cfg, runtimeclient.Options{ - Scheme: sch, - }) - if err != nil { - log.Fatalf("failed to create kubernetes client: %v", err) - } - - if opt.Clientset, err = kubernetes.NewForConfig(cfg); err != nil { - log.Fatalf("failed to create kubernetes client: %v", err) - } - - if err := content(cmd.Context(), opt, args); err != nil { - log.Fatalf("content command failed: %v", err) - } - }, - } - contentCmd.Flags().StringVar(&opt.namespace, "namespace", util.DefaultSystemNamespace, "namespace to run content query job.") - return contentCmd -} - -func content(ctx context.Context, opt options, args []string) error { - // Create a temporary ClusterRoleBinding to bind the ServiceAccount to bundle-reader ClusterRole - crb := &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: "rukpakctl-crb", - Namespace: opt.namespace, - }, - Subjects: []rbacv1.Subject{{Kind: "ServiceAccount", Name: "rukpakctl-sa", Namespace: opt.namespace}}, - RoleRef: rbacv1.RoleRef{APIGroup: "rbac.authorization.k8s.io", Kind: "ClusterRole", Name: "bundle-reader"}, - } - crb, err := opt.RbacV1().ClusterRoleBindings().Create(ctx, crb, metav1.CreateOptions{}) - if err != nil { - return fmt.Errorf("failed to create a cluster role bindings: %v", err) - } - defer deletecrb(ctx, opt.Clientset) - - // Create a temporary ServiceAccount - sa := corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: "rukpakctl-sa", - Namespace: opt.namespace, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: "rbac.authorization.k8s.io/v1", - Kind: "ClusterRoleBinding", - Name: "rukpakctl-crb", - UID: crb.ObjectMeta.UID, - }, - }, - }, - } - _, err = opt.CoreV1().ServiceAccounts(opt.namespace).Create(ctx, &sa, metav1.CreateOptions{}) - if err != nil { - return fmt.Errorf("failed to create a service account: %v", err) - } - - bundledeployment := &rukpakv1alpha2.BundleDeployment{} - err = opt.Get(ctx, runtimeclient.ObjectKey{Name: args[0]}, bundledeployment) - if err != nil { - return err - } - url := bundledeployment.Status.ContentURL - if url == "" { - return errors.New("error: url is not available") - } - - // Create a Job that reads from the URL and outputs contents in the pod log - mounttoken := true - job := &batchv1.Job{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "rukpakctl-job-", - Namespace: opt.namespace, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: "rbac.authorization.k8s.io/v1", - Kind: "ClusterRoleBinding", - Name: "rukpakctl-crb", - UID: crb.ObjectMeta.UID, - }, - }, - }, - Spec: batchv1.JobSpec{ - Template: corev1.PodTemplateSpec{ - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: "rukpakctl", - Image: "curlimages/curl", - Command: []string{"sh", "-c", "curl -sSLk -H \"Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)\" -o - " + url + " | tar ztv"}, - }, - }, - ServiceAccountName: "rukpakctl-sa", - RestartPolicy: "Never", - AutomountServiceAccountToken: &mounttoken, - }, - }, - }, - } - job, err = opt.BatchV1().Jobs(opt.namespace).Create(ctx, job, metav1.CreateOptions{}) - if err != nil { - return fmt.Errorf("failed to create a job: %v", err) - } - - // Wait for Job completion - if err := wait.PollImmediateUntil(time.Second, func() (bool, error) { - deployedJob, err := opt.BatchV1().Jobs(opt.namespace).Get(ctx, job.ObjectMeta.Name, metav1.GetOptions{}) - if err != nil { - return false, fmt.Errorf("failed to get a job: %v", err) - } - return deployedJob.Status.CompletionTime != nil, nil - }, ctx.Done()); err != nil { - return fmt.Errorf("failed waiting for job to complete: %v", err) - } - - // Get Pod for the Job - podSelector := labels.Set{"job-name": job.Name}.AsSelector() - pods, err := opt.CoreV1().Pods(opt.namespace).List(ctx, metav1.ListOptions{LabelSelector: podSelector.String()}) - if err != nil { - return fmt.Errorf("failed to list pods for job: %v", err) - } - const expectedPods = 1 - if len(pods.Items) != expectedPods { - return fmt.Errorf("unexpected number of pods found for job: expected %d, found %d", expectedPods, len(pods.Items)) - } - - // Get logs of the Pod - logReader, err := opt.CoreV1().Pods(opt.namespace).GetLogs(pods.Items[0].Name, &corev1.PodLogOptions{}).Stream(ctx) - if err != nil { - return fmt.Errorf("failed to get pod logs: %v", err) - } - defer logReader.Close() - if _, err := io.Copy(os.Stdout, logReader); err != nil { - return fmt.Errorf("failed to read log: %v", err) - } - return nil -} - -func deletecrb(ctx context.Context, kube kubernetes.Interface) { - if err := kube.RbacV1().ClusterRoleBindings().Delete(ctx, "rukpakctl-crb", metav1.DeleteOptions{}); err != nil { - fmt.Printf("failed to delete clusterrolebinding: %v", err) - } -} diff --git a/cmd/rukpakctl/cmd/root.go b/cmd/rukpakctl/cmd/root.go deleted file mode 100644 index 1dcd7010..00000000 --- a/cmd/rukpakctl/cmd/root.go +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright © 2022 NAME HERE -*/ -package cmd - -import ( - "os" - - "github.com/spf13/cobra" -) - -// Execute adds all child commands to the root command and sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute() { - rootCmd := &cobra.Command{ - Use: "rukpakctl", - Short: "A brief description of your application", - Long: `A longer description that spans multiple lines and likely contains -examples and usage of using your application. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, - } - - rootCmd.AddCommand( - newContentCmd(), - newRunCmd(), - newVersionCmd(), - ) - - // Only add the alpha command if its non-nil. It will be nil if - // it has no subcommands. We structure it this way because alpha - // commands can come and go. - if alphaCmd := newAlphaCmd(); alphaCmd != nil { - rootCmd.AddCommand(alphaCmd) - } - - err := rootCmd.Execute() - if err != nil { - os.Exit(1) - } -} diff --git a/cmd/rukpakctl/cmd/run.go b/cmd/rukpakctl/cmd/run.go deleted file mode 100644 index 195d3793..00000000 --- a/cmd/rukpakctl/cmd/run.go +++ /dev/null @@ -1,89 +0,0 @@ -/* -Copyright © 2022 NAME HERE -*/ -package cmd - -import ( - "fmt" - "log" - "os" - - "github.com/spf13/cobra" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/manager/signals" - - "github.com/operator-framework/rukpak/internal/provisioner/plain" - "github.com/operator-framework/rukpak/internal/rukpakctl" - "github.com/operator-framework/rukpak/internal/util" -) - -// newRunCmd creates the run command -func newRunCmd() *cobra.Command { - var ( - systemNamespace string - uploadServiceName string - caSecretName string - bundleDeploymentProvisionerClassName string - bundleProvisionerClassName string - ) - - cmd := &cobra.Command{ - Use: "run ", - Short: "Run a bundle from an upload of a local bundle directory.", - Long: `Run a bundle from an upload of a local bundle directory. - -The run subcommand allows bundle developers to quickly iterate on bundles -they are developing, and to test how their bundle deployment pivots from -one version to the next. -`, - Example: ` - # - # Initial creation of memcached-api bundle deployment: - # - $ rukpakctl run memcached-api ./memcached-api-v0.1.0/ - bundledeployment.core.rukpak.io "memcached-api" applied - successfully uploaded bundle content for "memcached-api-5b9bbf8799" - - # - # Pivot to a new bundle for the existing memcached-api bundle-deployment - # - $ rukpakctl run memcached-api ./memcached-api-v0.2.0/ - bundledeployment.core.rukpak.io "memcached-api" applied - successfully uploaded bundle content for "memcached-api-8578dfddf9" - - # - # Run the same command again - # - $ rukpakctl run memcached-api ./memcached-api-v0.2.0/ - bundledeployment.core.rukpak.io "memcached-api" applied - bundle "memcached-api-8578dfddf9" is already up-to-date -`, - Args: cobra.ExactArgs(2), - Run: func(cmd *cobra.Command, args []string) { - bundleDeploymentName, bundleDir := args[0], args[1] - ctx := signals.SetupSignalHandler() - - cfg := ctrl.GetConfigOrDie() - - r := rukpakctl.Run{ - Config: cfg, - SystemNamespace: systemNamespace, - UploadServiceName: uploadServiceName, - CASecretName: caSecretName, - } - _, err := r.Run(ctx, bundleDeploymentName, os.DirFS(bundleDir), rukpakctl.RunOptions{ - BundleDeploymentProvisionerClassName: bundleDeploymentProvisionerClassName, - Log: func(format string, a ...interface{}) { fmt.Printf(format, a...) }, - }) - if err != nil { - log.Fatal(err) - } - }, - } - cmd.Flags().StringVar(&systemNamespace, "system-namespace", util.DefaultSystemNamespace, "the namespace in which the rukpak controllers are deployed.") - cmd.Flags().StringVar(&uploadServiceName, "upload-service-name", util.DefaultUploadServiceName, "the name of the service of the upload manager.") - cmd.Flags().StringVar(&caSecretName, "ca-secret-name", "rukpak-ca", "the name of the secret in the system namespace containing the root CAs used to authenticate the upload service.") - cmd.Flags().StringVar(&bundleDeploymentProvisionerClassName, "bundle-deployment-provisioner-class", plain.ProvisionerID, "Provisioner class name to set on bundle deployment.") - cmd.Flags().StringVar(&bundleProvisionerClassName, "bundle-provisioner-class", plain.ProvisionerID, "Provisioner class name to set on bundle.") - return cmd -} diff --git a/cmd/rukpakctl/cmd/version.go b/cmd/rukpakctl/cmd/version.go deleted file mode 100644 index ed1adfb9..00000000 --- a/cmd/rukpakctl/cmd/version.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2023 The Operator Framework Authors. - -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 cmd - -import ( - "fmt" - - "github.com/spf13/cobra" - - "github.com/operator-framework/rukpak/internal/version" -) - -// newVersionCmd creates the version command -func newVersionCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "version", - Short: "Print the rukpakctl version information.", - Run: func(cmd *cobra.Command, args []string) { - fmt.Println(version.String()) - }, - } - return cmd -} diff --git a/cmd/rukpakctl/main.go b/cmd/rukpakctl/main.go deleted file mode 100644 index 3ec46287..00000000 --- a/cmd/rukpakctl/main.go +++ /dev/null @@ -1,12 +0,0 @@ -/* -Copyright © 2022 NAME HERE -*/ -package main - -import ( - "github.com/operator-framework/rukpak/cmd/rukpakctl/cmd" -) - -func main() { - cmd.Execute() -} diff --git a/go.mod b/go.mod index 2195384d..79067bb2 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,7 @@ require ( github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-git/v5 v5.11.0 github.com/go-logr/logr v1.4.1 - github.com/gorilla/handlers v1.5.2 - github.com/gorilla/mux v1.8.0 + github.com/gorilla/handlers v1.5.1 github.com/nlepage/go-tarfs v1.2.1 github.com/onsi/ginkgo/v2 v2.13.2 github.com/onsi/gomega v1.30.0 @@ -17,7 +16,7 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.4 - golang.org/x/crypto v0.17.0 + golang.org/x/crypto v0.18.0 golang.org/x/sync v0.5.0 helm.sh/helm/v3 v3.11.1 k8s.io/api v0.26.10 @@ -100,6 +99,7 @@ require ( github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.1 // indirect + github.com/gorilla/mux v1.8.0 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect @@ -179,8 +179,8 @@ require ( golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/oauth2 v0.15.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/term v0.15.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.16.1 // indirect diff --git a/go.sum b/go.sum index d5432d72..f2ee4cd9 100644 --- a/go.sum +++ b/go.sum @@ -182,6 +182,7 @@ github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZM github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -338,8 +339,8 @@ github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= -github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -727,8 +728,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -919,15 +920,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/internal/controllers/bundledeployment/bundledeployment.go b/internal/controllers/bundledeployment/bundledeployment.go index 810f4fd0..6a878a4a 100644 --- a/internal/controllers/bundledeployment/bundledeployment.go +++ b/internal/controllers/bundledeployment/bundledeployment.go @@ -6,10 +6,8 @@ import ( "errors" "fmt" "io" - "io/fs" "strings" "sync" - "time" helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client" "helm.sh/helm/v3/pkg/action" @@ -73,12 +71,6 @@ func WithHandler(h Handler) Option { } } -func WithBundleDeplymentProcessor(b Processor) Option { - return func(c *controller) { - c.bundleDeploymentProcessor = b - } -} - func WithProvisionerID(provisionerID string) Option { return func(c *controller) { c.provisionerID = provisionerID @@ -125,8 +117,6 @@ func SetupWithManager(mgr manager.Manager, systemNsCache cache.Cache, systemName o(c) } - c.setDefaults() - if err := c.validateConfig(); err != nil { return fmt.Errorf("invalid configuration: %v", err) } @@ -148,14 +138,6 @@ func SetupWithManager(mgr manager.Manager, systemNsCache cache.Cache, systemName return nil } -func (c *controller) setDefaults() { - if c.bundleDeploymentProcessor == nil { - c.bundleDeploymentProcessor = ProcessorFunc(func(_ context.Context, fsys fs.FS, _ *rukpakv1alpha2.BundleDeployment) (fs.FS, error) { - return fsys, nil - }) - } -} - func (c *controller) validateConfig() error { errs := []error{} if c.handler == nil { @@ -186,12 +168,11 @@ func (c *controller) validateConfig() error { type controller struct { cl client.Client - handler Handler - bundleDeploymentProcessor Processor - provisionerID string - acg helmclient.ActionClientGetter - storage storage.Storage - releaseNamespace string + handler Handler + provisionerID string + acg helmclient.ActionClientGetter + storage storage.Storage + releaseNamespace string unpacker unpackersource.Unpacker controller crcontroller.Controller @@ -200,9 +181,8 @@ type controller struct { dynamicWatchGVKs map[schema.GroupVersionKind]struct{} } -// TODO: recheck rbac //+kubebuilder:rbac:groups=core.rukpak.io,resources=bundledeployments/finalizers,verbs=update -//+kubebuilder:rbac:groups=core.rukpak.io,resources=bundledeployments,verbs=list;watch;update;patch +//+kubebuilder:rbac:groups=core.rukpak.io,resources=bundledeployments,verbs=list;watch //+kubebuilder:rbac:groups=core.rukpak.io,resources=bundledeployments/status,verbs=update;patch //+kubebuilder:rbac:verbs=get,urls=/bundles/*;/uploads/* //+kubebuilder:rbac:groups=core,resources=pods,verbs=list;watch;create;delete @@ -230,13 +210,22 @@ func (c *controller) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu reconciledBD := existingBD.DeepCopy() res, reconcileErr := c.reconcile(ctx, reconciledBD) - if !equality.Semantic.DeepEqual(existingBD.Status, reconciledBD.Status) { + // Do checks before any Update()s, as Update() may modify the resource structure! + updateStatus := !equality.Semantic.DeepEqual(existingBD.Status, reconciledBD.Status) + updateFinalizers := !equality.Semantic.DeepEqual(existingBD.Finalizers, reconciledBD.Finalizers) + unexpectedFieldsChanged := checkForUnexpectedFieldChange(*existingBD, *reconciledBD) + + if updateStatus { if updateErr := c.cl.Status().Update(ctx, reconciledBD); updateErr != nil { return res, utilerrors.NewAggregate([]error{reconcileErr, updateErr}) } } - existingBD.Status, reconciledBD.Status = rukpakv1alpha2.BundleDeploymentStatus{}, rukpakv1alpha2.BundleDeploymentStatus{} - if !equality.Semantic.DeepEqual(existingBD, reconciledBD) { + + if unexpectedFieldsChanged { + panic("spec or metadata changed by reconciler") + } + + if updateFinalizers { if updateErr := c.cl.Update(ctx, reconciledBD); updateErr != nil { return res, utilerrors.NewAggregate([]error{reconcileErr, updateErr}) } @@ -252,9 +241,8 @@ func (c *controller) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu func (c *controller) reconcile(ctx context.Context, bd *rukpakv1alpha2.BundleDeployment) (ctrl.Result, error) { bd.Status.ObservedGeneration = bd.Generation - // handle finalizers - finalizerBundleDelpoyment := bd.DeepCopy() - finalizerResult, err := c.finalizers.Finalize(ctx, finalizerBundleDelpoyment) + // handle finalizers. + _, err := c.finalizers.Finalize(ctx, bd) if err != nil { bd.Status.ResolvedSource = nil @@ -268,19 +256,6 @@ func (c *controller) reconcile(ctx context.Context, bd *rukpakv1alpha2.BundleDep return ctrl.Result{}, err } - if finalizerResult.Updated { - // The only thing outside the status that should ever change when handling finalizers - // is the list of finalizers in the object's metadata. In particular, we'd expect - // finalizers to be added or removed. - bd.ObjectMeta.Finalizers = finalizerBundleDelpoyment.ObjectMeta.Finalizers - } - if finalizerResult.StatusUpdated { - bd.Status = finalizerBundleDelpoyment.Status - } - if finalizerResult.Updated || finalizerResult.StatusUpdated || !bd.GetDeletionTimestamp().IsZero() { - return ctrl.Result{}, nil - } - unpackResult, err := c.unpacker.Unpack(ctx, bd) if err != nil { return ctrl.Result{}, updateStatusUnpackFailing(&bd.Status, fmt.Errorf("source bundle content: %v", err)) @@ -291,20 +266,12 @@ func (c *controller) reconcile(ctx context.Context, bd *rukpakv1alpha2.BundleDep updateStatusUnpackPending(&bd.Status, unpackResult) // There must a limit to number of retries if status is stuck at // unpack pending. - // Forcefully requing here, to ensure that the next reconcile - // is triggered. - // TODO: Caliberate the requeue interval if needed. - return ctrl.Result{RequeueAfter: 5 * time.Second}, nil + return ctrl.Result{}, nil case unpackersource.StateUnpacking: updateStatusUnpacking(&bd.Status, unpackResult) return ctrl.Result{}, nil case unpackersource.StateUnpacked: - storeFS, err := c.bundleDeploymentProcessor.Process(ctx, unpackResult.Bundle, bd) - if err != nil { - return ctrl.Result{}, updateStatusUnpackFailing(&bd.Status, err) - } - - if err := c.storage.Store(ctx, bd, storeFS); err != nil { + if err := c.storage.Store(ctx, bd, unpackResult.Bundle); err != nil { return ctrl.Result{}, updateStatusUnpackFailing(&bd.Status, fmt.Errorf("persist bundle content: %v", err)) } contentURL, err := c.storage.URLFor(ctx, bd) @@ -330,9 +297,9 @@ func (c *controller) reconcile(ctx context.Context, bd *rukpakv1alpha2.BundleDep chrt, values, err := c.handler.Handle(ctx, bundleFS, bd) if err != nil { meta.SetStatusCondition(&bd.Status.Conditions, metav1.Condition{ - Type: rukpakv1alpha2.TypeHasValidBundle, + Type: rukpakv1alpha2.TypeInstalled, Status: metav1.ConditionFalse, - Reason: rukpakv1alpha2.ReasonBundleLoadFailed, + Reason: rukpakv1alpha2.ReasonInstallFailed, Message: err.Error(), }) return ctrl.Result{}, err @@ -586,6 +553,13 @@ func (p *postrenderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, erro return &buf, nil } +// Compare resources - ignoring status & metadata.finalizers +func checkForUnexpectedFieldChange(a, b rukpakv1alpha2.BundleDeployment) bool { + a.Status, b.Status = rukpakv1alpha2.BundleDeploymentStatus{}, rukpakv1alpha2.BundleDeploymentStatus{} + a.Finalizers, b.Finalizers = []string{}, []string{} + return !equality.Semantic.DeepEqual(a, b) +} + func updateStatusUnpackFailing(status *rukpakv1alpha2.BundleDeploymentStatus, err error) error { status.ResolvedSource = nil status.ContentURL = "" diff --git a/internal/controllers/bundledeployment/interfaces.go b/internal/controllers/bundledeployment/interfaces.go index 803422ff..955fd0d6 100644 --- a/internal/controllers/bundledeployment/interfaces.go +++ b/internal/controllers/bundledeployment/interfaces.go @@ -19,16 +19,3 @@ type HandlerFunc func(context.Context, fs.FS, *rukpakv1alpha2.BundleDeployment) func (f HandlerFunc) Handle(ctx context.Context, fsys fs.FS, bd *rukpakv1alpha2.BundleDeployment) (*chart.Chart, chartutil.Values, error) { return f(ctx, fsys, bd) } - -// TODO: Having two interfaces with same parameters seems unnecessary. This should ideally -// be moved to HandleBundleDeployment. With it, we can remove the additional step of loading from -// store. -type Processor interface { - Process(context.Context, fs.FS, *rukpakv1alpha2.BundleDeployment) (fs.FS, error) -} - -type ProcessorFunc func(context.Context, fs.FS, *rukpakv1alpha2.BundleDeployment) (fs.FS, error) - -func (f ProcessorFunc) Process(ctx context.Context, fsys fs.FS, b *rukpakv1alpha2.BundleDeployment) (fs.FS, error) { - return f(ctx, fsys, b) -} diff --git a/internal/provisioner/helm/helm.go b/internal/provisioner/helm/helm.go index 4b0c4832..af4bcb15 100644 --- a/internal/provisioner/helm/helm.go +++ b/internal/provisioner/helm/helm.go @@ -21,28 +21,21 @@ const ( ProvisionerID = "core-rukpak-io-helm" ) -func ProcessBundleDeployment(_ context.Context, fsys fs.FS, _ *rukpakv1alpha2.BundleDeployment) (fs.FS, error) { +func HandleBundleDeployment(_ context.Context, fsys fs.FS, bd *rukpakv1alpha2.BundleDeployment) (*chart.Chart, chartutil.Values, error) { // Helm expects an FS whose root contains a single chart directory. Depending on how // the bundle is sourced, the FS may or may not contain this single chart directory in // its root (e.g. charts uploaded via 'rukpakctl run ') would not. // This FS wrapper adds this base directory unless the FS already has a base directory. chartFS, err := util.EnsureBaseDirFS(fsys, "chart") if err != nil { - return nil, err - } - - if _, err = getChart(chartFS); err != nil { - return nil, err + return nil, nil, err } - return chartFS, nil -} -func HandleBundleDeployment(_ context.Context, fsys fs.FS, bd *rukpakv1alpha2.BundleDeployment) (*chart.Chart, chartutil.Values, error) { values, err := loadValues(bd) if err != nil { return nil, nil, err } - chart, err := getChart(fsys) + chart, err := getChart(chartFS) if err != nil { return nil, nil, err } diff --git a/internal/provisioner/plain/plain.go b/internal/provisioner/plain/plain.go index 9516503b..7e0e71c5 100644 --- a/internal/provisioner/plain/plain.go +++ b/internal/provisioner/plain/plain.go @@ -24,14 +24,11 @@ const ( manifestsDir = "manifests" ) -func ProcessBundleDeployment(_ context.Context, fsys fs.FS, _ *rukpakv1alpha2.BundleDeployment) (fs.FS, error) { +func HandleBundleDeployment(_ context.Context, fsys fs.FS, bd *rukpakv1alpha2.BundleDeployment) (*chart.Chart, chartutil.Values, error) { if err := ValidateBundle(fsys); err != nil { - return nil, err + return nil, nil, err } - return fsys, nil -} -func HandleBundleDeployment(_ context.Context, fsys fs.FS, bd *rukpakv1alpha2.BundleDeployment) (*chart.Chart, chartutil.Values, error) { chrt, err := chartFromBundle(fsys, bd) if err != nil { return nil, nil, err diff --git a/internal/provisioner/registry/registry.go b/internal/provisioner/registry/registry.go index 91d8f827..8652c140 100644 --- a/internal/provisioner/registry/registry.go +++ b/internal/provisioner/registry/registry.go @@ -5,6 +5,9 @@ import ( "fmt" "io/fs" + "helm.sh/helm/v3/pkg/chart" + "helm.sh/helm/v3/pkg/chartutil" + rukpakv1alpha2 "github.com/operator-framework/rukpak/api/v1alpha2" "github.com/operator-framework/rukpak/internal/convert" "github.com/operator-framework/rukpak/internal/provisioner/plain" @@ -15,14 +18,10 @@ const ( ProvisionerID = "core-rukpak-io-registry" ) -func ProcessBundleDeployment(_ context.Context, fsys fs.FS, _ *rukpakv1alpha2.BundleDeployment) (fs.FS, error) { +func HandleBundleDeployment(ctx context.Context, fsys fs.FS, bd *rukpakv1alpha2.BundleDeployment) (*chart.Chart, chartutil.Values, error) { plainFS, err := convert.RegistryV1ToPlain(fsys) if err != nil { - return nil, fmt.Errorf("convert registry+v1 bundle to plain+v0 bundle: %v", err) - } - - if err := plain.ValidateBundle(plainFS); err != nil { - return nil, fmt.Errorf("validate bundle: %v", err) + return nil, nil, fmt.Errorf("convert registry+v1 bundle to plain+v0 bundle: %v", err) } - return plainFS, nil + return plain.HandleBundleDeployment(ctx, plainFS, bd) } diff --git a/internal/rukpakctl/ca.go b/internal/rukpakctl/ca.go deleted file mode 100644 index 586c62ca..00000000 --- a/internal/rukpakctl/ca.go +++ /dev/null @@ -1,26 +0,0 @@ -package rukpakctl - -import ( - "context" - "crypto/x509" - "errors" - "fmt" - - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -// GetClusterCA returns an x509.CertPool by reading the contents of a Kubernetes Secret. It uses the provided -// client to get the requested secret and then loads the contents of the secret's "ca.crt" key into the cert pool. -func GetClusterCA(ctx context.Context, cl client.Reader, secretKey types.NamespacedName) (*x509.CertPool, error) { - caSecret := &corev1.Secret{} - if err := cl.Get(ctx, secretKey, caSecret); err != nil { - return nil, fmt.Errorf("get rukpak certificate authority: %v", err) - } - certPool := x509.NewCertPool() - if !certPool.AppendCertsFromPEM(caSecret.Data["ca.crt"]) { - return nil, errors.New("failed to load certificate authority into cert pool: malformed PEM?") - } - return certPool, nil -} diff --git a/internal/rukpakctl/portforward.go b/internal/rukpakctl/portforward.go deleted file mode 100644 index 64e60d53..00000000 --- a/internal/rukpakctl/portforward.go +++ /dev/null @@ -1,151 +0,0 @@ -package rukpakctl - -import ( - "bytes" - "context" - "errors" - "fmt" - "net/http" - "net/url" - "strings" - "time" - - "golang.org/x/sync/errgroup" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/portforward" - "k8s.io/client-go/transport/spdy" -) - -// ServicePortForwarder forwards a port from a local port to a Kubernetes service. -type ServicePortForwarder struct { - cfg *rest.Config - cl kubernetes.Interface - - ready chan struct{} - localPort uint16 - - serviceName string - serviceNamespace string - port intstr.IntOrString -} - -// NewServicePortForwarder creates a new ServicePortForwarder. -func NewServicePortForwarder(cfg *rest.Config, service types.NamespacedName, port intstr.IntOrString) (*ServicePortForwarder, error) { - cl, err := kubernetes.NewForConfig(cfg) - if err != nil { - return nil, err - } - - return &ServicePortForwarder{ - cfg: cfg, - cl: cl, - ready: make(chan struct{}), - - serviceName: service.Name, - serviceNamespace: service.Namespace, - port: port, - }, nil -} - -// Start starts the port-forward defined by the ServicePortForwarder and blocks until the provided context is closed. -// When the provided context is closed, the forwarded port is also closed. This function opens a random local port, -// which can be discovered using the LocalPort method. -func (pf *ServicePortForwarder) Start(ctx context.Context) error { - eg, ctx := errgroup.WithContext(ctx) - - var subset corev1.EndpointSubset - if err := wait.PollImmediateUntil(time.Second*1, func() (bool, error) { - endpoints, err := pf.cl.CoreV1().Endpoints(pf.serviceNamespace).Get(ctx, pf.serviceName, metav1.GetOptions{}) - if err != nil { - return false, err - } - - if len(endpoints.Subsets) == 0 || len(endpoints.Subsets[0].Addresses) == 0 { - return false, nil - } - subset = endpoints.Subsets[0] - return true, nil - }, ctx.Done()); err != nil { - if errors.Is(err, ctx.Err()) { - return fmt.Errorf("could not find available endpoint for %s service", pf.serviceName) - } - return err - } - - podName := subset.Addresses[0].TargetRef.Name - port := pf.port.IntVal - if port == 0 { - for _, p := range subset.Ports { - if p.Name == pf.port.StrVal { - port = p.Port - break - } - } - } - if port == 0 { - return fmt.Errorf("could not find port %q for service %q", pf.port.String(), pf.serviceName) - } - - path := fmt.Sprintf("/api/v1/namespaces/%s/pods/%s/portforward", pf.serviceNamespace, podName) - host := strings.TrimLeft(pf.cfg.Host, "htps:/") - serverURL := url.URL{Scheme: "https", Path: path, Host: host} - roundTripper, upgrader, err := spdy.RoundTripperFor(pf.cfg) - if err != nil { - return err - } - - dialer := spdy.NewDialer(upgrader, &http.Client{Transport: roundTripper}, http.MethodPost, &serverURL) - stopChan, readyChan := make(chan struct{}, 1), make(chan struct{}, 1) - out, errOut := new(bytes.Buffer), new(bytes.Buffer) - - forwarder, err := portforward.New(dialer, []string{fmt.Sprintf("0:%d", port)}, stopChan, readyChan, out, errOut) - if err != nil { - return err - } - - eg.Go(func() error { - if err = forwarder.ForwardPorts(); err != nil { // Locks until stopChan is closed. - return err - } - return nil - }) - eg.Go(func() error { - <-ctx.Done() - close(stopChan) - return nil - }) - - // readyChan will be closed when the forwarded ports are ready. - <-readyChan - if errOut.String() != "" { - return fmt.Errorf(errOut.String()) - } - - forwardedPorts, err := forwarder.GetPorts() - if err != nil { - return err - } - pf.localPort = forwardedPorts[0].Local - close(pf.ready) - return eg.Wait() -} - -// LocalPort returns the local port on which the port forward is listening. It automatically -// waits until the port forward is configured, so there is no need for callers to coordinate -// calls between Start and LocalPort (other than that Start must be called at some point for -// a local port to eventually become ready). If the provided context is closed prior to the -// local port becoming ready, LocalPort returns the context's error. -func (pf *ServicePortForwarder) LocalPort(ctx context.Context) (uint16, error) { - select { - case <-ctx.Done(): - return 0, ctx.Err() - case <-pf.ready: - return pf.localPort, nil - } -} diff --git a/internal/rukpakctl/run.go b/internal/rukpakctl/run.go deleted file mode 100644 index 5eac997b..00000000 --- a/internal/rukpakctl/run.go +++ /dev/null @@ -1,117 +0,0 @@ -package rukpakctl - -import ( - "context" - "fmt" - "hash/fnv" - "io/fs" - - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" - - rukpakv1alpha2 "github.com/operator-framework/rukpak/api/v1alpha2" - "github.com/operator-framework/rukpak/internal/provisioner/plain" - "github.com/operator-framework/rukpak/internal/util" -) - -// Run implements rukpakctl's `run` subcommand -type Run struct { - Config *rest.Config - - SystemNamespace string - UploadServiceName string - CASecretName string -} - -// RunOptions define extra options used for Run. -type RunOptions struct { - BundleDeploymentProvisionerClassName string - Log func(format string, v ...interface{}) -} - -// Run runs the provided bundle using a bundle deployment with the given bundleDeploymentName. -// The RunOptions enable further configuration, such as the provisioner class names to use and -// an optional logger. By default, the plain provisioner for the bundle and bundle deployment. -// Run returns a boolean value indicating whether the bundle deployment was created or modified -// and an error value if any error occurs. -func (r *Run) Run(ctx context.Context, bundleDeploymentName string, bundle fs.FS, opts RunOptions) (bool, error) { - if opts.BundleDeploymentProvisionerClassName == "" { - opts.BundleDeploymentProvisionerClassName = plain.ProvisionerID - } - if opts.Log == nil { - opts.Log = func(_ string, _ ...interface{}) {} - } - - sch := scheme.Scheme - if err := rukpakv1alpha2.AddToScheme(sch); err != nil { - return false, err - } - cl, err := client.New(r.Config, client.Options{Scheme: sch}) - if err != nil { - return false, err - } - - digest := fnv.New64a() - if err := util.FSToTarGZ(digest, bundle); err != nil { - return false, err - } - - bundleDeploymentLabels := map[string]string{ - "app": bundleDeploymentName, - "bundleDigest": fmt.Sprintf("%x", digest.Sum(nil)), - } - - bd := buildBundleDeployment(bundleDeploymentName, bundleDeploymentLabels, opts.BundleDeploymentProvisionerClassName) - if err := cl.Patch(ctx, bd, client.Apply, client.ForceOwnership, client.FieldOwner("rukpakctl")); err != nil { - return false, fmt.Errorf("apply bundle deployment: %v", err) - } - opts.Log("bundledeployment.core.rukpak.io %q applied\n", bundleDeploymentName) - - rukpakCA, err := GetClusterCA(ctx, cl, types.NamespacedName{Namespace: r.SystemNamespace, Name: r.CASecretName}) - if err != nil { - return false, err - } - - bu := BundleUploader{ - UploadServiceNamespace: r.SystemNamespace, - UploadServiceName: r.UploadServiceName, - Cfg: r.Config, - RootCAs: rukpakCA, - } - modified, err := bu.Upload(ctx, bundleDeploymentName, bundle) - if err != nil { - return false, fmt.Errorf("failed to upload bundle: %v", err) - } - if !modified { - opts.Log("bundle %q is already up-to-date\n", bundleDeploymentName) - } else { - opts.Log("successfully uploaded bundle content for %q\n", bundleDeploymentName) - } - return modified, nil -} - -func buildBundleDeployment(bdName string, bundleDeploymentLabels map[string]string, biPCN string) *unstructured.Unstructured { - // We use unstructured here to avoid problems of serializing default values when sending patches to the apiserver. - // If you use a typed object, any default values from that struct get serialized into the JSON patch, which could - // cause unrelated fields to be patched back to the default value even though that isn't the intention. Using an - // unstructured ensures that the patch contains only what is specified. Using unstructured like this is basically - // identical to "kubectl apply -f" - return &unstructured.Unstructured{Object: map[string]interface{}{ - "apiVersion": rukpakv1alpha2.GroupVersion.String(), - "kind": rukpakv1alpha2.BundleDeploymentKind, - "metadata": map[string]interface{}{ - "name": bdName, - "labels": bundleDeploymentLabels, - }, - "spec": map[string]interface{}{ - "provisionerClassName": biPCN, - "source": map[string]interface{}{ - "type": rukpakv1alpha2.SourceTypeUpload, - "upload": &rukpakv1alpha2.UploadSource{}, - }, - }, - }} -} diff --git a/internal/rukpakctl/upload.go b/internal/rukpakctl/upload.go deleted file mode 100644 index c4759f92..00000000 --- a/internal/rukpakctl/upload.go +++ /dev/null @@ -1,137 +0,0 @@ -package rukpakctl - -import ( - "context" - "crypto/x509" - "errors" - "fmt" - "io" - "io/fs" - "net/http" - "time" - - "golang.org/x/sync/errgroup" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/client-go/rest" - - "github.com/operator-framework/rukpak/internal/util" -) - -// BundleUploader uploads bundle filesystems to rukpak's upload service. -type BundleUploader struct { - UploadServiceName string - UploadServiceNamespace string - - Cfg *rest.Config - RootCAs *x509.CertPool -} - -// Upload uploads the contents of a bundle to the bundle upload service configured on the -// BundleUploader. -// -// To perform the upload, Upload utilizes a Kubernetes API port-forward to forward a port from -// the uploader service to the local machine. Once the port has been forwarded, Upload -// uploads the bundleFS as the content for the bundle named by the provided bundleName. -// -// Upload returns a boolean value indicating if the bundle content was modified on the server and -// an error value that will convey any errors that occurred during the upload. -// -// Uploads of content that is identical to the existing bundle's content will not result in an error, -// which means this function is idempotent. Running this function multiple times with the same input -// does not result in any change to the cluster state after the initial upload. -func (bu *BundleUploader) Upload(ctx context.Context, bundleName string, bundleFS fs.FS) (bool, error) { - pf, err := NewServicePortForwarder(bu.Cfg, types.NamespacedName{Namespace: bu.UploadServiceNamespace, Name: bu.UploadServiceName}, intstr.FromString("https")) - if err != nil { - return false, err - } - - // cancel is called by the upload goroutine before it returns, thus ensuring - // the port-forwarding goroutine exits, which allows the errgroup.Wait() call - // to unblock. - ctx, cancel := context.WithCancel(ctx) - - eg, ctx := errgroup.WithContext(ctx) - eg.Go(func() error { - return pf.Start(ctx) - }) - - // Create a pipe to conserve memory. We don't need to buffer the entire bundle - // tar.gz prior to sending it. To use a pipe, we start a writer goroutine and - // a reader goroutine such that the reader reads as soon as the writer writes. - // The reader continues reading until it receives io.EOF, so we need to close - // writer (triggering the io.EOF) as soon as we finish writing. We close the - // writer with `bundleWriter.CloseWithError` so that an error encountered - // writing the FS to a tar.gz stream can be processed by the reader. - bundleReader, bundleWriter := io.Pipe() - eg.Go(func() error { - return bundleWriter.CloseWithError(util.FSToTarGZ(bundleWriter, bundleFS)) - }) - - var bundleModified bool - eg.Go(func() error { - defer func() { - cancel() - bundleWriter.Close() - }() - - // get the local port. this will wait until the port forwarder is ready. - localPort, err := pf.LocalPort(ctx) - if err != nil { - return err - } - - req, err := http.NewRequestWithContext(ctx, http.MethodPut, proxyBundleURL(bundleName, localPort), bundleReader) - if err != nil { - return err - } - - transport := http.DefaultTransport.(*http.Transport).Clone() - transport.TLSClientConfig, err = rest.TLSConfigFor(bu.Cfg) - if err != nil { - return err - } - if bu.RootCAs != nil { - transport.TLSClientConfig.RootCAs = bu.RootCAs - } - if bu.Cfg.BearerToken != "" { - req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", bu.Cfg.BearerToken)) - } - - httpClient := http.Client{ - Transport: transport, - Timeout: 10 * time.Second, - } - - resp, err := httpClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - switch resp.StatusCode { - case http.StatusCreated: - bundleModified = true - case http.StatusNoContent: - bundleModified = false - default: - body, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - if len(string(body)) > 0 { - return errors.New(string(body)) - } - return fmt.Errorf("unexpected response %q", resp.Status) - } - return nil - }) - if err := eg.Wait(); err != nil && !errors.Is(err, context.Canceled) { - return false, err - } - return bundleModified, nil -} - -func proxyBundleURL(bundleName string, port uint16) string { - return fmt.Sprintf("https://localhost:%d/uploads/%s", port, fmt.Sprintf("%s.tgz", bundleName)) -} diff --git a/internal/source/unpacker.go b/internal/source/unpacker.go index 9a07d982..dcddaee9 100644 --- a/internal/source/unpacker.go +++ b/internal/source/unpacker.go @@ -7,7 +7,6 @@ import ( "fmt" "io/fs" "net/http" - "time" "k8s.io/client-go/kubernetes" "sigs.k8s.io/controller-runtime/pkg/cluster" @@ -15,11 +14,6 @@ import ( rukpakv1alpha2 "github.com/operator-framework/rukpak/api/v1alpha2" ) -const ( - // uploadClientTimeout is the timeout to be used with http connections to upload manager. - uploadClientTimeout = time.Second * 10 -) - // Unpacker unpacks bundle content, either synchronously or asynchronously and // returns a Result, which conveys information about the progress of unpacking // the bundle content. @@ -101,7 +95,7 @@ func (s *unpacker) Unpack(ctx context.Context, bundle *rukpakv1alpha2.BundleDepl // source types. // // TODO: refactor NewDefaultUnpacker due to growing parameter list -func NewDefaultUnpacker(systemNsCluster cluster.Cluster, namespace, unpackImage string, baseUploadManagerURL string, rootCAs *x509.CertPool) (Unpacker, error) { +func NewDefaultUnpacker(systemNsCluster cluster.Cluster, namespace, unpackImage string, rootCAs *x509.CertPool) (Unpacker, error) { cfg := systemNsCluster.GetConfig() kubeClient, err := kubernetes.NewForConfig(cfg) if err != nil { @@ -129,11 +123,6 @@ func NewDefaultUnpacker(systemNsCluster cluster.Cluster, namespace, unpackImage Reader: systemNsCluster.GetClient(), ConfigMapNamespace: namespace, }, - rukpakv1alpha2.SourceTypeUpload: &Upload{ - baseDownloadURL: baseUploadManagerURL, - bearerToken: systemNsCluster.GetConfig().BearerToken, - client: http.Client{Timeout: uploadClientTimeout, Transport: httpTransport}, - }, rukpakv1alpha2.SourceTypeHTTP: &HTTP{ Reader: systemNsCluster.GetClient(), SecretNamespace: namespace, diff --git a/internal/source/upload.go b/internal/source/upload.go deleted file mode 100644 index c7abfb08..00000000 --- a/internal/source/upload.go +++ /dev/null @@ -1,76 +0,0 @@ -package source - -import ( - "compress/gzip" - "context" - "fmt" - "net/http" - - "github.com/nlepage/go-tarfs" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - rukpakv1alpha2 "github.com/operator-framework/rukpak/api/v1alpha2" -) - -// Upload is a bundle source that sources bundles from the rukpak upload service. -type Upload struct { - baseDownloadURL string - bearerToken string - client http.Client -} - -// Unpack unpacks an uploaded bundle by requesting the bundle contents from a web server hosted -// by rukpak's upload service. -func (b *Upload) Unpack(ctx context.Context, bundle *rukpakv1alpha2.BundleDeployment) (*Result, error) { - if bundle.Spec.Source.Type != rukpakv1alpha2.SourceTypeUpload { - return nil, fmt.Errorf("cannot unpack source type %q with %q unpacker", bundle.Spec.Source.Type, rukpakv1alpha2.SourceTypeUpload) - } - - // Proceed with fetching contents from a web server, only if the bundle upload was successful. - // If upload is a failure, we have "TypeUploadState" explicitly set to false. - if !isBundleContentUploaded(bundle) { - return &Result{State: StatePending, Message: "pending unpacking contents from uploaded bundle"}, nil - } - - url := fmt.Sprintf("%s/uploads/%s.tgz", b.baseDownloadURL, bundle.Name) - action := fmt.Sprintf("%s %s", http.MethodGet, url) - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) - if err != nil { - return nil, fmt.Errorf("create http request %q for bundle content: %v", action, err) - } - req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", b.bearerToken)) - resp, err := b.client.Do(req) - if err != nil { - return nil, fmt.Errorf("%s: http request for bundle content failed: %v", action, err) - } - defer resp.Body.Close() - if resp.StatusCode == http.StatusNotFound { - return &Result{State: StatePending, Message: "waiting for bundle to be uploaded"}, nil - } - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("%s: unexpected status %q", action, resp.Status) - } - gzipReader, err := gzip.NewReader(resp.Body) - if err != nil { - return nil, fmt.Errorf("read response as gzip: %v", err) - } - bundleFS, err := tarfs.New(gzipReader) - if err != nil { - return nil, fmt.Errorf("untar bundle contents from response: %v", err) - } - - message := generateMessage("upload") - - return &Result{Bundle: bundleFS, ResolvedSource: bundle.Spec.Source.DeepCopy(), State: StateUnpacked, Message: message}, nil -} - -func isBundleContentUploaded(bd *rukpakv1alpha2.BundleDeployment) bool { - if bd == nil { - return false - } - - condition := meta.FindStatusCondition(bd.Status.Conditions, rukpakv1alpha2.TypeUploadStatus) - return condition != nil && condition.Status == metav1.ConditionTrue -} diff --git a/internal/storage/http_test.go b/internal/storage/http_test.go index 26c41d2b..ae5ae7a2 100644 --- a/internal/storage/http_test.go +++ b/internal/storage/http_test.go @@ -24,14 +24,14 @@ import ( var _ = Describe("HTTP", func() { var ( ctx context.Context - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment testFS fs.FS localStore *LocalDirectory server *httptest.Server ) BeforeEach(func() { ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ObjectMeta: metav1.ObjectMeta{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ObjectMeta: metav1.ObjectMeta{ Name: util.GenerateBundleName("testbundle", rand.String(8)), }} @@ -44,16 +44,16 @@ var _ = Describe("HTTP", func() { // Setup the local store and store the generated FS. localStore = &LocalDirectory{RootDirectory: testDir} - Expect(localStore.Store(ctx, bundledeployment, testFS)).To(Succeed()) + Expect(localStore.Store(ctx, bundleDeployment, testFS)).To(Succeed()) // Create and start the server server = newTLSServer(localStore, "abc123") // Populate the content URL, this has to happen after the server has // started so that we know the server's base URL. - contentURL, err := localStore.URLFor(ctx, bundledeployment) + contentURL, err := localStore.URLFor(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) - bundledeployment.Status.ContentURL = contentURL + bundleDeployment.Status.ContentURL = contentURL }) AfterEach(func() { server.Close() @@ -67,7 +67,7 @@ var _ = Describe("HTTP", func() { It("should get a certificate verification error", func() { store := NewHTTP(opts...) - loadedTestFS, err := store.Load(ctx, bundledeployment) + loadedTestFS, err := store.Load(ctx, bundleDeployment) Expect(loadedTestFS).To(BeNil()) Expect(err).To(MatchError(Or( ContainSubstring("certificate is not trusted"), // works on darwin @@ -87,18 +87,18 @@ var _ = Describe("HTTP", func() { Context("with existing bundle", func() { It("should succeed", func() { store := NewHTTP(opts...) - loadedTestFS, err := store.Load(ctx, bundledeployment) + loadedTestFS, err := store.Load(ctx, bundleDeployment) Expect(fsEqual(testFS, loadedTestFS)).To(BeTrue()) Expect(err).ToNot(HaveOccurred()) }) }) Context("with non-existing bundle", func() { BeforeEach(func() { - bundledeployment.Status.ContentURL += "foobar" + bundleDeployment.Status.ContentURL += "foobar" }) It("should get 404 not found error", func() { store := NewHTTP(opts...) - loadedTestFS, err := store.Load(ctx, bundledeployment) + loadedTestFS, err := store.Load(ctx, bundleDeployment) Expect(loadedTestFS).To(BeNil()) Expect(err).To(MatchError(ContainSubstring("404 Not Found"))) }) @@ -110,7 +110,7 @@ var _ = Describe("HTTP", func() { }) It("should get a 401 Unauthorized error", func() { store := NewHTTP(opts...) - loadedTestFS, err := store.Load(ctx, bundledeployment) + loadedTestFS, err := store.Load(ctx, bundleDeployment) Expect(loadedTestFS).To(BeNil()) Expect(err).To(MatchError(ContainSubstring("401 Unauthorized"))) }) @@ -130,18 +130,18 @@ var _ = Describe("HTTP", func() { Context("with existing bundle", func() { It("should succeed", func() { store := NewHTTP(opts...) - loadedTestFS, err := store.Load(ctx, bundledeployment) + loadedTestFS, err := store.Load(ctx, bundleDeployment) Expect(fsEqual(testFS, loadedTestFS)).To(BeTrue()) Expect(err).ToNot(HaveOccurred()) }) }) Context("with non-existing bundle", func() { BeforeEach(func() { - bundledeployment.Status.ContentURL += "foobar" + bundleDeployment.Status.ContentURL += "foobar" }) It("should get 404 not found error", func() { store := NewHTTP(opts...) - loadedTestFS, err := store.Load(ctx, bundledeployment) + loadedTestFS, err := store.Load(ctx, bundleDeployment) Expect(loadedTestFS).To(BeNil()) Expect(err).To(MatchError(ContainSubstring("404 Not Found"))) }) @@ -153,7 +153,7 @@ var _ = Describe("HTTP", func() { }) It("should get a 401 Unauthorized error", func() { store := NewHTTP(opts...) - loadedTestFS, err := store.Load(ctx, bundledeployment) + loadedTestFS, err := store.Load(ctx, bundleDeployment) Expect(loadedTestFS).To(BeNil()) Expect(err).To(MatchError(ContainSubstring("401 Unauthorized"))) }) diff --git a/internal/storage/localdir_test.go b/internal/storage/localdir_test.go index eec00f0b..200fb70a 100644 --- a/internal/storage/localdir_test.go +++ b/internal/storage/localdir_test.go @@ -39,7 +39,7 @@ var _ = Describe("LocalDirectory", func() { store = LocalDirectory{RootDirectory: GinkgoT().TempDir()} testFS = generateFS() }) - When("a bundledeployment is not stored", func() { + When("a bundleDeployment is not stored", func() { Describe("Store", func() { It("should store a bundle FS", func() { Expect(store.Store(ctx, owner, testFS)).To(Succeed()) @@ -61,18 +61,18 @@ var _ = Describe("LocalDirectory", func() { }) }) }) - When("a bundledeployment is stored", func() { + When("a bundleDeployment is stored", func() { BeforeEach(func() { Expect(store.Store(ctx, owner, testFS)).To(Succeed()) }) Describe("Store", func() { - It("should re-store a bundledeployment FS", func() { + It("should re-store a bundleDeployment FS", func() { Expect(store.Store(ctx, owner, testFS)).To(Succeed()) }) }) Describe("Load", func() { - It("should load the bundledeployment", func() { + It("should load the bundleDeployment", func() { loadedTestFS, err := store.Load(ctx, owner) Expect(err).NotTo(HaveOccurred()) Expect(fsEqual(testFS, loadedTestFS)).To(BeTrue()) @@ -80,7 +80,7 @@ var _ = Describe("LocalDirectory", func() { }) Describe("Delete", func() { - It("should delete the bundledeployment", func() { + It("should delete the bundleDeployment", func() { Expect(store.Delete(ctx, owner)).To(Succeed()) _, err := os.Stat(filepath.Join(store.RootDirectory, fmt.Sprintf("%s.tgz", owner.GetName()))) Expect(err).To(WithTransform(func(err error) bool { return errors.Is(err, os.ErrNotExist) }, BeTrue())) diff --git a/internal/uploadmgr/gc.go b/internal/uploadmgr/gc.go deleted file mode 100644 index d6872cc8..00000000 --- a/internal/uploadmgr/gc.go +++ /dev/null @@ -1,106 +0,0 @@ -package uploadmgr - -import ( - "context" - "fmt" - "os" - "path/filepath" - "time" - - "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/util/sets" - toolscache "k8s.io/client-go/tools/cache" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/cache" - "sigs.k8s.io/controller-runtime/pkg/manager" - - rukpakv1alpha2 "github.com/operator-framework/rukpak/api/v1alpha2" -) - -type bundleGC struct { - storageDir string - storageSyncInterval time.Duration - cache cache.Cache - log logr.Logger -} - -// NewBundleGC returns a Runnable for controller-runtime that automatically garbage-collects -// bundle uploads as those bundles are deleted. In case deletion events are missed, the -// garbage collector also periodically deletes files in the storageDir that are not -// associated with an active uploaded bundle. -func NewBundleGC(cache cache.Cache, storageDir string, storageSyncInterval time.Duration) manager.Runnable { - return &bundleGC{storageDir: storageDir, storageSyncInterval: storageSyncInterval, cache: cache, log: ctrl.Log.WithName("gc")} -} - -// Start implemente the controller-runtime Runnable interface. -// It blocks until the context is closed. -func (gc *bundleGC) Start(ctx context.Context) error { - bundledeploymentInformer, err := gc.cache.GetInformer(ctx, &rukpakv1alpha2.BundleDeployment{}) - if err != nil { - return err - } - // Ignore the return value - _, err = bundledeploymentInformer.AddEventHandler(toolscache.ResourceEventHandlerFuncs{ - DeleteFunc: func(obj interface{}) { - bundleDeployment := obj.(*rukpakv1alpha2.BundleDeployment) - if bundleDeployment.Spec.Source.Type != rukpakv1alpha2.SourceTypeUpload { - return - } - filename := bundlePath(gc.storageDir, bundleDeployment.Name) - gc.log.Info("removing file", "path", filename) - if err := os.RemoveAll(filename); err != nil { - gc.log.Error(err, "failed to remove file", "path", filename) - } - }, - }) - if err != nil { - return err - } - - // Wait for the cache to sync to ensure that our bundle List calls - // in the below loop see a full view of the bundles that exist in - // the cluster. - if ok := gc.cache.WaitForCacheSync(ctx); !ok { - if ctx.Err() == nil { - return fmt.Errorf("cache did not sync") - } - return fmt.Errorf("cache did not sync: %v", ctx.Err()) - } - - ticker := time.NewTicker(gc.storageSyncInterval) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return nil - case <-ticker.C: - storageDirEntries, err := os.ReadDir(gc.storageDir) - if err != nil { - gc.log.Error(err, "failed to read local bundle storage directory") - continue - } - existingFiles := sets.NewString() - for _, e := range storageDirEntries { - existingFiles.Insert(e.Name()) - } - bundledeployments := &rukpakv1alpha2.BundleDeploymentList{} - if err := gc.cache.List(ctx, bundledeployments); err != nil { - gc.log.Error(err, "failed to list bundles from cache", err) - continue - } - for _, bundle := range bundledeployments.Items { - if bundle.Spec.Source.Type != rukpakv1alpha2.SourceTypeUpload { - continue - } - existingFiles.Delete(filepath.Base(bundlePath(gc.storageDir, bundle.Name))) - } - for _, staleFile := range existingFiles.List() { - filename := filepath.Join(gc.storageDir, staleFile) - gc.log.Info("removing file", "path", filename) - if err := os.RemoveAll(filename); err != nil { - gc.log.Error(err, "failed to remove file", "path", filename) - } - } - } - } -} diff --git a/internal/uploadmgr/handler.go b/internal/uploadmgr/handler.go deleted file mode 100644 index f0eff08e..00000000 --- a/internal/uploadmgr/handler.go +++ /dev/null @@ -1,148 +0,0 @@ -package uploadmgr - -import ( - "bytes" - "errors" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - - "github.com/gorilla/mux" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - utilerrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/client-go/util/retry" - "sigs.k8s.io/controller-runtime/pkg/client" - - rukpakv1alpha2 "github.com/operator-framework/rukpak/api/v1alpha2" - "github.com/operator-framework/rukpak/internal/util" -) - -const DefaultBundleCacheDir = "/var/cache/uploads" - -//+kubebuilder:rbac:groups=core.rukpak.io,resources=bundledeployments,verbs=list;watch -//+kubebuilder:rbac:groups=core.rukpak.io,resources=bundledeployments/status,verbs=update;patch -//+kubebuilder:rbac:groups=authentication.k8s.io,resources=tokenreviews,verbs=create -//+kubebuilder:rbac:groups=authorization.k8s.io,resources=subjectaccessreviews,verbs=create - -func NewUploadHandler(cl client.Client, storageDir string) http.Handler { - r := mux.NewRouter() - r.Methods(http.MethodGet).Path("/uploads/{bundleName}.tgz").Handler(http.StripPrefix("/uploads/", http.FileServer(http.FS(&util.FilesOnlyFilesystem{FS: os.DirFS(storageDir)})))) - r.Methods(http.MethodPut).Path("/uploads/{bundleName}.tgz").Handler(newPutHandler(cl, storageDir)) - return r -} - -func newPutHandler(cl client.Client, storageDir string) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - bundleName := mux.Vars(r)["bundleName"] - - bundledeployment := &rukpakv1alpha2.BundleDeployment{} - if err := cl.Get(r.Context(), types.NamespacedName{Name: bundleName}, bundledeployment); err != nil { - http.Error(w, err.Error(), int(getCode(err))) - return - } - if bundledeployment.Spec.Source.Type != rukpakv1alpha2.SourceTypeUpload { - http.Error(w, fmt.Sprintf("bundle source type is %q; expected %q", bundledeployment.Spec.Source.Type, rukpakv1alpha2.SourceTypeUpload), http.StatusConflict) - return - } - - uploadBundleData, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, fmt.Sprintf("read request body: %v", err), http.StatusInternalServerError) - return - } - bundleFilePath := bundlePath(storageDir, bundleName) - if existingData, err := os.ReadFile(bundleFilePath); err == nil { - if bytes.Equal(uploadBundleData, existingData) { - w.WriteHeader(http.StatusNoContent) - return - } - } - - if isBundleDeploymentUnpacked(bundledeployment) { - http.Error(w, "bundle has already been unpacked, cannot change content of existing bundle", http.StatusConflict) - return - } - - bundleFile, err := os.Create(bundleFilePath) - if err != nil { - http.Error(w, fmt.Sprintf("failed to store bundle data: %v", err), http.StatusInternalServerError) - return - } - defer bundleFile.Close() - - if _, err := bundleFile.Write(uploadBundleData); err != nil { - http.Error(w, fmt.Sprintf("failed to store bundle data: %v", err), http.StatusInternalServerError) - return - } - - if err := retry.RetryOnConflict(retry.DefaultRetry, func() error { - if err := cl.Get(r.Context(), types.NamespacedName{Name: bundleName}, bundledeployment); err != nil { - return err - } - if isBundleDeploymentUnpacked(bundledeployment) { - return nil - } - - meta.SetStatusCondition(&bundledeployment.Status.Conditions, metav1.Condition{ - Type: rukpakv1alpha2.TypeUnpacked, - Status: metav1.ConditionFalse, - Reason: rukpakv1alpha2.ReasonUnpackPending, - Message: "received bundle upload, waiting for provisioner to unpack it.", - }) - return cl.Status().Update(r.Context(), bundledeployment) - }); err != nil { - errs := []error{} - errs = append(errs, err) - - meta.SetStatusCondition(&bundledeployment.Status.Conditions, metav1.Condition{ - Type: rukpakv1alpha2.TypeUploadStatus, - Status: metav1.ConditionFalse, - Reason: rukpakv1alpha2.ReasonBundleLoadFailed, - Message: err.Error(), - }) - if statusUpdateErr := cl.Status().Update(r.Context(), bundledeployment); statusUpdateErr != nil { - errs = append(errs, statusUpdateErr) - } - http.Error(w, utilerrors.NewAggregate(errs).Error(), int(getCode(err))) - return - } - meta.SetStatusCondition(&bundledeployment.Status.Conditions, metav1.Condition{ - Type: rukpakv1alpha2.TypeUploadStatus, - Status: metav1.ConditionTrue, - Reason: rukpakv1alpha2.ReasonUploadSuccessful, - Message: "successfully uploaded bundle contents.", - }) - if statusUpdateErr := cl.Status().Update(r.Context(), bundledeployment); statusUpdateErr != nil { - // Though this would not be the http error returned from uploading, it - // is required to error, as BundleDeployment reconciler is waiting for - // was a successful upload status. - http.Error(w, statusUpdateErr.Error(), int(getCode(statusUpdateErr))) - } - w.WriteHeader(http.StatusCreated) - }) -} - -func isBundleDeploymentUnpacked(bd *rukpakv1alpha2.BundleDeployment) bool { - if bd == nil { - return false - } - - condition := meta.FindStatusCondition(bd.Status.Conditions, rukpakv1alpha2.TypeUnpacked) - return condition != nil && condition.Status == metav1.ConditionTrue -} - -func getCode(err error) int32 { - if status := apierrors.APIStatus(nil); errors.As(err, &status) { - return status.Status().Code - } - return http.StatusInternalServerError -} - -func bundlePath(baseDir, bundleName string) string { - return filepath.Join(baseDir, fmt.Sprintf("%s.tgz", bundleName)) -} diff --git a/internal/util/adopt.go b/internal/util/adopt.go deleted file mode 100644 index 5e2588cc..00000000 --- a/internal/util/adopt.go +++ /dev/null @@ -1,42 +0,0 @@ -package util - -import ( - "sigs.k8s.io/controller-runtime/pkg/client" - - "github.com/operator-framework/rukpak/api/v1alpha2" -) - -// AdoptObject sets metadata on an object to associate that object with a bundle -// deployment, such that it could be adopted by that bundle deployment. -// -// The systemNamespace is the namespace in which the provisioner managing the objects -// is running. And the bundleDeployment name is the name of the bundle deployment that -// should adopt the provided object. -// -// This function does _not_ apply the changes to a cluster, so callers must apply the -// updates themselves. -// -// NOTE: This function is designed specifically for the current helm-based -// implementation of the plain provisioner, and will track the plain provisioner's -// implementation. Should the plain provisioner change it's underlying mechanism -// for associating bundle deployments to managed objects, this implementation will -// also change. -func AdoptObject(obj client.Object, systemNamespace, bundleDeploymentName string) { - annotations := obj.GetAnnotations() - if annotations == nil { - annotations = map[string]string{} - } - annotations["meta.helm.sh/release-name"] = bundleDeploymentName - annotations["meta.helm.sh/release-namespace"] = systemNamespace - obj.SetAnnotations(annotations) - - labels := obj.GetLabels() - if labels == nil { - labels = map[string]string{} - } - - labels["app.kubernetes.io/managed-by"] = "Helm" - labels[CoreOwnerKindKey] = v1alpha2.BundleDeploymentKind - labels[CoreOwnerNameKey] = bundleDeploymentName - obj.SetLabels(labels) -} diff --git a/internal/util/util.go b/internal/util/util.go index 8df0c2a2..7e0660f1 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -8,7 +8,6 @@ import ( "fmt" "io" "os" - "sort" "time" "github.com/go-logr/logr" @@ -140,20 +139,6 @@ func MapConfigMapToBundleDeploymentHandler(ctx context.Context, cl client.Client }) } -// GetBundlesForBundleDeploymentSelector is responsible for returning a list of -// Bundle resource that exist on cluster that match the label selector specified -// in the BD parameter's spec.Selector field. -func GetBundlesForBundleDeploymentSelector(ctx context.Context, c client.Client, bd *rukpakv1alpha2.BundleDeployment) (*rukpakv1alpha2.BundleDeploymentList, error) { - selector := NewBundleDeploymentLabelSelector(bd) - bundleDeploymentList := &rukpakv1alpha2.BundleDeploymentList{} - if err := c.List(ctx, bundleDeploymentList, &client.ListOptions{ - LabelSelector: selector, - }); err != nil { - return nil, fmt.Errorf("failed to list bundles using the %s selector: %v", selector.String(), err) - } - return bundleDeploymentList, nil -} - const ( // maxBundleNameLength must be aligned with the Bundle CRD metadata.name length validation, defined in: // /manifests/base/apis/crds/patches/bundle_validation.yaml @@ -177,14 +162,6 @@ func GenerateBundleName(bdName, hash string) string { return fmt.Sprintf("%s-%s", bdName, hash) } -// SortBundleDeploymentsByCreation sorts a BundleDeploymentList's items by it's -// metadata.CreationTimestamp value. -func SortBundleDeploymentsByCreation(bundles *rukpakv1alpha2.BundleDeploymentList) { - sort.Slice(bundles.Items, func(a, b int) bool { - return bundles.Items[a].CreationTimestamp.Before(&bundles.Items[b].CreationTimestamp) - }) -} - // PodNamespace checks whether the controller is running in a Pod vs. // being run locally by inspecting the namespace file that gets mounted // automatically for Pods at runtime. If that file doesn't exist, then diff --git a/internal/webhook/bundledeployment.go b/internal/webhook/bundledeployment.go index 85c71cfe..5ce775ba 100644 --- a/internal/webhook/bundledeployment.go +++ b/internal/webhook/bundledeployment.go @@ -43,8 +43,8 @@ type Bundle struct { // ValidateCreate implements webhook.Validator so a webhook will be registered for the type func (b *Bundle) ValidateCreate(ctx context.Context, obj runtime.Object) error { - bundledeployment := obj.(*rukpakv1alpha2.BundleDeployment) - return b.checkBundleDeploymentSource(ctx, bundledeployment) + bundleDeployment := obj.(*rukpakv1alpha2.BundleDeployment) + return b.checkBundleDeploymentSource(ctx, bundleDeployment) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type @@ -58,25 +58,25 @@ func (b *Bundle) ValidateDelete(_ context.Context, _ runtime.Object) error { return nil } -func (b *Bundle) checkBundleDeploymentSource(ctx context.Context, bundledeployment *rukpakv1alpha2.BundleDeployment) error { - switch typ := bundledeployment.Spec.Source.Type; typ { +func (b *Bundle) checkBundleDeploymentSource(ctx context.Context, bundleDeployment *rukpakv1alpha2.BundleDeployment) error { + switch typ := bundleDeployment.Spec.Source.Type; typ { case rukpakv1alpha2.SourceTypeImage: - if bundledeployment.Spec.Source.Image == nil { + if bundleDeployment.Spec.Source.Image == nil { return fmt.Errorf("bundledeployment.spec.source.image must be set for source type \"image\"") } case rukpakv1alpha2.SourceTypeGit: - if bundledeployment.Spec.Source.Git == nil { + if bundleDeployment.Spec.Source.Git == nil { return fmt.Errorf("bundledeployment.spec.source.git must be set for source type \"git\"") } - if strings.HasPrefix(filepath.Clean(bundledeployment.Spec.Source.Git.Directory), "../") { + if strings.HasPrefix(filepath.Clean(bundleDeployment.Spec.Source.Git.Directory), "../") { return fmt.Errorf(`bundledeployment.spec.source.git.directory begins with "../": directory must define path within the repository`) } case rukpakv1alpha2.SourceTypeConfigMaps: - if len(bundledeployment.Spec.Source.ConfigMaps) == 0 { + if len(bundleDeployment.Spec.Source.ConfigMaps) == 0 { return fmt.Errorf(`bundledeployment.spec.source.configmaps must be set for source type "configmaps"`) } errs := []error{} - for i, cmSource := range bundledeployment.Spec.Source.ConfigMaps { + for i, cmSource := range bundleDeployment.Spec.Source.ConfigMaps { if strings.HasPrefix(filepath.Clean(cmSource.Path), ".."+string(filepath.Separator)) { errs = append(errs, fmt.Errorf("bundledeployment.spec.source.configmaps[%d].path is invalid: %q is outside bundle root", i, cmSource.Path)) } diff --git a/internal/webhook/configmaps.go b/internal/webhook/configmaps.go index 11b534fb..0f1490ff 100644 --- a/internal/webhook/configmaps.go +++ b/internal/webhook/configmaps.go @@ -31,12 +31,12 @@ func (w *ConfigMap) ValidateCreate(ctx context.Context, obj runtime.Object) erro return nil } - bundledeploymentList := &rukpakv1alpha2.BundleDeploymentList{} - if err := w.Client.List(ctx, bundledeploymentList); err != nil { + bundleDeploymentList := &rukpakv1alpha2.BundleDeploymentList{} + if err := w.Client.List(ctx, bundleDeploymentList); err != nil { return err } bundleReferrers := []string{} - for _, bundle := range bundledeploymentList.Items { + for _, bundle := range bundleDeploymentList.Items { if bundle.Spec.Source.Type == rukpakv1alpha2.SourceTypeConfigMaps { for _, bundleConfigMapRef := range bundle.Spec.Source.ConfigMaps { if bundleConfigMapRef.ConfigMap.Name == cm.Name { diff --git a/manifests/base/apis/crds/core.rukpak.io_bundledeployments.yaml b/manifests/base/apis/crds/core.rukpak.io_bundledeployments.yaml index 146890c8..6a32f573 100644 --- a/manifests/base/apis/crds/core.rukpak.io_bundledeployments.yaml +++ b/manifests/base/apis/crds/core.rukpak.io_bundledeployments.yaml @@ -220,13 +220,6 @@ spec: type: description: Type defines the kind of Bundle content being sourced. type: string - upload: - description: Upload is a source that enables this Bundle's content - to be uploaded via Rukpak's bundle upload service. This source - type is primarily useful with bundle development workflows because - it enables bundle developers to inject a local bundle directly - into the cluster. - type: object required: - type type: object @@ -471,13 +464,6 @@ spec: type: description: Type defines the kind of Bundle content being sourced. type: string - upload: - description: Upload is a source that enables this Bundle's content - to be uploaded via Rukpak's bundle upload service. This source - type is primarily useful with bundle development workflows because - it enables bundle developers to inject a local bundle directly - into the cluster. - type: object required: - type type: object diff --git a/manifests/base/apis/crds/patches/bundledeployment_validation.yaml b/manifests/base/apis/crds/patches/bundledeployment_validation.yaml index fa544abd..c13216e2 100644 --- a/manifests/base/apis/crds/patches/bundledeployment_validation.yaml +++ b/manifests/base/apis/crds/patches/bundledeployment_validation.yaml @@ -16,8 +16,6 @@ - image - required: - configMaps - - required: - - upload - required: - http diff --git a/manifests/base/core/resources/cluster_role.yaml b/manifests/base/core/resources/cluster_role.yaml index 1084d43a..44eaf649 100644 --- a/manifests/base/core/resources/cluster_role.yaml +++ b/manifests/base/core/resources/cluster_role.yaml @@ -55,8 +55,6 @@ rules: - bundledeployments verbs: - list - - patch - - update - watch - apiGroups: - core.rukpak.io diff --git a/manifests/base/core/resources/deployment.yaml b/manifests/base/core/resources/deployment.yaml index 56315655..ed4665c5 100644 --- a/manifests/base/core/resources/deployment.yaml +++ b/manifests/base/core/resources/deployment.yaml @@ -55,9 +55,7 @@ spec: command: ["/core"] args: - "--unpack-image=quay.io/operator-framework/rukpak:devel" - - "--base-upload-manager-url=https://$(CORE_SERVICE_NAME).$(CORE_SERVICE_NAMESPACE).svc" - "--provisioner-storage-dir=/var/cache/bundles" - - "--upload-storage-dir=/var/cache/uploads" - "--http-bind-address=127.0.0.1:8080" - "--http-external-address=https://$(CORE_SERVICE_NAME).$(CORE_SERVICE_NAMESPACE).svc" - "--feature-gates=BundleDeploymentHealth=true" diff --git a/manifests/base/provisioners/helm/resources/cluster_role.yaml b/manifests/base/provisioners/helm/resources/cluster_role.yaml index e66e8948..c4595e19 100644 --- a/manifests/base/provisioners/helm/resources/cluster_role.yaml +++ b/manifests/base/provisioners/helm/resources/cluster_role.yaml @@ -55,8 +55,6 @@ rules: - bundledeployments verbs: - list - - patch - - update - watch - apiGroups: - core.rukpak.io diff --git a/manifests/base/provisioners/helm/resources/deployment.yaml b/manifests/base/provisioners/helm/resources/deployment.yaml index d4d71b02..a9075ed8 100644 --- a/manifests/base/provisioners/helm/resources/deployment.yaml +++ b/manifests/base/provisioners/helm/resources/deployment.yaml @@ -55,7 +55,6 @@ spec: command: ["/helm"] args: - "--unpack-image=quay.io/operator-framework/rukpak:devel" - - "--base-upload-manager-url=https://$(CORE_SERVICE_NAME).$(CORE_SERVICE_NAMESPACE).svc" - "--storage-dir=/var/cache/bundles" - "--http-bind-address=127.0.0.1:8080" - "--http-external-address=https://$(HELM_PROVISIONER_SERVICE_NAME).$(HELM_PROVISIONER_SERVICE_NAMESPACE).svc" diff --git a/test/e2e/api_validation_test.go b/test/e2e/api_validation_test.go index b6314ca4..48d707d6 100644 --- a/test/e2e/api_validation_test.go +++ b/test/e2e/api_validation_test.go @@ -18,14 +18,14 @@ import ( var _ = Describe("bundle api validation", func() { When("the bundle name is too long", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context err error ) BeforeEach(func() { ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: "olm-crds-too-long-name-for-the-bundle-1234567890-1234567890", }, @@ -39,11 +39,11 @@ var _ = Describe("bundle api validation", func() { }, }, } - err = c.Create(ctx, bundledeployment) + err = c.Create(ctx, bundleDeployment) }) AfterEach(func() { By("deleting the testing Bundle Deployment resource for failure case") - err = c.Delete(ctx, bundledeployment) + err = c.Delete(ctx, bundleDeployment) Expect(err).To(WithTransform(apierrors.IsNotFound, BeTrue())) }) It("should fail the long name of bundle deployment during creation", func() { @@ -52,7 +52,7 @@ var _ = Describe("bundle api validation", func() { }) When("the bundle deployment with multiple sources", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context err error ) @@ -60,7 +60,7 @@ var _ = Describe("bundle api validation", func() { By("creating the Bundle resource") ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: "bundlenamegit", }, @@ -81,11 +81,11 @@ var _ = Describe("bundle api validation", func() { }, }, } - err = c.Create(ctx, bundledeployment) + err = c.Create(ctx, bundleDeployment) }) AfterEach(func() { By("deleting the testing Bundle resource for failure case") - err = c.Delete(ctx, bundledeployment) + err = c.Delete(ctx, bundleDeployment) Expect(err).To(WithTransform(apierrors.IsNotFound, BeTrue())) }) It("should fail the bundle creation", func() { @@ -95,7 +95,7 @@ var _ = Describe("bundle api validation", func() { When("the bundle with no sources", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context err error ) @@ -103,7 +103,7 @@ var _ = Describe("bundle api validation", func() { By("creating the Bundle resource") ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: "bundlenamegit", }, @@ -114,11 +114,11 @@ var _ = Describe("bundle api validation", func() { }, }, } - err = c.Create(ctx, bundledeployment) + err = c.Create(ctx, bundleDeployment) }) AfterEach(func() { By("deleting the testing Bundle resource for failure case") - err = c.Delete(ctx, bundledeployment) + err = c.Delete(ctx, bundleDeployment) Expect(err).To(WithTransform(apierrors.IsNotFound, BeTrue())) }) It("should fail the bundle creation", func() { @@ -128,7 +128,7 @@ var _ = Describe("bundle api validation", func() { When("the bundle source type is git and more than 1 refs are set", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context err error ) @@ -136,7 +136,7 @@ var _ = Describe("bundle api validation", func() { By("creating the Bundle resource") ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: "bundlenamemorerefs", }, @@ -154,11 +154,11 @@ var _ = Describe("bundle api validation", func() { }, }, } - err = c.Create(ctx, bundledeployment) + err = c.Create(ctx, bundleDeployment) }) AfterEach(func() { By("deleting the testing Bundle resource for failure case") - err = c.Delete(ctx, bundledeployment) + err = c.Delete(ctx, bundleDeployment) Expect(err).To(WithTransform(apierrors.IsNotFound, BeTrue())) }) It("should fail the bundle creation", func() { @@ -168,7 +168,7 @@ var _ = Describe("bundle api validation", func() { When("the bundle source type is git and no refs are set", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context err error ) @@ -176,7 +176,7 @@ var _ = Describe("bundle api validation", func() { By("creating the Bundle resource") ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: "bundlenamemorerefs", }, @@ -191,11 +191,11 @@ var _ = Describe("bundle api validation", func() { }, }, } - err = c.Create(ctx, bundledeployment) + err = c.Create(ctx, bundleDeployment) }) AfterEach(func() { By("deleting the testing Bundle resource for failure case") - err = c.Delete(ctx, bundledeployment) + err = c.Delete(ctx, bundleDeployment) Expect(err).To(WithTransform(apierrors.IsNotFound, BeTrue())) }) It("should fail the bundle creation", func() { @@ -204,7 +204,7 @@ var _ = Describe("bundle api validation", func() { }) When("a Bundle references an invalid provisioner class name", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context ) BeforeEach(func() { @@ -212,12 +212,12 @@ var _ = Describe("bundle api validation", func() { }) AfterEach(func() { By("ensuring the testing Bundle does not exist") - err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), &rukpakv1alpha2.BundleDeployment{}) + err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), &rukpakv1alpha2.BundleDeployment{}) Expect(err).To(WithTransform(apierrors.IsNotFound, BeTrue()), fmt.Sprintf("error was: %v", err)) }) It("should fail validation", func() { By("creating the testing Bundle resource") - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("bundle-invalid-%s", rand.String(6)), }, @@ -231,7 +231,7 @@ var _ = Describe("bundle api validation", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).To(And( Not(BeNil()), WithTransform(apierrors.IsInvalid, Equal(true)), diff --git a/test/e2e/helm_provisioner_test.go b/test/e2e/helm_provisioner_test.go index 77440a88..7777b9ce 100644 --- a/test/e2e/helm_provisioner_test.go +++ b/test/e2e/helm_provisioner_test.go @@ -256,12 +256,12 @@ var _ = Describe("helm provisioner bundledeployment", func() { if err := c.Get(ctx, client.ObjectKeyFromObject(bd), bd); err != nil { return nil, err } - return meta.FindStatusCondition(bd.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil + return meta.FindStatusCondition(bd.Status.Conditions, rukpakv1alpha2.TypeInstalled), nil }).Should(And( Not(BeNil()), - WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), + WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeInstalled)), WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionFalse)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonUnpackFailed)), + WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonInstallFailed)), WithTransform(func(c *metav1.Condition) string { return c.Message }, ContainSubstring("Chart.yaml file is missing")), )) }) diff --git a/test/e2e/plain_provisioner_test.go b/test/e2e/plain_provisioner_test.go index 4eb99edc..261463a7 100644 --- a/test/e2e/plain_provisioner_test.go +++ b/test/e2e/plain_provisioner_test.go @@ -23,14 +23,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/rand" "k8s.io/client-go/tools/remotecommand" "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" rukpakv1alpha2 "github.com/operator-framework/rukpak/api/v1alpha2" "github.com/operator-framework/rukpak/internal/provisioner/plain" - "github.com/operator-framework/rukpak/internal/rukpakctl" "github.com/operator-framework/rukpak/internal/storage" "github.com/operator-framework/rukpak/internal/util" ) @@ -51,14 +49,14 @@ func Logf(f string, v ...interface{}) { var _ = Describe("plain provisioner bundle", func() { When("a valid Bundle references the wrong unique provisioner ID", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context ) BeforeEach(func() { ctx = context.Background() By("creating the testing Bundle resource") - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "olm-crds-valid", }, @@ -72,33 +70,33 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { By("deleting the testing Bundle resource") - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) It("should consistently contain an empty status", func() { Consistently(func() bool { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return false } - return len(bundledeployment.Status.Conditions) == 0 + return len(bundleDeployment.Status.Conditions) == 0 }, 10*time.Second, 1*time.Second).Should(BeTrue()) }) }) When("a valid Bundle Deployment referencing a remote container image is created", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context ) BeforeEach(func() { ctx = context.Background() By("creating the testing Bundle resource") - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "olm-crds-valid", }, @@ -112,12 +110,12 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { By("deleting the testing Bundle resource") - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) @@ -125,10 +123,10 @@ var _ = Describe("plain provisioner bundle", func() { By("eventually writing a non-empty image digest to the status", func() { Eventually(func() (*rukpakv1alpha2.BundleSource, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return nil, err } - return bundledeployment.Status.ResolvedSource, nil + return bundleDeployment.Status.ResolvedSource, nil }).Should(And( Not(BeNil()), WithTransform(func(s *rukpakv1alpha2.BundleSource) rukpakv1alpha2.SourceType { return s.Type }, Equal(rukpakv1alpha2.SourceTypeImage)), @@ -146,7 +144,7 @@ var _ = Describe("plain provisioner bundle", func() { ) By("getting the underlying bundle unpacking pod") - selector := util.NewBundleDeploymentLabelSelector(bundledeployment) + selector := util.NewBundleDeploymentLabelSelector(bundleDeployment) Eventually(func() bool { pods := &corev1.PodList{} if err := c.List(ctx, pods, &client.ListOptions{ @@ -179,14 +177,14 @@ var _ = Describe("plain provisioner bundle", func() { When("a valid Bundle Deployment referencing a remote private container image is created", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context ) BeforeEach(func() { ctx = context.Background() By("creating the testing Bundle resource") - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "olm-crds-valid", }, @@ -201,22 +199,22 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { By("deleting the testing Bundle resource") - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) It("should eventually report a successful state", func() { By("eventually reporting an Unpacked phase", func() { Eventually(func() (*metav1.Condition, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return nil, err } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeInstalled), nil + return meta.FindStatusCondition(bundleDeployment.Status.Conditions, rukpakv1alpha2.TypeInstalled), nil }).Should(And( Not(BeNil()), WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeInstalled)), @@ -228,10 +226,10 @@ var _ = Describe("plain provisioner bundle", func() { By("eventually writing a non-empty image digest to the status", func() { Eventually(func() (*rukpakv1alpha2.BundleSource, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return nil, err } - return bundledeployment.Status.ResolvedSource, nil + return bundleDeployment.Status.ResolvedSource, nil }).Should(And( Not(BeNil()), WithTransform(func(s *rukpakv1alpha2.BundleSource) rukpakv1alpha2.SourceType { return s.Type }, Equal(rukpakv1alpha2.SourceTypeImage)), @@ -246,14 +244,14 @@ var _ = Describe("plain provisioner bundle", func() { When("an invalid Bundle Deployment referencing a remote container image is created", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context ) BeforeEach(func() { ctx = context.Background() By("creating the testing Bundle resource") - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "olm-crds-invalid", }, @@ -267,12 +265,12 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { By("deleting the testing Bundle resource") - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) @@ -281,7 +279,7 @@ var _ = Describe("plain provisioner bundle", func() { Eventually(func() bool { pod := &corev1.Pod{} if err := c.Get(ctx, types.NamespacedName{ - Name: bundledeployment.GetName(), + Name: bundleDeployment.GetName(), Namespace: defaultSystemNamespace, }, pod); err != nil { return false @@ -299,15 +297,15 @@ var _ = Describe("plain provisioner bundle", func() { By("waiting for the bundle to report back that state") Eventually(func() bool { - err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment) + err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment) if err != nil { return false } - unpackPending := meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.PhaseUnpacked) + unpackPending := meta.FindStatusCondition(bundleDeployment.Status.Conditions, rukpakv1alpha2.PhaseUnpacked) if unpackPending == nil { return false } - if unpackPending.Message != fmt.Sprintf(`Back-off pulling image "%s"`, bundledeployment.Spec.Source.Image.Ref) { + if unpackPending.Message != fmt.Sprintf(`Back-off pulling image "%s"`, bundleDeployment.Spec.Source.Image.Ref) { return false } return true @@ -317,14 +315,14 @@ var _ = Describe("plain provisioner bundle", func() { When("a bundle deployment containing no manifests is created", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context ) BeforeEach(func() { ctx = context.Background() By("creating the testing Bundle resource") - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "olm-crds-unsupported", }, @@ -338,27 +336,27 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { By("deleting the testing Bundle resource") - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) It("reports an unpack error when the manifests directory is missing", func() { By("waiting for the bundle to report back that state") Eventually(func() (*metav1.Condition, error) { - err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment) + err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment) if err != nil { return nil, err } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil + return meta.FindStatusCondition(bundleDeployment.Status.Conditions, rukpakv1alpha2.TypeInstalled), nil }).Should(And( Not(BeNil()), - WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), + WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeInstalled)), WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionFalse)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonUnpackFailed)), + WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonInstallFailed)), WithTransform(func(c *metav1.Condition) string { return c.Message }, ContainSubstring(`readdir manifests: file does not exist`)), )) }) @@ -366,14 +364,14 @@ var _ = Describe("plain provisioner bundle", func() { When("a bundle containing an empty manifests directory is created", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context ) BeforeEach(func() { ctx = context.Background() By("creating the testing Bundle resource") - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "olm-crds-unsupported", }, @@ -387,27 +385,27 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { By("deleting the testing Bundle resource") - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) It("reports an unpack error when the manifests directory contains no objects", func() { By("waiting for the bundle to report back that state") Eventually(func() (*metav1.Condition, error) { - err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment) + err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment) if err != nil { return nil, err } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil + return meta.FindStatusCondition(bundleDeployment.Status.Conditions, rukpakv1alpha2.TypeInstalled), nil }).Should(And( Not(BeNil()), - WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), + WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeInstalled)), WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionFalse)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonUnpackFailed)), + WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonInstallFailed)), WithTransform(func(c *metav1.Condition) string { return c.Message }, ContainSubstring(`found zero objects: plain+v0 bundles are required to contain at least one object`)), )) }) @@ -424,10 +422,10 @@ var _ = Describe("plain provisioner bundle", func() { When("the bundle is backed by a git commit", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ) BeforeEach(func() { - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "combo-git-commit", }, @@ -444,18 +442,18 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) It("Can create and unpack the bundle successfully", func() { Eventually(func() error { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return err } @@ -467,16 +465,16 @@ var _ = Describe("plain provisioner bundle", func() { return errors.New("expected exactly 1 provisioner pod") } - return checkProvisionerBundleDeployment(ctx, bundledeployment, provisionerPods.Items[0].Name) + return checkProvisionerBundleDeployment(ctx, bundleDeployment, provisionerPods.Items[0].Name) }).Should(BeNil()) }) }) When("the bundle deployment is backed by a git tag", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ) BeforeEach(func() { - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "combo-git-tag", }, @@ -493,19 +491,19 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) It("Can create and unpack the bundle successfully", func() { By("eventually unpacking the bundle", func() { Eventually(func() error { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return err } @@ -517,16 +515,16 @@ var _ = Describe("plain provisioner bundle", func() { return errors.New("expected exactly 1 provisioner pod") } - return checkProvisionerBundleDeployment(ctx, bundledeployment, provisionerPods.Items[0].Name) + return checkProvisionerBundleDeployment(ctx, bundleDeployment, provisionerPods.Items[0].Name) }).Should(BeNil()) }) By("eventually writing a non-empty commit hash to the status", func() { Eventually(func() (*rukpakv1alpha2.BundleSource, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return nil, err } - return bundledeployment.Status.ResolvedSource, nil + return bundleDeployment.Status.ResolvedSource, nil }).Should(And( Not(BeNil()), WithTransform(func(s *rukpakv1alpha2.BundleSource) rukpakv1alpha2.SourceType { return s.Type }, Equal(rukpakv1alpha2.SourceTypeGit)), @@ -541,10 +539,10 @@ var _ = Describe("plain provisioner bundle", func() { When("the bundle deployment is backed by a git branch", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ) BeforeEach(func() { - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "combo-git-branch", }, @@ -561,19 +559,19 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) It("Can create and unpack the bundle successfully", func() { By("eventually unpacking the bundle", func() { Eventually(func() error { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return err } @@ -585,16 +583,16 @@ var _ = Describe("plain provisioner bundle", func() { return errors.New("expected exactly 1 provisioner pod") } - return checkProvisionerBundleDeployment(ctx, bundledeployment, provisionerPods.Items[0].Name) + return checkProvisionerBundleDeployment(ctx, bundleDeployment, provisionerPods.Items[0].Name) }).Should(BeNil()) }) By("eventually writing a non-empty commit hash to the status", func() { Eventually(func() (*rukpakv1alpha2.BundleSource, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return nil, err } - return bundledeployment.Status.ResolvedSource, nil + return bundleDeployment.Status.ResolvedSource, nil }).Should(And( Not(BeNil()), WithTransform(func(s *rukpakv1alpha2.BundleSource) rukpakv1alpha2.SourceType { return s.Type }, Equal(rukpakv1alpha2.SourceTypeGit)), @@ -609,10 +607,10 @@ var _ = Describe("plain provisioner bundle", func() { When("the bundle deployment has a custom manifests directory", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ) BeforeEach(func() { - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "combo-git-custom-dir", }, @@ -630,18 +628,18 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) It("Can create and unpack the bundle successfully", func() { Eventually(func() error { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return err } @@ -653,14 +651,14 @@ var _ = Describe("plain provisioner bundle", func() { return errors.New("expected exactly 1 provisioner pod") } - return checkProvisionerBundleDeployment(ctx, bundledeployment, provisionerPods.Items[0].Name) + return checkProvisionerBundleDeployment(ctx, bundleDeployment, provisionerPods.Items[0].Name) }).Should(BeNil()) }) }) When("the bundle deployment is backed by a private repository", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment secret *corev1.Secret privateRepo string ) @@ -683,7 +681,7 @@ var _ = Describe("plain provisioner bundle", func() { } err := c.Create(ctx, secret) Expect(err).ToNot(HaveOccurred()) - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "combo-git-branch", }, @@ -705,12 +703,12 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err = c.Create(ctx, bundledeployment) + err = c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) err = c.Delete(ctx, secret) Expect(err).ToNot(HaveOccurred()) @@ -718,7 +716,7 @@ var _ = Describe("plain provisioner bundle", func() { It("Can create and unpack the bundle successfully", func() { Eventually(func() error { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return err } @@ -730,19 +728,19 @@ var _ = Describe("plain provisioner bundle", func() { return errors.New("expected exactly 1 provisioner pod") } - return checkProvisionerBundleDeployment(ctx, bundledeployment, provisionerPods.Items[0].Name) + return checkProvisionerBundleDeployment(ctx, bundleDeployment, provisionerPods.Items[0].Name) }).Should(BeNil()) }) }) When("the bundle deployment is backed by a local git repository", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment privateRepo string ) BeforeEach(func() { privateRepo = "ssh://git@local-git.rukpak-e2e.svc.cluster.local:2222/git-server/repos/combo" - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "combo-git-branch", }, @@ -765,18 +763,18 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) It("Can create and unpack the bundle successfully", func() { Eventually(func() error { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return err } @@ -788,7 +786,7 @@ var _ = Describe("plain provisioner bundle", func() { return errors.New("expected exactly 1 provisioner pod") } - return checkProvisionerBundleDeployment(ctx, bundledeployment, provisionerPods.Items[0].Name) + return checkProvisionerBundleDeployment(ctx, bundleDeployment, provisionerPods.Items[0].Name) }).Should(BeNil()) }) }) @@ -796,7 +794,7 @@ var _ = Describe("plain provisioner bundle", func() { When("the bundle deployment is backed by a configmap", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment configmap *corev1.ConfigMap ctx context.Context ) @@ -830,7 +828,7 @@ var _ = Describe("plain provisioner bundle", func() { } err = c.Create(ctx, configmap) Expect(err).ToNot(HaveOccurred()) - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "combo-local-", }, @@ -845,12 +843,12 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err = c.Create(ctx, bundledeployment) + err = c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { - Expect(client.IgnoreNotFound(c.Delete(ctx, bundledeployment))).To(Succeed()) + Expect(client.IgnoreNotFound(c.Delete(ctx, bundleDeployment))).To(Succeed()) Eventually(func() error { return client.IgnoreNotFound(c.Delete(ctx, configmap)) }).Should(Succeed()) @@ -858,20 +856,20 @@ var _ = Describe("plain provisioner bundle", func() { It("Can create and unpack the bundle successfully", func() { Eventually(func() error { - return c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment) + return c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment) }).Should(BeNil()) }) }) When("the bundle is backed by a non-existent configmap", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context ) BeforeEach(func() { ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "combo-local-", }, @@ -886,21 +884,21 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(client.IgnoreNotFound(err)).To(Succeed()) }) It("eventually results in a failing bundle state", func() { By("waiting until the bundle is reporting Failing state") Eventually(func() (*metav1.Condition, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return nil, err } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil + return meta.FindStatusCondition(bundleDeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil }).Should(And( Not(BeNil()), WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), @@ -914,7 +912,7 @@ var _ = Describe("plain provisioner bundle", func() { When("the bundle is backed by an invalid configmap", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment configmap *corev1.ConfigMap ctx context.Context ) @@ -947,7 +945,7 @@ var _ = Describe("plain provisioner bundle", func() { } err = c.Create(ctx, configmap) Expect(err).ToNot(HaveOccurred()) - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "combo-local-", }, @@ -962,12 +960,12 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err = c.Create(ctx, bundledeployment) + err = c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { - Expect(client.IgnoreNotFound(c.Delete(ctx, bundledeployment))).To(Succeed()) + Expect(client.IgnoreNotFound(c.Delete(ctx, bundleDeployment))).To(Succeed()) Eventually(func() error { return client.IgnoreNotFound(c.Delete(ctx, configmap)) }).Should(Succeed()) @@ -975,148 +973,23 @@ var _ = Describe("plain provisioner bundle", func() { It("checks the bundle's phase gets failing", func() { By("waiting until the bundle is reporting Failing state") Eventually(func() (*metav1.Condition, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { - return nil, err - } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil - }).Should(And( - Not(BeNil()), - WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), - WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionFalse)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonUnpackFailed)), - WithTransform(func(c *metav1.Condition) string { return c.Message }, ContainSubstring("json: cannot unmarshal string into Go value")), - )) - }) - }) - - When("the bundle deployment is uploaded", func() { - var ( - bundledeployment *rukpakv1alpha2.BundleDeployment - ctx context.Context - ) - - BeforeEach(func() { - ctx = context.Background() - - bundleFS := os.DirFS(filepath.Join(testdataDir, "bundles/plain-v0/valid")) - bundledeployment = &rukpakv1alpha2.BundleDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("valid-upload-%s", rand.String(8)), - }, - Spec: rukpakv1alpha2.BundleDeploymentSpec{ - ProvisionerClassName: plain.ProvisionerID, - Source: rukpakv1alpha2.BundleSource{ - Type: rukpakv1alpha2.SourceTypeUpload, - Upload: &rukpakv1alpha2.UploadSource{}, - }, - }, - } - err := c.Create(ctx, bundledeployment) - Expect(err).ToNot(HaveOccurred()) - - rootCAs, err := rukpakctl.GetClusterCA(ctx, c, types.NamespacedName{Namespace: defaultSystemNamespace, Name: "rukpak-ca"}) - Expect(err).ToNot(HaveOccurred()) - - bu := rukpakctl.BundleUploader{ - UploadServiceName: defaultUploadServiceName, - UploadServiceNamespace: defaultSystemNamespace, - Cfg: cfg, - RootCAs: rootCAs, - } - uploadCtx, cancel := context.WithTimeout(ctx, time.Second*5) - defer cancel() - _, err = bu.Upload(uploadCtx, bundledeployment.Name, bundleFS) - Expect(err).ToNot(HaveOccurred()) - }) - - AfterEach(func() { - err := c.Delete(ctx, bundledeployment) - Expect(client.IgnoreNotFound(err)).To(Succeed()) - }) - - It("can unpack the bundle successfully", func() { - Eventually(func() (*metav1.Condition, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return nil, err } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeInstalled), nil + return meta.FindStatusCondition(bundleDeployment.Status.Conditions, rukpakv1alpha2.TypeInstalled), nil }).Should(And( Not(BeNil()), WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeInstalled)), - WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionTrue)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonInstallationSucceeded)), - WithTransform(func(c *metav1.Condition) string { return c.Message }, ContainSubstring("Instantiated bundle")), - )) - }) - }) - - When("the bundle deployment is backed by an invalid upload", func() { - var ( - bundledeployment *rukpakv1alpha2.BundleDeployment - ctx context.Context - ) - const ( - manifestsDir = "manifests" - subdirName = "emptydir" - ) - BeforeEach(func() { - ctx = context.Background() - - bundleFS := os.DirFS(filepath.Join(testdataDir, "bundles/plain-v0/subdir")) - bundledeployment = &rukpakv1alpha2.BundleDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("invalid-upload-%s", rand.String(8)), - }, - Spec: rukpakv1alpha2.BundleDeploymentSpec{ - ProvisionerClassName: plain.ProvisionerID, - Source: rukpakv1alpha2.BundleSource{ - Type: rukpakv1alpha2.SourceTypeUpload, - Upload: &rukpakv1alpha2.UploadSource{}, - }, - }, - } - err := c.Create(ctx, bundledeployment) - Expect(err).ToNot(HaveOccurred()) - - rootCAs, err := rukpakctl.GetClusterCA(ctx, c, types.NamespacedName{Namespace: defaultSystemNamespace, Name: "rukpak-ca"}) - Expect(err).ToNot(HaveOccurred()) - - bu := rukpakctl.BundleUploader{ - UploadServiceName: defaultUploadServiceName, - UploadServiceNamespace: defaultSystemNamespace, - Cfg: cfg, - RootCAs: rootCAs, - } - uploadCtx, cancel := context.WithTimeout(ctx, time.Second*5) - defer cancel() - _, err = bu.Upload(uploadCtx, bundledeployment.Name, bundleFS) - Expect(err).ToNot(HaveOccurred()) - }) - AfterEach(func() { - err := c.Delete(ctx, bundledeployment) - Expect(client.IgnoreNotFound(err)).To(Succeed()) - }) - It("checks the bundle's phase gets failing", func() { - By("waiting until the bundle is reporting Failing state") - Eventually(func() (*metav1.Condition, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { - return nil, err - } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil - }).Should(And( - Not(BeNil()), - WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionFalse)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonUnpackFailed)), - WithTransform(func(c *metav1.Condition) string { return c.Message }, - ContainSubstring(fmt.Sprintf("subdirectories are not allowed within the %q directory of the bundle image filesystem: found %q", manifestsDir, filepath.Join(manifestsDir, subdirName)))), + WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonInstallFailed)), + WithTransform(func(c *metav1.Condition) string { return c.Message }, ContainSubstring("json: cannot unmarshal string into Go value")), )) }) }) When("a bundle deployment containing nested directory is created", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context ) const ( @@ -1127,7 +1000,7 @@ var _ = Describe("plain provisioner bundle", func() { ctx = context.Background() By("creating the testing Bundle resource") - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "namespace-subdirs", }, @@ -1141,26 +1014,26 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { By("deleting the testing Bundle resource") - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) It("reports an unpack error when the manifests directory contains directories", func() { By("eventually reporting an Unpacked phase", func() { Eventually(func() (*metav1.Condition, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return nil, err } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil + return meta.FindStatusCondition(bundleDeployment.Status.Conditions, rukpakv1alpha2.TypeInstalled), nil }).Should(And( Not(BeNil()), - WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), + WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeInstalled)), WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionFalse)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonUnpackFailed)), + WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonInstallFailed)), WithTransform(func(c *metav1.Condition) string { return c.Message }, ContainSubstring(fmt.Sprintf("subdirectories are not allowed within the %q directory of the bundle image filesystem: found %q", manifestsDir, filepath.Join(manifestsDir, subdirName)))), )) @@ -1171,11 +1044,11 @@ var _ = Describe("plain provisioner bundle", func() { When("valid bundle is created", func() { var ( ctx context.Context - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ) BeforeEach(func() { ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "combo-git-commit", }, @@ -1192,14 +1065,14 @@ var _ = Describe("plain provisioner bundle", func() { }, }, } - err := c.Create(ctx, bundledeployment) + err := c.Create(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) By("eventually reporting an Unpacked phase", func() { Eventually(func() (*metav1.Condition, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { + if err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment); err != nil { return nil, err } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil + return meta.FindStatusCondition(bundleDeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil }).Should(And( Not(BeNil()), WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), @@ -1210,14 +1083,14 @@ var _ = Describe("plain provisioner bundle", func() { By("eventually writing a content URL to the status", func() { Eventually(func() (string, error) { - err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment) + err := c.Get(ctx, client.ObjectKeyFromObject(bundleDeployment), bundleDeployment) Expect(err).ToNot(HaveOccurred()) - return bundledeployment.Status.ContentURL, nil + return bundleDeployment.Status.ContentURL, nil }).Should(Not(BeEmpty())) }) }) AfterEach(func() { - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) When("start server for bundle contents", func() { @@ -1251,7 +1124,7 @@ var _ = Describe("plain provisioner bundle", func() { err = c.Create(ctx, &crb) Expect(err).ToNot(HaveOccurred()) - url := bundledeployment.Status.ContentURL + url := bundleDeployment.Status.ContentURL // Create a Job that reads from the URL and outputs contents in the pod log mounttoken := true @@ -1329,7 +1202,7 @@ var _ = Describe("plain provisioner bundle", func() { }) }) - var _ = Describe("plain provisioner bundledeployment", func() { + var _ = Describe("plain provisioner bundleDeployment", func() { When("a BundleDeployment is dependent on another BundleDeployment", func() { var ( ctx context.Context diff --git a/test/e2e/registry_provisioner_test.go b/test/e2e/registry_provisioner_test.go index e2184453..f43f694a 100644 --- a/test/e2e/registry_provisioner_test.go +++ b/test/e2e/registry_provisioner_test.go @@ -93,7 +93,7 @@ var _ = Describe("registry provisioner bundle", func() { Expect(err).ToNot(HaveOccurred()) }) AfterEach(func() { - By("deleting the testing BI resource") + By("deleting the testing BD resource") Expect(c.Delete(ctx, bd)).To(Succeed()) }) @@ -102,12 +102,12 @@ var _ = Describe("registry provisioner bundle", func() { if err := c.Get(ctx, client.ObjectKeyFromObject(bd), bd); err != nil { return nil, err } - return meta.FindStatusCondition(bd.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil + return meta.FindStatusCondition(bd.Status.Conditions, rukpakv1alpha2.TypeInstalled), nil }).Should(And( Not(BeNil()), - WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), + WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeInstalled)), WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionFalse)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonUnpackFailed)), + WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonInstallFailed)), WithTransform(func(c *metav1.Condition) string { return c.Message }, ContainSubstring("convert registry+v1 bundle to plain+v0 bundle: AllNamespace install mode must be enabled")), )) }) diff --git a/test/e2e/rukpakctl_test.go b/test/e2e/rukpakctl_test.go deleted file mode 100644 index 3a03224e..00000000 --- a/test/e2e/rukpakctl_test.go +++ /dev/null @@ -1,218 +0,0 @@ -package e2e - -import ( - "context" - "errors" - "fmt" - "os/exec" - "strings" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/client" - - rukpakv1alpha2 "github.com/operator-framework/rukpak/api/v1alpha2" - "github.com/operator-framework/rukpak/internal/provisioner/plain" -) - -const ( - rukpakctlcmd = "../../bin/rukpakctl " - testbundles = "../../testdata/bundles/" -) - -var _ = Describe("rukpakctl run subcommand", func() { - When("run executed with a valid local manifest directory", func() { - var ( - ctx context.Context - bundlename string - bundledeploymentname string - bundledeployment *rukpakv1alpha2.BundleDeployment - ) - BeforeEach(func() { - ctx = context.Background() - out, err := exec.Command("sh", "-c", rukpakctlcmd+"run test "+testbundles+"plain-v0/valid").Output() - Expect(err).ToNot(HaveOccurred()) - fmt.Sscanf(string(out), "bundledeployment.core.rukpak.io %q applied\nsuccessfully uploaded bundle content for %q", &bundledeploymentname, &bundlename) - }) - AfterEach(func() { - Expect(c.Delete(ctx, bundledeployment)).To(Succeed()) - }) - It("should eventually report a successful state", func() { - bundledeployment = &rukpakv1alpha2.BundleDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: bundledeploymentname, - }, - } - By("eventually reporting Unpacked", func() { - Eventually(func() (*metav1.Condition, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { - return nil, err - } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil - }).Should(And( - Not(BeNil()), - WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), - WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionTrue)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonUnpackSuccessful)), - )) - }) - By("eventually reporting Installed", func() { - Eventually(func() (*metav1.Condition, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { - return nil, err - } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeInstalled), nil - }).Should(And( - Not(BeNil()), - WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeInstalled)), - WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionTrue)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonInstallationSucceeded)), - )) - }) - }) - }) - When("run executed with an invalid manifest directory", func() { - var ( - message string - ) - BeforeEach(func() { - out, err := exec.Command("sh", "-c", rukpakctlcmd+"run test "+testbundles+"plain-v0/notvalid").CombinedOutput() - message = string(out) - Expect(err).To(HaveOccurred()) - }) - It(`should fail with a "no such file or directory" message`, func() { - Expect(strings.Contains(message, "no such file or directory")).To(BeTrue()) - }) - }) - When("run executed with a bundle cannot unpacked", func() { - var ( - ctx context.Context - bundlename string - bundledeploymentname string - bundledeployment *rukpakv1alpha2.BundleDeployment - ) - BeforeEach(func() { - ctx = context.Background() - out, err := exec.Command("sh", "-c", rukpakctlcmd+"run test "+testbundles+"plain-v0/subdir").Output() - Expect(err).ToNot(HaveOccurred()) - fmt.Sscanf(string(out), "bundledeployment.core.rukpak.io %q applied\nsuccessfully uploaded bundle content for %q", &bundledeploymentname, &bundlename) - }) - AfterEach(func() { - Expect(c.Delete(ctx, bundledeployment)).To(Succeed()) - }) - It("should eventually report unpack fail", func() { - bundledeployment = &rukpakv1alpha2.BundleDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: bundledeploymentname, - }, - } - By("eventually reporting Unpack failed", func() { - Eventually(func() (*metav1.Condition, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { - return nil, err - } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil - }).Should(And( - Not(BeNil()), - WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), - WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionFalse)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonUnpackFailed)), - )) - }) - }) - }) -}) - -var _ = Describe("rukpakctl content subcommand", func() { - When("content executed with a valid bundle", func() { - var ( - ctx context.Context - bundledeployment *rukpakv1alpha2.BundleDeployment - output string - ) - BeforeEach(func() { - ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "combo-git-commit", - }, - Spec: rukpakv1alpha2.BundleDeploymentSpec{ - ProvisionerClassName: plain.ProvisionerID, - Source: rukpakv1alpha2.BundleSource{ - Type: rukpakv1alpha2.SourceTypeGit, - Git: &rukpakv1alpha2.GitSource{ - Repository: "https://github.com/exdx/combo-bundle", - Ref: rukpakv1alpha2.GitRef{ - Commit: "9e3ab7f1a36302ef512294d5c9f2e9b9566b811e", - }, - }, - }, - }, - } - err := c.Create(ctx, bundledeployment) - Expect(err).ToNot(HaveOccurred()) - By("eventually reporting an Unpacked phase", func() { - Eventually(func() (*metav1.Condition, error) { - if err := c.Get(ctx, client.ObjectKeyFromObject(bundledeployment), bundledeployment); err != nil { - return nil, err - } - return meta.FindStatusCondition(bundledeployment.Status.Conditions, rukpakv1alpha2.TypeUnpacked), nil - }).Should(And( - Not(BeNil()), - WithTransform(func(c *metav1.Condition) string { return c.Type }, Equal(rukpakv1alpha2.TypeUnpacked)), - WithTransform(func(c *metav1.Condition) metav1.ConditionStatus { return c.Status }, Equal(metav1.ConditionTrue)), - WithTransform(func(c *metav1.Condition) string { return c.Reason }, Equal(rukpakv1alpha2.ReasonUnpackSuccessful)), - )) - }) - out, err := exec.Command("sh", "-c", rukpakctlcmd+"content "+bundledeployment.ObjectMeta.Name).Output() // nolint:gosec - Expect(err).ToNot(HaveOccurred()) - output = string(out) - }) - AfterEach(func() { - err := c.Delete(ctx, bundledeployment) - Expect(err).ToNot(HaveOccurred()) - }) - - It("output all files in the bundle", func() { - Expect(strings.Contains(output, "manifests/00_namespace.yaml") && - strings.Contains(output, "manifests/01_cluster_role.yaml") && - strings.Contains(output, "manifests/01_service_account.yaml") && - strings.Contains(output, "manifests/02_deployment.yaml") && - strings.Contains(output, "manifests/03_cluster_role_binding.yaml") && - strings.Contains(output, "manifests/combo.io_combinations.yaml") && - strings.Contains(output, "manifests/combo.io_templates.yaml")).To(BeTrue()) - }) - }) - When("content executed with a wrong bundle name", func() { - var ( - output string - err error - ) - BeforeEach(func() { - var out []byte - out, err = exec.Command("sh", "-c", rukpakctlcmd+"content badname").Output() - Expect(err).To(HaveOccurred()) - output = string(out) - }) - - It("writes nothing into stdout", func() { - Expect(output).To(BeEmpty()) - }) - - It("writes an error message into stderr", func() { - Expect(err).To(WithTransform(func(err error) string { - var exitErr *exec.ExitError - if !errors.As(err, &exitErr) { - return "" - } - - return string(exitErr.Stderr) - }, SatisfyAll( - ContainSubstring("content command failed"), - ContainSubstring("bundledeployments.core.rukpak.io \"badname\" not found"), - ))) - }) - }) -}) diff --git a/test/e2e/webhook_test.go b/test/e2e/webhook_test.go index e2c2a50a..ab767e5f 100644 --- a/test/e2e/webhook_test.go +++ b/test/e2e/webhook_test.go @@ -15,7 +15,7 @@ import ( var _ = Describe("bundle deployment api validating webhook", func() { When("Bundle Deployment is valid", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context err error ) @@ -24,7 +24,7 @@ var _ = Describe("bundle deployment api validating webhook", func() { By("creating the valid Bundle resource") ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "valid-bundle-", }, @@ -38,11 +38,11 @@ var _ = Describe("bundle deployment api validating webhook", func() { }, }, } - err = c.Create(ctx, bundledeployment) + err = c.Create(ctx, bundleDeployment) }) AfterEach(func() { By("deleting the testing Bundle resource") - err := c.Delete(ctx, bundledeployment) + err := c.Delete(ctx, bundleDeployment) Expect(err).ToNot(HaveOccurred()) }) It("should create the bundle resource", func() { @@ -51,7 +51,7 @@ var _ = Describe("bundle deployment api validating webhook", func() { }) When("the bundle source type is git and git properties are not set", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context err error ) @@ -59,7 +59,7 @@ var _ = Describe("bundle deployment api validating webhook", func() { By("creating the Bundle resource") ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: "bundlenamegit", }, @@ -73,11 +73,11 @@ var _ = Describe("bundle deployment api validating webhook", func() { }, }, } - err = c.Create(ctx, bundledeployment) + err = c.Create(ctx, bundleDeployment) }) AfterEach(func() { By("deleting the testing Bundle resource for failure case") - err = c.Delete(ctx, bundledeployment) + err = c.Delete(ctx, bundleDeployment) Expect(err).To(WithTransform(apierrors.IsNotFound, BeTrue())) }) It("should fail the bundle creation", func() { @@ -86,7 +86,7 @@ var _ = Describe("bundle deployment api validating webhook", func() { }) When("the bundle source type is image and image properties are not set", func() { var ( - bundledeployment *rukpakv1alpha2.BundleDeployment + bundleDeployment *rukpakv1alpha2.BundleDeployment ctx context.Context err error ) @@ -94,7 +94,7 @@ var _ = Describe("bundle deployment api validating webhook", func() { By("creating the Bundle resource") ctx = context.Background() - bundledeployment = &rukpakv1alpha2.BundleDeployment{ + bundleDeployment = &rukpakv1alpha2.BundleDeployment{ ObjectMeta: metav1.ObjectMeta{ Name: "bundlenameimage", }, @@ -111,11 +111,11 @@ var _ = Describe("bundle deployment api validating webhook", func() { }, }, } - err = c.Create(ctx, bundledeployment) + err = c.Create(ctx, bundleDeployment) }) AfterEach(func() { By("deleting the testing Bundle resource for failure case") - err = c.Delete(ctx, bundledeployment) + err = c.Delete(ctx, bundleDeployment) Expect(err).To(WithTransform(apierrors.IsNotFound, BeTrue())) })