Skip to content

Commit b6b05d1

Browse files
authored
Merge pull request #122 from SimonBaeumer/add-docker-registry-auth
Add registry auth, add env support
2 parents d2b4251 + 9079325 commit b6b05d1

42 files changed

Lines changed: 522 additions & 8626 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# v2.1.0
2-
3-
- Added `--dir` flag to execute all commander test suites within a directory. This feature is not recursive.
2+
3+
- Add registry authentication for `docker` nodes
4+
- Add environment support for `Node` configurations
5+
- Add warning if `pass` is set in `Node` as clear text instead of an env variable
6+
- Added `--dir` flag to execute all commander test suites within a directory. This feature is not recursive.
47

58
# v2.0.0
69

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,9 @@ nodes:
729729
docker-host:
730730
type: docker
731731
image: docker.io/library/alpine:3.11.3
732-
user: 1000 # define the owner of the executed command
732+
docker-exec-user: 1000 # define the owner of the executed command
733+
user: user # registry user
734+
pass: password # registry password, it is recommended to use env variables like $REGISTRY_PASS
733735
config:
734736
nodes:
735737
- docker-host

examples/docker.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
nodes:
2+
ubuntu:
3+
type: docker
4+
image: docker.io/simonbaeumer/test-private:latest
5+
user: $COMMANDER_REGISTRY_USER
6+
pass: $COMMANDER_REGISTRY_PASS
7+
8+
tests:
9+
cat /etc/lsb-release:
10+
config:
11+
nodes:
12+
- ubuntu
13+
stdout:
14+
contains:
15+
- Ubuntu
16+
- "18.04"
17+
- bionic
18+
exit-code: 0

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ module github.com/SimonBaeumer/commander
22

