Skip to content

Commit 71639c1

Browse files
author
OpenShift Bot
committed
Merge pull request #1433 from ironcladlou/deploy-trigger-test-fix
Merged by openshift-bot
2 parents ba92269 + ab496df commit 71639c1

File tree

9 files changed

+428
-946
lines changed

9 files changed

+428
-946
lines changed

pkg/cmd/server/origin/master.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,6 @@ func (c *MasterConfig) InstallProtectedAPI(container *restful.Container) []strin
173173
IRFn: imageRepositoryRegistry.GetImageRepository,
174174
LIRFn2: imageRepositoryRegistry.ListImageRepositories,
175175
},
176-
Codec: latest.Codec,
177176
}
178177
_, kclient := c.DeploymentConfigControllerClients()
179178
deployRollback := &deployrollback.RollbackGenerator{}

pkg/deploy/api/test/ok.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,33 @@ func OkImageChangeTrigger() deployapi.DeploymentTriggerPolicy {
9595
ContainerNames: []string{
9696
"container1",
9797
},
98-
RepositoryName: "registry:8080/repo1",
99-
Tag: "tag1",
98+
From: kapi.ObjectReference{
99+
Kind: "ImageRepository",
100+
Name: "test-image-repo",
101+
},
102+
Tag: "latest",
103+
},
104+
}
105+
}
106+
107+
func OkImageChangeTriggerDeprecated() deployapi.DeploymentTriggerPolicy {
108+
return deployapi.DeploymentTriggerPolicy{
109+
Type: deployapi.DeploymentTriggerOnImageChange,
110+
ImageChangeParams: &deployapi.DeploymentTriggerImageChangeParams{
111+
Automatic: true,
112+
ContainerNames: []string{
113+
"container1",
114+
},
115+
RepositoryName: "registry:8080/repo1:ref1",
116+
Tag: "latest",
100117
},
101118
}
102119
}
103120

