From a584156162b7d3fb20a05e9feb44ce08171dc500 Mon Sep 17 00:00:00 2001 From: Niklas Date: Wed, 6 Dec 2023 10:09:43 +0100 Subject: [PATCH 01/13] #117 Add first version for setup helm deployment. Setup json and component-op are configurable. --- src/com/cloudogu/ces/cesbuildlib/K3d.groovy | 70 ++++++++++++++++----- 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy index 36517d4..53ff902 100644 --- a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy +++ b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy @@ -12,6 +12,8 @@ class K3d { */ private static String K3D_VERSION = "4.4.7" private static String K3D_LOG_FILENAME = "k8sLogs" + private static String HELM_SETUP_CONFIGURATION_FILE = "values.yaml" + private static String YQ_VERSION = "4.40.4" private String clusterName private script @@ -122,7 +124,7 @@ class K3d { // create helm-repo-config kubectl("create configmap component-operator-helm-repository --from-literal=endpoint=\"registry.cloudogu.com\" --from-literal=schema=\"oci\" --from-literal=plainHttp=\"false\"") - String auth = script.sh(script: "printf '%s:%s' '${script.env.HARBOR_USERNAME}' '${script.env.HARBOR_PASSWORD}' | base64", returnStdout: true, ) + String auth = script.sh(script: "printf '%s:%s' '${script.env.HARBOR_USERNAME}' '${script.env.HARBOR_PASSWORD}' | base64", returnStdout: true,) kubectlHideCommand("create secret generic component-operator-helm-registry --from-literal=config.json='{\"auths\": {\"registry.cloudogu.com\": {\"auth\": \"${auth?.trim()}\"}}}'", false) } } @@ -216,24 +218,60 @@ class K3d { this.externalIP = this.sh.returnStdOut("curl -H \"Metadata-Flavor: Google\" http://169.254.169.254/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip") } - void configureSetup(String tag, config = [:]) { - script.echo "configuring setup..." - // Config - kubectl("apply -f https://raw.githubusercontent.com/cloudogu/k8s-ces-setup/${tag}/k8s/k8s-ces-setup-config.yaml") + void appendToValuesYaml(String file, String key, String value) { + createEmptySetupValuesYamlIfItDoesNotExists() + docker.image("mikefarah/yq:${YQ_VERSION}") + .mountJenkinsUser().inside("--volume ${this.workspace}:/workdir -w /workdir") { + script.sh("yq -i \"${key} = \"${value}\"\" ${file}") + } + } + + void configureSetupJson(String config = [:]) { + String setupJsonConfigKey = "setup_json" + script.echo "configuring setup..." // Merge default config with the one passed as parameter config = defaultSetupConfig << config - writeSetupJson(config) - kubectl('create configmap k8s-ces-setup-json --from-file=setup.json') + appendToValuesYaml(HELM_SETUP_CONFIGURATION_FILE, setupJsonConfigKey, getSetupJson(config)) + } + + void configureSetupImage(String image) { + String imageKey = "k8s_ces_setup_image" + appendToValuesYaml(HELM_SETUP_CONFIGURATION_FILE, imageKey, image) } + void configureComponentOperatorVersion(String operatorVersion, String crdVersion = operatorVersion, String namespace = "k8s") { + String componentOpKey = "component_operator_chart" + String componentCRDKey = "component_operator_crd_chart" + + + def builder = new StringBuilder(namespace) + String operatorValue = builder.append("k8s-component-operator").append(operatorVersion).toString() + appendToValuesYaml(HELM_SETUP_CONFIGURATION_FILE, componentOpKey, operatorValue) + builder.setLength(0) + String crdValue = builder.append(namespace).append("k8s-component-operator-crd:").append(crdVersion).toString() + appendToValuesYaml(HELM_SETUP_CONFIGURATION_FILE, componentCRDKey, crdValue) + } + + void createEmptySetupValuesYamlIfItDoesNotExists() { + if (!new File(HELM_SETUP_CONFIGURATION_FILE).exists()) { + script.echo "create values.yaml for setup deployment" + script.writeFile file: HELM_SETUP_CONFIGURATION_FILE, text: "" + } + } + + // TODO Additional separate configureSetup Methods for component-op, components, log_level, etcd-client-image, key_provider and resource_patches void installAndTriggerSetup(String tag, Integer timout = 300, Integer interval = 5) { script.echo "Installing setup..." - String setup = this.sh.returnStdOut("curl -s https://raw.githubusercontent.com/cloudogu/k8s-ces-setup/${tag}/k8s/k8s-ces-setup.yaml") - setup = setup.replace("{{ .Namespace }}", "default") - script.writeFile file: 'setup.yaml', text: setup - kubectl('apply -f setup.yaml') + String registryUrl = "registry.cloudogu.com" + String registryNamespace = "k8s" + this.withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'harborhelmchartpush', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD']]) { + helm("registry login ${registryUrl} --username '${HARBOR_USERNAME}' --password '${HARBOR_PASSWORD}'") + } + + helm("install k8s-ces-setup oci://${registryUrl}/${registryNamespace}/k8s-ces-setup --version ${tag} --namespace default") + helm("registry logout ${registryUrl}") script.echo "Wait for dogu-operator to be ready..." waitForDeploymentRollout("k8s-dogu-operator-controller-manager", timout, interval) @@ -248,7 +286,7 @@ class K3d { */ void setup(String tag, config = [:], Integer timout = 300, Integer interval = 5) { assignExternalIP() - configureSetup(tag, config) + configureSetupJson(config) installAndTriggerSetup(tag, timout, interval) } @@ -307,7 +345,7 @@ spec: private void applyDevDoguDescriptor(Docker docker, String dogu, String imageUrl, String port) { String imageDev String doguJsonDevFile = "${this.workspace}/target/dogu.json" - docker.image('mikefarah/yq:4.22.1') + docker.image("mikefarah/yq:${YQ_VERSION}") .mountJenkinsUser() .inside("--volume ${this.workspace}:/workdir -w /workdir") { imageDev = this.sh.returnStdOut("yq -e '.Image' dogu.json | sed 's|registry\\.cloudogu\\.com\\(.\\+\\)|${imageUrl}.local:${port}\\1|g'") @@ -482,7 +520,7 @@ data: String registryPortProtocol String prefixedRegistryName = "k3d-${this.registryName}" String dockerInspect = script.sh(script: "docker inspect ${prefixedRegistryName}", returnStdout: true) - docker.image('mikefarah/yq:4.22.1') + docker.image("mikefarah/yq:${YQ_VERSION}") .mountJenkinsUser().inside("--volume ${this.workspace}:/workdir -w /workdir") { registryIp = script.sh(script: "echo '${dockerInspect}' | yq '.[].NetworkSettings.Networks.${prefixedRegistryName}.IPAddress'", returnStdout: true).trim() registryPortProtocol = script.sh(script: "echo '${dockerInspect}' | yq '.[].Config.Labels.\"k3s.registry.port.internal\"'", returnStdout: true).trim() @@ -506,11 +544,11 @@ data: return formatted } - private void writeSetupJson(config) { + private String getSetupJson(config) { List deps = config.dependencies + config.additionalDependencies String formattedDeps = formatDependencies(deps) - script.writeFile file: 'setup.json', text: """ + return """ { "naming":{ "fqdn":"${externalIP}", From b6c18cd1501ec07fc24449f1c710a140bd8f6242 Mon Sep 17 00:00:00 2001 From: Niklas Date: Wed, 6 Dec 2023 13:11:30 +0100 Subject: [PATCH 02/13] #117 Refactoring and fix errors. --- src/com/cloudogu/ces/cesbuildlib/K3d.groovy | 53 +++++++++++++-------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy index 53ff902..f7e63bc 100644 --- a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy +++ b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy @@ -27,6 +27,7 @@ class K3d { private K3dRegistry registry private String registryName private String workspace + private Docker docker def defaultSetupConfig = [ adminUsername : "ces-admin", @@ -67,6 +68,7 @@ class K3d { this.backendCredentialsID = backendCredentialsID this.harborCredentialsID = harborCredentialsID this.sh = new Sh(script) + this.docker = new Docker(script) } /** @@ -218,44 +220,58 @@ class K3d { this.externalIP = this.sh.returnStdOut("curl -H \"Metadata-Flavor: Google\" http://169.254.169.254/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip") } - void appendToValuesYaml(String file, String key, String value) { + void appendToYamlFile(String file, String key, String value) { createEmptySetupValuesYamlIfItDoesNotExists() + doInYQContainer { + script.sh("yq -i \"${key} = \\\"${value}\\\"\" ${file}") + } + } + + void appendFileToYamlFile(String file, String key, String fileName) { + createEmptySetupValuesYamlIfItDoesNotExists() + doInYQContainer { + script.sh("yq -i '${key} = load_str(\"${fileName}\")' ${file}") + } + } + + void doInYQContainer(Closure closure) { docker.image("mikefarah/yq:${YQ_VERSION}") .mountJenkinsUser().inside("--volume ${this.workspace}:/workdir -w /workdir") { - script.sh("yq -i \"${key} = \"${value}\"\" ${file}") + closure.call() } } - void configureSetupJson(String config = [:]) { - String setupJsonConfigKey = "setup_json" + void configureSetupJson(config = [:]) { + String setupJsonConfigKey = ".setup_json" script.echo "configuring setup..." // Merge default config with the one passed as parameter config = defaultSetupConfig << config + writeSetupJson(config) - appendToValuesYaml(HELM_SETUP_CONFIGURATION_FILE, setupJsonConfigKey, getSetupJson(config)) + appendFileToYamlFile(HELM_SETUP_CONFIGURATION_FILE, setupJsonConfigKey, "setup.json") } void configureSetupImage(String image) { - String imageKey = "k8s_ces_setup_image" - appendToValuesYaml(HELM_SETUP_CONFIGURATION_FILE, imageKey, image) + String imageKey = ".k8s_ces_setup_image" + appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, imageKey, image) } void configureComponentOperatorVersion(String operatorVersion, String crdVersion = operatorVersion, String namespace = "k8s") { - String componentOpKey = "component_operator_chart" - String componentCRDKey = "component_operator_crd_chart" + String componentOpKey = ".component_operator_chart" + String componentCRDKey = ".component_operator_crd_chart" def builder = new StringBuilder(namespace) String operatorValue = builder.append("k8s-component-operator").append(operatorVersion).toString() - appendToValuesYaml(HELM_SETUP_CONFIGURATION_FILE, componentOpKey, operatorValue) + appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, componentOpKey, operatorValue) builder.setLength(0) String crdValue = builder.append(namespace).append("k8s-component-operator-crd:").append(crdVersion).toString() - appendToValuesYaml(HELM_SETUP_CONFIGURATION_FILE, componentCRDKey, crdValue) + appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, componentCRDKey, crdValue) } void createEmptySetupValuesYamlIfItDoesNotExists() { - if (!new File(HELM_SETUP_CONFIGURATION_FILE).exists()) { + if (!script.fileExists(HELM_SETUP_CONFIGURATION_FILE)) { script.echo "create values.yaml for setup deployment" script.writeFile file: HELM_SETUP_CONFIGURATION_FILE, text: "" } @@ -302,12 +318,11 @@ class K3d { * @param doguYaml Name of the custom resources */ void installDogu(String dogu, String image, String doguYaml) { - Docker docker = new Docker(script) - String[] IpPort = getRegistryIpAndPort(docker) + String[] IpPort = getRegistryIpAndPort() String imageUrl = image.split(":")[0] patchCoreDNS(IpPort[0], imageUrl) - applyDevDoguDescriptor(docker, dogu, imageUrl, IpPort[1]) + applyDevDoguDescriptor(dogu, imageUrl, IpPort[1]) kubectl("apply -f ${doguYaml}") // Remove .local from Images. @@ -342,7 +357,7 @@ spec: kubectl("apply -f ${filename}") } - private void applyDevDoguDescriptor(Docker docker, String dogu, String imageUrl, String port) { + private void applyDevDoguDescriptor(String dogu, String imageUrl, String port) { String imageDev String doguJsonDevFile = "${this.workspace}/target/dogu.json" docker.image("mikefarah/yq:${YQ_VERSION}") @@ -515,7 +530,7 @@ data: kubectl("rollout restart -n kube-system deployment/coredns") } - private String[] getRegistryIpAndPort(Docker docker) { + private String[] getRegistryIpAndPort() { String registryIp String registryPortProtocol String prefixedRegistryName = "k3d-${this.registryName}" @@ -544,11 +559,11 @@ data: return formatted } - private String getSetupJson(config) { + private void writeSetupJson(config) { List deps = config.dependencies + config.additionalDependencies String formattedDeps = formatDependencies(deps) - return """ + script.writeFile file: 'setup.json', text: """ { "naming":{ "fqdn":"${externalIP}", From f0e13cd81b7cf889fe283c03ec729502c44066e6 Mon Sep 17 00:00:00 2001 From: Niklas Date: Wed, 6 Dec 2023 13:28:35 +0100 Subject: [PATCH 03/13] #117 Remove default dogu --- src/com/cloudogu/ces/cesbuildlib/K3d.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy index f7e63bc..f567c89 100644 --- a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy +++ b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy @@ -38,7 +38,7 @@ class K3d { "k8s/nginx-ingress", "official/postfix", "official/usermgt"], - defaultDogu : "cockpit", + defaultDogu : "", additionalDependencies : [], registryConfig : "", registryConfigEncrypted: "" From 2a13113cce344c9afafa3b7f52d72be67dab6c8e Mon Sep 17 00:00:00 2001 From: Niklas Date: Wed, 6 Dec 2023 13:51:01 +0100 Subject: [PATCH 04/13] #117 Add methods for components and log level --- src/com/cloudogu/ces/cesbuildlib/K3d.groovy | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy index f567c89..048ff9d 100644 --- a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy +++ b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy @@ -220,6 +220,13 @@ class K3d { this.externalIP = this.sh.returnStdOut("curl -H \"Metadata-Flavor: Google\" http://169.254.169.254/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip") } + void createEmptySetupValuesYamlIfItDoesNotExists() { + if (!script.fileExists(HELM_SETUP_CONFIGURATION_FILE)) { + script.echo "create values.yaml for setup deployment" + script.writeFile file: HELM_SETUP_CONFIGURATION_FILE, text: "" + } + } + void appendToYamlFile(String file, String key, String value) { createEmptySetupValuesYamlIfItDoesNotExists() doInYQContainer { @@ -270,14 +277,16 @@ class K3d { appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, componentCRDKey, crdValue) } - void createEmptySetupValuesYamlIfItDoesNotExists() { - if (!script.fileExists(HELM_SETUP_CONFIGURATION_FILE)) { - script.echo "create values.yaml for setup deployment" - script.writeFile file: HELM_SETUP_CONFIGURATION_FILE, text: "" - } + void configureComponents(components = [:]) { + def componentsFileName = "components.yaml" + writeYaml file: componentsFileName, data: components + appendFileToYamlFile(HELM_SETUP_CONFIGURATION_FILE, ".components", componentsFileName) + } + + void configureLogLevel(String loglevel) { + appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, ".logLevel", loglevel) } - // TODO Additional separate configureSetup Methods for component-op, components, log_level, etcd-client-image, key_provider and resource_patches void installAndTriggerSetup(String tag, Integer timout = 300, Integer interval = 5) { script.echo "Installing setup..." String registryUrl = "registry.cloudogu.com" From bb3bbc33783a0154e390472bf96e60888212a912 Mon Sep 17 00:00:00 2001 From: Niklas Date: Wed, 6 Dec 2023 15:23:27 +0100 Subject: [PATCH 05/13] #117 Fix setup image configuration --- src/com/cloudogu/ces/cesbuildlib/K3d.groovy | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy index 048ff9d..c8147d1 100644 --- a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy +++ b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy @@ -260,8 +260,12 @@ class K3d { } void configureSetupImage(String image) { - String imageKey = ".k8s_ces_setup_image" - appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, imageKey, image) + String repositoryKey = ".setup.image.repository" + String tagKey = ".setup.image.tag" + def i = image.lastIndexOf(":") + + appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, repositoryKey, image.substring(0, i)) + appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, tagKey, image.substring(i + 1, image.length())) } void configureComponentOperatorVersion(String operatorVersion, String crdVersion = operatorVersion, String namespace = "k8s") { From dd856a34b8d8b9c6d700d01e2a76b0074e1a8075 Mon Sep 17 00:00:00 2001 From: Niklas Date: Wed, 6 Dec 2023 16:59:42 +0100 Subject: [PATCH 06/13] #117 Fix and cleanup k3d files. --- src/com/cloudogu/ces/cesbuildlib/K3d.groovy | 133 ++++++++++---------- 1 file changed, 70 insertions(+), 63 deletions(-) diff --git a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy index c8147d1..023288c 100644 --- a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy +++ b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy @@ -12,7 +12,8 @@ class K3d { */ private static String K3D_VERSION = "4.4.7" private static String K3D_LOG_FILENAME = "k8sLogs" - private static String HELM_SETUP_CONFIGURATION_FILE = "values.yaml" + private static String K3D_SETUP_JSON_FILE = "k3d_setup.json" + private static String K3D_VALUES_YAML_FILE = "k3d_values.yaml" private static String YQ_VERSION = "4.40.4" private String clusterName @@ -221,9 +222,9 @@ class K3d { } void createEmptySetupValuesYamlIfItDoesNotExists() { - if (!script.fileExists(HELM_SETUP_CONFIGURATION_FILE)) { + if (!script.fileExists(K3D_VALUES_YAML_FILE)) { script.echo "create values.yaml for setup deployment" - script.writeFile file: HELM_SETUP_CONFIGURATION_FILE, text: "" + script.writeFile file: K3D_VALUES_YAML_FILE, text: "" } } @@ -244,7 +245,7 @@ class K3d { void doInYQContainer(Closure closure) { docker.image("mikefarah/yq:${YQ_VERSION}") .mountJenkinsUser().inside("--volume ${this.workspace}:/workdir -w /workdir") { - closure.call() + closure.call() } } @@ -256,7 +257,7 @@ class K3d { config = defaultSetupConfig << config writeSetupJson(config) - appendFileToYamlFile(HELM_SETUP_CONFIGURATION_FILE, setupJsonConfigKey, "setup.json") + appendFileToYamlFile(K3D_VALUES_YAML_FILE, setupJsonConfigKey, K3D_SETUP_JSON_FILE) } void configureSetupImage(String image) { @@ -264,8 +265,8 @@ class K3d { String tagKey = ".setup.image.tag" def i = image.lastIndexOf(":") - appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, repositoryKey, image.substring(0, i)) - appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, tagKey, image.substring(i + 1, image.length())) + appendToYamlFile(K3D_VALUES_YAML_FILE, repositoryKey, image.substring(0, i)) + appendToYamlFile(K3D_VALUES_YAML_FILE, tagKey, image.substring(i + 1, image.length())) } void configureComponentOperatorVersion(String operatorVersion, String crdVersion = operatorVersion, String namespace = "k8s") { @@ -274,21 +275,24 @@ class K3d { def builder = new StringBuilder(namespace) - String operatorValue = builder.append("k8s-component-operator").append(operatorVersion).toString() - appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, componentOpKey, operatorValue) + String operatorValue = builder.append("/k8s-component-operator:").append(operatorVersion).toString() + appendToYamlFile(K3D_VALUES_YAML_FILE, componentOpKey, operatorValue) builder.setLength(0) - String crdValue = builder.append(namespace).append("k8s-component-operator-crd:").append(crdVersion).toString() - appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, componentCRDKey, crdValue) + String crdValue = builder.append(namespace).append("/k8s-component-operator-crd:").append(crdVersion).toString() + appendToYamlFile(K3D_VALUES_YAML_FILE, componentCRDKey, crdValue) } void configureComponents(components = [:]) { - def componentsFileName = "components.yaml" - writeYaml file: componentsFileName, data: components - appendFileToYamlFile(HELM_SETUP_CONFIGURATION_FILE, ".components", componentsFileName) + // TODO better solution + components.each { i -> + i.value.each { j -> + appendToYamlFile(K3D_VALUES_YAML_FILE, new StringBuilder(".components.").append(i.key as String).append(".").append(j.key as String).toString(), j.value as String) + } + } } void configureLogLevel(String loglevel) { - appendToYamlFile(HELM_SETUP_CONFIGURATION_FILE, ".logLevel", loglevel) + appendToYamlFile(K3D_VALUES_YAML_FILE, ".logLevel", loglevel) } void installAndTriggerSetup(String tag, Integer timout = 300, Integer interval = 5) { @@ -306,13 +310,13 @@ class K3d { waitForDeploymentRollout("k8s-dogu-operator-controller-manager", timout, interval) } - /** - * Installs the setup to the cluster. Creates an example setup.json with plantuml as dogu and executes the setup. - * After that the method will wait until the dogu-operator is ready. - * @param tag Tag of the setup e. g. "v0.6.0" - * @param timout Timeout in seconds for the setup process e. g. 300 - * @param interval Interval in seconds for querying the actual state of the setup e. g. 2 - */ +/** + * Installs the setup to the cluster. Creates an example setup.json with plantuml as dogu and executes the setup. + * After that the method will wait until the dogu-operator is ready. + * @param tag Tag of the setup e. g. "v0.6.0" + * @param timout Timeout in seconds for the setup process e. g. 300 + * @param interval Interval in seconds for querying the actual state of the setup e. g. 2 + */ void setup(String tag, config = [:], Integer timout = 300, Integer interval = 5) { assignExternalIP() configureSetupJson(config) @@ -343,15 +347,15 @@ class K3d { patchDoguDeployment(dogu, image) } - /** - * Applies the specified dogu resource into the k8s cluster. This should be used for dogus which are not build or - * locally installed in the build process. An example for the usage would be to install a dogu dependency before - * starting integration tests. - * - * @param doguName Name of the dogu, e.g., "nginx-ingress" - * @param doguNamespace Namespace of the dogu, e.g., "official" - * @param doguVersion Version of the dogu, e.g., "13.9.9-1" - */ +/** + * Applies the specified dogu resource into the k8s cluster. This should be used for dogus which are not build or + * locally installed in the build process. An example for the usage would be to install a dogu dependency before + * starting integration tests. + * + * @param doguName Name of the dogu, e.g., "nginx-ingress" + * @param doguNamespace Namespace of the dogu, e.g., "official" + * @param doguVersion Version of the dogu, e.g., "13.9.9-1" + */ void applyDoguResource(String doguName, String doguNamespace, String doguVersion) { def filename = "target/make/k8s/${doguName}.yaml" def doguContentYaml = """ @@ -395,19 +399,19 @@ spec: kubectl("patch deployment '${dogu}' -p '{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"${dogu}\",\"image\":\"${image}\"}]}}}}'") } - /** - * returns a free, unprivileged TCP port - * - * @return new free, unprivileged TCP port - */ +/** + * returns a free, unprivileged TCP port + * + * @return new free, unprivileged TCP port + */ private String findFreeTcpPort() { String port = this.sh.returnStdOut('echo -n $(python3 -c \'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()\');') return port } - /** - * installs a local image registry to k3d - */ +/** + * installs a local image registry to k3d + */ private void installLocalRegistry() { def registryPort = findFreeTcpPort() def registryName = clusterName @@ -415,9 +419,9 @@ spec: this.registry.installLocalRegistry() } - /** - * Installs k3d - */ +/** + * Installs k3d + */ private void installK3d() { script.sh "rm -rf ${k3dDir}" script.sh "mkdir -p ${k3dBinaryDir}" @@ -430,9 +434,9 @@ spec: script.sh "curl -s https://raw.githubusercontent.com/rancher/k3d/main/install.sh | ${k3dInstallArguments} bash -s -- --no-sudo" } - /** - * Installs kubectl - */ +/** + * Installs kubectl + */ private void installKubectl() { def kubectlStatusCode = script.sh script: "snap list kubectl", returnStatus: true if (kubectlStatusCode == 0) { @@ -443,9 +447,9 @@ spec: script.echo "Installing kubectl..." script.sh script: "sudo snap install kubectl --classic" } - /** - * Installs helm - */ +/** + * Installs helm + */ void installHelm() { def helmStatusCode = script.sh script: "snap list helm", returnStatus: true if (helmStatusCode == 0 || helmStatusCode.equals("0")) { @@ -576,7 +580,7 @@ data: List deps = config.dependencies + config.additionalDependencies String formattedDeps = formatDependencies(deps) - script.writeFile file: 'setup.json', text: """ + script.writeFile file: K3D_SETUP_JSON_FILE, text: """ { "naming":{ "fqdn":"${externalIP}", @@ -619,16 +623,18 @@ data: } - /** - * Collects all necessary resources and log information used to identify problems with our kubernetes cluster. - * - * The collected information are archived as zip files at the build. - */ +/** + * Collects all necessary resources and log information used to identify problems with our kubernetes cluster. + * + * The collected information are archived as zip files at the build. + */ void collectAndArchiveLogs() { script.dir(K3D_LOG_FILENAME) { script.deleteDir() } script.sh("rm -rf ${K3D_LOG_FILENAME}.zip".toString()) + script.sh("rm -rf ${K3D_SETUP_JSON_FILE}".toString()) + script.sh("rm -rf ${K3D_VALUES_YAML_FILE}".toString()) collectResourcesSummaries() collectDoguDescriptions() @@ -639,9 +645,9 @@ data: script.archiveArtifacts(artifacts: fileNameString, allowEmptyArchive: "true") } - /** - * Collects all information about resources and their quantity and saves them as .yaml files. - */ +/** + * Collects all information about resources and their quantity and saves them as .yaml files. + */ void collectResourcesSummaries() { def relevantResources = [ "persistentvolumeclaim", @@ -669,9 +675,9 @@ data: } } - /** - * Collects all descriptions of dogus resources and saves them as .yaml files into the k8s logs directory. - */ +/** + * Collects all descriptions of dogus resources and saves them as .yaml files into the k8s logs directory. + */ void collectDoguDescriptions() { def allDoguNames = kubectl("get dogu --ignore-not-found -o name || true", true) try { @@ -690,9 +696,9 @@ data: } } - /** - * Collects all pod logs and saves them into the k8s logs directory. - */ +/** + * Collects all pod logs and saves them into the k8s logs directory. + */ void collectPodLogs() { def allPodNames = kubectl("get pods -o name || true", true) try { @@ -710,4 +716,5 @@ data: script.echo "Failed to collect pod logs because of: \n${ignored.toString()}\nSkipping collection step." } } + } From 939faedd7a8d2009cd3012327695ebc7d07095ec Mon Sep 17 00:00:00 2001 From: Benjamin Ernst Date: Thu, 7 Dec 2023 15:12:35 +0100 Subject: [PATCH 07/13] #117 add unit-tests for k3d-setup --- src/com/cloudogu/ces/cesbuildlib/K3d.groovy | 10 +- .../cloudogu/ces/cesbuildlib/K3dTest.groovy | 150 +++++++++++++++--- .../ces/cesbuildlib/ScriptMock.groovy | 4 + 3 files changed, 135 insertions(+), 29 deletions(-) diff --git a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy index 023288c..b198f48 100644 --- a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy +++ b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy @@ -284,9 +284,9 @@ class K3d { void configureComponents(components = [:]) { // TODO better solution - components.each { i -> - i.value.each { j -> - appendToYamlFile(K3D_VALUES_YAML_FILE, new StringBuilder(".components.").append(i.key as String).append(".").append(j.key as String).toString(), j.value as String) + components.each { componentName, componentConfig -> + componentConfig.each { configKey, configValue -> + appendToYamlFile(K3D_VALUES_YAML_FILE, ".components.${componentName}.${configKey}", configValue as String) } } } @@ -299,8 +299,8 @@ class K3d { script.echo "Installing setup..." String registryUrl = "registry.cloudogu.com" String registryNamespace = "k8s" - this.withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'harborhelmchartpush', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD']]) { - helm("registry login ${registryUrl} --username '${HARBOR_USERNAME}' --password '${HARBOR_PASSWORD}'") + script.withCredentials([[$class: 'UsernamePasswordMultiBinding', credentialsId: 'harborhelmchartpush', usernameVariable: 'HARBOR_USERNAME', passwordVariable: 'HARBOR_PASSWORD']]) { + helm("registry login ${registryUrl} --username '${script.env.HARBOR_USERNAME}' --password '${script.env.HARBOR_PASSWORD}'") } helm("install k8s-ces-setup oci://${registryUrl}/${registryNamespace}/k8s-ces-setup --version ${tag} --namespace default") diff --git a/test/com/cloudogu/ces/cesbuildlib/K3dTest.groovy b/test/com/cloudogu/ces/cesbuildlib/K3dTest.groovy index 2263994..557f51d 100644 --- a/test/com/cloudogu/ces/cesbuildlib/K3dTest.groovy +++ b/test/com/cloudogu/ces/cesbuildlib/K3dTest.groovy @@ -199,6 +199,9 @@ class K3dTest extends GroovyTestCase { def workspaceEnvDir = "leK3dWorkSpace" String tag = "v0.6.0" def scriptMock = new ScriptMock() + scriptMock.expectedShRetValueForScript.put("whoami", "jenkins") + scriptMock.expectedShRetValueForScript.put("cat /etc/passwd | grep jenkins", "jenkins:x:1000:1000:jenkins,,,:/home/jenkins:/bin/bash") + scriptMock.expectedShRetValueForScript.put("yq -i '.setup_json = load_str(\"k3d_setup.json\")' k3d_values.yaml", "foo") scriptMock.expectedShRetValueForScript.put("curl -s https://raw.githubusercontent.com/cloudogu/k8s-ces-setup/${tag}/k8s/k8s-ces-setup.yaml".toString(), "fake setup yaml with {{ .Namespace }}") scriptMock.expectedShRetValueForScript.put("sudo KUBECONFIG=${workspaceEnvDir}/.k3d/.kube/config kubectl rollout status deployment/k8s-dogu-operator-controller-manager".toString(), "successfully rolled out") scriptMock.expectedShRetValueForScript.put("curl -H \"Metadata-Flavor: Google\" http://169.254.169.254/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip", "192.168.56.2") @@ -210,16 +213,19 @@ class K3dTest extends GroovyTestCase { // then assertThat(scriptMock.actualEcho.get(0)).isEqualTo("configuring setup...") - assertThat(scriptMock.actualEcho.get(1)).isEqualTo("Installing setup...") - assertThat(scriptMock.actualEcho.get(2)).isEqualTo("Wait for dogu-operator to be ready...") + assertThat(scriptMock.actualEcho.get(1)).isEqualTo("create values.yaml for setup deployment") + assertThat(scriptMock.actualEcho.get(2)).isEqualTo("Installing setup...") + assertThat(scriptMock.actualEcho.get(3)).isEqualTo("Wait for dogu-operator to be ready...") assertThat(scriptMock.allActualArgs[0].trim()).isEqualTo("curl -H \"Metadata-Flavor: Google\" http://169.254.169.254/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip") - assertThat(scriptMock.allActualArgs[1].trim()).isEqualTo("sudo KUBECONFIG=${workspaceEnvDir}/.k3d/.kube/config kubectl apply -f https://raw.githubusercontent.com/cloudogu/k8s-ces-setup/${tag}/k8s/k8s-ces-setup-config.yaml".trim()) - assertThat(scriptMock.allActualArgs[2].trim()).isEqualTo("sudo KUBECONFIG=${workspaceEnvDir}/.k3d/.kube/config kubectl create configmap k8s-ces-setup-json --from-file=setup.json".trim()) - assertThat(scriptMock.allActualArgs[3].trim()).isEqualTo("curl -s https://raw.githubusercontent.com/cloudogu/k8s-ces-setup/${tag}/k8s/k8s-ces-setup.yaml".trim()) - assertThat(scriptMock.allActualArgs[4].trim()).isEqualTo("sudo KUBECONFIG=${workspaceEnvDir}/.k3d/.kube/config kubectl apply -f setup.yaml".trim()) - assertThat(scriptMock.allActualArgs[5].trim()).isEqualTo("sleep 1s") - assertThat(scriptMock.allActualArgs[6].trim()).isEqualTo("sudo KUBECONFIG=${workspaceEnvDir}/.k3d/.kube/config kubectl rollout status deployment/k8s-dogu-operator-controller-manager".trim()) + assertThat(scriptMock.allActualArgs[1].trim()).isEqualTo("whoami".trim()) + assertThat(scriptMock.allActualArgs[2].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) + assertThat(scriptMock.allActualArgs[3].trim()).isEqualTo("yq -i '.setup_json = load_str(\"k3d_setup.json\")' k3d_values.yaml".trim()) + assertThat(scriptMock.allActualArgs[4].trim()).isEqualTo("sudo KUBECONFIG=leK3dWorkSpace/.k3d/.kube/config helm registry login registry.cloudogu.com --username 'null' --password 'null'".trim()) + assertThat(scriptMock.allActualArgs[5].trim()).isEqualTo("sudo KUBECONFIG=leK3dWorkSpace/.k3d/.kube/config helm install k8s-ces-setup oci://registry.cloudogu.com/k8s/k8s-ces-setup --version v0.6.0 --namespace default".trim()) + assertThat(scriptMock.allActualArgs[6].trim()).isEqualTo("sudo KUBECONFIG=leK3dWorkSpace/.k3d/.kube/config helm registry logout registry.cloudogu.com".trim()) + assertThat(scriptMock.allActualArgs[7].trim()).isEqualTo("sleep 1s") + assertThat(scriptMock.allActualArgs[8].trim()).isEqualTo("sudo KUBECONFIG=${workspaceEnvDir}/.k3d/.kube/config kubectl rollout status deployment/k8s-dogu-operator-controller-manager".trim()) assertThat(scriptMock.writeFileParams.get(0)).isNotNull() String setupYaml = scriptMock.writeFileParams.get(1) @@ -232,34 +238,27 @@ class K3dTest extends GroovyTestCase { def workspaceEnvDir = "leK3dWorkSpace" String tag = "v0.6.0" def scriptMock = new ScriptMock() - scriptMock.expectedShRetValueForScript.put("curl -s https://raw.githubusercontent.com/cloudogu/k8s-ces-setup/${tag}/k8s/k8s-ces-setup.yaml".toString(), "fake setup yaml with {{ .Namespace }}") - scriptMock.expectedShRetValueForScript.put("sudo KUBECONFIG=${workspaceEnvDir}/.k3d/.kube/config kubectl rollout status deployment/k8s-dogu-operator-controller-manager".toString(), "error rollout") scriptMock.expectedShRetValueForScript.put("curl -H \"Metadata-Flavor: Google\" http://169.254.169.254/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip", "192.168.56.2") + scriptMock.expectedShRetValueForScript.put("whoami", "jenkins") + scriptMock.expectedShRetValueForScript.put("cat /etc/passwd | grep jenkins", "jenkins:x:1000:1000:jenkins,,,:/home/jenkins:/bin/bash") + scriptMock.expectedShRetValueForScript.put("yq -i '.setup_json = load_str(\"k3d_setup.json\")' k3d_values.yaml", "fake") K3d sut = new K3d(scriptMock, "leWorkSpace", "leK3dWorkSpace", "path") // when - shouldFail(RuntimeException) { + String errorMsg = shouldFail(RuntimeException) { sut.setup(tag, [:], 1, 1) } // then + assertThat(errorMsg).isEqualTo("failed to wait for deployment/k8s-dogu-operator-controller-manager rollout: timeout") + assertThat(scriptMock.actualEcho.get(0)).isEqualTo("configuring setup...") - assertThat(scriptMock.actualEcho.get(1)).isEqualTo("Installing setup...") - assertThat(scriptMock.actualEcho.get(2)).isEqualTo("Wait for dogu-operator to be ready...") + assertThat(scriptMock.actualEcho.get(1)).isEqualTo("create values.yaml for setup deployment") - assertThat(scriptMock.actualShMapArgs[0].trim()).isEqualTo("curl -H \"Metadata-Flavor: Google\" http://169.254.169.254/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip") - assertThat(scriptMock.actualShMapArgs[1].trim()).isEqualTo("sudo KUBECONFIG=${workspaceEnvDir}/.k3d/.kube/config kubectl apply -f https://raw.githubusercontent.com/cloudogu/k8s-ces-setup/${tag}/k8s/k8s-ces-setup-config.yaml".trim()) - assertThat(scriptMock.writeFileParams.get(0)).isNotNull() - assertThat(scriptMock.actualShMapArgs[2].trim()).isEqualTo("sudo KUBECONFIG=${workspaceEnvDir}/.k3d/.kube/config kubectl create configmap k8s-ces-setup-json --from-file=setup.json".trim()) - assertThat(scriptMock.actualShMapArgs[3].trim()).isEqualTo("curl -s https://raw.githubusercontent.com/cloudogu/k8s-ces-setup/${tag}/k8s/k8s-ces-setup.yaml".trim()) - String setupYaml = scriptMock.writeFileParams.get(1) - assertThat(setupYaml).isNotNull() - assertThat(setupYaml.contains("{{ .Namespace }}")).isFalse() - assertThat(scriptMock.actualShMapArgs[4].trim()).isEqualTo("sudo KUBECONFIG=${workspaceEnvDir}/.k3d/.kube/config kubectl apply -f setup.yaml".trim()) - assertThat(scriptMock.actualShStringArgs[0].trim()).isEqualTo("sleep 1s") - assertThat(scriptMock.actualShMapArgs[5].trim()).isEqualTo("sudo KUBECONFIG=${workspaceEnvDir}/.k3d/.kube/config kubectl rollout status deployment/k8s-dogu-operator-controller-manager".trim()) + assertThat(scriptMock.allActualArgs[0].trim()).isEqualTo("curl -H \"Metadata-Flavor: Google\" http://169.254.169.254/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip") + assertThat(scriptMock.allActualArgs[1].trim()).isEqualTo("whoami".trim()) } void testK3d_installDogu() { @@ -402,6 +401,8 @@ spec: int fileCounter = 0 assertThat(scriptMock.allActualArgs[i++].trim()).contains("called deleteDir()") assertThat(scriptMock.allActualArgs[i++].trim()).contains("rm -rf k8sLogs.zip") + assertThat(scriptMock.allActualArgs[i++].trim()).contains("rm -rf k3d_setup.json") + assertThat(scriptMock.allActualArgs[i++].trim()).contains("rm -rf k3d_values.yaml") assertThat(scriptMock.allActualArgs[i++].trim()).contains("sudo KUBECONFIG=leK3dWorkSpace/.k3d/.kube/config kubectl get persistentvolumeclaim --show-kind --ignore-not-found -l app=ces -o yaml || true") assertThat(scriptMock.writeFileParams[fileCounter++]).isEqualTo(["file": "persistentvolumeclaim.yaml", "text": "value for persistentvolumeclaim"]) @@ -519,4 +520,105 @@ spec: assertThat(scriptMock.allActualArgs[0].trim()).contains("sudo KUBECONFIG=leK3dWorkSpace/.k3d/.kube/config kubectl apply -f target/make/k8s/testName.yaml") assertThat(scriptMock.allActualArgs.size()).isEqualTo(1) } + + void testK3d_configureSetupImage() { + // given + def workspaceDir = "leWorkspace" + def k3dWorkspaceDir = "leK3dWorkSpace" + def scriptMock = new ScriptMock() + K3d sut = new K3d(scriptMock, workspaceDir, k3dWorkspaceDir, "path") + + scriptMock.expectedShRetValueForScript.put("whoami".toString(), "jenkins") + scriptMock.expectedShRetValueForScript.put("cat /etc/passwd | grep jenkins", "jenkins:x:1000:1000:jenkins,,,:/home/jenkins:/bin/bash") + scriptMock.expectedShRetValueForScript.put("yq -i \".setup.image.repository = \\\"docker.io/foo/image\\\"\" k3d_values.yaml", "foo") + scriptMock.expectedShRetValueForScript.put("yq -i \".setup.image.tag = \\\"1.2.3\\\"\" k3d_values.yaml", "foo") + + // when + sut.configureSetupImage("docker.io/foo/image:1.2.3") + + // then + assertThat(scriptMock.allActualArgs[0].trim()).isEqualTo("whoami".trim()) + assertThat(scriptMock.allActualArgs[1].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) + assertThat(scriptMock.allActualArgs[2].trim()).isEqualTo("yq -i \".setup.image.repository = \\\"docker.io/foo/image\\\"\" k3d_values.yaml".trim()) + assertThat(scriptMock.allActualArgs[3].trim()).isEqualTo("whoami".trim()) + assertThat(scriptMock.allActualArgs[4].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) + assertThat(scriptMock.allActualArgs[5].trim()).isEqualTo("yq -i \".setup.image.tag = \\\"1.2.3\\\"\" k3d_values.yaml".trim()) + } + + void testK3d_configureComponentOperatorVersion() { + // given + def workspaceDir = "leWorkspace" + def k3dWorkspaceDir = "leK3dWorkSpace" + def scriptMock = new ScriptMock() + K3d sut = new K3d(scriptMock, workspaceDir, k3dWorkspaceDir, "path") + + scriptMock.expectedShRetValueForScript.put("whoami".toString(), "jenkins") + scriptMock.expectedShRetValueForScript.put("cat /etc/passwd | grep jenkins", "jenkins:x:1000:1000:jenkins,,,:/home/jenkins:/bin/bash") + scriptMock.expectedShRetValueForScript.put("yq -i \".component_operator_chart = \\\"test_ns/k8s-component-operator:1.2.3\\\"\" k3d_values.yaml", "foo") + scriptMock.expectedShRetValueForScript.put("yq -i \".component_operator_crd_chart = \\\"test_ns/k8s-component-operator-crd:4.5.6\\\"\" k3d_values.yaml", "foo") + + // when + sut.configureComponentOperatorVersion("1.2.3", "4.5.6", "test_ns") + + // then + assertThat(scriptMock.allActualArgs[0].trim()).isEqualTo("whoami".trim()) + assertThat(scriptMock.allActualArgs[1].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) + assertThat(scriptMock.allActualArgs[2].trim()).isEqualTo("yq -i \".component_operator_chart = \\\"test_ns/k8s-component-operator:1.2.3\\\"\" k3d_values.yaml".trim()) + assertThat(scriptMock.allActualArgs[3].trim()).isEqualTo("whoami".trim()) + assertThat(scriptMock.allActualArgs[4].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) + assertThat(scriptMock.allActualArgs[5].trim()).isEqualTo("yq -i \".component_operator_crd_chart = \\\"test_ns/k8s-component-operator-crd:4.5.6\\\"\" k3d_values.yaml".trim()) + } + + void testK3d_configureLogLevel() { + // given + def workspaceDir = "leWorkspace" + def k3dWorkspaceDir = "leK3dWorkSpace" + def scriptMock = new ScriptMock() + K3d sut = new K3d(scriptMock, workspaceDir, k3dWorkspaceDir, "path") + + scriptMock.expectedShRetValueForScript.put("whoami".toString(), "jenkins") + scriptMock.expectedShRetValueForScript.put("cat /etc/passwd | grep jenkins", "jenkins:x:1000:1000:jenkins,,,:/home/jenkins:/bin/bash") + scriptMock.expectedShRetValueForScript.put("yq -i \".logLevel = \\\"SUPER_ERROR\\\"\" k3d_values.yaml", "foo") + + // when + sut.configureLogLevel("SUPER_ERROR") + + // then + assertThat(scriptMock.allActualArgs[0].trim()).isEqualTo("whoami".trim()) + assertThat(scriptMock.allActualArgs[1].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) + assertThat(scriptMock.allActualArgs[2].trim()).isEqualTo("yq -i \".logLevel = \\\"SUPER_ERROR\\\"\" k3d_values.yaml".trim()) + } + + void testK3d_configureComponents() { + // given + def workspaceDir = "leWorkspace" + def k3dWorkspaceDir = "leK3dWorkSpace" + def scriptMock = new ScriptMock() + K3d sut = new K3d(scriptMock, workspaceDir, k3dWorkspaceDir, "path") + + scriptMock.expectedShRetValueForScript.put("whoami".toString(), "jenkins") + scriptMock.expectedShRetValueForScript.put("cat /etc/passwd | grep jenkins", "jenkins:x:1000:1000:jenkins,,,:/home/jenkins:/bin/bash") + scriptMock.expectedShRetValueForScript.put("yq -i \".components.k8s-etcd.version = \\\"latest\\\"\" k3d_values.yaml", "foo") + scriptMock.expectedShRetValueForScript.put("yq -i \".components.k8s-etcd.helmRepositoryNamespace = \\\"k8s\\\"\" k3d_values.yaml", "foo") + scriptMock.expectedShRetValueForScript.put("yq -i \".components.k8s-promtail.version = \\\"1.2.3\\\"\" k3d_values.yaml", "foo") + scriptMock.expectedShRetValueForScript.put("yq -i \".components.k8s-promtail.helmRepositoryNamespace = \\\"test_ns\\\"\" k3d_values.yaml", "foo") + + // when + sut.configureComponents(["k8s-etcd" : ["version": "latest", "helmRepositoryNamespace": "k8s"], + "k8s-promtail": ["version": "1.2.3", "helmRepositoryNamespace": "test_ns"]]) + + // then + assertThat(scriptMock.allActualArgs[0].trim()).isEqualTo("whoami".trim()) + assertThat(scriptMock.allActualArgs[1].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) + assertThat(scriptMock.allActualArgs[2].trim()).isEqualTo("yq -i \".components.k8s-etcd.version = \\\"latest\\\"\" k3d_values.yaml".trim()) + assertThat(scriptMock.allActualArgs[3].trim()).isEqualTo("whoami".trim()) + assertThat(scriptMock.allActualArgs[4].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) + assertThat(scriptMock.allActualArgs[5].trim()).isEqualTo("yq -i \".components.k8s-etcd.helmRepositoryNamespace = \\\"k8s\\\"\" k3d_values.yaml".trim()) + assertThat(scriptMock.allActualArgs[6].trim()).isEqualTo("whoami".trim()) + assertThat(scriptMock.allActualArgs[7].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) + assertThat(scriptMock.allActualArgs[8].trim()).isEqualTo("yq -i \".components.k8s-promtail.version = \\\"1.2.3\\\"\" k3d_values.yaml".trim()) + assertThat(scriptMock.allActualArgs[9].trim()).isEqualTo("whoami".trim()) + assertThat(scriptMock.allActualArgs[10].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) + assertThat(scriptMock.allActualArgs[11].trim()).isEqualTo("yq -i \".components.k8s-promtail.helmRepositoryNamespace = \\\"test_ns\\\"\" k3d_values.yaml".trim()) + } } diff --git a/test/com/cloudogu/ces/cesbuildlib/ScriptMock.groovy b/test/com/cloudogu/ces/cesbuildlib/ScriptMock.groovy index 08c54d4..18c3c77 100644 --- a/test/com/cloudogu/ces/cesbuildlib/ScriptMock.groovy +++ b/test/com/cloudogu/ces/cesbuildlib/ScriptMock.groovy @@ -168,6 +168,10 @@ class ScriptMock { return files.get(file) } + boolean fileExists(String file) { + return files.containsKey(file) + } + Object readJSON(Map args) { String text = args.get('text') if (text != null) { From 24518edad424e34d051e7e4b7c3f722db1e7256a Mon Sep 17 00:00:00 2001 From: Benjamin Ernst Date: Thu, 7 Dec 2023 16:05:56 +0100 Subject: [PATCH 08/13] #117 improve configureComponents to only use one yq command --- src/com/cloudogu/ces/cesbuildlib/K3d.groovy | 16 ++++++++++++---- test/com/cloudogu/ces/cesbuildlib/K3dTest.groovy | 11 +---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy index b198f48..b5e7d39 100644 --- a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy +++ b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy @@ -228,13 +228,17 @@ class K3d { } } - void appendToYamlFile(String file, String key, String value) { + void yqEvalYamlFile(String file, String eval) { createEmptySetupValuesYamlIfItDoesNotExists() doInYQContainer { - script.sh("yq -i \"${key} = \\\"${value}\\\"\" ${file}") + script.sh("yq -i \"${eval}\" ${file}") } } + void appendToYamlFile(String file, String key, String value) { + yqEvalYamlFile(file, "${key} = \\\"${value}\\\"") + } + void appendFileToYamlFile(String file, String key, String fileName) { createEmptySetupValuesYamlIfItDoesNotExists() doInYQContainer { @@ -283,12 +287,16 @@ class K3d { } void configureComponents(components = [:]) { - // TODO better solution + def evals = [] components.each { componentName, componentConfig -> componentConfig.each { configKey, configValue -> - appendToYamlFile(K3D_VALUES_YAML_FILE, ".components.${componentName}.${configKey}", configValue as String) + evals << ".components.${componentName}.${configKey} = \\\"${configValue}\\\"" } } + + if (evals.size() > 0) { + yqEvalYamlFile(K3D_VALUES_YAML_FILE, evals.join(" | ")) + } } void configureLogLevel(String loglevel) { diff --git a/test/com/cloudogu/ces/cesbuildlib/K3dTest.groovy b/test/com/cloudogu/ces/cesbuildlib/K3dTest.groovy index 557f51d..b65f327 100644 --- a/test/com/cloudogu/ces/cesbuildlib/K3dTest.groovy +++ b/test/com/cloudogu/ces/cesbuildlib/K3dTest.groovy @@ -610,15 +610,6 @@ spec: // then assertThat(scriptMock.allActualArgs[0].trim()).isEqualTo("whoami".trim()) assertThat(scriptMock.allActualArgs[1].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) - assertThat(scriptMock.allActualArgs[2].trim()).isEqualTo("yq -i \".components.k8s-etcd.version = \\\"latest\\\"\" k3d_values.yaml".trim()) - assertThat(scriptMock.allActualArgs[3].trim()).isEqualTo("whoami".trim()) - assertThat(scriptMock.allActualArgs[4].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) - assertThat(scriptMock.allActualArgs[5].trim()).isEqualTo("yq -i \".components.k8s-etcd.helmRepositoryNamespace = \\\"k8s\\\"\" k3d_values.yaml".trim()) - assertThat(scriptMock.allActualArgs[6].trim()).isEqualTo("whoami".trim()) - assertThat(scriptMock.allActualArgs[7].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) - assertThat(scriptMock.allActualArgs[8].trim()).isEqualTo("yq -i \".components.k8s-promtail.version = \\\"1.2.3\\\"\" k3d_values.yaml".trim()) - assertThat(scriptMock.allActualArgs[9].trim()).isEqualTo("whoami".trim()) - assertThat(scriptMock.allActualArgs[10].trim()).isEqualTo("cat /etc/passwd | grep jenkins".trim()) - assertThat(scriptMock.allActualArgs[11].trim()).isEqualTo("yq -i \".components.k8s-promtail.helmRepositoryNamespace = \\\"test_ns\\\"\" k3d_values.yaml".trim()) + assertThat(scriptMock.allActualArgs[2].trim()).isEqualTo("yq -i \".components.k8s-etcd.version = \\\"latest\\\" | .components.k8s-etcd.helmRepositoryNamespace = \\\"k8s\\\" | .components.k8s-promtail.version = \\\"1.2.3\\\" | .components.k8s-promtail.helmRepositoryNamespace = \\\"test_ns\\\"\" k3d_values.yaml".trim()) } } From a9becc20b72ad5efba029177334d4923b4152df9 Mon Sep 17 00:00:00 2001 From: Benjamin Ernst Date: Thu, 7 Dec 2023 16:33:08 +0100 Subject: [PATCH 09/13] #117 add changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c91cdf..0ad54a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed +- Use Helm to install and configure k8s-ces-setup in k3d; #117 ## [1.68.0](https://github.com/cloudogu/ces-build-lib/releases/tag/1.68.0) - 2023-11-30 ### Added From d6db3ca66ab4e57ba3d2a1067f82bbb0add8ddb0 Mon Sep 17 00:00:00 2001 From: kahoona77 Date: Fri, 8 Dec 2023 09:44:02 +0100 Subject: [PATCH 10/13] Update src/com/cloudogu/ces/cesbuildlib/K3d.groovy Co-authored-by: Jeremias Weber --- src/com/cloudogu/ces/cesbuildlib/K3d.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy index b5e7d39..4715958 100644 --- a/src/com/cloudogu/ces/cesbuildlib/K3d.groovy +++ b/src/com/cloudogu/ces/cesbuildlib/K3d.groovy @@ -319,7 +319,7 @@ class K3d { } /** - * Installs the setup to the cluster. Creates an example setup.json with plantuml as dogu and executes the setup. + * Installs the setup to the cluster. Creates an example setup.json with usermgt as dogu and executes the setup. * After that the method will wait until the dogu-operator is ready. * @param tag Tag of the setup e. g. "v0.6.0" * @param timout Timeout in seconds for the setup process e. g. 300 From bec22f17b9242ef77194ddfacff42965919c21fc Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 8 Dec 2023 09:57:08 +0100 Subject: [PATCH 11/13] Bump version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1d02b1b..c8839df 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ com.cloudogu.ces ces-build-lib ces-build-lib - 1.68.0 + 2.0.0 From 79d90bd7a281ffab545b15672bba03bf2c34e675 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 8 Dec 2023 09:57:18 +0100 Subject: [PATCH 12/13] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ad54a9..ed8f10a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] + +## [2.0.0](https://github.com/cloudogu/ces-build-lib/releases/tag/2.0.0) - 2023-12-08 ### Changed - Use Helm to install and configure k8s-ces-setup in k3d; #117 From d34e59188c2b1b491490b567d9d3d5819fe41422 Mon Sep 17 00:00:00 2001 From: Jeremias Weber Date: Fri, 8 Dec 2023 10:04:39 +0100 Subject: [PATCH 13/13] Update usage --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c9158e..6e2da38 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Jenkins Pipeline Shared library, that contains additional features for Git, Mave * Install [Pipeline: GitHub Groovy Libraries](https://wiki.jenkins.io/display/JENKINS/Pipeline+GitHub+Library+Plugin) * Use the Library in any Jenkinsfile like so ``` -@Library('github.com/cloudogu/ces-build-lib@1.67.0') +@Library('github.com/cloudogu/ces-build-lib@2.0.0') import com.cloudogu.ces.cesbuildlib.* ``` * Best practice: Use a defined version (e.g. a git commit hash or a git tag, such as `6cd41e0` or `1.67.0` in the example above) and not a branch such as `develop`. Otherwise, your build might change when the there is a new commit on the branch. Using branches is like using snapshots! @@ -1092,6 +1092,10 @@ try { // your image name may look like this: k3d-citest-123456/your/image:yourTag-1.2.3-dev // the image name can be applied to your cluster as usual, f. i. with k3d.kubectl() with a customized K8s resource } + + stage('execute k8s-ces-setup') { + k3d.setup('0.20.0') + } stage('install resources and wait for them') { imageName = "registry.cloudogu.com/official/my-dogu-name:1.0.0"