Skip to content

Commit cee4861

Browse files
author
OpenShift Bot
authored
Merge pull request #9947 from smarterclayton/override_repo
Merged by openshift-bot
2 parents 9e17245 + 5fb8206 commit cee4861

File tree

14 files changed

+145
-16
lines changed

14 files changed

+145
-16
lines changed

Makefile

+5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ OS_OUTPUT_GOPATH ?= 1
1313

1414
export GOFLAGS
1515
export TESTFLAGS
16+
# If set to 1, create an isolated GOPATH inside _output using symlinks to avoid
17+
# other packages being accidentally included. Defaults to on.
1618
export OS_OUTPUT_GOPATH
19+
# May be used to set additional arguments passed to the image build commands for
20+
# mounting secrets specific to a build environment.
21+
export OS_BUILD_IMAGE_ARGS
1722

1823
# Build code.
1924
#

contrib/completions/bash/oc

+1
Original file line numberDiff line numberDiff line change
@@ -10624,6 +10624,7 @@ _oc_ex_dockerbuild()
1062410624
flags+=("--dockerfile=")
1062510625
flags_with_completion+=("--dockerfile")
1062610626
flags_completion+=("_filedir")
10627+
flags+=("--mount=")
1062710628
flags+=("--api-version=")
1062810629
flags+=("--as=")
1062910630
flags+=("--certificate-authority=")

contrib/completions/bash/openshift

+1
Original file line numberDiff line numberDiff line change
@@ -14957,6 +14957,7 @@ _openshift_cli_ex_dockerbuild()
1495714957
flags+=("--dockerfile=")
1495814958
flags_with_completion+=("--dockerfile")
1495914959
flags_completion+=("_filedir")
14960+
flags+=("--mount=")
1496014961
flags+=("--api-version=")
1496114962
flags+=("--as=")
1496214963
flags+=("--certificate-authority=")

contrib/completions/zsh/oc

+1
Original file line numberDiff line numberDiff line change
@@ -10785,6 +10785,7 @@ _oc_ex_dockerbuild()
1078510785
flags+=("--dockerfile=")
1078610786
flags_with_completion+=("--dockerfile")
1078710787
flags_completion+=("_filedir")
10788+
flags+=("--mount=")
1078810789
flags+=("--api-version=")
1078910790
flags+=("--as=")
1079010791
flags+=("--certificate-authority=")

contrib/completions/zsh/openshift

+1
Original file line numberDiff line numberDiff line change
@@ -15118,6 +15118,7 @@ _openshift_cli_ex_dockerbuild()
1511815118
flags+=("--dockerfile=")
1511915119
flags_with_completion+=("--dockerfile")
1512015120
flags_completion+=("_filedir")
15121+
flags+=("--mount=")
1512115122
flags+=("--api-version=")
1512215123
flags+=("--as=")
1512315124
flags+=("--certificate-authority=")

docs/generated/oc_by_example_content.adoc

+3
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,9 @@ Perform a direct Docker build
13481348
----
13491349
# Build the current directory into a single layer and tag
13501350
oc ex dockerbuild . myimage:latest
1351+
1352+
# Mount a client secret into the build at a certain path
1353+
oc ex dockerbuild . myimage:latest --mount ~/mysecret.pem:/etc/pki/secret/mysecret.pem
13511354
----
13521355
====
13531356

docs/man/man1/oc-ex-dockerbuild.1

+13-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ Build a Dockerfile into a single layer
1717

1818
.PP
1919
Builds the provided directory with a Dockerfile into a single layered image.
20-
Requires that you have a working connection to a Docker engine.
20+
Requires that you have a working connection to a Docker engine. You may mount
21+
secrets or config into the build with the \-\-mount flag \- these files will not
22+
be included in the final image.
23+
24+
.PP
25+
Experimental: This command is under active development and may change without notice.
2126

2227

2328
.SH OPTIONS
@@ -29,6 +34,10 @@ Requires that you have a working connection to a Docker engine.
2934
\fB\-\-dockerfile\fP=""
3035
An optional path to a Dockerfile to use.
3136

37+
.PP
38+
\fB\-\-mount\fP=[]
39+
An optional list of files and directories to mount during the build. Use SRC:DST syntax for each path.
40+
3241

