5
5
6
6
"github.com/golang/glog"
7
7
8
- "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
9
-
10
8
deployapi "github.com/openshift/origin/pkg/deploy/api"
11
9
imageapi "github.com/openshift/origin/pkg/image/api"
12
10
)
@@ -26,72 +24,56 @@ func (e fatalError) Error() string { return "fatal error handling imageRepositor
26
24
27
25
// Handle processes image change triggers associated with imageRepo.
28
26
func (c * ImageChangeController ) Handle (imageRepo * imageapi.ImageRepository ) error {
29
- configsToGenerate := []* deployapi.DeploymentConfig {}
30
- firedTriggersForConfig := make (map [string ][]deployapi.DeploymentTriggerImageChangeParams )
31
-
32
27
configs , err := c .deploymentConfigClient .listDeploymentConfigs ()
33
28
if err != nil {
34
29
return fmt .Errorf ("couldn't get list of deploymentConfigs while handling imageRepo %s: %v" , labelForRepo (imageRepo ), err )
35
30
}
36
31
32
+ // Find any configs which should be updated based on the new image state
33
+ configsToUpdate := map [string ]* deployapi.DeploymentConfig {}
37
34
for _ , config := range configs {
38
35
glog .V (4 ).Infof ("Detecting changed images for deploymentConfig %s" , labelFor (config ))
39
36
40
- // Extract relevant triggers for this imageRepo for this config
41
- triggersForConfig := []deployapi.DeploymentTriggerImageChangeParams {}
42
37
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 ) {
45
47
continue
46
48
}
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
50
55
}
51
- }
52
56
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
83
62
}
84
63
}
85
64
}
86
65
66
+ // Attempt to regenerate all configs which may contain image updates
87
67
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 )
90
70
if err != nil {
91
71
anyFailed = true
72
+ glog .Infof ("couldn't regenerate depoymentConfig %s: %s" , labelFor (config ), err )
92
73
continue
93
74
}
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 ))
95
77
}
96
78
97
79
if anyFailed {
@@ -106,64 +88,41 @@ func (c *ImageChangeController) Handle(imageRepo *imageapi.ImageRepository) erro
106
88
// When matching:
107
89
// - The trigger From field is preferred over the deprecated RepositoryName field.
108
90
// - 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
112
94
if len (namespace ) == 0 {
113
95
namespace = config .Namespace
114
96
}
115
97
116
- return repo .Namespace == namespace && repo .Name == trigger .From .Name
98
+ return repo .Namespace == namespace && repo .Name == params .From .Name
117
99
}
118
100
119
101
// This is an invalid state (as one of From.Name or RepositoryName is required), but
120
102
// account for it anyway.
121
- if len (trigger .RepositoryName ) == 0 {
103
+ if len (params .RepositoryName ) == 0 {
122
104
return false
123
105
}
124
106
125
107
// If the repo's repository information isn't yet available, we can't assume it'll match.
126
108
return len (repo .Status .DockerImageRepository ) > 0 &&
127
- trigger .RepositoryName == repo .Status .DockerImageRepository
109
+ params .RepositoryName == repo .Status .DockerImageRepository
128
110
}
129
111
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 {
131
116
// Get a regenerated config which includes the new image repo references
132
117
newConfig , err := c .deploymentConfigClient .generateDeploymentConfig (config .Namespace , config .Name )
133
118
if err != nil {
134
119
return fmt .Errorf ("error generating new version of deploymentConfig %s: %v" , labelFor (config ), err )
135
120
}
136
121
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
167
126
}
168
127
169
128
// Persist the new config
@@ -172,6 +131,7 @@ func (c *ImageChangeController) regenerate(imageRepo *imageapi.ImageRepository,
172
131
return err
173
132
}
174
133
134
+ glog .Infof ("Regenerated depoymentConfig %s for image updates" , labelFor (config ))
175
135
return nil
176
136
}
177
137
0 commit comments