174 lines
5.5 KiB
Go
174 lines
5.5 KiB
Go
package kubernetes
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"k8s.io/client-go/pkg/api/v1"
|
|
"k8s.io/client-go/pkg/apis/extensions/v1beta1"
|
|
|
|
"github.com/rusenask/keel/types"
|
|
"github.com/rusenask/keel/util/image"
|
|
|
|
"github.com/rusenask/keel/util/version"
|
|
|
|
log "github.com/Sirupsen/logrus"
|
|
)
|
|
|
|
func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy types.PolicyType, repo *types.Repository, deployment v1beta1.Deployment) (updated v1beta1.Deployment, shouldUpdateDeployment bool, err error) {
|
|
eventRepoRef, err := image.Parse(repo.Name)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
labels := deployment.GetLabels()
|
|
|
|
log.WithFields(log.Fields{
|
|
"labels": labels,
|
|
"name": deployment.Name,
|
|
"namespace": deployment.Namespace,
|
|
"policy": policy,
|
|
}).Info("provider.kubernetes.checkVersionedDeployment: keel policy found, checking deployment...")
|
|
|
|
shouldUpdateDeployment = false
|
|
|
|
for idx, c := range deployment.Spec.Template.Spec.Containers {
|
|
// Remove version if any
|
|
// containerImageName := versionreg.ReplaceAllString(c.Image, "")
|
|
|
|
conatinerImageRef, err := image.Parse(c.Image)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"error": err,
|
|
"image_name": c.Image,
|
|
}).Error("provider.kubernetes: failed to parse image name")
|
|
continue
|
|
}
|
|
|
|
log.WithFields(log.Fields{
|
|
"name": deployment.Name,
|
|
"namespace": deployment.Namespace,
|
|
"parsed_image_name": conatinerImageRef.Remote(),
|
|
"target_image_name": repo.Name,
|
|
"target_tag": repo.Tag,
|
|
"policy": policy,
|
|
"image": c.Image,
|
|
}).Info("provider.kubernetes: checking image")
|
|
|
|
if conatinerImageRef.Repository() != eventRepoRef.Repository() {
|
|
log.WithFields(log.Fields{
|
|
"parsed_image_name": conatinerImageRef.Remote(),
|
|
"target_image_name": repo.Name,
|
|
}).Info("provider.kubernetes: images do not match, ignoring")
|
|
continue
|
|
}
|
|
|
|
// if policy is force, don't bother with version checking
|
|
// same with `latest` images, update them to versioned ones
|
|
if policy == types.PolicyTypeForce || conatinerImageRef.Tag() == "latest" {
|
|
c = updateContainer(c, conatinerImageRef, newVersion.String())
|
|
|
|
deployment.Spec.Template.Spec.Containers[idx] = c
|
|
|
|
// marking this deployment for update
|
|
shouldUpdateDeployment = true
|
|
// updating digest if available
|
|
annotations := deployment.GetAnnotations()
|
|
|
|
if repo.Digest != "" {
|
|
// annotations[types.KeelDigestAnnotation+"/"+conatinerImageRef.Remote()] = repo.Digest
|
|
}
|
|
annotations = addImageToPull(annotations, c.Image)
|
|
|
|
deployment.SetAnnotations(annotations)
|
|
log.WithFields(log.Fields{
|
|
"parsed_image": conatinerImageRef.Remote(),
|
|
"raw_image_name": c.Image,
|
|
"target_image": repo.Name,
|
|
"target_image_tag": repo.Tag,
|
|
"policy": policy,
|
|
}).Info("provider.kubernetes: impacted deployment container found")
|
|
|
|
// success, moving to next container
|
|
continue
|
|
}
|
|
|
|
currentVersion, err := version.GetVersionFromImageName(c.Image)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"error": err,
|
|
"container_image": c.Image,
|
|
"container_image_tag": conatinerImageRef.Tag(),
|
|
"keel_policy": policy,
|
|
}).Error("provider.kubernetes: failed to get image version, is it tagged as semver?")
|
|
continue
|
|
}
|
|
|
|
log.WithFields(log.Fields{
|
|
"labels": labels,
|
|
"name": deployment.Name,
|
|
"namespace": deployment.Namespace,
|
|
"image": c.Image,
|
|
"current_version": currentVersion.String(),
|
|
"policy": policy,
|
|
}).Info("provider.kubernetes: current image version")
|
|
|
|
shouldUpdateContainer, err := version.ShouldUpdate(currentVersion, newVersion, policy)
|
|
if err != nil {
|
|
log.WithFields(log.Fields{
|
|
"error": err,
|
|
"new_version": newVersion.String(),
|
|
"current_version": currentVersion.String(),
|
|
"keel_policy": policy,
|
|
}).Error("provider.kubernetes: got error while checking whether deployment should be updated")
|
|
continue
|
|
}
|
|
|
|
log.WithFields(log.Fields{
|
|
"labels": labels,
|
|
"name": deployment.Name,
|
|
"namespace": deployment.Namespace,
|
|
"image": c.Image,
|
|
"current_version": currentVersion.String(),
|
|
"new_version": newVersion.String(),
|
|
"policy": policy,
|
|
"should_update": shouldUpdateContainer,
|
|
}).Info("provider.kubernetes: checked version, deciding whether to update")
|
|
|
|
if shouldUpdateContainer {
|
|
c = updateContainer(c, conatinerImageRef, newVersion.String())
|
|
deployment.Spec.Template.Spec.Containers[idx] = c
|
|
// marking this deployment for update
|
|
shouldUpdateDeployment = true
|
|
|
|
// updating annotations
|
|
annotations := deployment.GetAnnotations()
|
|
// updating digest if available
|
|
if repo.Digest != "" {
|
|
// annotations[types.KeelDigestAnnotation+"/"+conatinerImageRef.Remote()] = repo.Digest
|
|
}
|
|
deployment.SetAnnotations(annotations)
|
|
|
|
log.WithFields(log.Fields{
|
|
"parsed_image": conatinerImageRef.Remote(),
|
|
"raw_image_name": c.Image,
|
|
"target_image": repo.Name,
|
|
"target_image_tag": repo.Tag,
|
|
"policy": policy,
|
|
}).Info("provider.kubernetes: impacted deployment container found")
|
|
}
|
|
}
|
|
|
|
return deployment, shouldUpdateDeployment, nil
|
|
}
|
|
|
|
func updateContainer(container v1.Container, ref *image.Reference, version string) v1.Container {
|
|
// updating image
|
|
if ref.Registry() == image.DefaultRegistryHostname {
|
|
container.Image = fmt.Sprintf("%s:%s", ref.ShortName(), version)
|
|
} else {
|
|
container.Image = fmt.Sprintf("%s:%s", ref.Repository(), version)
|
|
}
|
|
|
|
return container
|
|
}
|