From 6b3f66f9d6033a3e3377722bd9cbd0c7cffdc8c0 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 7 Nov 2024 07:43:37 -0500 Subject: [PATCH] operator controller and rework kustomize to support bindata Dockerfile is updated to include new 'operator' binary and bindata directory. Bindata will contain all the CRDs, RBAC, and deployment files needed to deploy all the operators. Add Makefile targets for bindata, and run-operator. Forklift bindata impl from old CNOSP compute_node_operator. Implement new controllers/operator/openstack_controller.go which process files in /bindata. Calling 'make bindata' during a Renovate sync should keep things in sync. Jira: OSPRH-11244 --- .../workflows/build-openstack-operator.yaml | 1 - .pre-commit-config.yaml | 7 + Dockerfile | 4 + Makefile | 36 +- .../operator.openstack.org_openstacks.yaml | 41 +- apis/operator/v1beta1/conditions.go | 46 +++ apis/operator/v1beta1/openstack_types.go | 28 +- .../operator/v1beta1/zz_generated.deepcopy.go | 15 +- cmd/operator/main.go | 7 +- .../operator.openstack.org_openstacks.yaml | 41 +- config/crd/kustomization.yaml | 4 +- config/default/kustomization.yaml | 60 +-- config/default/webhookcainjection_patch.yaml | 14 + config/manager/manager.yaml | 2 +- ...nstack-operator.clusterserviceversion.yaml | 11 + config/operator/delete_crd.yaml | 35 ++ .../controller_operator_config.yaml | 11 + config/operator/deployment/deployment.yaml | 79 ++++ config/operator/deployment/kustomization.yaml | 16 + config/operator/kustomization.yaml | 16 + config/operator/manager_operator_images.yaml | 57 +++ config/operator/managers.yaml | 82 ++++ ...nstack-operator.clusterserviceversion.yaml | 56 +++ config/operator/manifests/kustomization.yaml | 24 ++ config/operator/rabbit.yaml | 44 +++ .../rbac/auth_proxy_client_clusterrole.yaml | 9 + config/operator/rbac/auth_proxy_role.yaml | 17 + .../rbac/auth_proxy_role_binding.yaml | 12 + config/operator/rbac/auth_proxy_service.yaml | 15 + config/operator/rbac/kustomization.yaml | 18 + .../operator/rbac/leader_election_role.yaml | 37 ++ .../rbac/leader_election_role_binding.yaml | 12 + config/operator/rbac/role.yaml | 115 ++++++ config/operator/rbac/role_binding.yaml | 12 + config/operator/rbac/service_account.yaml | 5 + config/rbac/kustomization.yaml | 10 + config/rbac/role.yaml | 26 -- config/samples/kustomization.yaml | 12 +- .../samples/operator_v1beta1_openstack.yaml | 6 +- controllers/operator/openstack_controller.go | 353 +++++++++++++++++- controllers/operator/suite_test.go | 80 ---- dependencies.yaml | 74 +--- go.mod | 2 +- hack/export_operator_related_images.sh | 23 ++ hack/sync-bindata.sh | 174 +++++++++ pkg/operator/bindata/apply.go | 62 +++ pkg/operator/bindata/merge.go | 55 +++ pkg/operator/bindata/render.go | 108 ++++++ renovate.json | 2 +- 49 files changed, 1712 insertions(+), 264 deletions(-) create mode 100644 apis/operator/v1beta1/conditions.go create mode 100644 config/operator/delete_crd.yaml create mode 100644 config/operator/deployment/controller_operator_config.yaml create mode 100644 config/operator/deployment/deployment.yaml create mode 100644 config/operator/deployment/kustomization.yaml create mode 100644 config/operator/kustomization.yaml create mode 100644 config/operator/manager_operator_images.yaml create mode 100644 config/operator/managers.yaml create mode 100644 config/operator/manifests/bases/openstack-operator.clusterserviceversion.yaml create mode 100644 config/operator/manifests/kustomization.yaml create mode 100644 config/operator/rabbit.yaml create mode 100644 config/operator/rbac/auth_proxy_client_clusterrole.yaml create mode 100644 config/operator/rbac/auth_proxy_role.yaml create mode 100644 config/operator/rbac/auth_proxy_role_binding.yaml create mode 100644 config/operator/rbac/auth_proxy_service.yaml create mode 100644 config/operator/rbac/kustomization.yaml create mode 100644 config/operator/rbac/leader_election_role.yaml create mode 100644 config/operator/rbac/leader_election_role_binding.yaml create mode 100644 config/operator/rbac/role.yaml create mode 100644 config/operator/rbac/role_binding.yaml create mode 100644 config/operator/rbac/service_account.yaml delete mode 100644 controllers/operator/suite_test.go create mode 100644 hack/export_operator_related_images.sh create mode 100755 hack/sync-bindata.sh create mode 100644 pkg/operator/bindata/apply.go create mode 100644 pkg/operator/bindata/merge.go create mode 100644 pkg/operator/bindata/render.go diff --git a/.github/workflows/build-openstack-operator.yaml b/.github/workflows/build-openstack-operator.yaml index c6fcf0f3c..4a3547af0 100644 --- a/.github/workflows/build-openstack-operator.yaml +++ b/.github/workflows/build-openstack-operator.yaml @@ -18,7 +18,6 @@ jobs: go_version: 1.21.x operator_sdk_version: 1.31.0 bundle_dockerfile: ./bundle.Dockerfile - catalog_extra_bundles_script: ./hack/pin-bundle-images.sh secrets: IMAGENAMESPACE: ${{ secrets.IMAGENAMESPACE }} QUAY_USERNAME: ${{ secrets.QUAY_USERNAME }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 01b4ed01a..cc719c4dd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,6 +25,12 @@ repos: entry: make args: ['operator-lint'] pass_filenames: false + - id: make-bindata + name: make-bindata + language: system + entry: make + args: ['bindata'] + pass_filenames: false - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 @@ -41,6 +47,7 @@ repos: - id: destroyed-symlinks - id: check-yaml args: [-m] + exclude: '^bindata/operator|^config/operator' - id: check-json - id: detect-private-key - id: end-of-file-fixer diff --git a/Dockerfile b/Dockerfile index 15f279e9b..368c1615e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,8 +26,10 @@ RUN if [ ! -f $CACHITO_ENV_FILE ]; then go mod download ; fi # Build manager RUN if [ -f $CACHITO_ENV_FILE ] ; then source $CACHITO_ENV_FILE ; fi ; env ${GO_BUILD_EXTRA_ENV_ARGS} go build ${GO_BUILD_EXTRA_ARGS} -a -o ${DEST_ROOT}/manager main.go +RUN if [ -f $CACHITO_ENV_FILE ] ; then source $CACHITO_ENV_FILE ; fi ; env ${GO_BUILD_EXTRA_ENV_ARGS} go build ${GO_BUILD_EXTRA_ARGS} -a -o ${DEST_ROOT}/operator cmd/operator/main.go RUN cp -r config/services ${DEST_ROOT}/services +RUN cp -r bindata ${DEST_ROOT}/bindata # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details @@ -65,9 +67,11 @@ WORKDIR / # Install operator binary to WORKDIR COPY --from=builder ${DEST_ROOT}/manager . +COPY --from=builder ${DEST_ROOT}/operator . # Install services COPY --from=builder ${DEST_ROOT}/services ${OPERATOR_SERVICES} +COPY --from=builder ${DEST_ROOT}/bindata /bindata USER $USER_ID diff --git a/Makefile b/Makefile index 213964fb7..ab30777a3 100644 --- a/Makefile +++ b/Makefile @@ -129,15 +129,30 @@ help: ## Display this help. ##@ Development +# (dprince) FIXME: controller-gen crd didn't seem to like multiple paths so I didn't split it. So we can continue using kubebuilder +# I did split out the rbac for both binaries so we can use separate roles .PHONY: manifests manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. - $(CONTROLLER_GEN) rbac:roleName=manager-role crd$(CRDDESC_OVERRIDE) webhook paths="./..." output:crd:artifacts:config=config/crd/bases && \ + mkdir -p config/operator/rbac && \ + $(CONTROLLER_GEN) crd$(CRDDESC_OVERRIDE) output:crd:artifacts:config=config/crd/bases webhook paths="./..." && \ + $(CONTROLLER_GEN) rbac:roleName=manager-role paths="{./apis/client/...,./apis/core/...,./apis/dataplane/...,./controllers/client/...,./controllers/core/...,./controllers/dataplane/...,./pkg/...}" output:dir=config/rbac && \ + $(CONTROLLER_GEN) rbac:roleName=operator-role paths="./controllers/operator/..." paths="./apis/operator/..." output:dir=config/operator/rbac && \ rm -f apis/bases/* && cp -a config/crd/bases apis/ .PHONY: generate generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." +.PHONY: bindata +bindata: ## Build docker image with the manager. + mkdir -p bindata/crds bindata/rbac bindata/operator + $(KUSTOMIZE) build config/crd > bindata/crds/crds.yaml + $(KUSTOMIZE) build config/default > bindata/operator/operator.yaml + cp config/operator/managers.yaml bindata/operator/ + cp config/operator/rabbit.yaml bindata/operator/ + $(KUSTOMIZE) build config/rbac > bindata/rbac/rbac.yaml + /bin/bash hack/sync-bindata.sh + .PHONY: fmt fmt: ## Run go fmt against code. go fmt ./... @@ -205,8 +220,17 @@ run: manifests generate fmt vet ## Run a controller from your host. source hack/export_related_images.sh && \ go run ./main.go -metrics-bind-address ":$(METRICS_PORT)" -health-probe-bind-address ":$(HEALTH_PORT)" +.PHONY: run-operator +run-operator: export METRICS_PORT?=8080 +run-operator: export HEALTH_PORT?=8081 +run-operator: export ENABLE_WEBHOOKS?=false +run-operator: export BASE_BINDATA?=bindata +run-operator: manifests generate fmt vet ## Run a controller from your host. + source hack/export_operator_related_images.sh && \ + go run ./cmd/operator/main.go -metrics-bind-address ":$(METRICS_PORT)" -health-probe-bind-address ":$(HEALTH_PORT)" + .PHONY: docker-build -docker-build: ## Build docker image with the manager. +docker-build: ## Build docker image with the manager. podman build -t ${IMG} . ${DOCKER_BUILD_ARGS} .PHONY: docker-push @@ -271,7 +295,7 @@ GINKGO_TESTS ?= ./tests/... ./apis/client/... ./apis/core/... ./apis/dataplane/. KUTTL ?= $(LOCALBIN)/kubectl-kuttl ## Tool Versions -KUSTOMIZE_VERSION ?= v3.8.7 +KUSTOMIZE_VERSION ?= v5.5.0 #(dprince: bumped to aquire new features like --load-restrictor) CONTROLLER_TOOLS_VERSION ?= v0.11.1 CRD_MARKDOWN_VERSION ?= v0.0.3 KUTTL_VERSION ?= 0.17.0 @@ -339,9 +363,9 @@ endif .PHONY: bundle bundle: build manifests kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files. $(OPERATOR_SDK) generate kustomize manifests -q - cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) - $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) - cp dependencies.yaml ./bundle/metadata + cd config/operator/deployment/ && $(KUSTOMIZE) edit set image controller=$(IMG) + $(KUSTOMIZE) build config/operator --load-restrictor='LoadRestrictionsNone' | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) + #cp dependencies.yaml ./bundle/metadata $(OPERATOR_SDK) bundle validate ./bundle .PHONY: bundle-build diff --git a/apis/bases/operator.openstack.org_openstacks.yaml b/apis/bases/operator.openstack.org_openstacks.yaml index 18cf475dc..cd4bc2838 100644 --- a/apis/bases/operator.openstack.org_openstacks.yaml +++ b/apis/bases/operator.openstack.org_openstacks.yaml @@ -15,7 +15,15 @@ spec: singular: openstack scope: Namespaced versions: - - name: v1beta1 + - additionalPrinterColumns: + - jsonPath: .status.deployedOperatorCount + name: Deployed Operator Count + type: integer + - description: Status + jsonPath: .status.conditions[0].status + name: Status + type: string + name: v1beta1 schema: openAPIV3Schema: properties: @@ -26,11 +34,36 @@ spec: metadata: type: object spec: - properties: - foo: - type: string type: object status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + severity: + type: string + status: + type: string + type: + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + deployedOperatorCount: + type: integer + observedGeneration: + format: int64 + type: integer type: object type: object served: true diff --git a/apis/operator/v1beta1/conditions.go b/apis/operator/v1beta1/conditions.go new file mode 100644 index 000000000..0019582da --- /dev/null +++ b/apis/operator/v1beta1/conditions.go @@ -0,0 +1,46 @@ +/* + +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 v1beta1 + +import ( + condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" +) + +// OpenStack Condition Types used by API objects. +const ( + // OpenStackOperatorReadyCondition Status=True condition which indicates if operators have been deployed + OpenStackOperatorReadyCondition condition.Type = "OpenStackOperatorReadyCondition" +) + +// Common Messages used by Openstack operator +const ( + // + // OpenStackOperator condition messages + // + + // OpenStackOperatorErrorMessage + OpenStackOperatorErrorMessage = "OpenStackOperator error occured %s" + + // OpenStackOperatorReadyInitMessage + OpenStackOperatorReadyInitMessage = "OpenStackOperator not started" + + // OpenStackOperatorReadyRunningMessage + OpenStackOperatorReadyRunningMessage = "OpenStackOperator in progress" + + // OpenStackOperatorReadyMessage + OpenStackOperatorReadyMessage = "OpenStackOperator completed" + +) diff --git a/apis/operator/v1beta1/openstack_types.go b/apis/operator/v1beta1/openstack_types.go index 7459ad7ae..9d9a0860a 100644 --- a/apis/operator/v1beta1/openstack_types.go +++ b/apis/operator/v1beta1/openstack_types.go @@ -17,30 +17,32 @@ limitations under the License. package v1beta1 import ( + condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. - // OpenStackSpec defines the desired state of OpenStack type OpenStackSpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file - - // Foo is an example field of OpenStack. Edit openstack_types.go to remove/update - Foo string `json:"foo,omitempty"` } // OpenStackStatus defines the observed state of OpenStack type OpenStackStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file -} -//+kubebuilder:object:root=true -//+kubebuilder:subresource:status + // +operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors={"urn:alm:descriptor:io.kubernetes.conditions"} + // Conditions + Conditions condition.Conditions `json:"conditions,omitempty" optional:"true"` + + // DeployedOperatorCount - the number of operators deployed + DeployedOperatorCount *int `json:"deployedOperatorCount,omitempty"` + + // ObservedGeneration - the most recent generation observed for this object. + ObservedGeneration int64 `json:"observedGeneration,omitempty"` // no spec yet so maybe we don't need this +} +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Deployed Operator Count",type=integer,JSONPath=`.status.deployedOperatorCount` +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[0].status",description="Status" // OpenStack is the Schema for the openstacks API type OpenStack struct { metav1.TypeMeta `json:",inline"` diff --git a/apis/operator/v1beta1/zz_generated.deepcopy.go b/apis/operator/v1beta1/zz_generated.deepcopy.go index 6357b41e4..8ea973b19 100644 --- a/apis/operator/v1beta1/zz_generated.deepcopy.go +++ b/apis/operator/v1beta1/zz_generated.deepcopy.go @@ -22,6 +22,7 @@ limitations under the License. package v1beta1 import ( + "github.com/openstack-k8s-operators/lib-common/modules/common/condition" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -31,7 +32,7 @@ func (in *OpenStack) DeepCopyInto(out *OpenStack) { out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) out.Spec = in.Spec - out.Status = in.Status + in.Status.DeepCopyInto(&out.Status) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStack. @@ -102,6 +103,18 @@ func (in *OpenStackSpec) DeepCopy() *OpenStackSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenStackStatus) DeepCopyInto(out *OpenStackStatus) { *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make(condition.Conditions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.DeployedOperatorCount != nil { + in, out := &in.DeployedOperatorCount, &out.DeployedOperatorCount + *out = new(int) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackStatus. diff --git a/cmd/operator/main.go b/cmd/operator/main.go index 52c80d04a..e10af1893 100644 --- a/cmd/operator/main.go +++ b/cmd/operator/main.go @@ -44,7 +44,6 @@ import ( operatorv1beta1 "github.com/openstack-k8s-operators/openstack-operator/apis/operator/v1beta1" operatorcontrollers "github.com/openstack-k8s-operators/openstack-operator/controllers/operator" - // +kubebuilder:scaffold:imports ) var ( @@ -55,7 +54,6 @@ var ( func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(operatorv1beta1.AddToScheme(scheme)) - // +kubebuilder:scaffold:scheme } func main() { @@ -96,7 +94,7 @@ func main() { }, HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, - LeaderElectionID: "40ba705e.openstack.org", + LeaderElectionID: "20ca801f.openstack.org", WebhookServer: webhook.NewServer( webhook.Options{ Port: 9443, @@ -147,7 +145,8 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "OpenStack") os.Exit(1) } - // +kubebuilder:scaffold:builder + operatorcontrollers.SetupEnv() + if err := mgr.AddHealthzCheck("healthz", checker); err != nil { setupLog.Error(err, "unable to set up health check") os.Exit(1) diff --git a/config/crd/bases/operator.openstack.org_openstacks.yaml b/config/crd/bases/operator.openstack.org_openstacks.yaml index 18cf475dc..cd4bc2838 100644 --- a/config/crd/bases/operator.openstack.org_openstacks.yaml +++ b/config/crd/bases/operator.openstack.org_openstacks.yaml @@ -15,7 +15,15 @@ spec: singular: openstack scope: Namespaced versions: - - name: v1beta1 + - additionalPrinterColumns: + - jsonPath: .status.deployedOperatorCount + name: Deployed Operator Count + type: integer + - description: Status + jsonPath: .status.conditions[0].status + name: Status + type: string + name: v1beta1 schema: openAPIV3Schema: properties: @@ -26,11 +34,36 @@ spec: metadata: type: object spec: - properties: - foo: - type: string type: object status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + severity: + type: string + status: + type: string + type: + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + deployedOperatorCount: + type: integer + observedGeneration: + format: int64 + type: integer type: object type: object served: true diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index a6b9db9f0..a55279ade 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -8,7 +8,7 @@ resources: - bases/dataplane.openstack.org_openstackdataplanenodesets.yaml - bases/dataplane.openstack.org_openstackdataplaneservices.yaml - bases/dataplane.openstack.org_openstackdataplanedeployments.yaml -- bases/operator.openstack.org_openstacks.yaml +#- bases/operator.openstack.org_openstacks.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -22,7 +22,7 @@ patchesStrategicMerge: # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. # patches here are for enabling the CA injection for each CRD -- patches/cainjection_in_core_openstackcontrolplanes.yaml +#- patches/cainjection_in_core_openstackcontrolplanes.yaml #- patches/cainjection_in_openstackclients.yaml #- patches/cainjection_in_openstackversions.yaml #- patches/cainjection_in_openstacks.yaml diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index ff3b2d7e4..1b9631f48 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -1,5 +1,5 @@ # Adds namespace to all resources. -namespace: openstack-operator-system +namespace: '{{ .OperatorNamespace }}' # Value of this field is prepended to the # names of all resources, e.g. a deployment named @@ -12,9 +12,9 @@ namePrefix: openstack-operator- #commonLabels: # someName: someValue -bases: -- ../crd -- ../rbac +resources: +#- ../crd +#- ../rbac - ../manager # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml @@ -49,29 +49,29 @@ patchesStrategicMerge: # the following config is for teaching kustomize how to do var substitution vars: # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldref: -# fieldpath: metadata.namespace -#- name: CERTIFICATE_NAME -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -#- name: SERVICE_NAMESPACE # namespace of the service -# objref: -# kind: Service -# version: v1 -# name: webhook-service -# fieldref: -# fieldpath: metadata.namespace -#- name: SERVICE_NAME -# objref: -# kind: Service -# version: v1 -# name: webhook-service +- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR + objref: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # this name should match the one in certificate.yaml + fieldref: + fieldpath: metadata.namespace +- name: CERTIFICATE_NAME + objref: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # this name should match the one in certificate.yaml +- name: SERVICE_NAMESPACE # namespace of the service + objref: + kind: Service + version: v1 + name: webhook-service + fieldref: + fieldpath: metadata.namespace +- name: SERVICE_NAME + objref: + kind: Service + version: v1 + name: webhook-service diff --git a/config/default/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml index 81e80999d..6596b12de 100644 --- a/config/default/webhookcainjection_patch.yaml +++ b/config/default/webhookcainjection_patch.yaml @@ -14,3 +14,17 @@ metadata: name: validating-webhook-configuration annotations: cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + labels: + app.kubernetes.io/name: mutatingingwebhookconfiguration + app.kubernetes.io/instance: mutating-webhook-configuration + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: openstack-operator + app.kubernetes.io/part-of: openstack-operator + app.kubernetes.io/managed-by: kustomize + name: mutating-webhook-configuration + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index b5f05ac15..a16168a60 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -73,5 +73,5 @@ spec: requests: cpu: 10m memory: 128Mi - serviceAccountName: controller-manager + serviceAccountName: openstack-operator-controller-manager terminationGracePeriodSeconds: 10 diff --git a/config/manifests/bases/openstack-operator.clusterserviceversion.yaml b/config/manifests/bases/openstack-operator.clusterserviceversion.yaml index f44cee10a..6597332e6 100644 --- a/config/manifests/bases/openstack-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/openstack-operator.clusterserviceversion.yaml @@ -606,6 +606,17 @@ spec: x-descriptors: - urn:alm:descriptor:io.kubernetes.conditions version: v1beta1 + - description: OpenStack is the Schema for the openstacks API + displayName: Open Stack + kind: OpenStack + name: openstacks.operator.openstack.org + statusDescriptors: + - description: Conditions + displayName: Conditions + path: conditions + x-descriptors: + - urn:alm:descriptor:io.kubernetes.conditions + version: v1beta1 - description: OpenStackVersion is the Schema for the openstackversionupdates API displayName: OpenStack Version diff --git a/config/operator/delete_crd.yaml b/config/operator/delete_crd.yaml new file mode 100644 index 000000000..a7299553b --- /dev/null +++ b/config/operator/delete_crd.yaml @@ -0,0 +1,35 @@ +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: openstackcontrolplanes.core.openstack.org +--- +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: openstackversions.core.openstack.org +--- +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: openstackclients.client.openstack.org +--- +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: openstackdataplanenodesets.dataplane.openstack.org +--- +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: openstackdataplaneservices.dataplane.openstack.org +--- +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: openstackdataplanedeployments.dataplane.openstack.org diff --git a/config/operator/deployment/controller_operator_config.yaml b/config/operator/deployment/controller_operator_config.yaml new file mode 100644 index 000000000..c4e68c29d --- /dev/null +++ b/config/operator/deployment/controller_operator_config.yaml @@ -0,0 +1,11 @@ +apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 +kind: ControllerManagerConfig +health: + healthProbeBindAddress: :8081 +metrics: + bindAddress: 127.0.0.1:8080 +webhook: + port: 9443 +leaderElection: + leaderElect: true + resourceName: 20ca801f.openstack.org diff --git a/config/operator/deployment/deployment.yaml b/config/operator/deployment/deployment.yaml new file mode 100644 index 000000000..a7e04bb66 --- /dev/null +++ b/config/operator/deployment/deployment.yaml @@ -0,0 +1,79 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: controller-operator + openstack.org/operator-name: openstack + name: system +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-operator + namespace: system + labels: + control-plane: controller-operator + openstack.org/operator-name: openstack +spec: + selector: + matchLabels: + openstack.org/operator-name: openstack + replicas: 1 + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: operator + labels: + control-plane: controller-operator + openstack.org/operator-name: openstack + spec: + securityContext: + runAsNonRoot: true + # TODO(user): For common cases that do not require escalating privileges + # it is recommended to ensure that all your Pods/Containers are restrictive. + # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted + # Please uncomment the following code if your project does NOT have to work on old Kubernetes + # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). + # seccompProfile: + # type: RuntimeDefault + containers: + - command: + - /operator + args: + - --leader-elect + env: + - name: ENABLE_WEBHOOKS + value: false + - name: OPENSTACK_RELEASE_VERSION + value: 0.0.1 + image: controller:latest + name: operator + securityContext: + allowPrivilegeEscalation: false + # TODO(user): uncomment for common cases that do not require escalating privileges + # capabilities: + # drop: + # - "ALL" + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + # TODO(user): Configure the resources accordingly based on the project requirements. + # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 10m + memory: 128Mi + serviceAccountName: controller-operator + terminationGracePeriodSeconds: 10 diff --git a/config/operator/deployment/kustomization.yaml b/config/operator/deployment/kustomization.yaml new file mode 100644 index 000000000..6ca4c7dc7 --- /dev/null +++ b/config/operator/deployment/kustomization.yaml @@ -0,0 +1,16 @@ +resources: +- deployment.yaml + +generatorOptions: + disableNameSuffixHash: true + +configMapGenerator: +- files: + - controller_operator_config.yaml + name: operator-config +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +images: +- name: controller + newName: quay.io/openstack-k8s-operators/openstack-operator + newTag: latest diff --git a/config/operator/kustomization.yaml b/config/operator/kustomization.yaml new file mode 100644 index 000000000..437691031 --- /dev/null +++ b/config/operator/kustomization.yaml @@ -0,0 +1,16 @@ +resources: +- ../crd/bases/operator.openstack.org_openstacks.yaml + +bases: +#- ../crd/ +- manifests +- rbac +- deployment +- ../certmanager/ +- ../samples/ + +patchesStrategicMerge: +#- delete_crd.yaml + +# Injects our custom images (ENV variable settings) +- manager_operator_images.yaml diff --git a/config/operator/manager_operator_images.yaml b/config/operator/manager_operator_images.yaml new file mode 100644 index 000000000..ded483abb --- /dev/null +++ b/config/operator/manager_operator_images.yaml @@ -0,0 +1,57 @@ +# NOTE: this file is automatically generated by hack/sync-bindata.sh! +# +# This patch inject custom ENV settings to the manager container +# Used to set our operator locations +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-operator + namespace: system +spec: + template: + spec: + containers: + - name: operator + env: + - name: RELATED_IMAGE_BARBICAN_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/barbican-operator@sha256:f6c85e80f70b7b7334d74fe6d9f86a9b2a5006566db9a6024d0f8966c80167cf + - name: RELATED_IMAGE_CINDER_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/cinder-operator@sha256:23972d5bc7d91b5ce22a12d7d7f8cba5c68c8eade0bf7c0d27c1cb5be7168468 + - name: RELATED_IMAGE_DESIGNATE_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/designate-operator@sha256:98b7d7960bdfceec9b682fb48401b332a360eb2047d3e745553c81a9c3c8e1fd + - name: RELATED_IMAGE_GLANCE_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/glance-operator@sha256:9838dad960de475da993d98b8d5d543ee8f0030efc9f47b4a534ab90cc098556 + - name: RELATED_IMAGE_HEAT_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/heat-operator@sha256:59fdb9653bd85003cadd7a05161a665bda2ecb77a464bf30fc73064fd13519a5 + - name: RELATED_IMAGE_HORIZON_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/horizon-operator@sha256:6eabb8c57ce9de3d1ba9f4748bd36c5bbd36c8acb223375211b95ac9904e4e2a + - name: RELATED_IMAGE_INFRA_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/infra-operator@sha256:a7f2d7883d811d2dea6bbb20f215def498afbb0c428508b54ca2792a86d68bdd + - name: RELATED_IMAGE_IRONIC_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/ironic-operator@sha256:c26aee3592941c2ea62834d0a03f471d95ef777ae339b26bc5115a384aa48b3a + - name: RELATED_IMAGE_KEYSTONE_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/keystone-operator@sha256:d8c3c098edcb972bcee5b944f8182113951d3435aabf5794c02ff39da1d36bba + - name: RELATED_IMAGE_MANILA_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/manila-operator@sha256:07fb8c80d9648b5c1f2f0c47855542861374c214b9df9df27906b736ccfa79fc + - name: RELATED_IMAGE_MARIADB_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/mariadb-operator@sha256:4e539d5414535f03c274051013b304339741e19f797632a39861ba2309b3518a + - name: RELATED_IMAGE_NEUTRON_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/neutron-operator@sha256:bf373ff7eb87a3b587b10ef6b2b276ff8d5c5166772f3c09233e735d6ac308f5 + - name: RELATED_IMAGE_NOVA_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/nova-operator@sha256:468f90dcdbc174cc789dde192493bb170fa18f688c8af5a97c2a81000e7bb6bd + - name: RELATED_IMAGE_OCTAVIA_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/octavia-operator@sha256:b376450aa86e083e2a9b93b4af6b6efd6978451187990d5d21ac967e5ef0ef8c + - name: RELATED_IMAGE_OPENSTACK_BAREMETAL_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/openstack-baremetal-operator@sha256:fd552ef3c74923dc69f7fc5ce44f1a5de91bb8e85839f0c4b48387f769e79820 + - name: RELATED_IMAGE_OVN_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/ovn-operator@sha256:b900bb87fef70e4c6eded20fc4be5a595cfe3d4b3ebacc88af7dff2af29991a5 + - name: RELATED_IMAGE_PLACEMENT_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/placement-operator@sha256:70f80e0f966c61504a6d64dd3d2937ef7d7b17a65e9c1c9501a13abfb535a5b7 + - name: RELATED_IMAGE_RABBITMQ_CLUSTER_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/rabbitmq-cluster-operator@sha256:225524223bf2a7f3a4ce95958fc9ca6fdab02745fb70374e8ff5bf1ddaceda4b + - name: RELATED_IMAGE_SWIFT_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/swift-operator@sha256:0c7b99f5d18487c3a3c834fd099fd32a9fbd595a8bfb0dc401390088dbe07662 + - name: RELATED_IMAGE_TELEMETRY_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/telemetry-operator@sha256:b18442d853a996d3cdde52944815c722861e7ea2ae87a75c6396b606ee571e1d + - name: RELATED_IMAGE_TEST_OPERATOR_MANAGER_IMAGE_URL + value: quay.io/openstack-k8s-operators/test-operator@sha256:1840e87b584328ad53cde0635d28550d2f75a27995b8bc2c9419bd2083614b04 diff --git a/config/operator/managers.yaml b/config/operator/managers.yaml new file mode 100644 index 000000000..d416bfd3f --- /dev/null +++ b/config/operator/managers.yaml @@ -0,0 +1,82 @@ +{{ $namespace := .OperatorNamespace }} +{{ range $operatorName, $operatorImage := .OperatorImages }} +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + control-plane: controller-manager + openstack.org/operator-name: {{ $operatorName }} + name: {{ $operatorName }}-operator-controller-manager + namespace: {{ $namespace }} +spec: + replicas: 1 + selector: + matchLabels: + openstack.org/operator-name: {{ $operatorName }} + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + control-plane: controller-manager + openstack.org/operator-name: {{ $operatorName }} + spec: + containers: + - args: + - --health-probe-bind-address=:8081 + - --metrics-bind-address=127.0.0.1:8080 + - --leader-elect + command: + - /manager + env: + - name: ENABLE_WEBHOOKS + value: 'false' + image: {{ $operatorImage }} + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: manager + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 10m + memory: 128Mi + securityContext: + allowPrivilegeEscalation: false + - args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8080/ + - --logtostderr=true + - --v=0 + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.13.0 + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + protocol: TCP + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 5m + memory: 64Mi + securityContext: + allowPrivilegeEscalation: false + securityContext: + runAsNonRoot: true + serviceAccountName: {{ $operatorName }}-operator-controller-manager + terminationGracePeriodSeconds: 10 +--- +{{ end }} diff --git a/config/operator/manifests/bases/openstack-operator.clusterserviceversion.yaml b/config/operator/manifests/bases/openstack-operator.clusterserviceversion.yaml new file mode 100644 index 000000000..81e91c8df --- /dev/null +++ b/config/operator/manifests/bases/openstack-operator.clusterserviceversion.yaml @@ -0,0 +1,56 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: '[]' + capabilities: Seamless Upgrades + features.operators.openshift.io/disconnected: "true" + features.operators.openshift.io/fips-compliant: "true" + features.operators.openshift.io/proxy-aware: "false" + features.operators.openshift.io/tls-profiles: "false" + features.operators.openshift.io/token-auth-aws: "false" + features.operators.openshift.io/token-auth-azure: "false" + features.operators.openshift.io/token-auth-gcp: "false" + operatorframework.io/suggested-namespace: openstack-operators + operatorframework.io/initialization-resource: '{"apiVersion":"operator.openstack.org/v1beta1","kind":"OpenStack","metadata":{"name":"openstack","namespace":"openstack-operators"},"spec":{}}' + operators.operatorframework.io/builder: operator-sdk-v1.31.0 + operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 + name: openstack-operator.v0.0.0 + namespace: placeholder +spec: + apiservicedefinitions: {} + customresourcedefinitions: + owned: + - description: OpenStack is the Schema for the openstacks API + displayName: Open Stack + kind: OpenStack + name: openstacks.operator.openstack.org + version: v1beta1 + description: Install and configure OpenStack + displayName: OpenStack + icon: + - base64data: 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 + mediatype: image/png + install: + spec: + deployments: null + strategy: "" + installModes: + - supported: false + type: OwnNamespace + - supported: false + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: true + type: AllNamespaces + keywords: + - OpenStack + links: + - name: Openstack Operator + url: https://github.com/openstack-k8s-operators/ + maturity: alpha + provider: + name: Red Hat Inc. + url: https://redhat.com/ + version: 0.1.0 diff --git a/config/operator/manifests/kustomization.yaml b/config/operator/manifests/kustomization.yaml new file mode 100644 index 000000000..3e6f72b56 --- /dev/null +++ b/config/operator/manifests/kustomization.yaml @@ -0,0 +1,24 @@ +# These resources constitute the fully configured set of manifests +# used to generate the 'manifests/' directory in a bundle. +resources: +- bases/openstack-operator.clusterserviceversion.yaml + +# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix. +# Do NOT uncomment sections with prefix [CERTMANAGER], as OLM does not support cert-manager. +# These patches remove the unnecessary "cert" volume and its manager container volumeMount. +#patchesJson6902: +#- target: +# group: apps +# version: v1 +# kind: Deployment +# name: controller-manager +# namespace: system +# patch: |- +# # Remove the manager container's "cert" volumeMount, since OLM will create and mount a set of certs. +# # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment. +# - op: remove +# path: /spec/template/spec/containers/1/volumeMounts/0 +# # Remove the "cert" volume, since OLM will create and mount a set of certs. +# # Update the indices in this path if adding or removing volumes in the manager's Deployment. +# - op: remove +# path: /spec/template/spec/volumes/0 diff --git a/config/operator/rabbit.yaml b/config/operator/rabbit.yaml new file mode 100644 index 000000000..f79da0e6c --- /dev/null +++ b/config/operator/rabbit.yaml @@ -0,0 +1,44 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: rabbitmq-operator + app.kubernetes.io/name: rabbitmq-cluster-operator + app.kubernetes.io/part-of: rabbitmq + name: rabbitmq-cluster-operator-manager + namespace: {{ .OperatorNamespace }} +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: rabbitmq-cluster-operator + template: + metadata: + labels: + app.kubernetes.io/component: rabbitmq-operator + app.kubernetes.io/name: rabbitmq-cluster-operator + app.kubernetes.io/part-of: rabbitmq + spec: + containers: + - command: + - /manager + env: + - name: OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: {{ .RabbitmqImage }} + name: operator + ports: + - containerPort: 9782 + name: metrics + protocol: TCP + resources: + limits: + cpu: 200m + memory: 500Mi + requests: + cpu: 5m + memory: 64Mi + serviceAccountName: rabbitmq-cluster-operator-controller-manager + terminationGracePeriodSeconds: 10 diff --git a/config/operator/rbac/auth_proxy_client_clusterrole.yaml b/config/operator/rbac/auth_proxy_client_clusterrole.yaml new file mode 100644 index 000000000..4c35b21a7 --- /dev/null +++ b/config/operator/rbac/auth_proxy_client_clusterrole.yaml @@ -0,0 +1,9 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: metrics-reader-operator +rules: +- nonResourceURLs: + - "/metrics" + verbs: + - get diff --git a/config/operator/rbac/auth_proxy_role.yaml b/config/operator/rbac/auth_proxy_role.yaml new file mode 100644 index 000000000..cfbb8a4b5 --- /dev/null +++ b/config/operator/rbac/auth_proxy_role.yaml @@ -0,0 +1,17 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: proxy-role-operator +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/config/operator/rbac/auth_proxy_role_binding.yaml b/config/operator/rbac/auth_proxy_role_binding.yaml new file mode 100644 index 000000000..440225c75 --- /dev/null +++ b/config/operator/rbac/auth_proxy_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: proxy-rolebinding-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: proxy-role-operator +subjects: +- kind: ServiceAccount + name: controller-operator + namespace: system diff --git a/config/operator/rbac/auth_proxy_service.yaml b/config/operator/rbac/auth_proxy_service.yaml new file mode 100644 index 000000000..36e384520 --- /dev/null +++ b/config/operator/rbac/auth_proxy_service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-operator + name: controller-operator-metrics-service-operator + namespace: system +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: https + selector: + openstack.org/operator-name: openstack-operator diff --git a/config/operator/rbac/kustomization.yaml b/config/operator/rbac/kustomization.yaml new file mode 100644 index 000000000..731832a6a --- /dev/null +++ b/config/operator/rbac/kustomization.yaml @@ -0,0 +1,18 @@ +resources: +# All RBAC will be applied under this service account in +# the deployment namespace. You may comment out this resource +# if your manager will use a service account that exists at +# runtime. Be sure to update RoleBinding and ClusterRoleBinding +# subjects if changing service account names. +- service_account.yaml +- role.yaml +- role_binding.yaml +- leader_election_role.yaml +- leader_election_role_binding.yaml +# Comment the following 4 lines if you want to disable +# the auth proxy (https://github.com/brancz/kube-rbac-proxy) +# which protects your /metrics endpoint. +- auth_proxy_service.yaml +- auth_proxy_role.yaml +- auth_proxy_role_binding.yaml +- auth_proxy_client_clusterrole.yaml diff --git a/config/operator/rbac/leader_election_role.yaml b/config/operator/rbac/leader_election_role.yaml new file mode 100644 index 000000000..78acf677e --- /dev/null +++ b/config/operator/rbac/leader_election_role.yaml @@ -0,0 +1,37 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: leader-election-role-operator +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/config/operator/rbac/leader_election_role_binding.yaml b/config/operator/rbac/leader_election_role_binding.yaml new file mode 100644 index 000000000..80e2f271c --- /dev/null +++ b/config/operator/rbac/leader_election_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: leader-election-rolebinding-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role-operator +subjects: +- kind: ServiceAccount + name: controller-operator + namespace: system diff --git a/config/operator/rbac/role.yaml b/config/operator/rbac/role.yaml new file mode 100644 index 000000000..d865d0b51 --- /dev/null +++ b/config/operator/rbac/role.yaml @@ -0,0 +1,115 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: operator-role +rules: +- apiGroups: + - "" + resources: + - configmaps + - namespaces + - serviceaccounts + verbs: + - '*' +- apiGroups: + - admissionregistration.k8s.io + resources: + - mutatingwebhookconfigurations + - validatingwebhookconfigurations + verbs: + - '*' +- apiGroups: + - apiextensions.k8s.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cert-manager.io + resources: + - certificates + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cert-manager.io + resources: + - issuers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - services + verbs: + - '*' +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - create + - get + - list + - update + - watch +- apiGroups: + - operator.openstack.org + resources: + - openstacks + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - operator.openstack.org + resources: + - openstacks/finalizers + verbs: + - update +- apiGroups: + - operator.openstack.org + resources: + - openstacks/status + verbs: + - get + - patch + - update +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + - clusterroles + - rolebindings + - roles + verbs: + - '*' diff --git a/config/operator/rbac/role_binding.yaml b/config/operator/rbac/role_binding.yaml new file mode 100644 index 000000000..edc1eb232 --- /dev/null +++ b/config/operator/rbac/role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: operator-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: operator-role +subjects: +- kind: ServiceAccount + name: controller-operator + namespace: system diff --git a/config/operator/rbac/service_account.yaml b/config/operator/rbac/service_account.yaml new file mode 100644 index 000000000..72275ca0d --- /dev/null +++ b/config/operator/rbac/service_account.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: controller-operator + namespace: system diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml index 731832a6a..e9c4ef55f 100644 --- a/config/rbac/kustomization.yaml +++ b/config/rbac/kustomization.yaml @@ -1,3 +1,13 @@ +# Adds namespace to all resources. +namespace: '{{ .OperatorNamespace }}' + +# Value of this field is prepended to the +# names of all resources, e.g. a deployment named +# "wordpress" becomes "alices-wordpress". +# Note that it should also match with the prefix (text before '-') of the namespace +# field above. +namePrefix: openstack-operator- + resources: # All RBAC will be applied under this service account in # the deployment namespace. You may comment out this resource diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 479bdd51f..4a072bbcc 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -662,32 +662,6 @@ rules: verbs: - get - list -- apiGroups: - - operator.openstack.org - resources: - - openstacks - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - operator.openstack.org - resources: - - openstacks/finalizers - verbs: - - update -- apiGroups: - - operator.openstack.org - resources: - - openstacks/status - verbs: - - get - - patch - - update - apiGroups: - ovn.openstack.org resources: diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 1dc0a3b7a..138d15b6b 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -3,11 +3,11 @@ # we do not have space for long examples here and want # to guide users to documentation instead resources: -- core_v1beta1_openstackcontrolplane_empty.yaml -- client_v1beta1_openstackclient_empty.yaml -- core_v1beta1_openstackversion_empty.yaml -- dataplane_v1beta1_openstackdataplanenodeset_empty.yaml -- dataplane_v1beta1_openstackdataplaneservice_empty.yaml -- dataplane_v1beta1_openstackdataplanedeployment_empty.yaml +#- core_v1beta1_openstackcontrolplane_empty.yaml +#- client_v1beta1_openstackclient_empty.yaml +#- core_v1beta1_openstackversion_empty.yaml +#- dataplane_v1beta1_openstackdataplanenodeset_empty.yaml +#- dataplane_v1beta1_openstackdataplaneservice_empty.yaml +#- dataplane_v1beta1_openstackdataplanedeployment_empty.yaml - operator_v1beta1_openstack.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/config/samples/operator_v1beta1_openstack.yaml b/config/samples/operator_v1beta1_openstack.yaml index 4eaf5baa0..3ed688957 100644 --- a/config/samples/operator_v1beta1_openstack.yaml +++ b/config/samples/operator_v1beta1_openstack.yaml @@ -3,10 +3,8 @@ kind: OpenStack metadata: labels: app.kubernetes.io/name: openstack - app.kubernetes.io/instance: openstack-sample + app.kubernetes.io/instance: openstack app.kubernetes.io/part-of: openstack-operator app.kubernetes.io/managed-by: kustomize app.kubernetes.io/created-by: openstack-operator - name: openstack-sample -spec: - # TODO(user): Add fields here + name: openstack diff --git a/controllers/operator/openstack_controller.go b/controllers/operator/openstack_controller.go index 8cb6cbd7c..c1ab48305 100644 --- a/controllers/operator/openstack_controller.go +++ b/controllers/operator/openstack_controller.go @@ -1,5 +1,5 @@ /* -Copyright 2022. +Copyright 2024. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -18,14 +18,35 @@ package operator import ( "context" + "fmt" + "os" + "path/filepath" + "sort" + "strings" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "github.com/go-logr/logr" + condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" + "github.com/openstack-k8s-operators/lib-common/modules/common/helper" + "github.com/openstack-k8s-operators/lib-common/modules/common/util" operatorv1beta1 "github.com/openstack-k8s-operators/openstack-operator/apis/operator/v1beta1" + "github.com/openstack-k8s-operators/openstack-operator/pkg/operator/bindata" + "github.com/pkg/errors" + appsv1 "k8s.io/api/apps/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/log" +) + +const ( + OperatorCount = 22 // like wow! ) // OpenStackReconciler reconciles a OpenStack object @@ -35,30 +56,344 @@ type OpenStackReconciler struct { Kclient kubernetes.Interface } +// GetLog returns a logger object with a prefix of "controller.name" and aditional controller context fields +func (r *OpenStackReconciler) GetLogger(ctx context.Context) logr.Logger { + return log.FromContext(ctx).WithName("Controllers").WithName("OpenStackControlPlane") +} + +var ( + envRelatedOperatorImages (map[string]*string) // operatorName -> image + rabbitmqImage string +) + +// SetupEnv - +func SetupEnv() { + envRelatedOperatorImages = make(map[string]*string) + for _, name := range os.Environ() { + envArr := strings.Split(name, "=") + + if strings.HasSuffix(envArr[0], "_OPERATOR_MANAGER_IMAGE_URL") { + operatorName := strings.TrimPrefix(envArr[0], "RELATED_IMAGE_") + operatorName = strings.TrimSuffix(operatorName, "_OPERATOR_MANAGER_IMAGE_URL") + operatorName = strings.ToLower(operatorName) + operatorName = strings.ReplaceAll(operatorName, "_", "-") + // rabbitmq-cluster is a special case with an alternate deployment template + if operatorName == "rabbitmq-cluster" { + rabbitmqImage = envArr[1] + } else { + envRelatedOperatorImages[operatorName] = &envArr[1] + } + log.Log.Info("Found operator related image", "operator", operatorName, "image", envArr[1]) + } + } +} + //+kubebuilder:rbac:groups=operator.openstack.org,resources=openstacks,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=operator.openstack.org,resources=openstacks/status,verbs=get;update;patch //+kubebuilder:rbac:groups=operator.openstack.org,resources=openstacks/finalizers,verbs=update +// +kubebuilder:rbac:groups=admissionregistration.k8s.io,resources=mutatingwebhookconfigurations;validatingwebhookconfigurations,verbs="*" +// +kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=clusterroles;clusterrolebindings;rolebindings;roles,verbs="*" +// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources="*",verbs="*" +// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete; +// +kubebuilder:rbac:groups="",resources=serviceaccounts;configmaps;namespaces,verbs="*" +// +kubebuilder:rbac:groups=core,resources=services,verbs="*"; +// +kubebuilder:rbac:groups=cert-manager.io,resources=issuers,verbs=get;list;watch;create;update;patch;delete; +// +kubebuilder:rbac:groups=cert-manager.io,resources=certificates,verbs=get;list;watch;create;update;patch;delete; +// +kubebuilder:rbac:groups="monitoring.coreos.com",resources=servicemonitors,verbs=list;get;watch;update;create // 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 -// the OpenStack object against the actual cluster state, and then -// perform operations to make the cluster state reflect the state specified by -// the user. // // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.14.1/pkg/reconcile -func (r *OpenStackReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - _ = log.FromContext(ctx) +func (r *OpenStackReconciler) Reconcile(ctx context.Context, req ctrl.Request) (result ctrl.Result, _err error) { + Log := r.GetLogger(ctx) + + // Fetch the OpenStack instance + instanceList := &operatorv1beta1.OpenStackList{} + err := r.Client.List(ctx, instanceList, &client.ListOptions{}) + if err != nil { + return ctrl.Result{}, errors.Wrap(err, "failed listing all OpenStack instances") + } + instance := &operatorv1beta1.OpenStack{} + err = r.Client.Get(ctx, req.NamespacedName, instance) + if err != nil { + if apierrors.IsNotFound(err) { + // Request object not found, could have been deleted after reconcile req. + // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. + // Return and don't requeue + return ctrl.Result{}, nil + } + // Error reading the object - requeue the req. + return ctrl.Result{}, err + } + + versionHelper, err := helper.NewHelper( + instance, + r.Client, + r.Kclient, + r.Scheme, + Log, + ) + if err != nil { + Log.Error(err, "unable to create helper") + return ctrl.Result{}, err + } - // TODO(user): your logic here + isNewInstance := instance.Status.Conditions == nil + if isNewInstance { + instance.Status.Conditions = condition.Conditions{} + } + // Save a copy of the condtions so that we can restore the LastTransitionTime + // when a condition's state doesn't change. + savedConditions := instance.Status.Conditions.DeepCopy() + + // Always patch the instance status when exiting this function so we can persist any changes. + defer func() { + // update the Ready condition based on the sub conditions + if instance.Status.Conditions.AllSubConditionIsTrue() { + instance.Status.Conditions.MarkTrue( + condition.ReadyCondition, condition.ReadyMessage) + } else { + // something is not ready so reset the Ready condition + instance.Status.Conditions.MarkUnknown( + condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage) + // and recalculate it based on the state of the rest of the conditions + instance.Status.Conditions.Set( + instance.Status.Conditions.Mirror(condition.ReadyCondition)) + } + + condition.RestoreLastTransitionTimes( + &instance.Status.Conditions, savedConditions) + + err := versionHelper.PatchInstance(ctx, instance) + if err != nil { + _err = err + return + } + }() + + cl := condition.CreateList( + condition.UnknownCondition(operatorv1beta1.OpenStackOperatorReadyCondition, condition.InitReason, string(operatorv1beta1.OpenStackOperatorReadyInitMessage)), + ) + instance.Status.Conditions.Init(&cl) + instance.Status.ObservedGeneration = instance.Generation + + instance.Status.Conditions.Set(condition.FalseCondition( + operatorv1beta1.OpenStackOperatorReadyCondition, + condition.RequestedReason, + condition.SeverityInfo, + operatorv1beta1.OpenStackOperatorReadyRunningMessage)) + + // We only want one instance of OpenStack. Ignore anything after that. + if len(instanceList.Items) > 0 { + if len(instanceList.Items) > 1 { + sort.Slice(instanceList.Items, func(i, j int) bool { + return instanceList.Items[j].CreationTimestamp.After(instanceList.Items[i].CreationTimestamp.Time) + }) + } + if instanceList.Items[0].Name != req.Name { + Log.Info("Ignoring OpenStack.operator.openstack.org because one already exists and does not match existing name") + err = r.Client.Delete(ctx, instance, &client.DeleteOptions{}) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + operatorv1beta1.OpenStackOperatorReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + operatorv1beta1.OpenStackOperatorErrorMessage, + err)) + Log.Error(err, "failed to remove OpenStack.operator.openstack.org instance") + } + return ctrl.Result{}, nil + } + } + + // TODO: cleanup obsolete resources here (remove old CSVs, etc) + /* + if err := r.cleanupObsoleteResources(ctx); err != nil { + return ctrl.Result{}, err + } + */ + + if err := r.applyManifests(ctx, instance); err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + operatorv1beta1.OpenStackOperatorReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + operatorv1beta1.OpenStackOperatorErrorMessage, + err)) + return ctrl.Result{}, err + } + + // Check if all deployments are running + deploymentsRunning, err := r.countDeployments(ctx, instance) + instance.Status.DeployedOperatorCount = &deploymentsRunning + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + operatorv1beta1.OpenStackOperatorReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + operatorv1beta1.OpenStackOperatorErrorMessage, + err)) + return ctrl.Result{}, err + } + if deploymentsRunning < OperatorCount { + Log.Info("Waiting for all deployments to be running", "current", deploymentsRunning, "expected", OperatorCount) + return ctrl.Result{}, nil + } + + instance.Status.Conditions.MarkTrue( + operatorv1beta1.OpenStackOperatorReadyCondition, + operatorv1beta1.OpenStackOperatorReadyMessage) + + Log.Info("Reconcile complete.") return ctrl.Result{}, nil + +} + +// countDeployments - +func (r *OpenStackReconciler) countDeployments(ctx context.Context, instance *operatorv1beta1.OpenStack) (int, error) { + deployments := &appsv1.DeploymentList{} + err := r.Client.List(ctx, deployments, &client.ListOptions{Namespace: instance.Namespace}) + if err != nil { + return 0, err + } + + count := 0 + for _, deployment := range deployments.Items { + if metav1.IsControlledBy(&deployment, instance) { + if deployment.Status.ReadyReplicas > 0 { + count++ + } + } + } + return count, nil +} + +func (r *OpenStackReconciler) applyManifests(ctx context.Context, instance *operatorv1beta1.OpenStack) error { + if err := r.applyCRDs(ctx, instance); err != nil { + log.Log.Error(err, "failed applying CRD manifests") + return err + } + + if err := r.applyRBAC(ctx, instance); err != nil { + log.Log.Error(err, "failed applying RBAC manifests") + return err + } + + if err := r.applyOperator(ctx, instance); err != nil { + log.Log.Error(err, "failed applying Operator manifests") + return err + } + + return nil +} + +func (r *OpenStackReconciler) applyCRDs(ctx context.Context, instance *operatorv1beta1.OpenStack) error { + data := bindata.MakeRenderData() + return r.renderAndApply(ctx, instance, data, "crds", false) +} + +func (r *OpenStackReconciler) applyRBAC(ctx context.Context, instance *operatorv1beta1.OpenStack) error { + data := bindata.MakeRenderData() + data.Data["OperatorNamespace"] = instance.Namespace + return r.renderAndApply(ctx, instance, data, "rbac", false) +} + +func (r *OpenStackReconciler) applyOperator(ctx context.Context, instance *operatorv1beta1.OpenStack) error { + data := bindata.MakeRenderData() + data.Data["OperatorNamespace"] = instance.Namespace + data.Data["OperatorImages"] = envRelatedOperatorImages + data.Data["RabbitmqImage"] = rabbitmqImage + return r.renderAndApply(ctx, instance, data, "operator", true) +} + +func (r *OpenStackReconciler) renderAndApply( + ctx context.Context, + instance *operatorv1beta1.OpenStack, + data bindata.RenderData, + sourceDirectory string, + setControllerReference bool, +) error { + var err error + + bindir := util.GetEnvVar("BASE_BINDATA", "/bindata") + + sourceFullDirectory := filepath.Join(bindir, sourceDirectory) + objs, err := bindata.RenderDir(sourceFullDirectory, &data) + if err != nil { + return errors.Wrapf(err, "failed to render openstack-operator - %s", sourceDirectory) + } + + // If no file found in directory - return error + if len(objs) == 0 { + return fmt.Errorf("no manifests rendered from %s", sourceFullDirectory) + } + + for _, obj := range objs { + // RenderDir seems to add an extra null entry to the list. It appears to be because of the + // nested templates. This just makes sure we don't try to apply an empty obj. + if obj.GetName() == "" { + continue + } + if setControllerReference { + // Set the controller reference. When the CR is removed, it will remove the CRDs as well + if obj.GetNamespace() != "" { + log.Log.Info("Setting controller reference", "object", obj.GetName(), "controller", instance.Name) + err = controllerutil.SetControllerReference(instance, obj, r.Scheme) + if err != nil { + return errors.Wrap(err, "failed to set owner reference") + } + } else { + log.Log.Info("skipping controller reference (cluster scoped)", "object", obj.GetName(), "controller", instance.Name) + } + } + + // Now apply the object + err = bindata.ApplyObject(ctx, r.Client, obj) + if err != nil { + return errors.Wrapf(err, "failed to apply object %v", obj) + } + } + return nil } // SetupWithManager sets up the controller with the Manager. func (r *OpenStackReconciler) SetupWithManager(mgr ctrl.Manager) error { + + deploymentFunc := handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, o client.Object) []reconcile.Request { + Log := r.GetLogger(ctx) + + instanceList := &operatorv1beta1.OpenStackList{} + err := r.Client.List(ctx, instanceList) + if err != nil { + Log.Error(err, "Unable to retrieve OpenStack instances") + return nil + } + + if len(instanceList.Items) == 0 { + return nil + } + + instance := &instanceList.Items[0] + if metav1.IsControlledBy(o, instance) { + Log.Info("Reconcile request for OpenStack instance", "instance", instance.Name) + return []reconcile.Request{ + { + NamespacedName: client.ObjectKey{ + Namespace: instance.Namespace, + Name: instance.Name, + }, + }, + } + } + + return nil + }) + return ctrl.NewControllerManagedBy(mgr). + Watches(&appsv1.Deployment{}, deploymentFunc). For(&operatorv1beta1.OpenStack{}). Complete(r) } diff --git a/controllers/operator/suite_test.go b/controllers/operator/suite_test.go deleted file mode 100644 index 5cef7a757..000000000 --- a/controllers/operator/suite_test.go +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright 2022. - -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 operator - -import ( - "path/filepath" - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/envtest" - logf "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - - operatorv1beta1 "github.com/openstack-k8s-operators/openstack-operator/apis/operator/v1beta1" - //+kubebuilder:scaffold:imports -) - -// These tests use Ginkgo (BDD-style Go testing framework). Refer to -// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. - -var cfg *rest.Config -var k8sClient client.Client -var testEnv *envtest.Environment - -func TestAPIs(t *testing.T) { - RegisterFailHandler(Fail) - - RunSpecs(t, "Controller Suite") -} - -var _ = BeforeSuite(func() { - logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) - - By("bootstrapping test environment") - testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, - ErrorIfCRDPathMissing: true, - } - - var err error - // cfg is defined in this file globally. - cfg, err = testEnv.Start() - Expect(err).NotTo(HaveOccurred()) - Expect(cfg).NotTo(BeNil()) - - err = operatorv1beta1.AddToScheme(scheme.Scheme) - Expect(err).NotTo(HaveOccurred()) - - //+kubebuilder:scaffold:scheme - - k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) - Expect(err).NotTo(HaveOccurred()) - Expect(k8sClient).NotTo(BeNil()) - -}) - -var _ = AfterSuite(func() { - By("tearing down the test environment") - err := testEnv.Stop() - Expect(err).NotTo(HaveOccurred()) -}) diff --git a/dependencies.yaml b/dependencies.yaml index d0b38a66e..4b16a5eec 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,81 +1,13 @@ dependencies: - type: olm.package value: - packageName: rabbitmq-cluster-operator + packageName: openshift-cert-manager-operator version: ">=0.0.0" - type: olm.package value: - packageName: barbican-operator + packageName: metallb-operator version: ">=0.0.0" - type: olm.package value: - packageName: cinder-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: glance-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: horizon-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: heat-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: infra-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: ironic-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: keystone-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: manila-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: mariadb-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: neutron-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: nova-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: openstack-baremetal-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: ovn-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: placement-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: swift-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: telemetry-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: octavia-operator - version: ">=0.0.0" - - type: olm.package - value: - packageName: designate-operator + packageName: cluster-observability-operator version: ">=0.0.0" diff --git a/go.mod b/go.mod index 22fa1b3da..e4c5e9f70 100644 --- a/go.mod +++ b/go.mod @@ -39,6 +39,7 @@ require ( github.com/openstack-k8s-operators/swift-operator/api v0.5.1-0.20241114094619-107d1aac9458 github.com/openstack-k8s-operators/telemetry-operator/api v0.5.1-0.20241111235825-227a5c47eff2 github.com/openstack-k8s-operators/test-operator/api v0.5.1-0.20241114145659-bda006a5385d + github.com/pkg/errors v0.9.1 github.com/rabbitmq/cluster-operator/v2 v2.11.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 @@ -84,7 +85,6 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/openstack-k8s-operators/lib-common/modules/openstack v0.5.1-0.20241104140916-71a0e9d9766d // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.19.0 // indirect github.com/prometheus/client_model v0.6.0 // indirect github.com/prometheus/common v0.53.0 // indirect diff --git a/hack/export_operator_related_images.sh b/hack/export_operator_related_images.sh new file mode 100644 index 000000000..4a9eb1eba --- /dev/null +++ b/hack/export_operator_related_images.sh @@ -0,0 +1,23 @@ +# NOTE: this file is automatically generated by hack/sync-bindata.sh! + +export RELATED_IMAGE_BARBICAN_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/barbican-operator@sha256:f6c85e80f70b7b7334d74fe6d9f86a9b2a5006566db9a6024d0f8966c80167cf +export RELATED_IMAGE_CINDER_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/cinder-operator@sha256:23972d5bc7d91b5ce22a12d7d7f8cba5c68c8eade0bf7c0d27c1cb5be7168468 +export RELATED_IMAGE_DESIGNATE_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/designate-operator@sha256:98b7d7960bdfceec9b682fb48401b332a360eb2047d3e745553c81a9c3c8e1fd +export RELATED_IMAGE_GLANCE_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/glance-operator@sha256:9838dad960de475da993d98b8d5d543ee8f0030efc9f47b4a534ab90cc098556 +export RELATED_IMAGE_HEAT_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/heat-operator@sha256:59fdb9653bd85003cadd7a05161a665bda2ecb77a464bf30fc73064fd13519a5 +export RELATED_IMAGE_HORIZON_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/horizon-operator@sha256:6eabb8c57ce9de3d1ba9f4748bd36c5bbd36c8acb223375211b95ac9904e4e2a +export RELATED_IMAGE_INFRA_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/infra-operator@sha256:a7f2d7883d811d2dea6bbb20f215def498afbb0c428508b54ca2792a86d68bdd +export RELATED_IMAGE_IRONIC_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/ironic-operator@sha256:c26aee3592941c2ea62834d0a03f471d95ef777ae339b26bc5115a384aa48b3a +export RELATED_IMAGE_KEYSTONE_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/keystone-operator@sha256:d8c3c098edcb972bcee5b944f8182113951d3435aabf5794c02ff39da1d36bba +export RELATED_IMAGE_MANILA_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/manila-operator@sha256:07fb8c80d9648b5c1f2f0c47855542861374c214b9df9df27906b736ccfa79fc +export RELATED_IMAGE_MARIADB_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/mariadb-operator@sha256:4e539d5414535f03c274051013b304339741e19f797632a39861ba2309b3518a +export RELATED_IMAGE_NEUTRON_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/neutron-operator@sha256:bf373ff7eb87a3b587b10ef6b2b276ff8d5c5166772f3c09233e735d6ac308f5 +export RELATED_IMAGE_NOVA_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/nova-operator@sha256:468f90dcdbc174cc789dde192493bb170fa18f688c8af5a97c2a81000e7bb6bd +export RELATED_IMAGE_OCTAVIA_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/octavia-operator@sha256:b376450aa86e083e2a9b93b4af6b6efd6978451187990d5d21ac967e5ef0ef8c +export RELATED_IMAGE_OPENSTACK_BAREMETAL_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/openstack-baremetal-operator@sha256:fd552ef3c74923dc69f7fc5ce44f1a5de91bb8e85839f0c4b48387f769e79820 +export RELATED_IMAGE_OVN_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/ovn-operator@sha256:b900bb87fef70e4c6eded20fc4be5a595cfe3d4b3ebacc88af7dff2af29991a5 +export RELATED_IMAGE_PLACEMENT_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/placement-operator@sha256:70f80e0f966c61504a6d64dd3d2937ef7d7b17a65e9c1c9501a13abfb535a5b7 +export RELATED_IMAGE_RABBITMQ_CLUSTER_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/rabbitmq-cluster-operator@sha256:225524223bf2a7f3a4ce95958fc9ca6fdab02745fb70374e8ff5bf1ddaceda4b +export RELATED_IMAGE_SWIFT_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/swift-operator@sha256:0c7b99f5d18487c3a3c834fd099fd32a9fbd595a8bfb0dc401390088dbe07662 +export RELATED_IMAGE_TELEMETRY_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/telemetry-operator@sha256:b18442d853a996d3cdde52944815c722861e7ea2ae87a75c6396b606ee571e1d +export RELATED_IMAGE_TEST_OPERATOR_MANAGER_IMAGE_URL=quay.io/openstack-k8s-operators/test-operator@sha256:1840e87b584328ad53cde0635d28550d2f75a27995b8bc2c9419bd2083614b04 diff --git a/hack/sync-bindata.sh b/hack/sync-bindata.sh new file mode 100755 index 000000000..fc128c84f --- /dev/null +++ b/hack/sync-bindata.sh @@ -0,0 +1,174 @@ +#!/bin/bash + +# extract select data from bundles: +# -CSV's +# -TODO: role data +set -ex + +function extract_bundle { + local IN_DIR=$1 + local OUT_DIR=$2 + for X in $(file ${IN_DIR}/* | grep gzip | cut -f 1 -d ':'); do + tar xvf $X -C ${OUT_DIR}/; + done +} + +OUT_DATA=bindata +EXTRACT_DIR=tmp/bindata + +mkdir -p "$EXTRACT_DIR" +mkdir -p "$OUT_DATA/crds" + +for BUNDLE in $(hack/pin-bundle-images.sh | tr "," " "); do + skopeo copy "docker://$BUNDLE" dir:${EXTRACT_DIR}/tmp; + extract_bundle "${EXTRACT_DIR}/tmp" "${OUT_DATA}/" +done + +cd "$OUT_DATA" +# copy CRDS into crds basedir +grep -l CustomResourceDefinition manifests/* | xargs -I % sh -c 'cp % ./crds/' + +# extract role, clusterRole, and deployment from CSV's +for X in $(ls manifests/*clusterserviceversion.yaml); do + echo $OPERATOR_NAME + OPERATOR_NAME=$(echo $X | sed -e "s|manifests\/\([^\.]*\)\..*|\1|") + LEADER_ELECTION_ROLE_RULES=$(cat $X | yq -r .spec.install.spec.permissions | sed -e 's|- rules:|rules:|' | sed -e 's| ||' | sed -e '/ serviceAccountName.*/d' +) + CLUSTER_ROLE_RULES=$(cat $X | yq -r .spec.install.spec.clusterPermissions| sed -e 's|- rules:|rules:|' | sed -e 's| ||' | sed -e '/ serviceAccountName.*/d' +) + +mkdir -p rbac +cat > rbac/$OPERATOR_NAME-rbac.yaml < ../config/operator/manager_operator_images.yaml < ../hack/export_operator_related_images.sh <> ../config/operator/manager_operator_images.yaml <> ../hack/export_operator_related_images.sh <