Skip to content

Commit 1b3a305

Browse files
authored
pkg,images: use openshift style user init and entrypoint (#969)
* pkg,images: use openshift style user init and entrypoint This updates the scaffolds for the go operator and the scorecard proxy to use openshift style user init and entrypoints (similar to the ansible and helm operators)
1 parent c5cc09b commit 1b3a305

File tree

11 files changed

+275
-21
lines changed

11 files changed

+275
-21
lines changed

commands/operator-sdk/cmd/new.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ func doScaffold() {
131131
err := s.Execute(cfg,
132132
&scaffold.Cmd{},
133133
&scaffold.Dockerfile{},
134+
&scaffold.Entrypoint{},
135+
&scaffold.UserSetup{},
134136
&scaffold.ServiceAccount{},
135137
&scaffold.Role{
136138
IsClusterScoped: isClusterScoped,

images/scorecard-proxy/Dockerfile

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
# Base image
22
FROM alpine:3.8
33

4-
RUN apk upgrade --update --no-cache
5-
USER nobody
4+
ENV PROXY=/usr/local/bin/scorecard-proxy \
5+
USER_UID=1001 \
6+
USER_NAME=proxy
67

7-
COPY scorecard-proxy /usr/local/bin/scorecard-proxy
8+
# install operator binary
9+
COPY scorecard-proxy ${PROXY}
10+
11+
COPY bin /usr/local/bin
12+
RUN /usr/local/bin/user_setup
13+
14+
ENTRYPOINT ["/usr/local/bin/entrypoint"]
15+
16+
USER ${USER_UID}

images/scorecard-proxy/bin/entrypoint

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/sh -e
2+
3+
# This is documented here:
4+
# https://docs.openshift.com/container-platform/3.11/creating_images/guidelines.html#openshift-specific-guidelines
5+
6+
if ! whoami &>/dev/null; then
7+
if [ -w /etc/passwd ]; then
8+
echo "${USER_NAME:-proxy}:x:$(id -u):$(id -g):${USER_NAME:-proxy} user:${HOME}:/sbin/nologin" >> /etc/passwd
9+
fi
10+
fi
11+
12+
exec ${PROXY} $@

images/scorecard-proxy/bin/user_setup

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/sh
2+
set -x
3+
4+
# ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be)
5+
mkdir -p ${HOME}
6+
chown ${USER_UID}:0 ${HOME}
7+
chmod ug+rwx ${HOME}
8+
9+
# runtime user will need to be able to self-insert in /etc/passwd
10+
chmod g+rw /etc/passwd
11+
12+
# no need for this script to remain in the image after running
13+
rm $0

pkg/scaffold/build_dockerfile.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,17 @@ func (s *Dockerfile) GetInput() (input.Input, error) {
3636

3737
const dockerfileTmpl = `FROM alpine:3.8
3838
39-
RUN apk upgrade --update --no-cache
39+
ENV OPERATOR=/usr/local/bin/{{.ProjectName}} \
40+
USER_UID=1001 \
41+
USER_NAME={{.ProjectName}}
4042
41-
USER nobody
43+
# install operator binary
44+
COPY build/_output/bin/{{.ProjectName}} ${OPERATOR}
4245
43-
ADD build/_output/bin/{{.ProjectName}} /usr/local/bin/{{.ProjectName}}
46+
COPY build/bin /usr/local/bin
47+
RUN /usr/local/bin/user_setup
48+
49+
ENTRYPOINT ["/usr/local/bin/entrypoint"]
50+
51+
USER ${USER_UID}
4452
`

pkg/scaffold/build_dockerfile_test.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,17 @@ func TestDockerfile(t *testing.T) {
3535

3636
const dockerfileExp = `FROM alpine:3.8
3737
38-
RUN apk upgrade --update --no-cache
38+
ENV OPERATOR=/usr/local/bin/app-operator \
39+
USER_UID=1001 \
40+
USER_NAME=app-operator
3941
40-
USER nobody
42+
# install operator binary
43+
COPY build/_output/bin/app-operator ${OPERATOR}
4144
42-
ADD build/_output/bin/app-operator /usr/local/bin/app-operator
45+
COPY build/bin /usr/local/bin
46+
RUN /usr/local/bin/user_setup
47+
48+
ENTRYPOINT ["/usr/local/bin/entrypoint"]
49+
50+
USER ${USER_UID}
4351
`

pkg/scaffold/constants.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,17 @@ const (
2323
filePathSep = string(filepath.Separator)
2424

2525
// dirs
26-
CmdDir = "cmd"
27-
ManagerDir = CmdDir + filePathSep + "manager"
28-
PkgDir = "pkg"
29-
ApisDir = PkgDir + filePathSep + "apis"
30-
ControllerDir = PkgDir + filePathSep + "controller"
31-
BuildDir = "build"
32-
BuildTestDir = BuildDir + filePathSep + "test-framework"
33-
BuildBinDir = BuildDir + filePathSep + "_output" + filePathSep + "bin"
34-
DeployDir = "deploy"
35-
OlmCatalogDir = DeployDir + filePathSep + "olm-catalog"
36-
CrdsDir = DeployDir + filePathSep + "crds"
37-
VersionDir = "version"
26+
CmdDir = "cmd"
27+
ManagerDir = CmdDir + filePathSep + "manager"
28+
PkgDir = "pkg"
29+
ApisDir = PkgDir + filePathSep + "apis"
30+
ControllerDir = PkgDir + filePathSep + "controller"
31+
BuildDir = "build"
32+
BuildTestDir = BuildDir + filePathSep + "test-framework"
33+
BuildBinDir = BuildDir + filePathSep + "_output" + filePathSep + "bin"
34+
BuildScriptDir = BuildDir + filePathSep + "bin"
35+
DeployDir = "deploy"
36+
OlmCatalogDir = DeployDir + filePathSep + "olm-catalog"
37+
CrdsDir = DeployDir + filePathSep + "crds"
38+
VersionDir = "version"
3839
)

pkg/scaffold/entrypoint.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2019 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package scaffold
16+
17+
import (
18+
"path/filepath"
19+
20+
"github.com/operator-framework/operator-sdk/pkg/scaffold/input"
21+
)
22+
23+
const EntrypointFile = "entrypoint"
24+
25+
// Entrypoint - entrypoint script
26+
type Entrypoint struct {
27+
input.Input
28+
}
29+
30+
func (e *Entrypoint) GetInput() (input.Input, error) {
31+
if e.Path == "" {
32+
e.Path = filepath.Join(BuildScriptDir, EntrypointFile)
33+
}
34+
e.TemplateBody = entrypointTmpl
35+
e.IsExec = true
36+
return e.Input, nil
37+
}
38+
39+
const entrypointTmpl = `#!/bin/sh -e
40+
41+
# This is documented here:
42+
# https://docs.openshift.com/container-platform/3.11/creating_images/guidelines.html#openshift-specific-guidelines
43+
44+
if ! whoami &>/dev/null; then
45+
if [ -w /etc/passwd ]; then
46+
echo "${USER_NAME:-{{.ProjectName}}}:x:$(id -u):$(id -g):${USER_NAME:-{{.ProjectName}}} user:${HOME}:/sbin/nologin" >> /etc/passwd
47+
fi
48+
fi
49+
50+
exec ${OPERATOR} $@
51+
`

pkg/scaffold/entrypoint_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2019 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package scaffold
16+
17+
import (
18+
"testing"
19+
20+
"github.com/operator-framework/operator-sdk/internal/util/diffutil"
21+
)
22+
23+
func EntrypointTest(t *testing.T) {
24+
s, buf := setupScaffoldAndWriter()
25+
err := s.Execute(appConfig, &Entrypoint{})
26+
if err != nil {
27+
t.Fatalf("Failed to execute the scaffold: (%v)", err)
28+
}
29+
30+
if entrypointExp != buf.String() {
31+
diffs := diffutil.Diff(entrypointExp, buf.String())
32+
t.Fatalf("Expected vs actual differs.\n%v", diffs)
33+
}
34+
}
35+
36+
const entrypointExp = `#!/bin/sh -e
37+
38+
# This is documented here:
39+
# https://docs.openshift.com/container-platform/3.11/creating_images/guidelines.html#openshift-specific-guidelines
40+
41+
if ! whoami &>/dev/null; then
42+
if [ -w /etc/passwd ]; then
43+
echo "${USER_NAME:-app-operator}:x:$(id -u):$(id -g):${USER_NAME:-app-operator} user:${HOME}:/sbin/nologin" >> /etc/passwd
44+
fi
45+
fi
46+
47+
exec ${OPERATOR} $@
48+
49+
`

pkg/scaffold/usersetup.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2019 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package scaffold
16+
17+
import (
18+
"path/filepath"
19+
20+
"github.com/operator-framework/operator-sdk/pkg/scaffold/input"
21+
)
22+
23+
const UserSetupFile = "user_setup"
24+
25+
// UserSetup - userSetup script
26+
type UserSetup struct {
27+
input.Input
28+
}
29+
30+
func (u *UserSetup) GetInput() (input.Input, error) {
31+
if u.Path == "" {
32+
u.Path = filepath.Join(BuildScriptDir, UserSetupFile)
33+
}
34+
u.TemplateBody = userSetupTmpl
35+
u.IsExec = true
36+
return u.Input, nil
37+
}
38+
39+
const userSetupTmpl = `#!/bin/sh
40+
set -x
41+
42+
# ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be)
43+
mkdir -p ${HOME}
44+
chown ${USER_UID}:0 ${HOME}
45+
chmod ug+rwx ${HOME}
46+
47+
# runtime user will need to be able to self-insert in /etc/passwd
48+
chmod g+rw /etc/passwd
49+
50+
# no need for this script to remain in the image after running
51+
rm $0
52+
`

pkg/scaffold/usersetup_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2019 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package scaffold
16+
17+
import (
18+
"testing"
19+
20+
"github.com/operator-framework/operator-sdk/internal/util/diffutil"
21+
)
22+
23+
func UserSetupTest(t *testing.T) {
24+
s, buf := setupScaffoldAndWriter()
25+
err := s.Execute(appConfig, &UserSetup{})
26+
if err != nil {
27+
t.Fatalf("Failed to execute the scaffold: (%v)", err)
28+
}
29+
30+
if userSetupExp != buf.String() {
31+
diffs := diffutil.Diff(userSetupExp, buf.String())
32+
t.Fatalf("Expected vs actual differs.\n%v", diffs)
33+
}
34+
}
35+
36+
const userSetupExp = `#!/bin/sh
37+
set -x
38+
39+
# ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be)
40+
mkdir -p ${HOME}
41+
chown ${USER_UID}:0 ${HOME}
42+
chmod ug+rwx ${HOME}
43+
44+
# runtime user will need to be able to self-insert in /etc/passwd
45+
chmod g+rw /etc/passwd
46+
47+
# no need for this script to remain in the image after running
48+
rm $0
49+
`

0 commit comments

Comments
 (0)