diff --git a/CHANGELOG.md b/CHANGELOG.md index d55d2352aa..d6d3aac34a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Usage: ``` ### 1.15-SNAPSHOT * Fix #2138: Support for Spring Boot Native Image +* Fix #2200: Support for Helm `values.yaml` fragments * Fix #2356: Helm values.yaml parameter names preserve case * Fix #2369: Helm chart apiVersion can be configured * Fix #2386: Helm icon inferred from annotations in independent resource files (not aggregated kubernetes/openshift.yaml) diff --git a/gradle-plugin/it/src/it/helm-dsl/expected/values.yaml b/gradle-plugin/it/src/it/helm-dsl/expected/values.yaml new file mode 100644 index 0000000000..2fbf0ffd71 --- /dev/null +++ b/gradle-plugin/it/src/it/helm-dsl/expected/values.yaml @@ -0,0 +1 @@ +--- {} diff --git a/gradle-plugin/it/src/it/helm-fragment-and-dsl/build.gradle b/gradle-plugin/it/src/it/helm-fragment-and-dsl/build.gradle index c33d2b4fb0..3faf53d38b 100644 --- a/gradle-plugin/it/src/it/helm-fragment-and-dsl/build.gradle +++ b/gradle-plugin/it/src/it/helm-fragment-and-dsl/build.gradle @@ -32,6 +32,7 @@ def extensionConfig = { name = 'repository/helm-dsl:latest' build { from = 'repository/from:latest' + ports = [8080] } } } @@ -53,6 +54,13 @@ def extensionConfig = { url = 'https://example.com/user1' }] icon = 'https://example.com/icon-is-overridden' + parameters = [{ + name = 'replicaCount' + value = 1 + }, { + name = 'imagePullPolicy' + value = '{{ .Values.deployment.imagePullPolicy }}' + }] } } diff --git a/gradle-plugin/it/src/it/helm-fragment-and-dsl/expected/values.yaml b/gradle-plugin/it/src/it/helm-fragment-and-dsl/expected/values.yaml new file mode 100644 index 0000000000..cb3d8d1c48 --- /dev/null +++ b/gradle-plugin/it/src/it/helm-fragment-and-dsl/expected/values.yaml @@ -0,0 +1,4 @@ +--- +replicaCount: "1" +deployment: + imagePullPolicy: "Always" diff --git a/gradle-plugin/it/src/it/helm-fragment-and-dsl/src/main/jkube/deployment.yaml b/gradle-plugin/it/src/it/helm-fragment-and-dsl/src/main/jkube/deployment.yaml new file mode 100644 index 0000000000..5c35313c99 --- /dev/null +++ b/gradle-plugin/it/src/it/helm-fragment-and-dsl/src/main/jkube/deployment.yaml @@ -0,0 +1,20 @@ +# +# Copyright (c) 2019 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at: +# +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Red Hat, Inc. - initial API and implementation +# + +spec: + replicas: ${replicaCount} + template: + spec: + containers: + - imagePullPolicy: ${imagePullPolicy} diff --git a/gradle-plugin/it/src/it/helm-fragment-and-dsl/src/main/jkube/values.helm.yaml b/gradle-plugin/it/src/it/helm-fragment-and-dsl/src/main/jkube/values.helm.yaml new file mode 100644 index 0000000000..53318f78c3 --- /dev/null +++ b/gradle-plugin/it/src/it/helm-fragment-and-dsl/src/main/jkube/values.helm.yaml @@ -0,0 +1,16 @@ +# +# Copyright (c) 2019 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at: +# +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Red Hat, Inc. - initial API and implementation +# + +deployment: + imagePullPolicy: Always diff --git a/gradle-plugin/it/src/it/helm-fragment/expected/values.yaml b/gradle-plugin/it/src/it/helm-fragment/expected/values.yaml new file mode 100644 index 0000000000..6d32760455 --- /dev/null +++ b/gradle-plugin/it/src/it/helm-fragment/expected/values.yaml @@ -0,0 +1,12 @@ +replicaCount: 1 + +image: + repository: nginx + +ingress: + enabled: false + className: "" + annotations: + kubernetes.io/ingress.class: nginx + kubernetes.io/tls-acme: "true" + tls: [] diff --git a/gradle-plugin/it/src/it/helm-fragment/src/main/jkube/values.helm.yaml b/gradle-plugin/it/src/it/helm-fragment/src/main/jkube/values.helm.yaml new file mode 100644 index 0000000000..b1c4a842cd --- /dev/null +++ b/gradle-plugin/it/src/it/helm-fragment/src/main/jkube/values.helm.yaml @@ -0,0 +1,26 @@ +# +# Copyright (c) 2019 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at: +# +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Red Hat, Inc. - initial API and implementation +# + +replicaCount: 1 + +image: + repository: nginx + +ingress: + enabled: false + className: "" + annotations: + kubernetes.io/ingress.class: nginx + kubernetes.io/tls-acme: "true" + tls: [] diff --git a/gradle-plugin/it/src/it/helm-properties/expected/values.yaml b/gradle-plugin/it/src/it/helm-properties/expected/values.yaml new file mode 100644 index 0000000000..2fbf0ffd71 --- /dev/null +++ b/gradle-plugin/it/src/it/helm-properties/expected/values.yaml @@ -0,0 +1 @@ +--- {} diff --git a/gradle-plugin/it/src/it/helm-zero-config/expected/values.yaml b/gradle-plugin/it/src/it/helm-zero-config/expected/values.yaml new file mode 100644 index 0000000000..2fbf0ffd71 --- /dev/null +++ b/gradle-plugin/it/src/it/helm-zero-config/expected/values.yaml @@ -0,0 +1 @@ +--- {} diff --git a/gradle-plugin/it/src/test/java/org/eclipse/jkube/gradle/plugin/tests/HelmIT.java b/gradle-plugin/it/src/test/java/org/eclipse/jkube/gradle/plugin/tests/HelmIT.java index 93d6845e24..353a35cd9d 100644 --- a/gradle-plugin/it/src/test/java/org/eclipse/jkube/gradle/plugin/tests/HelmIT.java +++ b/gradle-plugin/it/src/test/java/org/eclipse/jkube/gradle/plugin/tests/HelmIT.java @@ -34,21 +34,39 @@ class HelmIT { "helm-properties", "helm-zero-config" }) - void k8sResourceHelmFromFragment_whenRun_generatesK8sManifestsAndHelmChart(String projectName) throws Exception { + void k8sResourceHelmFromFragment_whenRun_generatesHelmChart(String projectName) throws Exception { // When final BuildResult result = gradleRunner.withITProject(projectName) .withArguments("clean", "k8sResource", "k8sHelm").build(); // Then - ResourceVerify.verifyResourceDescriptors(gradleRunner.resolveDefaultKubernetesHelmMetadataFile(projectName), - gradleRunner.resolveFile("expected", "Chart.yaml")); + ResourceVerify.verifyResourceDescriptors( + gradleRunner.resolveFile("build", "jkube", "helm", projectName, "kubernetes", "Chart.yaml"), + gradleRunner.resolveFile("expected", "Chart.yaml")); assertThat(result).extracting(BuildResult::getOutput).asString() .contains("Using resource templates from") - .contains("Adding a default Deployment") .contains("Adding revision history limit to 2") .contains("validating") .contains(String.format("Creating Helm Chart \"%s\" for Kubernetes", projectName)); } + @ParameterizedTest(name = "k8sResource k8sHelm with {0}") + @ValueSource(strings = { + "helm-dsl", + "helm-fragment", + "helm-fragment-and-dsl", + "helm-properties", + "helm-zero-config" + }) + void k8sResourceHelmFromFragment_whenRun_generatesHelmValues(String projectName) throws Exception { + // When + final BuildResult result = gradleRunner.withITProject(projectName) + .withArguments("clean", "k8sResource", "k8sHelm").build(); + // Then + ResourceVerify.verifyResourceDescriptors( + gradleRunner.resolveFile("build", "jkube", "helm", projectName, "kubernetes", "values.yaml"), + gradleRunner.resolveFile("expected", "values.yaml")); + } + @ParameterizedTest(name = "ocResource ocHelm with {0}") @ValueSource(strings = { "helm-dsl", @@ -57,16 +75,16 @@ void k8sResourceHelmFromFragment_whenRun_generatesK8sManifestsAndHelmChart(Strin "helm-properties", "helm-zero-config" }) - void ocResourceHelmFromFragment_whenRun_generatesOpenShiftManifestsAndHelmChart(String projectName) throws Exception { + void ocResourceHelmFromFragment_whenRun_generatesHelmChart(String projectName) throws Exception { // When final BuildResult result = gradleRunner.withITProject(projectName) .withArguments("clean", "ocResource", "ocHelm").build(); // Then - ResourceVerify.verifyResourceDescriptors(gradleRunner.resolveDefaultOpenShiftHelmMetadataFile(projectName), - gradleRunner.resolveFile("expected", "Chart.yaml")); + ResourceVerify.verifyResourceDescriptors( + gradleRunner.resolveFile("build", "jkube", "helm", projectName, "openshift", "Chart.yaml"), + gradleRunner.resolveFile("expected", "Chart.yaml")); assertThat(result).extracting(BuildResult::getOutput).asString() .contains("Using resource templates from") - .contains("Adding a default Deployment") .contains("Adding revision history limit to 2") .contains("validating") .contains(String.format("Creating Helm Chart \"%s\" for OpenShift", projectName)); diff --git a/gradle-plugin/it/src/test/java/org/eclipse/jkube/gradle/plugin/tests/ITGradleRunnerExtension.java b/gradle-plugin/it/src/test/java/org/eclipse/jkube/gradle/plugin/tests/ITGradleRunnerExtension.java index d4916c8b7d..83b0a034bb 100644 --- a/gradle-plugin/it/src/test/java/org/eclipse/jkube/gradle/plugin/tests/ITGradleRunnerExtension.java +++ b/gradle-plugin/it/src/test/java/org/eclipse/jkube/gradle/plugin/tests/ITGradleRunnerExtension.java @@ -66,14 +66,6 @@ public File resolveFile(String... relativePaths) { return path.toFile(); } - public File resolveDefaultKubernetesHelmMetadataFile(String projectName) { - return resolveFile("build", "jkube", "helm", projectName, "kubernetes", "Chart.yaml"); - } - - public File resolveDefaultOpenShiftHelmMetadataFile(String projectName) { - return resolveFile("build", "jkube", "helm", projectName, "openshift", "Chart.yaml"); - } - public File resolveDefaultKubernetesResourceFile() { return resolveFile("build", "classes", "java", "main", "META-INF", "jkube", "kubernetes.yml"); } diff --git a/jkube-kit/doc/src/main/asciidoc/inc/helm/_jkube_helm.adoc b/jkube-kit/doc/src/main/asciidoc/inc/helm/_jkube_helm.adoc index 93635a71e6..e2768c9308 100644 --- a/jkube-kit/doc/src/main/asciidoc/inc/helm/_jkube_helm.adoc +++ b/jkube-kit/doc/src/main/asciidoc/inc/helm/_jkube_helm.adoc @@ -3,24 +3,29 @@ ifeval::["{plugin-type}" == "maven"] This goal is for creating https://helm.sh/docs/topics/charts[Helm charts] -for your Maven project so that you can install, update or delete your app in Kubernetes +for your Maven project so that you can install, update, or delete your app in Kubernetes using https://github.com/helm/helm[Helm]. -For creating a Helm chart you simply call `{goal-prefix}:helm` goal on the command line: +To generate the Helm chart you simply need to call `{goal-prefix}:helm` goal on the command line: + include::maven/_resource_helm.adoc[] -The `{goal-prefix}:resource` goal is required to create the resource descriptors which are included in the Helm chart. -If you have already built the resource then you can omit this goal. + +[NOTE] +The `{goal-prefix}:resource` goal is required to create the resource descriptors that are included in the Helm chart. +If you have already generated the resources in a previous step then you can omit this goal. endif::[] ifeval::["{plugin-type}" == "gradle"] This task is for creating https://helm.sh/docs/topics/charts[Helm charts] -for your Gradle project so that you can install, update or delete your app in Kubernetes +for your Gradle project so that you can install, update, or delete your app in Kubernetes using https://github.com/helm/helm[Helm]. -For creating a Helm chart you simply call `{task-prefix}Helm` task on the command line: +To generate the Helm chart you simply need to call `{task-prefix}Helm` task on the command line: + include::gradle/_resource_helm.adoc[] -The `{task-prefix}Resource` goal is required to create the resource descriptors which are included in the Helm chart. -If you have already built the resource then you can omit this task. +[NOTE] +The `{task-prefix}Resource` goal is required to create the resource descriptors that are included in the Helm chart. +If you have already generated the resources in a previous step then you can omit this task. endif::[] @@ -230,10 +235,23 @@ Defaults to empty string. | In case we are generating a `.Values` variable, the default value. In case the placeholder has to be replaced by an expression, the Golang expression - e.g. `{{ .Chart.Name | upper }}`. + e.g. `{{ .Chart.Name \| upper }}`. |=== +=== Helm-specific fragments + +In addition to the standard Kubernetes <>, you can also provide fragments for Helm `Chart.yaml` and `values.yaml` files. + +For the `Chart.yaml` file you can provide a `Chart.helm.yaml` fragment in the `src/main/jkube` directory. + +For the `values.yaml` file you can provide a `values.helm.yaml` fragment in the `src/main/jkube` directory. + +These fragments will be merged with the opinionated and configured defaults. +The values provided in the fragments will override any of the generated default values taking precedence over them. + +=== Installing the generated Helm chart + In a next step you can install this via the https://github.com/helm/helm/releases[helm command line tool] as follows: ifeval::["{plugin-type}" == "maven"] diff --git a/jkube-kit/resource/helm/src/main/java/org/eclipse/jkube/kit/resource/helm/HelmService.java b/jkube-kit/resource/helm/src/main/java/org/eclipse/jkube/kit/resource/helm/HelmService.java index f0e6b08c88..0250772a49 100644 --- a/jkube-kit/resource/helm/src/main/java/org/eclipse/jkube/kit/resource/helm/HelmService.java +++ b/jkube-kit/resource/helm/src/main/java/org/eclipse/jkube/kit/resource/helm/HelmService.java @@ -22,11 +22,11 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.Properties; import java.util.function.Consumer; import java.util.function.UnaryOperator; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.eclipse.jkube.kit.common.JKubeConfiguration; import org.eclipse.jkube.kit.common.KitLogger; @@ -69,6 +69,9 @@ public class HelmService { private static final String CHART_FRAGMENT_REGEX = "^chart\\.helm\\.(?yaml|yml|json)$"; public static final Pattern CHART_FRAGMENT_PATTERN = Pattern.compile(CHART_FRAGMENT_REGEX, Pattern.CASE_INSENSITIVE); + private static final String VALUES_FRAGMENT_REGEX = "^values\\.helm\\.(?yaml|yml|json)$"; + public static final Pattern VALUES_FRAGMENT_PATTERN = Pattern.compile(VALUES_FRAGMENT_REGEX, Pattern.CASE_INSENSITIVE); + private final JKubeConfiguration jKubeConfiguration; private final ResourceServiceConfig resourceServiceConfig; private final KitLogger logger; @@ -230,11 +233,9 @@ private static void splitAndSaveTemplate(Template template, File templatesDir) t private void createChartYaml(HelmConfig helmConfig, File outputDir) throws IOException { final Chart chartFromHelmConfig = chartFromHelmConfig(helmConfig); - final Chart chartFromFragment = createChartFromFragment(resourceServiceConfig, jKubeConfiguration.getProperties()); + final Chart chartFromFragment = readFragment(CHART_FRAGMENT_PATTERN, Chart.class); final Chart mergedChart = Serialization.merge(chartFromHelmConfig, chartFromFragment); - - final File outputChartFile = new File(outputDir, CHART_FILENAME); - ResourceUtil.save(outputChartFile, mergedChart, ResourceFileType.yaml); + ResourceUtil.save(new File(outputDir, CHART_FILENAME), mergedChart, ResourceFileType.yaml); } private static Chart chartFromHelmConfig(HelmConfig helmConfig) { @@ -253,14 +254,14 @@ private static Chart chartFromHelmConfig(HelmConfig helmConfig) { .build(); } - private static Chart createChartFromFragment(ResourceServiceConfig resourceServiceConfig, Properties properties) { - File helmChartFragment = resolveHelmFragment(CHART_FRAGMENT_PATTERN, resourceServiceConfig); - if (helmChartFragment != null && helmChartFragment.exists()) { + private T readFragment(Pattern filePattern, Class type) { + final File helmChartFragment = resolveHelmFragment(filePattern, resourceServiceConfig); + if (helmChartFragment != null) { try { - String interpolatedFragmentContent = interpolate(helmChartFragment, properties, DEFAULT_FILTER); - return Serialization.unmarshal(interpolatedFragmentContent, Chart.class); + return Serialization.unmarshal( + interpolate(helmChartFragment, jKubeConfiguration.getProperties(), DEFAULT_FILTER), type); } catch (Exception e) { - throw new IllegalArgumentException("Failure in parsing Helm Chart fragment: " + e.getMessage(), e); + throw new IllegalArgumentException("Failure in parsing Helm fragment (" + helmChartFragment.getName() + "): " + e.getMessage(), e); } } return null; @@ -272,8 +273,8 @@ private static File resolveHelmFragment(Pattern filePattern, ResourceServiceConf for (File fragmentDir : fragmentDirs) { if (fragmentDir.exists() && fragmentDir.isDirectory()) { final File[] fragments = fragmentDir.listFiles((dir, name) -> filePattern.matcher(name).matches()); - if (fragments != null && fragments.length > 0) { - return fragments[0]; + if (fragments != null) { + return Stream.of(fragments).filter(File::exists).findAny().orElse(null); } } } @@ -320,15 +321,15 @@ private static void interpolateChartTemplates(List helmParameters } } - private static void createValuesYaml(List helmParameters, File outputDir) throws IOException { - final Map values = helmParameters.stream() + private void createValuesYaml(List helmParameters, File outputDir) throws IOException { + final Map valuesFromParameters = helmParameters.stream() .filter(hp -> hp.getValue() != null) // Placeholders replaced by Go expressions don't need to be persisted in the values.yaml file .filter(hp -> !hp.isGolangExpression()) .collect(Collectors.toMap(HelmParameter::getName, HelmParameter::getValue)); - - final File outputValuesFile = new File(outputDir, VALUES_FILENAME); - ResourceUtil.save(outputValuesFile, getNestedMap(values), ResourceFileType.yaml); + final Map valuesFromFragment = readFragment(VALUES_FRAGMENT_PATTERN, Map.class); + final Map mergedValues = Serialization.merge(getNestedMap(valuesFromParameters), valuesFromFragment); + ResourceUtil.save(new File(outputDir, VALUES_FILENAME), mergedValues, ResourceFileType.yaml); } private static List collectParameters(HelmConfig helmConfig) { diff --git a/jkube-kit/resource/helm/src/test/java/org/eclipse/jkube/kit/resource/helm/HelmServiceTest.java b/jkube-kit/resource/helm/src/test/java/org/eclipse/jkube/kit/resource/helm/HelmServiceTest.java index 9d7d2ee313..a6cbe7608d 100644 --- a/jkube-kit/resource/helm/src/test/java/org/eclipse/jkube/kit/resource/helm/HelmServiceTest.java +++ b/jkube-kit/resource/helm/src/test/java/org/eclipse/jkube/kit/resource/helm/HelmServiceTest.java @@ -19,6 +19,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.Objects; @@ -93,8 +94,9 @@ void prepareSourceDirValid_withNonExistentDirectory_shouldThrowException() throw @Test void generateHelmCharts() throws IOException { // Given - helmConfig.types(Collections.singletonList(HelmType.KUBERNETES)); - helmConfig.apiVersion("v1337").chart("Chart Name").version("1337"); + helmConfig + .types(Collections.singletonList(HelmType.KUBERNETES)) + .apiVersion("v1337").chart("Chart Name").version("1337"); // When helmService.generateHelmCharts(helmConfig.build()); // Then @@ -110,32 +112,42 @@ void generateHelmCharts() throws IOException { } @Test - void generateHelmCharts_whenInvalidChartYamlFragmentProvided_thenThrowException() { + void generateHelmCharts_withInvalidChartYamlFragmentProvided_throwsException() { // Given helmConfig.types(Collections.singletonList(HelmType.KUBERNETES)); resourceServiceConfig = ResourceServiceConfig.builder().resourceDirs(Collections.singletonList( - new File(Objects.requireNonNull(getClass().getResource("/invalid-helm-fragments")).getFile()))) + new File(Objects.requireNonNull(getClass().getResource("/invalid-helm-chart-fragment")).getFile()))) .build(); // When + Then assertThatIllegalArgumentException() .isThrownBy(() -> new HelmService(jKubeConfiguration, resourceServiceConfig, new KitLogger.SilentLogger()).generateHelmCharts(helmConfig.build())) - .withMessageContaining("Failure in parsing Helm Chart fragment: "); + .withMessageStartingWith("Failure in parsing Helm fragment (Chart.helm.yaml): "); } @Test - void generateHelmCharts_whenValidChartYamlFragmentProvided_thenMergeFragmentChart() throws Exception { + void generateHelmCharts_withInvalidValuesYamlFragmentProvided_throwsException() { // Given helmConfig.types(Collections.singletonList(HelmType.KUBERNETES)); - Properties properties = new Properties(); - properties.put("chart.name", "name-from-fragment"); - jKubeConfiguration = jKubeConfiguration.toBuilder() - .project(JavaProject.builder().properties(properties).build()) + resourceServiceConfig = ResourceServiceConfig.builder().resourceDirs(Collections.singletonList( + new File(Objects.requireNonNull(getClass().getResource("/invalid-helm-values-fragment")).getFile()))) .build(); + // When + Then + assertThatIllegalArgumentException() + .isThrownBy(() -> + new HelmService(jKubeConfiguration, resourceServiceConfig, new KitLogger.SilentLogger()).generateHelmCharts(helmConfig.build())) + .withMessageStartingWith("Failure in parsing Helm fragment (values.helm.yaml): "); + } + + @Test + void generateHelmCharts_withValidChartYamlFragment_usesMergedChart() throws Exception { + // Given + jKubeConfiguration.getProject().getProperties().put("chart.name", "name-from-fragment"); resourceServiceConfig = ResourceServiceConfig.builder().resourceDirs(Collections.singletonList( new File(Objects.requireNonNull(getClass().getResource("/valid-helm-fragments")).getFile()))) .build(); helmConfig + .types(Collections.singletonList(HelmType.KUBERNETES)) .apiVersion("v1") .chart("Chart Name") .version("1337") @@ -166,6 +178,37 @@ void generateHelmCharts_whenValidChartYamlFragmentProvided_thenMergeFragmentChar .hasFieldOrPropertyWithValue("dependencies", Collections.singletonList(Collections.singletonMap("name", "dependency-from-config"))); } + @Test + void generateHelmCharts_withValidValuesYamlFragment_usesMergedValues() throws Exception { + // Given + jKubeConfiguration.getProject().getProperties().put("property.in.fragment", "the-value"); + resourceServiceConfig = ResourceServiceConfig.builder().resourceDirs(Collections.singletonList( + new File(Objects.requireNonNull(getClass().getResource("/valid-helm-fragments")).getFile()))) + .build(); + helmConfig + .types(Collections.singletonList(HelmType.KUBERNETES)) + .parameters(Arrays.asList( + HelmParameter.builder().name("ingress.name").value("the-ingress-from-parameter").build(), + HelmParameter.builder().name("ingress.enabled").value("is overridden").build() + )); + // When + new HelmService(jKubeConfiguration, resourceServiceConfig, new KitLogger.SilentLogger()) + .generateHelmCharts(helmConfig.build()); + // Then + final Map savedValues = Serialization.unmarshal(helmOutputDirectory.resolve("kubernetes").resolve("values.yaml").toFile(), Map.class); + assertThat(savedValues) + .hasFieldOrPropertyWithValue("replaceableProperty", "the-value") + .hasFieldOrPropertyWithValue("replicaCount", 1) + .hasFieldOrPropertyWithValue("ingress.name", "the-ingress-from-parameter") + .hasFieldOrPropertyWithValue("ingress.enabled", false) + .hasFieldOrPropertyWithValue("ingress.tls", Collections.emptyList()) + .extracting("ingress.annotations").asInstanceOf(InstanceOfAssertFactories.map(String.class, String.class)) + .containsOnly( + entry("kubernetes.io/ingress.class", "nginx"), + entry("kubernetes.io/tls-acme", "true") + ); + } + @Test void createChartYamlWithDependencies() throws Exception { // Given diff --git a/jkube-kit/resource/helm/src/test/resources/invalid-helm-fragments/Chart.helm.yaml b/jkube-kit/resource/helm/src/test/resources/invalid-helm-chart-fragment/Chart.helm.yaml similarity index 100% rename from jkube-kit/resource/helm/src/test/resources/invalid-helm-fragments/Chart.helm.yaml rename to jkube-kit/resource/helm/src/test/resources/invalid-helm-chart-fragment/Chart.helm.yaml diff --git a/jkube-kit/resource/helm/src/test/resources/invalid-helm-values-fragment/values.helm.yaml b/jkube-kit/resource/helm/src/test/resources/invalid-helm-values-fragment/values.helm.yaml new file mode 100644 index 0000000000..3d1ab713d2 --- /dev/null +++ b/jkube-kit/resource/helm/src/test/resources/invalid-helm-values-fragment/values.helm.yaml @@ -0,0 +1 @@ +invalid-yaml: invalid: invalid diff --git a/jkube-kit/resource/helm/src/test/resources/valid-helm-fragments/values.helm.yaml b/jkube-kit/resource/helm/src/test/resources/valid-helm-fragments/values.helm.yaml new file mode 100644 index 0000000000..ff54369425 --- /dev/null +++ b/jkube-kit/resource/helm/src/test/resources/valid-helm-fragments/values.helm.yaml @@ -0,0 +1,35 @@ +replicaCount: 1 +replaceableProperty: ${property.in.fragment} + +image: + repository: nginx + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + className: "" + annotations: + kubernetes.io/ingress.class: nginx + kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + diff --git a/kubernetes-maven-plugin/doc/src/main/asciidoc/inc/_introduction.adoc b/kubernetes-maven-plugin/doc/src/main/asciidoc/inc/_introduction.adoc index 5c98e6284f..aee69fdfd1 100644 --- a/kubernetes-maven-plugin/doc/src/main/asciidoc/inc/_introduction.adoc +++ b/kubernetes-maven-plugin/doc/src/main/asciidoc/inc/_introduction.adoc @@ -352,6 +352,7 @@ An extract of the plugin configuration is shown below: The XML resource configuration is based on plain Kubernetes resource objects. When targeting OpenShift, Kubernetes resource descriptors will be automatically converted to their OpenShift counterparts, e.g. a Kubernetes http://kubernetes.io/docs/user-guide/deployments/[Deployment] will be converted to an OpenShift https://docs.openshift.com/container-platform/4.1/applications/deployments/what-deployments-are.html#deployments-and-deploymentconfigs_what-deployments-are[DeploymentConfig]. +[[introduction-examples-resource-fragments]] === Resource Fragments The third configuration option is to use an external configuration in form of YAML resource descriptors which are located in the `src/main/jkube` directory. Each resource gets its own file, which contains a skeleton of a resource descriptor. The plugin will pick up the resource, enrich it and then combine all to a single `kubernetes.yml` and `openshift.yml` file. Within these descriptor files you are can freely use any Kubernetes feature.