mirror of
https://github.com/helmfile/helmfile.git
synced 2026-10-05 13:41:40 +02:00
feat: Merge multiple docs inside a single helmfile.yaml (#270)
Resolves #254
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# The Helmfile Best Practices Guide
|
||||
|
||||
This guide covers the Helmfile’s considered patterns for writing advanced helmfiles. It focuses on how helmfile should be structured and executed.
|
||||
|
||||
## Layering
|
||||
|
||||
You may occasionally end up with many helmfiles that shares common parts like which repositories to use, and whichi release to be bundled by default.
|
||||
|
||||
Use Layering to extract te common parts into a dedicated *library helmfile*s, so that each helmfile becomes DRY.
|
||||
|
||||
Let's assume that your `helmfile.yaml` looks like:
|
||||
|
||||
```
|
||||
{ readFile "commons.yaml" }}
|
||||
---
|
||||
{{ readFile "environments.yaml" }}
|
||||
---
|
||||
releases:
|
||||
- name: myapp
|
||||
chart: mychart
|
||||
```
|
||||
|
||||
Whereas `commons.yaml` contained a monitoring agent:
|
||||
|
||||
```yaml
|
||||
releases:
|
||||
- name: metricbaet
|
||||
chart: stable/metricbeat
|
||||
```
|
||||
|
||||
And `environments.yaml` contained well-known environments:
|
||||
|
||||
```yaml
|
||||
environments:
|
||||
development:
|
||||
production:
|
||||
```
|
||||
|
||||
At run time, template expressions in your `helmfile.yaml` are executed:
|
||||
|
||||
```yaml
|
||||
releases:
|
||||
- name: metricbaet
|
||||
chart: stable/metricbeat
|
||||
---
|
||||
environments:
|
||||
development:
|
||||
production:
|
||||
---
|
||||
releases:
|
||||
- name: myapp
|
||||
chart: mychart
|
||||
```
|
||||
|
||||
Resulting YAML documents are merged in the order of occurrence,
|
||||
so that your `helmfile.yaml` becomes:
|
||||
|
||||
```yaml
|
||||
environments:
|
||||
development:
|
||||
production:
|
||||
|
||||
releases:
|
||||
- name: metricbaet
|
||||
chart: stable/metricbeat
|
||||
- name: myapp
|
||||
chart: mychart
|
||||
```
|
||||
|
||||
Great!
|
||||
|
||||
Now, repeat the above steps for each your `helmfile.yaml`, so that all your helmfiles becomes DRY.
|
||||
+23
-5
@@ -1,6 +1,7 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/imdario/mergo"
|
||||
"github.com/roboll/helmfile/environment"
|
||||
@@ -8,6 +9,7 @@ import (
|
||||
"github.com/roboll/helmfile/valuesfile"
|
||||
"go.uber.org/zap"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -64,16 +66,32 @@ func (c *creator) CreateFromYaml(content []byte, file string, env string) (*Helm
|
||||
if err != nil {
|
||||
return nil, &StateLoadError{fmt.Sprintf("failed to read %s", file), err}
|
||||
}
|
||||
state.FilePath = file
|
||||
state.basePath = basePath
|
||||
|
||||
unmarshal := yaml.UnmarshalStrict
|
||||
decoder := yaml.NewDecoder(bytes.NewReader(content))
|
||||
if !c.Strict {
|
||||
unmarshal = yaml.Unmarshal
|
||||
decoder.SetStrict(false)
|
||||
} else {
|
||||
decoder.SetStrict(true)
|
||||
}
|
||||
if err := unmarshal(content, &state); err != nil {
|
||||
return nil, &StateLoadError{fmt.Sprintf("failed to read %s", file), err}
|
||||
i := 0
|
||||
for {
|
||||
i++
|
||||
|
||||
var intermediate HelmState
|
||||
|
||||
err := decoder.Decode(&intermediate)
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return nil, &StateLoadError{fmt.Sprintf("failed to read %s: reading document at index %d", file, i), err}
|
||||
}
|
||||
|
||||
if err := mergo.Merge(&state, &intermediate, mergo.WithAppendSlice); err != nil {
|
||||
return nil, &StateLoadError{fmt.Sprintf("failed to read %s: merging document at index %d", file, i), err}
|
||||
}
|
||||
}
|
||||
state.FilePath = file
|
||||
|
||||
if len(state.DeprecatedReleases) > 0 {
|
||||
if len(state.Releases) > 0 {
|
||||
|
||||
Reference in New Issue
Block a user