diff --git a/stack_orchestrator/constants.py b/stack_orchestrator/constants.py
index 1cff6055..54cfe355 100644
--- a/stack_orchestrator/constants.py
+++ b/stack_orchestrator/constants.py
@@ -14,6 +14,8 @@
# along with this program. If not, see .
stack_file_name = "stack.yml"
+spec_file_name = "spec.yml"
+config_file_name = "config.env"
compose_deploy_type = "compose"
k8s_kind_deploy_type = "k8s-kind"
k8s_deploy_type = "k8s"
diff --git a/stack_orchestrator/deploy/deployment_create.py b/stack_orchestrator/deploy/deployment_create.py
index fd52dba8..88ce0b2a 100644
--- a/stack_orchestrator/deploy/deployment_create.py
+++ b/stack_orchestrator/deploy/deployment_create.py
@@ -25,7 +25,7 @@ from stack_orchestrator import constants
from stack_orchestrator.opts import opts
from stack_orchestrator.util import (get_stack_file_path, get_parsed_deployment_spec, get_parsed_stack_config,
global_options, get_yaml, get_pod_list, get_pod_file_path, pod_has_scripts,
- get_pod_script_paths, get_plugin_code_paths, error_exit)
+ get_pod_script_paths, get_plugin_code_paths, error_exit, env_var_map_from_file)
from stack_orchestrator.deploy.deploy_types import LaconicStackSetupCommand
from stack_orchestrator.deploy.deployer_factory import getDeployerConfigGenerator
from stack_orchestrator.deploy.deployment_context import DeploymentContext
@@ -244,12 +244,13 @@ def _parse_config_variables(variable_values: str):
variable_name = variable_value_pair[0]
variable_value = variable_value_pair[1]
result_values[variable_name] = variable_value
- result = {"config": result_values}
+ result = result_values
return result
@click.command()
@click.option("--config", help="Provide config variables for the deployment")
+@click.option("--config-file", help="Provide config variables in a file for the deployment")
@click.option("--kube-config", help="Provide a config file for a k8s deployment")
@click.option("--image-registry", help="Provide a container image registry url for this k8s cluster")
@click.option("--output", required=True, help="Write yaml spec file here")
@@ -257,14 +258,15 @@ def _parse_config_variables(variable_values: str):
help="Map ports to the host as one of: any-variable-random (default), "
"localhost-same, any-same, localhost-fixed-random, any-fixed-random")
@click.pass_context
-def init(ctx, config, kube_config, image_registry, output, map_ports_to_host):
+def init(ctx, config, config_file, kube_config, image_registry, output, map_ports_to_host):
stack = global_options(ctx).stack
deployer_type = ctx.obj.deployer.type
deploy_command_context = ctx.obj
return init_operation(
deploy_command_context,
stack, deployer_type,
- config, kube_config,
+ config, config_file,
+ kube_config,
image_registry,
output,
map_ports_to_host)
@@ -272,7 +274,8 @@ def init(ctx, config, kube_config, image_registry, output, map_ports_to_host):
# The init command's implementation is in a separate function so that we can
# call it from other commands, bypassing the click decoration stuff
-def init_operation(deploy_command_context, stack, deployer_type, config, kube_config, image_registry, output, map_ports_to_host):
+def init_operation(deploy_command_context, stack, deployer_type, config,
+ config_file, kube_config, image_registry, output, map_ports_to_host):
yaml = get_yaml()
default_spec_file_content = call_stack_deploy_init(deploy_command_context)
spec_file_content = {"stack": stack, constants.deploy_to_key: deployer_type}
@@ -292,12 +295,22 @@ def init_operation(deploy_command_context, stack, deployer_type, config, kube_co
if default_spec_file_content:
spec_file_content.update(default_spec_file_content)
config_variables = _parse_config_variables(config)
+ # Implement merge, since update() overwrites
if config_variables:
- # Implement merge, since update() overwrites
orig_config = spec_file_content.get("config", {})
- new_config = config_variables["config"]
+ new_config = config_variables
merged_config = {**new_config, **orig_config}
spec_file_content.update({"config": merged_config})
+ if config_file:
+ config_file_path = Path(config_file)
+ if not config_file_path.exists():
+ error_exit(f"config file: {config_file} does not exist")
+ config_file_variables = env_var_map_from_file(config_file_path)
+ if config_file_variables:
+ orig_config = spec_file_content.get("config", {})
+ new_config = config_file_variables
+ merged_config = {**new_config, **orig_config}
+ spec_file_content.update({"config": merged_config})
if opts.o.debug:
print(f"Creating spec file for stack: {stack} with content: {spec_file_content}")
@@ -368,10 +381,10 @@ def create_operation(deployment_command_context, spec_file, deployment_dir, netw
error_exit(f"{deployment_dir_path} already exists")
os.mkdir(deployment_dir_path)
# Copy spec file and the stack file into the deployment dir
- copyfile(spec_file, deployment_dir_path.joinpath("spec.yml"))
+ copyfile(spec_file, deployment_dir_path.joinpath(constants.spec_file_name))
copyfile(stack_file, deployment_dir_path.joinpath(os.path.basename(stack_file)))
# Copy any config varibles from the spec file into an env file suitable for compose
- _write_config_file(spec_file, deployment_dir_path.joinpath("config.env"))
+ _write_config_file(spec_file, deployment_dir_path.joinpath(constants.config_file_name))
# Copy any k8s config file into the deployment dir
if deployment_type == "k8s":
_write_kube_config_file(Path(parsed_spec[constants.kube_config_key]),
diff --git a/stack_orchestrator/deploy/k8s/cluster_info.py b/stack_orchestrator/deploy/k8s/cluster_info.py
index 6c19b20a..0aa74189 100644
--- a/stack_orchestrator/deploy/k8s/cluster_info.py
+++ b/stack_orchestrator/deploy/k8s/cluster_info.py
@@ -17,9 +17,10 @@ from kubernetes import client
from typing import Any, List, Set
from stack_orchestrator.opts import opts
+from stack_orchestrator.util import env_var_map_from_file
from stack_orchestrator.deploy.k8s.helpers import named_volumes_from_pod_files, volume_mounts_for_service, volumes_for_pod_files
from stack_orchestrator.deploy.k8s.helpers import get_node_pv_mount_path
-from stack_orchestrator.deploy.k8s.helpers import env_var_map_from_file, envs_from_environment_variables_map
+from stack_orchestrator.deploy.k8s.helpers import envs_from_environment_variables_map
from stack_orchestrator.deploy.deploy_util import parsed_pod_files_map_from_file_names, images_for_deployment
from stack_orchestrator.deploy.deploy_types import DeployEnvVars
from stack_orchestrator.deploy.spec import Spec
diff --git a/stack_orchestrator/deploy/k8s/helpers.py b/stack_orchestrator/deploy/k8s/helpers.py
index 82a33792..9f968dbf 100644
--- a/stack_orchestrator/deploy/k8s/helpers.py
+++ b/stack_orchestrator/deploy/k8s/helpers.py
@@ -14,7 +14,6 @@
# along with this program. If not, see .
from kubernetes import client
-from dotenv import dotenv_values
import os
from pathlib import Path
import subprocess
@@ -224,7 +223,3 @@ def generate_kind_config(deployment_dir: Path):
f"{port_mappings_yml}\n"
f"{mounts_yml}\n"
)
-
-
-def env_var_map_from_file(file: Path) -> Mapping[str, str]:
- return dotenv_values(file)
diff --git a/stack_orchestrator/deploy/webapp/deploy_webapp.py b/stack_orchestrator/deploy/webapp/deploy_webapp.py
index a2cd7253..391162c9 100644
--- a/stack_orchestrator/deploy/webapp/deploy_webapp.py
+++ b/stack_orchestrator/deploy/webapp/deploy_webapp.py
@@ -98,6 +98,7 @@ def create(ctx, deployment_dir, image, url, kube_config, image_registry, env_fil
stack,
"k8s",
None,
+ env_file,
kube_config,
image_registry,
spec_file_name,
diff --git a/stack_orchestrator/util.py b/stack_orchestrator/util.py
index 97d48963..0bd1a609 100644
--- a/stack_orchestrator/util.py
+++ b/stack_orchestrator/util.py
@@ -18,6 +18,8 @@ import os.path
import sys
import ruamel.yaml
from pathlib import Path
+from dotenv import dotenv_values
+from typing import Mapping
def include_exclude_check(s, include, exclude):
@@ -178,3 +180,7 @@ def global_options2(ctx):
def error_exit(s):
print(f"ERROR: {s}")
sys.exit(1)
+
+
+def env_var_map_from_file(file: Path) -> Mapping[str, str]:
+ return dotenv_values(file)