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

helm: Add support for remote chart version #1078

Merged
merged 2 commits into from
Sep 19, 2022
Merged
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
100 changes: 88 additions & 12 deletions internal/helm/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ package helm
import (
"bytes"
"context"
"errors"
"fmt"
"io/fs"
"os"
"path"
"regexp"
"sort"
"strings"
Expand All @@ -30,6 +34,8 @@ import (
corev1 "k8s.io/api/core/v1"
)

const ciliumChart = "https://helm.cilium.io"

var settings = cli.New()

// State contains Helm state for the current Cilium installation. Cilium CLI retrieves this
Expand Down Expand Up @@ -183,10 +189,10 @@ func newClient(namespace, k8sVersion string) (*action.Install, error) {
return helmClient, nil
}

func newChartFromCiliumVersion(ciliumVersion semver2.Version) (*chart.Chart, error) {
func newChartFromEmbeddedFile(ciliumVersion semver2.Version) (*chart.Chart, error) {
helmTgz, err := helm.HelmFS.ReadFile(fmt.Sprintf("cilium-%s.tgz", ciliumVersion))
if err != nil {
return nil, fmt.Errorf("cilium version not found: %s", err)
return nil, fmt.Errorf("cilium version not found: %w", err)
}

// Check chart dependencies to make sure all are present in /charts
Expand All @@ -197,6 +203,55 @@ func newChartFromDirectory(directory string) (*chart.Chart, error) {
return loader.LoadDir(directory)
}

// newChartFromRemoteWithCache fetches the chart from remote repository, the chart file
// is then stored in the local cache directory for future usage.
func newChartFromRemoteWithCache(ciliumVersion semver2.Version) (*chart.Chart, error) {
cacheDir, err := ciliumCacheDir()
if err != nil {
return nil, err
}
sayboras marked this conversation as resolved.
Show resolved Hide resolved

file := path.Join(cacheDir, fmt.Sprintf("cilium-%s.tgz", ciliumVersion))
if _, err = os.Stat(file); err != nil {
sayboras marked this conversation as resolved.
Show resolved Hide resolved
if !errors.Is(err, fs.ErrNotExist) {
return nil, err
}

// Download the chart from remote repository
pull := action.NewPullWithOpts(action.WithConfig(new(action.Configuration)))
pull.Settings = settings
pull.RepoURL = ciliumChart
pull.Version = ciliumVersion.String()
pull.DestDir = cacheDir

if _, err = pull.Run("cilium"); err != nil {
return nil, err
}
}

f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
return loader.LoadArchive(f)
}

func ciliumCacheDir() (string, error) {
cacheDir, err := os.UserCacheDir()
if err != nil {
return "", err
}

res := path.Join(cacheDir, "cilium-cli")
err = os.MkdirAll(res, 0755)
if err != nil && !os.IsExist(err) {
return "", err
}

return res, nil
}

// GenManifests returns the generated manifests in a map that maps the manifest
// name to its contents.
func GenManifests(
Expand All @@ -216,9 +271,15 @@ func GenManifests(
return nil, err
}
} else {
helmChart, err = newChartFromCiliumVersion(ciliumVer)
helmChart, err = newChartFromEmbeddedFile(ciliumVer)
if err != nil {
return nil, err
if !errors.Is(err, fs.ErrNotExist) {
return nil, err
}
helmChart, err = newChartFromRemoteWithCache(ciliumVer)
if err != nil {
return nil, err
}
}
}
sayboras marked this conversation as resolved.
Show resolved Hide resolved

Expand Down Expand Up @@ -328,14 +389,7 @@ func ListVersions() ([]string, error) {
func ResolveHelmChartVersion(versionFlag, chartDirectoryFlag string) (semver2.Version, error) {
if chartDirectoryFlag == "" {
// If --chart-directory flag is not specified, use the version specified with --version flag.
version, err := utils.ParseCiliumVersion(versionFlag)
if err != nil {
return semver2.Version{}, err
}
if _, err = newChartFromCiliumVersion(version); err != nil {
return semver2.Version{}, err
}
return version, nil
return resolveChartVersion(versionFlag)
}

// Get the chart version from the local Helm chart specified with --chart-directory flag.
Expand All @@ -345,3 +399,25 @@ func ResolveHelmChartVersion(versionFlag, chartDirectoryFlag string) (semver2.Ve
}
return versioncheck.MustVersion(localChart.Metadata.Version), nil
}

func resolveChartVersion(versionFlag string) (semver2.Version, error) {
version, err := utils.ParseCiliumVersion(versionFlag)
if err != nil {
return semver2.Version{}, err
}

_, err = newChartFromEmbeddedFile(version)
if err == nil {
return version, nil
}

if !errors.Is(err, fs.ErrNotExist) {
return semver2.Version{}, err
}

_, err = newChartFromRemoteWithCache(version)
if err != nil {
return semver2.Version{}, err
}
return version, nil
}