forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 1
Fix build image change controller race #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
mfojtik
merged 2 commits into
mfojtik:service-account-push-secrets
from
ncdc:service-account-push-secrets
May 28, 2015
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ import ( | |
| "fmt" | ||
| "strings" | ||
|
|
||
| kerrors "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" | ||
| "github.com/golang/glog" | ||
|
|
||
| kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" | ||
|
|
@@ -32,7 +33,6 @@ func (e ImageChangeControllerFatalError) Error() string { | |
| type ImageChangeController struct { | ||
| BuildConfigStore cache.Store | ||
| BuildConfigInstantiator buildclient.BuildConfigInstantiator | ||
| BuildConfigUpdater buildclient.BuildConfigUpdater | ||
| // Stop is an optional channel that controls when the controller exits | ||
| Stop <-chan struct{} | ||
| } | ||
|
|
@@ -51,18 +51,14 @@ func (c *ImageChangeController) HandleImageRepo(repo *imageapi.ImageStream) erro | |
| // TODO: this is inefficient | ||
| for _, bc := range c.BuildConfigStore.List() { | ||
| config := bc.(*buildapi.BuildConfig) | ||
| obj, err := kapi.Scheme.Copy(config) | ||
| if err != nil { | ||
| continue | ||
| } | ||
| originalConfig := obj.(*buildapi.BuildConfig) | ||
|
|
||
| from := buildutil.GetImageStreamForStrategy(config.Parameters.Strategy) | ||
| if from == nil || from.Kind != "ImageStreamTag" { | ||
| continue | ||
| } | ||
|
|
||
| shouldBuild := false | ||
| triggeredImage := "" | ||
| // For every ImageChange trigger find the latest tagged image from the image repository and replace that value | ||
| // throughout the build strategies. A new build is triggered only if the latest tagged image id or pull spec | ||
| // differs from the last triggered build recorded on the build config. | ||
|
|
@@ -99,68 +95,37 @@ func (c *ImageChangeController) HandleImageRepo(repo *imageapi.ImageStream) erro | |
| next := latest.DockerImageReference | ||
|
|
||
| if len(last) == 0 || (len(next) > 0 && next != last) { | ||
| trigger.ImageChange.LastTriggeredImageID = next | ||
| triggeredImage = next | ||
| shouldBuild = true | ||
| // it doesn't really make sense to have multiple image change triggers any more, | ||
| // so just exit the loop now | ||
| break | ||
| } | ||
| } | ||
|
|
||
| if shouldBuild { | ||
| // The following update is meant to reduce the chance that the image change controller | ||
| // will kick off multiple builds on an image change in a HA setup, where multiple controllers | ||
| // of the same type may be looking at the same etcd data. | ||
| // If multiple controllers read the same build config (with same ResourceVersion) above and | ||
| // make a determination that a build needs to be kicked off, the update will only allow one of | ||
| // those controllers to continue to launch the build, while the rest will return an error and | ||
| // reset their queue. This won't eliminate the chance of multiple builds, since another controller | ||
| // can read the build after this update and launch its own build. | ||
| // TODO: Find a better mechanism to synchronize in a HA setup. | ||
| if err := c.BuildConfigUpdater.Update(originalConfig); err != nil { | ||
| // Cannot make an update to the original build config. Likely it has been changed by another process | ||
| glog.V(4).Infof("Cannot update BuildConfig %s/%s when preparing to update LastTriggeredImageID: %v", config.Namespace, config.Name, err) | ||
| return err | ||
| } | ||
|
|
||
| glog.V(4).Infof("Running build for BuildConfig %s/%s", config.Namespace, config.Name) | ||
| // instantiate new build | ||
| request := &buildapi.BuildRequest{ObjectMeta: kapi.ObjectMeta{Name: config.Name}} | ||
| if _, err := c.BuildConfigInstantiator.Instantiate(config.Namespace, request); err != nil { | ||
| return fmt.Errorf("error instantiating Build from BuildConfig %s/%s: %v", config.Namespace, config.Name, err) | ||
| request := &buildapi.BuildRequest{ | ||
| ObjectMeta: kapi.ObjectMeta{ | ||
| Name: config.Name, | ||
| }, | ||
| Image: triggeredImage, | ||
| } | ||
| // and update the config | ||
| if err := c.updateConfig(config); err != nil { | ||
| // This is not a retryable error. The worst case outcome of not updating the buildconfig | ||
| // is that we might rerun a build for the same "new" imageid change in the future, | ||
| // which is better than guaranteeing we run the build 2+ times by retrying it here. | ||
| return ImageChangeControllerFatalError{ | ||
| Reason: fmt.Sprintf("error updating BuildConfig %s/%s with new LastTriggeredImageID", config.Namespace, config.Name), | ||
| Err: err, | ||
| if _, err := c.BuildConfigInstantiator.Instantiate(config.Namespace, request); err != nil { | ||
| if kerrors.IsConflict(err) { | ||
| // This is not a retryable error. The worst case outcome of not updating the buildconfig | ||
| // is that we might rerun a build for the same "new" imageid change in the future, | ||
| // which is better than guaranteeing we run the build 2+ times by retrying it here. | ||
| return ImageChangeControllerFatalError{ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These returns mean you'll only process one config. |
||
| Reason: fmt.Sprintf("unable to instantiate Build for BuildConfig %s/%s due to a conflicting update: %v", config.Namespace, config.Name, err), | ||
| Err: err, | ||
| } | ||
| } | ||
|
|
||
| return fmt.Errorf("error instantiating Build from BuildConfig %s/%s: %v", config.Namespace, config.Name, err) | ||
| } | ||
| } | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| // updateConfig is responsible for updating current BuildConfig object which was changed | ||
| // during instantiate call, it basically copies LastTriggeredImageID to fresh copy | ||
| // of the BuildConfig object | ||
| func (c *ImageChangeController) updateConfig(config *buildapi.BuildConfig) error { | ||
| item, _, err := c.BuildConfigStore.Get(config) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| if item == nil { | ||
| return fmt.Errorf("unable to retrieve BuildConfig %s/%s for updating", config.Namespace, config.Name) | ||
| } | ||
| newConfig := item.(*buildapi.BuildConfig) | ||
| for i, trigger := range newConfig.Triggers { | ||
| if trigger.Type != buildapi.ImageChangeBuildTriggerType { | ||
| continue | ||
| } | ||
| change := trigger.ImageChange | ||
| change.LastTriggeredImageID = config.Triggers[i].ImageChange.LastTriggeredImageID | ||
| } | ||
| glog.V(4).Infof("BuildConfig %s/%s is about to be updated", config.Namespace, config.Name) | ||
|
|
||
| return c.BuildConfigUpdater.Update(newConfig) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add JSON descriptions.