Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added env variable support for himl #55

Merged
merged 2 commits into from
Jul 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ remote_states:
endpoint: "{{outputs.cluster_composition.output.value.redis_endpoint}}"
```

### Merge with env variables
```yaml
kubeconfig_location: {{env(KUBECONFIG)}}
```


## himl config merger

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
cluster: cluster1
home: {{env(HOME)}}
10 changes: 9 additions & 1 deletion himl/config_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
import yaml
from deepmerge import Merger

from .interpolation import InterpolationResolver, EscapingResolver, InterpolationValidator, SecretResolver, DictIterator, replace_parent_working_directory
from .interpolation import InterpolationResolver, EscapingResolver, InterpolationValidator, SecretResolver, \
DictIterator, replace_parent_working_directory, EnvVarResolver
from .python_compat import iteritems, primitive_types, PY3
from .remote_state import S3TerraformRemoteStateRetriever

Expand Down Expand Up @@ -68,6 +69,9 @@ def process(self, cwd=None, path=None, filters=(), exclude_keys=(), enclosing_ke
# value2: "something-{{value1}} <--- this will be resolved at this step
generator.resolve_interpolations()

generator.resolve_env()
generator.resolve_interpolations()

if len(filters) > 0:
generator.filter_data(filters)

Expand Down Expand Up @@ -279,6 +283,10 @@ def resolve_secrets(self, default_aws_profile):
resolver = SecretResolver()
self.generated_data = resolver.resolve_secrets(self.generated_data, default_aws_profile)

def resolve_env(self):
resolver = EnvVarResolver()
self.generated_data = resolver.resolve_env_vars(self.generated_data)

def validate_interpolations(self):
self.interpolation_validator.check_all_interpolations_resolved(self.generated_data)

Expand Down
47 changes: 47 additions & 0 deletions himl/inject_env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright 2021 Adobe. All rights reserved.
# This file is licensed to you under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software distributed under
# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
# OF ANY KIND, either express or implied. See the License for the specific language
# governing permissions and limitations under the License.

from os import getenv


class EnvVarInjector(object):
"""
Resolve variables in the form:
{{env(HOME)}}
"""

def __init__(self):
return

def is_interpolation(self, value):
return value.startswith('{{') and value.endswith('}}')

def inject_env_var(self, line):
"""
Check if value is an interpolation and try to resolve it.
"""
if not self.is_interpolation(line):
return line

# remove {{ and }}
updated_line = line[2:-2]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about: key: "prefix-{{env(VAR)}}-suffix" ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to offer support for interpolation with prefix/suffix with environment variables? I was thinking something more similar to the secret resolvers

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess it's enough now


# check supported function to ensure the proper format is used
if not self.is_env_interpolation(updated_line):
return line

# remove env( and ) to extract the env Variable
updated_line = updated_line[4:-1]

# If env variable is missing or not set, the output will be None
return getenv(updated_line)

def is_env_interpolation(self, value):
return value.startswith('env(') and value.endswith(')')
18 changes: 18 additions & 0 deletions himl/interpolation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import re

from .inject_env import EnvVarInjector
from .inject_secrets import SecretInjector
from .python_compat import iteritems, string_types, primitive_types

Expand Down Expand Up @@ -83,6 +84,14 @@ def resolve_secrets(self, data, default_aws_profile):
return data


class EnvVarResolver(object):
def resolve_env_vars(self, data):
injector = EnvVarInjector()
env_resolver = EnvVarInterpolationsResolver(injector)
env_resolver.resolve_interpolations(data)
return data


class DictIterator(object):

def loop_all_items(self, data, process_func):
Expand Down Expand Up @@ -168,6 +177,15 @@ def do_resolve_interpolation(self, line):
return self.secrets_injector.inject_secret(line)


class EnvVarInterpolationsResolver(AbstractInterpolationResolver):
def __init__(self, env_vars_injector):
AbstractInterpolationResolver.__init__(self)
self.env_vars_injector = env_vars_injector

def do_resolve_interpolation(self, line):
return self.env_vars_injector.inject_env_var(line)


class InterpolationValidator(DictIterator):

def check_all_interpolations_resolved(self, data):
Expand Down