diff --git a/.github/actions/k3d/action.yaml b/.github/actions/k3d/action.yaml index b5496adcc0..d4d1d5bbbf 100644 --- a/.github/actions/k3d/action.yaml +++ b/.github/actions/k3d/action.yaml @@ -7,5 +7,5 @@ runs: - run: "curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash" shell: bash - - run: k3d cluster delete && k3d cluster create + - run: k3d cluster delete && k3d cluster create --k3s-arg="--disable=traefik@server:0" shell: bash diff --git a/docs/2-the-zarf-cli/100-cli-commands/zarf_dev_find-images.md b/docs/2-the-zarf-cli/100-cli-commands/zarf_dev_find-images.md index fdfb58a0f2..221ee2020a 100644 --- a/docs/2-the-zarf-cli/100-cli-commands/zarf_dev_find-images.md +++ b/docs/2-the-zarf-cli/100-cli-commands/zarf_dev_find-images.md @@ -16,11 +16,14 @@ zarf dev find-images [ PACKAGE ] [flags] ## Options ``` - -h, --help help for find-images - --kube-version string Override the default helm template KubeVersion when performing a package chart template - -p, --repo-chart-path string If git repos hold helm charts, often found with gitops tools, specify the chart path, e.g. "/" or "/chart" - --set stringToString Specify package variables to set on the command line (KEY=value). Note, if using a config file, this will be set by [package.create.set]. (default []) - --why string Find the location of the image given as an argument and print it to the console. + --create-set stringToString Specify package variables to set on the command line (KEY=value). Note, if using a config file, this will be set by [package.create.set]. (default []) + --deploy-set stringToString Specify deployment variables to set on the command line (KEY=value) (default []) + -f, --flavor string The flavor of components to include in the resulting package (i.e. have a matching or empty "only.flavor" key) + -h, --help help for find-images + --kube-version string Override the default helm template KubeVersion when performing a package chart template + --registry-url string Override the ###ZARF_REGISTRY### value (default "127.0.0.1:31999") + -p, --repo-chart-path string If git repos hold helm charts, often found with gitops tools, specify the chart path, e.g. "/" or "/chart" + --why string Prints the source manifest for the specified image ``` ## Options inherited from parent commands diff --git a/src/cmd/dev.go b/src/cmd/dev.go index a9f20b1251..2020a2be76 100644 --- a/src/cmd/dev.go +++ b/src/cmd/dev.go @@ -21,6 +21,7 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/transform" "github.com/defenseunicorns/zarf/src/pkg/utils" "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" + "github.com/defenseunicorns/zarf/src/types" "github.com/mholt/archiver/v3" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -190,8 +191,11 @@ var devFindImagesCmd = &cobra.Command{ // Ensure uppercase keys from viper v := common.GetViper() + pkgConfig.CreateOpts.SetVariables = helpers.TransformAndMergeMap( v.GetStringMapString(common.VPkgCreateSet), pkgConfig.CreateOpts.SetVariables, strings.ToUpper) + pkgConfig.PkgOpts.SetVariables = helpers.TransformAndMergeMap( + v.GetStringMapString(common.VPkgDeploySet), pkgConfig.PkgOpts.SetVariables, strings.ToUpper) // Configure the packager pkgClient := packager.NewOrDie(&pkgConfig) @@ -265,14 +269,23 @@ func init() { devFindImagesCmd.Flags().StringVarP(&pkgConfig.FindImagesOpts.RepoHelmChartPath, "repo-chart-path", "p", "", lang.CmdDevFlagRepoChartPath) // use the package create config for this and reset it here to avoid overwriting the config.CreateOptions.SetVariables devFindImagesCmd.Flags().StringToStringVar(&pkgConfig.CreateOpts.SetVariables, "set", v.GetStringMapString(common.VPkgCreateSet), lang.CmdDevFlagSet) + + devFindImagesCmd.Flags().MarkDeprecated("set", "this field is replaced by create-set") + devFindImagesCmd.Flags().MarkHidden("set") + devFindImagesCmd.Flags().StringVarP(&pkgConfig.CreateOpts.Flavor, "flavor", "f", v.GetString(common.VPkgCreateFlavor), lang.CmdPackageCreateFlagFlavor) + devFindImagesCmd.Flags().StringToStringVar(&pkgConfig.CreateOpts.SetVariables, "create-set", v.GetStringMapString(common.VPkgCreateSet), lang.CmdDevFlagSet) + devFindImagesCmd.Flags().StringToStringVar(&pkgConfig.PkgOpts.SetVariables, "deploy-set", v.GetStringMapString(common.VPkgDeploySet), lang.CmdPackageDeployFlagSet) // allow for the override of the default helm KubeVersion devFindImagesCmd.Flags().StringVar(&pkgConfig.FindImagesOpts.KubeVersionOverride, "kube-version", "", lang.CmdDevFlagKubeVersion) // check which manifests are using this particular image devFindImagesCmd.Flags().StringVar(&pkgConfig.FindImagesOpts.Why, "why", "", lang.CmdDevFlagFindImagesWhy) + defaultRegistry := fmt.Sprintf("%s:%d", helpers.IPV4Localhost, types.ZarfInClusterContainerRegistryNodePort) + devFindImagesCmd.Flags().StringVar(&pkgConfig.FindImagesOpts.RegistryURL, "registry-url", defaultRegistry, lang.CmdDevFlagFindImagesRegistry) + devLintCmd.Flags().StringToStringVar(&pkgConfig.CreateOpts.SetVariables, "set", v.GetStringMapString(common.VPkgCreateSet), lang.CmdPackageCreateFlagSet) devLintCmd.Flags().StringVarP(&pkgConfig.CreateOpts.Flavor, "flavor", "f", v.GetString(common.VPkgCreateFlavor), lang.CmdPackageCreateFlagFlavor) - devTransformGitLinksCmd.Flags().StringVar(&pkgConfig.InitOpts.GitServer.PushUsername, "git-account", config.ZarfGitPushUser, lang.CmdDevFlagGitAccount) + devTransformGitLinksCmd.Flags().StringVar(&pkgConfig.InitOpts.GitServer.PushUsername, "git-account", types.ZarfGitPushUser, lang.CmdDevFlagGitAccount) } func bindDevDeployFlags(v *viper.Viper) { diff --git a/src/cmd/initialize.go b/src/cmd/initialize.go index eea079af54..93a93c827c 100644 --- a/src/cmd/initialize.go +++ b/src/cmd/initialize.go @@ -23,6 +23,7 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/utils" "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" "github.com/defenseunicorns/zarf/src/pkg/zoci" + "github.com/defenseunicorns/zarf/src/types" "github.com/spf13/cobra" ) @@ -181,8 +182,8 @@ func init() { // Init package variable defaults that are non-zero values // NOTE: these are not in common.setDefaults so that zarf tools update-creds does not erroneously update values back to the default - v.SetDefault(common.VInitGitPushUser, config.ZarfGitPushUser) - v.SetDefault(common.VInitRegistryPushUser, config.ZarfRegistryPushUser) + v.SetDefault(common.VInitGitPushUser, types.ZarfGitPushUser) + v.SetDefault(common.VInitRegistryPushUser, types.ZarfRegistryPushUser) // Init package set variable flags initCmd.Flags().StringToStringVar(&pkgConfig.PkgOpts.SetVariables, "set", v.GetStringMapString(common.VPkgDeploySet), lang.CmdInitFlagSet) diff --git a/src/cmd/package.go b/src/cmd/package.go index 3e29b74b64..460f74014c 100644 --- a/src/cmd/package.go +++ b/src/cmd/package.go @@ -15,6 +15,7 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/packager/sources" "github.com/defenseunicorns/zarf/src/pkg/utils" + "github.com/defenseunicorns/zarf/src/types" "oras.land/oras-go/v2/registry" @@ -395,8 +396,8 @@ func bindMirrorFlags(v *viper.Viper) { // Init package variable defaults that are non-zero values // NOTE: these are not in common.setDefaults so that zarf tools update-creds does not erroneously update values back to the default - v.SetDefault(common.VInitGitPushUser, config.ZarfGitPushUser) - v.SetDefault(common.VInitRegistryPushUser, config.ZarfRegistryPushUser) + v.SetDefault(common.VInitGitPushUser, types.ZarfGitPushUser) + v.SetDefault(common.VInitRegistryPushUser, types.ZarfRegistryPushUser) // Always require confirm flag (no viper) mirrorFlags.BoolVar(&config.CommonOptions.Confirm, "confirm", false, lang.CmdPackageDeployFlagConfirm) diff --git a/src/config/config.go b/src/config/config.go index df4deb9030..f307e5268d 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -26,9 +26,7 @@ const ( GithubProject = "defenseunicorns/zarf" // ZarfMaxChartNameLength limits helm chart name size to account for K8s/helm limits and zarf prefix - ZarfMaxChartNameLength = 40 - ZarfGeneratedPasswordLen = 24 - ZarfGeneratedSecretLen = 48 + ZarfMaxChartNameLength = 40 ZarfAgentHost = "agent-hook.zarf.svc" @@ -53,16 +51,6 @@ const ( ZarfImagePullSecretName = "private-registry" ZarfGitServerSecretName = "private-git-server" - ZarfRegistryPushUser = "zarf-push" - ZarfRegistryPullUser = "zarf-pull" - ZarfInClusterContainerRegistryNodePort = 31999 - - ZarfGitPushUser = "zarf-git-user" - ZarfGitReadUser = "zarf-git-read-user" - - ZarfInClusterGitServiceURL = "http://zarf-gitea-http.zarf.svc.cluster.local:3000" - ZarfInClusterArtifactServiceURL = ZarfInClusterGitServiceURL + "/api/packages/" + ZarfGitPushUser - ZarfLoggingUser = "zarf-admin" ) diff --git a/src/config/lang/english.go b/src/config/lang/english.go index e4ed8c6d64..7bce402f94 100644 --- a/src/config/lang/english.go +++ b/src/config/lang/english.go @@ -379,12 +379,13 @@ $ zarf package pull oci://ghcr.io/defenseunicorns/packages/dos-games:1.0.0 -a sk "NOTE: This file must not already exist. If no filename is provided, the config will be written to the current working directory as zarf-config.toml." CmdDevGenerateConfigErr = "Unable to write the config file %s, make sure the file doesn't already exist" - CmdDevFlagExtractPath = `The path inside of an archive to use to calculate the sha256sum (i.e. for use with "files.extractPath")` - CmdDevFlagSet = "Specify package variables to set on the command line (KEY=value). Note, if using a config file, this will be set by [package.create.set]." - CmdDevFlagRepoChartPath = `If git repos hold helm charts, often found with gitops tools, specify the chart path, e.g. "/" or "/chart"` - CmdDevFlagGitAccount = "User or organization name for the git account that the repos are created under." - CmdDevFlagKubeVersion = "Override the default helm template KubeVersion when performing a package chart template" - CmdDevFlagFindImagesWhy = "Find the location of the image given as an argument and print it to the console." + CmdDevFlagExtractPath = `The path inside of an archive to use to calculate the sha256sum (i.e. for use with "files.extractPath")` + CmdDevFlagSet = "Specify package variables to set on the command line (KEY=value). Note, if using a config file, this will be set by [package.create.set]." + CmdDevFlagRepoChartPath = `If git repos hold helm charts, often found with gitops tools, specify the chart path, e.g. "/" or "/chart"` + CmdDevFlagGitAccount = "User or organization name for the git account that the repos are created under." + CmdDevFlagKubeVersion = "Override the default helm template KubeVersion when performing a package chart template" + CmdDevFlagFindImagesRegistry = "Override the ###ZARF_REGISTRY### value" + CmdDevFlagFindImagesWhy = "Prints the source manifest for the specified image" CmdDevLintShort = "Lints the given package for valid schema and recommended practices" CmdDevLintLong = "Verifies the package schema, checks if any variables won't be evaluated, and checks for unpinned images/repos/files" diff --git a/src/extensions/bigbang/bigbang.go b/src/extensions/bigbang/bigbang.go index 60c4267da7..3f2025f787 100644 --- a/src/extensions/bigbang/bigbang.go +++ b/src/extensions/bigbang/bigbang.go @@ -94,6 +94,7 @@ func Run(YOLO bool, tmpPaths *layout.ComponentPaths, c types.ZarfComponent) (typ }, path.Join(tmpPaths.Temp, bb), path.Join(tmpPaths.Temp, bb, "values"), + helm.WithPackageConfig(&types.PackagerConfig{}), ) // Download the chart from Git and save it to a temporary directory. diff --git a/src/internal/agent/hooks/argocd-repository.go b/src/internal/agent/hooks/argocd-repository.go index 00368863a3..4e4c0c5ef3 100644 --- a/src/internal/agent/hooks/argocd-repository.go +++ b/src/internal/agent/hooks/argocd-repository.go @@ -9,7 +9,6 @@ import ( "encoding/json" "fmt" - "github.com/defenseunicorns/zarf/src/config" "github.com/defenseunicorns/zarf/src/config/lang" "github.com/defenseunicorns/zarf/src/internal/agent/operations" "github.com/defenseunicorns/zarf/src/internal/agent/state" @@ -102,7 +101,7 @@ func mutateRepository(r *v1.AdmissionRequest) (result *operations.Result, err er func populateArgoRepositoryPatchOperations(repoURL string, zarfGitPullPassword string) []operations.PatchOperation { var patches []operations.PatchOperation patches = append(patches, operations.ReplacePatchOperation("/data/url", base64.StdEncoding.EncodeToString([]byte(repoURL)))) - patches = append(patches, operations.ReplacePatchOperation("/data/username", base64.StdEncoding.EncodeToString([]byte(config.ZarfGitReadUser)))) + patches = append(patches, operations.ReplacePatchOperation("/data/username", base64.StdEncoding.EncodeToString([]byte(types.ZarfGitReadUser)))) patches = append(patches, operations.ReplacePatchOperation("/data/password", base64.StdEncoding.EncodeToString([]byte(zarfGitPullPassword)))) return patches diff --git a/src/internal/packager/helm/chart.go b/src/internal/packager/helm/chart.go index a52c51967f..d8ffd3414b 100644 --- a/src/internal/packager/helm/chart.go +++ b/src/internal/packager/helm/chart.go @@ -139,12 +139,12 @@ func (h *Helm) InstallOrUpgradeChart() (types.ConnectStrings, string, error) { } // TemplateChart generates a helm template from a given chart. -func (h *Helm) TemplateChart() (string, chartutil.Values, error) { +func (h *Helm) TemplateChart() (manifest string, chartValues chartutil.Values, err error) { message.Debugf("helm.TemplateChart()") spinner := message.NewProgressSpinner("Templating helm chart %s", h.chart.Name) defer spinner.Stop() - err := h.createActionConfig(h.chart.Namespace, spinner) + err = h.createActionConfig(h.chart.Namespace, spinner) // Setup K8s connection. if err != nil { @@ -183,13 +183,18 @@ func (h *Helm) TemplateChart() (string, chartutil.Values, error) { return "", nil, fmt.Errorf("unable to load chart data: %w", err) } + client.PostRenderer, err = h.newRenderer() + if err != nil { + return "", nil, fmt.Errorf("unable to create helm renderer: %w", err) + } + // Perform the loadedChart installation. templatedChart, err := client.Run(loadedChart, chartValues) if err != nil { return "", nil, fmt.Errorf("error generating helm chart template: %w", err) } - manifest := templatedChart.Manifest + manifest = templatedChart.Manifest for _, hook := range templatedChart.Hooks { manifest += fmt.Sprintf("\n---\n%s", hook.Manifest) @@ -243,7 +248,7 @@ func (h *Helm) UpdateReleaseValues(updatedValues map[string]interface{}) error { // Namespace must be specified. client.Namespace = h.chart.Namespace - // Post-processing our manifests for reasons.... + // Post-processing our manifests to apply vars and run zarf helm logic in cluster client.PostRenderer = postRender // Set reuse values to only override the values we are explicitly given @@ -285,7 +290,7 @@ func (h *Helm) installChart(postRender *renderer) (*release.Release, error) { // Namespace must be specified. client.Namespace = h.chart.Namespace - // Post-processing our manifests for reasons.... + // Post-processing our manifests to apply vars and run zarf helm logic in cluster client.PostRenderer = postRender loadedChart, chartValues, err := h.loadChartData() @@ -298,10 +303,6 @@ func (h *Helm) installChart(postRender *renderer) (*release.Release, error) { } func (h *Helm) upgradeChart(lastRelease *release.Release, postRender *renderer) (*release.Release, error) { - // Print the postRender object piece by piece to not print the htpasswd - message.Debugf("helm.upgradeChart(%#v, %#v, %#v, %#v, %s)", postRender.actionConfig, postRender.connectStrings, - postRender.namespaces, postRender.Helm, fmt.Sprintf("values:template.Values{ registry: \"%s\" }", postRender.values.GetRegistry())) - // Migrate any deprecated APIs (if applicable) err := h.migrateDeprecatedAPIs(lastRelease) if err != nil { @@ -322,7 +323,7 @@ func (h *Helm) upgradeChart(lastRelease *release.Release, postRender *renderer) // Namespace must be specified. client.Namespace = h.chart.Namespace - // Post-processing our manifests for reasons.... + // Post-processing our manifests to apply vars and run zarf helm logic in cluster client.PostRenderer = postRender loadedChart, chartValues, err := h.loadChartData() diff --git a/src/internal/packager/helm/common.go b/src/internal/packager/helm/common.go index 9b2dd729a2..e06fe3fd3b 100644 --- a/src/internal/packager/helm/common.go +++ b/src/internal/packager/helm/common.go @@ -148,7 +148,19 @@ func WithKubeVersion(kubeVersion string) Modifier { } } +// WithPackageConfig sets the packager config for the chart +func WithPackageConfig(cfg *types.PackagerConfig) Modifier { + return func(h *Helm) { + h.cfg = cfg + } +} + // StandardName generates a predictable full path for a helm chart for Zarf. func StandardName(destination string, chart types.ZarfChart) string { return filepath.Join(destination, chart.Name+"-"+chart.Version) } + +// StandardValuesName generates a predictable full path for the values file for a helm chart for zarf +func StandardValuesName(destination string, chart types.ZarfChart, idx int) string { + return fmt.Sprintf("%s-%d", StandardName(destination, chart), idx) +} diff --git a/src/internal/packager/helm/post-render.go b/src/internal/packager/helm/post-render.go index 6774582dcd..7e9561ee3b 100644 --- a/src/internal/packager/helm/post-render.go +++ b/src/internal/packager/helm/post-render.go @@ -17,7 +17,6 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/utils" "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" "github.com/defenseunicorns/zarf/src/types" - "helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/releaseutil" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/yaml" @@ -28,7 +27,6 @@ import ( type renderer struct { *Helm - actionConfig *action.Configuration connectStrings types.ConnectStrings namespaces map[string]*corev1.Namespace values template.Values @@ -42,15 +40,21 @@ func (h *Helm) newRenderer() (*renderer, error) { return nil, err } + // TODO (@austinabro321) this should be cleaned up after https://github.com/defenseunicorns/zarf/pull/2276 gets merged + if h.cfg.State == nil { + valueTemplate.SetState(&types.ZarfState{}) + } + + namespaces := make(map[string]*corev1.Namespace) + if h.cluster != nil { + namespaces[h.chart.Namespace] = h.cluster.NewZarfManagedNamespace(h.chart.Namespace) + } + return &renderer{ Helm: h, connectStrings: make(types.ConnectStrings), - namespaces: map[string]*corev1.Namespace{ - // Add the passed-in namespace to the list - h.chart.Namespace: h.cluster.NewZarfManagedNamespace(h.chart.Namespace), - }, - values: *valueTemplate, - actionConfig: h.actionConfig, + namespaces: namespaces, + values: *valueTemplate, }, nil } @@ -90,12 +94,88 @@ func (r *renderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) { finalManifestsOutput := bytes.NewBuffer(nil) // Otherwise, loop over the resources, - for _, resource := range resources { + if r.cluster != nil { + if err := r.editHelmResources(resources, finalManifestsOutput); err != nil { + return nil, err + } + + if err := r.adoptAndUpdateNamespaces(); err != nil { + return nil, err + } + } else { + for _, resource := range resources { + fmt.Fprintf(finalManifestsOutput, "---\n# Source: %s\n%s\n", resource.Name, resource.Content) + } + } + + // Send the bytes back to helm + return finalManifestsOutput, nil +} + +func (r *renderer) adoptAndUpdateNamespaces() error { + c := r.cluster + existingNamespaces, _ := c.GetNamespaces() + for name, namespace := range r.namespaces { + + // Check to see if this namespace already exists + var existingNamespace bool + for _, serverNamespace := range existingNamespaces.Items { + if serverNamespace.Name == name { + existingNamespace = true + } + } + + if !existingNamespace { + // This is a new namespace, add it + if _, err := c.CreateNamespace(namespace); err != nil { + return fmt.Errorf("unable to create the missing namespace %s", name) + } + } else if r.cfg.DeployOpts.AdoptExistingResources { + if r.cluster.IsInitialNamespace(name) { + // If this is a K8s initial namespace, refuse to adopt it + message.Warnf("Refusing to adopt the initial namespace: %s", name) + } else { + // This is an existing namespace to adopt + if _, err := c.UpdateNamespace(namespace); err != nil { + return fmt.Errorf("unable to adopt the existing namespace %s", name) + } + } + } + + // If the package is marked as YOLO and the state is empty, skip the secret creation for this namespace + if r.cfg.Pkg.Metadata.YOLO && r.cfg.State.Distro == "YOLO" { + continue + } + + // Create the secret + validRegistrySecret := c.GenerateRegistryPullCreds(name, config.ZarfImagePullSecretName, r.cfg.State.RegistryInfo) + + // Try to get a valid existing secret + currentRegistrySecret, _ := c.GetSecret(name, config.ZarfImagePullSecretName) + if currentRegistrySecret.Name != config.ZarfImagePullSecretName || !reflect.DeepEqual(currentRegistrySecret.Data, validRegistrySecret.Data) { + // Create or update the zarf registry secret + if _, err := c.CreateOrUpdateSecret(validRegistrySecret); err != nil { + message.WarnErrf(err, "Problem creating registry secret for the %s namespace", name) + } + + // Generate the git server secret + gitServerSecret := c.GenerateGitPullCreds(name, config.ZarfGitServerSecretName, r.cfg.State.GitServer) + // Create or update the zarf git server secret + if _, err := c.CreateOrUpdateSecret(gitServerSecret); err != nil { + message.WarnErrf(err, "Problem creating git server secret for the %s namespace", name) + } + } + } + return nil +} + +func (r *renderer) editHelmResources(resources []releaseutil.Manifest, finalManifestsOutput *bytes.Buffer) error { + for _, resource := range resources { // parse to unstructured to have access to more data than just the name rawData := &unstructured.Unstructured{} if err := yaml.Unmarshal([]byte(resource.Content), rawData); err != nil { - return nil, fmt.Errorf("failed to unmarshal manifest: %#v", err) + return fmt.Errorf("failed to unmarshal manifest: %#v", err) } switch rawData.GetKind() { @@ -161,67 +241,8 @@ func (r *renderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) { message.Debugf("Unable to adopt resource %s: %s", rawData.GetName(), err.Error()) } } - // Finally place this back onto the output buffer fmt.Fprintf(finalManifestsOutput, "---\n# Source: %s\n%s\n", resource.Name, resource.Content) } - - c := r.cluster - existingNamespaces, _ := c.GetNamespaces() - - for name, namespace := range r.namespaces { - - // Check to see if this namespace already exists - var existingNamespace bool - for _, serverNamespace := range existingNamespaces.Items { - if serverNamespace.Name == name { - existingNamespace = true - } - } - - if !existingNamespace { - // This is a new namespace, add it - if _, err := c.CreateNamespace(namespace); err != nil { - return nil, fmt.Errorf("unable to create the missing namespace %s", name) - } - } else if r.cfg.DeployOpts.AdoptExistingResources { - if r.cluster.IsInitialNamespace(name) { - // If this is a K8s initial namespace, refuse to adopt it - message.Warnf("Refusing to adopt the initial namespace: %s", name) - } else { - // This is an existing namespace to adopt - if _, err := c.UpdateNamespace(namespace); err != nil { - return nil, fmt.Errorf("unable to adopt the existing namespace %s", name) - } - } - } - - // If the package is marked as YOLO and the state is empty, skip the secret creation for this namespace - if r.cfg.Pkg.Metadata.YOLO && r.cfg.State.Distro == "YOLO" { - continue - } - - // Create the secret - validRegistrySecret := c.GenerateRegistryPullCreds(name, config.ZarfImagePullSecretName, r.cfg.State.RegistryInfo) - - // Try to get a valid existing secret - currentRegistrySecret, _ := c.GetSecret(name, config.ZarfImagePullSecretName) - if currentRegistrySecret.Name != config.ZarfImagePullSecretName || !reflect.DeepEqual(currentRegistrySecret.Data, validRegistrySecret.Data) { - // Create or update the zarf registry secret - if _, err := c.CreateOrUpdateSecret(validRegistrySecret); err != nil { - message.WarnErrf(err, "Problem creating registry secret for the %s namespace", name) - } - - // Generate the git server secret - gitServerSecret := c.GenerateGitPullCreds(name, config.ZarfGitServerSecretName, r.cfg.State.GitServer) - - // Create or update the zarf git server secret - if _, err := c.CreateOrUpdateSecret(gitServerSecret); err != nil { - message.WarnErrf(err, "Problem creating git server secret for the %s namespace", name) - } - } - } - - // Send the bytes back to helm - return finalManifestsOutput, nil + return nil } diff --git a/src/internal/packager/helm/repo.go b/src/internal/packager/helm/repo.go index ce57641c91..4df052dbd8 100644 --- a/src/internal/packager/helm/repo.go +++ b/src/internal/packager/helm/repo.go @@ -262,7 +262,7 @@ func (h *Helm) finalizeChartPackage(saved, cosignKeyPath string) error { func (h *Helm) packageValues(cosignKeyPath string) error { for valuesIdx, path := range h.chart.ValuesFiles { - dst := fmt.Sprintf("%s-%d", StandardName(h.valuesPath, h.chart), valuesIdx) + dst := StandardValuesName(h.valuesPath, h.chart, valuesIdx) if helpers.IsURL(path) { if err := utils.DownloadToFile(path, dst, cosignKeyPath); err != nil { diff --git a/src/internal/packager/helm/utils.go b/src/internal/packager/helm/utils.go index 8e1718d725..3a6b789330 100644 --- a/src/internal/packager/helm/utils.go +++ b/src/internal/packager/helm/utils.go @@ -6,7 +6,6 @@ package helm import ( "fmt" - "strconv" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" @@ -43,7 +42,7 @@ func (h *Helm) parseChartValues() (chartutil.Values, error) { valueOpts := &values.Options{} for idx := range h.chart.ValuesFiles { - path := StandardName(h.valuesPath, h.chart) + "-" + strconv.Itoa(idx) + path := StandardValuesName(h.valuesPath, h.chart, idx) valueOpts.ValueFiles = append(valueOpts.ValueFiles, path) } diff --git a/src/internal/packager/template/template.go b/src/internal/packager/template/template.go index 7239947e8b..75882e6bdf 100644 --- a/src/internal/packager/template/template.go +++ b/src/internal/packager/template/template.go @@ -20,7 +20,6 @@ import ( // Values contains the values to be used in the template. type Values struct { config *types.PackagerConfig - registry string htpasswd string } @@ -56,8 +55,6 @@ func Generate(cfg *types.PackagerConfig) (*Values, error) { generated.htpasswd = fmt.Sprintf("%s\\n%s", pushUser, pullUser) } - generated.registry = regInfo.Address - return &generated, nil } @@ -66,9 +63,9 @@ func (values *Values) Ready() bool { return values.config.State != nil } -// GetRegistry returns the registry address. -func (values *Values) GetRegistry() string { - return values.registry +// SetState sets the state +func (values *Values) SetState(state *types.ZarfState) { + values.config.State = state } // GetVariables returns the variables to be used in the template. @@ -89,7 +86,7 @@ func (values *Values) GetVariables(component types.ZarfComponent) (templateMap m "STORAGE_CLASS": values.config.State.StorageClass, // Registry info - "REGISTRY": values.registry, + "REGISTRY": regInfo.Address, "NODEPORT": fmt.Sprintf("%d", regInfo.NodePort), "REGISTRY_AUTH_PUSH": regInfo.PushPassword, "REGISTRY_AUTH_PULL": regInfo.PullPassword, diff --git a/src/pkg/cluster/state.go b/src/pkg/cluster/state.go index 3b96c60b08..d9f7aee483 100644 --- a/src/pkg/cluster/state.go +++ b/src/pkg/cluster/state.go @@ -72,7 +72,7 @@ func (c *Cluster) InitZarfState(initOptions types.ZarfInitOptions) error { // Defaults state.Distro = distro - if state.LoggingSecret, err = helpers.RandomString(config.ZarfGeneratedPasswordLen); err != nil { + if state.LoggingSecret, err = helpers.RandomString(types.ZarfGeneratedPasswordLen); err != nil { return fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) } @@ -113,13 +113,18 @@ func (c *Cluster) InitZarfState(initOptions types.ZarfInitOptions) error { return fmt.Errorf("unable get default Zarf service account: %w", err) } - if state.GitServer, err = c.fillInEmptyGitServerValues(initOptions.GitServer); err != nil { + err = initOptions.GitServer.FillInEmptyValues() + if err != nil { return err } - if state.RegistryInfo, err = c.fillInEmptyContainerRegistryValues(initOptions.RegistryInfo); err != nil { + state.GitServer = initOptions.GitServer + err = initOptions.RegistryInfo.FillInEmptyValues() + if err != nil { return err } - state.ArtifactServer = c.fillInEmptyArtifactServerValues(initOptions.ArtifactServer) + state.RegistryInfo = initOptions.RegistryInfo + initOptions.ArtifactServer.FillInEmptyValues() + state.ArtifactServer = initOptions.ArtifactServer } else { if helpers.IsNotZeroAndNotEqual(initOptions.GitServer, state.GitServer) { message.Warn("Detected a change in Git Server init options on a re-init. Ignoring... To update run:") @@ -266,12 +271,12 @@ func (c *Cluster) MergeZarfState(oldState *types.ZarfState, initOptions types.Za // Set the new passwords if they should be autogenerated if newState.RegistryInfo.PushPassword == oldState.RegistryInfo.PushPassword && oldState.RegistryInfo.InternalRegistry { - if newState.RegistryInfo.PushPassword, err = helpers.RandomString(config.ZarfGeneratedPasswordLen); err != nil { + if newState.RegistryInfo.PushPassword, err = helpers.RandomString(types.ZarfGeneratedPasswordLen); err != nil { return nil, fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) } } if newState.RegistryInfo.PullPassword == oldState.RegistryInfo.PullPassword && oldState.RegistryInfo.InternalRegistry { - if newState.RegistryInfo.PullPassword, err = helpers.RandomString(config.ZarfGeneratedPasswordLen); err != nil { + if newState.RegistryInfo.PullPassword, err = helpers.RandomString(types.ZarfGeneratedPasswordLen); err != nil { return nil, fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) } } @@ -280,7 +285,7 @@ func (c *Cluster) MergeZarfState(oldState *types.ZarfState, initOptions types.Za newState.GitServer = helpers.MergeNonZero(newState.GitServer, initOptions.GitServer) // Set the state of the internal git server if it has changed - if newState.GitServer.Address == config.ZarfInClusterGitServiceURL { + if newState.GitServer.Address == types.ZarfInClusterGitServiceURL { newState.GitServer.InternalServer = true } else { newState.GitServer.InternalServer = false @@ -288,12 +293,12 @@ func (c *Cluster) MergeZarfState(oldState *types.ZarfState, initOptions types.Za // Set the new passwords if they should be autogenerated if newState.GitServer.PushPassword == oldState.GitServer.PushPassword && oldState.GitServer.InternalServer { - if newState.GitServer.PushPassword, err = helpers.RandomString(config.ZarfGeneratedPasswordLen); err != nil { + if newState.GitServer.PushPassword, err = helpers.RandomString(types.ZarfGeneratedPasswordLen); err != nil { return nil, fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) } } if newState.GitServer.PullPassword == oldState.GitServer.PullPassword && oldState.GitServer.InternalServer { - if newState.GitServer.PullPassword, err = helpers.RandomString(config.ZarfGeneratedPasswordLen); err != nil { + if newState.GitServer.PullPassword, err = helpers.RandomString(types.ZarfGeneratedPasswordLen); err != nil { return nil, fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) } } @@ -302,7 +307,7 @@ func (c *Cluster) MergeZarfState(oldState *types.ZarfState, initOptions types.Za newState.ArtifactServer = helpers.MergeNonZero(newState.ArtifactServer, initOptions.ArtifactServer) // Set the state of the internal artifact server if it has changed - if newState.ArtifactServer.Address == config.ZarfInClusterArtifactServiceURL { + if newState.ArtifactServer.Address == types.ZarfInClusterArtifactServiceURL { newState.ArtifactServer.InternalServer = true } else { newState.ArtifactServer.InternalServer = false @@ -319,105 +324,3 @@ func (c *Cluster) MergeZarfState(oldState *types.ZarfState, initOptions types.Za return &newState, nil } - -func (c *Cluster) fillInEmptyContainerRegistryValues(containerRegistry types.RegistryInfo) (types.RegistryInfo, error) { - var err error - // Set default NodePort if none was provided - if containerRegistry.NodePort == 0 { - containerRegistry.NodePort = config.ZarfInClusterContainerRegistryNodePort - } - - // Set default url if an external registry was not provided - if containerRegistry.Address == "" { - containerRegistry.InternalRegistry = true - containerRegistry.Address = fmt.Sprintf("%s:%d", helpers.IPV4Localhost, containerRegistry.NodePort) - } - - // Generate a push-user password if not provided by init flag - if containerRegistry.PushPassword == "" { - if containerRegistry.PushPassword, err = helpers.RandomString(config.ZarfGeneratedPasswordLen); err != nil { - return containerRegistry, fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) - } - } - - // Set pull-username if not provided by init flag - if containerRegistry.PullUsername == "" { - if containerRegistry.InternalRegistry { - containerRegistry.PullUsername = config.ZarfRegistryPullUser - } else { - // If this is an external registry and a pull-user wasn't provided, use the same credentials as the push user - containerRegistry.PullUsername = containerRegistry.PushUsername - } - } - if containerRegistry.PullPassword == "" { - if containerRegistry.InternalRegistry { - if containerRegistry.PullPassword, err = helpers.RandomString(config.ZarfGeneratedPasswordLen); err != nil { - return containerRegistry, fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) - } - } else { - // If this is an external registry and a pull-user wasn't provided, use the same credentials as the push user - containerRegistry.PullPassword = containerRegistry.PushPassword - } - } - - if containerRegistry.Secret == "" { - if containerRegistry.Secret, err = helpers.RandomString(config.ZarfGeneratedPasswordLen); err != nil { - return containerRegistry, fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) - } - } - - return containerRegistry, nil -} - -// Fill in empty GitServerInfo values with the defaults. -func (c *Cluster) fillInEmptyGitServerValues(gitServer types.GitServerInfo) (types.GitServerInfo, error) { - var err error - // Set default svc url if an external repository was not provided - if gitServer.Address == "" { - gitServer.Address = config.ZarfInClusterGitServiceURL - gitServer.InternalServer = true - } - - // Generate a push-user password if not provided by init flag - if gitServer.PushPassword == "" { - if gitServer.PushPassword, err = helpers.RandomString(config.ZarfGeneratedPasswordLen); err != nil { - return gitServer, fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) - } - } - - // Set read-user information if using an internal repository, otherwise copy from the push-user - if gitServer.PullUsername == "" { - if gitServer.InternalServer { - gitServer.PullUsername = config.ZarfGitReadUser - } else { - gitServer.PullUsername = gitServer.PushUsername - } - } - if gitServer.PullPassword == "" { - if gitServer.InternalServer { - if gitServer.PullPassword, err = helpers.RandomString(config.ZarfGeneratedPasswordLen); err != nil { - return gitServer, fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) - } - } else { - gitServer.PullPassword = gitServer.PushPassword - } - } - - return gitServer, nil -} - -// Fill in empty ArtifactServerInfo values with the defaults. -func (c *Cluster) fillInEmptyArtifactServerValues(artifactServer types.ArtifactServerInfo) types.ArtifactServerInfo { - // Set default svc url if an external registry was not provided - if artifactServer.Address == "" { - artifactServer.Address = config.ZarfInClusterArtifactServiceURL - artifactServer.InternalServer = true - } - - // Set the push username to the git push user if not specified - if artifactServer.PushUsername == "" { - artifactServer.PushUsername = config.ZarfGitPushUser - } - - return artifactServer -} diff --git a/src/pkg/packager/create_stages.go b/src/pkg/packager/create_stages.go index 5ea66cc3fb..88044a4096 100644 --- a/src/pkg/packager/create_stages.go +++ b/src/pkg/packager/create_stages.go @@ -423,7 +423,7 @@ func (p *Packager) addComponent(index int, component types.ZarfComponent) error continue } - rel := fmt.Sprintf("%s-%d", helm.StandardName(layout.ValuesDir, chart), valuesIdx) + rel := helm.StandardValuesName(layout.ValuesDir, chart, valuesIdx) p.cfg.Pkg.Components[index].Charts[chartIdx].ValuesFiles[valuesIdx] = rel if err := utils.CreatePathAndCopy(path, filepath.Join(componentPaths.Base, rel)); err != nil { diff --git a/src/pkg/packager/deploy.go b/src/pkg/packager/deploy.go index 585b50de14..c5047074a4 100644 --- a/src/pkg/packager/deploy.go +++ b/src/pkg/packager/deploy.go @@ -63,7 +63,7 @@ func (p *Packager) Deploy() (err error) { // Set variables and prompt if --confirm is not set if err := p.setVariableMapInConfig(); err != nil { - return fmt.Errorf("unable to set the active variables: %w", err) + return err } p.hpaModified = false @@ -526,7 +526,7 @@ func (p *Packager) installChartAndManifests(componentPaths *layout.ComponentPath // zarf magic for the value file for idx := range chart.ValuesFiles { - chartValueName := fmt.Sprintf("%s-%d", helm.StandardName(componentPaths.Values, chart), idx) + chartValueName := helm.StandardValuesName(componentPaths.Values, chart, idx) if err := p.valueTemplate.Apply(component, chartValueName, false); err != nil { return installedCharts, err } diff --git a/src/pkg/packager/dev.go b/src/pkg/packager/dev.go index b4e1744d46..675ee540ee 100644 --- a/src/pkg/packager/dev.go +++ b/src/pkg/packager/dev.go @@ -62,7 +62,7 @@ func (p *Packager) DevDeploy() error { // Set variables and prompt if --confirm is not set if err := p.setVariableMapInConfig(); err != nil { - return fmt.Errorf("unable to set the active variables: %w", err) + return err } p.connectStrings = make(types.ConnectStrings) diff --git a/src/pkg/packager/prepare.go b/src/pkg/packager/prepare.go index 7a1df0b982..b2b77fd5b7 100644 --- a/src/pkg/packager/prepare.go +++ b/src/pkg/packager/prepare.go @@ -6,17 +6,19 @@ package packager import ( "fmt" - "github.com/goccy/go-yaml" "os" "path/filepath" "regexp" "sort" "strings" + "github.com/goccy/go-yaml" + "github.com/defenseunicorns/zarf/src/config" "github.com/defenseunicorns/zarf/src/config/lang" "github.com/defenseunicorns/zarf/src/internal/packager/helm" "github.com/defenseunicorns/zarf/src/internal/packager/kustomize" + "github.com/defenseunicorns/zarf/src/internal/packager/template" "github.com/defenseunicorns/zarf/src/pkg/layout" "github.com/defenseunicorns/zarf/src/pkg/message" "github.com/defenseunicorns/zarf/src/pkg/utils" @@ -56,7 +58,7 @@ func (p *Packager) FindImages() (imgMap map[string][]string, err error) { message.Note(fmt.Sprintf("Using build directory %s", p.cfg.CreateOpts.BaseDir)) if err = p.readZarfYAML(layout.ZarfYAML); err != nil { - return nil, fmt.Errorf("unable to read the zarf.yaml file: %s", err.Error()) + return nil, fmt.Errorf("unable to read the zarf.yaml file: %w", err) } if err := p.composeComponents(); err != nil { @@ -69,7 +71,7 @@ func (p *Packager) FindImages() (imgMap map[string][]string, err error) { // After components are composed, template the active package if err := p.fillActiveTemplate(); err != nil { - return nil, fmt.Errorf("unable to fill values in template: %s", err.Error()) + return nil, fmt.Errorf("unable to fill values in template: %w", err) } for _, component := range p.cfg.Pkg.Components { @@ -83,6 +85,10 @@ func (p *Packager) FindImages() (imgMap map[string][]string, err error) { componentDefinition := "\ncomponents:\n" + if err := p.setVariableMapInConfig(); err != nil { + return nil, err + } + for _, component := range p.cfg.Pkg.Components { if len(component.Charts)+len(component.Manifests)+len(component.Repos) < 1 { @@ -123,36 +129,64 @@ func (p *Packager) FindImages() (imgMap map[string][]string, err error) { if err != nil { return nil, err } - + values, err := template.Generate(p.cfg) + if err != nil { + return nil, fmt.Errorf("unable to generate template values") + } + // Adding these so the default builtin values exist in case any helm charts rely on them + registryInfo := types.RegistryInfo{Address: p.cfg.FindImagesOpts.RegistryURL} + err = registryInfo.FillInEmptyValues() + if err != nil { + return nil, err + } + gitServer := types.GitServerInfo{} + err = gitServer.FillInEmptyValues() + if err != nil { + return nil, err + } + artifactServer := types.ArtifactServerInfo{} + artifactServer.FillInEmptyValues() + values.SetState(&types.ZarfState{ + RegistryInfo: registryInfo, + GitServer: gitServer, + ArtifactServer: artifactServer}) for _, chart := range component.Charts { + helmCfg := helm.New( chart, componentPaths.Charts, componentPaths.Values, helm.WithKubeVersion(kubeVersionOverride), + helm.WithPackageConfig(p.cfg), ) - err := helmCfg.PackageChart(component.DeprecatedCosignKeyPath) + err = helmCfg.PackageChart(component.DeprecatedCosignKeyPath) if err != nil { - return nil, fmt.Errorf("unable to package the chart %s: %s", chart.URL, err.Error()) + return nil, fmt.Errorf("unable to package the chart %s: %w", chart.Name, err) } - // Generate helm templates for this chart - template, values, err := helmCfg.TemplateChart() + valuesFilePaths, _ := utils.RecursiveFileList(componentPaths.Values, nil, false) + for _, path := range valuesFilePaths { + if err := values.Apply(component, path, false); err != nil { + return nil, err + } + } + // Generate helm templates for this chart + chartTemplate, chartValues, err := helmCfg.TemplateChart() if err != nil { - message.WarnErrf(err, "Problem rendering the helm template for %s: %s", chart.URL, err.Error()) - erroredCharts = append(erroredCharts, chart.URL) + message.WarnErrf(err, "Problem rendering the helm template for %s: %s", chart.Name, err.Error()) + erroredCharts = append(erroredCharts, chart.Name) continue } // Break the template into separate resources - yamls, _ := utils.SplitYAML([]byte(template)) + yamls, _ := utils.SplitYAML([]byte(chartTemplate)) resources = append(resources, yamls...) chartTarball := helm.StandardName(componentPaths.Charts, chart) + ".tgz" - annotatedImages, err := helm.FindAnnotatedImagesForChart(chartTarball, values) + annotatedImages, err := helm.FindAnnotatedImagesForChart(chartTarball, chartValues) if err != nil { message.WarnErrf(err, "Problem looking for image annotations for %s: %s", chart.URL, err.Error()) erroredCharts = append(erroredCharts, chart.URL) @@ -178,7 +212,7 @@ func (p *Packager) FindImages() (imgMap map[string][]string, err error) { kname := fmt.Sprintf("kustomization-%s-%d.yaml", manifest.Name, idx) destination := filepath.Join(componentPaths.Manifests, kname) if err := kustomize.Build(k, destination, manifest.KustomizeAllowAnyDirectory); err != nil { - return nil, fmt.Errorf("unable to build the kustomization for %s: %s", k, err.Error()) + return nil, fmt.Errorf("unable to build the kustomization for %s: %w", k, err) } manifest.Files = append(manifest.Files, destination) } @@ -191,8 +225,18 @@ func (p *Packager) FindImages() (imgMap map[string][]string, err error) { return nil, fmt.Errorf(lang.ErrDownloading, f, err.Error()) } f = destination + } else { + filename := filepath.Base(f) + newDestination := filepath.Join(componentPaths.Manifests, filename) + if err := utils.CreatePathAndCopy(f, newDestination); err != nil { + return nil, fmt.Errorf("unable to copy manifest %s: %w", f, err) + } + f = newDestination } + if err := values.Apply(component, f, true); err != nil { + return nil, err + } // Read the contents of each file contents, err := os.ReadFile(f) if err != nil { diff --git a/src/pkg/packager/variables.go b/src/pkg/packager/variables.go index fb3e20f6d3..53f4e05df3 100644 --- a/src/pkg/packager/variables.go +++ b/src/pkg/packager/variables.go @@ -126,7 +126,7 @@ func (p *Packager) setVariableMapInConfig() error { val, err := interactive.PromptVariable(variable) if err != nil { - return err + return fmt.Errorf("unable to get value from prompt: %w", err) } p.setVariableInConfig(variable.Name, val, variable.Sensitive, variable.AutoIndent, variable.Type) diff --git a/src/pkg/utils/helpers/random.go b/src/pkg/utils/helpers/random.go index 63e7bfa89c..d06700ad7f 100644 --- a/src/pkg/utils/helpers/random.go +++ b/src/pkg/utils/helpers/random.go @@ -17,7 +17,6 @@ func RandomString(length int) (string, error) { bytes := make([]byte, length) if _, err := rand.Read(bytes); err != nil { - //message.Fatal(err, "unable to generate a random secret") return "", err } diff --git a/src/test/common.go b/src/test/common.go index 99fe96614c..eab1f58fde 100644 --- a/src/test/common.go +++ b/src/test/common.go @@ -9,7 +9,6 @@ import ( "context" "fmt" "os" - "path/filepath" "regexp" "runtime" "strings" @@ -72,15 +71,19 @@ func (e2e *ZarfE2ETest) Zarf(args ...string) (string, string, error) { defer os.RemoveAll(tmpdir) args = append(args, "--tmpdir", tmpdir) } - if !slices.Contains(args, "--zarf-cache") && !slices.Contains(args, "tools") { - if os.Getenv("CI") == "true" { - // We make the cache dir relative to the working directory to make it work on the Windows Runners - // - they use two drives which filepath.Rel cannot cope with. - relCacheDir, _ := filepath.Abs(".cache-location") - args = append(args, "--zarf-cache", relCacheDir) - defer os.RemoveAll(relCacheDir) + if !slices.Contains(args, "--zarf-cache") && !slices.Contains(args, "tools") && os.Getenv("CI") == "true" { + // We make the cache dir relative to the working directory to make it work on the Windows Runners + // - they use two drives which filepath.Rel cannot cope with. + cwd, err := os.Getwd() + if err != nil { + return "", "", err } - + cacheDir, err := os.MkdirTemp(cwd, "zarf-") + if err != nil { + return "", "", err + } + args = append(args, "--zarf-cache", cacheDir) + defer os.RemoveAll(cacheDir) } return exec.CmdWithContext(context.TODO(), exec.PrintCfg(), e2e.ZarfBinPath, args...) } diff --git a/src/test/e2e/00_use_cli_test.go b/src/test/e2e/00_use_cli_test.go index 6efdd86b2d..df9ece1db3 100644 --- a/src/test/e2e/00_use_cli_test.go +++ b/src/test/e2e/00_use_cli_test.go @@ -70,37 +70,6 @@ func TestUseCLI(t *testing.T) { require.Contains(t, stdOut, yamlVersion, "Zarf version should be the same in all formats") }) - t.Run("zarf prepare find-images", func(t *testing.T) { - t.Parallel() - // Test `zarf prepare find-images` for a remote asset - stdOut, stdErr, err := e2e.Zarf("prepare", "find-images", "examples/helm-charts", "--kube-version=v1.23.0") - require.NoError(t, err, stdOut, stdErr) - require.Contains(t, stdOut, "ghcr.io/stefanprodan/podinfo:6.4.0", "The chart image should be found by Zarf") - // Test `zarf prepare find-images` with a chart that uses helm annotations - stdOut, stdErr, err = e2e.Zarf("prepare", "find-images", "src/test/packages/00-helm-annotations") - require.NoError(t, err, stdOut, stdErr) - require.Contains(t, stdOut, "registry1.dso.mil/ironbank/opensource/istio/pilot:1.17.2", "The pilot image should be found by Zarf") - }) - - t.Run("zarf prepare find-images --kube-version", func(t *testing.T) { - t.Parallel() - controllerImageWithTag := "quay.io/jetstack/cert-manager-controller:v1.11.1" - controlImageWithSignature := "quay.io/jetstack/cert-manager-controller:sha256-4f1782c8316f34aae6b9ab823c3e6b7e6e4d92ec5dac21de6a17c3da44c364f1.sig" - - // Test `zarf prepare find-images` on a chart that has a `kubeVersion` declaration greater than the Helm default (v1.20.0) - // This should pass because we build Zarf specifying the kubeVersion value from the kubernetes client-go library instead - stdOut, stdErr, err := e2e.Zarf("prepare", "find-images", "src/test/packages/00-kube-version-override") - require.NoError(t, err, stdOut, stdErr) - require.Contains(t, stdOut, controllerImageWithTag, "The chart image should be found by Zarf") - require.Contains(t, stdOut, controlImageWithSignature, "The image signature should be found by Zarf") - - // Test `zarf prepare find-images` with `--kube-version` specified and less than than the declared minimum (v1.21.0) - stdOut, stdErr, err = e2e.Zarf("prepare", "find-images", "--kube-version=v1.20.0", "src/test/packages/00-kube-version-override") - require.Error(t, err, stdOut, stdErr) - require.Contains(t, stdErr, "Problem rendering the helm template for https://charts.jetstack.io/", "The kubeVersion declaration should prevent this from templating") - require.Contains(t, stdErr, "following charts had errors: [https://charts.jetstack.io/]", "Zarf should print an ending error message") - }) - t.Run("zarf deploy should fail when given a bad component input", func(t *testing.T) { t.Parallel() // Test for expected failure when given a bad component input @@ -164,7 +133,7 @@ func TestUseCLI(t *testing.T) { require.FileExists(t, "binaries/eksctl_Darwin_arm64") require.FileExists(t, "binaries/eksctl_Linux_x86_64") - e2e.CleanFiles("binaries/eksctl_Darwin_x86_64", "binaries/eksctl_Darwin_arm64", "binaries/eksctl_Linux_x86_64", path) + e2e.CleanFiles("binaries/eksctl_Darwin_x86_64", "binaries/eksctl_Darwin_arm64", "binaries/eksctl_Linux_x86_64", path, "eks.yaml") }) t.Run("zarf package create with tmpdir and cache", func(t *testing.T) { @@ -243,4 +212,5 @@ func TestUseCLI(t *testing.T) { require.FileExists(t, tlsKey) }) + } diff --git a/src/test/e2e/12_lint_test.go b/src/test/e2e/12_lint_test.go index cf132c4068..62b6964e88 100644 --- a/src/test/e2e/12_lint_test.go +++ b/src/test/e2e/12_lint_test.go @@ -28,6 +28,7 @@ func TestLint(t *testing.T) { configPath := filepath.Join(testPackagePath, "zarf-config.toml") os.Setenv("ZARF_CONFIG", configPath) _, stderr, err := e2e.Zarf("dev", "lint", testPackagePath, "-f", "good-flavor") + os.Unsetenv("ZARF_CONFIG") require.Error(t, err, "Require an exit code since there was warnings / errors") strippedStderr := e2e.StripMessageFormatting(stderr) diff --git a/src/test/e2e/13_find_images_test.go b/src/test/e2e/13_find_images_test.go index c37e1967c8..3235d519f1 100644 --- a/src/test/e2e/13_find_images_test.go +++ b/src/test/e2e/13_find_images_test.go @@ -1,8 +1,9 @@ package test import ( - "os" + "fmt" "path/filepath" + "strings" "testing" "github.com/stretchr/testify/require" @@ -11,40 +12,77 @@ import ( func TestFindImages(t *testing.T) { t.Log("E2E: Find Images") - t.Run("zarf test find images success", func(t *testing.T) { - t.Log("E2E: Test Find Images") + t.Run("zarf prepare find-images", func(t *testing.T) { + t.Parallel() + // Test `zarf prepare find-images` for a remote asset + stdOut, stdErr, err := e2e.Zarf("prepare", "find-images", "examples/helm-charts") + require.NoError(t, err, stdOut, stdErr) + require.Contains(t, stdOut, "ghcr.io/stefanprodan/podinfo:6.4.0", "The chart image should be found by Zarf") + // Test `zarf prepare find-images` with a chart that uses helm annotations + stdOut, stdErr, err = e2e.Zarf("prepare", "find-images", "src/test/packages/00-helm-annotations") + require.NoError(t, err, stdOut, stdErr) + require.Contains(t, stdOut, "registry1.dso.mil/ironbank/opensource/istio/pilot:1.17.2", "The pilot image should be found by Zarf") + }) - testPackagePath := filepath.Join("examples", "dos-games") - expectedOutput, err := os.ReadFile("src/test/packages/13-find-images/dos-games-find-images-expected.txt") - require.NoError(t, err) + t.Run("zarf prepare find-images --kube-version", func(t *testing.T) { + t.Parallel() + controllerImageWithTag := "quay.io/jetstack/cert-manager-controller:v1.11.1" + controlImageWithSignature := "quay.io/jetstack/cert-manager-controller:sha256-4f1782c8316f34aae6b9ab823c3e6b7e6e4d92ec5dac21de6a17c3da44c364f1.sig" - stdout, _, err := e2e.Zarf("dev", "find-images", testPackagePath) - require.NoError(t, err) - require.Contains(t, stdout, string(expectedOutput)) + // Test `zarf prepare find-images` on a chart that has a `kubeVersion` declaration greater than the Helm default (v1.20.0) + // This should pass because we build Zarf specifying the kubeVersion value from the kubernetes client-go library instead + stdOut, stdErr, err := e2e.Zarf("prepare", "find-images", "src/test/packages/00-kube-version-override") + require.NoError(t, err, stdOut, stdErr) + require.Contains(t, stdOut, controllerImageWithTag, "The chart image should be found by Zarf") + require.Contains(t, stdOut, controlImageWithSignature, "The image signature should be found by Zarf") + + // Test `zarf prepare find-images` with `--kube-version` specified and less than than the declared minimum (v1.21.0) + stdOut, stdErr, err = e2e.Zarf("prepare", "find-images", "--kube-version=v1.20.0", "src/test/packages/00-kube-version-override") + require.Error(t, err, stdOut, stdErr) + require.Contains(t, stdErr, "Problem rendering the helm template for cert-manager", "The kubeVersion declaration should prevent this from templating") + require.Contains(t, stdErr, "following charts had errors: [cert-manager]", "Zarf should print an ending error message") }) - t.Run("zarf test find images --why w/ helm chart success", func(t *testing.T) { - t.Log("E2E: Test Find Images against a helm chart with why flag") + t.Run("zarf dev find-images with helm or manifest vars", func(t *testing.T) { + t.Parallel() + registry := "coolregistry.gov" + agentTag := "test" - testPackagePath := filepath.Join("examples", "wordpress") - expectedOutput, err := os.ReadFile("src/test/packages/13-find-images/helm-charts-find-images-why-expected.txt") + stdOut, _, err := e2e.Zarf("prepare", "find-images", ".", "--registry-url", registry, "--create-set", fmt.Sprintf("agent_image_tag=%s", agentTag)) require.NoError(t, err) + internalRegistryImage := fmt.Sprintf("%s/%s:%s", registry, "defenseunicorns/zarf/agent", agentTag) + require.Contains(t, stdOut, internalRegistryImage, "registry image should be found with registry url") + require.Contains(t, stdOut, "busybox:latest", "Busybox image should be found as long as helm chart doesn't error") - stdout, _, err := e2e.Zarf("dev", "find-images", testPackagePath, "--why", "docker.io/bitnami/apache-exporter:0.13.3-debian-11-r2") + path := filepath.Join("src", "test", "packages", "00-find-images-with-vars") + stdOut, _, err = e2e.Zarf("prepare", "find-images", path, "--deploy-set", "BUSYBOX_IMAGE=busybox:earliest") require.NoError(t, err) - require.Contains(t, stdout, string(expectedOutput)) + require.Contains(t, stdOut, "nginx:latest", "Manifests aren't interpreting vars") + require.Contains(t, stdOut, "busybox:earliest", "Values files aren't interpreting vars") }) - t.Run("zarf test find images --why w/ manifests success", func(t *testing.T) { - t.Log("E2E: Test Find Images against manifests with why flag") + t.Run("zarf test find images --why w/ helm chart success", func(t *testing.T) { + t.Parallel() + testPackagePath := filepath.Join("examples", "wordpress") + sets := []string{"WORDPRESS_USERNAME=zarf", "WORDPRESS_PASSWORD=fake", "WORDPRESS_EMAIL=hello@defenseunicorns.com", "WORDPRESS_FIRST_NAME=zarf", "WORDPRESS_LAST_NAME=zarf", "WORDPRESS_BLOG_NAME=blog"} + deploysSet := strings.Join(sets, ",") + stdOut, _, err := e2e.Zarf("dev", "find-images", testPackagePath, "--why", "docker.io/bitnami/apache-exporter:0.13.3-debian-11-r2", "--deploy-set", deploysSet) + require.NoError(t, err) + require.Contains(t, stdOut, "component: wordpress") + require.Contains(t, stdOut, "chart: wordpress") + require.Contains(t, stdOut, "image: docker.io/bitnami/wordpress:6.2.0-debian-11-r18") + }) + t.Run("zarf test find images --why w/ manifests success", func(t *testing.T) { + t.Parallel() testPackagePath := filepath.Join("examples", "manifests") - expectedOutput, err := os.ReadFile("src/test/packages/13-find-images/manifests-find-images-why-expected.txt") - require.NoError(t, err) - stdout, _, err := e2e.Zarf("dev", "find-images", testPackagePath, "--why", "httpd:alpine3.18") + stdOut, _, err := e2e.Zarf("dev", "find-images", testPackagePath, "--why", "httpd:alpine3.18") require.NoError(t, err) - require.Contains(t, stdout, string(expectedOutput)) + require.Contains(t, stdOut, "component: httpd-local") + require.Contains(t, stdOut, "manifest: simple-httpd-deployment") + require.Contains(t, stdOut, "image: httpd:alpine3.18") + }) } diff --git a/src/test/e2e/22_git_and_gitops_test.go b/src/test/e2e/22_git_and_gitops_test.go index 3138a742c7..f83bd6ba05 100644 --- a/src/test/e2e/22_git_and_gitops_test.go +++ b/src/test/e2e/22_git_and_gitops_test.go @@ -12,9 +12,9 @@ import ( "path/filepath" "testing" - "github.com/defenseunicorns/zarf/src/config" "github.com/defenseunicorns/zarf/src/internal/packager/git" "github.com/defenseunicorns/zarf/src/pkg/cluster" + "github.com/defenseunicorns/zarf/src/types" "github.com/stretchr/testify/require" ) @@ -75,7 +75,7 @@ func testGitServerReadOnly(t *testing.T, gitURL string) { // Get the repo as the readonly user repoName := "zarf-public-test-2469062884" getRepoRequest, _ := http.NewRequest("GET", fmt.Sprintf("%s/api/v1/repos/%s/%s", gitURL, state.GitServer.PushUsername, repoName), nil) - getRepoResponseBody, _, err := gitCfg.DoHTTPThings(getRepoRequest, config.ZarfGitReadUser, state.GitServer.PullPassword) + getRepoResponseBody, _, err := gitCfg.DoHTTPThings(getRepoRequest, types.ZarfGitReadUser, state.GitServer.PullPassword) require.NoError(t, err) // Make sure the only permissions are pull (read) @@ -98,8 +98,8 @@ func testGitServerTagAndHash(t *testing.T, gitURL string) { // Get the Zarf repo tag repoTag := "v0.0.1" - getRepoTagsRequest, _ := http.NewRequest("GET", fmt.Sprintf("%s/api/v1/repos/%s/%s/tags/%s", gitURL, config.ZarfGitPushUser, repoName, repoTag), nil) - getRepoTagsResponseBody, _, err := gitCfg.DoHTTPThings(getRepoTagsRequest, config.ZarfGitReadUser, state.GitServer.PullPassword) + getRepoTagsRequest, _ := http.NewRequest("GET", fmt.Sprintf("%s/api/v1/repos/%s/%s/tags/%s", gitURL, types.ZarfGitPushUser, repoName, repoTag), nil) + getRepoTagsResponseBody, _, err := gitCfg.DoHTTPThings(getRepoTagsRequest, types.ZarfGitReadUser, state.GitServer.PullPassword) require.NoError(t, err) // Make sure the pushed tag exists @@ -110,8 +110,8 @@ func testGitServerTagAndHash(t *testing.T, gitURL string) { // Get the Zarf repo commit repoHash := "01a23218923f24194133b5eb11268cf8d73ff1bb" - getRepoCommitsRequest, _ := http.NewRequest("GET", fmt.Sprintf("%s/api/v1/repos/%s/%s/git/commits/%s", gitURL, config.ZarfGitPushUser, repoName, repoHash), nil) - getRepoCommitsResponseBody, _, err := gitCfg.DoHTTPThings(getRepoCommitsRequest, config.ZarfGitReadUser, state.GitServer.PullPassword) + getRepoCommitsRequest, _ := http.NewRequest("GET", fmt.Sprintf("%s/api/v1/repos/%s/%s/git/commits/%s", gitURL, types.ZarfGitPushUser, repoName, repoHash), nil) + getRepoCommitsResponseBody, _, err := gitCfg.DoHTTPThings(getRepoCommitsRequest, types.ZarfGitReadUser, state.GitServer.PullPassword) require.NoError(t, err) require.Contains(t, string(getRepoCommitsResponseBody), repoHash) } @@ -125,7 +125,7 @@ func waitFluxPodInfoDeployment(t *testing.T) { // Tests the URL mutation for GitRepository CRD for Flux. stdOut, stdErr, err = e2e.Kubectl("get", "gitrepositories", "podinfo", "-n", "flux-system", "-o", "jsonpath={.spec.url}") require.NoError(t, err, stdOut, stdErr) - expectedMutatedRepoURL := fmt.Sprintf("%s/%s/podinfo-1646971829.git", config.ZarfInClusterGitServiceURL, config.ZarfGitPushUser) + expectedMutatedRepoURL := fmt.Sprintf("%s/%s/podinfo-1646971829.git", types.ZarfInClusterGitServiceURL, types.ZarfGitPushUser) require.Equal(t, expectedMutatedRepoURL, stdOut) // Remove the flux example when deployment completes @@ -143,7 +143,7 @@ func waitArgoDeployment(t *testing.T) { stdOut, stdErr, err := e2e.Zarf("package", "deploy", path, "--components=argocd-apps", "--confirm") require.NoError(t, err, stdOut, stdErr) - expectedMutatedRepoURL := fmt.Sprintf("%s/%s/podinfo-1646971829.git", config.ZarfInClusterGitServiceURL, config.ZarfGitPushUser) + expectedMutatedRepoURL := fmt.Sprintf("%s/%s/podinfo-1646971829.git", types.ZarfInClusterGitServiceURL, types.ZarfGitPushUser) // Tests the mutation of the private repository Secret for ArgoCD. stdOut, stdErr, err = e2e.Kubectl("get", "secret", "argocd-repo-github-podinfo", "-n", "argocd", "-o", "jsonpath={.data.url}") diff --git a/src/test/e2e/25_helm_test.go b/src/test/e2e/25_helm_test.go index fef3433e76..1926785c9a 100644 --- a/src/test/e2e/25_helm_test.go +++ b/src/test/e2e/25_helm_test.go @@ -60,7 +60,7 @@ func testHelmChartsExample(t *testing.T) { require.NoError(t, err, stdOut, stdErr) // Create a test package (with a registry override (host to host+subpath) to test that as well) - // expect to fail as ghcr.io is overriden and the expected final image doesn't exist but the override works well based on the error message in the output + // expect to fail as ghcr.io is overridden and the expected final image doesn't exist but the override works well based on the error message in the output stdOut, stdErr, err = e2e.Zarf("package", "create", "examples/helm-charts", "-o", "build", "--registry-override", "ghcr.io=localhost:555/noway", "--tmpdir", tmpdir, "--confirm") require.Error(t, err, stdOut, stdErr) require.Contains(t, string(stdErr), "localhost:555/noway") diff --git a/src/test/packages/00-find-images-with-vars/deployment.yaml b/src/test/packages/00-find-images-with-vars/deployment.yaml new file mode 100644 index 0000000000..8d4b344dae --- /dev/null +++ b/src/test/packages/00-find-images-with-vars/deployment.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: simple-deployment + labels: + app: simple-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: simple-deployment + template: + metadata: + labels: + app: simple-deployment + spec: + containers: + - name: server + image: "###ZARF_CONST_SAMPLE_IMAGE###" diff --git a/src/test/packages/00-find-images-with-vars/simple-helm/Chart.yaml b/src/test/packages/00-find-images-with-vars/simple-helm/Chart.yaml new file mode 100644 index 0000000000..2c128bf819 --- /dev/null +++ b/src/test/packages/00-find-images-with-vars/simple-helm/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: simple-helm +description: A Helm chart for Kubernetes +type: application +version: 0.1.0 +appVersion: "0.0.1" diff --git a/src/test/packages/00-find-images-with-vars/simple-helm/templates/deployment.yaml b/src/test/packages/00-find-images-with-vars/simple-helm/templates/deployment.yaml new file mode 100644 index 0000000000..335cb8afbb --- /dev/null +++ b/src/test/packages/00-find-images-with-vars/simple-helm/templates/deployment.yaml @@ -0,0 +1,19 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: simple-deployment + labels: + app: simple-deployment +spec: + replicas: 1 + selector: + matchLabels: + app: simple-deployment + template: + metadata: + labels: + app: simple-deployment + spec: + containers: + - name: busybox + image: {{.Values.busybox}} diff --git a/src/test/packages/00-find-images-with-vars/values.yaml b/src/test/packages/00-find-images-with-vars/values.yaml new file mode 100644 index 0000000000..da10dacc6b --- /dev/null +++ b/src/test/packages/00-find-images-with-vars/values.yaml @@ -0,0 +1 @@ +busybox: ###ZARF_VAR_BUSYBOX_IMAGE### diff --git a/src/test/packages/00-find-images-with-vars/zarf.yaml b/src/test/packages/00-find-images-with-vars/zarf.yaml new file mode 100644 index 0000000000..b58911d993 --- /dev/null +++ b/src/test/packages/00-find-images-with-vars/zarf.yaml @@ -0,0 +1,31 @@ +kind: ZarfPackageConfig +metadata: + name: find-image-with-variables + description: Simple zarf package with variables + +variables: + - name: BUSYBOX_IMAGE + default: "busybox:latest" + +constants: + - name: SAMPLE_IMAGE + value: "nginx:latest" + +components: +- name: simple-var + required: true + manifests: + - name: simple-deployment + namespace: zarf + files: + - deployment.yaml +- name: chart-with-var + required: true + charts: + - name: simple + releaseName: simple + localPath: simple-helm + namespace: zarf-simple + version: 0.1.0 + valuesFiles: + - values.yaml diff --git a/src/test/packages/13-find-images/dos-games-find-images-expected.txt b/src/test/packages/13-find-images/dos-games-find-images-expected.txt deleted file mode 100644 index 8d661f4e52..0000000000 --- a/src/test/packages/13-find-images/dos-games-find-images-expected.txt +++ /dev/null @@ -1,7 +0,0 @@ -components: - - - name: baseline - images: - - defenseunicorns/zarf-game:multi-tile-dark - # Cosign artifacts for images - dos-games - baseline - - index.docker.io/defenseunicorns/zarf-game:sha256-0b694ca1c33afae97b7471488e07968599f1d2470c629f76af67145ca64428af.sig diff --git a/src/test/packages/13-find-images/helm-charts-find-images-why-expected.txt b/src/test/packages/13-find-images/helm-charts-find-images-why-expected.txt deleted file mode 100644 index 132a02e855..0000000000 --- a/src/test/packages/13-find-images/helm-charts-find-images-why-expected.txt +++ /dev/null @@ -1,187 +0,0 @@ -component: wordpress -chart: wordpress -resource: - -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - app.kubernetes.io/instance: wordpress - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: wordpress - helm.sh/chart: wordpress-16.0.4 - name: wordpress - namespace: wordpress -spec: - replicas: 1 - selector: - matchLabels: - app.kubernetes.io/instance: wordpress - app.kubernetes.io/name: wordpress - strategy: - type: RollingUpdate - template: - metadata: - annotations: null - labels: - app.kubernetes.io/instance: wordpress - app.kubernetes.io/managed-by: Helm - app.kubernetes.io/name: wordpress - helm.sh/chart: wordpress-16.0.4 - spec: - affinity: - nodeAffinity: null - podAffinity: null - podAntiAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - podAffinityTerm: - labelSelector: - matchLabels: - app.kubernetes.io/instance: wordpress - app.kubernetes.io/name: wordpress - topologyKey: kubernetes.io/hostname - weight: 1 - containers: - - env: - - name: BITNAMI_DEBUG - value: "false" - - name: ALLOW_EMPTY_PASSWORD - value: "yes" - - name: MARIADB_HOST - value: wordpress-mariadb - - name: MARIADB_PORT_NUMBER - value: "3306" - - name: WORDPRESS_DATABASE_NAME - value: bitnami_wordpress - - name: WORDPRESS_DATABASE_USER - value: bn_wordpress - - name: WORDPRESS_DATABASE_PASSWORD - valueFrom: - secretKeyRef: - key: mariadb-password - name: wordpress-mariadb - - name: WORDPRESS_USERNAME - value: null - - name: WORDPRESS_PASSWORD - valueFrom: - secretKeyRef: - key: wordpress-password - name: wordpress - - name: WORDPRESS_EMAIL - value: null - - name: WORDPRESS_FIRST_NAME - value: null - - name: WORDPRESS_LAST_NAME - value: null - - name: WORDPRESS_HTACCESS_OVERRIDE_NONE - value: "no" - - name: WORDPRESS_ENABLE_HTACCESS_PERSISTENCE - value: "no" - - name: WORDPRESS_BLOG_NAME - value: null - - name: WORDPRESS_SKIP_BOOTSTRAP - value: "no" - - name: WORDPRESS_TABLE_PREFIX - value: wp_ - - name: WORDPRESS_SCHEME - value: http - - name: WORDPRESS_EXTRA_WP_CONFIG_CONTENT - value: "" - - name: WORDPRESS_PLUGINS - value: none - - name: APACHE_HTTP_PORT_NUMBER - value: "8080" - - name: APACHE_HTTPS_PORT_NUMBER - value: "8443" - envFrom: null - image: docker.io/bitnami/wordpress:6.2.0-debian-11-r18 - imagePullPolicy: IfNotPresent - livenessProbe: - failureThreshold: 6 - httpGet: - httpHeaders: [] - path: /wp-admin/install.php - port: http - scheme: HTTP - initialDelaySeconds: 120 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - name: wordpress - ports: - - containerPort: 8080 - name: http - - containerPort: 8443 - name: https - readinessProbe: - failureThreshold: 6 - httpGet: - httpHeaders: [] - path: /wp-login.php - port: http - scheme: HTTP - initialDelaySeconds: 30 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - resources: - limits: {} - requests: - cpu: 300m - memory: 512Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - runAsNonRoot: true - runAsUser: 1001 - volumeMounts: - - mountPath: /bitnami/wordpress - name: wordpress-data - subPath: wordpress - - command: - - /bin/apache_exporter - - --scrape_uri - - http://status.localhost:8080/server-status/?auto - image: docker.io/bitnami/apache-exporter:0.13.3-debian-11-r2 - imagePullPolicy: IfNotPresent - livenessProbe: - failureThreshold: 3 - httpGet: - path: /metrics - port: metrics - initialDelaySeconds: 15 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 5 - name: metrics - ports: - - containerPort: 9117 - name: metrics - readinessProbe: - failureThreshold: 3 - httpGet: - path: /metrics - port: metrics - initialDelaySeconds: 5 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 3 - resources: - limits: {} - requests: {} - hostAliases: - - hostnames: - - status.localhost - ip: 127.0.0.1 - securityContext: - fsGroup: 1001 - seccompProfile: - type: RuntimeDefault - serviceAccountName: default - volumes: - - name: wordpress-data - persistentVolumeClaim: - claimName: wordpress - diff --git a/src/test/packages/13-find-images/manifests-find-images-why-expected.txt b/src/test/packages/13-find-images/manifests-find-images-why-expected.txt deleted file mode 100644 index d3ed40d8ac..0000000000 --- a/src/test/packages/13-find-images/manifests-find-images-why-expected.txt +++ /dev/null @@ -1,24 +0,0 @@ -component: httpd-local -manifest: simple-httpd-deployment -resource: - -apiVersion: apps/v1 -kind: Deployment -metadata: - name: httpd-deployment -spec: - replicas: 2 - selector: - matchLabels: - app: httpd - template: - metadata: - labels: - app: httpd - spec: - containers: - - image: httpd:alpine3.18 - name: httpd - ports: - - containerPort: 80 - diff --git a/src/types/k8s.go b/src/types/k8s.go index b01cea1848..b34b10a211 100644 --- a/src/types/k8s.go +++ b/src/types/k8s.go @@ -5,9 +5,12 @@ package types import ( + "fmt" "time" + "github.com/defenseunicorns/zarf/src/config/lang" "github.com/defenseunicorns/zarf/src/pkg/k8s" + "github.com/defenseunicorns/zarf/src/pkg/utils/helpers" ) // WebhookStatus defines the status of a Component Webhook operating on a Zarf package secret. @@ -32,6 +35,21 @@ const ( ComponentStatusRemoving ComponentStatus = "Removing" ) +// Values during setup of the initial zarf state +const ( + ZarfGeneratedPasswordLen = 24 + ZarfGeneratedSecretLen = 48 + ZarfInClusterContainerRegistryNodePort = 31999 + ZarfRegistryPushUser = "zarf-push" + ZarfRegistryPullUser = "zarf-pull" + + ZarfGitPushUser = "zarf-git-user" + ZarfGitReadUser = "zarf-git-read-user" + + ZarfInClusterGitServiceURL = "http://zarf-gitea-http.zarf.svc.cluster.local:3000" + ZarfInClusterArtifactServiceURL = ZarfInClusterGitServiceURL + "/api/packages/" + ZarfGitPushUser +) + // ZarfState is maintained as a secret in the Zarf namespace to track Zarf init data. type ZarfState struct { ZarfAppliance bool `json:"zarfAppliance" jsonschema:"description=Indicates if Zarf was initialized while deploying its own k8s cluster"` @@ -91,6 +109,43 @@ type GitServerInfo struct { InternalServer bool `json:"internalServer" jsonschema:"description=Indicates if we are using a git server that Zarf is directly managing"` } +// FillInEmptyValues sets every necessary value that's currently empty to a reasonable default +func (gs *GitServerInfo) FillInEmptyValues() error { + var err error + // Set default svc url if an external repository was not provided + if gs.Address == "" { + gs.Address = ZarfInClusterGitServiceURL + gs.InternalServer = true + } + + // Generate a push-user password if not provided by init flag + if gs.PushPassword == "" { + if gs.PushPassword, err = helpers.RandomString(ZarfGeneratedPasswordLen); err != nil { + return fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) + } + } + + // Set read-user information if using an internal repository, otherwise copy from the push-user + if gs.PullUsername == "" { + if gs.InternalServer { + gs.PullUsername = ZarfGitReadUser + } else { + gs.PullUsername = gs.PushUsername + } + } + if gs.PullPassword == "" { + if gs.InternalServer { + if gs.PullPassword, err = helpers.RandomString(ZarfGeneratedPasswordLen); err != nil { + return fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) + } + } else { + gs.PullPassword = gs.PushPassword + } + } + + return nil +} + // ArtifactServerInfo contains information Zarf uses to communicate with a artifact registry to push/pull repositories to. type ArtifactServerInfo struct { PushUsername string `json:"pushUsername" jsonschema:"description=Username of a user with push access to the artifact registry"` @@ -100,6 +155,20 @@ type ArtifactServerInfo struct { InternalServer bool `json:"internalServer" jsonschema:"description=Indicates if we are using a artifact registry that Zarf is directly managing"` } +// FillInEmptyValues sets every necessary value that's currently empty to a reasonable default +func (as *ArtifactServerInfo) FillInEmptyValues() { + // Set default svc url if an external registry was not provided + if as.Address == "" { + as.Address = ZarfInClusterArtifactServiceURL + as.InternalServer = true + } + + // Set the push username to the git push user if not specified + if as.PushUsername == "" { + as.PushUsername = ZarfGitPushUser + } +} + // RegistryInfo contains information Zarf uses to communicate with a container registry to push/pull images. type RegistryInfo struct { PushUsername string `json:"pushUsername" jsonschema:"description=Username of a user with push access to the registry"` @@ -113,3 +182,53 @@ type RegistryInfo struct { Secret string `json:"secret" jsonschema:"description=Secret value that the registry was seeded with"` } + +// FillInEmptyValues sets every necessary value not already set to a reasonable default +func (ri *RegistryInfo) FillInEmptyValues() error { + var err error + // Set default NodePort if none was provided + if ri.NodePort == 0 { + ri.NodePort = ZarfInClusterContainerRegistryNodePort + } + + // Set default url if an external registry was not provided + if ri.Address == "" { + ri.InternalRegistry = true + ri.Address = fmt.Sprintf("%s:%d", helpers.IPV4Localhost, ri.NodePort) + } + + // Generate a push-user password if not provided by init flag + if ri.PushPassword == "" { + if ri.PushPassword, err = helpers.RandomString(ZarfGeneratedPasswordLen); err != nil { + return fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) + } + } + + // Set pull-username if not provided by init flag + if ri.PullUsername == "" { + if ri.InternalRegistry { + ri.PullUsername = ZarfRegistryPullUser + } else { + // If this is an external registry and a pull-user wasn't provided, use the same credentials as the push user + ri.PullUsername = ri.PushUsername + } + } + if ri.PullPassword == "" { + if ri.InternalRegistry { + if ri.PullPassword, err = helpers.RandomString(ZarfGeneratedPasswordLen); err != nil { + return fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) + } + } else { + // If this is an external registry and a pull-user wasn't provided, use the same credentials as the push user + ri.PullPassword = ri.PushPassword + } + } + + if ri.Secret == "" { + if ri.Secret, err = helpers.RandomString(ZarfGeneratedSecretLen); err != nil { + return fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err) + } + } + + return nil +} diff --git a/src/types/runtime.go b/src/types/runtime.go index af4fd8ae55..a508367e34 100644 --- a/src/types/runtime.go +++ b/src/types/runtime.go @@ -55,6 +55,7 @@ type ZarfInspectOptions struct { type ZarfFindImagesOptions struct { RepoHelmChartPath string `json:"repoHelmChartPath" jsonschema:"description=Path to the helm chart directory"` KubeVersionOverride string `json:"kubeVersionOverride" jsonschema:"description=Kubernetes version to use for the helm chart"` + RegistryURL string `json:"registryURL" jsonschema:"description=Manual override for ###ZARF_REGISTRY###"` Why string `json:"why" jsonschema:"description=Find the location of the image given as an argument and print it to the console."` }