diff --git a/provider/kubernetes/kubernetes.go b/provider/kubernetes/kubernetes.go index 816f309b3..01903fece 100644 --- a/provider/kubernetes/kubernetes.go +++ b/provider/kubernetes/kubernetes.go @@ -70,11 +70,22 @@ type UpdatePlan struct { CurrentVersion string // New version that's already in the deployment NewVersion string + + // Current version with digest + CurrentVersionFull string + // New version with digest + NewVersionFull string } func (p *UpdatePlan) String() string { if p.Resource != nil { - return fmt.Sprintf("%s %s->%s", p.Resource.Identifier, p.CurrentVersion, p.NewVersion) + // Sometimes only a digest is updated, by a tag stays the same. Then saying latest -> latest + // doesn't tell us much + if p.CurrentVersion == p.NewVersion { + return fmt.Sprintf("%s %s->%s", p.Resource.Identifier, p.CurrentVersionFull, p.NewVersionFull) + } else { + return fmt.Sprintf("%s %s->%s", p.Resource.Identifier, p.CurrentVersion, p.NewVersion) + } } return "empty plan" } @@ -295,7 +306,7 @@ func (p *Provider) updateDeployments(plans []*UpdatePlan) (updated []*k8s.Generi ResourceKind: resource.Kind(), Identifier: resource.Identifier, Name: "preparing to update resource", - Message: fmt.Sprintf("Preparing to update %s %s/%s %s->%s (%s)", resource.Kind(), resource.Namespace, resource.Name, plan.CurrentVersion, plan.NewVersion, strings.Join(resource.GetImages(), ", ")), + Message: fmt.Sprintf("Preparing to update %s %s/%s %s->%s (%s)", resource.Kind(), resource.Namespace, resource.Name, plan.CurrentVersionFull, plan.NewVersionFull, strings.Join(resource.GetImages(), ", ")), CreatedAt: time.Now(), Type: types.NotificationPreDeploymentUpdate, Level: types.LevelDebug, @@ -310,7 +321,7 @@ func (p *Provider) updateDeployments(plans []*UpdatePlan) (updated []*k8s.Generi var err error timestamp := time.Now().Format(time.RFC3339) - annotations["kubernetes.io/change-cause"] = fmt.Sprintf("keel automated update, version %s -> %s [%s]", plan.CurrentVersion, plan.NewVersion, timestamp) + annotations["kubernetes.io/change-cause"] = fmt.Sprintf("keel automated update, version %s -> %s [%s]", plan.CurrentVersionFull, plan.NewVersionFull, timestamp) resource.SetAnnotations(annotations) @@ -329,7 +340,7 @@ func (p *Provider) updateDeployments(plans []*UpdatePlan) (updated []*k8s.Generi Name: "update resource", ResourceKind: resource.Kind(), Identifier: resource.Identifier, - Message: fmt.Sprintf("%s %s/%s update %s->%s failed, error: %s", resource.Kind(), resource.Namespace, resource.Name, plan.CurrentVersion, plan.NewVersion, err), + Message: fmt.Sprintf("%s %s/%s update %s->%s failed, error: %s", resource.Kind(), resource.Namespace, resource.Name, plan.CurrentVersionFull, plan.NewVersionFull, err), CreatedAt: time.Now(), Type: types.NotificationDeploymentUpdate, Level: types.LevelError, @@ -357,9 +368,9 @@ func (p *Provider) updateDeployments(plans []*UpdatePlan) (updated []*k8s.Generi var msg string releaseNotes := types.ParseReleaseNotesURL(resource.GetAnnotations()) if releaseNotes != "" { - msg = fmt.Sprintf("Successfully updated %s %s/%s %s->%s (%s). Release notes: %s", resource.Kind(), resource.Namespace, resource.Name, plan.CurrentVersion, plan.NewVersion, strings.Join(resource.GetImages(), ", "), releaseNotes) + msg = fmt.Sprintf("Successfully updated %s %s/%s %s->%s (%s). Release notes: %s", resource.Kind(), resource.Namespace, resource.Name, plan.CurrentVersionFull, plan.NewVersionFull, strings.Join(resource.GetImages(), ", "), releaseNotes) } else { - msg = fmt.Sprintf("Successfully updated %s %s/%s %s->%s (%s)", resource.Kind(), resource.Namespace, resource.Name, plan.CurrentVersion, plan.NewVersion, strings.Join(resource.GetImages(), ", ")) + msg = fmt.Sprintf("Successfully updated %s %s/%s %s->%s (%s)", resource.Kind(), resource.Namespace, resource.Name, plan.CurrentVersionFull, plan.NewVersionFull, strings.Join(resource.GetImages(), ", ")) } err = p.sender.Send(types.EventNotification{ @@ -382,8 +393,8 @@ func (p *Provider) updateDeployments(plans []*UpdatePlan) (updated []*k8s.Generi "error": err, "name": resource.Name, "kind": resource.Kind(), - "previous": plan.CurrentVersion, - "new": plan.NewVersion, + "previous": plan.CurrentVersionFull, + "new": plan.NewVersionFull, "namespace": resource.Namespace, }).Error("provider.kubernetes: got error while sending notification") } @@ -391,8 +402,8 @@ func (p *Provider) updateDeployments(plans []*UpdatePlan) (updated []*k8s.Generi log.WithFields(log.Fields{ "name": resource.Name, "kind": resource.Kind(), - "previous": plan.CurrentVersion, - "new": plan.NewVersion, + "previous": plan.CurrentVersionFull, + "new": plan.NewVersionFull, "namespace": resource.Namespace, }).Info("provider.kubernetes: resource updated") updated = append(updated, resource) diff --git a/provider/kubernetes/kubernetes_test.go b/provider/kubernetes/kubernetes_test.go index 5586c9934..ebf5f8dc0 100644 --- a/provider/kubernetes/kubernetes_test.go +++ b/provider/kubernetes/kubernetes_test.go @@ -314,10 +314,10 @@ func TestGetImpactedInit(t *testing.T) { { meta_v1.TypeMeta{}, meta_v1.ObjectMeta{ - Name: "dep-1", - Namespace: "xxxx", + Name: "dep-1", + Namespace: "xxxx", Annotations: map[string]string{types.KeelInitContainerAnnotation: "true"}, - Labels: map[string]string{types.KeelPolicyLabel: "all"}, + Labels: map[string]string{types.KeelPolicyLabel: "all"}, }, apps_v1.DeploymentSpec{ Template: v1.PodTemplateSpec{ @@ -335,10 +335,10 @@ func TestGetImpactedInit(t *testing.T) { { meta_v1.TypeMeta{}, meta_v1.ObjectMeta{ - Name: "dep-2", - Namespace: "xxxx", + Name: "dep-2", + Namespace: "xxxx", Annotations: map[string]string{types.KeelInitContainerAnnotation: "false"}, - Labels: map[string]string{"whatever": "all"}, + Labels: map[string]string{"whatever": "all"}, }, apps_v1.DeploymentSpec{ Template: v1.PodTemplateSpec{ diff --git a/provider/kubernetes/updates.go b/provider/kubernetes/updates.go index 44583ddbc..1464134e6 100644 --- a/provider/kubernetes/updates.go +++ b/provider/kubernetes/updates.go @@ -86,6 +86,8 @@ func checkForUpdate(plc policy.Policy, repo *types.Repository, resource *k8s.Gen updatePlan.CurrentVersion = containerImageRef.Tag() updatePlan.NewVersion = repo.Tag + updatePlan.CurrentVersionFull = fmt.Sprintf("%s:%s", containerImageRef.Tag(), repo.Digest) + updatePlan.NewVersionFull = fmt.Sprintf("%s:%s", repo.Tag, repo.NewDigest) updatePlan.Resource = resource } } @@ -147,6 +149,8 @@ func checkForUpdate(plc policy.Policy, repo *types.Repository, resource *k8s.Gen updatePlan.CurrentVersion = containerImageRef.Tag() updatePlan.NewVersion = repo.Tag + updatePlan.CurrentVersionFull = fmt.Sprintf("%s:%s", containerImageRef.Tag(), repo.Digest) + updatePlan.NewVersionFull = fmt.Sprintf("%s:%s", repo.Tag, repo.NewDigest) updatePlan.Resource = resource } diff --git a/trigger/poll/single_tag_watcher.go b/trigger/poll/single_tag_watcher.go index 562a71ad4..038aa0e8c 100644 --- a/trigger/poll/single_tag_watcher.go +++ b/trigger/poll/single_tag_watcher.go @@ -67,9 +67,10 @@ func (j *WatchTagJob) Run() { event := types.Event{ Repository: types.Repository{ - Name: j.details.trackedImage.Image.Repository(), - Tag: j.details.trackedImage.Image.Tag(), - Digest: currentDigest, + Name: j.details.trackedImage.Image.Repository(), + Tag: j.details.trackedImage.Image.Tag(), + Digest: currentDigest, + NewDigest: j.details.digest, }, TriggerName: types.TriggerTypePoll.String(), } diff --git a/types/types.go b/types/types.go index 10595d494..1c1e62634 100644 --- a/types/types.go +++ b/types/types.go @@ -77,10 +77,11 @@ func init() { // Repository - represents main docker repository fields that // keel cares about type Repository struct { - Host string `json:"host"` - Name string `json:"name"` - Tag string `json:"tag"` - Digest string `json:"digest"` // optional digest field + Host string `json:"host"` + Name string `json:"name"` + Tag string `json:"tag"` + Digest string `json:"digest"` // optional digest field + NewDigest string `json:"new_digest"` // optional field for new digest } // String gives you [host/]team/repo[:tag] identifier