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

feat: add oci format chart support #57

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ linters:
- unused
- whitespace
- gci
# - depguard
# - gocritic
# - depguard
# - godox
Expand Down
32 changes: 25 additions & 7 deletions chartify.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"
"text/template"

"github.com/Masterminds/semver/v3"
"github.com/otiai10/copy"
"helm.sh/helm/v3/pkg/registry"
)
Expand Down Expand Up @@ -374,7 +375,7 @@ func (r *Runner) Chartify(release, dirOrChart string, opts ...ChartifyOption) (s
} else {
// Flatten the chart by fetching dependent chart archives and merging their K8s manifests into the temporary local chart
// So that we can uniformly patch them with JSON patch, Strategic-Merge patch, or with injectors
_, err := r.run(r.helmBin(), "dependency", "up", tempDir)
_, err := r.run(nil, r.helmBin(), "dependency", "up", tempDir)
if err != nil {
return "", err
}
Expand All @@ -384,7 +385,7 @@ func (r *Runner) Chartify(release, dirOrChart string, opts ...ChartifyOption) (s
// and its dependencies. But ovbiously, previous `helm fetch` run doesn't download the adhoc dependencies we added
// after running `helm fetch`.
// We need to download adhoc dependencies on our own by running helmfile dependency up.
_, err := r.run(r.helmBin(), "dependency", "up", tempDir)
_, err := r.run(nil, r.helmBin(), "dependency", "up", tempDir)
if err != nil {
return "", err
}
Expand Down Expand Up @@ -526,7 +527,7 @@ func (r *Runner) ReadAdhocDependencies(u *ChartifyOpts) ([]Dependency, error) {
repo := repoAndChart[0]
name = repoAndChart[1]

out, err := r.run(r.helmBin(), "repo", "list")
out, err := r.run(nil, r.helmBin(), "repo", "list")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -693,16 +694,33 @@ func (r *Runner) copyToTempDir(path, tempDir, chartVersion string) (string, erro
}

func (r *Runner) fetchAndUntarUnderDir(chart, tempDir, chartVersion string) (string, error) {
command := []string{"fetch", chart, "--untar", "-d", tempDir}
helmVersionConstraint, _ := semver.NewConstraint(">= 3.7.0")
helmVersion, err := r.DetectHelmVersion()
if err != nil {
return "", err
}
var helmPullCommand []string
if helmVersionConstraint.Check(helmVersion) {
helmPullCommand = []string{"pull", chart, "--untar", "-d", tempDir}

if chartVersion != "" {
command = append(command, "--version", chartVersion)
if chartVersion != "" {
helmPullCommand = append(helmPullCommand, "--version", chartVersion)
}
} else {
helmPullCommand = []string{"chart", "pull", chart}
}

if _, err := r.run(r.helmBin(), command...); err != nil {
if _, err := r.run(map[string]string{}, r.helmBin(), helmPullCommand...); err != nil {
return "", err
}

if !helmVersionConstraint.Check(helmVersion) {
helmExportCommand := []string{"chart", "export", chart, "--destination", tempDir}
if _, err := r.run(map[string]string{}, r.helmBin(), helmExportCommand...); err != nil {
return "", err
}
}

files, err := r.ReadDir(tempDir)
if err != nil {
return "", err
Expand Down
4 changes: 2 additions & 2 deletions inject.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (r *Runner) Inject(files []string, o InjectOpts) error {
for _, file := range files {
flags := strings.Replace(flagsTemplate, "FILE", file, 1)
command := fmt.Sprintf("%s %s", injector, flags)
stdout, err := r.runBytes("", command)
stdout, err := r.runBytes(nil, "", command)
if err != nil {
return err
}
Expand All @@ -45,7 +45,7 @@ func (r *Runner) Inject(files []string, o InjectOpts) error {
for _, file := range files {
cmd := strings.Replace(tmpl, "FILE", file, 1)

stdout, err := r.runBytes("", cmd)
stdout, err := r.runBytes(nil, "", cmd)
if err != nil {
return err
}
Expand Down
3 changes: 1 addition & 2 deletions kustomize.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ func (r *Runner) KustomizeBuild(srcDir string, tempDir string, opts ...Kustomize
}
kustomizeArgs = append(kustomizeArgs, f)
}

f, err := r.kustomizeLoadRestrictionsNoneFlag()
if err != nil {
return "", err
Expand All @@ -175,7 +174,7 @@ func (r *Runner) KustomizeBuild(srcDir string, tempDir string, opts ...Kustomize

// kustomizeVersion returns the kustomize binary version.
func (r *Runner) kustomizeVersion() (*semver.Version, error) {
versionInfo, err := r.run(r.kustomizeBin(), "version")
versionInfo, err := r.run(nil, r.kustomizeBin(), "version")
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ resources:
kustomizeArgs = append(kustomizeArgs, f)
}

_, err := r.run(r.kustomizeBin(), kustomizeArgs...)
_, err := r.run(nil, r.kustomizeBin(), kustomizeArgs...)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion replace.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func (r *Runner) ReplaceWithRendered(name, chartName, chartPath string, o Replac
command = fmt.Sprintf("%s template --debug=%v %s --name %s%s --output-dir %s", r.helmBin(), o.Debug, chartPath, name, additionalFlags, helmOutputDir)
}

stdout, err := r.run(command)
stdout, err := r.run(nil, command)
if err != nil {
return nil, err
}
Expand Down
48 changes: 39 additions & 9 deletions runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"os/exec"
"path/filepath"
"strings"

"github.com/Masterminds/semver/v3"
)

type RunCommandFunc func(name string, args []string, dir string, stdout, stderr io.Writer, env map[string]string) error
Expand Down Expand Up @@ -101,8 +103,8 @@ func (r *Runner) kustomizeBin() string {
return "kustomize"
}

func (r *Runner) run(cmd string, args ...string) (string, error) {
bytes, err := r.runBytes("", cmd, args...)
func (r *Runner) run(envs map[string]string, cmd string, args ...string) (string, error) {
bytes, err := r.runBytes(envs, "", cmd, args...)

var out string

Expand All @@ -114,7 +116,7 @@ func (r *Runner) run(cmd string, args ...string) (string, error) {
}

func (r *Runner) runInDir(dir, cmd string, args ...string) (string, error) {
bytes, err := r.runBytes(dir, cmd, args...)
bytes, err := r.runBytes(nil, dir, cmd, args...)

var out string

Expand All @@ -125,7 +127,7 @@ func (r *Runner) runInDir(dir, cmd string, args ...string) (string, error) {
return out, err
}

func (r *Runner) runBytes(dir, cmd string, args ...string) ([]byte, error) {
func (r *Runner) runBytes(envs map[string]string, dir, cmd string, args ...string) ([]byte, error) {
nameArgs := strings.Split(cmd, " ")

name := nameArgs[0]
Expand All @@ -137,7 +139,7 @@ func (r *Runner) runBytes(dir, cmd string, args ...string) ([]byte, error) {
args = a
}

bytes, errBytes, err := r.captureBytes(name, args, dir)
bytes, errBytes, err := r.captureBytes(name, args, dir, envs)
if err != nil {
c := strings.Join(append([]string{name}, args...), " ")

Expand Down Expand Up @@ -170,23 +172,51 @@ func (r *Runner) IsHelm3() bool {
}

// Autodetect from `helm version`
out, err := r.run(r.helmBin(), "version", "--client", "--short")
sv, err := r.DetectHelmVersion()
if err != nil {
panic(err)
}

return strings.HasPrefix(out, "v3.")
return sv.Major() == 3
}

// DetectHelmVersion detects the version of Helm installed on the system.
// It runs the `helm version` command and parses the output to extract the client version.
// Returns the detected Helm version as a semver.Version object.
// If an error occurs during the detection process, it returns an error.
func (r *Runner) DetectHelmVersion() (*semver.Version, error) {
// Autodetect from `helm version`
out, err := r.run(nil, r.helmBin(), "version", "--client", "--short")
if err != nil {
return nil, fmt.Errorf("error determining helm version: %w", err)
}

if len(out) == 0 {
return nil, fmt.Errorf("error determining helm version: output was empty")
}
v, err := FindSemVerInfo(out)

if err != nil {
return nil, fmt.Errorf("error find helm srmver version '%s': %w", out, err)
}

ver, err := semver.NewVersion(v)
if err != nil {
return nil, fmt.Errorf("error parsing helm version '%s'", ver)
}

return ver, nil
}

func (r *Runner) captureBytes(binary string, args []string, dir string) ([]byte, []byte, error) {
func (r *Runner) captureBytes(binary string, args []string, dir string, envs map[string]string) ([]byte, []byte, error) {
r.Logf("running %s %s", binary, strings.Join(args, " "))
_, err := exec.LookPath(binary)
if err != nil {
return nil, nil, err
}

var stdout, stderr bytes.Buffer
err = r.RunCommand(binary, args, dir, &stdout, &stderr, map[string]string{})
err = r.RunCommand(binary, args, dir, &stdout, &stderr, envs)
if err != nil {
r.Logf(stderr.String())
}
Expand Down