diff --git a/cmd/sti/main.go b/cmd/sti/main.go index 6aa83c3aa..1168619b2 100644 --- a/cmd/sti/main.go +++ b/cmd/sti/main.go @@ -4,6 +4,7 @@ import ( "flag" "fmt" "os" + "path/filepath" "strings" "github.com/golang/glog" @@ -38,11 +39,18 @@ func parseEnvs(cmd *cobra.Command, name string) (map[string]string, error) { return envs, nil } -func dockerSocket() string { - if host := os.Getenv("DOCKER_HOST"); host != "" { - return host +func defaultDockerConfig() *api.DockerConfig { + cfg := &api.DockerConfig{} + if cfg.Endpoint = os.Getenv("DOCKER_HOST"); cfg.Endpoint == "" { + cfg.Endpoint = "unix:///var/run/docker.sock" } - return "unix:///var/run/docker.sock" + if os.Getenv("DOCKER_TLS_VERIFY") == "1" { + certPath := os.Getenv("DOCKER_CERT_PATH") + cfg.CertFile = filepath.Join(certPath, "cert.pem") + cfg.KeyFile = filepath.Join(certPath, "key.pem") + cfg.CAFile = filepath.Join(certPath, "ca.pem") + } + return cfg } func validRequest(r *api.Request) bool { @@ -215,7 +223,11 @@ func main() { cmd.Help() }, } - stiCmd.PersistentFlags().StringVarP(&(req.DockerSocket), "url", "U", dockerSocket(), "Set the url of the docker socket to use") + req.DockerConfig = defaultDockerConfig() + stiCmd.PersistentFlags().StringVarP(&(req.DockerConfig.Endpoint), "url", "U", req.DockerConfig.Endpoint, "Set the url of the docker socket to use") + stiCmd.PersistentFlags().StringVar(&(req.DockerConfig.CertFile), "cert", req.DockerConfig.CertFile, "Set the path of the docker TLS certificate file") + stiCmd.PersistentFlags().StringVar(&(req.DockerConfig.KeyFile), "key", req.DockerConfig.KeyFile, "Set the path of the docker TLS key file") + stiCmd.PersistentFlags().StringVar(&(req.DockerConfig.CAFile), "ca", req.DockerConfig.CAFile, "Set the path of the docker TLS ca file") stiCmd.AddCommand(newCmdVersion()) stiCmd.AddCommand(newCmdBuild(req)) diff --git a/pkg/api/types.go b/pkg/api/types.go index 4d9151c73..2229f9929 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -6,8 +6,8 @@ type Request struct { // BaseImage describes which image is used for building the result images. BaseImage string - // DockerSocket describes how to access host docker daemon. - DockerSocket string + // DockerConfig describes how to access host docker daemon. + DockerConfig *DockerConfig // PreserveWorkingDir describes if working directory should be left after processing. PreserveWorkingDir bool @@ -63,6 +63,21 @@ type Request struct { ContextDir string } +// DockerConfig contains the configuration for a Docker connection +type DockerConfig struct { + // Endpoint is the docker network endpoint or socket + Endpoint string + + // CertFile is the certificate file path for a TLS connection + CertFile string + + // KeyFile is the key file path for a TLS connection + KeyFile string + + // CAFile is the certificate authority file path for a TLS connection + CAFile string +} + // Result structure contains information from build process. type Result struct { diff --git a/pkg/build/strategies/layered/layered.go b/pkg/build/strategies/layered/layered.go index b6d9d787e..16fe7856f 100644 --- a/pkg/build/strategies/layered/layered.go +++ b/pkg/build/strategies/layered/layered.go @@ -28,7 +28,7 @@ type Layered struct { } func New(request *api.Request, scripts build.ScriptsHandler) (*Layered, error) { - d, err := docker.New(request.DockerSocket) + d, err := docker.New(request.DockerConfig) if err != nil { return nil, err } diff --git a/pkg/build/strategies/onbuild/onbuild.go b/pkg/build/strategies/onbuild/onbuild.go index 4fb3fb74f..ce4725254 100644 --- a/pkg/build/strategies/onbuild/onbuild.go +++ b/pkg/build/strategies/onbuild/onbuild.go @@ -36,7 +36,7 @@ type onBuildSourceHandler struct { // New returns a new instance of OnBuild builder func New(request *api.Request) (*OnBuild, error) { - dockerHandler, err := docker.New(request.DockerSocket) + dockerHandler, err := docker.New(request.DockerConfig) if err != nil { return nil, err } diff --git a/pkg/build/strategies/sti/sti.go b/pkg/build/strategies/sti/sti.go index 4528b335c..ea8efbba1 100644 --- a/pkg/build/strategies/sti/sti.go +++ b/pkg/build/strategies/sti/sti.go @@ -67,7 +67,7 @@ type STI struct { // be used for the case that the base Docker image does not have 'tar' or 'bash' // installed. func New(req *api.Request) (*STI, error) { - docker, err := docker.New(req.DockerSocket) + docker, err := docker.New(req.DockerConfig) if err != nil { return nil, err } diff --git a/pkg/build/strategies/strategies.go b/pkg/build/strategies/strategies.go index b17fd5505..2c97cb191 100644 --- a/pkg/build/strategies/strategies.go +++ b/pkg/build/strategies/strategies.go @@ -28,7 +28,7 @@ func GetStrategy(request *api.Request) (build.Builder, error) { // It returns information about the base image, containing metadata necessary // for choosing the right STI build strategy. func GetBaseImage(request *api.Request) (*docker.PullResult, error) { - d, err := docker.New(request.DockerSocket) + d, err := docker.New(request.DockerConfig) result := docker.PullResult{} if err != nil { return nil, err diff --git a/pkg/docker/docker.go b/pkg/docker/docker.go index 722b21b53..6a8296965 100644 --- a/pkg/docker/docker.go +++ b/pkg/docker/docker.go @@ -7,7 +7,7 @@ import ( "strings" "sync" - "github.com/fsouza/go-dockerclient" + docker "github.com/fsouza/go-dockerclient" "github.com/golang/glog" "github.com/openshift/source-to-image/pkg/api" @@ -98,8 +98,18 @@ type BuildImageOptions struct { } // New creates a new implementation of the STI Docker interface -func New(endpoint string) (Docker, error) { - client, err := docker.NewClient(endpoint) +func New(config *api.DockerConfig) (Docker, error) { + var client *docker.Client + var err error + if config.CertFile != "" && config.KeyFile != "" && config.CAFile != "" { + client, err = docker.NewTLSClient( + config.Endpoint, + config.CertFile, + config.KeyFile, + config.CAFile) + } else { + client, err = docker.NewClient(config.Endpoint) + } if err != nil { return nil, err } @@ -175,7 +185,12 @@ func (d *stiDocker) PullImage(name string) (image *docker.Image, err error) { // RemoveContainer removes a container and its associated volumes. func (d *stiDocker) RemoveContainer(id string) error { - return d.client.RemoveContainer(docker.RemoveContainerOptions{id, true, true}) + opts := docker.RemoveContainerOptions{ + ID: id, + RemoveVolumes: true, + Force: true, + } + return d.client.RemoveContainer(opts) } // getVariable gets environment variable's value from the image metadata diff --git a/test/integration/integration_test.go b/test/integration/integration_test.go index b29580043..f6fb0135d 100644 --- a/test/integration/integration_test.go +++ b/test/integration/integration_test.go @@ -56,16 +56,34 @@ var ( FakeScriptsFileURL string ) -func dockerSocket() string { - if dh := os.Getenv("DOCKER_HOST"); dh != "" { - return dh +func dockerConfig() *api.DockerConfig { + cfg := &api.DockerConfig{} + if cfg.Endpoint = os.Getenv("DOCKER_HOST"); cfg.Endpoint == "" { + cfg.Endpoint = DefaultDockerSocket } - return DefaultDockerSocket + if os.Getenv("DOCKER_TLS_VERIFY") == "1" { + certPath := os.Getenv("DOCKER_CERT_PATH") + cfg.CertFile = filepath.Join(certPath, "cert.pem") + cfg.KeyFile = filepath.Join(certPath, "key.pem") + cfg.CAFile = filepath.Join(certPath, "ca.pem") + } + return cfg +} + +func dockerClient(config *api.DockerConfig) (*docker.Client, error) { + if config.CertFile != "" && config.KeyFile != "" && config.CAFile != "" { + return docker.NewTLSClient( + config.Endpoint, + config.CertFile, + config.KeyFile, + config.CAFile) + } + return docker.NewClient(config.Endpoint) } // setup sets up integration tests func (i *integrationTest) setup() { - i.dockerClient, _ = docker.NewClient(dockerSocket()) + i.dockerClient, _ = dockerClient(dockerConfig()) if !i.setupComplete { // get the full path to this .go file so we can construct the file url // using this file's dirname @@ -171,7 +189,7 @@ func (i *integrationTest) exerciseCleanBuild(tag string, verifyCallback bool, im } req := &api.Request{ - DockerSocket: dockerSocket(), + DockerConfig: dockerConfig(), BaseImage: imageName, Source: TestSource, Tag: tag, @@ -226,7 +244,7 @@ func TestIncrementalBuildScriptsNoSaveArtifacts(t *testing.T) { func (i *integrationTest) exerciseIncrementalBuild(tag, imageName string, removePreviousImage bool, expectClean bool) { t := i.t req := &api.Request{ - DockerSocket: dockerSocket(), + DockerConfig: dockerConfig(), BaseImage: imageName, Source: TestSource, Tag: tag, @@ -248,7 +266,7 @@ func (i *integrationTest) exerciseIncrementalBuild(tag, imageName string, remove previousImageID := resp.ImageID req = &api.Request{ - DockerSocket: dockerSocket(), + DockerConfig: dockerConfig(), BaseImage: imageName, Source: TestSource, Tag: tag,