From 6fe958883d21cba100912765ce479b142b27e0e6 Mon Sep 17 00:00:00 2001 From: Tomas Tomecek Date: Sat, 16 Mar 2019 14:57:29 +0100 Subject: [PATCH] enable loading variables recursively Signed-off-by: Tomas Tomecek --- ansible_bender/constants.py | 1 + ansible_bender/core.py | 47 ++++++++++++++++++++-------------- tests/data/full_conf_pb.yaml | 2 +- tests/integration/test_conf.py | 14 +++++----- 4 files changed, 37 insertions(+), 27 deletions(-) diff --git a/ansible_bender/constants.py b/ansible_bender/constants.py index 6f0165f..f185e73 100644 --- a/ansible_bender/constants.py +++ b/ansible_bender/constants.py @@ -1,6 +1,7 @@ OUT_LOGGER = "ab-out" OUT_LOGGER_FORMAT = "%(message)s" TIMESTAMP_FORMAT = "%Y%m%d-%H%M%S%f" +TIMESTAMP_FORMAT_TOGETHER = "%Y%m%d%H%M%S%f" NO_CACHE_TAG = "no-cache" # configuration related constants diff --git a/ansible_bender/core.py b/ansible_bender/core.py index 0871e1e..0c21f33 100644 --- a/ansible_bender/core.py +++ b/ansible_bender/core.py @@ -28,6 +28,7 @@ ... """ +import copy import datetime import json import logging @@ -43,7 +44,7 @@ import ansible_bender from ansible_bender import callback_plugins from ansible_bender.conf import ImageMetadata, Build -from ansible_bender.constants import TIMESTAMP_FORMAT +from ansible_bender.constants import TIMESTAMP_FORMAT, TIMESTAMP_FORMAT_TOGETHER from ansible_bender.exceptions import AbBuildUnsuccesful from ansible_bender.utils import run_cmd, ap_command_exists, random_str, graceful_get, \ is_ansibles_python_2 @@ -241,7 +242,7 @@ def expand_pb_vars(self): """ populate vars from a playbook, defined in vars section - :return: dict + :return: dict with the content of ansible_bender var """ with open(self.playbook_path) as fd: plays = yaml.safe_load(fd) @@ -259,38 +260,49 @@ def expand_pb_vars(self): bender_vars = graceful_get(d, "vars", "ansible_bender") if not bender_vars: + logger.info("no bender data found in the playbook") return {} tmp = tempfile.mkdtemp(prefix="ab") json_data_path = os.path.join(tmp, "j.json") + + # we cannot use "vars" variable because the variables are not expanded in there + pb_vars = copy.deepcopy(d["vars"]) + while True: + # just in case the variable is already defined + timestamp = datetime.datetime.now().strftime(TIMESTAMP_FORMAT_TOGETHER) + ab_vars_key = f"ab_vars_{timestamp}" + if ab_vars_key not in pb_vars: + logger.debug("ab vars key = %s", ab_vars_key) + pb_vars[ab_vars_key] = d["vars"] + break + jinja_pb_vars_key = '{{ %s }}' % ab_vars_key pb = { "name": "Let Ansible expand variables", "hosts": "localhost", - "vars": { - "ab_vars": d["vars"], - }, + "vars": pb_vars, "vars_files": d.get("vars_files", []), "gather_facts": False, "tasks": [ - {"debug": {"msg": "{{ ab_vars }}"}}, + {"debug": {"msg": jinja_pb_vars_key}}, { "copy": { "dest": json_data_path, - "content": '{{ ab_vars }}' + "content": jinja_pb_vars_key } } ] } + i_path = os.path.join(tmp, "i") with open(i_path, "w") as fd: fd.write("localhost ansible_connection=local") - tmp_pb_path = os.path.join(tmp, "p.yaml") + tmp_pb_path = os.path.join(tmp, "p.json") with open(tmp_pb_path, "w") as fd: - yaml.safe_dump([pb], fd) + json.dump([pb], fd) playbook_base = os.path.basename(self.playbook_path).split(".", 1)[0] - timestamp = datetime.datetime.now().strftime(TIMESTAMP_FORMAT) symlink_name = f".{playbook_base}-{timestamp}-{random_str()}.yaml" playbook_dir = os.path.dirname(self.playbook_path) symlink_path = os.path.join(playbook_dir, symlink_name) @@ -304,22 +316,19 @@ def expand_pb_vars(self): provide_output=False, log_stderr=True, ansible_args=args) with open(json_data_path) as fd: - return json.load(fd) + return json.load(fd)["ansible_bender"] finally: os.unlink(symlink_path) shutil.rmtree(tmp) - def process_pb_vars(self, playbook_vars): + def process_pb_vars(self, bender_data): """ accept variables from the playbook and update the Build and ImageMetadata objects with them - :param playbook_vars: dict with all the playbook variables + :param bender_data: dict with the content of ansible_bender vars :return: """ - try: - bender_data = playbook_vars["ansible_bender"] - except KeyError: - logger.info("no bender data found in the playbook") + if not bender_data: return self.metadata.update_from_configuration(bender_data.get("target_image", {})) self.build.update_from_configuration(bender_data) @@ -330,8 +339,8 @@ def get_build_and_metadata(self): :return: Build(), ImageMetadata() """ - data = self.expand_pb_vars() + bender_data = self.expand_pb_vars() - self.process_pb_vars(data) + self.process_pb_vars(bender_data) return self.build, self.metadata diff --git a/tests/data/full_conf_pb.yaml b/tests/data/full_conf_pb.yaml index d261a05..de3f3b0 100644 --- a/tests/data/full_conf_pb.yaml +++ b/tests/data/full_conf_pb.yaml @@ -22,7 +22,7 @@ annotations: bohemian: rhapsody environment: - z: x + z: '{{ key }}' cmd: command -x -y z user: leonardo diff --git a/tests/integration/test_conf.py b/tests/integration/test_conf.py index 458e894..0307f31 100644 --- a/tests/integration/test_conf.py +++ b/tests/integration/test_conf.py @@ -13,13 +13,13 @@ def test_expand_pb_vars(): p = PbVarsParser(b_p_w_vars_path) data = p.expand_pb_vars() - assert data["ansible_bender"]["base_image"] == "docker.io/library/python:3-alpine" - assert data["ansible_bender"]["ansible_extra_args"] == "-vvv" + assert data["base_image"] == "docker.io/library/python:3-alpine" + assert data["ansible_extra_args"] == "-vvv" playbook_dir = os.path.dirname(b_p_w_vars_path) - assert data["ansible_bender"]["working_container"]["volumes"] == [f"{playbook_dir}:/src"] - assert data["ansible_bender"]["target_image"]["name"] == "challet" - assert data["ansible_bender"]["target_image"]["labels"] == {"x": "y"} - assert data["ansible_bender"]["target_image"]["environment"] == {"asd": playbook_dir} + assert data["working_container"]["volumes"] == [f"{playbook_dir}:/src"] + assert data["target_image"]["name"] == "challet" + assert data["target_image"]["labels"] == {"x": "y"} + assert data["target_image"]["environment"] == {"asd": playbook_dir} def test_b_m_empty(): @@ -59,7 +59,7 @@ def test_set_all_params(): assert b.build_volumes == ["/c:/d"] assert b.target_image == "funky-mona-lisa" - assert m.env_vars == {"z": "x"} + assert m.env_vars == {"z": "value"} assert m.volumes == ["/a"] assert m.working_dir == "/workshop" assert m.labels == {"x": "y"}