Skip to content

Commit 6d94501

Browse files
committed
Fix "helm values" call for local helm repos
For doing so, move logic to determine the path of the helm chart ot the individual repo types, instead of redundantly implementing them in Helm and ArgoCDRelease. Note that chartRepo field had to be removed in Helm class because calling a method like RepoType.create in the Helm() constructor causes Jenkins CPS errors like expected to call com.cloudogu.gitopsbuildlib.deployment.helm.Helm.<init> but wound up catching com.cloudogu.gitopsbuildlib.deployment.helm.Helm.createRepoType
1 parent 43b456e commit 6d94501

11 files changed

Lines changed: 90 additions & 56 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,15 +615,15 @@ git client checkout the default branch given within the HEADs meta information.
615615
it checks out the given version as expected.
616616

617617
#### Local Helm Chart
618-
The `repoType: LOCAL` can be used if you store the helm repository locally, e.g. in your Git Repository. A common
618+
The `repoType: LOCAL` can be used if you store the helm repository locally, i.e. in your Git Repository. A common
619619
pattern used in this context would be the "Umbrella pattern".
620620

621621
```groovy
622622
def gitopsConfig = [
623623
deployments: [
624624
helm : [
625625
repoType : 'LOCAL',
626-
chartPath: 'helm/chart',
626+
chartPath: 'helm/chart' /* Must be relative to jenkins WORKSPACE */,
627627
updateValues: [[fieldPath: "image.name", newValue: imageName]]
628628
]
629629
]

src/com/cloudogu/gitopsbuildlib/deployment/helm/Helm.groovy

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,18 @@ import com.cloudogu.gitopsbuildlib.deployment.SourceType
55
import com.cloudogu.gitopsbuildlib.deployment.helm.helmrelease.ArgoCDRelease
66
import com.cloudogu.gitopsbuildlib.deployment.helm.helmrelease.FluxV1Release
77
import com.cloudogu.gitopsbuildlib.deployment.helm.helmrelease.HelmRelease
8-
import com.cloudogu.gitopsbuildlib.deployment.helm.repotype.GitRepo
9-
import com.cloudogu.gitopsbuildlib.deployment.helm.repotype.HelmRepo
10-
import com.cloudogu.gitopsbuildlib.deployment.helm.repotype.LocalRepo
11-
import com.cloudogu.gitopsbuildlib.deployment.helm.repotype.RepoType
8+
import com.cloudogu.gitopsbuildlib.deployment.helm.repotype.RepoType
129

1310
class Helm extends Deployment {
1411

15-
protected RepoType chartRepo
1612
protected HelmRelease helmRelease
1713

18-
private String helmChartTempDir = ".helmChartTempDir"
19-
private String chartRootDir = "chart"
14+
public static final String HELM_CHART_TEMP_DIR = ".helmChartTempDir"
15+
public static final String CHART_ROOT_DIR = "chart"
2016

2117
Helm(def script, def gitopsConfig) {
2218
super(script, gitopsConfig)
2319
this.extraResourcesFolder = "extraResources"
24-
25-
if (gitopsConfig.deployments.helm.repoType == 'GIT') {
26-
chartRepo = new GitRepo(script)
27-
} else if (gitopsConfig.deployments.helm.repoType == 'HELM') {
28-
chartRepo = new HelmRepo(script)
29-
} else if (gitopsConfig.deployments.helm.repoType == 'LOCAL') {
30-
chartRepo = new LocalRepo(script)
31-
} else {
32-
script.error("Unknown helm repo type: ${gitopsConfig.deployments.helm.repoType}")
33-
}
3420

3521
if(gitopsConfig.gitopsTool == 'FLUX') {
3622
helmRelease = new FluxV1Release(script)
@@ -39,13 +25,13 @@ class Helm extends Deployment {
3925
}
4026
}
4127

42-
4328
@Override
4429
def preValidation(String stage) {
4530
def sourcePath = gitopsConfig.deployments.sourcePath
4631
def destinationPath = getDestinationFolder(getFolderStructureStrategy(), stage)
4732

48-
chartRepo.prepareRepo(gitopsConfig, helmChartTempDir, chartRootDir)
33+
RepoType repoType = RepoType.create(gitopsConfig.deployments.helm.repoType, script)
34+
repoType.prepareRepo(gitopsConfig, HELM_CHART_TEMP_DIR, CHART_ROOT_DIR)
4935

5036
// writing the merged-values.yaml via writeYaml into a file has the advantage, that it gets formatted as valid yaml
5137
// This makes it easier to read in and indent for the inline use in the helmRelease.
@@ -56,17 +42,17 @@ class Helm extends Deployment {
5642
if (script.fileExists("${script.env.WORKSPACE}/${sourcePath}/values-shared.yaml")) {
5743
valueFiles.add("${script.env.WORKSPACE}/${sourcePath}/values-shared.yaml")
5844
}
59-
script.writeFile file: "${script.env.WORKSPACE}/${helmChartTempDir}/mergedValues.yaml", text: mergeValuesFiles(gitopsConfig, valueFiles as String[])
45+
script.writeFile file: "${script.env.WORKSPACE}/${HELM_CHART_TEMP_DIR}/mergedValues.yaml", text: mergeValuesFiles(gitopsConfig, valueFiles as String[], repoType)
6046

61-
updateYamlValue("${script.env.WORKSPACE}/${helmChartTempDir}/mergedValues.yaml", gitopsConfig)
47+
updateYamlValue("${script.env.WORKSPACE}/${HELM_CHART_TEMP_DIR}/mergedValues.yaml", gitopsConfig)
6248

63-
script.writeFile file: "${destinationPath}/applicationRelease.yaml", text: helmRelease.create(gitopsConfig, getNamespace(stage), "${script.env.WORKSPACE}/${helmChartTempDir}/mergedValues.yaml")
49+
script.writeFile file: "${destinationPath}/applicationRelease.yaml", text: helmRelease.create(gitopsConfig, getNamespace(stage), "${script.env.WORKSPACE}/${HELM_CHART_TEMP_DIR}/mergedValues.yaml")
6450
}
6551

6652
@Override
6753
def postValidation(String stage) {
6854
// clean the helm chart folder since the validation on this helm chart is done
69-
script.sh "rm -rf ${script.env.WORKSPACE}/${helmChartTempDir} || true"
55+
script.sh "rm -rf ${script.env.WORKSPACE}/${HELM_CHART_TEMP_DIR} || true"
7056
}
7157

7258
@Override
@@ -75,7 +61,7 @@ class Helm extends Deployment {
7561

7662
gitopsConfig.validators.each { validator ->
7763
validator.value.validator.validate(validator.value.enabled, getGitopsTool(), SourceType.PLAIN, "${destinationPath}", validator.value.config, gitopsConfig)
78-
validator.value.validator.validate(validator.value.enabled, getGitopsTool(), SourceType.HELM, "${script.env.WORKSPACE}/${helmChartTempDir}",validator.value.config, gitopsConfig)
64+
validator.value.validator.validate(validator.value.enabled, getGitopsTool(), SourceType.HELM, "${script.env.WORKSPACE}/${HELM_CHART_TEMP_DIR}",validator.value.config, gitopsConfig)
7965
}
8066
}
8167

@@ -97,20 +83,14 @@ class Helm extends Deployment {
9783
script.writeYaml file: yamlFilePath, data: data, overwrite: true
9884
}
9985

100-
private String mergeValuesFiles(Map gitopsConfig, String[] valuesFiles) {
101-
def helmConfig = gitopsConfig.deployments.helm
86+
private String mergeValuesFiles(Map gitopsConfig, String[] valuesFiles, RepoType repoType) {
10287

10388
String mergedValuesFile = ""
10489

105-
def chartDir = ''
106-
if (helmConfig.containsKey('chartPath') && helmConfig.chartPath) {
107-
chartDir = helmConfig.chartPath
108-
} else if ( helmConfig.containsKey('chartName')) {
109-
chartDir = helmConfig.chartName
110-
}
90+
def chartPath = repoType.getChartPath(gitopsConfig, HELM_CHART_TEMP_DIR, CHART_ROOT_DIR)
11191

11292
withDockerImage(gitopsConfig.buildImages.helm) {
113-
String helmScript = "helm values ${script.env.WORKSPACE}/${helmChartTempDir}/${chartRootDir}/${chartDir} ${valuesFilesWithParameter(valuesFiles)}"
93+
String helmScript = "helm values ${chartPath} ${valuesFilesWithParameter(valuesFiles)}"
11494
mergedValuesFile = script.sh returnStdout: true, script: helmScript
11595
}
11696
return mergedValuesFile

src/com/cloudogu/gitopsbuildlib/deployment/helm/helmrelease/ArgoCDRelease.groovy

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.cloudogu.gitopsbuildlib.deployment.helm.helmrelease
22

3+
import com.cloudogu.gitopsbuildlib.deployment.helm.Helm
4+
import com.cloudogu.gitopsbuildlib.deployment.helm.repotype.RepoType
35
import com.cloudogu.gitopsbuildlib.docker.DockerWrapper
46

57
class ArgoCDRelease extends HelmRelease {
@@ -23,31 +25,24 @@ class ArgoCDRelease extends HelmRelease {
2325
} else if (helmConfig.repoType == 'LOCAL') {
2426
return createResourcesFromLocalRepo(gitopsConfig, application, namespace, mergedValuesFile)
2527
}
26-
return null // Validated in base class Helm
28+
return null // Validated in deployViaGitOps.groovy
2729
}
2830

2931
private String createResourcesFromGitRepo(Map gitopsConfig, String application, String namespace, String mergedValuesFile) {
30-
Map helmConfig = gitopsConfig.deployments.helm
31-
32-
def chartPath = "${script.env.WORKSPACE}/.helmChartTempDir/chart/"
33-
if (helmConfig.containsKey('chartPath')) {
34-
chartPath += helmConfig.chartPath
35-
}
36-
37-
return createHelmRelease(gitopsConfig, chartPath as String, application, namespace, gitopsConfig.buildImages.helm, mergedValuesFile)
32+
return createHelmRelease(gitopsConfig, application, namespace, gitopsConfig.buildImages.helm, mergedValuesFile)
3833
}
3934

4035
private String createResourcesFromHelmRepo(Map gitopsConfig, String application, String namespace, String mergedValuesFile) {
41-
String chartPath = "${script.env.WORKSPACE}/.helmChartTempDir/chart/${gitopsConfig.deployments.helm.chartName}"
42-
return createHelmRelease(gitopsConfig, chartPath, application, namespace, gitopsConfig.buildImages.helm, mergedValuesFile)
36+
return createHelmRelease(gitopsConfig, application, namespace, gitopsConfig.buildImages.helm, mergedValuesFile)
4337
}
4438

4539
private String createResourcesFromLocalRepo(Map gitopsConfig, String application, String namespace, String mergedValuesFile) {
46-
return createHelmRelease(gitopsConfig, gitopsConfig.deployments.helm.chartPath, application, namespace, gitopsConfig.buildImages.helm, mergedValuesFile)
40+
return createHelmRelease(gitopsConfig, application, namespace, gitopsConfig.buildImages.helm, mergedValuesFile)
4741
}
4842

49-
private String createHelmRelease(Map gitopsConfig, def chartPath, String application, String namespace, def helmImageConfig, String mergedValuesFile) {
43+
private String createHelmRelease(Map gitopsConfig, String application, String namespace, def helmImageConfig, String mergedValuesFile) {
5044
String helmRelease = ""
45+
def chartPath = RepoType.create(gitopsConfig.deployments.helm.repoType, script).getChartPath(gitopsConfig, Helm.HELM_CHART_TEMP_DIR, Helm.CHART_ROOT_DIR)
5146
dockerWrapper.withDockerImage(helmImageConfig) {
5247
String templateScript = "helm template ${application} ${chartPath} -n ${namespace} --kube-version ${gitopsConfig.k8sVersion} -f ${mergedValuesFile}"
5348
helmRelease = script.sh returnStdout: true, script: templateScript

src/com/cloudogu/gitopsbuildlib/deployment/helm/helmrelease/FluxV1Release.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,6 @@ ${values}
5555
} else if (helmConfig.repoType == 'LOCAL') {
5656
return script.error("Helm repoType LOCAL not supported for fluxv1")
5757
}
58-
return null // Validated in base class Helm
58+
return null // Validated in deployViaGitOps.groovy
5959
}
6060
}

src/com/cloudogu/gitopsbuildlib/deployment/helm/repotype/GitRepo.groovy

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ class GitRepo extends RepoType {
66
super(script)
77
}
88

9+
@Override
10+
String getChartPath(Map gitopsConfig, String helmChartTempDir, String chartRootDir) {
11+
def helmConfig = gitopsConfig.deployments.helm
12+
def chartPath = ''
13+
if (helmConfig.containsKey('chartPath') && helmConfig.chartPath) {
14+
chartPath = helmConfig.chartPath
15+
}
16+
17+
return "${script.env.WORKSPACE}/${helmChartTempDir}/${chartRootDir}/${chartPath}"
18+
}
19+
920
@Override
1021
void prepareRepo(Map gitopsConfig, String helmChartTempDir, String chartRootDir) {
1122
def helmConfig = gitopsConfig.deployments.helm

src/com/cloudogu/gitopsbuildlib/deployment/helm/repotype/HelmRepo.groovy

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ class HelmRepo extends RepoType {
66
super(script)
77
}
88

9+
@Override
10+
String getChartPath(Map gitopsConfig, String helmChartTempDir, String chartRootDir) {
11+
return "${script.env.WORKSPACE}/${helmChartTempDir}/${chartRootDir}/${gitopsConfig.deployments.helm.chartName}"
12+
}
13+
914
@Override
1015
void prepareRepo(Map gitopsConfig, String helmChartTempDir, String chartRootDir) {
1116
def helmConfig = gitopsConfig.deployments.helm

src/com/cloudogu/gitopsbuildlib/deployment/helm/repotype/LocalRepo.groovy

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,16 @@ class LocalRepo extends RepoType {
88

99
@Override
1010
void prepareRepo(Map gitopsConfig, String helmChartTempDir, String chartRootDir) {
11+
// Nothing to prepare for a local chart
12+
}
13+
14+
@Override
15+
String getChartPath(Map gitopsConfig, String helmChartTempDir, String chartRootDir) {
16+
def chartPath = gitopsConfig.deployments.helm.chartPath
17+
// Use absolute paths, so e.g. helm values works in .configRepoTempDir
18+
if (!chartRootDir.contains(script.env.WORKSPACE)) {
19+
chartPath = "${script.env.WORKSPACE}/${chartPath}"
20+
}
21+
return "${chartPath}"
1122
}
1223
}

src/com/cloudogu/gitopsbuildlib/deployment/helm/repotype/RepoType.groovy

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,21 @@ abstract class RepoType {
1313
}
1414

1515
abstract void prepareRepo(Map gitopsConfig, String helmChartTempDir, String chartRootDir)
16-
16+
abstract String getChartPath(Map gitopsConfig, String helmChartTempDir, String chartRootDir)
17+
1718
void withDockerImage(def imageConfig, Closure body) {
1819
dockerWrapper.withDockerImage(imageConfig, body)
1920
}
21+
22+
static RepoType create(String potentialRepoType, def script) {
23+
RepoType repoType = null
24+
if (potentialRepoType == 'GIT') {
25+
repoType = new GitRepo(script)
26+
} else if (potentialRepoType == 'HELM') {
27+
repoType = new HelmRepo(script)
28+
} else if (potentialRepoType == 'LOCAL') {
29+
repoType = new LocalRepo(script)
30+
}
31+
return repoType
32+
}
2033
}

test/com/cloudogu/gitopsbuildlib/deployment/HelmTest.groovy

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,20 @@ class HelmTest {
3131
version: '1.0'
3232
]
3333
]
34+
35+
def localRepo = [
36+
sourcePath: 'k8s',
37+
destinationRootPath: '.',
38+
helm : [
39+
repoType: 'LOCAL',
40+
chartPath: 'chart/path'
41+
]
42+
]
3443

35-
private Map getGitopsConfig(Map deployment) {
44+
private Map getGitopsConfig(Map deployment, String tool = 'FLUX') {
3645
return [
3746
application: 'app',
38-
gitopsTool: 'FLUX',
47+
gitopsTool: tool,
3948
stages: [
4049
staging: [
4150
namespace: 'fluxv1-staging'
@@ -88,6 +97,7 @@ class HelmTest {
8897
def dockerMock = scriptMock.dockerMock
8998
def helmGit = new Helm(scriptMock.mock, getGitopsConfig(gitRepo))
9099
def helmHelm = new Helm(scriptMock.mock, getGitopsConfig(helmRepo))
100+
def helmLocal = new Helm(scriptMock.mock, getGitopsConfig(localRepo, 'ARGO'))
91101

92102
@Test
93103
void 'creating helm release with git repo'() {
@@ -289,6 +299,13 @@ spec:
289299

290300
assertThat(scriptMock.actualShArgs[0]).isEqualTo('yamllint -f standard staging/app')
291301
assertThat(scriptMock.actualShArgs[1]).isEqualTo('kubeval -d staging/app -v null --strict --ignore-missing-schemas')
302+
}
303+
304+
@Test
305+
void 'creating helm release with local repo'() {
306+
helmLocal.preValidation('staging')
292307

308+
assertThat(dockerMock.actualImages[0]).contains('helmImage')
309+
assertThat(scriptMock.actualShArgs[0]).isEqualTo('[returnStdout:true, script:helm values workspace/chart/path -f workspace/k8s/values-staging.yaml -f workspace/k8s/values-shared.yaml ]')
293310
}
294311
}

test/com/cloudogu/gitopsbuildlib/deployment/helm/helmrelease/ArgoCDReleaseTest.groovy

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class ArgoCDReleaseTest {
9797
deployments: [
9898
helm: [
9999
repoType : 'LOCAL',
100-
chartPath: '/my/path',
100+
chartPath: 'my/path',
101101
version : '1.0'
102102
]
103103
],
@@ -112,8 +112,6 @@ class ArgoCDReleaseTest {
112112

113113
assertThat(scriptMock.dockerMock.actualImages[0]).isEqualTo('helmImg')
114114
assertThat(scriptMock.actualShArgs[0]).isEqualTo('[returnStdout:true, ' +
115-
'script:helm template app /my/path -n namespace --kube-version 1.24.8 -f this/is/a/valuesfile]')
115+
'script:helm template app workspace/my/path -n namespace --kube-version 1.24.8 -f this/is/a/valuesfile]')
116116
}
117-
118-
119117
}

0 commit comments

Comments
 (0)