Skip to content

Commit d079d77

Browse files
authoredAug 15, 2019
Merge pull request #2597 from corneliusweig/w/minikube-structure-test
Pass minikube docker configuration to container-structure-test
2 parents 9600d0d + 9e8a1f9 commit d079d77

File tree

8 files changed

+161
-58
lines changed

8 files changed

+161
-58
lines changed
 

‎pkg/skaffold/test/structure/structure.go

+18-1
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ package structure
1919
import (
2020
"context"
2121
"io"
22+
"os"
2223
"os/exec"
2324

24-
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
2525
"github.com/pkg/errors"
2626
"github.com/sirupsen/logrus"
27+
28+
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
2729
)
2830

2931
// Test is the entrypoint for running structure tests
@@ -38,10 +40,25 @@ func (tr *Runner) Test(ctx context.Context, out io.Writer, image string) error {
3840
cmd := exec.CommandContext(ctx, "container-structure-test", args...)
3941
cmd.Stdout = out
4042
cmd.Stderr = out
43+
cmd.Env = tr.env()
4144

4245
if err := util.RunCmd(cmd); err != nil {
4346
return errors.Wrap(err, "running container-structure-test")
4447
}
4548

4649
return nil
4750
}
51+
52+
// env returns a merged environment of the current process environment and any extra environment.
53+
// This ensures that the correct docker environment configuration is passed to container-structure-test,
54+
// for example when running on minikube.
55+
func (tr *Runner) env() []string {
56+
if tr.extraEnv == nil {
57+
return nil
58+
}
59+
60+
parentEnv := os.Environ()
61+
mergedEnv := make([]string, len(parentEnv), len(parentEnv)+len(tr.extraEnv))
62+
copy(mergedEnv, parentEnv)
63+
return append(mergedEnv, tr.extraEnv...)
64+
}

‎pkg/skaffold/test/structure/types.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ limitations under the License.
1717
package structure
1818

1919
type Runner struct {
20-
testFiles []string
20+
testFiles, extraEnv []string
2121
}
2222

