Skip to content

Commit

Permalink
Merge pull request #11 from GuessWhoSamFoo/upgrade-values
Browse files Browse the repository at this point in the history
Add editor tab to upgrade release values
  • Loading branch information
Sam Foo authored Apr 26, 2021
2 parents ad0f6f3 + 5dcf663 commit 4f418be
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 4 deletions.
13 changes: 12 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
SHELL = /bin/bash

PLUGIN_NAME=octant-helm

ifdef XDG_CONFIG_HOME
OCTANT_PLUGIN_DIR ?= ${XDG_CONFIG_HOME}/octant/plugins
else ifeq ($(OS),Windows_NT)
OCTANT_PLUGIN_DIR ?= ${LOCALAPPDATA}/octant/plugins
else
OCTANT_PLUGIN_DIR ?= ${HOME}/.config/octant/plugins
endif

.PHONY: build
build:
go build -o bin/octant-helm cmd/octant-helm/main.go
@go build -o bin/$(PLUGIN_NAME) cmd/octant-helm/main.go
@cp bin/$(PLUGIN_NAME) $(OCTANT_PLUGIN_DIR)/$(PLUGIN_NAME)

.PHONY: dev
dev:
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
helm.sh/helm/v3 v3.4.2
k8s.io/api v0.19.4
k8s.io/apimachinery v0.19.4
sigs.k8s.io/yaml v1.2.0
)

replace (
Expand Down
50 changes: 50 additions & 0 deletions pkg/plugin/actions/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ package actions
import (
"fmt"
"github.com/bloodorangeio/octant-helm/pkg/config"
"github.com/bloodorangeio/octant-helm/pkg/helm"
"github.com/vmware-tanzu/octant/pkg/action"
"github.com/vmware-tanzu/octant/pkg/plugin/service"
"github.com/vmware-tanzu/octant/pkg/store"
helmAction "helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chartutil"
"k8s.io/apimachinery/pkg/labels"
)

const (
UpdateHelmReleaseValues = "octant-helm.dev/update"
UninstallHelmReleaseAction = "octant-helm.dev/uninstall"
)

Expand All @@ -30,6 +35,16 @@ func ActionHandler(request *service.ActionRequest) error {
return err
}
return uninstallRelease(request, actionConfig, releaseName)
case UpdateHelmReleaseValues:
releaseValues, err := request.Payload.String("update")
if err != nil {
return err
}
releaseName, err := request.Payload.String("releaseName")
if err != nil {
return err
}
return updateReleaseValues(request, actionConfig, releaseValues, releaseName)
default:
return fmt.Errorf("unable to find handler for plugin: %s", "octant-helm")
}
Expand All @@ -46,3 +61,38 @@ func uninstallRelease(request *service.ActionRequest, config *helmAction.Configu
request.DashboardClient.SendAlert(request.Context(), request.ClientState.ClientID, alert)
return nil
}