33
require (
44
github.com/Microsoft/go-winio v0.4.14 // indirect
5-
github.com/SimonBaeumer/cmd v1.1.0
5+
github.com/SimonBaeumer/cmd v1.2.3
66
github.com/antchfx/xmlquery v1.1.0
77
github.com/antchfx/xpath v1.1.0 // indirect
88
github.com/docker/distribution v2.7.1+incompatible // indirect
99
github.com/docker/docker v1.13.1
1010
github.com/docker/go-connections v0.4.0 // indirect
1111
github.com/docker/go-units v0.4.0 // indirect
12+
github.com/kr/pretty v0.2.0 // indirect
1213
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e
1314
github.com/magiconair/properties v1.8.1 // indirect
1415
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+q
22
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
33
github.com/SimonBaeumer/cmd v1.1.0 h1:tr5dUMlly/8bLiC5B0J1AcE4ISru8POEfzAirWnUJnY=
44
github.com/SimonBaeumer/cmd v1.1.0/go.mod h1:4mc/LDXDWNbkeooqHP83yx3JXtInPHjJkF8zhzqqmZE=
5+
github.com/SimonBaeumer/cmd v1.2.3 h1:Q9/FMZntNPlnbCPzXTCBzx+kRhVX9j3NAh2MCYvnMTA=
6+
github.com/SimonBaeumer/cmd v1.2.3/go.mod h1:4mc/LDXDWNbkeooqHP83yx3JXtInPHjJkF8zhzqqmZE=
57
github.com/antchfx/jsonquery v1.0.0 h1:1Yhk496SrCoY6fJkFZqpXEqbwOw5sFtLns9la4NoK3I=
68
github.com/antchfx/jsonquery v1.0.0/go.mod h1:h7950pvPrUZzJIflNqsELgDQovTpPNa0rAHf8NwjegY=
79
github.com/antchfx/xmlquery v1.1.0 h1:vj0kZ1y3Q6my4AV+a9xbWrMYzubw+84zuiKgvfV8vb8=
@@ -21,6 +23,11 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh
2123
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
2224
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
2325
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
26+
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
27+
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
28+
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
29+
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
30+
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
2431
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k=
2532
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
2633
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
@@ -61,6 +68,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
6168
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
6269
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
6370
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
71+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
6472
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
6573
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
6674
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

integration/linux/docker.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ nodes:
22
docker-host:
33
type: docker
44
image: docker.io/library/alpine:3.11.3
5-
user: 1001
5+
docker-exec-user: 1001
66

77
config:
88
nodes:

pkg/runtime/docker_executor.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package runtime
33
import (
44
"bytes"
55
"context"
6+
"encoding/base64"
7+
"encoding/json"
68
"fmt"
79
"github.com/docker/docker/api/types"
810
"github.com/docker/docker/api/types/container"
@@ -15,9 +17,11 @@ import (
1517

1618
// DockerExecutor executes the test inside a docker container
1719
type DockerExecutor struct {
18-
Image string // Image which is started to execute the test
19-
Privileged bool // Enable privileged mode for the container
20-
User string // User defines which user executes the test
20+
Image string // Image which is started to execute the test
21+
Privileged bool // Enable privileged mode for the container
22+
ExecUser string // ExecUser defines which user executes the docker container
23+
RegistryUser string
24+
RegistryPass string
2125
}
2226

2327
// Execute executes the script inside a docker container
@@ -31,8 +35,20 @@ func (e DockerExecutor) Execute(test TestCase) TestResult {
3135
}
3236
}
3337

38+
authConfig := types.AuthConfig{
39+
Username: e.RegistryUser,
40+
Password: e.RegistryPass,
41+
}
42+
encodedJSON, err := json.Marshal(authConfig)
43+
if err != nil {
44+
panic(err)
45+
}
46+
authStr := base64.URLEncoding.EncodeToString(encodedJSON)
47+
3448
log.Printf("Pulling image %s\n", e.Image)
35-
reader, err := cli.ImagePull(ctx, e.Image, types.ImagePullOptions{})
49+
reader, err := cli.ImagePull(ctx, e.Image, types.ImagePullOptions{
50+
RegistryAuth: authStr,
51+
})
3652
if err != nil {
3753
test.Result.Error = fmt.Errorf("could not pull image '%s' with error: '%s'", e.Image, err)
3854
return TestResult{
@@ -53,7 +69,7 @@ func (e DockerExecutor) Execute(test TestCase) TestResult {
5369
Image: e.Image,
5470
WorkingDir: test.Command.Dir,
5571
Env: env,
56-
User: e.User,
72+
User: e.ExecUser,
5773
Cmd: []string{"/bin/sh", "-c", test.Command.Cmd},
5874
Tty: false,
5975
}, nil, nil, "")

pkg/runtime/node.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package runtime
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"strings"
7+
)
8+
9+
// Node represents a configured node with everything needed to connect to the given host
10+
// which is defined in the type property
11+
// If the type is not available the test will fail and stop its execution
12+
type Node struct {
13+
Name string
14+
Type string
15+
User string
16+
Pass string
17+
Addr string
18+
Image string
19+
IdentityFile string
20+
Privileged bool
21+
DockerExecUser string
22+
}
23+
24+
func (n *Node) ExpandEnv() {
25+
n.Name = os.ExpandEnv(n.Name)
26+
n.Type = os.ExpandEnv(n.Type)
27+
n.User = os.ExpandEnv(n.User)
28+
n.Addr = os.ExpandEnv(n.Addr)
29+
n.Image = os.ExpandEnv(n.Image)
30+
n.IdentityFile = os.ExpandEnv(n.IdentityFile)
31+
n.DockerExecUser = os.ExpandEnv(n.DockerExecUser)
32+
33+
if n.Pass != "" && !strings.Contains(n.Pass, "$") {
34+
fmt.Printf("WARNING: Consider using env variables with $VAR or ${VAR} in node %s instead of directly adding passwords to config files.\n", n.Name)
35+
}
36+
n.Pass = os.ExpandEnv(n.Pass)
37+
}

pkg/runtime/node_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package runtime
2+
3+
import (
4+
"github.com/SimonBaeumer/cmd"
5+
"github.com/stretchr/testify/assert"
6+
"os"
7+
"testing"
8+
)
9+
10+
func TestNodeExpandEnv(t *testing.T) {
11+
os.Setenv("NAME", "test")
12+
os.Setenv("TYPE", "docker")
13+
os.Setenv("USER", "user")
14+
os.Setenv("PASS", "pass")
15+
os.Setenv("ADDR", "addr")
16+
os.Setenv("IMAGE", "image")
17+
os.Setenv("IDENTITY_FILE", "identity-file")
18+
os.Setenv("DOCKER_EXEC_USER", "docker-exec-user")
19+
20+
n := Node{
21+
Name: "$NAME",
22+
Type: "$TYPE",
23+
User: "$USER",
24+
Pass: "$PASS",
25+
Addr: "$ADDR",
26+
Image: "$IMAGE",
27+
IdentityFile: "$IDENTITY_FILE",
28+
DockerExecUser: "$DOCKER_EXEC_USER",
29+
}
30+
31+
n.ExpandEnv()
32+
33+
assert.Equal(t, "test", n.Name)
34+
assert.Equal(t, "docker", n.Type)
35+
assert.Equal(t, "user", n.User)
36+
assert.Equal(t, "pass", n.Pass)
37+
assert.Equal(t, "addr", n.Addr)
38+
assert.Equal(t, "image", n.Image)
39+
assert.Equal(t, "identity-file", n.IdentityFile)
40+
assert.Equal(t, "docker-exec-user", n.DockerExecUser)
41+
}
42+
43+
func TestExpandEnv_PrintWarning(t *testing.T) {
44+
n := Node{
45+
Name: "Node01",
46+
Pass: "clean password",
47+
}
48+
49+
out, _ := cmd.CaptureStandardOutput(func() interface{} {
50+
n.ExpandEnv()
51+
return nil
52+
})
53+
54+
assert.Equal(t, "WARNING: Consider using env variables with $VAR or ${VAR} in node Node01 instead of directly adding passwords to config files.\n", out)
55+
}

pkg/runtime/runtime.go

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,6 @@ type TestCase struct {
5757
Nodes []string
5858
}
5959

60-
// Node represents a configured node with everything needed to connect to the given host
61-
// which is defined in the type property
62-
// If the type is not available the test will fail and stop its execution
63-
type Node struct {
64-
Name string
65-
Type string
66-
User string
67-
Pass string
68-
Addr string
69-
Image string
70-
IdentityFile string
71-
Privileged bool
72-
}
73-
7460
//GlobalTestConfig represents the configuration for a test
7561
type GlobalTestConfig struct {
7662
Env map[string]string
@@ -204,9 +190,11 @@ func (r *Runtime) getExecutor(node string) Executor {
204190
case "docker":
205191
log.Println("Use docker executor")
206192
return DockerExecutor{
207-
Image: n.Image,
208-
Privileged: n.Privileged,
209-
User: n.User,
193+
Image: n.Image,
194+
Privileged: n.Privileged,
195+
ExecUser: n.DockerExecUser,
196+
RegistryPass: n.Pass,
197+
RegistryUser: n.User,
210198
}
211199
case "":
212200
return NewLocalExecutor()
@@ -217,7 +205,7 @@ func (r *Runtime) getExecutor(node string) Executor {
217205
}
218206

219207
log.Fatal(fmt.Sprintf("Node %s not found", node))
220-
return LocalExecutor{}
208+
return NewLocalExecutor()
221209
}
222210

223211
func executeRetryInterval(t TestCase) {

0 commit comments

Comments
 (0)