woodpecker-helm3/internal/helm/plan.go

167 lines
3.4 KiB
Go
Raw Normal View History

2019-12-09 17:56:02 +00:00
package helm
import (
"fmt"
2019-12-09 17:56:02 +00:00
"github.com/pelotech/drone-helm3/internal/run"
"os"
2019-12-09 17:56:02 +00:00
)
const (
kubeConfigTemplate = "/root/.kube/config.tpl"
kubeConfigFile = "/root/.kube/config"
)
// A Step is one step in the plan.
2019-12-09 17:56:02 +00:00
type Step interface {
Prepare(run.Config) error
Execute(run.Config) error
2019-12-09 17:56:02 +00:00
}
// A Plan is a series of steps to perform.
2019-12-09 17:56:02 +00:00
type Plan struct {
steps []Step
cfg Config
runCfg run.Config
2019-12-09 17:56:02 +00:00
}
// NewPlan makes a plan for running a helm operation.
2019-12-09 17:56:02 +00:00
func NewPlan(cfg Config) (*Plan, error) {
p := Plan{
cfg: cfg,
runCfg: run.Config{
Debug: cfg.Debug,
Values: cfg.Values,
StringValues: cfg.StringValues,
ValuesFiles: cfg.ValuesFiles,
Namespace: cfg.Namespace,
Stdout: cfg.Stdout,
Stderr: cfg.Stderr,
},
}
p.steps = (*determineSteps(cfg))(cfg)
for i, step := range p.steps {
if cfg.Debug {
fmt.Fprintf(os.Stderr, "calling %T.Prepare (step %d)\n", step, i)
}
if err := step.Prepare(p.runCfg); err != nil {
err = fmt.Errorf("while preparing %T step: %w", step, err)
2019-12-09 17:56:02 +00:00
return nil, err
}
}
return &p, nil
}
// determineSteps is primarily for the tests' convenience: it allows testing the "which stuff should
// we do" logic without building a config that meets all the steps' requirements.
func determineSteps(cfg Config) *func(Config) []Step {
switch cfg.Command {
case "upgrade":
return &upgrade
case "uninstall", "delete":
return &uninstall
2019-12-09 17:56:02 +00:00
case "lint":
return &lint
2019-12-09 17:56:02 +00:00
case "help":
return &help
2019-12-09 17:56:02 +00:00
default:
switch cfg.DroneEvent {
case "push", "tag", "deployment", "pull_request", "promote", "rollback":
return &upgrade
case "delete":
return &uninstall
2019-12-09 17:56:02 +00:00
default:
panic("not implemented")
2019-12-09 17:56:02 +00:00
}
}
}
// Execute runs each step in the plan, aborting and reporting on error
2019-12-09 17:56:02 +00:00
func (p *Plan) Execute() error {
for i, step := range p.steps {
if p.cfg.Debug {
fmt.Fprintf(p.cfg.Stderr, "calling %T.Execute (step %d)\n", step, i)
}
if err := step.Execute(p.runCfg); err != nil {
return fmt.Errorf("while executing %T step: %w", step, err)
2019-12-09 17:56:02 +00:00
}
}
return nil
}
var upgrade = func(cfg Config) []Step {
steps := initKube(cfg)
if cfg.UpdateDependencies {
steps = append(steps, depUpdate(cfg)...)
}
steps = append(steps, &run.Upgrade{
Chart: cfg.Chart,
Release: cfg.Release,
ChartVersion: cfg.ChartVersion,
DryRun: cfg.DryRun,
Wait: cfg.Wait,
ReuseValues: cfg.ReuseValues,
Timeout: cfg.Timeout,
Force: cfg.Force,
})
2019-12-09 17:56:02 +00:00
return steps
2019-12-09 17:56:02 +00:00
}
var uninstall = func(cfg Config) []Step {
steps := initKube(cfg)
if cfg.UpdateDependencies {
steps = append(steps, depUpdate(cfg)...)
}
steps = append(steps, &run.Uninstall{
Release: cfg.Release,
DryRun: cfg.DryRun,
})
return steps
}
var lint = func(cfg Config) []Step {
steps := make([]Step, 0)
if cfg.UpdateDependencies {
steps = append(steps, depUpdate(cfg)...)
}
steps = append(steps, &run.Lint{
Chart: cfg.Chart,
})
return steps
}
var help = func(cfg Config) []Step {
help := &run.Help{}
return []Step{help}
}
func initKube(cfg Config) []Step {
return []Step{
&run.InitKube{
SkipTLSVerify: cfg.SkipTLSVerify,
Certificate: cfg.Certificate,
APIServer: cfg.APIServer,
ServiceAccount: cfg.ServiceAccount,
Token: cfg.KubeToken,
TemplateFile: kubeConfigTemplate,
ConfigFile: kubeConfigFile,
},
}
}
func depUpdate(cfg Config) []Step {
return []Step{
&run.DepUpdate{
Chart: cfg.Chart,
},
}
}