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

fix: handle failure during upgrade #31

Merged
merged 11 commits into from
Jan 3, 2024
Merged
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
2 changes: 1 addition & 1 deletion internal/cli/local/setup/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,5 +131,5 @@ func runSetup(cmd *cobra.Command, args []string) error {
Override: chartLocation,
}

return chart.InstallOrUpgrade(cmd.Context(), chartConfig, helmOptions)
return chart.Install(cmd.Context(), chartConfig, helmOptions)
}
14 changes: 9 additions & 5 deletions internal/cli/local/upgrade/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"strings"
"time"

"github.com/spf13/cobra"

Expand Down Expand Up @@ -64,15 +65,18 @@ func runUpgrade(cmd *cobra.Command, args []string) error {
}
}

err := k3s.Upgrade(cmd.Context(), config.K3S)
err := k3s.Upgrade(cmd.Context(), k3s.UpgradeConfig{Debug: config.Debug})
if err != nil {
return err
}

if len(k3sImportConfig.ImagePaths) == 0 {
err = k3s.ImportBundleImages(cmd.Context(), k3sImportConfig.FailFast)
time.Sleep(5 * time.Second) // wait for k3s to be ready

// in debug mode we don't do fail-fast
if len(config.Images.ImportPaths) == 0 {
err = k3s.ImportBundleImages(cmd.Context(), !config.Debug)
} else {
err = k3s.ImportImages(cmd.Context(), k3sImportConfig.ImagePaths, k3sImportConfig.FailFast)
err = k3s.ImportImages(cmd.Context(), config.Images.ImportPaths, !config.Debug)
}

if err != nil {
Expand Down Expand Up @@ -119,5 +123,5 @@ func runUpgrade(cmd *cobra.Command, args []string) error {
Override: chartLocation,
}

return chart.InstallOrUpgrade(cmd.Context(), chartConfig, helmOptions)
return chart.Upgrade(cmd.Context(), chartConfig, helmOptions, config.Debug)
}
18 changes: 7 additions & 11 deletions internal/cli/local/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"github.com/weka/gohomecli/internal/cli/app/hooks"
"github.com/weka/gohomecli/internal/install/bundle"
"github.com/weka/gohomecli/internal/install/k3s"
"github.com/weka/gohomecli/internal/install/web"
"github.com/weka/gohomecli/internal/utils"
)
Expand All @@ -19,19 +18,17 @@ var config struct {
Web bool
WebBindAddr string
BundlePath string
K3S k3s.UpgradeConfig
Chart struct {
Images struct {
ImportPaths []string
}
Chart struct {
kubeConfigPath string
localChart string
jsonConfig string
remoteDownload bool
remoteVersion string
}
}

var k3sImportConfig struct {
ImagePaths []string
FailFast bool
Debug bool
}

var upgradeCmd = &cobra.Command{
Expand All @@ -51,13 +48,12 @@ func init() {
}

upgradeCmd.Flags().StringVar(&config.BundlePath, "bundle", bundle.BundlePath(), "bundle directory with k3s package")
upgradeCmd.Flags().BoolVar(&config.K3S.Debug, "debug", false, "enable debug mode")
upgradeCmd.Flags().BoolVar(&config.Debug, "debug", false, "enable debug mode")

upgradeCmd.Flags().MarkHidden("bundle")
upgradeCmd.Flags().MarkHidden("debug")

upgradeCmd.Flags().BoolVar(&k3sImportConfig.FailFast, "fail-fast", false, "fail on first error")
upgradeCmd.Flags().StringSliceVarP(&k3sImportConfig.ImagePaths, "image-path", "f", nil, "images to import (if specified, bundle images are ignored)")
upgradeCmd.Flags().StringSliceVarP(&config.Images.ImportPaths, "image-path", "f", nil, "images to import (if specified, bundle images are ignored)")

upgradeCmd.Flags().StringVarP(&config.Chart.kubeConfigPath, "kube-config", "k", "/etc/rancher/k3s/k3s.yaml", "Path to kubeconfig file")
upgradeCmd.Flags().StringVarP(&config.Chart.localChart, "local-chart", "l", "", "Path to local chart directory/archive")
Expand Down
176 changes: 176 additions & 0 deletions internal/install/chart/chart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package chart

import (
"fmt"
"os"
"path/filepath"
"time"

helmclient "github.com/mittwald/go-helm-client"
"gopkg.in/yaml.v3"
"helm.sh/helm/v3/pkg/repo"

"github.com/weka/gohomecli/internal/install/bundle"
"github.com/weka/gohomecli/internal/utils"
)

const (
ReleaseName = "wekahome"
ReleaseNamespace = "home-weka-io"
RepositoryURL = "https://weka.github.io/gohome"
RepositoryName = "wekahome"
ChartName = "wekahome"
)

var ErrUnableToFindChart = fmt.Errorf("unable to determine chart location")

var logger = utils.GetLogger("HelmChart")

type LocationOverride struct {
Path string // path to chart package
RemoteDownload bool // download from remote repository
Version string // version of the chart to download from remote repository
}

type HelmOptions struct {
KubeConfig []byte // path or content of kubeconfig file
Override *LocationOverride // override chart package location
KubeContext string // kubeconfig context to use
NamespaceOverride string // override namespace for release
}

// Configuration flat options for the chart, pointers are used to distinguish between empty and unset values
type Configuration struct {
Host *string `json:"host"` // ingress host
TLS *bool `json:"tls"` // ingress tls enabled
TLSCert *string `json:"tlsCert"` // ingress tls cert
TLSKey *string `json:"tlsKey"` // ingress tls key

SMTPHost *string `json:"smtpHost"` // smtp server host
SMTPPort *int `json:"smtpPort"` // smtp server port
SMTPUser *string `json:"smtpUser"` // smtp server user
SMTPPassword *string `json:"smtpPassword"` // smtp server password
SMTPInsecure *bool `json:"smtpInsecure"` // smtp insecure connection
SMTPSender *string `json:"smtpSender"` // smtp sender name
SMTPSenderEmail *string `json:"smtpSenderEmail"` // smtp sender email

DiagnosticsRetentionDays *int `json:"diagnosticsRetentionDays"` // diagnostics retention days
EventsRetentionDays *int `json:"eventsRetentionDays"` // events retention days

ForwardingEnabled bool `json:"forwardingEnabled"` // forwarding enabled
ForwardingUrl *string `json:"forwardingUrl"` // forwarding url override
ForwardingEnableEvents *bool `json:"forwardingEnableEvents"` // forwarding enable events
ForwardingEnableUsageReports *bool `json:"forwardingEnableUsageReports"` // forwarding enable usage reports
ForwardingEnableAnalytics *bool `json:"forwardingEnableAnalytics"` // forwarding enable analytics
ForwardingEnableDiagnostics *bool `json:"forwardingEnableDiagnostics"` // forwarding enable diagnostics
ForwardingEnableStats *bool `json:"forwardingEnableStats"` // forwarding enable stats
ForwardingEnableClusterRegistration *bool `json:"forwardingEnableClusterRegistration"` // forwarding enable cluster registration

Autoscaling bool `json:"autoscaling"` // enable services autoscaling
WekaNodesServed *int `json:"wekaNodesMonitored"` // number of weka nodes to monitor, controls load preset
}

func chartSpec(client helmclient.Client, cfg *Configuration, opts *HelmOptions) (*helmclient.ChartSpec, error) {
namespace := ReleaseNamespace
if opts.NamespaceOverride != "" {
namespace = opts.NamespaceOverride
}

logger.Debug().
Interface("locationOverride", opts.Override).
Msg("Determining chart location")
chartLocation, err := getChartLocation(client, opts)
if err != nil {
return nil, err
}

logger.Debug().
Interface("configuration", cfg).
Msg("Generating chart values")

values, err := generateValuesV3(cfg)
if err != nil {
return nil, err
}

valuesYaml, err := yaml.Marshal(values)
if err != nil {
return nil, fmt.Errorf("failed serializing values yaml: %w", err)
}
logger.Debug().Msgf("Generated values:\n %s", string(valuesYaml))

chartVersion := "" // any available
if opts.Override != nil {
chartVersion = opts.Override.Version
}
return &helmclient.ChartSpec{
ReleaseName: ReleaseName,
ChartName: chartLocation,
Version: chartVersion,
Namespace: namespace,
ValuesYaml: string(valuesYaml),
CreateNamespace: true,
ResetValues: true,
Wait: true,
WaitForJobs: true,
Timeout: time.Minute * 5,
}, nil
}

func findBundledChart() (string, error) {
path := ""

err := bundle.Walk("", func(name string, info os.FileInfo, err error) error {
if err != nil {
return err
}

if path != "" {
return nil
}

matched, err := filepath.Match("wekahome-*.tgz", info.Name())
if err != nil {
return err
}

if matched {
path = name
}

return nil
})

if err != nil || path == "" {
return "", fmt.Errorf("unable to find wekahome chart in bundle")
}

return path, nil
}

func getChartLocation(client helmclient.Client, opts *HelmOptions) (string, error) {
var chartLocation string

if opts.Override != nil && opts.Override.RemoteDownload {
err := client.AddOrUpdateChartRepo(repo.Entry{
Name: RepositoryName,
URL: RepositoryURL,
})
if err != nil {
return "", fmt.Errorf("failed adding chart repo: %w", err)
}

chartLocation = fmt.Sprintf("%s/%s", RepositoryName, ChartName)
return chartLocation, nil
}

if opts.Override != nil && opts.Override.Path != "" {
return opts.Override.Path, nil
}

if bundle.IsBundled() {
return findBundledChart()
}

return "", ErrUnableToFindChart
}
32 changes: 0 additions & 32 deletions internal/install/chart/configuration.go

This file was deleted.

Loading
Loading