func updateReleaseValues(request *service.ActionRequest, config *helmAction.Configuration, values string, releaseName string) error {
upgradeClient := helmAction.NewUpgrade(config)

client := request.DashboardClient
ul, err := client.List(request.Context(), store.Key{
APIVersion: "v1",
Kind: "Secret",
Selector: &labels.Set{
"owner": "helm",
"name": releaseName,
},
})
if err != nil {
return err
}
r := helm.UnstructuredListToHelmReleaseByName(ul, releaseName)
if r == nil {
return fmt.Errorf("cannot find release name: %s", releaseName)
}
v, err := chartutil.ReadValues([]byte(values))
if err != nil {
return err
}
// TODO: There are upgrades which require secrets. How would this be shown to a user?
release, err := upgradeClient.Run(releaseName, r.Chart, v)
if err != nil {
message := fmt.Sprintf("Unable to upgrade release: %s", err)
request.DashboardClient.SendAlert(request.Context(), request.ClientState.ClientID, action.CreateAlert(action.AlertTypeError, message, action.DefaultAlertExpiration))
} else {
alert := action.CreateAlert(action.AlertTypeInfo, "Upgrade helm release: "+release.Name, action.DefaultAlertExpiration)
request.DashboardClient.SendAlert(request.Context(), request.ClientState.ClientID, alert)
}
return nil
}
7 changes: 6 additions & 1 deletion pkg/plugin/router/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ func helmReleaseHandler(request service.Request) (component.ContentResponse, err
if err != nil {
return component.EmptyContentResponse, err
}
helmEditorView, err := views.BuildHelmReleaseViewForValues(request)
if err != nil {
return component.EmptyContentResponse, err
}

response := component.NewContentResponse(title)
response.Add(helmReleaseView)
response.Add(helmReleaseView, helmEditorView)
return *response, nil
}
1 change: 1 addition & 0 deletions pkg/plugin/settings/capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func GetCapabilities() *plugin.Capabilities {
return &plugin.Capabilities{
ActionNames: []string{
actions.UninstallHelmReleaseAction,
actions.UpdateHelmReleaseValues,
},
IsModule: true,
}
Expand Down
60 changes: 58 additions & 2 deletions pkg/plugin/views/helm_release.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ package views // import "github.com/bloodorangeio/octant-helm/pkg/plugin/views"
import (
"fmt"
"github.com/bloodorangeio/octant-helm/pkg/config"
"github.com/bloodorangeio/octant-helm/pkg/plugin/actions"
helmAction "helm.sh/helm/v3/pkg/action"
//"helm.sh/helm/v3/pkg/chartutil"
"sigs.k8s.io/yaml"

//"helm.sh/helm/v3/pkg/cli"
"log"
"strconv"
"strings"
Expand Down Expand Up @@ -92,7 +97,7 @@ func BuildHelmReleaseViewForRequest(request service.Request) (component.Componen
"Revision": component.NewText(strconv.Itoa(h.Version)),
"Updated": component.NewTimestamp(h.Info.LastDeployed.Time),
"Status": component.NewText(h.Info.Status.String()),
"Chart": component.NewText(fmt.Sprintf("%s-%s", h.Name, h.Chart.Metadata.Version)),
"Chart": component.NewText(fmt.Sprintf("%s-%s", h.Chart.Metadata.Name, h.Chart.Metadata.Version)),
"App Version": component.NewText(appVersion),
"Description": component.NewText(h.Info.Description),
})
Expand All @@ -102,7 +107,8 @@ func BuildHelmReleaseViewForRequest(request service.Request) (component.Componen
notesBody := component.NewMarkdownText(fmt.Sprintf("```\n%s\n```", strings.TrimSpace(r.Info.Notes)))
notesCard.SetBody(notesBody)

flexLayout := component.NewFlexLayout("")
flexLayout := component.NewFlexLayout("Summary")
flexLayout.SetAccessor("summary")
flexLayout.AddSections(component.FlexLayoutSection{
{Width: component.WidthHalf, View: statusSummary},
{Width: component.WidthFull, View: historyTable},
Expand All @@ -111,3 +117,53 @@ func BuildHelmReleaseViewForRequest(request service.Request) (component.Componen

return flexLayout, title, nil
}

func BuildHelmReleaseViewForValues(request service.Request) (component.Component, error) {
releaseName := strings.TrimPrefix(request.Path(), "/")
client := request.DashboardClient()
ul, err := client.List(request.Context(), store.Key{
APIVersion: "v1",
Kind: "Secret",
Selector: &labels.Set{
"owner": "helm",
"name": releaseName,
},
})
if err != nil {
return component.NewError(component.TitleFromString("Cannot list Helm releases: "), err), nil
}

r := helm.UnstructuredListToHelmReleaseByName(ul, releaseName)
if r == nil {
return component.NewText("Error: release not found"), nil
}


actionConfig, err := config.NewActionConfig(request.ClientState().Namespace)
if err != nil {
return component.NewError(component.TitleFromString("Create Helm config: "), err), nil
}
valuesClient := helmAction.NewGetValues(actionConfig)
values, err := valuesClient.Run(r.Name)
if err != nil {
return component.NewError(component.TitleFromString("Get values: "), err), nil
}

// No user supplied values so show all supplied defaults instead
if len(values) == 0 {
values = r.Chart.Values
}
v, err := yaml.Marshal(values)
if err != nil {
return component.NewError(component.TitleFromString("Error"), err), nil
}

editor := component.NewEditor(component.TitleFromString("Values"), string(v), false)
editor.Config.Language = "yaml"
editor.Config.Metadata = map[string]string{
"releaseName": releaseName,
}
editor.SetAccessor("chart")
editor.Config.SubmitAction = actions.UpdateHelmReleaseValues
return editor, nil
}

0 comments on commit 4f418be

Please sign in to comment.