def _parse_chart( all_config: Tuple[str, Union[ChartOpts, LocalChartOpts], pulumi.ResourceOptions] ) -> pulumi.Output: release_name, config, opts = all_config # Create temporary directory and file to hold chart data and override values. with NamedTemporaryFile() as overrides: with TemporaryDirectory() as chart_dir: if isinstance(config, ChartOpts): chart_to_fetch = f'{config.repo}/{config.chart}' if config.repo else config.chart # Configure fetch options. fetch_opts_dict = {} if config.fetch_opts is not None: fetch_opts_dict = { k: v for k, v in vars(config.fetch_opts).items() if v is not None } fetch_opts_dict["destination"] = chart_dir if config.version is not None: fetch_opts_dict["version"] = config.version fetch_opts = FetchOpts(**fetch_opts_dict) # Fetch the chart. _fetch(chart_to_fetch, fetch_opts) fetched_chart_name = os.listdir(chart_dir)[0] chart = os.path.join(chart_dir, fetched_chart_name) else: chart = config.path default_values = os.path.join(chart, 'values.yaml') # Write overrides file. vals = config.values if config.values is not None else {} data = json.dumps(vals).encode('utf-8') overrides.write(data) namespace_arg = ['--namespace', config.namespace ] if config.namespace else [] # Use 'helm template' to create a combined YAML manifest. cmd = [ 'helm', 'template', chart, '--name', release_name, '--values', default_values, '--values', overrides.name ] cmd.extend(namespace_arg) output = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, check=True) yaml_str: str = output.stdout # Parse the manifest and create the specified resources. return _parse_yaml_document(yaml.safe_load_all(yaml_str), opts, config.transformations)
def _parse_chart(all_config: Tuple[str, Union[ChartOpts, LocalChartOpts], pulumi.ResourceOptions]) -> pulumi.Output: release_name, config, opts = all_config # Create temporary directory and file to hold chart data and override values. # Note: We're intentionally using the lower-level APIs here because the async Outputs are being handled in # a different scope, which was causing the temporary files/directory to be deleted before they were referenced # in the Output handlers. We manually clean these up once we're done with another async handler that depends # on the result of the operations. overrides, overrides_filename = mkstemp() chart_dir = mkdtemp() if isinstance(config, ChartOpts): if config.repo and 'http' in config.repo: raise ValueError('`repo` specifies the name of the Helm chart repo.' 'Use `fetch_opts.repo` to specify a URL.') chart_to_fetch = f'{config.repo}/{config.chart}' if config.repo else config.chart # Configure fetch options. fetch_opts_dict = {} if config.fetch_opts is not None: fetch_opts_dict = {k: v for k, v in vars(config.fetch_opts).items() if v is not None} fetch_opts_dict["destination"] = chart_dir if config.version is not None: fetch_opts_dict["version"] = config.version fetch_opts = FetchOpts(**fetch_opts_dict) # Fetch the chart. _fetch(chart_to_fetch, fetch_opts) fetched_chart_name = os.listdir(chart_dir)[0] chart = os.path.join(chart_dir, fetched_chart_name) else: chart = config.path default_values = os.path.join(chart, 'values.yaml') # Write overrides file. vals = config.values if config.values is not None else {} data = pulumi.Output.from_input(vals).apply(lambda x: json.dumps(x)) file = open(overrides, 'w') pulumi.Output.all(file, data).apply(_write_override_file) namespace_arg = ['--namespace', config.namespace] if config.namespace else [] # Use 'helm template' to create a combined YAML manifest. cmd = ['helm', 'template', chart, '--name', release_name, '--values', default_values, '--values', overrides_filename] cmd.extend(namespace_arg) chart_resources = pulumi.Output.all(cmd, data).apply(_run_helm_cmd) # Parse the manifest and create the specified resources. resources = chart_resources.apply( lambda yaml_str: _parse_yaml_document(yaml.safe_load_all(yaml_str), opts, config.transformations)) pulumi.Output.all(file, chart_dir, resources).apply(_cleanup_temp_dir) return resources
def _parse_chart(all_config: Tuple[Union[ChartOpts, LocalChartOpts], pulumi.ResourceOptions]) -> pulumi.Output: config, opts = all_config json_opts = config.to_json() # Rather than using the default provider for the following invoke call, use the version specified # in package.json. invoke_opts = pulumi.InvokeOptions(version=_utilities.get_version()) objects = json_opts.apply(lambda x: pulumi.runtime.invoke('kubernetes:helm:template', {'jsonOpts': x}, invoke_opts).value['result']) return objects.apply(lambda x: _parse_yaml_document(x, opts, config.transformations))
def _parse_chart( all_config: Tuple[str, Union[ChartOpts, LocalChartOpts], pulumi.ResourceOptions] ) -> pulumi.Output: release_name, config, opts = all_config # Create temporary directory and file to hold chart data and override values. # Note: We're intentionally using the lower-level APIs here because the async Outputs are being handled in # a different scope, which was causing the temporary files/directory to be deleted before they were referenced # in the Output handlers. We manually clean these up once we're done with another async handler that depends # on the result of the operations. overrides, overrides_filename = mkstemp() chart_dir = mkdtemp() if isinstance(config, ChartOpts): if config.repo and 'http' in config.repo: raise ValueError( '`repo` specifies the name of the Helm chart repo.' 'Use `fetch_opts.repo` to specify a URL.') chart_to_fetch = f'{config.repo}/{config.chart}' if config.repo else config.chart # Configure fetch options. fetch_opts_dict = {} if config.fetch_opts is not None: fetch_opts_dict = { k: v for k, v in vars(config.fetch_opts).items() if v is not None } fetch_opts_dict["destination"] = chart_dir if config.version is not None: fetch_opts_dict["version"] = config.version fetch_opts = FetchOpts(**fetch_opts_dict) # Fetch the chart. _fetch(chart_to_fetch, fetch_opts) # Sort the directories into alphabetical order, and choose the first fetched_chart_name = sorted(os.listdir(chart_dir), key=str.lower)[0] chart = os.path.join(chart_dir, fetched_chart_name) else: chart = config.path default_values = os.path.join(chart, 'values.yaml') # Write overrides file. vals = config.values if config.values is not None else {} data = pulumi.Output.from_input(vals).apply(lambda x: json.dumps(x)) file = open(overrides, 'w') pulumi.Output.all(file, data).apply(_write_override_file) apiversions_arg = [ f'--api-versions={version}' for version in config.api_versions ] if config.api_versions else [] namespace_arg = ['--namespace', config.namespace ] if config.namespace else [] crd_arg = ['--include-crds'] if _is_helm_v3() else [] # Use 'helm template' to create a combined YAML manifest. cmd = [ 'helm', 'template', chart, '--name-template', release_name, '--values', default_values, '--values', overrides_filename ] cmd.extend(apiversions_arg) cmd.extend(namespace_arg) cmd.extend(crd_arg) chart_resources = pulumi.Output.all(cmd, data).apply(_run_helm_cmd) # Rather than using the default provider for the following invoke call, use the version specified # in package.json. invoke_opts = pulumi.InvokeOptions(version=_utilities.get_version()) objects = chart_resources.apply( lambda text: pulumi.runtime.invoke('kubernetes:yaml:decode', { 'text': text, 'defaultNamespace': config.namespace }, invoke_opts).value['result']) # Parse the manifest and create the specified resources. resources = objects.apply(lambda objects: _parse_yaml_document( objects, opts, config.transformations)) pulumi.Output.all(file, chart_dir, resources).apply(_cleanup_temp_dir) return resources