Skip to content
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

Allow S2I behavior to be overriden by caller #310

Merged
merged 1 commit into from
Oct 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pkg/build/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,9 @@ type SourceHandler interface {
type LayeredDockerBuilder interface {
Builder
}

// Overrides are interfaces that may be passed into build strategies to
// alter the behavior of a strategy.
type Overrides struct {
Downloader Downloader
}
3 changes: 2 additions & 1 deletion pkg/build/strategies/layered/layered.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type Layered struct {
scripts build.ScriptsHandler
}

func New(config *api.Config, scripts build.ScriptsHandler) (*Layered, error) {
func New(config *api.Config, scripts build.ScriptsHandler, overrides build.Overrides) (*Layered, error) {
d, err := docker.New(config.DockerConfig, config.PullAuthentication)
if err != nil {
return nil, err
Expand Down Expand Up @@ -82,6 +82,7 @@ func (b *Layered) CreateDockerfile(config *api.Config) error {
return nil
}

// TODO: this should stop generating a file, and instead stream the tar.
func (b *Layered) SourceTar(config *api.Config) (io.ReadCloser, error) {
uploadDir := filepath.Join(config.WorkingDir, "upload")
tarFileName, err := b.tar.CreateTarFile(b.config.WorkingDir, uploadDir)
Expand Down
24 changes: 17 additions & 7 deletions pkg/build/strategies/onbuild/onbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type onBuildSourceHandler struct {
}

// New returns a new instance of OnBuild builder
func New(config *api.Config) (*OnBuild, error) {
func New(config *api.Config, overrides build.Overrides) (*OnBuild, error) {
dockerHandler, err := docker.New(config.DockerConfig, config.PullAuthentication)
if err != nil {
return nil, err
Expand All @@ -50,15 +50,25 @@ func New(config *api.Config) (*OnBuild, error) {
tar: tar.New(),
}
// Use STI Prepare() and download the 'run' script optionally.
s, err := sti.New(config)
s, err := sti.New(config, overrides)
s.SetScripts([]string{}, []string{api.Assemble, api.Run})
downloader, sourceUrl, err := scm.DownloaderForSource(config.Source)
if err != nil {
return nil, err

downloader := overrides.Downloader
if downloader == nil {
d, sourceURL, err := scm.DownloaderForSource(config.Source)
if err != nil {
return nil, err
}
downloader = d
config.Source = sourceURL
}

b.source = onBuildSourceHandler{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is dupe of line 61

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean - if no override is provided, we now create a default downloader and set it. b.source is only set once.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, you meant 61 in the old file. Fixed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i liked the old line 61 better than your new one. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed it for you - including saving you from a govet error for anonymous
field declarations

On Mon, Oct 19, 2015 at 5:48 PM, Ben Parees notifications@github.com
wrote:

In pkg/build/strategies/onbuild/onbuild.go
#310 (comment)
:

s.SetScripts([]string{}, []string{api.Assemble, api.Run})
  • downloader, sourceUrl, err := scm.DownloaderForSource(config.Source)
  • if err != nil {
  •   return nil, err
    
  • downloader := overrides.Downloader
  • if downloader == nil {
  •   d, sourceURL, err := scm.DownloaderForSource(config.Source)
    
  •   if err != nil {
    
  •       return nil, err
    
  •   }
    
  •   downloader = d
    
  •   config.Source = sourceURL
    
  • }
  • b.source = onBuildSourceHandler{

i liked the old line 61 better than your new one. :)


Reply to this email directly or view it on GitHub
https://github.com/openshift/source-to-image/pull/310/files#r42430517.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, now yours is better :)

Downloader: downloader,
Preparer: s,
Ignorer: &ignore.DockerIgnorer{},
}
config.Source = sourceUrl

b.source = onBuildSourceHandler{downloader, s, &ignore.DockerIgnorer{}}
b.garbage = &build.DefaultCleaner{b.fs, b.docker}
return b, nil
}
Expand Down
56 changes: 36 additions & 20 deletions pkg/build/strategies/sti/sti.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"path/filepath"
"regexp"
"strings"
"sync"

"github.com/golang/glog"
"github.com/openshift/source-to-image/pkg/api"
Expand Down Expand Up @@ -66,7 +67,7 @@ type STI struct {
// If the layeredBuilder parameter is specified, then the builder provided will
// be used for the case that the base Docker image does not have 'tar' or 'bash'
// installed.
func New(req *api.Config) (*STI, error) {
func New(req *api.Config, overrides build.Overrides) (*STI, error) {
docker, err := dockerpkg.New(req.DockerConfig, req.PullAuthentication)
if err != nil {
return nil, err
Expand Down Expand Up @@ -99,13 +100,18 @@ func New(req *api.Config) (*STI, error) {

// The sources are downloaded using the GIT downloader.
// TODO: Add more SCM in future.
b.source, req.Source, err = scm.DownloaderForSource(req.Source)
if err != nil {
return nil, err
b.source = overrides.Downloader
if b.source == nil {
downloader, sourceURL, err := scm.DownloaderForSource(req.Source)
if err != nil {
return nil, err
}
b.source = downloader
req.Source = sourceURL
}

b.garbage = &build.DefaultCleaner{b.fs, b.docker}
b.layered, err = layered.New(req, b)
b.layered, err = layered.New(req, b, overrides)

// Set interfaces
b.preparer = b
Expand Down Expand Up @@ -168,8 +174,10 @@ func (b *STI) Build(config *api.Config) (*api.Result, error) {
// struct Build func leverages the STI struct Prepare func directly below
func (b *STI) Prepare(config *api.Config) error {
var err error
if config.WorkingDir, err = b.fs.CreateWorkingDirectory(); err != nil {
return err
if len(config.WorkingDir) == 0 {
if config.WorkingDir, err = b.fs.CreateWorkingDirectory(); err != nil {
return err
}
}

b.result = &api.Result{
Expand Down Expand Up @@ -374,18 +382,6 @@ func (b *STI) Execute(command string, config *api.Config) error {

buildEnv := append(scripts.ConvertEnvironment(env), b.generateConfigEnv()...)

uploadDir := filepath.Join(config.WorkingDir, "upload")
tarFileName, err := b.tar.CreateTarFile(config.WorkingDir, uploadDir)
if err != nil {
return err
}

tarFile, err := b.fs.Open(tarFileName)
if err != nil {
return err
}
defer tarFile.Close()

errOutput := ""
outReader, outWriter := io.Pipe()
errReader, errWriter := io.Pipe()
Expand All @@ -410,8 +406,28 @@ func (b *STI) Execute(command string, config *api.Config) error {
Env: buildEnv,
PostExec: b.postExecutor,
}

if !config.LayeredBuild {
opts.Stdin = tarFile
wg := sync.WaitGroup{}
wg.Add(1)
uploadDir := filepath.Join(config.WorkingDir, "upload")

// TODO: be able to pass a stream directly to the Docker build to avoid the double temp hit
r, w := io.Pipe()
go func() {
var err error
defer func() {
w.CloseWithError(err)
if r := recover(); r != nil {
glog.Errorf("recovered panic: %#v", r)
}
wg.Done()
}()
err = b.tar.CreateTarStream(uploadDir, false, w)
}()

opts.Stdin = r
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason you can't move all this logic (setting up the stdin stream) above the creation of the RunContainerOptions struct, and populate the opts.Stdin field as part of creating that struct, instead of doing it here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i guess it's a scoping issue. meh.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only reason would be that stdin is not always set, so you'd need an empty var stdin and go abhors empty variable declarations.

defer wg.Wait()
}

go func(reader io.Reader) {
Expand Down
75 changes: 56 additions & 19 deletions pkg/build/strategies/sti/sti_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package sti
import (
"errors"
"fmt"
"io"
"reflect"
"testing"

"github.com/openshift/source-to-image/pkg/api"
"github.com/openshift/source-to-image/pkg/build"
stierr "github.com/openshift/source-to-image/pkg/errors"
"github.com/openshift/source-to-image/pkg/ignore"
"github.com/openshift/source-to-image/pkg/scm/file"
"github.com/openshift/source-to-image/pkg/scm/git"
"github.com/openshift/source-to-image/pkg/test"
)
Expand All @@ -24,6 +26,7 @@ type FakeSTI struct {
ExistsError error
BuildRequest *api.Config
BuildResult *api.Result
DownloadError error
SaveArtifactsCalled bool
SaveArtifactsError error
FetchSourceCalled bool
Expand Down Expand Up @@ -103,8 +106,8 @@ func (f *FakeSTI) fetchSource() error {
return f.FetchSourceError
}

func (f *FakeSTI) Download(*api.Config) error {
return nil
func (f *FakeSTI) Download(*api.Config) (*api.SourceInfo, error) {
return nil, f.DownloadError
}

func (f *FakeSTI) Execute(command string, r *api.Config) error {
Expand All @@ -131,6 +134,41 @@ func (f *FakeDockerBuild) Build(*api.Config) (*api.Result, error) {
return nil, f.LayeredBuildError
}

func TestDefaultSource(t *testing.T) {
config := &api.Config{
Source: "file://.",
DockerConfig: &api.DockerConfig{Endpoint: "unix:///var/run/docker.sock"},
}
sti, err := New(config, build.Overrides{})
if err != nil {
t.Fatal(err)
}
if config.Source == "" {
t.Errorf("Config.Source not set: %v", config.Source)
}
if _, ok := sti.source.(*file.File); !ok || sti.source == nil {
t.Errorf("Source interface not set: %#v", sti.source)
}
}

func TestOverrides(t *testing.T) {
fd := &FakeSTI{}
sti, err := New(
&api.Config{
DockerConfig: &api.DockerConfig{Endpoint: "unix:///var/run/docker.sock"},
},
build.Overrides{
Downloader: fd,
},
)
if err != nil {
t.Fatal(err)
}
if sti.source != fd {
t.Errorf("Override of downloader not set: %#v", sti)
}
}

func TestBuild(t *testing.T) {
incrementalTest := []bool{false, true}
for _, incremental := range incrementalTest {
Expand Down Expand Up @@ -681,7 +719,8 @@ func TestExecuteOK(t *testing.T) {
if err != nil {
t.Errorf("Unexpected error returned: %v", err)
}
if th.CreateTarBase != "/working-dir" {
th = rh.tar.(*test.FakeTar).Copy()
if th.CreateTarBase != "" {
t.Errorf("Unexpected tar base directory: %s", th.CreateTarBase)
}
if th.CreateTarDir != "/working-dir/upload" {
Expand All @@ -691,26 +730,26 @@ func TestExecuteOK(t *testing.T) {
if !ok {
t.Fatalf("Unable to convert %v to FakeFilesystem", rh.fs)
}
if fh.OpenFile != "/working-dir/test.tar" {
t.Errorf("Unexpected file opened: %s", fh.OpenFile)
if fh.OpenFile != "" {
t.Fatalf("Unexpected file opened: %s", fh.OpenFile)
}
if !fh.OpenFileResult.CloseCalled {
t.Errorf("Tar file was not closed.")
if fh.OpenFileResult != nil {
t.Errorf("Tar file was opened.")
}
ro := fd.RunContainerOpts

if ro.Image != rh.config.BuilderImage {
t.Errorf("Unexpected Image passed to RunContainer")
}
if ro.Stdin != fh.OpenFileResult {
t.Errorf("Unexpected input stream: %#v", fd.RunContainerOpts.Stdin)
if _, ok := ro.Stdin.(*io.PipeReader); !ok {
t.Errorf("Unexpected input stream: %#v", ro.Stdin)
}
if !ro.PullImage {
t.Errorf("PullImage is not true for RunContainer")
}
if ro.Command != "test-command" {
t.Errorf("Unexpected command passed to RunContainer: %s",
fd.RunContainerOpts.Command)
ro.Command)
}
if pe.PostExecuteContainerID != "1234" {
t.Errorf("PostExecutor not called with expected ID: %s",
Expand All @@ -725,17 +764,15 @@ func TestExecuteErrorCreateTarFile(t *testing.T) {
rh := newFakeSTI(&FakeSTI{})
rh.tar.(*test.FakeTar).CreateTarError = errors.New("CreateTarError")
err := rh.Execute("test-command", rh.config)
if err == nil || err.Error() != "CreateTarError" {
if err != nil {
t.Errorf("An error was expected for CreateTarFile, but got different: %v", err)
}
}

func TestExecuteErrorOpenTarFile(t *testing.T) {
rh := newFakeSTI(&FakeSTI{})
rh.fs.(*test.FakeFileSystem).OpenError = errors.New("OpenTarError")
err := rh.Execute("test-command", rh.config)
if err == nil || err.Error() != "OpenTarError" {
t.Errorf("An error was expected for OpenTarFile, but got different: %v", err)
ro := rh.docker.(*test.FakeDocker).RunContainerOpts
if ro.Stdin == nil {
t.Fatalf("Stream not passed to Docker interface")
}
if _, err := ro.Stdin.Read(make([]byte, 5)); err == nil || err.Error() != "CreateTarError" {
t.Errorf("An error was expected for CreateTarFile, but got different: %#v", ro)
}
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/build/strategies/sti/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type Usage struct {

// NewUsage creates a new instance of the default Usage implementation
func NewUsage(config *api.Config) (*Usage, error) {
b, err := New(config)
b, err := New(config, build.Overrides{})
if err != nil {
return nil, err
}
Expand Down
11 changes: 9 additions & 2 deletions pkg/build/strategies/strategies.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,24 @@ import (
)

// GetStrategy decides what build strategy will be used for the STI build.
// TODO: deprecated, use Strategy() instead
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason you can't just delete this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concern about other callers and trying to get this in before 3.1

func GetStrategy(config *api.Config) (build.Builder, error) {
return Strategy(config, build.Overrides{})
}

// Strategy creates the appropriate build strategy for the provided config, using
// the overrides provided. Not all strategies support all overrides.
func Strategy(config *api.Config, overrides build.Overrides) (build.Builder, error) {
image, err := GetBuilderImage(config)
if err != nil {
return nil, err
}

if image.OnBuild {
return onbuild.New(config)
return onbuild.New(config, overrides)
}

return sti.New(config)
return sti.New(config, overrides)
}

// GetBuilderImage processes the config and performs operations necessary to make
Expand Down
6 changes: 4 additions & 2 deletions pkg/tar/tar.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ type Tar interface {
CreateTarFile(base, dir string) (string, error)

// CreateTarStream creates a tar from the given directory
// and streams it to the given writer
// and streams it to the given writer.
// An error is returned if an error occurs during streaming.
CreateTarStream(dir string, includeDirInPath bool, writer io.Writer) error

// ExtractTarStream extracts files from a given tar stream.
Expand Down Expand Up @@ -87,6 +88,7 @@ func (t *stiTar) shouldExclude(path string) bool {
// CreateTarStream creates a tar stream on the given writer from
// the given directory while excluding files that match the given
// exclusion pattern.
// TODO: this should encapsulate the goroutine that generates the stream.
func (t *stiTar) CreateTarStream(dir string, includeDirInPath bool, writer io.Writer) error {
tarWriter := tar.NewWriter(writer)
defer tarWriter.Close()
Expand Down Expand Up @@ -148,7 +150,7 @@ func (t *stiTar) writeTarHeader(tarWriter *tar.Writer, dir string, path string,
prefix = filepath.Dir(prefix)
}
header.Name = filepath.ToSlash(path[1+len(prefix):])
glog.V(3).Infof("Adding to tar: %s as %s", path, header.Name)
glog.V(5).Infof("Adding to tar: %s as %s", path, header.Name)
if err = tarWriter.WriteHeader(header); err != nil {
return err
}
Expand Down
Loading