3342
.SH OPTIONS INHERITED FROM PARENT COMMANDS
3443
.PP
@@ -104,6 +113,9 @@ Requires that you have a working connection to a Docker engine.
104113
# Build the current directory into a single layer and tag
105114
oc ex dockerbuild . myimage:latest
106115

116+
# Mount a client secret into the build at a certain path
117+
oc ex dockerbuild . myimage:latest \-\-mount \~/mysecret.pem:/etc/pki/secret/mysecret.pem
118+
107119
.fi
108120
.RE
109121

docs/man/man1/openshift-cli-ex-dockerbuild.1

+13-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ Build a Dockerfile into a single layer
1717

1818
.PP
1919
Builds the provided directory with a Dockerfile into a single layered image.
20-
Requires that you have a working connection to a Docker engine.
20+
Requires that you have a working connection to a Docker engine. You may mount
21+
secrets or config into the build with the \-\-mount flag \- these files will not
22+
be included in the final image.
23+
24+
.PP
25+
Experimental: This command is under active development and may change without notice.
2126

2227

2328
.SH OPTIONS
@@ -29,6 +34,10 @@ Requires that you have a working connection to a Docker engine.
2934
\fB\-\-dockerfile\fP=""
3035
An optional path to a Dockerfile to use.
3136

37+
.PP
38+
\fB\-\-mount\fP=[]
39+
An optional list of files and directories to mount during the build. Use SRC:DST syntax for each path.
40+
3241

3342
.SH OPTIONS INHERITED FROM PARENT COMMANDS
3443
.PP
@@ -104,6 +113,9 @@ Requires that you have a working connection to a Docker engine.
104113
# Build the current directory into a single layer and tag
105114
openshift cli ex dockerbuild . myimage:latest
106115

116+
# Mount a client secret into the build at a certain path
117+
openshift cli ex dockerbuild . myimage:latest \-\-mount \~/mysecret.pem:/etc/pki/secret/mysecret.pem
118+
107119
.fi
108120
.RE
109121

hack/build-base-images.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ if [[ -z "${oc}" ]]; then
2424
fi
2525

2626
function build() {
27-
"${oc}" ex dockerbuild $2 $1
27+
eval "'${oc}' ex dockerbuild $2 $1 ${OS_BUILD_IMAGE_ARGS:-}"
2828
}
2929

3030
# Build the images

hack/build-images.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ if [[ -z "${oc}" ]]; then
6161
fi
6262

6363
function build() {
64-
"${oc}" ex dockerbuild $2 $1
64+
eval "'${oc}' ex dockerbuild $2 $1 ${OS_BUILD_IMAGE_ARGS:-}"
6565
}
6666

6767
# Create link to file if the FS supports hardlinks, otherwise copy the file

images/base/Dockerfile

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
#
22
# This is the base image from which all OpenShift Origin images inherit. Only packages
3-
# common to all downstream images should be here. Depends on Centos 7.2+
3+
# common to all downstream images should be here. Depends on Centos 7.2+.
44
#
55
# The standard name for this image is openshift/origin-base
66
#
77
FROM centos:centos7
88

9-
# Until nss-3.21.0-9.el7_2 and openssl-libs-1.0.1e-51.el7_2.5.x86_64 is
10-
# released in the base image we need to manually update this to workaround an
11-
# issue where some of the mirrors are using a certificate
12-
RUN yum update -y nss openssl-libs && \
13-
yum clean all
14-
159
RUN INSTALL_PKGS="which git tar wget hostname sysvinit-tools util-linux bsdtar epel-release \
1610
socat ethtool device-mapper iptables tree findutils nmap-ncat e2fsprogs xfsprogs lsof" && \
1711
yum install -y $INSTALL_PKGS && \

images/openvswitch/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#
44
# The standard name for this image is openshift/openvswitch
55
#
6-
FROM centos:centos7
6+
FROM openshift/origin-base
77

