func()

in internal/generators/helm.go [150:235]


func (hg *HelmGenerator) Generate(component *core.Component) (manifest string, err error) {
	logger.Info(emoji.Sprintf(":truck: Generating component '%s' with helm with repo %s", component.Name, component.Source))

	configYaml, err := yaml.Marshal(&component.Config.Config)
	if err != nil {
		logger.Error(fmt.Sprintf("Marshalling config yaml for helm generated component '%s' failed with: %s\n", component.Name, err.Error()))
		return "", err
	}

	// Write helm config to temporary file in tmp folder
	randomString, err := uuid.NewRandom()
	if err != nil {
		return "", err
	}
	overriddenValuesFileName := fmt.Sprintf("%s.yaml", randomString.String())
	absOverriddenPath := path.Join(os.TempDir(), overriddenValuesFileName)
	defer os.Remove(absOverriddenPath)

	logger.Debug(emoji.Sprintf(":pencil: Writing config %s to %s\n", configYaml, absOverriddenPath))
	if err = ioutil.WriteFile(absOverriddenPath, configYaml, 0777); err != nil {
		return "", err
	}

	// Default to `default` namespace unless provided
	namespace := "default"
	if component.Config.Namespace != "" {
		namespace = component.Config.Namespace
	}

	// Run `helm template` on the chart using the config stored in temp dir
	chartPath, err := hg.getChartPath(component)
	if err != nil {
		return "", err
	}
	logger.Info(emoji.Sprintf(":memo: Running `helm template` on template '%s'", chartPath))
	output, err := exec.Command("helm", "template", component.Name, chartPath, "--values", absOverriddenPath, "--namespace", namespace).CombinedOutput()
	if err != nil {
		logger.Error(fmt.Sprintf("helm template failed with:\n%s: %s", err, output))
		return "", err
	}
	// Remove any empty/non-map entries in manifests
	logger.Info(emoji.Sprintf(":scissors: Removing empty entries from generated manifests from chart '%s'", chartPath))
	stringManifests, err := cleanK8sManifest(string(output))
	if err != nil {
		return "", err
	}

	// helm template does not inject namespace unless chart directly provides support for it: https://github.com/helm/helm/issues/3553
	// some helm templates expect Tiller to inject namespace, so enable Fabrikate component designer to
	// opt into injecting these namespaces manually.  We should reassess if this is necessary after Helm 3 is released and client side
	// templating really becomes a first class function in Helm.
	if component.Config.InjectNamespace && component.Config.Namespace != "" {
		logger.Info(emoji.Sprintf(":syringe: Injecting namespace '%s' into manifests for component '%s'", component.Config.Namespace, component.Name))
		var successes []namespaceInjectionResponse
		for resp := range addNamespaceToManifests(stringManifests, component.Config.Namespace) {
			// If error; return the error immediately
			if resp.err != nil {
				logger.Error(emoji.Sprintf(":exclamation: Encountered error while injecting namespace '%s' into manifests for component '%s':\n%s", component.Config.Namespace, component.Name, resp.err))
				return stringManifests, resp.err
			}

			// If warning; just log the warning
			if resp.warn != nil {
				logger.Warn(emoji.Sprintf(":question: Encountered warning while injecting namespace '%s' into manifests for component '%s':\n%s", component.Config.Namespace, component.Name, *resp.warn))
			}

			// Add the manifest if one was returned
			if resp.namespacedManifest != nil {
				successes = append(successes, resp)
			}
		}

		sort.Slice(successes, func(i, j int) bool {
			return successes[i].index < successes[j].index
		})

		namespacedManifests := ""
		for _, resp := range successes {
			namespacedManifests += fmt.Sprintf("---\n%s\n", *resp.namespacedManifest)
		}

		stringManifests = namespacedManifests
	}

	return stringManifests, err
}