Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1766 - Git Tag and Chart Version assumed to match #1892

Merged
merged 18 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/extensions/bigbang/bigbang.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,14 @@ func Run(YOLO bool, tmpPaths types.ComponentPaths, c types.ZarfComponent) (types
}
}

bbRepo := fmt.Sprintf("%s@%s", cfg.Repo, cfg.Version)

// Configure helm to pull down the Big Bang chart.
helmCfg := helm.Helm{
Chart: types.ZarfChart{
Name: bb,
Namespace: bb,
URL: cfg.Repo,
URL: bbRepo,
Version: cfg.Version,
ValuesFiles: cfg.ValuesFiles,
GitPath: "./chart",
Expand Down Expand Up @@ -494,7 +496,7 @@ func findImagesforBBChartRepo(repo string, values chartutil.Values) (images []st

chart := types.ZarfChart{
Name: repo,
URL: matches[0],
URL: repo,
Version: matches[1],
GitPath: "chart",
}
Expand Down
2 changes: 1 addition & 1 deletion src/internal/agent/hooks/flux.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func mutateGitRepo(r *v1.AdmissionRequest) (result *operations.Result, err error
// Mutate the git URL if necessary
if isCreate || (isUpdate && !isPatched) {
// Mutate the git URL so that the hostname matches the hostname in the Zarf state
transformedURL, err := transform.GitTransformURL(zarfState.GitServer.Address, patchedURL, zarfState.GitServer.PushUsername)
transformedURL, err := transform.GitURL(zarfState.GitServer.Address, patchedURL, zarfState.GitServer.PushUsername)
if err != nil {
message.Warnf("Unable to transform the git url, using the original url we have: %s", patchedURL)
}
Expand Down
2 changes: 1 addition & 1 deletion src/internal/agent/http/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func proxyRequestTransform(r *http.Request) error {
} else {
switch {
case isGitUserAgent(r.UserAgent()):
targetURL, err = transform.GitTransformURL(zarfState.GitServer.Address, getTLSScheme(r.TLS)+r.Host+r.URL.String(), zarfState.GitServer.PushUsername)
targetURL, err = transform.GitURL(zarfState.GitServer.Address, getTLSScheme(r.TLS)+r.Host+r.URL.String(), zarfState.GitServer.PushUsername)
case isPipUserAgent(r.UserAgent()):
targetURL, err = transform.PipTransformURL(zarfState.ArtifactServer.Address, getTLSScheme(r.TLS)+r.Host+r.URL.String())
case isNpmUserAgent(r.UserAgent()):
Expand Down
4 changes: 2 additions & 2 deletions src/internal/packager/git/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (g *Git) Pull(gitURL, targetFolder string, shallow bool) error {
g.Spinner.Updatef("Processing git repo %s", gitURL)

// Split the remote url and the zarf reference
gitURLNoRef, refPlain, err := transform.GitTransformURLSplitRef(gitURL)
gitURLNoRef, refPlain, err := transform.GitURLSplitRef(gitURL)
if err != nil {
return err
}
Expand All @@ -51,7 +51,7 @@ func (g *Git) Pull(gitURL, targetFolder string, shallow bool) error {
}

// Construct a path unique to this git repo
repoFolder, err := transform.GitTransformURLtoFolderName(gitURL)
repoFolder, err := transform.GitURLtoFolderName(gitURL)
if err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions src/internal/packager/git/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (g *Git) PushRepo(srcURL, targetFolder string) error {
defer spinner.Stop()

// Setup git paths, including a unique name for the repo based on the hash of the git URL to avoid conflicts.
repoFolder, err := transform.GitTransformURLtoFolderName(srcURL)
repoFolder, err := transform.GitURLtoFolderName(srcURL)
if err != nil {
return fmt.Errorf("unable to parse git url (%s): %w", srcURL, err)
}
Expand All @@ -34,7 +34,7 @@ func (g *Git) PushRepo(srcURL, targetFolder string) error {
// Check that this package is using the new repo format (if not fallback to the format from <= 0.24.x)
_, err = os.Stat(repoPath)
if os.IsNotExist(err) {
repoFolder, err = transform.GitTransformURLtoRepoName(srcURL)
repoFolder, err = transform.GitURLtoRepoName(srcURL)
if err != nil {
return fmt.Errorf("unable to parse git url (%s): %w", srcURL, err)
}
Expand Down Expand Up @@ -63,7 +63,7 @@ func (g *Git) PushRepo(srcURL, targetFolder string) error {
return err
}
remoteURL := remote.Config().URLs[0]
repoName, err := transform.GitTransformURLtoRepoName(remoteURL)
repoName, err := transform.GitURLtoRepoName(remoteURL)
if err != nil {
message.Warnf("Unable to add the read-only user to the repo: %s\n", repoName)
return err
Expand Down Expand Up @@ -94,7 +94,7 @@ func (g *Git) prepRepoForPush() (*git.Repository, error) {
}

remoteURL := remote.Config().URLs[0]
targetURL, err := transform.GitTransformURL(g.Server.Address, remoteURL, g.Server.PushUsername)
targetURL, err := transform.GitURL(g.Server.Address, remoteURL, g.Server.PushUsername)
if err != nil {
return nil, fmt.Errorf("unable to transform the git url: %w", err)
}
Expand Down
2 changes: 2 additions & 0 deletions src/internal/packager/helm/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/defenseunicorns/zarf/src/types"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/cli"
)

// Helm is a config object for working with helm charts.
Expand All @@ -25,6 +26,7 @@ type Helm struct {
Cluster *cluster.Cluster
Cfg *types.PackagerConfig
KubeVersion string
Settings *cli.EnvSettings

actionConfig *action.Configuration
}
Expand Down
107 changes: 76 additions & 31 deletions src/internal/packager/helm/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/internal/packager/git"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/transform"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/registry"
Expand All @@ -22,65 +24,82 @@ import (
"helm.sh/helm/v3/pkg/repo"
)

// PackageChart creates a chart archive from a path to a chart on the host os and builds chart dependencies
func (h *Helm) PackageChart(destination string) error {
cmwylie19 marked this conversation as resolved.
Show resolved Hide resolved
if len(h.Chart.URL) > 0 {
url, refPlain, err := transform.GitURLSplitRef(h.Chart.URL)
// check if the chart is a git url with a ref (if an error is returned url will be empty)
isGitURL := strings.HasSuffix(url, ".git")
if err != nil {
message.Debugf("unable to parse the url, continuing with %s", h.Chart.URL)
}

if isGitURL {
// if it is a git url append chart version as if its a tag
if refPlain == "" {
h.Chart.URL = fmt.Sprintf("%s@%s", h.Chart.URL, h.Chart.Version)
}

_, err = h.PackageChartFromGit(destination)

if err != nil {
return fmt.Errorf("error creating chart archive, unable to pull the chart from git: %s", err.Error())
}
} else {
h.DownloadPublishedChart(destination)
}

} else {
_, err := h.PackageChartFromLocalFiles(destination)
if err != nil {
return fmt.Errorf("error creating chart archive, unable to package the chart: %s", err.Error())
}
}
return nil
}

// PackageChartFromLocalFiles creates a chart archive from a path to a chart on the host os.
func (h *Helm) PackageChartFromLocalFiles(destination string) string {
func (h *Helm) PackageChartFromLocalFiles(destination string) (string, error) {
spinner := message.NewProgressSpinner("Processing helm chart %s:%s from %s", h.Chart.Name, h.Chart.Version, h.Chart.LocalPath)
defer spinner.Stop()

// Validate the chart
_, err := loader.LoadDir(h.Chart.LocalPath)
if err != nil {
spinner.Fatalf(err, "Validation failed for chart from %s (%s)", h.Chart.LocalPath, err.Error())
spinner.Errorf(err, "Validation failed for chart from %s (%s)", h.Chart.LocalPath, err.Error())
return "", err
}

h.buildChartDependencies(spinner)
client := action.NewPackage()

client.Destination = destination
path, err := client.Run(h.Chart.LocalPath, nil)

if err != nil {
spinner.Fatalf(err, "Helm is unable to save the archive and create the package %s", path)
spinner.Errorf(err, "Helm is unable to save the archive and create the package %s", path)
return "", err
}

spinner.Success()

return path
return path, nil
}

// PackageChartFromGit is a special implementation of chart archiving that supports the https://p1.dso.mil/#/products/big-bang/ model.
func (h *Helm) PackageChartFromGit(destination string) (string, error) {
spinner := message.NewProgressSpinner("Processing helm chart %s", h.Chart.Name)
defer spinner.Stop()

client := action.NewPackage()

// Retrieve the repo containing the chart
gitPath, err := h.DownloadChartFromGitToTemp(spinner)
if err != nil {
return "", err
}
defer os.RemoveAll(gitPath)

// Set the directory for the chart
chartPath := filepath.Join(gitPath, h.Chart.GitPath)

// Validate the chart
if _, err := loader.LoadDir(chartPath); err != nil {
spinner.Errorf(err, "Validation failed for chart %s (%s)", h.Chart.Name, err.Error())
return "", err
}

// Tell helm where to save the archive and create the package
client.Destination = destination
name, err := client.Run(chartPath, nil)
if err != nil {
spinner.Errorf(err, "Helm is unable to save the archive and create the package %s", name)
return "", err
}

spinner.Success()

return name, nil
// Set the directory for the chart and package it
h.Chart.LocalPath = filepath.Join(gitPath, h.Chart.GitPath)
return h.PackageChartFromLocalFiles(destination)
}

// DownloadPublishedChart loads a specific chart version from a remote repo.
Expand Down Expand Up @@ -154,14 +173,40 @@ func (h *Helm) DownloadChartFromGitToTemp(spinner *message.Spinner) (string, err
// Create the Git configuration and download the repo
gitCfg := git.NewWithSpinner(h.Cfg.State.GitServer, spinner)

gitRepoWithRef := fmt.Sprintf("%s@%s", h.Chart.URL, h.Chart.Version)

// Download the git repo to a temporary directory
err := gitCfg.DownloadRepoToTemp(gitRepoWithRef)
err := gitCfg.DownloadRepoToTemp(h.Chart.URL)
if err != nil {
spinner.Errorf(err, "Unable to download the git repo %s", gitRepoWithRef)
spinner.Errorf(err, "Unable to download the git repo %s", h.Chart.URL)
return "", err
}

return gitCfg.GitPath, nil
}

// buildChartDependencies builds the helm chart dependencies
func (h *Helm) buildChartDependencies(spinner *message.Spinner) error {
regClient, err := registry.NewClient(registry.ClientOptEnableCache(true))
if err != nil {
spinner.Fatalf(err, "Unable to create a new registry client")
}
h.Settings = cli.New()
man := &downloader.Manager{
Out: os.Stdout,
ChartPath: h.Chart.LocalPath,
Getters: getter.All(h.Settings),
RegistryClient: regClient,

RepositoryConfig: h.Settings.RepositoryConfig,
RepositoryCache: h.Settings.RepositoryCache,
Debug: false,
}
// Verify the chart
man.Verify = downloader.VerifyIfPossible

// Build the deps from the helm chart
err = man.Build()
if e, ok := err.(downloader.ErrRepoNotFound); ok {
return fmt.Errorf("%s. Please add the missing repos via 'helm repo add'", e.Error())
}
return nil
}
7 changes: 4 additions & 3 deletions src/internal/packager/helm/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,14 @@ func (h *Helm) parseChartValues() (map[string]any, error) {
func (h *Helm) createActionConfig(namespace string, spinner *message.Spinner) error {
// Initialize helm SDK
actionConfig := new(action.Configuration)
settings := cli.New()
// Set the setings for the helm SDK
h.Settings = cli.New()

// Set the namespace for helm
settings.SetNamespace(namespace)
h.Settings.SetNamespace(namespace)

// Setup K8s connection
err := actionConfig.Init(settings.RESTClientGetter(), namespace, "", spinner.Updatef)
err := actionConfig.Init(h.Settings.RESTClientGetter(), namespace, "", spinner.Updatef)

// Set the actionConfig is the received Helm pointer
h.actionConfig = actionConfig
Expand Down
20 changes: 5 additions & 15 deletions src/pkg/packager/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -326,8 +325,7 @@ func (p *Packager) addComponent(index int, component types.ZarfComponent, isSkel

// If any helm charts are defined, process them.
for chartIdx, chart := range component.Charts {
re := regexp.MustCompile(`\.git$`)
isGitURL := re.MatchString(chart.URL)

helmCfg := helm.Helm{
Chart: chart,
Cfg: p.cfg,
Expand All @@ -343,18 +341,10 @@ func (p *Packager) addComponent(index int, component types.ZarfComponent, isSkel
}

p.cfg.Pkg.Components[index].Charts[chartIdx].LocalPath = rel
} else if isGitURL {
_, err = helmCfg.PackageChartFromGit(componentPath.Charts)
if err != nil {
return fmt.Errorf("error creating chart archive, unable to pull the chart from git: %s", err.Error())
}
} else if len(chart.URL) > 0 {
helmCfg.DownloadPublishedChart(componentPath.Charts)
} else {
path := helmCfg.PackageChartFromLocalFiles(componentPath.Charts)
zarfFilename := fmt.Sprintf("%s-%s.tgz", chart.Name, chart.Version)
if !strings.HasSuffix(path, zarfFilename) {
return fmt.Errorf("error creating chart archive, user provided chart name and/or version does not match given chart")
err := helmCfg.PackageChart(componentPath.Charts)
if err != nil {
return err
}
}

Expand Down Expand Up @@ -694,7 +684,7 @@ func (p *Packager) removeCopiesFromDifferentialPackage() error {
// Generate a list of all unique repos for this component
for _, repoURL := range component.Repos {
// Split the remote url and the zarf reference
_, refPlain, err := transform.GitTransformURLSplitRef(repoURL)
_, refPlain, err := transform.GitURLSplitRef(repoURL)
if err != nil {
return err
}
Expand Down
18 changes: 5 additions & 13 deletions src/pkg/packager/prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,27 +113,19 @@ func (p *Packager) FindImages(baseDir, repoHelmChartPath string, kubeVersionOver
if len(component.Charts) > 0 {
_ = utils.CreateDirectory(componentPath.Charts, 0700)
_ = utils.CreateDirectory(componentPath.Values, 0700)
re := regexp.MustCompile(`\.git$`)

for _, chart := range component.Charts {
isGitURL := re.MatchString(chart.URL)

helmCfg := helm.Helm{
Chart: chart,
Cfg: p.cfg,
}

helmCfg.Cfg.State = types.ZarfState{}
if isGitURL {
path, err := helmCfg.PackageChartFromGit(componentPath.Charts)
if err != nil {
return fmt.Errorf("unable to download chart from git repo (%s): %w", chart.URL, err)
}
// track the actual chart path
chartOverrides[chart.Name] = path
} else if len(chart.URL) > 0 {
helmCfg.DownloadPublishedChart(componentPath.Charts)
} else {
helmCfg.PackageChartFromLocalFiles(componentPath.Charts)

err := helmCfg.PackageChart(componentPath.Charts)
if err != nil {
return fmt.Errorf("unable to package the chart %s: %s", chart.URL, err.Error())
}

for idx, path := range chart.ValuesFiles {
Expand Down
Loading