Skip to content

Commit

Permalink
add image change controller
Browse files Browse the repository at this point in the history
  • Loading branch information
bparees committed Dec 22, 2014
1 parent b91c57a commit 8f2fe96
Show file tree
Hide file tree
Showing 11 changed files with 287 additions and 49 deletions.
21 changes: 20 additions & 1 deletion examples/sample-app/application-template-stibuild.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@
"name": "origin-ruby-sample"
}
},
{
"metadata":{
"name": "ruby-20-centos",
},
"kind": "ImageRepository",
"apiVersion": "v1beta1",
"dockerImageRepository": "172.121.17.3:5001/openshift/ruby-20-centos",
"labels": {
"name": "ruby-20-centos"
}
},
{
"metadata":{
"name": "ruby-sample-build",
Expand All @@ -70,6 +81,14 @@
"generic": {
"secret": "secret101"
}
},
{
"type": "imageChange",
"imageChange": {
"image": "172.121.17.3:5001/openshift/ruby-20-centos",
"repositoryName": "172.121.17.3:5001/openshift/ruby-20-centos",
"tag":"latest"
}
}
],
"parameters": {
Expand All @@ -82,7 +101,7 @@
"strategy": {
"type": "STI",
"stiStrategy": {
"image": "openshift/ruby-20-centos"
"image": "172.121.17.3:5001/openshift/ruby-20-centos"
}
},
"output": {
Expand Down
37 changes: 30 additions & 7 deletions pkg/build/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,23 @@ type BuildStatus string

// Valid values for BuildStatus.
const (
// BuildNew is automatically assigned to a newly created build.
// BuildStatusNew is automatically assigned to a newly created build.
BuildStatusNew BuildStatus = "New"

// BuildPending indicates that a pod name has been assigned and a build is
// BuildStatusPending indicates that a pod name has been assigned and a build is
// about to start running.
BuildStatusPending BuildStatus = "Pending"

// BuildRunning indicates that a pod has been created and a build is running.
// BuildStatusRunning indicates that a pod has been created and a build is running.
BuildStatusRunning BuildStatus = "Running"

// BuildComplete indicates that a build has been successful.
// BuildStatusComplete indicates that a build has been successful.
BuildStatusComplete BuildStatus = "Complete"

// BuildFailed indicates that a build has executed and failed.
// BuildStatusFailed indicates that a build has executed and failed.
BuildStatusFailed BuildStatus = "Failed"

// BuildError indicates that an error prevented the build from executing.
// BuildStatusError indicates that an error prevented the build from executing.
BuildStatusError BuildStatus = "Error"

// BuildStatusCancelled indicates that a running/pending build was stopped from executing.
Expand All @@ -72,7 +72,7 @@ type BuildSourceType string

// Valid values for BuildSourceType.
const (
//BuildGitSource is a Git SCM
//BuildSourceGit is a Git SCM
BuildSourceGit BuildSourceType = "Git"
)

Expand Down Expand Up @@ -175,6 +175,11 @@ type DockerBuildStrategy struct {
// NoCache if set to true indicates that the docker build must be executed with the
// --no-cache=true flag
NoCache bool `json:"noCache,omitempty" yaml:"noCache,omitempty"`

// BaseImage is optional and indicates the image that the dockerfile for this
// build should "FROM". If present, the build process will substitute this value
// into the FROM line of the dockerfile.
BaseImage string `json:"noCache,omitempty" yaml:"noCache,omitempty"`
}

// STIBuildStrategy defines input parameters specific to an STI build.
Expand Down Expand Up @@ -219,6 +224,17 @@ type WebHookTrigger struct {
Secret string `json:"secret,omitempty" yaml:"secret,omitempty"`
}

// BuildTriggerImageChangeParams represents the parameters to the ImageChange trigger.
type ImageChangeTrigger struct {
// Image is used to specify the value in the BuildConfig to replace with the
// immutable image id supplied by the ImageRepository when this trigger fires.
Image string `json:"image,omitempty" yaml:"image,omitempty"`
// RepositoryName is the identifier for a Docker image repository to watch for changes.
RepositoryName string `json:"repositoryName,omitempty" yaml:"repositoryName,omitempty"`
// Tag is the name of an image repository tag to watch for changes.
Tag string `json:"tag,omitempty" yaml:"tag,omitempty"`
}

// BuildTriggerPolicy describes a policy for a single trigger that results in a new Build.
type BuildTriggerPolicy struct {
// Type is the type of build trigger
Expand All @@ -229,6 +245,9 @@ type BuildTriggerPolicy struct {

// GenericWebHook contains the parameters for a Generic webhook type of trigger
GenericWebHook *WebHookTrigger `json:"generic,omitempty" yaml:"generic,omitempty"`

// ImageChange contains parameters for an ImageChange type of trigger
ImageChange *ImageChangeTrigger `json:"imageChange,omitempty" yaml:"imageChange,omitempty"`
}

// BuildTriggerType refers to a specific BuildTriggerPolicy implementation.
Expand All @@ -242,6 +261,10 @@ const (
// GenericWebHookType represents a trigger that launches builds on
// generic webhook invocations
GenericWebHookType BuildTriggerType = "generic"

// ImageChangeType represents a trigger that launches builds on
// availability of a new version of an image
ImageChangeType BuildTriggerType = "imageChange"
)

// BuildList is a collection of Builds.
Expand Down
33 changes: 26 additions & 7 deletions pkg/build/api/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,23 @@ type BuildStatus string

// Valid values for BuildStatus.
const (
// BuildNew is automatically assigned to a newly created build.
// BuildStatusNew is automatically assigned to a newly created build.
BuildStatusNew BuildStatus = "New"

// BuildPending indicates that a pod name has been assigned and a build is
// BuildStatusPending indicates that a pod name has been assigned and a build is
// about to start running.
BuildStatusPending BuildStatus = "Pending"

// BuildRunning indicates that a pod has been created and a build is running.
// BuildStatusRunning indicates that a pod has been created and a build is running.
BuildStatusRunning BuildStatus = "Running"

// BuildComplete indicates that a build has been successful.
BuildStatusComplete BuildStatus = "Complete"
// BuildStatusComplete indicates that a build has been successful.

// BuildFailed indicates that a build has executed and failed.
// BuildStatusFailed indicates that a build has executed and failed.
BuildStatusFailed BuildStatus = "Failed"

// BuildError indicates that an error prevented the build from executing.
// BuildStatusError indicates that an error prevented the build from executing.
BuildStatusError BuildStatus = "Error"

// BuildStatusCancelled indicates that a running/pending build was stopped from executing.
Expand All @@ -72,7 +72,7 @@ type BuildSourceType string

// Valid values for BuildSourceType.
const (
//BuildGitSource is a Git SCM
//BuildSourceGit is a Git SCM
BuildSourceGit BuildSourceType = "Git"
)

Expand Down Expand Up @@ -175,6 +175,11 @@ type DockerBuildStrategy struct {
// NoCache if set to true indicates that the docker build must be executed with the
// --no-cache=true flag
NoCache bool `json:"noCache,omitempty" yaml:"noCache,omitempty"`

// BaseImage is optional and indicates the image that the dockerfile for this
// build should "FROM". If present, the build process will substitute this value
// into the FROM line of the dockerfile.
BaseImage string `json:"noCache,omitempty" yaml:"noCache,omitempty"`
}

// STIBuildStrategy defines input parameters specific to an STI build.
Expand Down Expand Up @@ -223,6 +228,17 @@ type WebHookTrigger struct {
Secret string `json:"secret,omitempty" yaml:"secret,omitempty"`
}

// BuildTriggerImageChangeParams represents the parameters to the ImageChange trigger.
type ImageChangeTrigger struct {
// ImageName is used to specify the value in the BuildConfig to replace with the
// immutable image id supplied by the ImageRepository when this trigger fires.
Image string `json:"image,omitempty" yaml:"image,omitempty"`
// RepositoryName is the identifier for a Docker image repository to watch for changes.
RepositoryName string `json:"repositoryName,omitempty" yaml:"repositoryName,omitempty"`
// Tag is the name of an image repository tag to watch for changes.
Tag string `json:"tag,omitempty" yaml:"tag,omitempty"`
}

// BuildTriggerPolicy describes a policy for a single trigger that results in a new Build.
type BuildTriggerPolicy struct {
// Type is the type of build trigger
Expand All @@ -233,6 +249,9 @@ type BuildTriggerPolicy struct {

// GenericWebHook contains the parameters for a Generic webhook type of trigger
GenericWebHook *WebHookTrigger `json:"generic,omitempty" yaml:"generic,omitempty"`

// ImageChange contains parameters for an ImageChange type of trigger
ImageChange *ImageChangeTrigger `json:"imageChange,omitempty" yaml:"imageChange,omitempty"`
}

// BuildTriggerType refers to a specific BuildTriggerPolicy implementation.
Expand Down
65 changes: 39 additions & 26 deletions pkg/build/builder/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"net/url"
"os"
"path/filepath"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -54,10 +55,10 @@ func (d *DockerBuilder) Build() error {
if err = d.fetchSource(buildDir); err != nil {
return err
}
if err = d.dockerBuild(buildDir); err != nil {
if err = d.addBuildParameters(buildDir); err != nil {
return err
}
if err = d.addImageVars(); err != nil {
if err = d.dockerBuild(buildDir); err != nil {
return err
}
if d.build.Parameters.Output.Registry != "" || d.authPresent {
Expand Down Expand Up @@ -125,40 +126,52 @@ func (d *DockerBuilder) fetchSource(dir string) error {
return d.git.Checkout(dir, d.build.Parameters.Source.Git.Ref)
}

// dockerBuild performs a docker build on the source that has been retrieved
func (d *DockerBuilder) dockerBuild(dir string) error {
var noCache bool
if d.build.Parameters.Strategy.DockerStrategy != nil {
if d.build.Parameters.Strategy.DockerStrategy.ContextDir != "" {
dir = filepath.Join(dir, d.build.Parameters.Strategy.DockerStrategy.ContextDir)
}
noCache = d.build.Parameters.Strategy.DockerStrategy.NoCache
}
return buildImage(d.dockerClient, dir, noCache, imageTag(d.build), d.tar)
}
// addBuildParameters checks if a BaseImage is set to replace the default base image.
// If that's the case then change the Dockerfile to make the build with the given image.
// Also append the environment variables in the Dockerfile.
func (d *DockerBuilder) addBuildParameters(dir string) error {
dockerfilePath := filepath.Join(dir, d.build.Parameters.Strategy.DockerStrategy.ContextDir, "Dockerfile")

// addImageVars creates a new Dockerfile which adds certain environment
// variables to the previously tagged image
func (d *DockerBuilder) addImageVars() error {
var noCache bool
envVars := getBuildEnvVars(d.build)
tempDir, err := ioutil.TempDir("", "overlay")
fileStat, err := os.Lstat(dockerfilePath)
filePerm := fileStat.Mode()

fileData, err := ioutil.ReadFile(dockerfilePath)
if err != nil {
return err
}
overlay, err := os.Create(filepath.Join(tempDir, "Dockerfile"))
if err != nil {
return err

var newFileData string

if d.build.Parameters.Strategy.DockerStrategy.BaseImage != "" {
re := regexp.MustCompile(`^FROM \w+.+/+\w+`)
newFileData = re.ReplaceAllString(string(fileData), fmt.Sprintf("FROM %s\n", d.build.Parameters.Strategy.DockerStrategy.BaseImage))
}
overlay.WriteString(fmt.Sprintf("FROM %s\n", imageTag(d.build)))

envVars := getBuildEnvVars(d.build)
for k, v := range envVars {
overlay.WriteString(fmt.Sprintf("ENV %s %s\n", k, v))
newFileData = newFileData + fmt.Sprintf("ENV %s %s\n", k, v)
}
if err = overlay.Close(); err != nil {

err = ioutil.WriteFile(dockerfilePath, []byte(newFileData), filePerm)
if err != nil {
return err
}

var noCache bool
if d.build.Parameters.Strategy.DockerStrategy != nil {
noCache = d.build.Parameters.Strategy.DockerStrategy.NoCache
}
return buildImage(d.dockerClient, tempDir, noCache, imageTag(d.build), d.tar)
return buildImage(d.dockerClient, dir, noCache, imageTag(d.build), d.tar)
}

// dockerBuild performs a docker build on the source that has been retrieved
func (d *DockerBuilder) dockerBuild(dir string) error {
var noCache bool
if d.build.Parameters.Strategy.DockerStrategy != nil {
if d.build.Parameters.Strategy.DockerStrategy.ContextDir != "" {
dir = filepath.Join(dir, d.build.Parameters.Strategy.DockerStrategy.ContextDir)
}
noCache = d.build.Parameters.Strategy.DockerStrategy.NoCache
}
return buildImage(d.dockerClient, dir, noCache, imageTag(d.build), d.tar)
}
3 changes: 2 additions & 1 deletion pkg/build/builder/sti.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ func NewSTIBuilder(client DockerClient, dockerSocket string, authCfg docker.Auth
// Build executes the STI build
func (s *STIBuilder) Build() error {
request := &sti.STIRequest{
BaseImage: s.build.Parameters.Strategy.STIStrategy.Image,
BaseImage: s.build.Parameters.Strategy.STIStrategy.Image,
DockerSocket: s.dockerSocket,
Source: s.build.Parameters.Source.Git.URI,
Tag: imageTag(s.build),
Environment: getBuildEnvVars(s.build),
Clean: s.build.Parameters.Strategy.STIStrategy.Clean,
}

if s.build.Parameters.Revision != nil && s.build.Parameters.Revision.Git != nil &&
s.build.Parameters.Revision.Git.Commit != "" {
request.Ref = s.build.Parameters.Revision.Git.Commit
Expand Down
Loading

0 comments on commit 8f2fe96

Please sign in to comment.