def render_single_yaml( self, input_path: str, output_path: str, checker: BaseChecker = None, raw: bool = False, ) -> None: """ Read in single YAML file from specified path, render environment variables, then write out to a known location in the working dir. """ self.logger.info("Rendering YAML at %s to %s", input_path, output_path) with open(input_path, "r") as fh: content = fh.read() if not raw: env = dict(get_kv(self.workflow.environment.render(), multiple=True)) rendered = render(content, env=env) rendered = render_jinja(rendered, env=env) else: rendered = content if checker: check_errors = checker.check(rendered) if check_errors: raise errors.ManifestCheck("\n".join(check_errors)) with open(output_path, "w") as fh: fh.write(rendered)
def render_config(workflow: "Workflow", config: dict) -> dict: # render the config prior to returning it content = yaml_dump(config) rendered_content = render(content, env=workflow.environment.data) rendered_config = yaml_load(rendered_content) print(f"rendered_config={rendered_config}") return rendered_config
def test_multiple_subs_on_same_line(self, *mocks): env = {'JOB_NAME': 'the-job', 'BUILD_NUMBER': '1234'} content = ( ' - /tmp/jenkins/${JOB_NAME}/${BUILD_NUMBER}:/usr/local/src/results' ) rendered = utils.render(content, env=env) expected = f' - /tmp/jenkins/{env["JOB_NAME"]}/{env["BUILD_NUMBER"]}:/usr/local/src/results' self.assertEqual(expected, rendered)
def data(self): try: content = self.load() except NoSuchConfig: content = {} # if the content is empty return immediately if not content: return content rendered = render(content) return yaml_load(rendered)
def render_single_yaml(self, input_path: str, output_path: str) -> None: ''' Read in single YAML file from specified path, render environment variables, then write out to a known location in the working dir. ''' self.logger.info("Rendering YAML at %s to %s", input_path, output_path) # TODO: Add support for multiple YAML documents in a single file with open(input_path, 'r') as fh: content = fh.read() rendered = render(content, env=self.workflow.environment.data) with open(output_path, 'w') as fh: fh.write(rendered)
def get_profile_compose_file(self, profile): """ Processes the profile to generate the compose file """ try: os.environ.update(self.env.data) except NoSuchConfig as exc: if not self.workflow.subcommand.is_env_error_okay(exc): raise filenames = get_overlay_filenames(profile) # merge multiple files together so that deploying stacks works # https://github.com/moby/moby/issues/30127 if len(filenames) > 1: yaml_contents = [] for item in filenames: with open(item, 'r') as fh: yaml_contents.append(yaml.load(fh)) merged = remerge(yaml_contents) content = yaml.dump(merged, default_flow_style=False) else: with open(filenames[0], 'r') as fh: content = fh.read() fh = tempfile.TemporaryFile(mode='w+') # render the file try: rendered = render(content) except EnvError as exc: if not self.workflow.subcommand.is_missing_profile_okay(exc): raise return fh fh.write(rendered) fh.flush() fh.seek(0, 0) return fh
def get_profile_compose_file(self, profile: dict): """ Processes the profile to generate the compose file """ content = self._compile(profile) fh = tempfile.TemporaryFile(mode="w+") # render the file try: rendered = render(content, env=self.workflow.environment.data) except EnvError as exc: if not self.workflow.subcommand.is_missing_profile_okay(exc): raise return fh fh.write(rendered) fh.flush() fh.seek(0, 0) return fh
def data(self) -> dict: """ Returns the loaded config as a dictionary """ if self._data is not None: return self._data data = self.load() # render placeholders for k, v in data.items(): if not v.startswith(RUNTIME_PLACEHOLDER): continue location, location_ref = v.split("://", 1) location_ref = location_ref or k if k not in self._rendered_config: self._rendered_config[k] = v new_val = os.environ.get(location_ref) if new_val is None: if (hasattr(self.workflow.args, "action") and self.is_env_modification_action()): new_val = RUNTIME_PLACEHOLDER else: raise errors.RuntimeEnvError( f"runtime substitution for {k}={v} not found") data[k] = new_val # render substitutions sub_count = True while sub_count: # reset the substitution count to break the loop when no subs are made sub_count = 0 for k, v in data.items(): rendered = utils.render(v, env=data) if rendered != v: sub_count += 1 if k not in self._rendered_config: self._rendered_config[k] = v data[k] = rendered if self.workflow.subcommand.update_version_env_vars: # regenerate the full docker image name self._docker_image = None data.update({ DOCKER_IMAGE_VAR: self.set_docker_tag(self.docker_image), VERSION_VAR: self.version, }) self._data = data return self._data
def data(self) -> dict: """ Returns the loaded config as a dictionary """ if self._data is not None: return self._data data = self.load() args = self.workflow.args action = None if 'action' in args: action = args.action # render placeholders for k, v in data.items(): if not v.startswith('runtime://'): continue location, location_ref = v.split('://', 1) location_ref = location_ref or k if k not in self._rendered_config: self._rendered_config[k] = v new_val = os.environ.get(location_ref) if new_val is None: raise errors.RuntimeEnvError( f'runtime substitution for {k}={v} not found') data[k] = new_val # render substitutions sub_count = True while sub_count: # reset the substitution count to break the loop when no subs are made sub_count = 0 for k, v in data.items(): rendered = utils.render(v, env=data) if rendered != v: sub_count += 1 if k not in self._rendered_config: self._rendered_config[k] = v data[k] = rendered # set defaults when no value is set for k, v in self.cf_env.items(): if k not in data: data[k] = v if self.workflow.subcommand.update_version_env_vars: data.update({ DOCKER_IMAGE_VAR: self.set_docker_tag(self.docker_image), VERSION_VAR: self.version, }) self._data = data return self._data