feat: make environment context available (#832)
* feat: make environment context available
This feature adds the "{{.Environment.KubeContext}}" variable.
Discussion #829
Signed-off-by: sewieland <sebastian.wieland@iav.de>
* chore: fix tests which compare logging outputs
This commit adds an addtional space wherever needed to the expected log outputs due to the added "KubeContext" in the environment struct.
Discussion #829
Signed-off-by: Sebastian Wieland <wieland.s@mailbox.org>
* docs: added documentation for `Environment.KubeContext`
Discussion #829
Signed-off-by: Sebastian Wieland <wieland.s@mailbox.org>
* test: make sure the `Environment.KubeContext` is mapped out correctly
Discussion #829
Signed-off-by: Sebastian Wieland <wieland.s@mailbox.org>
---------
Signed-off-by: sewieland <sebastian.wieland@iav.de>
Signed-off-by: Sebastian Wieland <wieland.s@mailbox.org>
Co-authored-by: sewieland <sebastian.wieland@iav.de>
This commit is contained in:
parent
c299cd930d
commit
8b3ad5b793
|
|
@ -3,13 +3,14 @@
|
|||
- `Environment`: The information about the environment. This is set by the
|
||||
`--environment` flag. It has several objects inside of it:
|
||||
- `Environment.Name`: The name of the environment
|
||||
- `Environment.KubeContext`: The kube context to be used by default for releases in the environment.
|
||||
- `Values`: Values passed into the environment.
|
||||
- `StateValues`: alias for `Values`.
|
||||
- `Namespace`: The namespace to be released into
|
||||
|
||||
# release template built-in objects
|
||||
|
||||
it be used for the below tow cases:
|
||||
it be used for the below two cases:
|
||||
|
||||
1. release definition
|
||||
```
|
||||
|
|
@ -56,6 +57,7 @@ releases:
|
|||
- `Environment`: The information about the environment. This is set by the
|
||||
`--environment` flag. It has several objects inside of it:
|
||||
- `Environment.Name`: The name of the environment
|
||||
- `Environment.KubeContext`: The kube context to be used by default for releases in the environment.
|
||||
- `Chart`: The chart name for the release.
|
||||
- `KubeContext`: The kube context to be used for the release
|
||||
- `Namespace`: The namespace to be released into
|
||||
|
|
|
|||
|
|
@ -1353,6 +1353,67 @@ releases:
|
|||
For templating, imagine that you created a hook that generates a helm chart on-the-fly by running an external tool like ksonnet, kustomize, or your own template engine.
|
||||
It will allow you to write your helm releases with any language you like, while still leveraging goodies provided by helm.
|
||||
|
||||
### Hooks, Kubectl and Environments
|
||||
|
||||
Hooks can also be used in combination with small tasks using `kubectl` directly,
|
||||
e.g.: in order to install a custom storage class.
|
||||
|
||||
In the following example, a specific release depends on a custom storage class.
|
||||
Further, all enviroments have a default kube context configured where releases are deployed into.
|
||||
The `.Environment.KubeContext` is used in order to apply / remove the YAML to the correct context depending on the environment.
|
||||
|
||||
`environments.yaml`:
|
||||
|
||||
```yaml
|
||||
environments:
|
||||
dev:
|
||||
values:
|
||||
- ../values/default.yaml
|
||||
- ../values/dev.yaml
|
||||
kubeContext: dev-cluster
|
||||
prod:
|
||||
values:
|
||||
- ../values/default.yaml
|
||||
- ../values/prod.yaml
|
||||
kubeContext: prod-cluster
|
||||
```
|
||||
|
||||
`helmfile.yaml`:
|
||||
|
||||
```yaml
|
||||
bases:
|
||||
- ./environments.yaml
|
||||
|
||||
---
|
||||
releases:
|
||||
- name: myService
|
||||
namespace: my-ns
|
||||
installed: true
|
||||
chart: mychart
|
||||
version: "1.2.3"
|
||||
values:
|
||||
- ../services/my-service/values.yaml.gotmpl
|
||||
hooks:
|
||||
- events: ["presync"]
|
||||
showlogs: true
|
||||
command: "kubectl"
|
||||
args:
|
||||
- "apply"
|
||||
- "-f"
|
||||
- "./custom-storage-class.yaml"
|
||||
- "--context"
|
||||
- "{{`{{.Environment.KubeContext}}`}}"
|
||||
- events: ["postuninstall"]
|
||||
showlogs: true
|
||||
command: "kubectl"
|
||||
args:
|
||||
- "delete"
|
||||
- "-f"
|
||||
- "./custom-storage-class.yaml"
|
||||
- "--context"
|
||||
- "{{`{{.Environment.KubeContext}}`}}"
|
||||
```
|
||||
|
||||
### Global Hooks
|
||||
|
||||
In contrast to the per release hooks mentioned above these are run only once at the very beginning and end of the execution of a helmfile command and only the `prepare` and `cleanup` hooks are available respectively.
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
type Environment struct {
|
||||
Name string
|
||||
KubeContext string
|
||||
Values map[string]interface{}
|
||||
Defaults map[string]interface{}
|
||||
}
|
||||
|
|
@ -19,6 +20,7 @@ var EmptyEnvironment Environment
|
|||
func New(name string) *Environment {
|
||||
return &Environment{
|
||||
Name: name,
|
||||
KubeContext: "",
|
||||
Values: map[string]interface{}{},
|
||||
Defaults: map[string]interface{}{},
|
||||
}
|
||||
|
|
@ -53,6 +55,7 @@ func (e Environment) DeepCopy() Environment {
|
|||
|
||||
return Environment{
|
||||
Name: e.Name,
|
||||
KubeContext: e.KubeContext,
|
||||
Values: values,
|
||||
Defaults: defaults,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ func (c *StateCreator) loadEnvValues(st *HelmState, name string, failOnMissingEn
|
|||
return nil, &UndefinedEnvError{msg: fmt.Sprintf("environment \"%s\" is not defined", name)}
|
||||
}
|
||||
|
||||
newEnv := &environment.Environment{Name: name, Values: envVals}
|
||||
newEnv := &environment.Environment{Name: name, Values: envVals, KubeContext: envSpec.KubeContext}
|
||||
|
||||
if ctxEnv != nil {
|
||||
intCtxEnv := *ctxEnv
|
||||
|
|
|
|||
|
|
@ -489,3 +489,58 @@ func TestReadFromYaml_Helmfiles_Selectors(t *testing.T) {
|
|||
require.Equalf(t, test.helmfiles, st.Helmfiles, "for path %s", test.path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadFromYaml_EnvironmentContext(t *testing.T) {
|
||||
yamlFile := "/example/path/to/helmfile.yaml"
|
||||
yamlContent := []byte(`environments:
|
||||
production:
|
||||
values: []
|
||||
kubeContext: myCtx
|
||||
|
||||
releases:
|
||||
- name: myrelease
|
||||
namespace: mynamespace
|
||||
chart: mychart
|
||||
values:
|
||||
- values.yaml.gotmpl
|
||||
`)
|
||||
|
||||
valuesFile := "/example/path/to/values.yaml.gotmpl"
|
||||
valuesContent := []byte(`envName: {{ .Environment.Name }}
|
||||
envContext: {{ .Environment.KubeContext }}
|
||||
releaseName: {{ .Release.Name }}
|
||||
releaseContext: {{ .Release.KubeContext }}
|
||||
`)
|
||||
|
||||
expectedValues := `envName: production
|
||||
envContext: myCtx
|
||||
releaseName: myrelease
|
||||
releaseContext:
|
||||
`
|
||||
|
||||
testFs := testhelper.NewTestFs(map[string]string{
|
||||
valuesFile: string(valuesContent),
|
||||
})
|
||||
testFs.Cwd = "/example/path/to"
|
||||
|
||||
r := remote.NewRemote(logger, testFs.Cwd, testFs.ToFileSystem())
|
||||
state, err := NewCreator(logger, testFs.ToFileSystem(), nil, nil, "", r, false, "").
|
||||
ParseAndLoad(yamlContent, filepath.Dir(yamlFile), yamlFile, "production", true, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
release := state.Releases[0]
|
||||
|
||||
state.ApplyOverrides(&release)
|
||||
|
||||
actualValuesData, err := state.RenderReleaseValuesFileToBytes(&release, valuesFile)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
actualValues := string(actualValuesData)
|
||||
|
||||
if !reflect.DeepEqual(expectedValues, actualValues) {
|
||||
t.Errorf("unexpected values: expected=%v, actual=%v", expectedValues, actualValues)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue