Skip to content

Commit

Permalink
Merge branch 'release/v0.9.0' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
kahoona77 authored and cesmarvin committed Dec 8, 2023
2 parents 6b730d0 + ce32292 commit 3b65e61
Show file tree
Hide file tree
Showing 133 changed files with 6,070 additions and 2,284 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [v0.9.0] - 2023-12-08
### Added
- [#14] Patch template for mirroring this component and its images
### Changed
- [#17] Replace create-backup-script with an operator subcommand.
This way, the backup schedule cron job can use the same image as the operator.
- [#15] Delete kustomize structure and hold the operator yaml files just in a helm chart.

## [v0.8.0] - 2023-12-04
### Added
- [#19] Sync backup list with provider on operator startup
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ RUN make compile-generic
FROM gcr.io/distroless/static:nonroot
LABEL maintainer="[email protected]" \
NAME="k8s-backup-operator" \
VERSION="0.8.0"
VERSION="0.9.0"

WORKDIR /
COPY --from=builder /workspace/target/k8s-backup-operator .
Expand Down
90 changes: 31 additions & 59 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!groovy

@Library('github.com/cloudogu/ces-build-lib@1.66.1')
@Library('github.com/cloudogu/ces-build-lib@1.68.0')
import com.cloudogu.ces.cesbuildlib.*

// Creating necessary git objects
Expand All @@ -21,8 +21,9 @@ repositoryName = "k8s-backup-operator"
project = "github.com/${repositoryOwner}/${repositoryName}"
registry = "registry.cloudogu.com"
registry_namespace = "k8s"
helmTemplateDir = "target/helm/${repositoryName}/templates"
helmCrdTemplateDir = "target/helm/${repositoryName}-crd/templates"
helmTargetDir = "target/k8s"
helmChartDir = "${helmTargetDir}/helm"
helmCRDChartDir = "${helmTargetDir}/helm-crd"

// Configuration of branches
productionReleaseBranch = "main"
Expand Down Expand Up @@ -63,24 +64,17 @@ node('docker') {
}

stage('Generate k8s Resources') {
make 'k8s-create-temporary-resource'
archiveArtifacts 'target/*.yaml'
make 'crd-helm-generate'
make 'helm-generate'
archiveArtifacts "${helmTargetDir}/**/*"
}

stage('Generate Helm Resources') {
String controllerVersion = makefile.getVersion()
make 'helm-package-release'
sh ".bin/helm template ${repositoryName} target/helm/${repositoryName}-${controllerVersion}.tgz --output-dir=target/helm"

make 'crd-helm-package'
sh ".bin/helm template ${repositoryName}-crd target/helm-crd/${repositoryName}-crd-${controllerVersion}.tgz --output-dir=target/helm"
stage("Lint helm") {
make 'crd-helm-lint'
make 'helm-lint'
}
}

stage("Lint k8s Resources") {
stageLintK8SResources(makefile)
}

stage('SonarQube') {
stageStaticAnalysisSonarQube()
}
Expand All @@ -94,22 +88,25 @@ node('docker') {
k3d.startK3d()
}

def imageName
def imageName = ""
stage('Build & Push Image') {
imageName = k3d.buildAndPushToLocalRegistry("cloudogu/${repositoryName}", controllerVersion)
}

GString sourceDeploymentYaml = "${helmTemplateDir}/${repositoryName}_${controllerVersion}.yaml"
stage('Update development resources') {
docker.image('mikefarah/yq:4.22.1')
def repository = imageName.substring(0, imageName.lastIndexOf(":"))
docker.image("golang:${goVersion}")
.mountJenkinsUser()
.inside("--volume ${WORKSPACE}:/workdir -w /workdir") {
sh "yq -i '(select(.kind == \"Deployment\").spec.template.spec.containers[]|select(.name == \"manager\")).image=\"${imageName}\"' ${sourceDeploymentYaml}"
sh "STAGE=development IMAGE_DEV=${repository} make helm-values-replace-image-repo"
}
}

stage('Deploy etcd') {
k3d.kubectl("apply -f https://raw.githubusercontent.com/cloudogu/k8s-etcd/develop/manifests/etcd.yaml")
withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'harborhelmchartpush', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD']]) {
k3d.helm("registry login ${registry} --username '${HARBOR_USERNAME}' --password '${HARBOR_PASSWORD}'")
k3d.helm("install k8s-etcd oci://${registry}/${registry_namespace}/k8s-etcd --version 3.5.9-1")
}
}

stage('Wait for etcd to be ready') {
Expand All @@ -118,15 +115,18 @@ node('docker') {
}

stage('Deploy Manager') {
k3d.kubectl("apply -f ${helmCrdTemplateDir}")
k3d.kubectl("apply -f ${helmTemplateDir}")
k3d.helm("install ${repositoryName}-crd ${helmCRDChartDir}")
k3d.helm("install ${repositoryName} ${helmChartDir}")
}

stage('Wait for Ready Rollout') {
k3d.kubectl("--namespace default wait --for=condition=Ready pods --all")
}

stageAutomaticRelease(makefile)
} catch(Exception e) {
k3d.collectAndArchiveLogs()
throw e as java.lang.Throwable
} finally {
stage('Remove k3d cluster') {
k3d.deleteK3d()
Expand All @@ -144,18 +144,6 @@ void gitWithCredentials(String command) {
}
}

void stageLintK8SResources(Makefile makefile) {
String kubevalImage = "cytopia/kubeval:0.13"
String controllerVersion = makefile.getVersion()

docker
.image(kubevalImage)
.inside("-v ${WORKSPACE}/target:/data -t --entrypoint=")
{
sh "kubeval /data/${repositoryName}_${controllerVersion}.yaml --ignore-missing-schemas"
}
}

void stageStaticAnalysisReviewDog() {
def commitSha = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()

Expand Down Expand Up @@ -218,51 +206,35 @@ void stageAutomaticRelease(Makefile makefile) {
}
}

stage('Finish Release') {
gitflow.finishRelease(releaseVersion, productionReleaseBranch)
}

stage('Sign after Release') {
gpg.createSignature()
}

stage('Regenerate resources for release') {
new Docker(this)
.image("golang:${goVersion}")
.mountJenkinsUser()
.inside("--volume ${WORKSPACE}:/go/src/${project} -w /go/src/${project}")
{
make 'k8s-create-temporary-resource'
}
}

stage('Push to Registry') {
GString targetOperatorResourceYaml = "target/${repositoryName}_${controllerVersion}.yaml"

DoguRegistry registry = new DoguRegistry(this)
registry.pushK8sYaml(targetOperatorResourceYaml, repositoryName, "k8s", "${controllerVersion}")
}

stage('Push Helm chart to Harbor') {
new Docker(this)
.image("golang:${goVersion}")
.mountJenkinsUser()
.inside("--volume ${WORKSPACE}:/go/src/${project} -w /go/src/${project}")
{
// Package operator-chart & crd-chart
make 'helm-package-release'
make 'helm-package'
make 'crd-helm-package'
archiveArtifacts "${helmTargetDir}/**/*"

// Push charts
withCredentials([usernamePassword(credentialsId: 'harborhelmchartpush', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD')]) {
sh ".bin/helm registry login ${registry} --username '${HARBOR_USERNAME}' --password '${HARBOR_PASSWORD}'"

sh ".bin/helm push target/helm/${repositoryName}-${controllerVersion}.tgz oci://${registry}/${registry_namespace}/"
sh ".bin/helm push target/helm-crd/${repositoryName}-crd-${controllerVersion}.tgz oci://${registry}/${registry_namespace}/"
sh ".bin/helm push ${helmChartDir}/${repositoryName}-${controllerVersion}.tgz oci://${registry}/${registry_namespace}/"
sh ".bin/helm push ${helmCRDChartDir}/${repositoryName}-crd-${controllerVersion}.tgz oci://${registry}/${registry_namespace}/"
}
}
}

stage('Finish Release') {
gitflow.finishRelease(releaseVersion, productionReleaseBranch)
}

stage('Add Github-Release') {
releaseId = github.createReleaseWithChangelog(releaseVersion, changelog, productionReleaseBranch)
}
Expand Down
112 changes: 51 additions & 61 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
# Set these to the desired values
ARTIFACT_ID=k8s-backup-operator
VERSION=0.8.0
## Image URL to use all building/pushing image targets
IMAGE_DEV=${K3CES_REGISTRY_URL_PREFIX}/${ARTIFACT_ID}:${VERSION}
VERSION=0.9.0
IMAGE=cloudogu/${ARTIFACT_ID}:${VERSION}
GOTAG?=1.21
MAKEFILES_VERSION=8.7.0
MAKEFILES_VERSION=9.0.1
LINT_VERSION=v1.55.2
STAGE?=production

Expand All @@ -22,75 +20,67 @@ include build/make/clean.mk
include build/make/digital-signature.mk
include build/make/mocks.mk

PRE_COMPILE=generate
K8S_RESOURCE_TEMP_FOLDER ?= $(TARGET_DIR)
K8S_PRE_GENERATE_TARGETS=k8s-create-temporary-resource template-dev-only-image-pull-policy template-cronjob-image
K8S_COMPONENT_SOURCE_VALUES = ${HELM_SOURCE_DIR}/values.yaml
K8S_COMPONENT_TARGET_VALUES = ${HELM_TARGET_DIR}/values.yaml
CRD_BACKUP_SOURCE = ${HELM_CRD_SOURCE_DIR}/templates/k8s.cloudogu.com_backups.yaml
CRD_RESTORE_SOURCE = ${HELM_CRD_SOURCE_DIR}/templates/k8s.cloudogu.com_restores.yaml
CRD_SCHEDULE_SOURCE = ${HELM_CRD_SOURCE_DIR}/templates/k8s.cloudogu.com_backupschedules.yaml
PRE_COMPILE=generate-deepcopy
HELM_PRE_APPLY_TARGETS=template-stage template-log-level template-image-pull-policy
HELM_PRE_GENERATE_TARGETS = helm-values-update-image-version
HELM_POST_GENERATE_TARGETS = helm-values-replace-image-repo
CRD_POST_MANIFEST_TARGETS = crd-add-labels crd-add-backup-labels
CHECK_VAR_TARGETS=check-all-vars
IMAGE_IMPORT_TARGET=image-import

include build/make/k8s-controller.mk

.PHONY: build-boot
build-boot: image-import k8s-apply kill-operator-pod ## Builds a new version of the operator and deploys it into the K8s-EcoSystem.

##@ Controller specific targets

.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
@echo "Generate manifests..."
@$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
@cp config/crd/bases/k8s.cloudogu.com_backups.yaml pkg/api/v1/
@cp config/crd/bases/k8s.cloudogu.com_restores.yaml pkg/api/v1/
@cp config/crd/bases/k8s.cloudogu.com_backupschedules.yaml pkg/api/v1/

.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
@echo "Auto-generate deepcopy functions..."
@$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."

##@ 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 --wait=false --ignore-not-found=true -f -
@kubectl patch crd/backups.k8s.cloudogu.com -p '{"metadata":{"finalizers":[]}}' --type=merge || true
@kubectl patch crd/restores.k8s.cloudogu.com -p '{"metadata":{"finalizers":[]}}' --type=merge || true
@kubectl patch crd/backupschedules.k8s.cloudogu.com -p '{"metadata":{"finalizers":[]}}' --type=merge || true
build-boot: helm-apply kill-operator-pod ## Builds a new version of the operator and deploys it into the K8s-EcoSystem.
.PHONY: crd-add-backup-labels
crd-add-backup-labels: $(BINARY_YQ)
@echo "Adding backup label to CRDs..."
@for file in ${HELM_CRD_SOURCE_DIR}/templates/*.yaml ; do \
$(BINARY_YQ) -i e ".metadata.labels.\"k8s.cloudogu.com/part-of\" = \"backup\"" $${file} ;\
done

.PHONY: helm-values-update-image-version
helm-values-update-image-version: $(BINARY_YQ)
@echo "Updating the image version in source values.yaml to ${VERSION}..."
@$(BINARY_YQ) -i e ".manager.image.tag = \"${VERSION}\"" ${K8S_COMPONENT_SOURCE_VALUES}

.PHONY: helm-values-replace-image-repo
helm-values-replace-image-repo: $(BINARY_YQ)
@if [[ ${STAGE} == "development" ]]; then \
echo "Setting dev image repo in target values.yaml!" ;\
$(BINARY_YQ) -i e ".manager.image.repository=\"${IMAGE_DEV}\"" "${K8S_COMPONENT_TARGET_VALUES}" ;\
fi

.PHONY: template-stage
template-stage:
@echo "Setting STAGE env in deployment to ${STAGE}!"
@$(BINARY_YQ) -i e "(select(.kind == \"Deployment\").spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").env[]|select(.name==\"STAGE\").value)=\"${STAGE}\"" $(K8S_RESOURCE_TEMP_YAML)
@$(BINARY_YQ) -i e "(select(.kind == \"CronJob\").spec.jobTemplate.spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").env[]|select(.name==\"STAGE\").value)=\"${STAGE}\"" $(K8S_RESOURCE_TEMP_YAML)

.PHONY: template-log-level
template-log-level:
@echo "Setting LOG_LEVEL env in deployment to ${LOG_LEVEL}!"
@$(BINARY_YQ) -i e "(select(.kind == \"Deployment\").spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").env[]|select(.name==\"LOG_LEVEL\").value)=\"${LOG_LEVEL}\"" $(K8S_RESOURCE_TEMP_YAML)
@$(BINARY_YQ) -i e "(select(.kind == \"CronJob\").spec.jobTemplate.spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").env[]|select(.name==\"LOG_LEVEL\").value)=\"${LOG_LEVEL}\"" $(K8S_RESOURCE_TEMP_YAML)

.PHONY: template-dev-only-image-pull-policy
template-dev-only-image-pull-policy: $(BINARY_YQ)
@echo "Setting pull policy to always!"
@$(BINARY_YQ) -i e "(select(.kind == \"Deployment\").spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").imagePullPolicy)=\"Always\"" $(K8S_RESOURCE_TEMP_YAML)
@$(BINARY_YQ) -i e "(select(.kind == \"CronJob\").spec.jobTemplate.spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").imagePullPolicy)=\"Always\"" $(K8S_RESOURCE_TEMP_YAML)

.PHONY: template-cronjob-image
template-cronjob-image: $(BINARY_YQ)
@echo "Setting image for CronJobs..."
template-stage: $(BINARY_YQ)
@if [[ ${STAGE} == "development" ]]; then \
$(BINARY_YQ) -i e "(select(.kind == \"CronJob\").spec.jobTemplate.spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").image)=\"$(IMAGE_DEV)\"" $(K8S_RESOURCE_TEMP_YAML); \
else \
$(BINARY_YQ) -i e "(select(.kind == \"CronJob\").spec.jobTemplate.spec.template.spec.containers[]|select(.image == \"*$(ARTIFACT_ID)*\").image)=\"$(IMAGE)\"" $(K8S_RESOURCE_TEMP_YAML); \
echo "Setting STAGE env in deployment to ${STAGE}!" ;\
$(BINARY_YQ) -i e ".manager.env.stage=\"${STAGE}\"" ${K8S_COMPONENT_TARGET_VALUES} ;\
fi
@echo "Done."

.PHONY: template-log-level
template-log-level: ${BINARY_YQ}
@if [[ "${STAGE}" == "development" ]]; then \
echo "Setting LOG_LEVEL env in deployment to ${LOG_LEVEL}!" ; \
$(BINARY_YQ) -i e ".manager.env.logLevel=\"${LOG_LEVEL}\"" "${K8S_COMPONENT_TARGET_VALUES}" ; \
fi

.PHONY: template-image-pull-policy
template-image-pull-policy: $(BINARY_YQ)
@if [[ "${STAGE}" == "development" ]]; then \
echo "Setting pull policy to always!" ; \
$(BINARY_YQ) -i e ".manager.imagePullPolicy=\"Always\"" "${K8S_COMPONENT_TARGET_VALUES}" ; \
fi

.PHONY: kill-operator-pod
kill-operator-pod:
@echo "Restarting k8s-backup-operator!"
@kubectl -n ${NAMESPACE} delete pods -l 'app.kubernetes.io/name=k8s-backup-operator'
@kubectl -n ${NAMESPACE} delete pods -l "app.kubernetes.io/name=$(ARTIFACT_ID)"

##@ Debug

Expand Down
30 changes: 17 additions & 13 deletions build/make/coder-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,27 @@ function generateUniqueWorkspaceName() {

function buildImage() {
local tag="$1"
local buildDir="${2:-./build}"
local secretDir="${3:-./secretArgs}"
local containerBuildDir="${2:-./container}"
local secretDir="${3:-./secrets}"
local containerExec="${4:-podman}"
local secretArgs=()

# include build-secrets if there are any
# shellcheck disable=SC2231
for secretPath in $secretDir/*; do
# do not match .sh scripts
[[ $secretPath == *.sh ]] && continue
local secretName
secretName=$(basename "$secretPath")
secretArgs+=("--secret=id=$secretName,src=$secretDir/$secretName")
done
local secretArgs=()
if [ -d "$secretDir" ]; then
# shellcheck disable=SC2231
for secretPath in $secretDir/*; do
# do not match .sh scripts
[[ $secretPath == *.sh ]] && continue
local secretName
secretName=$(basename "$secretPath")
secretArgs+=("--secret=id=$secretName,src=$secretDir/$secretName")
done
fi

if [ "$containerExec" = "podman" ]; then
$containerExec build -t "$tag" --pull=newer "$buildDir" "${secretArgs[@]}"
$containerExec build -t "$tag" --pull=newer "$containerBuildDir" "${secretArgs[@]}"
else
$containerExec build -t "$tag" --pull "$buildDir" "${secretArgs[@]}"
$containerExec build -t "$tag" --pull "$containerBuildDir" "${secretArgs[@]}"
fi
}

Expand Down
Loading

0 comments on commit 3b65e61

Please sign in to comment.