feat: Merge multiple docs inside a single helmfile.yaml (#270)
Resolves #254
This commit is contained in:
parent
1ade353c1a
commit
9808849986
|
|
@ -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.
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue