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

Expose env vars as parameters to the stack #682

Merged
merged 2 commits into from
Aug 7, 2023
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
1 change: 1 addition & 0 deletions ecs_composex/compose/compose_services/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ def __init__(
self.set_container_definition()
self.links = set_else_none("links", definition)
self.family_links: list = []
self.x_environment: dict = set_else_none("x-environment", definition, {})

def __repr__(self):
return self.name
Expand Down
11 changes: 11 additions & 0 deletions ecs_composex/ecs/ecs_family/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,17 @@ def validate_compute_configuration_for_task(self, settings):

validate_compute_configuration_for_task(self, settings)

def x_environment_processing(self):
"""
Checks for each service if `x-environment` was set
"""
from .family_helpers import swap_environment_value_with_parameter

for service in self.ordered_services:
if not service.x_environment:
continue
swap_environment_value_with_parameter(self, service)


class ServiceStack(ComposeXStack):
"""
Expand Down
87 changes: 86 additions & 1 deletion ecs_composex/ecs/ecs_family/family_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,30 @@

from __future__ import annotations

from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Union

if TYPE_CHECKING:
from ecs_composex.common.settings import ComposeXSettings
from ecs_composex.ecs.ecs_family import ComposeFamily
from ecs_composex.common.stacks import ComposeXStack
from ecs_composex.compose.compose_services import ComposeService
from troposphere.iam import Role

from troposphere import (
AWS_ACCOUNT_ID,
AWS_PARTITION,
AWS_REGION,
MAX_PARAMETERS,
FindInMap,
GetAtt,
NoValue,
Ref,
Sub,
)
from troposphere.ecs import Environment
from troposphere.iam import Policy, PolicyType

from ecs_composex.common import NONALPHANUM
from ecs_composex.common.cfn_params import Parameter
from ecs_composex.common.logging import LOG
from ecs_composex.common.troposphere_tools import add_parameters
Expand Down Expand Up @@ -312,3 +316,84 @@ def set_service_dependency_on_all_iam_policies(family: ComposeFamily) -> None:
else:
setattr(family.ecs_service.ecs_service, "DependsOn", policies)
LOG.debug(family.ecs_service.ecs_service.DependsOn)


def update_env_var_to_parameter(
family: ComposeFamily,
service: ComposeService,
env_var: Environment,
set_as_params: Union[list, dict],
) -> None:
"""
Function that will replace a user-defined environment variable with a Template Parameter
If the SetAsParameter is a list, goes through them and generates the CFN Parameter properties
If SetAsParameter is a dict, it will import the user-defined Parameter settings.
"""
type_to_param_type: dict = {str: "String", int: "Number", float: "Number"}
for var_name in set_as_params:
if env_var.Name != var_name:
continue
if env_var.Name not in service.environment:
continue
parameter_title: str = NONALPHANUM.sub("", var_name)
if type(service.environment[var_name]):
LOG.warning(
"{}.{} - Env var values have to be string. Value will be cast with Sub".format(
family.name, service.name
)
)
if isinstance(set_as_params, list):
env_var_param = Parameter(
parameter_title,
group_label="User Defined Service Variable",
Type=type_to_param_type[type(service.environment[var_name])],
)
elif isinstance(set_as_params, dict):
if (
"Type" in set_as_params[var_name]
and set_as_params[var_name]["Type"].find("List") >= 0
):
raise ValueError(
"{}.{} - For environment variables, Parameter property Type cannot be a List. Got {}".format(
family.name, service.name, set_as_params[var_name]["Type"]
)
)
env_var_param = Parameter(
parameter_title,
group_label="User Defined Service Variable",
**set_as_params[var_name],
)
else:
raise TypeError(
"services.{} - Value for x-environment.SetAsParameter must be either a list or mapping/dict. Got",
type(set_as_params),
)
add_parameters(family.template, [env_var_param])
family.stack.Parameters.update(
{env_var_param.title: service.environment[var_name]}
)
setattr(env_var, "Value", Sub(env_var_param.title))


def swap_environment_value_with_parameter(
family: ComposeFamily, service: ComposeService
) -> None:
set_as_params = service.x_environment["SetAsParameter"]
for env_var in service.cfn_environment:
if len(family.stack.Parameters) > MAX_PARAMETERS:
LOG.warning(
"{}.{} - Too many parameters already set for this stack".format(
family.name, service.name
)
)
break
if not isinstance(env_var, Environment):
continue
if not isinstance(env_var.Value, (str, int, float)):
LOG.debug(
"Env var {} is not str or int. Cannot convert. Got {}".format(
env_var.Name, type(env_var.Value)
),
)
continue
update_env_var_to_parameter(family, service, env_var, set_as_params)
1 change: 1 addition & 0 deletions ecs_composex/ecs_composex.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ def generate_full_template(settings: ComposeXSettings):
family.finalize_family_settings()
map_resource_return_value_to_services_command(family, settings)
family.state_facts()
family.x_environment_processing()

set_ecs_cluster_identifier(settings.root_stack, settings)
add_all_tags(settings.root_stack.stack_template, settings)
Expand Down
3 changes: 3 additions & 0 deletions ecs_composex/specs/compose-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@
"x-docker_opts": {
"$ref": "services.x-docker_opts.spec.json"
},
"x-environment": {
"$ref": "services.x-environment.spec.json"
},
"x-prometheus": {
"$ref": "services.x-prometheus.spec.json"
},
Expand Down
36 changes: 36 additions & 0 deletions ecs_composex/specs/services.x-environment.spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"id": "services.x-environment",
"$id": "services.x-environment.spec.json",
"type": "object",
"title": "services.x-environment specification",
"description": "The services.x-environment specification for ComposeX",
"additionalProperties": false,
"required": [
"SetAsParameter"
],
"properties": {
"SetAsParameter": {
"oneOf": [
{
"type": "object",
"minProperties": 1,
"additionalProperties": false,
"patternProperties": {
"^x-": {},
"^[a-zA-Z0-9_]+$": {
"type": "object"
}
}
},
{
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
}
]
}
}
}