/// <summary> /// Create a Chart resource with the given unique name, arguments, and options. /// </summary> /// /// <param name="releaseName">The unique name of the resource</param> /// <param name="args">The arguments used to populate this resource's properties</param> /// <param name="options">A bag of options that control this resource's behavior</param> public Chart(string releaseName, Union <ChartArgs, LocalChartArgs> args, ComponentResourceOptions?options = null) : base("kubernetes:helm.sh/v3:Chart", GetName(args, releaseName), MakeResourceOptions(options)) { releaseName = GetName(args, releaseName); var config = args.Unwrap(); var configDeps = Output.Create(OutputUtilities.GetDependenciesAsync(config)); OutputUtilities.GetIsKnownAsync(config).ContinueWith(isKnown => { if (!isKnown.Result) { // Note that this can only happen during a preview. Log.Info("[Can't preview] all chart values must be known ahead of time to generate an accurate preview.", this); } }); var resources = Output.Tuple(config, configDeps).Apply(values => { var chartArgs = values.Item1; var dependencies = values.Item2; try { return(ParseTemplate(chartArgs, releaseName, dependencies)); } catch (Exception e) { // Shed stack trace, only emit the error. throw new ResourceException(e.Message, this); } }); RegisterResources(resources); }
/// <summary> /// Create an instance of the specified Helm chart. /// </summary> /// <param name="releaseName">Name of the Chart (e.g., nginx-ingress).</param> /// <param name="args">Configuration options for the Chart.</param> /// <param name="options">A bag of options that control this resource's behavior.</param> protected ChartBase(string releaseName, Union <ChartArgs, LocalChartArgs> args, ComponentResourceOptions?options = null) : base("kubernetes:helm.sh/v2:Chart", GetName(args, releaseName), options) { releaseName = GetName(args, releaseName); var config = args.Unwrap(); var configDeps = Output.Create(OutputUtilities.GetDependenciesAsync(config)); OutputUtilities.GetIsKnownAsync(config).ContinueWith(isKnown => { if (!isKnown.Result) { // Note that this can only happen during a preview. Log.Info("[Can't preview] all chart values must be known ahead of time to generate an accurate preview.", this); } }); var resources = Output.Tuple(config, configDeps).Apply(values => { var chartArgs = values.Item1; var dependencies = values.Item2; // Create temporary directories and files to hold chart data and override values. var overrides = Path.GetTempFileName(); var chartDirectoryName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); var chartDirectory = Directory.CreateDirectory(chartDirectoryName); try { string chart; string defaultValues; BaseChartArgsUnwrap cfgBase; if (chartArgs.IsT0) { var cfg = chartArgs.AsT0; // Fetch chart. if (cfg.Repo != null && cfg.Repo.Contains("http")) { throw new Exception( $"`{nameof(cfg.Repo)}` specifies the name of the Helm chart repo. Use `{nameof(ChartArgs)}.{nameof(cfg.Repo)}` to specify a URL."); } var chartToFetch = !string.IsNullOrEmpty(cfg.Repo) ? $"{cfg.Repo}/{cfg.Chart}" : cfg.Chart; var fetchOptions = cfg.FetchOptions ?? new ChartFetchArgsUnwrap(); fetchOptions.Destination = chartDirectoryName; fetchOptions.Version = cfg.Version; Fetch(chartToFetch, fetchOptions); // Sort the directories into alphabetical order, and choose the first var fetchedChart = chartDirectory.GetDirectories().OrderBy(x => x.Name).ToArray()[0]; var fetchedChartName = fetchedChart.Name; chart = fetchedChart.FullName; defaultValues = Path.Join(chartDirectoryName, fetchedChartName, "values.yaml"); cfgBase = cfg; } else { var cfg = chartArgs.AsT1; chart = cfg.Path; defaultValues = Path.Join(chart, "values.yaml"); cfgBase = cfg; } // Write overrides file. var data = JsonSerializer.Serialize(cfgBase.Values); File.WriteAllText(overrides, data); // Does not require Tiller. From the `helm template` documentation: // // > Render chart templates locally and display the output. // > // > This does not require Tiller. However, any values that would normally be // > looked up or retrieved in-cluster will be faked locally. Additionally, none // > of the server-side testing of chart validity (e.g. whether an API is supported) // > is done. var flags = new List <string>(new[] { "template", chart, "--name-template", releaseName, "--values", defaultValues, "--values", overrides }); if (cfgBase.ApiVersions.Length > 0) { flags.Add("--api-versions"); flags.Add(string.Join(",", cfgBase.ApiVersions)); } if (!string.IsNullOrEmpty(cfgBase.Namespace)) { flags.Add("--namespace"); flags.Add(cfgBase.Namespace); } if (IsHelmV3()) { flags.Add("--include-crds"); } var yaml = ExecuteCommand("helm", flags.ToArray(), new Dictionary <string, string>()); return(ParseTemplate( yaml, cfgBase.Transformations, cfgBase.ResourcePrefix, dependencies, cfgBase.Namespace)); } catch (Exception e) { // Shed stack trace, only emit the error. throw new ResourceException(e.Message, this); } finally { chartDirectory.Delete(true); } }); RegisterResources(resources); }