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

Trigger deployment as success when new replicaSet has reached min you need #2143

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/helm/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command {
f.StringVar(&inst.keyring, "keyring", defaultKeyring(), "location of public keys used for verification")
f.StringVar(&inst.version, "version", "", "specify the exact chart version to install. If this is not specified, the latest version is installed")
f.Int64Var(&inst.timeout, "timeout", 300, "time in seconds to wait for any individual kubernetes operation (like Jobs for hooks)")
f.BoolVar(&inst.wait, "wait", false, "if set, will wait until all Pods, PVCs, and Services are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.BoolVar(&inst.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")

return cmd
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/helm/rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command {
f.BoolVar(&rollback.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable")
f.BoolVar(&rollback.disableHooks, "no-hooks", false, "prevent hooks from running during rollback")
f.Int64Var(&rollback.timeout, "timeout", 300, "time in seconds to wait for any individual kubernetes operation (like Jobs for hooks)")
f.BoolVar(&rollback.wait, "wait", false, "if set, will wait until all Pods, PVCs, and Services are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.BoolVar(&rollback.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")

return cmd
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/helm/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command {
f.Int64Var(&upgrade.timeout, "timeout", 300, "time in seconds to wait for any individual kubernetes operation (like Jobs for hooks)")
f.BoolVar(&upgrade.resetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart")
f.BoolVar(&upgrade.reuseValues, "reuse-values", false, "when upgrading, reuse the last release's values, and merge in any new values. If '--reset-values' is specified, this is ignored.")
f.BoolVar(&upgrade.wait, "wait", false, "if set, will wait until all Pods, PVCs, and Services are in a ready state before marking the release as successful. It will wait for as long as --timeout")
f.BoolVar(&upgrade.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")

f.MarkDeprecated("disable-hooks", "use --no-hooks instead")

Expand Down
6 changes: 5 additions & 1 deletion docs/using_helm.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,11 +353,15 @@ is not a full list of cli flags. To see a description of all flags, just run

- `--timeout`: A value in seconds to wait for Kubernetes commands to complete
This defaults to 300 (5 minutes)
- `--wait`: Waits until all Pods are in a ready state, PVCs are bound, and
- `--wait`: Waits until all Pods are in a ready state, PVCs are bound, Deployments
have minimum (`Desired` minus `maxUnavailable`) Pods in ready state and
Services have and IP address (and Ingress if a `LoadBalancer`) before
marking the release as successful. It will wait for as long as the
`--timeout` value. If timeout is reached, the release will be marked as
`FAILED`.

Note: In scenario where Deployment has `replicas` set to 1 and `maxUnavailable` is not set to 0 as part of rolling
update strategy, `--wait` will return as ready as it has satisfied the minimum Pod in ready condition.
- `--no-hooks`: This skips running hooks for the command
- `--recreate-pods` (only available for `upgrade` and `rollback`): This flag
will cause all pods to be recreated (with the exception of pods belonging to
Expand Down
45 changes: 38 additions & 7 deletions pkg/kube/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ import (
apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1"
batchinternal "k8s.io/kubernetes/pkg/apis/batch"
batch "k8s.io/kubernetes/pkg/apis/batch/v1"
ext "k8s.io/kubernetes/pkg/apis/extensions"
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
conditions "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
Expand All @@ -59,6 +61,12 @@ type Client struct {
SchemaCacheDir string
}

// deployment holds associated replicaSets for a deployment
type deployment struct {
replicaSets *ext.ReplicaSet
deployment *ext.Deployment
}

// New create a new Client
func New(config clientcmd.ClientConfig) *Client {
return &Client{
Expand Down Expand Up @@ -550,6 +558,15 @@ func volumesReady(vols []api.PersistentVolumeClaim) bool {
return true
}

func deploymentsReady(deployments []deployment) bool {
for _, v := range deployments {
if !(v.replicaSets.Status.ReadyReplicas >= v.deployment.Spec.Replicas-deploymentutil.MaxUnavailable(*v.deployment)) {
return false
}
}
return true
}

func getPods(client *internalclientset.Clientset, namespace string, selector map[string]string) ([]api.Pod, error) {
list, err := client.Pods(namespace).List(api.ListOptions{
FieldSelector: fields.Everything(),
Expand Down Expand Up @@ -578,6 +595,8 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
pods := []api.Pod{}
services := []api.Service{}
pvc := []api.PersistentVolumeClaim{}
replicaSets := []*ext.ReplicaSet{}
deployments := []deployment{}
for _, v := range created {
obj, err := c.AsVersionedObject(v.Object)
if err != nil && !runtime.IsNotRegisteredError(err) {
Expand Down Expand Up @@ -605,13 +624,25 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
if err != nil {
return false, err
}
for _, r := range rs.Items {
list, err := getPods(client, value.Namespace, r.Spec.Selector.MatchLabels)
if err != nil {
return false, err
}
pods = append(pods, list...)

for i := range rs.Items {
replicaSets = append(replicaSets, &rs.Items[i])
}

currentDeployment, err := client.Deployments(value.Namespace).Get(value.Name)
if err != nil {
return false, err
}
// Find RS associated with deployment
newReplicaSet, err := deploymentutil.FindNewReplicaSet(currentDeployment, replicaSets)
if err != nil {
return false, err
}
newDeployment := deployment{
newReplicaSet,
currentDeployment,
}
deployments = append(deployments, newDeployment)
case (*extensions.DaemonSet):
list, err := getPods(client, value.Namespace, value.Spec.Selector.MatchLabels)
if err != nil {
Expand Down Expand Up @@ -644,7 +675,7 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
services = append(services, *svc)
}
}
return podsReady(pods) && servicesReady(services) && volumesReady(pvc), nil
return podsReady(pods) && servicesReady(services) && volumesReady(pvc) && deploymentsReady(deployments), nil
})
}

Expand Down