using generic resource instead of deployment

feature/stateful_set
Karolis Rusenas 2018-04-17 08:53:43 +01:00
parent f927d56a00
commit 07566e4da5
3 changed files with 136 additions and 74 deletions

View File

@ -2,16 +2,16 @@ package kubernetes
import (
"fmt"
"time"
"k8s.io/api/extensions/v1beta1"
"github.com/keel-hq/keel/internal/k8s"
"github.com/keel-hq/keel/types"
"github.com/keel-hq/keel/util/image"
log "github.com/sirupsen/logrus"
)
func (p *Provider) checkUnversionedDeployment(policy types.PolicyType, repo *types.Repository, deployment v1beta1.Deployment) (updatePlan *UpdatePlan, shouldUpdateDeployment bool, err error) {
func (p *Provider) checkUnversionedDeployment(policy types.PolicyType, repo *types.Repository, resource *k8s.GenericResource) (updatePlan *UpdatePlan, shouldUpdateDeployment bool, err error) {
updatePlan = &UpdatePlan{}
eventRepoRef, err := image.Parse(repo.Name)
@ -19,22 +19,21 @@ func (p *Provider) checkUnversionedDeployment(policy types.PolicyType, repo *typ
return
}
labels := deployment.GetLabels()
labels := resource.GetLabels()
log.WithFields(log.Fields{
"labels": labels,
"name": deployment.Name,
"namespace": deployment.Namespace,
"name": resource.Name,
"namespace": resource.Namespace,
"kind": resource.Kind(),
"policy": policy,
}).Info("provider.kubernetes.checkVersionedDeployment: keel policy found, checking deployment...")
}).Info("provider.kubernetes.checkVersionedDeployment: keel policy found, checking resource...")
annotations := deployment.GetAnnotations()
annotations := resource.GetAnnotations()
shouldUpdateDeployment = false
for idx, c := range deployment.Spec.Template.Spec.Containers {
// Remove version if any
// containerImageName := versionreg.ReplaceAllString(c.Image, "")
// for idx, c := range deployment.Spec.Template.Spec.Containers {
for idx, c := range resource.Containers() {
containerImageRef, err := image.Parse(c.Image)
if err != nil {
log.WithFields(log.Fields{
@ -45,8 +44,9 @@ func (p *Provider) checkUnversionedDeployment(policy types.PolicyType, repo *typ
}
log.WithFields(log.Fields{
"name": deployment.Name,
"namespace": deployment.Namespace,
"name": resource.Name,
"namespace": resource.Namespace,
"kind": resource.Kind(),
"parsed_image_name": containerImageRef.Remote(),
"target_image_name": repo.Name,
"target_tag": repo.Tag,
@ -72,31 +72,35 @@ func (p *Provider) checkUnversionedDeployment(policy types.PolicyType, repo *typ
// updating image
if containerImageRef.Registry() == image.DefaultRegistryHostname {
c.Image = fmt.Sprintf("%s:%s", containerImageRef.ShortName(), repo.Tag)
// c.Image = fmt.Sprintf("%s:%s", containerImageRef.ShortName(), repo.Tag)
resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.ShortName(), repo.Tag))
} else {
c.Image = fmt.Sprintf("%s:%s", containerImageRef.Repository(), repo.Tag)
// c.Image = fmt.Sprintf("%s:%s", containerImageRef.Repository(), repo.Tag)
resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.Repository(), repo.Tag))
}
deployment.Spec.Template.Spec.Containers[idx] = c
// deployment.Spec.Template.Spec.Containers[idx] = c
// marking this deployment for update
shouldUpdateDeployment = true
// updating annotations
annotations := deployment.GetAnnotations()
annotations := resource.GetAnnotations()
// updating digest if available
if repo.Digest != "" {
// if repo.Digest != "" {
// annotations[types.KeelDigestAnnotation+"/"+containerImageRef.Remote()] = repo.Digest
}
// annotations[types.KeelDigestAnnotation+"/"+containerImageRef.Remote()] = repo.Digest
// }
// adding image for updates
annotations = addImageToPull(annotations, c.Image)
// annotations = addImageToPull(annotations, c.Image)
deployment.SetAnnotations(annotations)
annotations["keel.sh/update-time"] = time.Now().String()
resource.SetAnnotations(annotations)
updatePlan.CurrentVersion = containerImageRef.Tag()
updatePlan.NewVersion = repo.Tag
updatePlan.Deployment = deployment
updatePlan.Resource = resource
log.WithFields(log.Fields{
"parsed_image": containerImageRef.Remote(),

View File

@ -2,14 +2,13 @@ package kubernetes
import (
"fmt"
"time"
// "k8s.io/api/core/v1"
"k8s.io/api/core/v1"
// "k8s.io/api/extensions/v1beta1"
"k8s.io/api/extensions/v1beta1"
"github.com/keel-hq/keel/internal/k8s"
"github.com/keel-hq/keel/types"
"github.com/keel-hq/keel/util/image"
@ -19,7 +18,7 @@ import (
)
// func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy types.PolicyType, repo *types.Repository, deployment v1beta1.Deployment) (updated v1beta1.Deployment, shouldUpdateDeployment bool, err error) {
func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy types.PolicyType, repo *types.Repository, deployment v1beta1.Deployment) (updatePlan *UpdatePlan, shouldUpdateDeployment bool, err error) {
func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy types.PolicyType, repo *types.Repository, resource *k8s.GenericResource) (updatePlan *UpdatePlan, shouldUpdateDeployment bool, err error) {
updatePlan = &UpdatePlan{}
eventRepoRef, err := image.Parse(repo.Name)
@ -27,22 +26,24 @@ func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy ty
return
}
labels := deployment.GetLabels()
labels := resource.GetLabels()
log.WithFields(log.Fields{
"labels": labels,
"name": deployment.Name,
"namespace": deployment.Namespace,
"name": resource.Name,
"namespace": resource.Namespace,
"kind": resource.Kind(),
"policy": policy,
}).Info("provider.kubernetes.checkVersionedDeployment: keel policy found, checking deployment...")
}).Info("provider.kubernetes.checkVersionedDeployment: keel policy found, checking resource...")
shouldUpdateDeployment = false
for idx, c := range deployment.Spec.Template.Spec.Containers {
// for idx, c := range deployment.Spec.Template.Spec.Containers {
for idx, c := range resource.Containers() {
// Remove version if any
// containerImageName := versionreg.ReplaceAllString(c.Image, "")
conatinerImageRef, err := image.Parse(c.Image)
containerImageRef, err := image.Parse(c.Image)
if err != nil {
log.WithFields(log.Fields{
"error": err,
@ -52,18 +53,19 @@ func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy ty
}
log.WithFields(log.Fields{
"name": deployment.Name,
"namespace": deployment.Namespace,
"parsed_image_name": conatinerImageRef.Remote(),
"name": resource.Name,
"namespace": resource.Namespace,
"parsed_image_name": containerImageRef.Remote(),
"kind": resource.Kind(),
"target_image_name": repo.Name,
"target_tag": repo.Tag,
"policy": policy,
"image": c.Image,
}).Info("provider.kubernetes: checking image")
if conatinerImageRef.Repository() != eventRepoRef.Repository() {
if containerImageRef.Repository() != eventRepoRef.Repository() {
log.WithFields(log.Fields{
"parsed_image_name": conatinerImageRef.Remote(),
"parsed_image_name": containerImageRef.Remote(),
"target_image_name": repo.Name,
}).Info("provider.kubernetes: images do not match, ignoring")
continue
@ -71,33 +73,45 @@ func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy ty
// 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())
if policy == types.PolicyTypeForce || containerImageRef.Tag() == "latest" {
// c = updateContainer(c, conatinerImageRef, newVersion.String())
deployment.Spec.Template.Spec.Containers[idx] = c
if containerImageRef.Registry() == image.DefaultRegistryHostname {
// container.Image = fmt.Sprintf("%s:%s", ref.ShortName(), version)
resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.ShortName(), newVersion.String()))
} else {
// container.Image = fmt.Sprintf("%s:%s", ref.Repository(), version)
resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.Repository(), newVersion.String()))
}
// deployment.Spec.Template.Spec.Containers[idx] = c
// marking this deployment for update
shouldUpdateDeployment = true
// updating digest if available
annotations := deployment.GetAnnotations()
annotations := resource.GetAnnotations()
if repo.Digest != "" {
// annotations[types.KeelDigestAnnotation+"/"+conatinerImageRef.Remote()] = repo.Digest
}
annotations = addImageToPull(annotations, c.Image)
annotations["keel.sh/update-time"] = time.Now().String()
// if repo.Digest != "" {
// annotations[types.KeelDigestAnnotation+"/"+conatinerImageRef.Remote()] = repo.Digest
// }
// annotations = addImageToPull(annotations, c.Image)
deployment.SetAnnotations(annotations)
resource.SetAnnotations(annotations)
log.WithFields(log.Fields{
"parsed_image": conatinerImageRef.Remote(),
"parsed_image": containerImageRef.Remote(),
"raw_image_name": c.Image,
"target_image": repo.Name,
"target_image_tag": repo.Tag,
"policy": policy,
}).Info("provider.kubernetes: impacted deployment container found")
updatePlan.CurrentVersion = conatinerImageRef.Tag()
updatePlan.CurrentVersion = containerImageRef.Tag()
updatePlan.NewVersion = newVersion.Original
updatePlan.Deployment = deployment
updatePlan.Resource = resource
// success, moving to next container
continue
@ -108,7 +122,7 @@ func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy ty
log.WithFields(log.Fields{
"error": err,
"container_image": c.Image,
"container_image_tag": conatinerImageRef.Tag(),
"container_image_tag": containerImageRef.Tag(),
"keel_policy": policy,
}).Error("provider.kubernetes: failed to get image version, is it tagged as semver?")
continue
@ -116,8 +130,8 @@ func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy ty
log.WithFields(log.Fields{
"labels": labels,
"name": deployment.Name,
"namespace": deployment.Namespace,
"name": resource.Name,
"namespace": resource.Namespace,
"image": c.Image,
"current_version": currentVersion.String(),
"policy": policy,
@ -136,8 +150,8 @@ func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy ty
log.WithFields(log.Fields{
"labels": labels,
"name": deployment.Name,
"namespace": deployment.Namespace,
"name": resource.Name,
"namespace": resource.Namespace,
"image": c.Image,
"current_version": currentVersion.String(),
"new_version": newVersion.String(),
@ -146,25 +160,34 @@ func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy ty
}).Info("provider.kubernetes: checked version, deciding whether to update")
if shouldUpdateContainer {
c = updateContainer(c, conatinerImageRef, newVersion.String())
deployment.Spec.Template.Spec.Containers[idx] = c
// c = updateContainer(c, conatinerImageRef, newVersion.String())
if containerImageRef.Registry() == image.DefaultRegistryHostname {
resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.ShortName(), newVersion.String()))
} else {
resource.UpdateContainer(idx, fmt.Sprintf("%s:%s", containerImageRef.Repository(), newVersion.String()))
}
// deployment.Spec.Template.Spec.Containers[idx] = c
// marking this deployment for update
shouldUpdateDeployment = true
// updating annotations
annotations := deployment.GetAnnotations()
annotations := resource.GetAnnotations()
// updating digest if available
if repo.Digest != "" {
// annotations[types.KeelDigestAnnotation+"/"+conatinerImageRef.Remote()] = repo.Digest
}
deployment.SetAnnotations(annotations)
// if repo.Digest != "" {
// annotations[types.KeelDigestAnnotation+"/"+conatinerImageRef.Remote()] = repo.Digest
// }
annotations["keel.sh/update-time"] = time.Now().String()
resource.SetAnnotations(annotations)
updatePlan.CurrentVersion = currentVersion.Original
updatePlan.NewVersion = newVersion.Original
updatePlan.Deployment = deployment
updatePlan.Resource = resource
log.WithFields(log.Fields{
"parsed_image": conatinerImageRef.Remote(),
"parsed_image": containerImageRef.Remote(),
"raw_image_name": c.Image,
"target_image": repo.Name,
"target_image_tag": repo.Tag,
@ -176,13 +199,13 @@ func (p *Provider) checkVersionedDeployment(newVersion *types.Version, policy ty
return updatePlan, 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)
}
// 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
}
// return container
// }

View File

@ -25,6 +25,8 @@ func mustEncode(data string) string {
return base64.StdEncoding.EncodeToString([]byte(data))
}
var secretDockerConfigJSONPayloadWithUsernamePassword = `{"auths":{"https://index.docker.io/v1/":{"username":"login","password":"somepass","email":"email@email.com","auth":"longbase64secret"}}}`
func TestGetSecret(t *testing.T) {
imgRef, _ := image.Parse("karolisr/webhook-demo:0.0.11")
@ -92,6 +94,39 @@ func TestGetDockerConfigJSONSecret(t *testing.T) {
t.Errorf("unexpected pass: %s", creds.Password)
}
}
func TestGetDockerConfigJSONSecretUsernmePassword(t *testing.T) {
imgRef, _ := image.Parse("karolisr/webhook-demo:0.0.11")
impl := &testutil.FakeK8sImplementer{
AvailableSecret: &v1.Secret{
Data: map[string][]byte{
dockerConfigJSONKey: []byte(secretDockerConfigJSONPayloadWithUsernamePassword),
},
Type: v1.SecretTypeDockerConfigJson,
},
}
getter := NewGetter(impl)
trackedImage := &types.TrackedImage{
Image: imgRef,
Namespace: "default",
Secrets: []string{"myregistrysecret"},
}
creds, err := getter.Get(trackedImage)
if err != nil {
t.Errorf("failed to get creds: %s", err)
}
if creds.Username != "login" {
t.Errorf("unexpected username: %s", creds.Username)
}
if creds.Password != "somepass" {
t.Errorf("unexpected pass: %s", creds.Password)
}
}
func TestGetSecretNotFound(t *testing.T) {
imgRef, _ := image.Parse("karolisr/webhook-demo:0.0.11")