From 64cb57be9f7d2dc66079cf7a7791ff4105fa95b5 Mon Sep 17 00:00:00 2001 From: Bryce Palmer Date: Tue, 11 Apr 2023 09:42:27 -0400 Subject: [PATCH 1/3] fix goreleaser/release issues Signed-off-by: Bryce Palmer --- .github/workflows/release.yaml | 3 + .gitignore | 3 + .goreleaser.yml | 17 +++-- Makefile | 8 +- apiserver.Dockerfile | 2 +- cmd/manager/main.go | 134 ++++++++++++++++++++++++++++++++- controller.Dockerfile | 2 +- main.go | 133 -------------------------------- 8 files changed, 157 insertions(+), 145 deletions(-) mode change 120000 => 100644 cmd/manager/main.go delete mode 100644 main.go diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 35b8780d..08a6fbe3 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -51,6 +51,9 @@ jobs: else echo IMAGE_TAG="$(git describe --tags --always)" >> $GITHUB_ENV fi + - name: Create release manifests + run: make quickstart + - name: Run goreleaser run: make release env: diff --git a/.gitignore b/.gitignore index bda386c2..493209ce 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,9 @@ vendor/ bin/ dist/ cover.out +catalogd.yaml +manager +apiserver # apiserver certificates config/certificates \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml index c0c39914..a647d8fc 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -11,7 +11,6 @@ builds: - id: catalogd-controller main: ./cmd/manager/ binary: bin/manager - tags: $GO_BUILD_TAGS goos: - linux goarch: @@ -19,12 +18,9 @@ builds: - arm64 - ppc64le - s390x - ldflags: - - -X main.Version={{ .Version }} - id: catalogd-server main: ./cmd/apiserver/ binary: bin/apiserver - tags: $GO_BUILD_TAGS goos: - linux goarch: @@ -32,8 +28,6 @@ builds: - arm64 - ppc64le - s390x - ldflags: - - -X main.Version={{ .Version }} dockers: - image_templates: - "{{ .Env.CONTROLLER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-amd64" @@ -89,4 +83,13 @@ docker_manifests: - "{{ .Env.APISERVER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-ppc64le" - "{{ .Env.APISERVER_IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}-s390x" release: - disable: '{{ ne .Env.ENABLE_RELEASE_PIPELINE "true" }}' \ No newline at end of file + disable: '{{ ne .Env.ENABLE_RELEASE_PIPELINE "true" }}' + extra_files: + - glob: 'catalogd.yaml' + header: | + ## Installation + ```bash + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/{{ .Env.CERT_MGR_VERSION }}/cert-manager.yaml + kubectl wait --for=condition=Available --namespace=cert-manager deployment/cert-manager-webhook --timeout=60s + kubectl apply -f https://github.com/operator-framework/catalogd/releases/download/{{ .Tag }}/catalogd.yaml + ``` diff --git a/Makefile b/Makefile index 449cec18..a638a1c2 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ GIT_COMMIT ?= $(shell git rev-parse HEAD) VERSION_FLAGS ?= -ldflags "GitCommit=$(GIT_COMMIT)" GO_BUILD_TAGS ?= upstream +VERSION ?= $(GIT_COMMIT) # Image URL to use all building/pushing controller image targets CONTROLLER_IMG ?= quay.io/operator-framework/catalogd-controller # Image URL to use all building/pushing apiserver image targets @@ -76,11 +77,11 @@ verify: tidy fmt generate ## Verify the current code generation and lint .PHONY: build-controller build-controller: generate fmt vet ## Build manager binary. - CGO_ENABLED=0 GOOS=linux go build -tags $(GO_BUILD_TAGS) $(VERSION_FLAGS) -o bin/manager main.go + CGO_ENABLED=0 GOOS=linux go build -tags $(GO_BUILD_TAGS) $(VERSION_FLAGS) -o manager cmd/manager/main.go .PHONY: build-server build-server: fmt vet ## Build api-server binary. - CGO_ENABLED=0 GOOS=linux go build -tags $(GO_BUILD_TAGS) $(VERSION_FLAGS) -o bin/apiserver cmd/apiserver/main.go + CGO_ENABLED=0 GOOS=linux go build -tags $(GO_BUILD_TAGS) $(VERSION_FLAGS) -o apiserver cmd/apiserver/main.go .PHONY: run run: generate fmt vet ## Run a controller from your host. @@ -155,6 +156,9 @@ export APISERVER_IMAGE_REPO ?= $(SERVER_IMG) export IMAGE_TAG ?= $(IMG_TAG) release: goreleaser ## Runs goreleaser for catalogd. By default, this will run only as a snapshot and will not publish any artifacts unless it is run with different arguments. To override the arguments, run with "GORELEASER_ARGS=...". When run as a github action from a tag, this target will publish a full release. $(GORELEASER) $(GORELEASER_ARGS) + +quickstart: kustomize generate ## Generate the installation release manifests and scripts + kubectl kustomize config/default | sed "s/:devel/:$(VERSION)/g" > catalogd.yaml ################ # Hack / Tools # diff --git a/apiserver.Dockerfile b/apiserver.Dockerfile index 2e21faea..1351124e 100644 --- a/apiserver.Dockerfile +++ b/apiserver.Dockerfile @@ -11,6 +11,6 @@ # targetPort: 8443 FROM gcr.io/distroless/static:latest WORKDIR / -COPY bin/apiserver . +COPY apiserver . ENTRYPOINT ["/apiserver"] \ No newline at end of file diff --git a/cmd/manager/main.go b/cmd/manager/main.go deleted file mode 120000 index f67563dc..00000000 --- a/cmd/manager/main.go +++ /dev/null @@ -1 +0,0 @@ -../../main.go \ No newline at end of file diff --git a/cmd/manager/main.go b/cmd/manager/main.go new file mode 100644 index 00000000..04ad2153 --- /dev/null +++ b/cmd/manager/main.go @@ -0,0 +1,133 @@ +/* +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 main + +import ( + "flag" + "os" + + // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) + // to ensure that exec-entrypoint and run can make use of them. + _ "k8s.io/client-go/plugin/pkg/client/auth" + + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/healthz" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + "github.com/operator-framework/catalogd/pkg/apis/core/v1beta1" + corecontrollers "github.com/operator-framework/catalogd/pkg/controllers/core" + "github.com/operator-framework/catalogd/pkg/profile" + //+kubebuilder:scaffold:imports +) + +var ( + scheme = runtime.NewScheme() + setupLog = ctrl.Log.WithName("setup") +) + +func init() { + utilruntime.Must(clientgoscheme.AddToScheme(scheme)) + + utilruntime.Must(v1beta1.AddToScheme(scheme)) + //+kubebuilder:scaffold:scheme +} + +func main() { + var metricsAddr string + var enableLeaderElection bool + var probeAddr string + var opmImage string + var profiling bool + flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") + flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + flag.BoolVar(&enableLeaderElection, "leader-elect", false, + "Enable leader election for controller manager. "+ + "Enabling this will ensure there is only one active controller manager.") + flag.StringVar(&opmImage, "opm-image", "quay.io/operator-framework/opm:v1.26", "The opm image to use when unpacking catalog images") + opts := zap.Options{ + Development: true, + } + flag.BoolVar(&profiling, "profiling", false, "enable profiling endpoints to allow for using pprof") + opts.BindFlags(flag.CommandLine) + flag.Parse() + + ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ + Scheme: scheme, + MetricsBindAddress: metricsAddr, + Port: 9443, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "catalogd-operator-lock", + }) + if err != nil { + setupLog.Error(err, "unable to start manager") + os.Exit(1) + } + + if err = (&corecontrollers.CatalogSourceReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Cfg: mgr.GetConfig(), + OpmImage: opmImage, + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "CatalogSource") + os.Exit(1) + } + if err = (&corecontrollers.BundleMetadataReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "BundleMetadata") + os.Exit(1) + } + if err = (&corecontrollers.PackageReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "Package") + os.Exit(1) + } + //+kubebuilder:scaffold:builder + + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up health check") + os.Exit(1) + } + if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up ready check") + os.Exit(1) + } + + if profiling { + pprofer := profile.NewPprofer() + if err := pprofer.ConfigureControllerManager(mgr); err != nil { + setupLog.Error(err, "unable to setup pprof configuration") + os.Exit(1) + } + } + + setupLog.Info("starting manager") + if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { + setupLog.Error(err, "problem running manager") + os.Exit(1) + } +} diff --git a/controller.Dockerfile b/controller.Dockerfile index c0dd7f07..6643a5c4 100644 --- a/controller.Dockerfile +++ b/controller.Dockerfile @@ -2,7 +2,7 @@ # Refer to https://github.com/GoogleContainerTools/distroless for more details FROM gcr.io/distroless/static:nonroot WORKDIR / -COPY bin/manager . +COPY manager . USER 65532:65532 ENTRYPOINT ["/manager"] \ No newline at end of file diff --git a/main.go b/main.go deleted file mode 100644 index 04ad2153..00000000 --- a/main.go +++ /dev/null @@ -1,133 +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 main - -import ( - "flag" - "os" - - // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) - // to ensure that exec-entrypoint and run can make use of them. - _ "k8s.io/client-go/plugin/pkg/client/auth" - - "k8s.io/apimachinery/pkg/runtime" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" - clientgoscheme "k8s.io/client-go/kubernetes/scheme" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/healthz" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - - "github.com/operator-framework/catalogd/pkg/apis/core/v1beta1" - corecontrollers "github.com/operator-framework/catalogd/pkg/controllers/core" - "github.com/operator-framework/catalogd/pkg/profile" - //+kubebuilder:scaffold:imports -) - -var ( - scheme = runtime.NewScheme() - setupLog = ctrl.Log.WithName("setup") -) - -func init() { - utilruntime.Must(clientgoscheme.AddToScheme(scheme)) - - utilruntime.Must(v1beta1.AddToScheme(scheme)) - //+kubebuilder:scaffold:scheme -} - -func main() { - var metricsAddr string - var enableLeaderElection bool - var probeAddr string - var opmImage string - var profiling bool - flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") - flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") - flag.BoolVar(&enableLeaderElection, "leader-elect", false, - "Enable leader election for controller manager. "+ - "Enabling this will ensure there is only one active controller manager.") - flag.StringVar(&opmImage, "opm-image", "quay.io/operator-framework/opm:v1.26", "The opm image to use when unpacking catalog images") - opts := zap.Options{ - Development: true, - } - flag.BoolVar(&profiling, "profiling", false, "enable profiling endpoints to allow for using pprof") - opts.BindFlags(flag.CommandLine) - flag.Parse() - - ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) - - mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: metricsAddr, - Port: 9443, - HealthProbeBindAddress: probeAddr, - LeaderElection: enableLeaderElection, - LeaderElectionID: "catalogd-operator-lock", - }) - if err != nil { - setupLog.Error(err, "unable to start manager") - os.Exit(1) - } - - if err = (&corecontrollers.CatalogSourceReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Cfg: mgr.GetConfig(), - OpmImage: opmImage, - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "CatalogSource") - os.Exit(1) - } - if err = (&corecontrollers.BundleMetadataReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "BundleMetadata") - os.Exit(1) - } - if err = (&corecontrollers.PackageReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create controller", "controller", "Package") - os.Exit(1) - } - //+kubebuilder:scaffold:builder - - if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { - setupLog.Error(err, "unable to set up health check") - os.Exit(1) - } - if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { - setupLog.Error(err, "unable to set up ready check") - os.Exit(1) - } - - if profiling { - pprofer := profile.NewPprofer() - if err := pprofer.ConfigureControllerManager(mgr); err != nil { - setupLog.Error(err, "unable to setup pprof configuration") - os.Exit(1) - } - } - - setupLog.Info("starting manager") - if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { - setupLog.Error(err, "problem running manager") - os.Exit(1) - } -} From b4cb75b89ef1c164f69855a4f77de886e3fdfc0d Mon Sep 17 00:00:00 2001 From: Bryce Palmer Date: Tue, 11 Apr 2023 11:35:53 -0400 Subject: [PATCH 2/3] address review comments Signed-off-by: Bryce Palmer --- Makefile | 10 +-- ...d.operatorframework.io_catalogsources.yaml | 79 +++++++++++++++++-- 2 files changed, 77 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index a638a1c2..dcef1b62 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ GIT_COMMIT ?= $(shell git rev-parse HEAD) VERSION_FLAGS ?= -ldflags "GitCommit=$(GIT_COMMIT)" GO_BUILD_TAGS ?= upstream -VERSION ?= $(GIT_COMMIT) +VERSION ?= $(shell git describe --tags --always --dirty) # Image URL to use all building/pushing controller image targets CONTROLLER_IMG ?= quay.io/operator-framework/catalogd-controller # Image URL to use all building/pushing apiserver image targets @@ -77,11 +77,11 @@ verify: tidy fmt generate ## Verify the current code generation and lint .PHONY: build-controller build-controller: generate fmt vet ## Build manager binary. - CGO_ENABLED=0 GOOS=linux go build -tags $(GO_BUILD_TAGS) $(VERSION_FLAGS) -o manager cmd/manager/main.go + CGO_ENABLED=0 GOOS=linux go build -tags $(GO_BUILD_TAGS) $(VERSION_FLAGS) -o bin/manager cmd/manager/main.go .PHONY: build-server build-server: fmt vet ## Build api-server binary. - CGO_ENABLED=0 GOOS=linux go build -tags $(GO_BUILD_TAGS) $(VERSION_FLAGS) -o apiserver cmd/apiserver/main.go + CGO_ENABLED=0 GOOS=linux go build -tags $(GO_BUILD_TAGS) $(VERSION_FLAGS) -o bin/apiserver cmd/apiserver/main.go .PHONY: run run: generate fmt vet ## Run a controller from your host. @@ -89,7 +89,7 @@ run: generate fmt vet ## Run a controller from your host. .PHONY: docker-build-controller docker-build-controller: build-controller test ## Build docker image with the controller manager. - docker build -f controller.Dockerfile -t ${CONTROLLER_IMG}:${IMG_TAG} . + docker build -f controller.Dockerfile -t ${CONTROLLER_IMG}:${IMG_TAG} bin/ .PHONY: docker-push-controller docker-push-controller: ## Push docker image with the controller manager. @@ -97,7 +97,7 @@ docker-push-controller: ## Push docker image with the controller manager. .PHONY: docker-build-server docker-build-server: build-server test ## Build docker image with the apiserver. - docker build -f apiserver.Dockerfile -t ${SERVER_IMG}:${IMG_TAG} . + docker build -f apiserver.Dockerfile -t ${SERVER_IMG}:${IMG_TAG} bin/ .PHONY: docker-push-server docker-push-server: ## Push docker image with the apiserver. diff --git a/config/crd/bases/catalogd.operatorframework.io_catalogsources.yaml b/config/crd/bases/catalogd.operatorframework.io_catalogsources.yaml index 9b5c723f..a3638ddb 100644 --- a/config/crd/bases/catalogd.operatorframework.io_catalogsources.yaml +++ b/config/crd/bases/catalogd.operatorframework.io_catalogsources.yaml @@ -52,14 +52,79 @@ spec: status: description: CatalogSourceStatus defines the observed state of CatalogSource properties: - latestImagePoll: - description: The last time the image has been polled to ensure the - image is up-to-date - format: date-time - type: string - required: - - latestImagePoll + conditions: + description: Conditions store the status conditions of the CatalogSource + instances + 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 type: object type: object served: true storage: true + subresources: + status: {} From 4fdad6d8464646730d3fc8f1091d22c54c536f81 Mon Sep 17 00:00:00 2001 From: Bryce Palmer Date: Tue, 11 Apr 2023 11:36:16 -0400 Subject: [PATCH 3/3] address review comments Signed-off-by: Bryce Palmer --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 493209ce..de319430 100644 --- a/.gitignore +++ b/.gitignore @@ -12,8 +12,7 @@ bin/ dist/ cover.out catalogd.yaml -manager -apiserver + # apiserver certificates config/certificates \ No newline at end of file