Commit 7cbed3f7 authored by Taylor Thomas's avatar Taylor Thomas Committed by GitHub

Merge pull request #2143 from kiich/deploymentsReady-when-newRS-has-minimumReplicas

Trigger deployment as success when new replicaSet has reached min you need
parents eb4a187d 85a91394
...@@ -172,7 +172,7 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command { ...@@ -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.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.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.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 return cmd
} }
......
...@@ -80,7 +80,7 @@ func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command { ...@@ -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.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.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.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 return cmd
} }
......
...@@ -116,7 +116,7 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command { ...@@ -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.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.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.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") f.MarkDeprecated("disable-hooks", "use --no-hooks instead")
......
...@@ -353,11 +353,15 @@ is not a full list of cli flags. To see a description of all flags, just run ...@@ -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 - `--timeout`: A value in seconds to wait for Kubernetes commands to complete
This defaults to 300 (5 minutes) 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 Services have and IP address (and Ingress if a `LoadBalancer`) before
marking the release as successful. It will wait for as long as the 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 `--timeout` value. If timeout is reached, the release will be marked as
`FAILED`. `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 - `--no-hooks`: This skips running hooks for the command
- `--recreate-pods` (only available for `upgrade` and `rollback`): This flag - `--recreate-pods` (only available for `upgrade` and `rollback`): This flag
will cause all pods to be recreated (with the exception of pods belonging to will cause all pods to be recreated (with the exception of pods belonging to
......
...@@ -34,10 +34,12 @@ import ( ...@@ -34,10 +34,12 @@ import (
apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1" apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1"
batchinternal "k8s.io/kubernetes/pkg/apis/batch" batchinternal "k8s.io/kubernetes/pkg/apis/batch"
batch "k8s.io/kubernetes/pkg/apis/batch/v1" batch "k8s.io/kubernetes/pkg/apis/batch/v1"
ext "k8s.io/kubernetes/pkg/apis/extensions"
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1" extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
conditions "k8s.io/kubernetes/pkg/client/unversioned" conditions "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util"
"k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
...@@ -59,6 +61,12 @@ type Client struct { ...@@ -59,6 +61,12 @@ type Client struct {
SchemaCacheDir string SchemaCacheDir string
} }
// deployment holds associated replicaSets for a deployment
type deployment struct {
replicaSets *ext.ReplicaSet
deployment *ext.Deployment
}
// New create a new Client // New create a new Client
func New(config clientcmd.ClientConfig) *Client { func New(config clientcmd.ClientConfig) *Client {
return &Client{ return &Client{
...@@ -550,6 +558,15 @@ func volumesReady(vols []api.PersistentVolumeClaim) bool { ...@@ -550,6 +558,15 @@ func volumesReady(vols []api.PersistentVolumeClaim) bool {
return true 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) { func getPods(client *internalclientset.Clientset, namespace string, selector map[string]string) ([]api.Pod, error) {
list, err := client.Pods(namespace).List(api.ListOptions{ list, err := client.Pods(namespace).List(api.ListOptions{
FieldSelector: fields.Everything(), FieldSelector: fields.Everything(),
...@@ -578,6 +595,8 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error { ...@@ -578,6 +595,8 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
pods := []api.Pod{} pods := []api.Pod{}
services := []api.Service{} services := []api.Service{}
pvc := []api.PersistentVolumeClaim{} pvc := []api.PersistentVolumeClaim{}
replicaSets := []*ext.ReplicaSet{}
deployments := []deployment{}
for _, v := range created { for _, v := range created {
obj, err := c.AsVersionedObject(v.Object) obj, err := c.AsVersionedObject(v.Object)
if err != nil && !runtime.IsNotRegisteredError(err) { if err != nil && !runtime.IsNotRegisteredError(err) {
...@@ -605,13 +624,25 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error { ...@@ -605,13 +624,25 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
if err != nil { if err != nil {
return false, err return false, err
} }
for _, r := range rs.Items {
list, err := getPods(client, value.Namespace, r.Spec.Selector.MatchLabels) for i := range rs.Items {
if err != nil { replicaSets = append(replicaSets, &rs.Items[i])
return false, err }
}
pods = append(pods, list...) 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): case (*extensions.DaemonSet):
list, err := getPods(client, value.Namespace, value.Spec.Selector.MatchLabels) list, err := getPods(client, value.Namespace, value.Spec.Selector.MatchLabels)
if err != nil { if err != nil {
...@@ -644,7 +675,7 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error { ...@@ -644,7 +675,7 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
services = append(services, *svc) services = append(services, *svc)
} }
} }
return podsReady(pods) && servicesReady(services) && volumesReady(pvc), nil return podsReady(pods) && servicesReady(services) && volumesReady(pvc) && deploymentsReady(deployments), nil
}) })
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment