Skip to content

Commit

Permalink
Fix Deployment await logic
Browse files Browse the repository at this point in the history
The Deployment await logic had a bug for the old `extensions/v1beta1`
apiVersion which was causing the await logic to erroneously pass for
change triggered rollouts, even if the Deployment was invalid.

For some reason, the resource client was defaulting to
the old apiVersion, even though recent versions were available on the
cluster. Updated the client to prefer newer apiVersions, and
fixed the buggy await logic related to that apiVersion.
  • Loading branch information
lblackstone committed Jul 23, 2019
1 parent 9dcb704 commit 48a6953
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
(https://github.com/pulumi/pulumi-kubernetes/pull/637).
- Use `opts` instead of `__opts__` and `resource_name` instead of `__name__` in Python SDK
(https://github.com/pulumi/pulumi-kubernetes/pull/639).
- Properly detect failed Deployment on rollout. (https://github.com/pulumi/pulumi-kubernetes/pull/646).

## 0.25.2 (July 11, 2019)

Expand Down
20 changes: 12 additions & 8 deletions pkg/await/apps_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,8 +405,9 @@ func (dia *deploymentInitAwaiter) processDeploymentEvent(event watch.Event) {
return
}

// extensions/v1beta1 does not include the "Progressing" status for rollouts.
progressingStatusUnavailable := dia.deployment.GetAPIVersion() == "extensions/v1beta1"
// extensions/v1beta1 does not include the "Progressing" status for rollouts, so handle that special case if
// that status is not found in the following check.
progressingStatusUnavailable := true

// Success occurs when the ReplicaSet of the `currentGeneration` is marked as available, and
// when the deployment is available.
Expand All @@ -416,10 +417,8 @@ func (dia *deploymentInitAwaiter) processDeploymentEvent(event watch.Event) {
continue
}

if progressingStatusUnavailable {
// Since we can't tell for sure from this version of the API, mark as available.
dia.replicaSetAvailable = true
} else if condition["type"] == "Progressing" {
if condition["type"] == "Progressing" {
progressingStatusUnavailable = false
isProgressing := condition["status"] == trueStatus
if !isProgressing {
rawReason, hasReason := condition["reason"]
Expand Down Expand Up @@ -460,6 +459,11 @@ func (dia *deploymentInitAwaiter) processDeploymentEvent(event watch.Event) {
}
}

// Since we can't tell for sure from this version of the API, mark ReplicaSet as available.
if progressingStatusUnavailable {
dia.replicaSetAvailable = true
}

dia.checkReplicaSetStatus()
dia.checkPersistentVolumeClaimStatus()
}
Expand Down Expand Up @@ -541,10 +545,10 @@ func (dia *deploymentInitAwaiter) checkReplicaSetStatus() {

if dia.changeTriggeredRollout() {
dia.updatedReplicaSetReady = lastGeneration != dia.currentGeneration && updatedReplicaSetCreated &&
readyReplicasExists && readyReplicas >= int64(specReplicas)
readyReplicasExists && readyReplicas >= specReplicas
} else {
dia.updatedReplicaSetReady = updatedReplicaSetCreated &&
readyReplicasExists && readyReplicas >= int64(specReplicas)
readyReplicasExists && readyReplicas >= specReplicas
}

if !dia.updatedReplicaSetReady {
Expand Down
39 changes: 30 additions & 9 deletions pkg/clients/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"strings"

"github.com/pulumi/pulumi-kubernetes/pkg/kinds"
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery"
Expand Down Expand Up @@ -116,22 +117,42 @@ func (dcs *DynamicClientSet) gvkForKind(kind kinds.Kind) (*schema.GroupVersionKi
}
}

var fallbackResourceList *v1.APIResourceList
for _, gvResources := range resources {
for _, resource := range gvResources.APIResources {
if resource.Kind == string(kind) {
var gv schema.GroupVersion
gv, err = schema.ParseGroupVersion(gvResources.GroupVersion)
if err != nil {
return nil, err
}
return &schema.GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: resource.Kind}, nil
}
// For some reason, the server is returning the old "extensions/v1beta1" GV before "apps/v1", so manually
// skip it and fallback to it if the Kind is not found.
if gvResources.GroupVersion == "extensions/v1beta1" {
fallbackResourceList = gvResources
continue
}
versionKind, err, done := dcs.searchKindInGVResources(gvResources, kind, err)
if done {
return versionKind, err
}
}

versionKind, err, done := dcs.searchKindInGVResources(fallbackResourceList, kind, err)
if done {
return versionKind, err
}

return nil, fmt.Errorf("failed to find gvk for Kind: %q", kind)
}

func (dcs *DynamicClientSet) searchKindInGVResources(gvResources *v1.APIResourceList, kind kinds.Kind, err error) (*schema.GroupVersionKind, error, bool) {
for _, resource := range gvResources.APIResources {
if resource.Kind == string(kind) {
var gv schema.GroupVersion
gv, err = schema.ParseGroupVersion(gvResources.GroupVersion)
if err != nil {
return nil, err, true
}
return &schema.GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: resource.Kind}, nil, true
}
}
return nil, nil, false
}

func (dcs *DynamicClientSet) IsNamespacedKind(gvk schema.GroupVersionKind) (bool, error) {
gv := gvk.GroupVersion().String()
if strings.Contains(gv, "core/v1") {
Expand Down

0 comments on commit 48a6953

Please sign in to comment.