diff --git a/Makefile b/Makefile index 398ff957e..ee79232bb 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,8 @@ export IMAGE_REPO ?= quay.io/operator-framework/operator-controller export IMAGE_TAG ?= devel export GO_BUILD_TAGS ?= upstream +export CERT_MGR_VERSION ?= v1.9.0 +export WAIT_TIMEOUT ?= 60s IMG?=$(IMAGE_REPO):$(IMAGE_TAG) OPERATOR_CONTROLLER_NAMESPACE ?= operator-controller-system @@ -99,11 +101,11 @@ build: manifests generate fmt vet ## Build manager binary. go build -o bin/manager main.go .PHONY: run -run: docker-build kind-cluster kind-load install deploy wait ## Build the operator-controller then deploy it into a new kind cluster. +run: docker-build kind-cluster kind-load cert-mgr rukpak install deploy wait ## Build the operator-controller then deploy it into a new kind cluster. .PHONY: wait wait: - kubectl wait --for=condition=Available --namespace=$(OPERATOR_CONTROLLER_NAMESPACE) deployment/operator-controller-controller-manager --timeout=60s + kubectl wait --for=condition=Available --namespace=$(OPERATOR_CONTROLLER_NAMESPACE) deployment/operator-controller-controller-manager --timeout=$(WAIT_TIMEOUT) # If you wish built the manager image targeting other platforms you can use the --platform flag. # (i.e. docker build --platform linux/arm64 ). However, you must enable docker buildKit for it. @@ -139,6 +141,17 @@ ifndef ignore-not-found ignore-not-found = false endif +## TODO dfranz: replace cert-mgr and rukpak targets with our chosen method of distribution when available +.PHONY: cert-mgr +cert-mgr: ## Install cert-manager + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/$(CERT_MGR_VERSION)/cert-manager.yaml + kubectl wait --for=condition=Available --namespace=cert-manager deployment/cert-manager-webhook --timeout=$(WAIT_TIMEOUT) + +.PHONY: rukpak +rukpak: ## Install rukpak + kubectl apply -f https://github.com/operator-framework/rukpak/releases/latest/download/rukpak.yaml + kubectl wait --for=condition=Available --namespace=rukpak-system deployment/core --timeout=$(WAIT_TIMEOUT) + .PHONY: install install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. $(KUSTOMIZE) build config/crd | kubectl apply -f - diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 5958e8c78..02b255528 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -5,6 +5,17 @@ metadata: creationTimestamp: null name: manager-role rules: +- apiGroups: + - core.rukpak.io + resources: + - bundledeployments + verbs: + - create + - get + - list + - patch + - update + - watch - apiGroups: - operators.operatorframework.io resources: diff --git a/controllers/operator_controller.go b/controllers/operator_controller.go index f8229b083..306dc5a06 100644 --- a/controllers/operator_controller.go +++ b/controllers/operator_controller.go @@ -19,10 +19,12 @@ package controllers import ( "context" + rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" "k8s.io/apimachinery/pkg/api/equality" apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" @@ -41,10 +43,20 @@ type OperatorReconciler struct { resolver *resolution.OperatorResolver } +func NewOperatorReconciler(c client.Client, s *runtime.Scheme, r *resolution.OperatorResolver) *OperatorReconciler { + return &OperatorReconciler{ + Client: c, + Scheme: s, + resolver: r, + } +} + //+kubebuilder:rbac:groups=operators.operatorframework.io,resources=operators,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=operators.operatorframework.io,resources=operators/status,verbs=get;update;patch //+kubebuilder:rbac:groups=operators.operatorframework.io,resources=operators/finalizers,verbs=update +//+kubebuilder:rbac:groups=core.rukpak.io,resources=bundledeployments,verbs=get;list;watch;create;update;patch + // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. // TODO(user): Modify the Reconcile function to compare the state specified by @@ -125,8 +137,14 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha if err != nil { return ctrl.Result{}, err } - // TODO(perdasilva): use bundlePath to stamp out bundle deployment - _ = bundlePath + dep, err := r.generateExpectedBundleDeployment(*op, bundlePath) + if err != nil { + return ctrl.Result{}, err + } + // Create bundleDeployment if not found or Update if needed + if err := r.ensureBundleDeployment(ctx, dep); err != nil { + return ctrl.Result{}, err + } break } } @@ -145,12 +163,48 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha return ctrl.Result{}, nil } +func (r *OperatorReconciler) generateExpectedBundleDeployment(o operatorsv1alpha1.Operator, bundlePath string) (*rukpakv1alpha1.BundleDeployment, error) { + dep := &rukpakv1alpha1.BundleDeployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: o.GetName(), + }, + Spec: rukpakv1alpha1.BundleDeploymentSpec{ + //TODO: Don't assume plain provisioner + ProvisionerClassName: "core-rukpak-io-plain", + Template: &rukpakv1alpha1.BundleTemplate{ + ObjectMeta: metav1.ObjectMeta{ + // TODO: Remove + Labels: map[string]string{ + "app": "my-bundle", + }, + }, + Spec: rukpakv1alpha1.BundleSpec{ + Source: rukpakv1alpha1.BundleSource{ + // TODO: Don't assume image type + Type: rukpakv1alpha1.SourceTypeImage, + Image: &rukpakv1alpha1.ImageSource{ + Ref: bundlePath, + }, + }, + + //TODO: Don't assume registry provisioner + ProvisionerClassName: "core-rukpak-io-registry", + }, + }, + }, + } + + if err := ctrl.SetControllerReference(&o, dep, r.Scheme); err != nil { + return nil, err + } + return dep, nil +} + // SetupWithManager sets up the controller with the Manager. func (r *OperatorReconciler) SetupWithManager(mgr ctrl.Manager) error { - r.resolver = resolution.NewOperatorResolver(mgr.GetClient(), resolution.HardcodedEntitySource) - err := ctrl.NewControllerManagedBy(mgr). For(&operatorsv1alpha1.Operator{}). + Owns(&rukpakv1alpha1.BundleDeployment{}). Complete(r) if err != nil { @@ -158,3 +212,22 @@ func (r *OperatorReconciler) SetupWithManager(mgr ctrl.Manager) error { } return nil } + +func (r *OperatorReconciler) ensureBundleDeployment(ctx context.Context, desiredBundleDeployment *rukpakv1alpha1.BundleDeployment) error { + existingBundleDeployment := &rukpakv1alpha1.BundleDeployment{} + err := r.Client.Get(ctx, types.NamespacedName{Name: desiredBundleDeployment.GetName()}, existingBundleDeployment) + if err != nil { + if client.IgnoreNotFound(err) != nil { + return err + } + return r.Client.Create(ctx, desiredBundleDeployment) + } + + // Check if the existing bundleDeployment's spec needs to be updated + if equality.Semantic.DeepEqual(existingBundleDeployment.Spec, desiredBundleDeployment.Spec) { + return nil + } + + existingBundleDeployment.Spec = desiredBundleDeployment.Spec + return r.Client.Update(ctx, existingBundleDeployment) +} diff --git a/controllers/suite_test.go b/controllers/suite_test.go index a0758025a..8925bfcb8 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -38,7 +38,9 @@ import ( operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" "github.com/operator-framework/operator-controller/controllers" + "github.com/operator-framework/operator-controller/internal/resolution" operatorutil "github.com/operator-framework/operator-controller/internal/util" + rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" //+kubebuilder:scaffold:imports ) @@ -63,7 +65,9 @@ var _ = BeforeSuite(func() { By("bootstrapping test environment") testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")}, + CRDDirectoryPaths: []string{ + filepath.Join("..", "config", "crd", "bases"), + filepath.Join("..", "testdata", "crds")}, ErrorIfCRDPathMissing: true, } @@ -76,6 +80,9 @@ var _ = BeforeSuite(func() { err = operatorsv1alpha1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) + err = rukpakv1alpha1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + //+kubebuilder:scaffold:scheme k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) @@ -87,10 +94,11 @@ var _ = BeforeSuite(func() { }) Expect(err).ToNot(HaveOccurred()) - err = (&controllers.OperatorReconciler{ - Client: k8sManager.GetClient(), - Scheme: k8sManager.GetScheme(), - }).SetupWithManager(k8sManager) + err = controllers.NewOperatorReconciler( + k8sManager.GetClient(), + k8sManager.GetScheme(), + resolution.NewOperatorResolver(k8sManager.GetClient(), resolution.HardcodedEntitySource), + ).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) ctx, cancel = context.WithCancel(context.Background()) diff --git a/go.mod b/go.mod index ea14e1b49..2b032d70e 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/onsi/gomega v1.22.1 github.com/operator-framework/deppy v0.0.0-20230125110717-dc02e928470f github.com/operator-framework/operator-registry v1.26.2 + github.com/operator-framework/rukpak v0.11.0 k8s.io/apimachinery v0.25.0 k8s.io/client-go v0.25.0 sigs.k8s.io/controller-runtime v0.13.1 @@ -42,7 +43,7 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.8 // indirect - github.com/google/gofuzz v1.1.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.2.0 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/josharian/intern v1.0.0 // indirect diff --git a/go.sum b/go.sum index 3f5f054f4..c3df05218 100644 --- a/go.sum +++ b/go.sum @@ -203,8 +203,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -291,6 +291,8 @@ github.com/operator-framework/deppy v0.0.0-20230125110717-dc02e928470f h1:YxUZyQ github.com/operator-framework/deppy v0.0.0-20230125110717-dc02e928470f/go.mod h1:JaF7sX6tn7mpXcOehYjSHiKM1Y0z09vEfC6dca4AVuo= github.com/operator-framework/operator-registry v1.26.2 h1:kQToR/hPqdivljaRXM0olPllNIcc/GUk1VBoGwagJmk= github.com/operator-framework/operator-registry v1.26.2/go.mod h1:Z7XIb/3ZkhBQCvMD/rJphyuY4LmU/eWpZS+o0Mm1WAk= +github.com/operator-framework/rukpak v0.11.0 h1:D2UAlYkmCl/i6zWE+yP9oIzOScVu9VwtqJKKt+dklWw= +github.com/operator-framework/rukpak v0.11.0/go.mod h1:n8oYwfz4a50Oh9hYnPgxiD2wa+xLbPq3cI67wapcL4Y= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -336,8 +338,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/main.go b/main.go index 739d67917..a11ae31c1 100644 --- a/main.go +++ b/main.go @@ -33,6 +33,8 @@ import ( operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" "github.com/operator-framework/operator-controller/controllers" + "github.com/operator-framework/operator-controller/internal/resolution" + rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" //+kubebuilder:scaffold:imports ) @@ -45,6 +47,7 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(operatorsv1alpha1.AddToScheme(scheme)) + utilruntime.Must(rukpakv1alpha1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } @@ -89,10 +92,11 @@ func main() { os.Exit(1) } - if err = (&controllers.OperatorReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { + if err = controllers.NewOperatorReconciler( + mgr.GetClient(), + mgr.GetScheme(), + resolution.NewOperatorResolver(mgr.GetClient(), resolution.HardcodedEntitySource), + ).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Operator") os.Exit(1) } diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index 428c0b25f..15b98a628 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -12,6 +12,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" operatorv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" + rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" ) var ( @@ -33,6 +34,9 @@ var _ = BeforeSuite(func() { err := operatorv1alpha1.AddToScheme(scheme) Expect(err).To(Not(HaveOccurred())) + err = rukpakv1alpha1.AddToScheme(scheme) + Expect(err).To(Not(HaveOccurred())) + c, err = client.New(cfg, client.Options{Scheme: scheme}) Expect(err).To(Not(HaveOccurred())) }) diff --git a/test/e2e/install_test.go b/test/e2e/install_test.go index 260a4f454..51fe780d4 100644 --- a/test/e2e/install_test.go +++ b/test/e2e/install_test.go @@ -12,6 +12,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" operatorv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" + rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" ) const ( @@ -22,11 +23,12 @@ const ( var _ = Describe("Operator Install", func() { It("resolves the specified package with correct bundle path", func() { var ( - ctx context.Context = context.Background() - pkgName string = "prometheus" - operator *operatorv1alpha1.Operator = &operatorv1alpha1.Operator{ + ctx context.Context = context.Background() + pkgName string = "prometheus" + operatorName string = fmt.Sprintf("operator-%s", rand.String(8)) + operator *operatorv1alpha1.Operator = &operatorv1alpha1.Operator{ ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("operator-%s", rand.String(8)), + Name: operatorName, }, Spec: operatorv1alpha1.OperatorSpec{ PackageName: pkgName, @@ -48,6 +50,16 @@ var _ = Describe("Operator Install", func() { g.Expect(operator.Status.Conditions[0].Message).To(Equal("resolution was successful")) }).WithTimeout(defaultTimeout).WithPolling(defaultPoll).Should(Succeed()) + By("eventually installing the package successfully") + Eventually(func(g Gomega) { + bd := rukpakv1alpha1.BundleDeployment{} + err = c.Get(ctx, types.NamespacedName{Name: operatorName}, &bd) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(len(bd.Status.Conditions)).To(Equal(2)) + g.Expect(bd.Status.Conditions[0].Reason).To(Equal("UnpackSuccessful")) + g.Expect(bd.Status.Conditions[1].Reason).To(Equal("InstallationSucceeded")) + }).WithTimeout(defaultTimeout).WithPolling(defaultPoll).Should(Succeed()) + By("deleting the Operator resource") err = c.Delete(ctx, operator) Expect(err).ToNot(HaveOccurred()) diff --git a/testdata/crds/core.rukpak.io_bundledeployments.yaml b/testdata/crds/core.rukpak.io_bundledeployments.yaml new file mode 100644 index 000000000..534291c57 --- /dev/null +++ b/testdata/crds/core.rukpak.io_bundledeployments.yaml @@ -0,0 +1,368 @@ +## TODO dfranz: remove this file and add a crds package in rukpak so we can grab it from that repo instead of having two copies +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.9.0 + creationTimestamp: null + name: bundledeployments.core.rukpak.io +spec: + group: core.rukpak.io + names: + kind: BundleDeployment + listKind: BundleDeploymentList + plural: bundledeployments + shortNames: + - bd + - bds + singular: bundledeployment + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.activeBundle + name: Active Bundle + type: string + - jsonPath: .status.conditions[?(.type=="Installed")].reason + name: Install State + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .spec.provisionerClassName + name: Provisioner + priority: 1 + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: BundleDeployment is the Schema for the bundledeployments API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BundleDeploymentSpec defines the desired state of BundleDeployment + properties: + config: + description: Config is provisioner specific configurations + type: object + x-kubernetes-preserve-unknown-fields: true + provisionerClassName: + description: ProvisionerClassName sets the name of the provisioner + that should reconcile this BundleDeployment. + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + template: + description: Template describes the generated Bundle that this deployment + will manage. + properties: + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + description: 'Specification of the desired behavior of the Bundle. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status' + properties: + provisionerClassName: + description: ProvisionerClassName sets the name of the provisioner + that should reconcile this BundleDeployment. + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + source: + description: Source defines the configuration for the underlying + Bundle content. + properties: + git: + description: Git is the git repository that backs the + content of this Bundle. + properties: + auth: + description: Auth configures the authorization method + if necessary. + properties: + insecureSkipVerify: + description: InsecureSkipVerify controls whether + a client verifies the server's certificate chain + and host name. If InsecureSkipVerify is true, + the clone operation will accept any certificate + presented by the server and any host name in + that certificate. In this mode, TLS is susceptible + to machine-in-the-middle attacks unless custom + verification is used. This should be used only + for testing. + type: boolean + secret: + description: Secret contains reference to the + secret that has authorization information and + is in the namespace that the provisioner is + deployed. The secret is expected to contain + `data.username` and `data.password` for the + username and password, respectively for http(s) + scheme. Refer to https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret + For the ssh authorization of the GitSource, + the secret is expected to contain `data.ssh-privatekey` + and `data.ssh-knownhosts` for the ssh privatekey + and the host entry in the known_hosts file respectively. + Refer to https://kubernetes.io/docs/concepts/configuration/secret/#ssh-authentication-secrets + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + type: object + directory: + description: Directory refers to the location of the + bundle within the git repository. Directory is optional + and if not set defaults to ./manifests. + type: string + ref: + description: Ref configures the git source to clone + a specific branch, tag, or commit from the specified + repo. Ref is required, and exactly one field within + Ref is required. Setting more than one field or + zero fields will result in an error. + properties: + branch: + description: Branch refers to the branch to checkout + from the repository. The Branch should contain + the bundle manifests in the specified directory. + type: string + commit: + description: Commit refers to the commit to checkout + from the repository. The Commit should contain + the bundle manifests in the specified directory. + type: string + tag: + description: Tag refers to the tag to checkout + from the repository. The Tag should contain + the bundle manifests in the specified directory. + type: string + type: object + repository: + description: Repository is a URL link to the git repository + containing the bundle. Repository is required and + the URL should be parsable by a standard git tool. + type: string + required: + - ref + - repository + type: object + http: + description: HTTP is the remote location that backs the + content of this Bundle. + properties: + auth: + description: Auth configures the authorization method + if necessary. + properties: + insecureSkipVerify: + description: InsecureSkipVerify controls whether + a client verifies the server's certificate chain + and host name. If InsecureSkipVerify is true, + the clone operation will accept any certificate + presented by the server and any host name in + that certificate. In this mode, TLS is susceptible + to machine-in-the-middle attacks unless custom + verification is used. This should be used only + for testing. + type: boolean + secret: + description: Secret contains reference to the + secret that has authorization information and + is in the namespace that the provisioner is + deployed. The secret is expected to contain + `data.username` and `data.password` for the + username and password, respectively for http(s) + scheme. Refer to https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret + For the ssh authorization of the GitSource, + the secret is expected to contain `data.ssh-privatekey` + and `data.ssh-knownhosts` for the ssh privatekey + and the host entry in the known_hosts file respectively. + Refer to https://kubernetes.io/docs/concepts/configuration/secret/#ssh-authentication-secrets + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + type: object + type: object + url: + description: URL is where the bundle contents is. + type: string + required: + - url + type: object + image: + description: Image is the bundle image that backs the + content of this bundle. + properties: + pullSecret: + description: ImagePullSecretName contains the name + of the image pull secret in the namespace that the + provisioner is deployed. + type: string + ref: + description: Ref contains the reference to a container + image containing Bundle contents. + type: string + required: + - ref + type: object + local: + description: Local is a reference to a local object in + the cluster. + properties: + configMap: + properties: + name: + type: string + namespace: + type: string + required: + - name + - namespace + type: object + required: + - configMap + type: object + 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 + required: + - provisionerClassName + - source + type: object + required: + - spec + type: object + required: + - provisionerClassName + - template + type: object + status: + description: BundleDeploymentStatus defines the observed state of BundleDeployment + properties: + activeBundle: + type: string + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + observedGeneration: + format: int64 + type: integer + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {}