Skip to content

Commit

Permalink
Merge pull request #211 from deviceinsight/feature/allow-excluding-fi…
Browse files Browse the repository at this point in the history
…les-from-property-replacement

Allow excluding files from property replacement
  • Loading branch information
stefan-hudelmaier authored Oct 5, 2023
2 parents a645683 + 3937c32 commit 09de586
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

* Support excluding files from property replacement.

## Version 2.13.0

* Support escaping placeholders with backslash e.g. `\${MY_ENV_VAR}` will no longer be expanded
Expand Down
51 changes: 48 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ that the correct docker image is used. An example snippet:
## Configuration

| Property | Default | Description |
|---|---|---|
|---|--|---|
| chartName | The Maven `artifactId` | The name of the chart |
| chartVersion | `${project.model.version}` | The version of the chart |
| chartRepoUrl | `null` | The URL of the Chart repository where dependencies are required from and where charts should be published to |
Expand All @@ -95,6 +95,8 @@ that the correct docker image is used. An example snippet:
| extraValuesFiles | None | a list of additional values files that can be generated dynamically and will be merged with the values.yaml during [Package](#package). |
| outputFile | target/test-classes/helm.yaml | output file for [template goal](#template) |
| deployAtEnd | `false` | If true, the helm chart is deployed at the end of a multi-module Maven build. This option does not make sense for single-module Maven projects. |
| propertyReplacement | Empty | Structure to configure property replacement performed on the chart files |
| propertyReplacement.exclusions | Empty | List of file extensions that should be excluded from property replacement. The expressions are by default glob expressions |

## Goals

Expand Down Expand Up @@ -131,11 +133,11 @@ To use the `deployAtEnd` functionality it's mandatory to put the Helm Maven Plug
<plugin>
<groupId>com.deviceinsight.helm</groupId>
<artifactId>helm-maven-plugin</artifactId>
<version>2.11.1</version>
<version>2.14.0</version>
<configuration>
<chartName>my-chart</chartName>
<chartRepoUrl>https://charts.helm.sh/stable</chartRepoUrl>
<helmVersion>3.5.2</helmVersion>
<helmVersion>3.13.0</helmVersion>
<strictLint>true</strictLint>
<valuesFile>src/test/helm/my-chart/values.yaml</valuesFile>
<deployAtEnd>true</deployAtEnd>
Expand All @@ -155,6 +157,49 @@ To use the `deployAtEnd` functionality it's mandatory to put the Helm Maven Plug
</build>
```

### Exclude files from property replacement

To exclude files from property replacement, you can use the `propertyReplacement` configuration.
Any `exclusion` matching will exclude the file from property replacement.
By default, glob expressions are used.
You can also use regular expressions by prefixing the expression with `regex`.

```xml
<build>
<plugins>
...
<plugin>
<groupId>com.deviceinsight.helm</groupId>
<artifactId>helm-maven-plugin</artifactId>
<version>2.14.0</version>
<configuration>
<chartName>my-chart</chartName>
<chartRepoUrl>https://charts.helm.sh/stable</chartRepoUrl>
<helmVersion>3.13.0</helmVersion>
<strictLint>true</strictLint>
<valuesFile>src/test/helm/my-chart/values.yaml</valuesFile>
<propertyReplacement>
<exclusions>
<exclusion>**/grafana-dashboards/**/*.json</exclusion>
<exclusion>regex:.*/grafana-dashboards/.*\.json</exclusion>
</exclusions>
</propertyReplacement>
</configuration>
<executions>
<execution>
<goals>
<goal>package</goal>
<goal>lint</goal>
<goal>template</goal>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
```

## Troubleshooting

1. _**Problem**_
Expand Down
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<gitflow-maven-plugin.version>1.20.0</gitflow-maven-plugin.version>
<nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version>
<maven-gpg-plugin.version>3.1.0</maven-gpg-plugin.version>
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -238,6 +239,11 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
</plugins>
</build>

Expand Down
6 changes: 4 additions & 2 deletions src/main/kotlin/com/deviceinsight/helm/PackageMojo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ class PackageMojo : ResolveHelmMojo(), ServerAuthentication {

companion object {
private val PLACEHOLDER_REGEX = Regex("""(\\?)\$\{(.*?)}""")
private val SUBSTITUTED_EXTENSIONS = setOf("json", "tpl", "yml", "yaml")
}

@Component(role = SecDispatcher::class, hint = "default")
Expand Down Expand Up @@ -79,6 +78,9 @@ class PackageMojo : ResolveHelmMojo(), ServerAuthentication {
@Parameter(property = "extraValuesFiles")
private val extraValuesFiles: List<String> = emptyList()

@Parameter(property = "propertyReplacement")
private val propertyReplacement = PropertyReplacement()

@Throws(MojoExecutionException::class)
override fun execute() {

Expand Down Expand Up @@ -164,7 +166,7 @@ class PackageMojo : ResolveHelmMojo(), ServerAuthentication {
parentFile.mkdirs()
}

if (!SUBSTITUTED_EXTENSIONS.contains(file.extension.lowercase())) {
if (!propertyReplacement.isPropertyReplacementCandidate(file)) {
file.copyTo(targetFile, true)
return@onEach
}
Expand Down
35 changes: 35 additions & 0 deletions src/main/kotlin/com/deviceinsight/helm/PropertyReplacement.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.deviceinsight.helm

import org.apache.maven.plugins.annotations.Parameter
import java.io.File
import java.nio.file.FileSystems
import java.nio.file.PathMatcher

class PropertyReplacement {

@Parameter(property = "exclusions")
var exclusions: List<String> = emptyList()

private val exclusionPatchMatchers = lazy { exclusions.toPathMatchers() }

companion object {
private val SUBSTITUTED_EXTENSIONS = setOf("json", "tpl", "yml", "yaml")
private val PATH_MATCHER_PATTERN = Regex("^(glob|regex):.*$")
}

fun isPropertyReplacementCandidate(file: File): Boolean {
val extension = file.extension.lowercase()
return SUBSTITUTED_EXTENSIONS.contains(extension)
&& file.doesNotMatchAnyExclusion()
}

private fun File.doesNotMatchAnyExclusion() = exclusionPatchMatchers.value.none { it.matches(this.toPath()) }

private fun List<String>.toPathMatchers(): List<PathMatcher> = this
.map { prependGlobIfMissing(it) }
.map { FileSystems.getDefault().getPathMatcher(it) }

private fun prependGlobIfMissing(path: String): String = if (PATH_MATCHER_PATTERN.matches(path)) path else "glob:$path"

}

35 changes: 35 additions & 0 deletions src/test/kotlin/com/deviceinsight/helm/PropertyReplacementTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.deviceinsight.helm

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
import java.io.File

class PropertyReplacementTest {

@ParameterizedTest
@ValueSource(strings = ["test.txt", "test.xml"])
fun `isPropertyReplacementCandidate should return false if file extension is not in inclusion list`(filename: String) {
val file = File(filename)
val propertyReplacement = PropertyReplacement()
assertThat(propertyReplacement.isPropertyReplacementCandidate(file)).isFalse
}

@ParameterizedTest
@ValueSource(strings = ["test.json", "test.tpl", "test.yml", "test.yaml"])
fun `isPropertyReplacementCandidate should return true if file extension is in inclusion list`(filename: String) {
val file = File(filename)
val propertyReplacement = PropertyReplacement()
assertThat(propertyReplacement.isPropertyReplacementCandidate(file)).isTrue
}

@ParameterizedTest
@ValueSource(strings = ["dashboards/test.json", "templates/test.json", "templates/default/test.json"])
fun `isPropertyReplacementCandidate should return false if file matches exclusion pattern`(filename: String) {
val file = File(filename)
val propertyReplacement = PropertyReplacement()
propertyReplacement.exclusions =
listOf("regex:dashboards/.*\\.json", "glob:templates/*.json", "templates/**/*.json")
assertThat(propertyReplacement.isPropertyReplacementCandidate(file)).isFalse
}
}

0 comments on commit 09de586

Please sign in to comment.