diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index d0caf4e..0000000 --- a/.dockerignore +++ /dev/null @@ -1,5 +0,0 @@ -# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file -# Ignore build and test binaries. -bin/ -testbin/ -!bin/manager* diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..a5625ee --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,18 @@ +name: CI + +on: + push: + tags: + - v* + branches: + - master + - main + pull_request: + +permissions: + contents: write + +jobs: + build_validate_test: + uses: openmcp-project/build/.github/workflows/ci.lib.yaml@main + secrets: inherit diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 24e25f9..fdcd53c 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -1,105 +1,15 @@ -name: publish +name: Publish + on: push: tags: - v* workflow_dispatch: - permissions: packages: write -env: - OCI_URL: ghcr.io/openmcp-project - jobs: - release_tag: - name: Release version - runs-on: ubuntu-24.04 - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ssh-key: ${{ secrets.PUSH_KEY }} - fetch-tags: true - fetch-depth: 0 - - - name: Read and validate VERSION - id: version - run: | - VERSION=$(cat VERSION) - if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-dev)?$ ]]; then - echo "Invalid version format in VERSION file: $VERSION" - exit 1 - fi - echo "New version: $VERSION" - echo "version=$VERSION" >> $GITHUB_ENV - - - name: Skip release if version is a dev version - if: contains(env.version, '-dev') - run: | - echo "Skipping development version release: ${{ env.version }}" - echo "SKIP=true" >> $GITHUB_ENV - exit 0 - - - name: Set up Docker - uses: docker/setup-docker-action@v4 - with: - daemon-config: | - { - "features": { - "containerd-snapshotter": true - } - } - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Context for Buildx - id: buildx-context - run: | - docker context create builders - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up Docker Buildx - timeout-minutes: 5 - uses: docker/setup-buildx-action@v2 - with: - version: latest - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version-file: go.mod - - - name: Build the ${{ github.repository }} - run: | - make reviewable - make build-docker-binary - - - name: Build and push Images - run: | - IMG=ghcr.io/openmcp-project/metrics-operator:${{ env.version }} make docker-buildx docker-push - - - name: Package and push helm chart - run: | - make helm-package helm-push - - - name: setup OCM - uses: open-component-model/ocm-setup-action@main - - - name: Create OCM CTF - run: | - ocm add componentversions --create \ - --file ctf component-constructor.yaml \ - --settings settings.yaml -- VERSION=${{ env.version }} - - - name: Push CTF - run: | - ocm transfer ctf --overwrite ./ctf ${{ env.OCI_URL }} + release_publish: + uses: openmcp-project/build/.github/workflows/publish.lib.yaml@main + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a102805..bbdc43f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -11,114 +11,5 @@ permissions: jobs: release_tag: - name: Release version - runs-on: ubuntu-24.04 - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ssh-key: ${{ secrets.PUSH_KEY }} - fetch-tags: true - fetch-depth: 0 - - - name: Read and validate VERSION - id: version - run: | - VERSION=$(cat VERSION) - if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-dev)?$ ]]; then - echo "Invalid version format in VERSION file: $VERSION" - exit 1 - fi - echo "New version: $VERSION" - echo "version=$VERSION" >> $GITHUB_ENV - - - name: Skip release if version is a dev version - if: contains(env.version, '-dev') - run: | - echo "Skipping development version release: ${{ env.version }}" - echo "SKIP=true" >> $GITHUB_ENV - exit 0 - - - name: Check if VERSION is already tagged - id: check_tag - run: | - if git rev-parse "refs/tags/${{ env.version }}" >/dev/null 2>&1; then - echo "Tag ${{ env.version }} already exists. Skipping release." - echo "SKIP=true" >> $GITHUB_ENV - exit 0 - fi - echo "Tag ${{ env.version }} doesn't exists. Proceeding with release." - - - name: Create Git tag - if: ${{ env.SKIP != 'true' }} - run: | - AUTHOR_NAME=$(git log -1 --pretty=format:'%an') - AUTHOR_EMAIL=$(git log -1 --pretty=format:'%ae') - echo "Tagging as $AUTHOR_NAME <$AUTHOR_EMAIL>" - - echo "AUTHOR_NAME=$AUTHOR_NAME" >> $GITHUB_ENV - echo "AUTHOR_EMAIL=$AUTHOR_EMAIL" >> $GITHUB_ENV - - git config user.name "$AUTHOR_NAME" - git config user.email "$AUTHOR_EMAIL" - - git tag -a "${{ env.version }}" -m "Release ${{ env.version }}" - git push origin "${{ env.version }}" - - - name: Build Changelog - id: github_release - - uses: mikepenz/release-changelog-builder-action@v5 - with: - mode: "PR" - configurationJson: | - { - "template": "#{{CHANGELOG}}", - "pr_template": "- #{{TITLE}}: ##{{NUMBER}}", - "categories": [ - { - "title": "## Feature", - "labels": ["feat", "feature"] - }, - { - "title": "## Fix", - "labels": ["fix", "bug"] - }, - { - "title": "## Other", - "labels": [] - } - ], - "label_extractor": [ - { - "pattern": "^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test){1}(\\([\\w\\-\\.]+\\))?(!)?: ([\\w ])+([\\s\\S]*)", - "on_property": "title", - "target": "$1" - } - ] - } - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Create GitHub release - if: ${{ env.SKIP != 'true' }} - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ env.version }} - name: Release ${{ env.version }} - body: ${{steps.github_release.outputs.changelog}} - draft: true - prerelease: false - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Push dev VERSION - if: ${{ env.SKIP != 'true' }} - run: | - echo "${{ env.version }}-dev" > VERSION - make helm-chart - git config user.name "${{ env.AUTHOR_NAME }}" - git config user.email "${{ env.AUTHOR_EMAIL }}" - git add VERSION charts/metrics-operator/Chart.yaml charts/metrics-operator/values.yaml - git commit -m "chore: update VERSION to ${{ env.version }}-dev" - git push origin main + uses: openmcp-project/build/.github/workflows/release.lib.yaml@main + secrets: inherit diff --git a/.github/workflows/reuse-scan.yaml b/.github/workflows/reuse-scan.yaml deleted file mode 100644 index 195930d..0000000 --- a/.github/workflows/reuse-scan.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# This workflow is triggered by the user and runs the REUSE compliance check (reuse lint) on the repository. - -name: REUSE Compliance Check - -on: - pull_request: - workflow_call: {} - push: - branches: - - main - - -jobs: - lint-reuse: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - name: REUSE Compliance Check - uses: fsfe/reuse-action@3ae3c6bdf1257ab19397fab11fd3312144692083 # v4.0.0 diff --git a/.github/workflows/reuse.yaml b/.github/workflows/reuse.yaml new file mode 100644 index 0000000..aa0ba49 --- /dev/null +++ b/.github/workflows/reuse.yaml @@ -0,0 +1,11 @@ +name: REUSE Compliance Check + +on: [push, pull_request] + +permissions: + contents: read + +jobs: + run_reuse: + uses: openmcp-project/build/.github/workflows/reuse.lib.yaml@main + secrets: inherit diff --git a/.github/workflows/reviewable.yaml b/.github/workflows/reviewable.yaml deleted file mode 100644 index c1c4587..0000000 --- a/.github/workflows/reviewable.yaml +++ /dev/null @@ -1,53 +0,0 @@ -# This workflow will run make reviewable and make check-diff as checks - -name: make reviewable && make check-Diff - -on: - pull_request: - workflow_call: {} - push: - tags: - - v* - branches: - - main - -env: - GO_IMPORT_VERSION: 'v0.16.1' - -jobs: - run: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - submodules: true - - - name: Set up Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 - with: - go-version: '1.24' - - - name: Install goimports - run: | - cd /tmp - go install golang.org/x/tools/cmd/goimports@${{ env.GO_IMPORT_VERSION }} - - - name: make reviewable - run: make reviewable - env: - RUNNING_IN_CI: 'true' - - - name: tidy - run: go mod tidy - - - name: sync chart version - run: make helm-chart - - - name: make check-diff - run: make check-diff - - - name: run tests - run: make test - - - name: build - run: make build diff --git a/.github/workflows/validate-pr-content.yaml b/.github/workflows/validate-pr-content.yaml new file mode 100644 index 0000000..52a07c0 --- /dev/null +++ b/.github/workflows/validate-pr-content.yaml @@ -0,0 +1,15 @@ +name: Validate Pull Request Content + +on: + pull_request: + types: + - opened + - edited + +permissions: + contents: read + +jobs: + validate_pr_content: + uses: openmcp-project/build/.github/workflows/validate-pr-content.lib.yaml@main + secrets: inherit \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c0425ec --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "hack/common"] + path = hack/common + url = https://github.com/openmcp-project/build diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..7729fd6 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,49 @@ +version: "2" +run: + allow-parallel-runners: true +linters: + default: none + enable: + - copyloopvar + - dupl + - errcheck + - ginkgolinter + - goconst + - gocyclo + - govet + - ineffassign + - misspell + - nakedret + - prealloc + - revive + - staticcheck + - unconvert + - unparam + - unused + settings: + revive: + rules: + - name: comment-spacings + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - zz_generated.*\.go$ + - tmp/.* + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/Makefile b/Makefile deleted file mode 100644 index 22fef06..0000000 --- a/Makefile +++ /dev/null @@ -1,330 +0,0 @@ -PROJECT_NAME := metrics -PROJECT_FULL_NAME := metrics-operator - -# Image URL to use all building/pushing image targets -IMG_VERSION ?= dev -IMG_BASE ?= $(PROJECT_FULL_NAME) -IMG ?= $(IMG_BASE):$(IMG_VERSION) -# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.27.1 - -# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) -ifeq (,$(shell go env GOBIN)) -GOBIN=$(shell go env GOPATH)/bin -else -GOBIN=$(shell go env GOBIN) -endif - -# CONTAINER_TOOL defines the container tool to be used for building images. -# Be aware that the target commands are only tested with Docker which is -# scaffolded by default. However, you might want to replace it to use other -# tools. (i.e. podman) -CONTAINER_TOOL ?= docker - -# Setting SHELL to bash allows bash commands to be executed by recipes. -# Options are set to exit when a recipe line exits non-zero or a piped command fails. -SHELL = /usr/bin/env bash -o pipefail -.SHELLFLAGS = -ec - -.PHONY: all -all: build - -##@ General -# The help target prints out all targets with their descriptions organized -# beneath their categories. The categories are represented by '##@' and the -# target descriptions by '##'. The awk commands is responsible for reading the -# entire set of makefiles included in this invocation, looking for lines of the -# file as xyz: ## something, and then pretty-format the target and help. Then, -# if there's a line with ##@ something, that gets pretty-printed as a category. -# More info on the usage of ANSI control characters for terminal formatting: -# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters -# More info on the awk command: -# http://linuxcommand.org/lc3_adv_awk.php - -.PHONY: help -help: ## Display this help. - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-25s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) - -#---------------------------------------------------------------------------------------------- -##@ Build Dependencies - -## Location to install dependencies to -LOCALBIN ?= $(shell pwd)/bin -$(LOCALBIN): - mkdir -p $(LOCALBIN) - -## Tool Binaries -KUBECTL ?= kubectl -KIND ?= kind # fix this to use tools -KUSTOMIZE ?= $(LOCALBIN)/kustomize -CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen -ENVTEST ?= $(LOCALBIN)/setup-envtest -GOTESTSUM ?= $(LOCALBIN)/gotestsum -GOLANGCILINT ?= $(LOCALBIN)/golangci-lint -HELM ?= $(LOCALBIN)/helm - -## Tool Versions -KUSTOMIZE_VERSION ?= v5.4.1 -CONTROLLER_TOOLS_VERSION ?= v0.17.2 -GOLANGCILINT_VERSION ?= v2.0.2 - -.PHONY: kustomize -kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. If wrong version is installed, it will be removed before downloading. -$(KUSTOMIZE): $(LOCALBIN) - @if test -x $(LOCALBIN)/kustomize && ! $(LOCALBIN)/kustomize version | grep -q $(KUSTOMIZE_VERSION); then \ - echo "$(LOCALBIN)/kustomize version is not expected $(KUSTOMIZE_VERSION). Removing it before installing."; \ - rm -rf $(LOCALBIN)/kustomize; \ - fi - test -s $(LOCALBIN)/kustomize || GOBIN=$(LOCALBIN) GO111MODULE=on go install sigs.k8s.io/kustomize/kustomize/v5@$(KUSTOMIZE_VERSION) - -$(GOLANGCILINT): $(LOCALBIN) - @if test -x $(LOCALBIN)/golangci-lint && ! $(LOCALBIN)/golangci-lint version | grep -q $(GOLANGCILINT_VERSION); then \ - echo "$(LOCALBIN)/golangci-lint version is not expected $(GOLANGCILINT_VERSION). Removing it before installing."; \ - rm -rf $(LOCALBIN)/golangci-lint; \ - fi - test -s $(LOCALBIN)/golangci-lint || GOBIN=$(LOCALBIN) GO111MODULE=on go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(GOLANGCILINT_VERSION) - -.PHONY: controller-gen -controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. If wrong version is installed, it will be overwritten. -$(CONTROLLER_GEN): $(LOCALBIN) - test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \ - GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) - -.PHONY: envtest -envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. -$(ENVTEST): $(LOCALBIN) - test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest - -.PHONY: envtest-bins -envtest-bins: envtest ## Download envtest binaries - $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) - -.PHONY: gotestsum -gotestsum: $(GOTESTSUM) ## Download gotestsum locally if necessary. -$(GOTESTSUM): $(LOCALBIN) - test -s $(LOCALBIN)/gotestsum || GOBIN=$(LOCALBIN) go install gotest.tools/gotestsum@latest - -.PHONY: lint -lint: $(GOLANGCILINT) ## Run golangci-lint against code. - $(GOLANGCILINT) config verify - $(GOLANGCILINT) run ./... - -.PHONY: lint-fix -lint-fix: $(GOLANGCILINT) ## Run golangci-lint with --fix option to automatically fix issues. - $(GOLANGCILINT) run --fix - -#---------------------------------------------------------------------------------------------- -##@ Code Generation & Formatting -.PHONY: manifests -manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. - $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases - $(CONTROLLER_GEN) crd paths="./..." output:crd:artifacts:config=cmd/embedded/crds - -.PHONY: generate -generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. - $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." - -.PHONY: fmt -fmt: ## Run go fmt against code. - go fmt ./... - -.PHONY: vet -vet: ## Run go vet against code. - go vet ./... - -#---------------------------------------------------------------------------------------------- -##@ Build -.PHONY: build -build: manifests generate fmt vet ## Build manager binary. - go build -o bin/manager cmd/main.go - -.PHONY: build-docker-binary -build-docker-binary: manifests generate fmt vet ## Build manager binary for Docker image. - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o bin/manager-linux.amd64 cmd/main.go - -.PHONY: docker-build -docker-build: test build-docker-binary ## Build docker image with the manager. - $(CONTAINER_TOOL) build -t ${IMG} . - -.PHONY: docker-push -docker-push: ## Push docker image with the manager. - $(CONTAINER_TOOL) push ${IMG} - -# PLATFORMS defines the target platforms for the manager image be build to provide support to multiple -# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: -# - able to use docker buildx . More info: https://docs.docker.com/build/buildx/ -# - be using containerd image store with docker. More Info: https://docs.docker.com/engine/storage/containerd/ -# - have enable BuildKit, More info: https://docs.docker.com/develop/develop-images/build_enhancements/ - -PLATFORMS ?= linux/arm64,linux/amd64 - -.PHONY: docker-buildx -docker-buildx: test - $(CONTAINER_TOOL) buildx build --platform=$(PLATFORMS) --tag $(IMG) --load -f Dockerfile . - -#---------------------------------------------------------------------------------------------- -##@ Deployment -.PHONY: install -install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. - $(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f - - -.PHONY: uninstall -uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. - $(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f - - -.PHONY: deploy -deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. - cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} - $(KUSTOMIZE) build config/default | $(KUBECTL) apply -f - - -.PHONY: undeploy -undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. - $(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f - - -#---------------------------------------------------------------------------------------------- -##@ Local Development Utilities -.PHONY: dev-build -dev-build: docker-build ## Build the Docker image for local development. - @echo "Finished building docker image" ${IMG} - -.PHONY: kind-load-image -kind-load-image: ## Load the Docker image into the local kind cluster for development. - $(KIND) load docker-image ${IMG} --name=$(PROJECT_FULL_NAME)-dev - -.PHONY: kind-cluster -kind-cluster: ## Create a kind cluster for development (no CRDs or resources applied). - $(KIND) create cluster --name=$(PROJECT_FULL_NAME)-dev - -.PHONY: dev-clean -dev-clean: ## Delete the local kind cluster used for development. - $(KIND) delete cluster --name=$(PROJECT_FULL_NAME)-dev - -.PHONY: run -run: ## Run the operator locally (for debugging/development). - ## todo: add flag --debug - OPERATOR_CONFIG_NAMESPACE=metrics-operator-system go run ./cmd/main.go start - -#---------------------------------------------------------------------------------------------- -##@ Testing -.PHONY: test -test: manifests generate fmt vet envtest ## Run tests. - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... -coverprofile cover.out - -#---------------------------------------------------------------------------------------------- -##@ Testing: Run Operator outside of the cluster -.PHONY: dev-local -dev-local: ## Create a local kind cluster and install CRDs for development. - $(KIND) create cluster --name=$(PROJECT_FULL_NAME)-dev - $(MAKE) install - -.PHONY: dev-local-all -dev-local-all: ## Full local dev setup: clean-up, create cluster, install CRDs, Crossplane, namespaces, secrets, and sample metrics. - $(MAKE) dev-clean - $(MAKE) kind-cluster - $(MAKE) install - $(MAKE) crossplane-install - $(MAKE) crossplane-provider-install - $(MAKE) helm-provider-sample - $(MAKE) dev-operator-namespace - $(MAKE) dev-apply-dynatrace-prod-setup - $(MAKE) dev-basic-metric - $(MAKE) dev-managed-metric - -#---------------------------------------------------------------------------------------------- -##@ Testing: Run Operator inside the cluster (production scenario) - -.PHONY: dev-deploy -dev-deploy: manifests kustomize dev-build dev-clean kind-cluster kind-load-image helm-install-local ## Build the Docker image, create a local kind cluster, and deploy the Operator. - -#---------------------------------------------------------------------------------------------- -##@ Example Resources -.PHONY: dev-operator-namespace -dev-operator-namespace: ## Create the operator namespace if it does not exist. - kubectl create namespace metrics-operator-system --dry-run=client -o yaml | kubectl apply -f - - -.PHONY: dev-basic-metric -dev-basic-metric: ## Apply the basic metric example to the cluster. - kubectl apply -f examples/basic_metric.yaml - -.PHONY: dev-managed-metric -dev-managed-metric: ## Apply the managed metric example to the cluster. - kubectl apply -f examples/managed_metric.yaml - -.PHONY: dev-apply-dynatrace-prod-setup -dev-apply-dynatrace-prod-setup: ## Apply Dynatrace production setup example to the cluster. - kubectl apply -f examples/datasink/dynatrace-prod-setup.yaml - -.PHONY: dev-apply-metric-dynatrace-prod -dev-apply-metric-dynatrace-prod: ## Apply metric using Dynatrace production example to the cluster. - kubectl apply -f examples/datasink/metric-using-dynatrace-prod.yaml - -#---------------------------------------------------------------------------------------------- -##@ Helm - -HELM_VERSION ?= v3.18.0 -OCI_REGISTRY ?= ghcr.io/openmcp-project/charts - -$(HELM): $(LOCALBIN) - @if test -x $(LOCALBIN)/helm && ! $(LOCALBIN)/helm version --short | grep -q $(HELM_VERSION); then \ - echo "$(LOCALBIN)/helm version is not expected $(HELM_VERSION). Removing it before installing."; \ - rm -rf $(LOCALBIN)/helm; \ - fi - test -s $(LOCALBIN)/helm || (curl -sSL https://get.helm.sh/helm-$(HELM_VERSION)-$(shell uname | tr '[:upper:]' '[:lower:]')-amd64.tar.gz | tar xz -C /tmp && \ - mv /tmp/$(shell uname | tr '[:upper:]' '[:lower:]')-amd64/helm $(LOCALBIN)/helm && \ - chmod +x $(LOCALBIN)/helm && \ - rm -rf /tmp/$(shell uname | tr '[:upper:]' '[:lower:]')-amd64) - -.PHONY: helm-package -helm-package: $(HELM) helm-chart ## Package the Helm chart. - $(LOCALBIN)/helm package charts/$(PROJECT_FULL_NAME)/ -d ./ --version $(shell cat VERSION) - -.PHONY: helm-push -helm-push: $(HELM) ## Push the Helm chart to the OCI registry. - $(LOCALBIN)/helm push $(PROJECT_FULL_NAME)-$(shell cat VERSION).tgz oci://$(OCI_REGISTRY) - -.PHONY: helm-chart -helm-chart: ## Generate Helm chart files from templates. - OPERATOR_VERSION=$(shell cat VERSION) envsubst < charts/$(PROJECT_FULL_NAME)/Chart.yaml.tpl > charts/$(PROJECT_FULL_NAME)/Chart.yaml - OPERATOR_VERSION=$(shell cat VERSION) envsubst < charts/$(PROJECT_FULL_NAME)/values.yaml.tpl > charts/$(PROJECT_FULL_NAME)/values.yaml - -.PHONY: helm-install-local -helm-install-local: $(HELM) ## Install the Helm chart locally using the Docker image - $(LOCALBIN)/helm upgrade --install $(PROJECT_FULL_NAME) charts/$(PROJECT_FULL_NAME)/ --set image.repository=$(IMG_BASE) --set image.tag=$(IMG_VERSION) --set image.pullPolicy=Never - $(KIND) load docker-image ${IMG} --name=$(PROJECT_FULL_NAME)-dev - -#---------------------------------------------------------------------------------------------- -##@ Crossplane - -# CROSSPLANE_NAMESPACE defines the namespace where Crossplane will be installed. -CROSSPLANE_NAMESPACE ?= crossplane-system - -.PHONY: crossplane-install -crossplane-install: ## Install Crossplane into the cluster. - helm install crossplane crossplane-stable/crossplane --namespace $(CROSSPLANE_NAMESPACE) --create-namespace --wait - -.PHONY: crossplane-provider-install -crossplane-provider-install: ## Install the Helm provider using kubectl - kubectl apply -f examples/crossplane/provider.yaml -n $(CROSSPLANE_NAMESPACE) - kubectl wait --for=condition=Healthy provider/provider-helm --timeout=1m - kubectl apply -f examples/crossplane/provider-config.yaml -n $(CROSSPLANE_NAMESPACE) - -.PHONY: helm-provider-sample -helm-provider-sample: ## Apply the Helm provider sample to the cluster. - kubectl apply -f examples/crossplane/release.yaml -n $(CROSSPLANE_NAMESPACE) - -#---------------------------------------------------------------------------------------------- -##@ Utility -.PHONY: lefthook -lefthook: ## Initializes pre-commit hooks using lefthook https://github.com/evilmartians/lefthook - lefthook install - -.PHONY: check-diff -check-diff: generate manifests ## Ensures that go generate doesn't create a diff - @echo checking clean branch - @if git status --porcelain | grep . ; then echo Uncommitted changes found after running make generate manifests. Please ensure you commit all generated files in this branch after running make generate. && false; else echo branch is clean; fi - -.PHONY: reviewable -reviewable: ## Ensures that the code is reviewable by running generate, lint, and test - @$(MAKE) generate - @$(MAKE) lint - @$(MAKE) test diff --git a/Makefile b/Makefile new file mode 120000 index 0000000..c21893a --- /dev/null +++ b/Makefile @@ -0,0 +1 @@ +./hack/common/Makefile \ No newline at end of file diff --git a/README.md b/README.md index 3ab8ac8..7bcb990 100644 --- a/README.md +++ b/README.md @@ -180,23 +180,30 @@ You’ll need a Kubernetes cluster to run against. You can use [KIND](https://si ### Quickstart -1. Clone the repository and install prerequisites (Go, Docker, kind, kubectl). -2. Configure your data sink by copying the configuration in [`examples/datasink/basic-datasink.yaml`](examples/datasink/basic-datasink.yaml) and modifying it to suit your environment. +This project uses [Taskfile](https://taskfile.dev/) to streamline development activities. Most of the common targets are shared among other OpenMCP components using a shared [build](https://github.com/openmcp-project/build/) repository. The build repository is included as a git submodule. + +This will ensure the submodule is pulled and updated to latest included revision. Some of the common tasks supported are: +1. Clone the repository and install prerequisites (Go, Docker, kind, kubectl, task). +2. Ensure the build submodule is initialized and updated: +```bash +git submodule update --init +``` +3. Configure your data sink by copying the configuration in [`examples/datasink/basic-datasink.yaml`](examples/datasink/basic-datasink.yaml) and modifying it to suit your environment. - For example, if using Dynatrace, create a Kubernetes Secret with your API token and update the DataSink resource accordingly. - The file should be placed and named like this: `examples/datasink/dynatrace-prod-setup.yaml`. (automatically excluded in [.gitignore](.gitignore)) -3. Run `make dev-local-all` to set up a local development environment. -4. Run `make run` to start the Metrics Operator locally. -5. Check your data sink for incoming metrics. +4. Run `task dev:local:all` to set up a local development environment. +5. Run `task run` to start the Metrics Operator locally. +6. Check your data sink for incoming metrics. ### Common Development Tasks -This project uses a Makefile to streamline development tasks. Common targets include: - -- `make dev-local-all` – Set up a local kind cluster with all CRDs, Crossplane, and sample resources. -- `make run` – Run the operator locally for development. -- `make dev-clean` – Delete the local kind cluster. -- `make test` – Run all Go tests. -- `make lint` – Run golangci-lint on the codebase. -- `make manifests generate` – Regenerate CRDs and deepcopy code after API changes. +To get a full list of the supported tasks, you can run the `task` command with no arguments. However, the most commonly used tasks are: + +- `task dev:local:all` – Set up a local kind cluster with all CRDs, Crossplane, and sample resources. +- `task run` – Run the operator locally for development. +- `task dev:clean` – Delete the local kind cluster. +- `task test` – Run all Go tests. +- `task generate` – Regenerate CRDs and deepcopy code after API changes. +- `task validate:lint` – Run golangci-lint on the codebase. ## Usage diff --git a/Taskfile.yaml b/Taskfile.yaml new file mode 100644 index 0000000..dd8a30b --- /dev/null +++ b/Taskfile.yaml @@ -0,0 +1,153 @@ +version: 3 + +vars: + API_DIRS: '{{.ROOT_DIR}}/api/v1alpha1/...' + MANIFEST_OUT: '{{.ROOT_DIR}}/cmd/metrics-operator/embedded/crds' + CODE_DIRS: '{{.ROOT_DIR}}/cmd/... {{.ROOT_DIR}}/internal/... {{.ROOT_DIR}}/api/v1alpha1/...' + COMPONENTS: 'metrics-operator' + REPO_NAME: 'https://github.com/openmcp-project/metrics-operator' + REPO_URL: 'https://github.com/openmcp-project/metrics-operator' + GENERATE_DOCS_INDEX: "false" + ENVTEST_REQUIRED: "true" + # local tasks + KUSTOMIZE_VERSION: "v5.4.1" + CROSSPLANE_NAMESPACE: "crossplane-system" + IGNORE_NOT_FOUND: "false" +includes: + shared: + taskfile: hack/common/Taskfile_controller.yaml + flatten: true + +tasks: + dev:internal:kustomize: + desc: "Download kustomize locally if necessary" + internal: true + cmds: + - test -s {{.ROOT_DIR}}/bin/kustomize || GOBIN={{.ROOT_DIR}}/bin/ GO111MODULE=on go install sigs.k8s.io/kustomize/kustomize/v5@{{.KUSTOMIZE_VERSION}} + + dev:crd:install: + desc: "Install CRDs into the K8s cluster specified in ~/.kube/config" + deps: + - dev:internal:kustomize + - generate + cmds: + # we need to use --load-restrictor=LoadRestrictionsNone because config/crd/bases is a symlink to cmd/metrics-operator/embedded/crds/, and that's considered an external dir, kustomize doesn't like that. + - '{{.ROOT_DIR}}/bin/kustomize build --load-restrictor=LoadRestrictionsNone config/crd | kubectl apply -f -' + + dev:crd:uninstall: + desc: "Uninstall CRDs from the K8s cluster specified in ~/.kube/config" + deps: + - dev:internal:kustomize + - generate + cmds: + - '{{.ROOT_DIR}}/bin/kustomize build config/crd | kubectl delete --ignore-not-found={{.IGNORE_NOT_FOUND}} -f -' + + dev:manager:deploy: + desc: "Deploy controller to the K8s cluster specified in ~/.kube/config" + deps: + - dev:internal:kustomize + - generate + cmds: + - cd {{.ROOT_DIR}}/config/manager && {{.ROOT_DIR}}/bin/kustomize edit set image controller={{.IMG}} + - '{{.ROOT_DIR}}/bin/kustomize build config/default | kubectl apply -f -' + + dev:manager:undeploy: + desc: "Undeploy controller from the K8s cluster specified in ~/.kube/config" + deps: + - dev:internal:kustomize + - generate + cmds: + - '{{.ROOT_DIR}}/bin/kustomize build config/default | kubectl delete --ignore-not-found={{.IGNORE_NOT_FOUND}} -f -' + + dev:kind-cluster:create: + desc: "Create a kind cluster for development (no CRDs or resources applied)" + cmds: + - kind create cluster --name={{.COMPONENTS}}-dev + + dev:kind-cluster:delete: + desc: "Delete the local kind cluster used for development" + aliases: + - dev:clean + cmds: + - kind delete cluster --name={{.COMPONENTS}}-dev + + dev:run: + desc: "Run the operator locally (for debugging/development)" + aliases: + - run + cmds: + - 'OPERATOR_CONFIG_NAMESPACE=metrics-operator-system go run ./cmd/metrics-operator/main.go start' + + dev:test: + desc: "Run tests" + aliases: + - test + deps: + - validate:all + + dev:local:all: + desc: "Create a local kind cluster and install CRDs for development" + cmds: # we use cmds here to trick taskfile into run things in order and wait for each one! + - task dev:kind-cluster:delete + - task dev:kind-cluster:create + - task dev:crd:install + - task dev:crossplane:all + - task dev:operator-namespace + - task dev:basic-metric + - task dev:managed-metric + - test -e {{.ROOT_DIR}}/examples/datasink/dynatrace-prod-setup.yaml && task dev:dynatrace-prod-setup || echo -e '\n\nYou should add your dynatrace configuration here {{.ROOT_DIR}}/examples/datasink/dynatrace-prod-setup.yaml\n\n' + + + dev:operator-namespace: + desc: "Create the operator namespace if it does not exist." + cmds: + - kubectl create namespace metrics-operator-system --dry-run=client -o yaml | kubectl apply -f - + + dev:basic-metric: + desc: "Apply the basic metric example to the cluster." + cmds: + - kubectl apply -f {{.ROOT_DIR}}/examples/basic_metric.yaml + + dev:managed-metric: + desc: "Apply the managed metric example to the cluster." + cmds: + - kubectl apply -f {{.ROOT_DIR}}/examples/managed_metric.yaml + + dev:dynatrace-prod-setup: + desc: "Apply Dynatrace production setup example to the cluster." + cmds: + - kubectl apply -f {{.ROOT_DIR}}/examples/datasink/dynatrace-prod-setup.yaml + + dev:metric-dynatrace-prod: + desc: "Apply metric using Dynatrace production example to the cluster." + cmds: + - kubectl apply -f {{.ROOT_DIR}}/examples/datasink/metric-using-dynatrace-prod.yaml + + dev:crossplane:all: + desc: "Full Crossplane setup: install core, provider, and sample" + cmds: + - task dev:crossplane:install + - task dev:crossplane:provider:install + - task dev:helm-provider-sample + + dev:crossplane:install: + desc: "Install Crossplane into the cluster via Helm" + deps: + - build:ocm:tools:localbin + - build:helm:tools:helm + cmds: + - helm repo add crossplane-stable https://charts.crossplane.io/stable + - helm repo update + - helm install crossplane crossplane-stable/crossplane --namespace {{.CROSSPLANE_NAMESPACE}} --create-namespace --wait + + dev:crossplane:provider:install: + desc: "Install the Helm provider via kubectl" + cmds: + - kubectl apply -f {{.ROOT_DIR}}/examples/crossplane/provider.yaml -n {{.CROSSPLANE_NAMESPACE}} + - kubectl wait --for=condition=Healthy provider/provider-helm --timeout=1m + - kubectl apply -f {{.ROOT_DIR}}/examples/crossplane/provider-config.yaml -n {{.CROSSPLANE_NAMESPACE}} + + dev:helm-provider-sample: + desc: "Apply the Helm provider sample" + cmds: + - kubectl apply -f {{.ROOT_DIR}}/examples/crossplane/release.yaml -n {{.CROSSPLANE_NAMESPACE}} diff --git a/api/v1alpha1/metric_types.go b/api/v1alpha1/metric_types.go index eee1a1a..4949eb0 100644 --- a/api/v1alpha1/metric_types.go +++ b/api/v1alpha1/metric_types.go @@ -116,7 +116,7 @@ func (r *Metric) GvkToString() string { return fmt.Sprintf("%s/%s, Kind=%s", r.Spec.Target.Group, r.Spec.Target.Version, r.Spec.Target.Kind) } -//+kubebuilder:object:root=true +// +kubebuilder:object:root=true // MetricList contains a list of Metric type MetricList struct { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index f6ea205..3c0d29f 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1,27 +1,11 @@ //go:build !ignore_autogenerated -/* -Copyright 2024. - -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. -*/ - // Code generated by controller-gen. DO NOT EDIT. package v1alpha1 import ( - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) diff --git a/cmd/embedded/crds/metrics.openmcp.cloud_datasinks.yaml b/cmd/embedded/crds/metrics.openmcp.cloud_datasinks.yaml deleted file mode 100644 index 0718529..0000000 --- a/cmd/embedded/crds/metrics.openmcp.cloud_datasinks.yaml +++ /dev/null @@ -1,163 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.17.2 - name: datasinks.metrics.openmcp.cloud -spec: - group: metrics.openmcp.cloud - names: - kind: DataSink - listKind: DataSinkList - plural: datasinks - singular: datasink - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .spec.connection.endpoint - name: ENDPOINT - type: string - - jsonPath: .metadata.creationTimestamp - name: AGE - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: DataSink is the Schema for the datasinks API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: DataSinkSpec defines the desired state of DataSink - properties: - authentication: - description: Authentication specifies the authentication configuration - properties: - apiKey: - description: APIKey specifies API key authentication configuration - properties: - secretKeyRef: - description: SecretKeyRef references a key in a Kubernetes - Secret containing the API key - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its key must - be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - required: - - secretKeyRef - type: object - type: object - connection: - description: Connection specifies the connection details for the data - sink - properties: - endpoint: - description: Endpoint specifies the target endpoint URL - type: string - required: - - endpoint - type: object - required: - - connection - type: object - status: - description: DataSinkStatus defines the observed state of DataSink - properties: - conditions: - description: Conditions represent the latest available observations - of an object's state - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - 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. - 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: {} diff --git a/cmd/embedded/crds/metrics.openmcp.cloud_managedmetrics.yaml b/cmd/embedded/crds/metrics.openmcp.cloud_managedmetrics.yaml deleted file mode 100644 index 18254a9..0000000 --- a/cmd/embedded/crds/metrics.openmcp.cloud_managedmetrics.yaml +++ /dev/null @@ -1,189 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.17.2 - name: managedmetrics.metrics.openmcp.cloud -spec: - group: metrics.openmcp.cloud - names: - kind: ManagedMetric - listKind: ManagedMetricList - plural: managedmetrics - singular: managedmetric - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.ready - name: READY - type: string - - jsonPath: .status.observation.resources - name: VALUE - type: string - - jsonPath: .status.observation.timestamp - name: OBSERVED - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: ManagedMetric is the Schema for the managedmetrics API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: ManagedMetricSpec defines the desired state of ManagedMetric - properties: - dataSinkRef: - description: |- - DataSinkRef specifies the DataSink to be used for this managed metric. - If not specified, the DataSink named "default" in the operator's - namespace will be used. - properties: - name: - description: Name is the name of the DataSink resource. - type: string - required: - - name - type: object - description: - description: Sets the description that will be used to identify the - metric in Dynatrace(or other providers) - type: string - fieldSelector: - description: Define fields of your object to adapt filters of the - query - type: string - group: - description: Define the group of your object that should be instrumented - (without version at the end) - type: string - interval: - default: 10m - description: Define in what interval the query should be recorded - type: string - kind: - description: Decide which kind the metric should keep track of (needs - to be plural version) - type: string - labelSelector: - description: Define labels of your object to adapt filters of the - query - type: string - name: - description: Sets the name that will be used to identify the metric - in Dynatrace(or other providers) - type: string - remoteClusterAccessRef: - description: RemoteClusterAccessRef is to be used by other types to - reference a RemoteClusterAccess type - properties: - name: - type: string - namespace: - type: string - type: object - version: - description: Define version of the object you want to intrsument - type: string - type: object - status: - description: ManagedMetricStatus defines the observed state of ManagedMetric - properties: - conditions: - description: Conditions represent the latest available observations - of an object's state - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - 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. - 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 - observation: - description: Observation represent the latest available observation - of an object's state - properties: - resources: - description: Number of resources of the managed metric (i.e. how - many managed resource are there that match the query) - type: string - timestamp: - description: The timestamp of the observation - format: date-time - type: string - type: object - ready: - description: |- - Is set when Metric is Successfully executed and keeps track of the current cycle. - The cycle starts anew and the status will be set to active if execution was successful - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/cmd/embedded/crds/metrics.openmcp.cloud_metrics.yaml b/cmd/embedded/crds/metrics.openmcp.cloud_metrics.yaml deleted file mode 100644 index 822ee29..0000000 --- a/cmd/embedded/crds/metrics.openmcp.cloud_metrics.yaml +++ /dev/null @@ -1,214 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.17.2 - name: metrics.metrics.openmcp.cloud -spec: - group: metrics.openmcp.cloud - names: - kind: Metric - listKind: MetricList - plural: metrics - singular: metric - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.ready - name: READY - type: string - - jsonPath: .status.observation.latestValue - name: VALUE - type: string - - jsonPath: .status.observation.timestamp - name: OBSERVED - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - description: Metric is the Schema for the metrics API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: MetricSpec defines the desired state of Metric - properties: - dataSinkRef: - description: |- - DataSinkRef specifies the DataSink to be used for this metric. - If not specified, the DataSink named "default" in the operator's - namespace will be used. - properties: - name: - description: Name is the name of the DataSink resource. - type: string - required: - - name - type: object - description: - description: Sets the description that will be used to identify the - metric in Dynatrace(or other providers) - type: string - fieldSelector: - description: Define fields of your object to adapt filters of the - query - type: string - interval: - default: 10m - description: Define in what interval the query should be recorded - type: string - labelSelector: - description: Define labels of your object to adapt filters of the - query - type: string - name: - description: Sets the name that will be used to identify the metric - in Dynatrace(or other providers) - type: string - projections: - items: - description: Projection defines the projection of the metric - properties: - fieldPath: - description: Define the path to the field that should be extracted - type: string - name: - description: Define the name of the field that should be extracted - type: string - type: object - type: array - remoteClusterAccessRef: - description: RemoteClusterAccessRef is to be used by other types to - reference a RemoteClusterAccess type - properties: - name: - type: string - namespace: - type: string - type: object - target: - description: GroupVersionKind defines the group, version and kind - of the object that should be instrumented - properties: - group: - description: Define the group of your object that should be instrumented - type: string - kind: - description: Define the kind of the object that should be instrumented - type: string - version: - description: Define version of the object you want to be instrumented - type: string - type: object - required: - - target - type: object - status: - description: MetricStatus defines the observed state of ManagedMetric - properties: - conditions: - description: Conditions represent the latest available observations - of an object's state - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - 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. - 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 - observation: - description: Observation represent the latest available observation - of an object's state - properties: - dimensions: - items: - description: Dimension defines the dimension of the metric - properties: - name: - type: string - value: - type: string - type: object - type: array - latestValue: - description: The latest value of the metric - type: string - timestamp: - description: The timestamp of the observation - format: date-time - type: string - type: object - ready: - description: Ready is like a snapshot of the current state of the - metric's lifecycle - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/config/crd/bases/metrics.openmcp.cloud_datasinks.yaml b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_datasinks.yaml similarity index 99% rename from config/crd/bases/metrics.openmcp.cloud_datasinks.yaml rename to cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_datasinks.yaml index 0718529..127022d 100644 --- a/config/crd/bases/metrics.openmcp.cloud_datasinks.yaml +++ b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_datasinks.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.2 + controller-gen.kubebuilder.io/version: v0.18.0 name: datasinks.metrics.openmcp.cloud spec: group: metrics.openmcp.cloud diff --git a/cmd/embedded/crds/metrics.openmcp.cloud_federatedclusteraccesses.yaml b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_federatedclusteraccesses.yaml similarity index 98% rename from cmd/embedded/crds/metrics.openmcp.cloud_federatedclusteraccesses.yaml rename to cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_federatedclusteraccesses.yaml index 6c400d4..2c5b6e3 100644 --- a/cmd/embedded/crds/metrics.openmcp.cloud_federatedclusteraccesses.yaml +++ b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_federatedclusteraccesses.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.2 + controller-gen.kubebuilder.io/version: v0.18.0 name: federatedclusteraccesses.metrics.openmcp.cloud spec: group: metrics.openmcp.cloud diff --git a/cmd/embedded/crds/metrics.openmcp.cloud_federatedmanagedmetrics.yaml b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_federatedmanagedmetrics.yaml similarity index 99% rename from cmd/embedded/crds/metrics.openmcp.cloud_federatedmanagedmetrics.yaml rename to cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_federatedmanagedmetrics.yaml index b3fd487..91e5856 100644 --- a/cmd/embedded/crds/metrics.openmcp.cloud_federatedmanagedmetrics.yaml +++ b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_federatedmanagedmetrics.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.2 + controller-gen.kubebuilder.io/version: v0.18.0 name: federatedmanagedmetrics.metrics.openmcp.cloud spec: group: metrics.openmcp.cloud diff --git a/cmd/embedded/crds/metrics.openmcp.cloud_federatedmetrics.yaml b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_federatedmetrics.yaml similarity index 99% rename from cmd/embedded/crds/metrics.openmcp.cloud_federatedmetrics.yaml rename to cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_federatedmetrics.yaml index d02bfa5..e8fec2c 100644 --- a/cmd/embedded/crds/metrics.openmcp.cloud_federatedmetrics.yaml +++ b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_federatedmetrics.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.2 + controller-gen.kubebuilder.io/version: v0.18.0 name: federatedmetrics.metrics.openmcp.cloud spec: group: metrics.openmcp.cloud diff --git a/config/crd/bases/metrics.openmcp.cloud_managedmetrics.yaml b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_managedmetrics.yaml similarity index 99% rename from config/crd/bases/metrics.openmcp.cloud_managedmetrics.yaml rename to cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_managedmetrics.yaml index 18254a9..bbab00b 100644 --- a/config/crd/bases/metrics.openmcp.cloud_managedmetrics.yaml +++ b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_managedmetrics.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.2 + controller-gen.kubebuilder.io/version: v0.18.0 name: managedmetrics.metrics.openmcp.cloud spec: group: metrics.openmcp.cloud diff --git a/config/crd/bases/metrics.openmcp.cloud_metrics.yaml b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_metrics.yaml similarity index 99% rename from config/crd/bases/metrics.openmcp.cloud_metrics.yaml rename to cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_metrics.yaml index 822ee29..7a473fb 100644 --- a/config/crd/bases/metrics.openmcp.cloud_metrics.yaml +++ b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_metrics.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.2 + controller-gen.kubebuilder.io/version: v0.18.0 name: metrics.metrics.openmcp.cloud spec: group: metrics.openmcp.cloud diff --git a/cmd/embedded/crds/metrics.openmcp.cloud_remoteclusteraccesses.yaml b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_remoteclusteraccesses.yaml similarity index 98% rename from cmd/embedded/crds/metrics.openmcp.cloud_remoteclusteraccesses.yaml rename to cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_remoteclusteraccesses.yaml index c2b0fc4..c4971b1 100644 --- a/cmd/embedded/crds/metrics.openmcp.cloud_remoteclusteraccesses.yaml +++ b/cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_remoteclusteraccesses.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.17.2 + controller-gen.kubebuilder.io/version: v0.18.0 name: remoteclusteraccesses.metrics.openmcp.cloud spec: group: metrics.openmcp.cloud diff --git a/cmd/main.go b/cmd/metrics-operator/main.go similarity index 98% rename from cmd/main.go rename to cmd/metrics-operator/main.go index bca3225..5f9dace 100644 --- a/cmd/main.go +++ b/cmd/metrics-operator/main.go @@ -44,7 +44,7 @@ import ( "github.com/openmcp-project/metrics-operator/internal/controller" metricsv1alpha1 "github.com/openmcp-project/metrics-operator/api/v1alpha1" - //+kubebuilder:scaffold:imports + // +kubebuilder:scaffold:imports ) var _ = api.Target{} @@ -65,7 +65,7 @@ func init() { utilruntime.Must(apiextensionsv1.AddToScheme(scheme)) utilruntime.Must(metricsv1alpha1.AddToScheme(scheme)) - //+kubebuilder:scaffold:scheme + // +kubebuilder:scaffold:scheme } func runInit(setupClient client.Client) { @@ -176,7 +176,7 @@ func main() { setupFederatedManagedMetricController(mgr) - //+kubebuilder:scaffold:builder + // +kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { setupLog.Error(err, "unable to set up health check") diff --git a/config/crd/bases b/config/crd/bases new file mode 120000 index 0000000..4cc504b --- /dev/null +++ b/config/crd/bases @@ -0,0 +1 @@ +../../cmd/metrics-operator/embedded/crds/ \ No newline at end of file diff --git a/config/crd/bases/metrics.openmcp.cloud_federatedclusteraccesses.yaml b/config/crd/bases/metrics.openmcp.cloud_federatedclusteraccesses.yaml deleted file mode 100644 index 6c400d4..0000000 --- a/config/crd/bases/metrics.openmcp.cloud_federatedclusteraccesses.yaml +++ /dev/null @@ -1,69 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.17.2 - name: federatedclusteraccesses.metrics.openmcp.cloud -spec: - group: metrics.openmcp.cloud - names: - kind: FederatedClusterAccess - listKind: FederatedClusterAccessList - plural: federatedclusteraccesses - singular: federatedclusteraccess - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: FederatedClusterAccess is the Schema for the federatedclusteraccesses - API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FederatedClusterAccessSpec defines the desired state of FederatedClusterAccess - properties: - kubeConfigPath: - description: Field that contains the kubeconfig to access the target - cluster. Use dot notation to access nested fields. - type: string - target: - description: Define the target resources that should be monitored - properties: - group: - description: Define the group of your object that should be instrumented - type: string - kind: - description: Define the kind of the object that should be instrumented - type: string - version: - description: Define version of the object you want to be instrumented - type: string - type: object - type: object - status: - description: FederatedClusterAccessStatus defines the observed state of - FederatedClusterAccess - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/config/crd/bases/metrics.openmcp.cloud_federatedmanagedmetrics.yaml b/config/crd/bases/metrics.openmcp.cloud_federatedmanagedmetrics.yaml deleted file mode 100644 index b3fd487..0000000 --- a/config/crd/bases/metrics.openmcp.cloud_federatedmanagedmetrics.yaml +++ /dev/null @@ -1,165 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.17.2 - name: federatedmanagedmetrics.metrics.openmcp.cloud -spec: - group: metrics.openmcp.cloud - names: - kind: FederatedManagedMetric - listKind: FederatedManagedMetricList - plural: federatedmanagedmetrics - singular: federatedmanagedmetric - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: FederatedManagedMetric is the Schema for the federatedmanagedmetrics - API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FederatedManagedMetricSpec defines the desired state of FederatedManagedMetric - properties: - dataSinkRef: - description: |- - DataSinkRef specifies the DataSink to be used for this federated managed metric. - If not specified, the DataSink named "default" in the operator's - namespace will be used. - properties: - name: - description: Name is the name of the DataSink resource. - type: string - required: - - name - type: object - description: - type: string - federateClusterAccessRef: - description: FederateClusterAccessRef is a reference to a FederateCA - properties: - name: - type: string - namespace: - type: string - type: object - fieldSelector: - description: Define fields of your object to adapt filters of the - query - type: string - interval: - default: 10m - description: Define in what interval the query should be recorded - type: string - labelSelector: - description: Define labels of your object to adapt filters of the - query - type: string - name: - type: string - type: object - status: - description: FederatedManagedMetricStatus defines the observed state of - FederatedManagedMetric - properties: - conditions: - description: Conditions represent the latest available observations - of an object's state - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - 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. - 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 - lastReconcileTime: - format: date-time - type: string - observation: - description: FederatedObservation represents the latest available - observation of an object's state - properties: - activeCount: - type: integer - failedCount: - type: integer - pendingCount: - type: integer - type: object - ready: - description: Ready is like a snapshot of the current state of the - metric's lifecycle - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/config/crd/bases/metrics.openmcp.cloud_federatedmetrics.yaml b/config/crd/bases/metrics.openmcp.cloud_federatedmetrics.yaml deleted file mode 100644 index d02bfa5..0000000 --- a/config/crd/bases/metrics.openmcp.cloud_federatedmetrics.yaml +++ /dev/null @@ -1,191 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.17.2 - name: federatedmetrics.metrics.openmcp.cloud -spec: - group: metrics.openmcp.cloud - names: - kind: FederatedMetric - listKind: FederatedMetricList - plural: federatedmetrics - singular: federatedmetric - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: FederatedMetric is the Schema for the federatedmetrics API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: FederatedMetricSpec defines the desired state of FederatedMetric - properties: - dataSinkRef: - description: |- - DataSinkRef specifies the DataSink to be used for this federated metric. - If not specified, the DataSink named "default" in the operator's - namespace will be used. - properties: - name: - description: Name is the name of the DataSink resource. - type: string - required: - - name - type: object - description: - type: string - federateClusterAccessRef: - description: FederateClusterAccessRef is a reference to a FederateCA - properties: - name: - type: string - namespace: - type: string - type: object - fieldSelector: - description: Define fields of your object to adapt filters of the - query - type: string - interval: - default: 10m - description: Define in what interval the query should be recorded - type: string - labelSelector: - description: Define labels of your object to adapt filters of the - query - type: string - name: - type: string - projections: - items: - description: Projection defines the projection of the metric - properties: - fieldPath: - description: Define the path to the field that should be extracted - type: string - name: - description: Define the name of the field that should be extracted - type: string - type: object - type: array - target: - description: GroupVersionKind defines the group, version and kind - of the object that should be instrumented - properties: - group: - description: Define the group of your object that should be instrumented - type: string - kind: - description: Define the kind of the object that should be instrumented - type: string - version: - description: Define version of the object you want to be instrumented - type: string - type: object - required: - - target - type: object - status: - description: FederatedMetricStatus defines the observed state of FederatedMetric - properties: - conditions: - description: Conditions represent the latest available observations - of an object's state - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - 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. - 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 - lastReconcileTime: - format: date-time - type: string - observation: - description: FederatedObservation represents the latest available - observation of an object's state - properties: - activeCount: - type: integer - failedCount: - type: integer - pendingCount: - type: integer - type: object - ready: - description: Ready is like a snapshot of the current state of the - metric's lifecycle - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/config/crd/bases/metrics.openmcp.cloud_remoteclusteraccesses.yaml b/config/crd/bases/metrics.openmcp.cloud_remoteclusteraccesses.yaml deleted file mode 100644 index c2b0fc4..0000000 --- a/config/crd/bases/metrics.openmcp.cloud_remoteclusteraccesses.yaml +++ /dev/null @@ -1,84 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.17.2 - name: remoteclusteraccesses.metrics.openmcp.cloud -spec: - group: metrics.openmcp.cloud - names: - kind: RemoteClusterAccess - listKind: RemoteClusterAccessList - plural: remoteclusteraccesses - singular: remoteclusteraccess - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: RemoteClusterAccess is the Schema for the remoteclusteraccesses - API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: RemoteClusterAccessSpec defines the desired state of RemoteClusterAccess - properties: - kubeConfigSecretRef: - description: Reference to the secret that contains the kubeconfig - to access an external cluster other than the one the operator is - running in - properties: - key: - description: Key is the key in the secret to use - type: string - name: - description: Name is the name of the secret - type: string - namespace: - description: Namespace is the namespace of the secret - type: string - type: object - remoteClusterConfig: - description: ClusterAccessConfig defines the configuration to access - a remote cluster - properties: - clusterSecretRef: - description: RemoteClusterSecretRef is a reference to a secret - that contains host, audience, and caData to a remote cluster - properties: - name: - type: string - namespace: - type: string - type: object - serviceAccountName: - type: string - serviceAccountNamespace: - type: string - type: object - type: object - status: - description: RemoteClusterAccessStatus defines the observed state of RemoteClusterAccess - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/hack/common b/hack/common new file mode 160000 index 0000000..2a47837 --- /dev/null +++ b/hack/common @@ -0,0 +1 @@ +Subproject commit 2a47837f16d7645d74ff63c26901bca1bce05702 diff --git a/internal/controller/federatedmanagedmetric_controller.go b/internal/controller/federatedmanagedmetric_controller.go index e6c3d9f..fed79c4 100644 --- a/internal/controller/federatedmanagedmetric_controller.go +++ b/internal/controller/federatedmanagedmetric_controller.go @@ -85,12 +85,12 @@ func (r *FederatedManagedMetricReconciler) handleGetError(err error, log logr.Lo return ctrl.Result{RequeueAfter: RequeueAfterError}, err } -func (r *FederatedManagedMetricReconciler) scheduleNextReconciliation(metric *v1alpha1.FederatedManagedMetric) (ctrl.Result, error) { +func (r *FederatedManagedMetricReconciler) scheduleNextReconciliation(metric *v1alpha1.FederatedManagedMetric) ctrl.Result { elapsed := time.Since(metric.Status.LastReconcileTime.Time) return ctrl.Result{ RequeueAfter: metric.Spec.Interval.Duration - elapsed, - }, nil + } } func (r *FederatedManagedMetricReconciler) shouldReconcile(metric *v1alpha1.FederatedManagedMetric) bool { @@ -139,7 +139,7 @@ func (r *FederatedManagedMetricReconciler) Reconcile(ctx context.Context, req ct // Check if enough time has passed since the last reconciliation if !r.shouldReconcile(&metric) { - return r.scheduleNextReconciliation(&metric) + return r.scheduleNextReconciliation(&metric), nil } /* diff --git a/internal/controller/federatedmetric_controller.go b/internal/controller/federatedmetric_controller.go index 756b1a8..6306d0c 100644 --- a/internal/controller/federatedmetric_controller.go +++ b/internal/controller/federatedmetric_controller.go @@ -86,12 +86,12 @@ func handleGetError(err error, log logr.Logger) (ctrl.Result, error) { return ctrl.Result{RequeueAfter: RequeueAfterError}, err } -func scheduleNextReconciliation(metric *v1alpha1.FederatedMetric) (ctrl.Result, error) { +func scheduleNextReconciliation(metric *v1alpha1.FederatedMetric) ctrl.Result { elapsed := time.Since(metric.Status.LastReconcileTime.Time) return ctrl.Result{ RequeueAfter: metric.Spec.Interval.Duration - elapsed, - }, nil + } } func shouldReconcile(metric *v1alpha1.FederatedMetric) bool { @@ -141,7 +141,7 @@ func (r *FederatedMetricReconciler) Reconcile(ctx context.Context, req ctrl.Requ // Check if enough time has passed since the last reconciliation if !shouldReconcile(&metric) { - return scheduleNextReconciliation(&metric) + return scheduleNextReconciliation(&metric), nil } /* diff --git a/internal/controller/managedmetric_controller.go b/internal/controller/managedmetric_controller.go index aaac045..c1b4aed 100644 --- a/internal/controller/managedmetric_controller.go +++ b/internal/controller/managedmetric_controller.go @@ -33,6 +33,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "github.com/go-logr/logr" + "github.com/openmcp-project/metrics-operator/internal/clientoptl" "github.com/openmcp-project/metrics-operator/internal/common" "github.com/openmcp-project/metrics-operator/internal/config" @@ -61,11 +62,11 @@ func (r *ManagedMetricReconciler) getRestConfig() *rest.Config { return r.inRestConfig } -func (r *ManagedMetricReconciler) scheduleNextReconciliation(metric *v1alpha1.ManagedMetric) (ctrl.Result, error) { +func (r *ManagedMetricReconciler) scheduleNextReconciliation(metric *v1alpha1.ManagedMetric) ctrl.Result { elapsed := time.Since(metric.Status.Observation.Timestamp.Time) return ctrl.Result{ RequeueAfter: metric.Spec.Interval.Duration - elapsed, - }, nil + } } func (r *ManagedMetricReconciler) shouldReconcile(metric *v1alpha1.ManagedMetric) bool { @@ -91,11 +92,11 @@ func (r *ManagedMetricReconciler) getDataSinkCredentials(ctx context.Context, ma return retriever.GetDataSinkCredentials(ctx, managedMetric.Spec.DataSinkRef, managedMetric, l) } -//+kubebuilder:rbac:groups=metrics.openmcp.cloud,resources=managedmetrics,verbs=get;list;watch;create;update;patch;delete -//+kubebuilder:rbac:groups=metrics.openmcp.cloud,resources=managedmetrics/status,verbs=get;update;patch -//+kubebuilder:rbac:groups=metrics.openmcp.cloud,resources=managedmetrics/finalizers,verbs=update -//+kubebuilder:rbac:groups=metrics.openmcp.cloud,resources=datasinks,verbs=get;list;watch -//+kubebuilder:rbac:groups="",resources=secrets,verbs=get +// +kubebuilder:rbac:groups=metrics.openmcp.cloud,resources=managedmetrics,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=metrics.openmcp.cloud,resources=managedmetrics/status,verbs=get;update;patch +// +kubebuilder:rbac:groups=metrics.openmcp.cloud,resources=managedmetrics/finalizers,verbs=update +// +kubebuilder:rbac:groups=metrics.openmcp.cloud,resources=datasinks,verbs=get;list;watch +// +kubebuilder:rbac:groups="",resources=secrets,verbs=get // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. @@ -137,7 +138,7 @@ func (r *ManagedMetricReconciler) Reconcile(ctx context.Context, req ctrl.Reques // Check if enough time has passed since the last reconciliation if !r.shouldReconcile(&metric) { - return r.scheduleNextReconciliation(&metric) + return r.scheduleNextReconciliation(&metric), nil } /* diff --git a/internal/controller/metric_controller.go b/internal/controller/metric_controller.go index da15aed..da2003c 100644 --- a/internal/controller/metric_controller.go +++ b/internal/controller/metric_controller.go @@ -81,12 +81,12 @@ func (r *MetricReconciler) getDataSinkCredentials(ctx context.Context, metric *v return retriever.GetDataSinkCredentials(ctx, metric.Spec.DataSinkRef, metric, l) } -func (r *MetricReconciler) scheduleNextReconciliation(metric *v1alpha1.Metric) (ctrl.Result, error) { +func (r *MetricReconciler) scheduleNextReconciliation(metric *v1alpha1.Metric) ctrl.Result { elapsed := time.Since(metric.Status.Observation.Timestamp.Time) return ctrl.Result{ RequeueAfter: metric.Spec.Interval.Duration - elapsed, - }, nil + } } func (r *MetricReconciler) shouldReconcile(metric *v1alpha1.Metric) bool { @@ -146,7 +146,7 @@ func (r *MetricReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr // Check if enough time has passed since the last reconciliation if !r.shouldReconcile(&metric) { - return r.scheduleNextReconciliation(&metric) + return r.scheduleNextReconciliation(&metric), nil } /*