Ejemplo n.º 1
0
        /// <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);
        }
Ejemplo n.º 2
0
        /// <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);
        }