Skip to content

Commit

Permalink
Helm: Support if statements at resource level
Browse files Browse the repository at this point in the history
  • Loading branch information
Sgitario committed Dec 13, 2022
1 parent d20d6f0 commit 5d4b6ed
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright 2018 The original authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**/
package io.dekorate.helm.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.CONSTRUCTOR, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface AddIfStatement {

String property();

String onResourceKind() default "";

String onResourceName() default "";

boolean withDefaultValue() default true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,6 @@
ValueReference[] values() default {};

HelmExpression[] expressions() default {};

AddIfStatement[] addIfStatements() default {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import io.dekorate.WithConfigReferences;
import io.dekorate.WithProject;
import io.dekorate.WithSession;
import io.dekorate.helm.config.AddIfStatement;
import io.dekorate.helm.config.Annotation;
import io.dekorate.helm.config.HelmChartConfig;
import io.dekorate.helm.config.HelmExpression;
Expand Down Expand Up @@ -77,11 +78,14 @@ public class HelmWriterSessionListener implements SessionListener, WithProject,
private static final List<String> ADDITIONAL_CHART_FILES = Arrays.asList("README.md", "LICENSE", "values.schema.json",
"app-readme.md", "questions.yml", "questions.yaml", "requirements.yml", "requirements.yaml");
private static final String KIND = "kind";
private static final String METADATA = "metadata";
private static final String NAME = "name";
private static final String START_TAG = "{{";
private static final String END_TAG = "}}";
private static final String VALUES_START_TAG = START_TAG + " .Values.";
private static final String VALUES_END_TAG = " " + END_TAG;
private static final String EMPTY = "";
private static final String IF_STATEMENT_START_TAG = "{{- if .Values.%s }}";
private static final String TEMPLATE_FUNCTION_START_TAG = "{{- define";
private static final String TEMPLATE_FUNCTION_END_TAG = "{{- end }}";
private static final String HELM_HELPER_PREFIX = "_";
Expand Down Expand Up @@ -129,7 +133,8 @@ public Map<String, String> writeHelmFiles(Session session, Project project,
Map<String, String> artifacts = new HashMap<>();
if (helmConfig.isEnabled()) {
validateHelmConfig(helmConfig);
List<ConfigReference> valuesReferences = mergeValuesReferencesFromDecorators(configReferences, session);
List<ConfigReference> valuesReferences = mergeValuesReferencesFromDecorators(configReferences,
helmConfig.getAddIfStatements(), session);

try {
LOGGER.info(String.format("Creating Helm Chart \"%s\"", helmConfig.getName()));
Expand Down Expand Up @@ -240,10 +245,14 @@ private Map<String, String> createEmptyChartFolder(HelmChartConfig helmConfig, P
}

private List<ConfigReference> mergeValuesReferencesFromDecorators(List<ConfigReference> configReferencesFromConfig,
Session session) {
AddIfStatement[] addIfStatements, Session session) {
List<ConfigReference> configReferences = new LinkedList<>();
// From user
configReferences.addAll(configReferencesFromConfig);
// From if statements: these are boolean values
for (AddIfStatement addIfStatement : addIfStatements) {
configReferences.add(new ConfigReference(addIfStatement.getProperty(), null, addIfStatement.getWithDefaultValue()));
}
// From decorators
for (WithConfigReferences decorator : session.getResourceRegistry().getConfigReferences()) {
configReferences.addAll(decorator.getConfigReferences());
Expand Down Expand Up @@ -275,12 +284,7 @@ private Map<String, String> createValuesYaml(HelmChartConfig helmConfig, List<Co
+ "either a path or a default value. ");
}

String property = value.getProperty();
if (!startWithDependencyPrefix(value.getProperty(), helmConfig.getDependencies())) {
property = helmConfig.getValuesRootAlias() + "." + value.getProperty();
}

prodValues.put(Strings.kebabToCamelCase(property), value.getValue());
prodValues.put(deductProperty(helmConfig, value.getProperty()), value.getValue());
}
}

Expand Down Expand Up @@ -309,6 +313,14 @@ private Map<String, String> createValuesYaml(HelmChartConfig helmConfig, List<Co
return artifacts;
}

private String deductProperty(HelmChartConfig helmConfig, String property) {
if (!startWithDependencyPrefix(property, helmConfig.getDependencies())) {
property = helmConfig.getValuesRootAlias() + "." + property;
}

return Strings.kebabToCamelCase(property);
}

private Map<String, Object> mergeWithFileIfExists(Path inputDir, String file, Map<String, Object> data) {
Map<String, Object> valuesAsMultiValueMap = toMultiValueMap(data);
File templateValuesFile = inputDir.resolve(file).toFile();
Expand Down Expand Up @@ -411,6 +423,22 @@ private Map<String, String> processTemplates(HelmChartConfig helmConfig, Path in
adaptedString = functions + System.lineSeparator() + adaptedString;
}

// Add if statements at resource level
for (AddIfStatement addIfStatement : helmConfig.getAddIfStatements()) {
if ((Strings.isNullOrEmpty(addIfStatement.getOnResourceKind())
|| Strings.equals(addIfStatement.getOnResourceKind(), kind))
&& (Strings.isNullOrEmpty(addIfStatement.getOnResourceName())
|| Strings.equals(addIfStatement.getOnResourceName(), getNameFromResource(resource)))) {

adaptedString = String.format(IF_STATEMENT_START_TAG, deductProperty(helmConfig, addIfStatement.getProperty()))
+ System.lineSeparator()
+ adaptedString
+ System.lineSeparator()
+ TEMPLATE_FUNCTION_END_TAG
+ System.lineSeparator();
}
}

adaptedString = adaptedString
.replaceAll(Pattern.quote("\"" + START_TAG), START_TAG)
.replaceAll(Pattern.quote(END_TAG + "\""), END_TAG)
Expand All @@ -428,6 +456,18 @@ private Map<String, String> processTemplates(HelmChartConfig helmConfig, Path in
return templates;
}

private String getNameFromResource(Map<Object, Object> resource) {
Object metadata = resource.get(METADATA);
if (metadata != null && metadata instanceof Map) {
Object name = ((Map) metadata).get(NAME);
if (name != null) {
return name.toString();
}
}

return null;
}

private Map<String, String> processUserDefinedTemplates(Path inputDir, Map<String, String> templates, Path templatesDir)
throws IOException {
Map<String, String> functionsByResource = new HashMap<>();
Expand Down
10 changes: 10 additions & 0 deletions assets/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ The section below describes all the available subtypes.
| dekorate.helm.extension | String | Extension of the Helm tarball file. | tar.gz |
| dekorate.helm.tarFileClassifier | String | Classifier to be appended into the generated Helm tarball file name. | |
| dekorate.helm.values | ValueReference[] | The configuration references to be mapped into the Helm values file. | |
| dekorate.helm.addIfStatements | AddIfStatement[] | The if statements to include in the generated resources. | |
| dekorate.helm.notes | String | Template for the NOTES.txt file that will be included in the generated Helm Chart. It must be a classpath resource. | /NOTES.template.txt |
| dekorate.helm.valuesRootAlias | String | Alias of the root element in the generated values file. | app |
| dekorate.helm.inputFolder | String | The input folder in which to place the user-defined Helm files. These files will be used as inputs to populate the generated Helm files. At the moment, the only supported Helm files are the `values.yaml`, the `LICENSE`, the `NOTES.txt`, and the `README.md` files. The folder will be created in the path specified in the Dekorate input path property (`dekorate.options.input-path`, see the Dekorate options table [here](#generator-options)). | helm |
Expand Down Expand Up @@ -523,6 +524,15 @@ The section below describes all the available subtypes.
| value | String | The dependency repository. | (empty) |
| expression | String | The complete Helm expression to be replaced with. If not provided, it will use `{{ .Values.<root alias>.<property> }}`. | (empty) |

### AddIfStatement

| Property | Type | Description | Default Value |
|--------------------|----------|-------------------------------------------------------------------|---------------|
| property | String | The property to use in the if statement. | |
| onResourceKind | String | The resource kind where to include the if statement. | |
| onResourceName | String | The resource name where to include the if statement. | (empty) |
| withDefaultValue | Boolean | The default value of the property | true |

## Tekton
| Property | Type | Description | Default Value |
|-------------------------------------------------|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------|
Expand Down
10 changes: 10 additions & 0 deletions docs/configuration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,7 @@ The section below describes all the available subtypes.
| dekorate.helm.extension | String | Extension of the Helm tarball file. | tar.gz |
| dekorate.helm.tarFileClassifier | String | Classifier to be appended into the generated Helm tarball file name. | |
| dekorate.helm.values | ValueReference[] | The configuration references to be mapped into the Helm values file. | |
| dekorate.helm.addIfStatements | AddIfStatement[] | The if statements to include in the generated resources. | |
| dekorate.helm.notes | String | Template for the NOTES.txt file that will be included in the generated Helm Chart. It must be a classpath resource. | /NOTES.template.txt |
| dekorate.helm.valuesRootAlias | String | Alias of the root element in the generated values file. | app |
| dekorate.helm.inputFolder | String | The input folder in which to place the user-defined Helm files. These files will be used as inputs to populate the generated Helm files. At the moment, the only supported Helm files are the `values.yaml`, the `LICENSE`, the `NOTES.txt`, and the `README.md` files. The folder will be created in the path specified in the Dekorate input path property (`dekorate.options.input-path`, see the Dekorate options table [here](#generator-options)). | helm |
Expand Down Expand Up @@ -589,6 +590,15 @@ The section below describes all the available subtypes.
| value | String | The dependency repository. | (empty) |
| expression | String | The complete Helm expression to be replaced with. If not provided, it will use `{{ .Values.<root alias>.<property> }}`. | (empty) |

### AddIfStatement

| Property | Type | Description | Default Value |
|--------------------|----------|-------------------------------------------------------------------|---------------|
| property | String | The property to use in the if statement. | |
| onResourceKind | String | The resource kind where to include the if statement. | |
| onResourceName | String | The resource name where to include the if statement. | (empty) |
| withDefaultValue | Boolean | The default value of the property | true |

## Tekton

| Property | Type | Description | Default Value |
Expand Down
Loading

0 comments on commit 5d4b6ed

Please sign in to comment.