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

Bugfixes on "waiting for Liveness and Readiness" step #14

Merged
merged 1 commit into from
Feb 14, 2019
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
206 changes: 103 additions & 103 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,26 @@ import (
)

type sprayCmd struct {
chartName string
chartVersion string
targets []string
namespace string
resetValues bool
reuseValues bool
valueFiles []string
valuesSet string
force bool
dryRun bool
debug bool
chartName string
chartVersion string
targets []string
namespace string
resetValues bool
reuseValues bool
valueFiles []string
valuesSet string
force bool
dryRun bool
debug bool
}

// Dependency ...
type Dependency struct {
Name string
Alias string
UsedName string
Targeted bool
Weight int
Name string
Alias string
UsedName string
Targeted bool
Weight int
}

var (
Expand Down Expand Up @@ -94,10 +94,10 @@ func newSprayCmd(args []string) *cobra.Command {
p := &sprayCmd{}

cmd := &cobra.Command{
Use: "helm spray [CHART]",
Short: `Helm plugin to upgrade subcharts from an umbrella chart`,
Long: globalUsage,
SilenceUsage: true,
Use: "helm spray [CHART]",
Short: `Helm plugin to upgrade subcharts from an umbrella chart`,
Long: globalUsage,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {

if len(args) != 1 {
Expand Down Expand Up @@ -136,12 +136,12 @@ func newSprayCmd(args []string) *cobra.Command {
f.BoolVar(&p.debug, "debug", false, "enable verbose output")
f.Parse(args)

// When called through helm, debug mode is transmitted through the HELM_DEBUG envvar
if !p.debug {
if "1" == os.Getenv("HELM_DEBUG") {
p.debug = true
}
}
// When called through helm, debug mode is transmitted through the HELM_DEBUG envvar
if !p.debug {
if "1" == os.Getenv("HELM_DEBUG") {
p.debug = true
}
}

return cmd

Expand Down Expand Up @@ -170,30 +170,30 @@ func (p *sprayCmd) spray() error {
dependencies := make([]Dependency, len(reqs.Dependencies))

for i, req := range reqs.Dependencies {
// Dependency name and alias
// Dependency name and alias
dependencies[i].Name = req.Name
dependencies[i].Alias = req.Alias
if req.Alias == "" {
dependencies[i].UsedName = dependencies[i].Name
} else {
dependencies[i].UsedName = dependencies[i].Alias
}

// Is dependency targeted? If --target is specificed, it should match the name of the current dependency;
// if no --target is specified, then all dependencies are targeted
if len(p.targets) > 0 {
dependencies[i].Targeted = false
for j := range p.targets {
if p.targets[j] == dependencies[i].UsedName {
dependencies[i].Targeted = true
}
}
} else {
dependencies[i].Targeted = true
}

// Get weight of the dependency. If no weight is specified, setting it to 0
dependencies[i].Weight = 0
if req.Alias == "" {
dependencies[i].UsedName = dependencies[i].Name
} else {
dependencies[i].UsedName = dependencies[i].Alias
}

// Is dependency targeted? If --target is specificed, it should match the name of the current dependency;
// if no --target is specified, then all dependencies are targeted
if len(p.targets) > 0 {
dependencies[i].Targeted = false
for j := range p.targets {
if p.targets[j] == dependencies[i].UsedName {
dependencies[i].Targeted = true
}
}
} else {
dependencies[i].Targeted = true
}

// Get weight of the dependency. If no weight is specified, setting it to 0
dependencies[i].Weight = 0
depi, err := values.Table(dependencies[i].UsedName)
if (err == nil && depi["weight"] != nil) {
w64 := depi["weight"].(float64)
Expand All @@ -206,72 +206,72 @@ func (p *sprayCmd) spray() error {
}

// For debug...
if p.debug {
if p.debug {
for _, dependency := range dependencies {
if dependency.Alias == "" {
fmt.Printf("[spray] subchart: \"%s\" | targeted: %t | weight: %d\n", dependency.Name, dependency.Targeted, dependency.Weight)
} else {
fmt.Printf("[spray] subchart: \"%s\" (is alias of: \"%s\") | targeted: %t | weight: %d\n", dependency.Alias, dependency.Name, dependency.Targeted, dependency.Weight)
}
if dependency.Alias == "" {
fmt.Printf("[spray] subchart: \"%s\" | targeted: %t | weight: %d\n", dependency.Name, dependency.Targeted, dependency.Weight)
} else {
fmt.Printf("[spray] subchart: \"%s\" (is alias of: \"%s\") | targeted: %t | weight: %d\n", dependency.Alias, dependency.Name, dependency.Targeted, dependency.Weight)
}
}
}
}

for i := 0; i <= getMaxWeight(dependencies); i++ {
shouldWait := false
shouldWait := false

// Upgrade the current (targeted) Deployments, following the increasing weight
// Upgrade the current (targeted) Deployments, following the increasing weight
for _, dependency := range dependencies {
if dependency.Targeted {
if dependency.Weight == i {
fmt.Println("[spray] upgrading release: \"" + dependency.UsedName + "\"...")
shouldWait = true

// Add the "<dependency>.enabled" flags to ensure that only the current chart is to be executed
valuesSet := ""
for _, dep := range dependencies {
if dep.UsedName == dependency.UsedName {
valuesSet = valuesSet + dep.UsedName + ".enabled=true,"
} else {
valuesSet = valuesSet + dep.UsedName + ".enabled=false,"
}
}
valuesSet = valuesSet + p.valuesSet

// Upgrade the Deployment
helm.UpgradeWithValues(p.namespace, dependency.UsedName, dependency.UsedName, p.chartName, p.resetValues, p.reuseValues, p.valueFiles, valuesSet, p.force, p.dryRun, p.debug)

if !p.dryRun {
status := helm.GetHelmStatus(dependency.UsedName)
if status != "DEPLOYED" {
os.Exit(1)
}
}

fmt.Println("[spray] release: \"" + dependency.UsedName + "\" upgraded")
}
}
if dependency.Targeted {
if dependency.Weight == i {
fmt.Println("[spray] upgrading release: \"" + dependency.UsedName + "\"...")
shouldWait = true

// Add the "<dependency>.enabled" flags to ensure that only the current chart is to be executed
valuesSet := ""
for _, dep := range dependencies {
if dep.UsedName == dependency.UsedName {
valuesSet = valuesSet + dep.UsedName + ".enabled=true,"
} else {
valuesSet = valuesSet + dep.UsedName + ".enabled=false,"
}
}
valuesSet = valuesSet + p.valuesSet

// Upgrade the Deployment
helm.UpgradeWithValues(p.namespace, dependency.UsedName, dependency.UsedName, p.chartName, p.resetValues, p.reuseValues, p.valueFiles, valuesSet, p.force, p.dryRun, p.debug)

if !p.dryRun {
status := helm.GetHelmStatus(dependency.UsedName)
if status != "DEPLOYED" {
os.Exit(1)
}
}

fmt.Println("[spray] release: \"" + dependency.UsedName + "\" upgraded")
}
}
}

// Wait availability of the Deployment just upgraded
if shouldWait {
fmt.Println("[spray] waiting for Liveness and Readiness...")

if !p.dryRun {
for _, dependency := range dependencies {
if i > 0 && dependency.Weight == i {
for {
if kubectl.IsDeploymentUpToDate(dependency.UsedName, p.namespace) {
break
}
time.Sleep(5 * time.Second)
}
}
}
}
// Wait availability of the Deployment just upgraded
if shouldWait {
fmt.Println("[spray] waiting for Liveness and Readiness...")

if !p.dryRun {
for _, dependency := range dependencies {
if dependency.Weight == i && dependency.Targeted == true {
for {
if kubectl.IsDeploymentUpToDate(dependency.UsedName, p.namespace) {
break
}
time.Sleep(5 * time.Second)
}
}
}
}
}
}

fmt.Println("[spray] upgrade completed.")
fmt.Println("[spray] upgrade completed.")

return nil
}
Expand Down
70 changes: 35 additions & 35 deletions pkg/helm/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,39 +97,39 @@ func Delete(chart string, dryRun bool) {
// UpgradeWithValues ...
func UpgradeWithValues(namespace string, release string, chartName string, chartPath string, resetValues bool, reuseValues bool, valueFiles []string, valuesSet string, force bool, dryRun bool, debug bool) {
var myargs []string = []string{"upgrade", "--install", release, chartPath, "--namespace", namespace, "--set", valuesSet}
for _, v := range valueFiles {
myargs = append(myargs, "-f")
myargs = append(myargs, v)
}
for _, v := range valueFiles {
myargs = append(myargs, "-f")
myargs = append(myargs, v)
}

if resetValues {
myargs = append(myargs, "--reset-values")
}
if resetValues {
myargs = append(myargs, "--reset-values")
}

if reuseValues {
myargs = append(myargs, "--reuse-values")
}
if reuseValues {
myargs = append(myargs, "--reuse-values")
}

if force {
myargs = append(myargs, "--force")
}
if force {
myargs = append(myargs, "--force")
}

if dryRun {
myargs = append(myargs, "--dry-run")
}
myargs = append(myargs, "--dry-run")
}

if debug {
myargs = append(myargs, "--debug")
fmt.Printf("[spray] running helm command for \"%s\": %v\n", release, myargs)
}
if debug {
myargs = append(myargs, "--debug")
fmt.Printf("[spray] running helm command for \"%s\": %v\n", release, myargs)
}

cmd := exec.Command("helm", myargs...)
if debug {
cmd.Stdout = os.Stdout
} else {
cmdOutput := &bytes.Buffer{}
cmd.Stdout = cmdOutput
}
if debug {
cmd.Stdout = os.Stdout
} else {
cmdOutput := &bytes.Buffer{}
cmd.Stdout = cmdOutput
}
cmd.Stderr = os.Stderr

if err := cmd.Run(); err != nil {
Expand All @@ -148,18 +148,18 @@ func Upgrade(namespace string, chart string, chartPath string, valuesSet string,
myargs = []string{"upgrade", "--install", "--namespace", namespace, "--set", chart + ".enabled=true," + valuesSet, chart, chartPath}
}

if debug {
myargs = append(myargs, "--debug")
fmt.Printf("[spray] running command: %v\n", myargs)
}
if debug {
myargs = append(myargs, "--debug")
fmt.Printf("[spray] running command: %v\n", myargs)
}

cmd := exec.Command("helm", myargs...)
if debug {
cmd.Stdout = os.Stdout
} else {
cmdOutput := &bytes.Buffer{}
cmd.Stdout = cmdOutput
}
if debug {
cmd.Stdout = os.Stdout
} else {
cmdOutput := &bytes.Buffer{}
cmd.Stdout = cmdOutput
}
cmd.Stderr = os.Stderr

if err := cmd.Run(); err != nil {
Expand Down
10 changes: 6 additions & 4 deletions pkg/kubectl/kubectl.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ package kubectl

import (
"fmt"
"log"
"os"
"os/exec"
)
Expand Down Expand Up @@ -90,23 +89,26 @@ func IsStatefulSetUpToDate(deployment string, namespace string) bool {
func getDesired(k8stype string, namespace string, deployment string) string {
desired, err := exec.Command("kubectl", "--namespace", namespace, "get", k8stype, deployment, "-o=jsonpath='{.spec.replicas}'").Output()
if err != nil {
log.Fatal(err)
// Cannot make the difference between an error when calling kubectl and no corresponding resource found. Return "0" in any case.
return "0"
}
return string(desired)
}

func getReady(k8stype string, namespace string, deployment string) string {
ready, err := exec.Command("kubectl", "--namespace", namespace, "get", k8stype, deployment, "-o=jsonpath='{.status.readyReplicas}'").Output()
if err != nil {
log.Fatal(err)
// Cannot make the difference between an error when calling kubectl and no corresponding resource found. Return "0" in any case.
return "0"
}
return string(ready)
}

func getUpdated(k8stype string, namespace string, deployment string) string {
updated, err := exec.Command("kubectl", "--namespace", namespace, "get", k8stype, deployment, "-o=jsonpath='{.status.updatedReplicas}'").Output()
if err != nil {
log.Fatal(err)
// Cannot make the difference between an error when calling kubectl and no corresponding resource found. Return "0" in any case.
return "0"
}
return string(updated)
}