mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-03-18 10:32:36 +00:00
Allow users to specify a local Helm chart folder via CLI flag or config, which takes precedence over the KUBESHARK_HELM_CHART_PATH env variable and the remote Helm repo. Also update nginx proxy config to disable buffering for better streaming and large snapshot support.
190 lines
4.6 KiB
Go
190 lines
4.6 KiB
Go
package helm
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/kubeshark/kubeshark/config"
|
|
"github.com/kubeshark/kubeshark/misc"
|
|
"github.com/pkg/errors"
|
|
"github.com/rs/zerolog/log"
|
|
"helm.sh/helm/v3/pkg/action"
|
|
"helm.sh/helm/v3/pkg/chart"
|
|
"helm.sh/helm/v3/pkg/chart/loader"
|
|
"helm.sh/helm/v3/pkg/cli"
|
|
"helm.sh/helm/v3/pkg/downloader"
|
|
"helm.sh/helm/v3/pkg/getter"
|
|
"helm.sh/helm/v3/pkg/kube"
|
|
"helm.sh/helm/v3/pkg/registry"
|
|
"helm.sh/helm/v3/pkg/release"
|
|
"helm.sh/helm/v3/pkg/repo"
|
|
)
|
|
|
|
const ENV_HELM_DRIVER = "HELM_DRIVER"
|
|
|
|
var settings = cli.New()
|
|
|
|
type Helm struct {
|
|
repo string
|
|
releaseName string
|
|
releaseNamespace string
|
|
}
|
|
|
|
func NewHelm(repo string, releaseName string, releaseNamespace string) *Helm {
|
|
return &Helm{
|
|
repo: repo,
|
|
releaseName: releaseName,
|
|
releaseNamespace: releaseNamespace,
|
|
}
|
|
}
|
|
|
|
func parseOCIRef(chartRef string) (string, string, error) {
|
|
refTagRegexp := regexp.MustCompile(`^(oci://[^:]+(:[0-9]{1,5})?[^:]+):(.*)$`)
|
|
caps := refTagRegexp.FindStringSubmatch(chartRef)
|
|
if len(caps) != 4 {
|
|
return "", "", errors.Errorf("improperly formatted oci chart reference: %s", chartRef)
|
|
}
|
|
chartRef = caps[1]
|
|
tag := caps[3]
|
|
|
|
return chartRef, tag, nil
|
|
}
|
|
|
|
func (h *Helm) Install() (rel *release.Release, err error) {
|
|
kubeConfigPath := config.Config.KubeConfigPath()
|
|
actionConfig := new(action.Configuration)
|
|
if err = actionConfig.Init(kube.GetConfig(kubeConfigPath, "", h.releaseNamespace), h.releaseNamespace, os.Getenv(ENV_HELM_DRIVER), func(format string, v ...interface{}) {
|
|
log.Info().Msgf(format, v...)
|
|
}); err != nil {
|
|
return
|
|
}
|
|
|
|
client := action.NewInstall(actionConfig)
|
|
client.Namespace = h.releaseNamespace
|
|
client.ReleaseName = h.releaseName
|
|
|
|
chartPath := config.Config.Tap.Release.HelmChartPath
|
|
if chartPath == "" {
|
|
chartPath = os.Getenv(fmt.Sprintf("%s_HELM_CHART_PATH", strings.ToUpper(misc.Program)))
|
|
}
|
|
if chartPath == "" {
|
|
var chartURL string
|
|
chartURL, err = repo.FindChartInRepoURL(h.repo, h.releaseName, "", "", "", "", getter.All(&cli.EnvSettings{}))
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var cp string
|
|
cp, err = client.ChartPathOptions.LocateChart(chartURL, settings)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
m := &downloader.Manager{
|
|
Out: os.Stdout,
|
|
ChartPath: cp,
|
|
Keyring: client.ChartPathOptions.Keyring,
|
|
SkipUpdate: false,
|
|
Getters: getter.All(settings),
|
|
RepositoryConfig: settings.RepositoryConfig,
|
|
RepositoryCache: settings.RepositoryCache,
|
|
Debug: settings.Debug,
|
|
}
|
|
|
|
dl := downloader.ChartDownloader{
|
|
Out: m.Out,
|
|
Verify: m.Verify,
|
|
Keyring: m.Keyring,
|
|
RepositoryConfig: m.RepositoryConfig,
|
|
RepositoryCache: m.RepositoryCache,
|
|
RegistryClient: m.RegistryClient,
|
|
Getters: m.Getters,
|
|
Options: []getter.Option{
|
|
getter.WithInsecureSkipVerifyTLS(false),
|
|
},
|
|
}
|
|
|
|
repoPath := filepath.Dir(m.ChartPath)
|
|
err = os.MkdirAll(repoPath, os.ModePerm)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
version := ""
|
|
if registry.IsOCI(chartURL) {
|
|
chartURL, version, err = parseOCIRef(chartURL)
|
|
if err != nil {
|
|
return
|
|
}
|
|
dl.Options = append(dl.Options,
|
|
getter.WithRegistryClient(m.RegistryClient),
|
|
getter.WithTagName(version))
|
|
}
|
|
|
|
log.Info().
|
|
Str("url", chartURL).
|
|
Str("repo-path", repoPath).
|
|
Msg("Downloading Helm chart:")
|
|
|
|
if _, _, err = dl.DownloadTo(chartURL, version, repoPath); err != nil {
|
|
return
|
|
}
|
|
|
|
chartPath = m.ChartPath
|
|
}
|
|
var chart *chart.Chart
|
|
chart, err = loader.Load(chartPath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
log.Info().
|
|
Str("release", chart.Metadata.Name).
|
|
Str("version", chart.Metadata.Version).
|
|
Strs("source", chart.Metadata.Sources).
|
|
Str("kube-version", chart.Metadata.KubeVersion).
|
|
Msg("Installing using Helm:")
|
|
|
|
var configMarshalled []byte
|
|
configMarshalled, err = json.Marshal(config.Config)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var configUnmarshalled map[string]interface{}
|
|
err = json.Unmarshal(configMarshalled, &configUnmarshalled)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
rel, err = client.Run(chart, configUnmarshalled)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (h *Helm) Uninstall() (resp *release.UninstallReleaseResponse, err error) {
|
|
kubeConfigPath := config.Config.KubeConfigPath()
|
|
actionConfig := new(action.Configuration)
|
|
if err = actionConfig.Init(kube.GetConfig(kubeConfigPath, "", h.releaseNamespace), h.releaseNamespace, os.Getenv(ENV_HELM_DRIVER), func(format string, v ...interface{}) {
|
|
log.Info().Msgf(format, v...)
|
|
}); err != nil {
|
|
return
|
|
}
|
|
|
|
client := action.NewUninstall(actionConfig)
|
|
|
|
resp, err = client.Run(h.releaseName)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|