Skip to content

Commit

Permalink
Add / Upgrade / Remove extensions via websocket (#1651)
Browse files Browse the repository at this point in the history
  • Loading branch information
sgalsaleh authored Dec 19, 2024
1 parent 1c27b97 commit 3ce063d
Show file tree
Hide file tree
Showing 5 changed files with 279 additions and 54 deletions.
97 changes: 62 additions & 35 deletions pkg/extensions/extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import (
"context"
"sort"

k0sv1beta1 "github.com/k0sproject/k0s/pkg/apis/k0s/v1beta1"
"github.com/pkg/errors"
ecv1beta1 "github.com/replicatedhq/embedded-cluster/kinds/apis/v1beta1"
"github.com/replicatedhq/embedded-cluster/pkg/config"
"github.com/replicatedhq/embedded-cluster/pkg/helm"
"github.com/replicatedhq/embedded-cluster/pkg/spinner"
"github.com/replicatedhq/embedded-cluster/pkg/versions"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
helmrepo "helm.sh/helm/v3/pkg/repo"
)

func Install(ctx context.Context) error {
Expand All @@ -30,24 +29,8 @@ func Install(ctx context.Context) error {
return errors.Wrap(err, "create helm client")
}

for _, k0sRepo := range config.AdditionalRepositories() {
logrus.Debugf("Adding helm repository %s", k0sRepo.Name)

helmRepo := &helmrepo.Entry{
Name: k0sRepo.Name,
URL: k0sRepo.URL,
Username: k0sRepo.Username,
Password: k0sRepo.Password,
CertFile: k0sRepo.CertFile,
KeyFile: k0sRepo.KeyFile,
CAFile: k0sRepo.CAFile,
}
if k0sRepo.Insecure != nil {
helmRepo.InsecureSkipTLSverify = *k0sRepo.Insecure
}
if err := hcli.AddRepo(helmRepo); err != nil {
return errors.Wrapf(err, "add helm repository %s", k0sRepo.Name)
}
if err := addRepos(hcli, config.AdditionalRepositories()); err != nil {
return errors.Wrap(err, "add additional helm repositories")
}

// sort by order first
Expand All @@ -59,22 +42,66 @@ func Install(ctx context.Context) error {
for _, ext := range sorted {
loading.Infof("Installing %s", ext.Name)

var values map[string]interface{}
if err := yaml.Unmarshal([]byte(ext.Values), &values); err != nil {
return errors.Wrap(err, "unmarshal values")
if err := install(ctx, hcli, ext); err != nil {
return errors.Wrap(err, "install extension")
}
}

_, err = hcli.Install(ctx, helm.InstallOptions{
ReleaseName: ext.Name,
ChartPath: ext.ChartName,
ChartVersion: ext.Version,
Values: values,
Namespace: ext.TargetNS,
Timeout: ext.Timeout.Duration,
})
if err != nil {
return errors.Wrap(err, "helm install")
}
return nil
}

func Add(ctx context.Context, repos []k0sv1beta1.Repository, ext ecv1beta1.Chart) error {
hcli, err := helm.NewHelm(helm.HelmOptions{
K0sVersion: versions.K0sVersion,
})
if err != nil {
return errors.Wrap(err, "create helm client")
}

if err := addRepos(hcli, repos); err != nil {
return errors.Wrap(err, "add repos")
}

if err := install(ctx, hcli, ext); err != nil {
return errors.Wrap(err, "install extension")
}

return nil
}

func Upgrade(ctx context.Context, repos []k0sv1beta1.Repository, ext ecv1beta1.Chart) error {
hcli, err := helm.NewHelm(helm.HelmOptions{
K0sVersion: versions.K0sVersion,
})
if err != nil {
return errors.Wrap(err, "create helm client")
}

if err := addRepos(hcli, repos); err != nil {
return errors.Wrap(err, "add repos")
}

if err := upgrade(ctx, hcli, ext); err != nil {
return errors.Wrap(err, "upgrade extension")
}

return nil
}

func Remove(ctx context.Context, repos []k0sv1beta1.Repository, ext ecv1beta1.Chart) error {
hcli, err := helm.NewHelm(helm.HelmOptions{
K0sVersion: versions.K0sVersion,
})
if err != nil {
return errors.Wrap(err, "create helm client")
}

if err := addRepos(hcli, repos); err != nil {
return errors.Wrap(err, "add repos")
}

if err := uninstall(ctx, hcli, ext); err != nil {
return errors.Wrap(err, "uninstall extension")
}

return nil
Expand Down
91 changes: 91 additions & 0 deletions pkg/extensions/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package extensions

import (
"context"

k0sv1beta1 "github.com/k0sproject/k0s/pkg/apis/k0s/v1beta1"
"github.com/pkg/errors"
ecv1beta1 "github.com/replicatedhq/embedded-cluster/kinds/apis/v1beta1"
"github.com/replicatedhq/embedded-cluster/pkg/helm"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
helmrepo "helm.sh/helm/v3/pkg/repo"
)

func addRepos(hcli *helm.Helm, repos []k0sv1beta1.Repository) error {
for _, r := range repos {
logrus.Debugf("Adding helm repository %s", r.Name)

helmRepo := &helmrepo.Entry{
Name: r.Name,
URL: r.URL,
Username: r.Username,
Password: r.Password,
CertFile: r.CertFile,
KeyFile: r.KeyFile,
CAFile: r.CAFile,
}
if r.Insecure != nil {
helmRepo.InsecureSkipTLSverify = *r.Insecure
}
if err := hcli.AddRepo(helmRepo); err != nil {
return errors.Wrapf(err, "add helm repository %s", r.Name)
}
}

return nil
}

func install(ctx context.Context, hcli *helm.Helm, ext ecv1beta1.Chart) error {
var values map[string]interface{}
if err := yaml.Unmarshal([]byte(ext.Values), &values); err != nil {
return errors.Wrap(err, "unmarshal values")
}

_, err := hcli.Install(ctx, helm.InstallOptions{
ReleaseName: ext.Name,
ChartPath: ext.ChartName,
ChartVersion: ext.Version,
Values: values,
Namespace: ext.TargetNS,
Timeout: ext.Timeout.Duration,
})
if err != nil {
return errors.Wrap(err, "helm install")
}

return nil
}

func upgrade(ctx context.Context, hcli *helm.Helm, ext ecv1beta1.Chart) error {
var values map[string]interface{}
if err := yaml.Unmarshal([]byte(ext.Values), &values); err != nil {
return errors.Wrap(err, "unmarshal values")
}

_, err := hcli.Upgrade(ctx, helm.UpgradeOptions{
ReleaseName: ext.Name,
ChartPath: ext.ChartName,
ChartVersion: ext.Version,
Values: values,
Namespace: ext.TargetNS,
Timeout: ext.Timeout.Duration,
})
if err != nil {
return errors.Wrap(err, "helm upgrade")
}

return nil
}

func uninstall(ctx context.Context, hcli *helm.Helm, ext ecv1beta1.Chart) error {
err := hcli.Uninstall(ctx, helm.UninstallOptions{
ReleaseName: ext.Name,
Namespace: ext.TargetNS,
})
if err != nil {
return errors.Wrap(err, "helm uninstall")
}

return nil
}
24 changes: 24 additions & 0 deletions pkg/helm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ type UpgradeOptions struct {
Force bool
}

type UninstallOptions struct {
ReleaseName string
Namespace string
}

type Helm struct {
tmpdir string
kversion *semver.Version
Expand Down Expand Up @@ -359,6 +364,25 @@ func (h *Helm) Upgrade(ctx context.Context, opts UpgradeOptions) (*release.Relea
return release, nil
}

func (h *Helm) Uninstall(ctx context.Context, opts UninstallOptions) error {
cfg, err := h.getActionCfg(opts.Namespace)
if err != nil {
return fmt.Errorf("get action configuration: %w", err)
}

client := action.NewUninstall(cfg)

if deadline, ok := ctx.Deadline(); ok {
client.Timeout = time.Until(deadline)
}

if _, err := client.Run(opts.ReleaseName); err != nil {
return fmt.Errorf("uninstall release: %w", err)
}

return nil
}

func (h *Helm) Render(releaseName string, chartPath string, values map[string]interface{}, namespace string) ([][]byte, error) {
cfg := &action.Configuration{}

Expand Down
15 changes: 8 additions & 7 deletions pkg/websocket/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,26 @@ import (
"github.com/sirupsen/logrus"
)

func reportUpgradeStarted(ctx context.Context, data map[string]string) {
if err := sendUpgradeReport(ctx, data, "running", ""); err != nil {
func reportStepStarted(ctx context.Context, data map[string]string) {
if err := sendStepReport(ctx, data, "running", ""); err != nil {
logrus.Errorf("failed to report upgrade started: %s", err.Error())
}
}

func reportUpgradeError(ctx context.Context, data map[string]string, errMsg string) {
if err := sendUpgradeReport(ctx, data, "failed", errMsg); err != nil {
func reportStepError(ctx context.Context, data map[string]string, errMsg string) {
logrus.Error(errMsg)
if err := sendStepReport(ctx, data, "failed", errMsg); err != nil {
logrus.Errorf("failed to report upgrade error: %s", err.Error())
}
}

func reportUpgradeSuccess(ctx context.Context, data map[string]string) {
if err := sendUpgradeReport(ctx, data, "complete", ""); err != nil {
func reportStepSuccess(ctx context.Context, data map[string]string) {
if err := sendStepReport(ctx, data, "complete", ""); err != nil {
logrus.Errorf("failed to report upgrade success: %s", err.Error())
}
}

func sendUpgradeReport(ctx context.Context, data map[string]string, status string, errMsg string) error {
func sendStepReport(ctx context.Context, data map[string]string, status string, errMsg string) error {
reportBody := map[string]string{
"versionLabel": data["versionLabel"],
"status": status,
Expand Down
Loading

0 comments on commit 3ce063d

Please sign in to comment.