Merge pull request #135 from AXOOM/feat/required_envs
Introduce template function `required_env`
This commit is contained in:
		
						commit
						c5d530632b
					
				
							
								
								
									
										26
									
								
								README.md
								
								
								
								
							
							
						
						
									
										26
									
								
								README.md
								
								
								
								
							|  | @ -52,9 +52,11 @@ releases: | ||||||
|       - name: address |       - name: address | ||||||
|         value: https://vault.example.com |         value: https://vault.example.com | ||||||
|       - name: db.password |       - name: db.password | ||||||
|         value: {{ env "DB_PASSWORD" }}    # value taken from environment variable. Quotes are necessary. Will throw an error if the environment variable is not set. $DB_PASSWORD needs to be set in the calling environment ex: export DB_PASSWORD='password1' |         value: {{ requiredEnv "DB_PASSWORD" }}    # value taken from environment variable. Quotes are necessary. Will throw an error if the environment variable is not set. $DB_PASSWORD needs to be set in the calling environment ex: export DB_PASSWORD='password1' | ||||||
|       - name: proxy.domain |       - name: proxy.domain | ||||||
|         value: {{ env "PLATFORM_ID" }}.my-domain.com # Interpolate environment variable with a fixed string |         value: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com # Interpolate environment variable with a fixed string | ||||||
|  |       - name: proxy.scheme | ||||||
|  |         value: {{ env "SCHEME" | default "https" }} | ||||||
| 
 | 
 | ||||||
|   # Local chart example |   # Local chart example | ||||||
|   - name: grafana                            # name of this release |   - name: grafana                            # name of this release | ||||||
|  | @ -62,10 +64,18 @@ releases: | ||||||
|     chart: ../my-charts/grafana              # the chart being installed to create this release, referenced by relative path to local chart |     chart: ../my-charts/grafana              # the chart being installed to create this release, referenced by relative path to local chart | ||||||
|     values: |     values: | ||||||
|     - "../../my-values/grafana/values.yaml"             # Values file (relative path to manifest) |     - "../../my-values/grafana/values.yaml"             # Values file (relative path to manifest) | ||||||
|     - ./values/{{ env "PLATFORM_ENV" }}/config.yaml # Values file taken from path with environment variable. $PLATFORM_ENV must be set in the calling environment. |     - ./values/{{ requiredEnv "PLATFORM_ENV" }}/config.yaml # Values file taken from path with environment variable. $PLATFORM_ENV must be set in the calling environment. | ||||||
| 
 | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | ## Templating | ||||||
|  | 
 | ||||||
|  | Helmfile uses [Go templates](https://godoc.org/text/template) for templating your helmfile.yaml. While go ships several built-in functions, we have added all of the functions in the [Sprig library](https://godoc.org/github.com/Masterminds/sprig). | ||||||
|  | 
 | ||||||
|  | We also added one special template function: `requiredEnv`.   | ||||||
|  | The `required_env` function allows you to declare a particular environment variable as required for template rendering.   | ||||||
|  | If the environment variable is unset or empty, the template rendering will fail with an error message. | ||||||
|  | 
 | ||||||
| ## Using environment variables | ## Using environment variables | ||||||
| 
 | 
 | ||||||
| Environment variables can be used in most places for templating the helmfile. Currently this is supported for `name`, `namespace`, `value` (in set) and `url` (in repositories). | Environment variables can be used in most places for templating the helmfile. Currently this is supported for `name`, `namespace`, `value` (in set) and `url` (in repositories). | ||||||
|  | @ -75,17 +85,19 @@ Examples: | ||||||
| ```yaml | ```yaml | ||||||
| respositories: | respositories: | ||||||
| - name: your-private-git-repo-hosted-charts | - name: your-private-git-repo-hosted-charts | ||||||
|   url: https://{{ env "GITHUB_TOKEN"}}@raw.githubusercontent.com/kmzfs/helm-repo-in-github/master/ |   url: https://{{ requiredEnv "GITHUB_TOKEN"}}@raw.githubusercontent.com/kmzfs/helm-repo-in-github/master/ | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ```yaml | ```yaml | ||||||
| releases: | releases: | ||||||
|   - name: {{ env "NAME" }}-vault |   - name: {{ requiredEnv "NAME" }}-vault | ||||||
|     namespace: {{ env "NAME" }} |     namespace: {{ requiredEnv "NAME" }} | ||||||
|     chart: roboll/vault-secret-manager |     chart: roboll/vault-secret-manager | ||||||
|     set: |     set: | ||||||
|       - name: proxy.domain |       - name: proxy.domain | ||||||
|         value: {{ env "PLATFORM_ID" }}.my-domain.com |         value: {{ requiredEnv "PLATFORM_ID" }}.my-domain.com | ||||||
|  |       - name: proxy.scheme | ||||||
|  |         value: {{ env "SCHEME" | default "https" }} | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ## installation | ## installation | ||||||
|  |  | ||||||
|  | @ -107,7 +107,21 @@ func readFromYaml(content []byte, file string) (*HelmState, error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func stringTemplate() *template.Template { | func stringTemplate() *template.Template { | ||||||
| 	return template.New("stringTemplate").Funcs(sprig.TxtFuncMap()) | 	funcMap := sprig.TxtFuncMap() | ||||||
|  | 	alterFuncMap(&funcMap) | ||||||
|  | 	return template.New("stringTemplate").Funcs(funcMap) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func alterFuncMap(funcMap *template.FuncMap) { | ||||||
|  | 	(*funcMap)["requiredEnv"] = getRequiredEnv | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func getRequiredEnv(name string) (string, error) { | ||||||
|  | 	if val, exists := os.LookupEnv(name); exists && len(val) > 0 { | ||||||
|  | 		return val, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return "", fmt.Errorf("required env var `%s` is not set", name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func renderTemplateString(s string) (string, error) { | func renderTemplateString(s string) (string, error) { | ||||||
|  |  | ||||||
|  | @ -351,6 +351,25 @@ func Test_renderTemplateString(t *testing.T) { | ||||||
| 			}, | 			}, | ||||||
| 			wantErr: true, | 			wantErr: true, | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "required env var", | ||||||
|  | 			args: args{ | ||||||
|  | 				s: "{{ requiredEnv \"HF_TEST\" }}", | ||||||
|  | 				envs: map[string]string{ | ||||||
|  | 					"HF_TEST": "value", | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			want:    "value", | ||||||
|  | 			wantErr: false, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name: "required env var not set", | ||||||
|  | 			args: args{ | ||||||
|  | 				s:    "{{ requiredEnv \"HF_TEST_NONE\" }}", | ||||||
|  | 				envs: map[string]string{}, | ||||||
|  | 			}, | ||||||
|  | 			wantErr: true, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
| 	for _, tt := range tests { | 	for _, tt := range tests { | ||||||
| 		t.Run(tt.name, func(t *testing.T) { | 		t.Run(tt.name, func(t *testing.T) { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue