Skip to content

Commit

Permalink
Merge pull request #14 from pamiel/wait-deployed
Browse files Browse the repository at this point in the history
Bugfixes on "waiting for Liveness and Readiness" step
  • Loading branch information
jroucheton authored Feb 14, 2019
2 parents 7480081 + 67ac62c commit 88cf79e
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 142 deletions.
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)
}

0 comments on commit 88cf79e

Please sign in to comment.