88
COPY scripts/* /usr/local/bin/
99

pkg/cmd/cli/cmd/dockerbuild/dockerbuild.go

+25-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,17 @@ const (
2525
Build a Dockerfile into a single layer
2626
2727
Builds the provided directory with a Dockerfile into a single layered image.
28-
Requires that you have a working connection to a Docker engine.`
28+
Requires that you have a working connection to a Docker engine. You may mount
29+
secrets or config into the build with the --mount flag - these files will not
30+
be included in the final image.
31+
32+
Experimental: This command is under active development and may change without notice.`
2933

3034
dockerbuildExample = ` # Build the current directory into a single layer and tag
31-
%[1]s ex dockerbuild . myimage:latest`
35+
%[1]s ex dockerbuild . myimage:latest
36+
37+
# Mount a client secret into the build at a certain path
38+
%[1]s ex dockerbuild . myimage:latest --mount ~/mysecret.pem:/etc/pki/secret/mysecret.pem`
3239
)
3340

3441
type DockerbuildOptions struct {
@@ -37,6 +44,9 @@ type DockerbuildOptions struct {
3744

3845
Client *docker.Client
3946

47+
MountSpecs []string
48+
49+
Mounts []builder.Mount
4050
Directory string
4151
Tag string
4252
DockerfilePath string
@@ -68,6 +78,7 @@ func NewCmdDockerbuild(fullName string, f *clientcmd.Factory, out, errOut io.Wri
6878
},
6979
}
7080

81+
cmd.Flags().StringSliceVar(&options.MountSpecs, "mount", options.MountSpecs, "An optional list of files and directories to mount during the build. Use SRC:DST syntax for each path.")
7182
cmd.Flags().StringVar(&options.DockerfilePath, "dockerfile", options.DockerfilePath, "An optional path to a Dockerfile to use.")
7283
cmd.Flags().BoolVar(&options.AllowPull, "allow-pull", true, "Pull the images that are not present.")
7384
cmd.MarkFlagFilename("dockerfile")
@@ -89,6 +100,17 @@ func (o *DockerbuildOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command,
89100
if len(o.DockerfilePath) == 0 {
90101
o.DockerfilePath = filepath.Join(o.Directory, "Dockerfile")
91102
}
103+
104+
var mounts []builder.Mount
105+
for _, s := range o.MountSpecs {
106+
segments := strings.Split(s, ":")
107+
if len(segments) != 2 {
108+
return kcmdutil.UsageError(cmd, "--mount must be of the form SOURCE:DEST")
109+
}
110+
mounts = append(mounts, builder.Mount{SourcePath: segments[0], DestinationPath: segments[1]})
111+
}
112+
o.Mounts = mounts
113+
92114
client, err := docker.NewClientFromEnv()
93115
if err != nil {
94116
return err
@@ -114,6 +136,7 @@ func (o *DockerbuildOptions) Run() error {
114136
e.Out, e.ErrOut = o.Out, o.Err
115137
e.AllowPull = o.AllowPull
116138
e.Directory = o.Directory
139+
e.TransientMounts = o.Mounts
117140
e.Tag = o.Tag
118141
e.AuthFn = o.Keyring.Lookup
119142
e.LogFn = func(format string, args ...interface{}) {

pkg/util/docker/dockerfile/builder/client.go

+78-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import (
88
"io"
99
"os"
1010
"path"
11+
"path/filepath"
1112
"runtime"
13+
"strconv"
1214
"strings"
1315

1416
"k8s.io/kubernetes/pkg/credentialprovider"
@@ -22,6 +24,12 @@ import (
2224
"github.com/openshift/origin/pkg/util/docker/dockerfile/builder/imageprogress"
2325
)
2426

27+
// Mount represents a binding between the current system and the destination client
28+
type Mount struct {
29+
SourcePath string
30+
DestinationPath string
31+
}
32+
2533
// ClientExecutor can run Docker builds from a Docker client.
2634
type ClientExecutor struct {
2735
// Client is a client to a Docker daemon.
@@ -38,6 +46,11 @@ type ClientExecutor struct {
3846
// AllowPull when set will pull images that are not present on
3947
// the daemon.
4048
AllowPull bool
49+
// TransientMounts are a set of mounts from outside the build
50+
// to the inside that will not be part of the final image. Any
51+
// content created inside the mount's destinationPath will be
52+
// omitted from the final image.
53+
TransientMounts []Mount
4154

4255
Out, ErrOut io.Writer
4356

@@ -125,6 +138,8 @@ func (e *ClientExecutor) Build(r io.Reader, args map[string]string) error {
125138
e.LogFn("FROM %s", from)
126139
glog.V(4).Infof("step: FROM %s", from)
127140

141+
var sharedMount string
142+
128143
// create a container to execute in, if necessary
129144
mustStart := b.RequiresStart(node)
130145
if e.Container == nil {
@@ -134,6 +149,23 @@ func (e *ClientExecutor) Build(r io.Reader, args map[string]string) error {
134149
},
135150
}
136151
if mustStart {
152+
// Transient mounts only make sense on images that will be running processes
153+
if len(e.TransientMounts) > 0 {
154+
volumeName, err := randSeq(imageSafeCharacters, 24)
155+
if err != nil {
156+
return err
157+
}
158+
v, err := e.Client.CreateVolume(docker.CreateVolumeOptions{Name: volumeName})
159+
if err != nil {
160+
return err
161+
}
162+
defer e.cleanupVolume(volumeName)
163+
sharedMount = v.Mountpoint
164+
opts.HostConfig = &docker.HostConfig{
165+
Binds: []string{sharedMount + ":/tmp/__temporarymount"},
166+
}
167+
}
168+
137169
// TODO: windows support
138170
if len(e.Command) > 0 {
139171
opts.Config.Cmd = e.Command
@@ -157,9 +189,40 @@ func (e *ClientExecutor) Build(r io.Reader, args map[string]string) error {
157189
defer e.Cleanup()
158190
}
159191

192+
// copy any source content into the temporary mount path
193+
if mustStart && len(e.TransientMounts) > 0 {
194+
var copies []Copy
195+
for i, mount := range e.TransientMounts {
196+
source := mount.SourcePath
197+
copies = append(copies, Copy{
198+
Src: source,
199+
Dest: []string{path.Join("/tmp/__temporarymount", strconv.Itoa(i))},
200+
})
201+
}
202+
if err := e.Copy(copies...); err != nil {
203+
return err
204+
}
205+
}
206+
160207
// TODO: lazy start
161208
if mustStart && !e.Container.State.Running {
162-
if err := e.Client.StartContainer(e.Container.ID, e.HostConfig); err != nil {
209+
var hostConfig docker.HostConfig
210+
if e.HostConfig != nil {
211+
hostConfig = *e.HostConfig
212+
}
213+
214+
// mount individual items temporarily
215+
for i, mount := range e.TransientMounts {
216+
if len(sharedMount) == 0 {
217+
return fmt.Errorf("no mount point available for temporary mounts")
218+
}
219+
hostConfig.Binds = append(
220+
hostConfig.Binds,
221+
fmt.Sprintf("%s:%s:%s", path.Join(sharedMount, strconv.Itoa(i)), mount.DestinationPath, "ro"),
222+
)
223+
}
224+
225+
if err := e.Client.StartContainer(e.Container.ID, &hostConfig); err != nil {
163226
return err
164227
}
165228
// TODO: is this racy? may have to loop wait in the actual run step
@@ -276,6 +339,11 @@ func randSeq(source string, n int) (string, error) {
276339
return string(random), nil
277340
}
278341

342+
// cleanupVolume attempts to remove the provided volume
343+
func (e *ClientExecutor) cleanupVolume(name string) error {
344+
return e.Client.RemoveVolume(name)
345+
}
346+
279347
// CleanupImage attempts to remove the provided image.
280348
func (e *ClientExecutor) CleanupImage(name string) error {
281349
return e.Client.RemoveImage(name)
@@ -448,7 +516,15 @@ func (e *ClientExecutor) Archive(src, dst string, allowDecompression, allowDownl
448516
closer = append(closer, func() error { return os.RemoveAll(base) })
449517
}
450518
} else {
451-
base = e.Directory
519+
if filepath.IsAbs(src) {
520+
base = filepath.Dir(src)
521+
src, err = filepath.Rel(base, src)
522+
if err != nil {
523+
return nil, nil, err
524+
}
525+
} else {
526+
base = e.Directory
527+
}
452528
infos, err = CalcCopyInfo(src, base, allowDecompression, true)
453529
}
454530
if err != nil {

0 commit comments

Comments
 (0)