2323
// NewRunner creates a new structure.Runner.
24-
func NewRunner(files []string) *Runner {
24+
func NewRunner(files, extraEnv []string) *Runner {
2525
return &Runner{
2626
testFiles: files,
27+
extraEnv: extraEnv,
2728
}
2829
}
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright 2019 The Skaffold Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package structure
18+
19+
import (
20+
"context"
21+
"io/ioutil"
22+
"testing"
23+
24+
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
25+
"github.com/GoogleContainerTools/skaffold/testutil"
26+
)
27+
28+
func TestNewRunner(t *testing.T) {
29+
const (
30+
imageName = "foo.io/baz"
31+
structureTestName = "foo.testcase"
32+
)
33+
34+
testutil.Run(t, "", func(t *testutil.T) {
35+
extraEnv := []string{"SOME=env_var", "OTHER=env_value"}
36+
fakeCmd := t.NewFakeCmd().
37+
WithRunEnv("container-structure-test test -v warn --image "+imageName+" --config "+structureTestName, extraEnv)
38+
t.Override(&util.DefaultExecCommand, fakeCmd)
39+
40+
testRunner := NewRunner([]string{structureTestName}, extraEnv)
41+
err := testRunner.Test(context.Background(), ioutil.Discard, imageName)
42+
t.CheckNoError(err)
43+
})
44+
}

‎pkg/skaffold/test/test.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,29 @@ import (
2020
"context"
2121
"io"
2222

23+
"github.com/pkg/errors"
24+
2325
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build"
26+
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker"
2427
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner/runcontext"
2528
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
2629
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/test/structure"
2730
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
28-
29-
"github.com/pkg/errors"
3031
)
3132

3233
// NewTester parses the provided test cases from the Skaffold config,
3334
// and returns a Tester instance with all the necessary test runners
3435
// to run all specified tests.
3536
func NewTester(runCtx *runcontext.RunContext) Tester {
37+
client, err := docker.NewAPIClient(runCtx)
38+
if err != nil {
39+
return nil
40+
}
41+
3642
return FullTester{
3743
testCases: runCtx.Cfg.Test,
3844
workingDir: runCtx.WorkingDir,
45+
extraEnv: client.ExtraEnv(),
3946
}
4047
}
4148

@@ -79,7 +86,7 @@ func (t FullTester) runStructureTests(ctx context.Context, out io.Writer, bRes [
7986

8087
fqn := resolveArtifactImageTag(testCase.ImageName, bRes)
8188

82-
runner := structure.NewRunner(files)
89+
runner := structure.NewRunner(files, t.extraEnv)
8390
return runner.Test(ctx, out, fqn)
8491
}
8592

‎pkg/skaffold/test/test_test.go

+49-52
Original file line numberDiff line numberDiff line change
@@ -87,66 +87,63 @@ func TestNoTest(t *testing.T) {
8787
}
8888

8989
func TestTestSuccess(t *testing.T) {
90-
tmpDir, cleanup := testutil.NewTempDir(t)
91-
defer cleanup()
92-
93-
tmpDir.Touch("tests/test1.yaml", "tests/test2.yaml", "test3.yaml")
94-
95-
defer func(c util.Command) { util.DefaultExecCommand = c }(util.DefaultExecCommand)
96-
util.DefaultExecCommand = testutil.
97-
NewFakeCmd(t).
98-
WithRun("container-structure-test test -v warn --image TAG --config " + tmpDir.Path("tests/test1.yaml") + " --config " + tmpDir.Path("tests/test2.yaml")).
99-
WithRun("container-structure-test test -v warn --image TAG --config " + tmpDir.Path("test3.yaml"))
100-
101-
runCtx := &runcontext.RunContext{
102-
WorkingDir: tmpDir.Root(),
103-
Cfg: latest.Pipeline{
104-
Test: []*latest.TestCase{
105-
{
106-
ImageName: "image",
107-
StructureTests: []string{"./tests/*"},
108-
},
109-
{},
110-
{
111-
ImageName: "image",
112-
StructureTests: []string{"test3.yaml"},
90+
testutil.Run(t, "", func(t *testutil.T) {
91+
tmpDir := t.NewTempDir()
92+
tmpDir.Touch("tests/test1.yaml", "tests/test2.yaml", "test3.yaml")
93+
94+
fakeCmd := t.NewFakeCmd().
95+
WithRun("container-structure-test test -v warn --image TAG --config " + tmpDir.Path("tests/test1.yaml") + " --config " + tmpDir.Path("tests/test2.yaml")).
96+
WithRun("container-structure-test test -v warn --image TAG --config " + tmpDir.Path("test3.yaml"))
97+
t.Override(&util.DefaultExecCommand, fakeCmd)
98+
99+
runCtx := &runcontext.RunContext{
100+
WorkingDir: tmpDir.Root(),
101+
Cfg: latest.Pipeline{
102+
Test: []*latest.TestCase{
103+
{
104+
ImageName: "image",
105+
StructureTests: []string{"./tests/*"},
106+
},
107+
{},
108+
{
109+
ImageName: "image",
110+
StructureTests: []string{"test3.yaml"},
111+
},
113112
},
114113
},
115-
},
116-
}
114+
}
117115

118-
err := NewTester(runCtx).Test(context.Background(), ioutil.Discard, []build.Artifact{{
119-
ImageName: "image",
120-
Tag: "TAG",
121-
}})
116+
err := NewTester(runCtx).Test(context.Background(), ioutil.Discard, []build.Artifact{{
117+
ImageName: "image",
118+
Tag: "TAG",
119+
}})
122120

123-
testutil.CheckError(t, false, err)
121+
t.CheckError(false, err)
122+
})
124123
}
125124

126125
func TestTestFailure(t *testing.T) {
127-
tmpDir, cleanup := testutil.NewTempDir(t)
128-
defer cleanup()
129-
130-
tmpDir.Touch("test.yaml")
131-
132-
defer func(c util.Command) { util.DefaultExecCommand = c }(util.DefaultExecCommand)
133-
util.DefaultExecCommand = testutil.
134-
NewFakeCmd(t).
135-
WithRunErr("container-structure-test test -v warn --image broken-image --config "+tmpDir.Path("test.yaml"), errors.New("FAIL"))
136-
137-
runCtx := &runcontext.RunContext{
138-
WorkingDir: tmpDir.Root(),
139-
Cfg: latest.Pipeline{
140-
Test: []*latest.TestCase{
141-
{
142-
ImageName: "broken-image",
143-
StructureTests: []string{"test.yaml"},
126+
testutil.Run(t, "", func(t *testutil.T) {
127+
tmpDir := t.NewTempDir()
128+
tmpDir.Touch("test.yaml")
129+
130+
fakeCmd := t.NewFakeCmd().
131+
WithRunErr("container-structure-test test -v warn --image broken-image --config "+tmpDir.Path("test.yaml"), errors.New("FAIL"))
132+
t.Override(&util.DefaultExecCommand, fakeCmd)
133+
134+
runCtx := &runcontext.RunContext{
135+
WorkingDir: tmpDir.Root(),
136+
Cfg: latest.Pipeline{
137+
Test: []*latest.TestCase{
138+
{
139+
ImageName: "broken-image",
140+
StructureTests: []string{"test.yaml"},
141+
},
144142
},
145143
},
146-
},
147-
}
148-
149-
err := NewTester(runCtx).Test(context.Background(), ioutil.Discard, []build.Artifact{{}})
144+
}
150145

151-
testutil.CheckError(t, true, err)
146+
err := NewTester(runCtx).Test(context.Background(), ioutil.Discard, []build.Artifact{{}})
147+
t.CheckError(true, err)
148+
})
152149
}

‎pkg/skaffold/test/types.go

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ type Tester interface {
4444
type FullTester struct {
4545
testCases []*latest.TestCase
4646
workingDir string
47+
extraEnv []string
4748
}
4849

4950
// Runner is the lowest-level test executor in Skaffold, responsible for

‎testutil/cmd_helper.go

+32
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type run struct {
3434
command string
3535
input []byte
3636
output []byte
37+
env []string
3738
err error
3839
}
3940

@@ -117,6 +118,14 @@ func (c *FakeCmd) WithRunOutErr(command string, output string, err error) *FakeC
117118
})
118119
}
119120

121+
// WithRunEnv registers a command that requires the given env variables to be set.
122+
func (c *FakeCmd) WithRunEnv(command string, env []string) *FakeCmd {
123+
return c.addRun(run{
124+
command: command,
125+
env: env,
126+
})
127+
}
128+
120129
func (c *FakeCmd) RunCmdOut(cmd *exec.Cmd) ([]byte, error) {
121130
command := strings.Join(cmd.Args, " ")
122131

@@ -129,6 +138,8 @@ func (c *FakeCmd) RunCmdOut(cmd *exec.Cmd) ([]byte, error) {
129138
c.t.Errorf("expected: %s. Got: %s", r.command, command)
130139
}
131140

141+
c.assertCmdEnv(r.env, cmd.Env)
142+
132143
if r.output == nil {
133144
c.t.Errorf("expected RunCmd(%s) to be called. Got RunCmdOut(%s)", r.command, command)
134145
}
@@ -152,6 +163,8 @@ func (c *FakeCmd) RunCmd(cmd *exec.Cmd) error {
152163
c.t.Errorf("expected RunCmdOut(%s) to be called. Got RunCmd(%s)", r.command, command)
153164
}
154165

166+
c.assertCmdEnv(r.env, cmd.Env)
167+
155168
if r.input != nil {
156169
if cmd.Stdin == nil {
157170
c.t.Error("expected to run the command with a custom stdin", command)
@@ -171,3 +184,22 @@ func (c *FakeCmd) RunCmd(cmd *exec.Cmd) error {
171184

172185
return r.err
173186
}
187+
188+
// assertCmdEnv ensures that actualEnv contains all values from requiredEnv
189+
func (c *FakeCmd) assertCmdEnv(requiredEnv, actualEnv []string) {
190+
if requiredEnv == nil {
191+
return
192+
}
193+
c.t.Helper()
194+
195+
envs := make(map[string]struct{}, len(actualEnv))
196+
for _, e := range actualEnv {
197+
envs[e] = struct{}{}
198+
}
199+
200+
for _, e := range requiredEnv {
201+
if _, ok := envs[e]; !ok {
202+
c.t.Errorf("expected env variable with value %q", e)
203+
}
204+
}
205+
}

‎testutil/util.go

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ type T struct {
3535
teardownActions []func()
3636
}
3737

38+
func (t *T) NewFakeCmd() *FakeCmd {
39+
return NewFakeCmd(t.T)
40+
}
41+
3842
func (t *T) FakeRun(command string) *FakeCmd {
3943
return FakeRun(t.T, command)
4044
}

0 commit comments

Comments
 (0)
Please sign in to comment.