104121
func OkDeploymentConfig(version int) *deployapi.DeploymentConfig {
105122
return &deployapi.DeploymentConfig{
106123
ObjectMeta: kapi.ObjectMeta{
107-
Namespace: kapi.NamespaceDefault,
108-
Name: "config",
124+
Name: "config",
109125
},
110126
LatestVersion: version,
111127
Triggers: []deployapi.DeploymentTriggerPolicy{

pkg/deploy/api/types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ type DeploymentTriggerImageChangeParams struct {
182182
From kapi.ObjectReference `json:"from"`
183183
// Tag is the name of an image repository tag to watch for changes.
184184
Tag string `json:"tag,omitempty"`
185+
// LastTriggeredImage is the last image to be triggered.
186+
LastTriggeredImage string `json:"lastTriggeredImage"`
185187
}
186188

187189
// DeploymentDetails captures information about the causes of a deployment.

pkg/deploy/api/v1beta1/types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ type DeploymentTriggerImageChangeParams struct {
183183
From kapi.ObjectReference `json:"from"`
184184
// Tag is the name of an image repository tag to watch for changes.
185185
Tag string `json:"tag,omitempty"`
186+
// LastTriggeredImage is the last image to be triggered.
187+
LastTriggeredImage string `json:"lastTriggeredImage"`
186188
}
187189

188190
// DeploymentDetails captures information about the causes of a deployment.

pkg/deploy/controller/imagechange/controller.go

Lines changed: 43 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import (
55

66
"github.com/golang/glog"
77

8-
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
9-
108
deployapi "github.com/openshift/origin/pkg/deploy/api"
119
imageapi "github.com/openshift/origin/pkg/image/api"
1210
)
@@ -26,72 +24,56 @@ func (e fatalError) Error() string { return "fatal error handling imageRepositor
2624

2725
// Handle processes image change triggers associated with imageRepo.
2826
func (c *ImageChangeController) Handle(imageRepo *imageapi.ImageRepository) error {
29-
configsToGenerate := []*deployapi.DeploymentConfig{}
30-
firedTriggersForConfig := make(map[string][]deployapi.DeploymentTriggerImageChangeParams)
31-
3227
configs, err := c.deploymentConfigClient.listDeploymentConfigs()
3328
if err != nil {
3429
return fmt.Errorf("couldn't get list of deploymentConfigs while handling imageRepo %s: %v", labelForRepo(imageRepo), err)
3530
}
3631

32+
// Find any configs which should be updated based on the new image state
33+
configsToUpdate := map[string]*deployapi.DeploymentConfig{}
3734
for _, config := range configs {
3835
glog.V(4).Infof("Detecting changed images for deploymentConfig %s", labelFor(config))
3936

40-
// Extract relevant triggers for this imageRepo for this config
41-
triggersForConfig := []deployapi.DeploymentTriggerImageChangeParams{}
4237
for _, trigger := range config.Triggers {
43-
if trigger.Type != deployapi.DeploymentTriggerOnImageChange ||
44-
!trigger.ImageChangeParams.Automatic {
38+
params := trigger.ImageChangeParams
39+
40+
// Only automatic image change triggers should fire
41+
if trigger.Type != deployapi.DeploymentTriggerOnImageChange || !params.Automatic {
42+
continue
43+
}
44+
45+
// Check if the image repo matches the trigger
46+
if !triggerMatchesImage(config, params, imageRepo) {
4547
continue
4648
}
47-
if triggerMatchesImage(config, trigger.ImageChangeParams, imageRepo) {
48-
glog.V(4).Infof("Found matching %s trigger for deploymentConfig %s: %#v", trigger.Type, labelFor(config), trigger.ImageChangeParams)
49-
triggersForConfig = append(triggersForConfig, *trigger.ImageChangeParams)
49+
50+
// Find the latest tag event for the trigger tag
51+
latestEvent, err := imageapi.LatestTaggedImage(imageRepo, params.Tag)
52+
if err != nil {
53+
glog.V(4).Infof("Couldn't find latest tag event for tag %s in imageRepo %s: %s", params.Tag, labelForRepo(imageRepo), err)
54+
continue
5055
}
51-
}
5256

53-
for _, params := range triggersForConfig {
54-
glog.V(4).Infof("Processing image triggers for deploymentConfig %s", labelFor(config))
55-
containerNames := util.NewStringSet(params.ContainerNames...)
56-
for _, container := range config.Template.ControllerTemplate.Template.Spec.Containers {
57-
if !containerNames.Has(container.Name) {
58-
continue
59-
}
60-
61-
ref, err := imageapi.ParseDockerImageReference(container.Image)
62-
if err != nil {
63-
glog.V(4).Infof("Skipping container %s for config %s; container's image is invalid: %v", container.Name, labelFor(config), err)
64-
continue
65-
}
66-
67-
latest, err := imageapi.LatestTaggedImage(imageRepo, params.Tag)
68-
if err != nil {
69-
glog.V(4).Infof("Skipping container %s for config %s; %s", container.Name, labelFor(config), err)
70-
continue
71-
}
72-
73-
containerImageID := ref.ID
74-
if len(containerImageID) == 0 {
75-
// For v1 images, the container image's tag name is by convention the same as the image ID it references
76-
containerImageID = ref.Tag
77-
}
78-
if latest.Image != containerImageID {
79-
glog.V(4).Infof("Container %s for config %s: image id changed from %q to %q; regenerating config", container.Name, labelFor(config), containerImageID, latest.Image)
80-
configsToGenerate = append(configsToGenerate, config)
81-
firedTriggersForConfig[config.Name] = append(firedTriggersForConfig[config.Name], params)
82-
}
57+
// Ensure a change occured
58+
if len(latestEvent.DockerImageReference) > 0 &&
59+
latestEvent.DockerImageReference != params.LastTriggeredImage {
60+
// Mark the config for regeneration
61+
configsToUpdate[config.Name] = config
8362
}
8463
}
8564
}
8665

66+
// Attempt to regenerate all configs which may contain image updates
8767
anyFailed := false
88-
for _, config := range configsToGenerate {
89-
err := c.regenerate(imageRepo, config, firedTriggersForConfig[config.Name])
68+
for _, config := range configsToUpdate {
69+
err := c.regenerate(config)
9070
if err != nil {
9171
anyFailed = true
72+
glog.Infof("couldn't regenerate depoymentConfig %s: %s", labelFor(config), err)
9273
continue
9374
}
94-
glog.V(4).Infof("Updated deploymentConfig %s in response to image change trigger", labelFor(config))
75+
76+
glog.V(4).Infof("Regenerated deploymentConfig %s in response to image change trigger", labelFor(config))
9577
}
9678

9779
if anyFailed {
@@ -106,64 +88,41 @@ func (c *ImageChangeController) Handle(imageRepo *imageapi.ImageRepository) erro
10688
// When matching:
10789
// - The trigger From field is preferred over the deprecated RepositoryName field.
10890
// - The namespace of the trigger is preferred over the config's namespace.
109-
func triggerMatchesImage(config *deployapi.DeploymentConfig, trigger *deployapi.DeploymentTriggerImageChangeParams, repo *imageapi.ImageRepository) bool {
110-
if len(trigger.From.Name) > 0 {
111-
namespace := trigger.From.Namespace
91+
func triggerMatchesImage(config *deployapi.DeploymentConfig, params *deployapi.DeploymentTriggerImageChangeParams, repo *imageapi.ImageRepository) bool {
92+
if len(params.From.Name) > 0 {
93+
namespace := params.From.Namespace
11294
if len(namespace) == 0 {
11395
namespace = config.Namespace
11496
}
11597

116-
return repo.Namespace == namespace && repo.Name == trigger.From.Name
98+
return repo.Namespace == namespace && repo.Name == params.From.Name
11799
}
118100

119101
// This is an invalid state (as one of From.Name or RepositoryName is required), but
120102
// account for it anyway.
121-
if len(trigger.RepositoryName) == 0 {
103+
if len(params.RepositoryName) == 0 {
122104
return false
123105
}
124106

125107
// If the repo's repository information isn't yet available, we can't assume it'll match.
126108
return len(repo.Status.DockerImageRepository) > 0 &&
127-
trigger.RepositoryName == repo.Status.DockerImageRepository
109+
params.RepositoryName == repo.Status.DockerImageRepository
128110
}
129111

130-
func (c *ImageChangeController) regenerate(imageRepo *imageapi.ImageRepository, config *deployapi.DeploymentConfig, triggers []deployapi.DeploymentTriggerImageChangeParams) error {
112+
// regenerate calls the generator to get a new config. If the newly generated
113+
// config's version is newer, update the old config to be the new config.
114+
// Otherwise do nothing.
115+
func (c *ImageChangeController) regenerate(config *deployapi.DeploymentConfig) error {
131116
// Get a regenerated config which includes the new image repo references
132117
newConfig, err := c.deploymentConfigClient.generateDeploymentConfig(config.Namespace, config.Name)
133118
if err != nil {
134119
return fmt.Errorf("error generating new version of deploymentConfig %s: %v", labelFor(config), err)
135120
}
136121

137-
// Update the deployment config with the trigger that resulted in the new config
138-
causes := []*deployapi.DeploymentCause{}
139-
for _, trigger := range triggers {
140-
repoName := trigger.RepositoryName
141-
142-
if len(repoName) == 0 {
143-
if len(imageRepo.Status.DockerImageRepository) == 0 {
144-
// If the trigger relies on a image repo reference, and we don't know what docker repo
145-
// it points at, we can't build a cause for the reference yet.
146-
continue
147-
}
148-
149-
latest, err := imageapi.LatestTaggedImage(imageRepo, trigger.Tag)
150-
if err != nil {
151-
return fmt.Errorf("error generating new version of deploymentConfig: %s: %s", labelFor(config), err)
152-
}
153-
repoName = latest.DockerImageReference
154-
}
155-
156-
causes = append(causes,
157-
&deployapi.DeploymentCause{
158-
Type: deployapi.DeploymentTriggerOnImageChange,
159-
ImageTrigger: &deployapi.DeploymentCauseImageTrigger{
160-
RepositoryName: repoName,
161-
Tag: trigger.Tag,
162-
},
163-
})
164-
}
165-
newConfig.Details = &deployapi.DeploymentDetails{
166-
Causes: causes,
122+
// No update occured
123+
if config.LatestVersion == newConfig.LatestVersion {
124+
glog.V(4).Infof("No version difference for generated config %s", labelFor(config))
125+
return nil
167126
}
168127

169128
// Persist the new config
@@ -172,6 +131,7 @@ func (c *ImageChangeController) regenerate(imageRepo *imageapi.ImageRepository,
172131
return err
173132
}
174133

134+
glog.Infof("Regenerated depoymentConfig %s for image updates", labelFor(config))
175135
return nil
176136
}
177137

0 commit comments

Comments
 (0)