From 127c5d8aab788b020a4722b20b6a13682db690c7 Mon Sep 17 00:00:00 2001 From: gsquared94 Date: Wed, 14 Apr 2021 21:12:22 -0700 Subject: [PATCH] add `context` field to `test` --- docs/content/en/schemas/v2beta14.json | 11 +++++-- pkg/skaffold/schema/defaults/defaults.go | 10 ++++++ pkg/skaffold/schema/latest/config.go | 9 ++++-- pkg/skaffold/test/custom/custom.go | 20 ++++++------ pkg/skaffold/test/custom/custom_test.go | 31 +++++++++---------- pkg/skaffold/test/structure/structure.go | 8 ++--- pkg/skaffold/test/structure/structure_test.go | 15 ++++----- pkg/skaffold/test/test_factory.go | 7 ++--- pkg/skaffold/test/test_factory_test.go | 15 +++++---- 9 files changed, 73 insertions(+), 53 deletions(-) diff --git a/docs/content/en/schemas/v2beta14.json b/docs/content/en/schemas/v2beta14.json index c72b83829eb..b3e1716137d 100755 --- a/docs/content/en/schemas/v2beta14.json +++ b/docs/content/en/schemas/v2beta14.json @@ -973,8 +973,8 @@ "type": "string" }, "type": "array", - "description": "should be set to the file dependencies for this command, so that the skaffold file watcher knows when to retest and perform file synchronization.", - "x-intellij-html-description": "should be set to the file dependencies for this command, so that the skaffold file watcher knows when to retest and perform file synchronization.", + "description": "locates the file dependencies for the command relative to workspace. Paths should be set to the file dependencies for this command, so that the skaffold file watcher knows when to retest and perform file synchronization.", + "x-intellij-html-description": "locates the file dependencies for the command relative to workspace. Paths should be set to the file dependencies for this command, so that the skaffold file watcher knows when to retest and perform file synchronization.", "default": "[]", "examples": [ "[\"src/test/**\"]" @@ -3005,6 +3005,12 @@ "image" ], "properties": { + "context": { + "type": "string", + "description": "directory containing the test sources.", + "x-intellij-html-description": "directory containing the test sources.", + "default": "." + }, "custom": { "items": { "$ref": "#/definitions/CustomTest" @@ -3036,6 +3042,7 @@ }, "preferredOrder": [ "image", + "context", "custom", "structureTests" ], diff --git a/pkg/skaffold/schema/defaults/defaults.go b/pkg/skaffold/schema/defaults/defaults.go index ca742f9c3e2..77f78c1ac94 100644 --- a/pkg/skaffold/schema/defaults/defaults.go +++ b/pkg/skaffold/schema/defaults/defaults.go @@ -107,6 +107,7 @@ func Set(c *latest.SkaffoldConfig) error { setDefaultAddress(pf) } + setDefaultTestWorkspace(c) return nil } @@ -384,3 +385,12 @@ func setDefaultArtifactDependencyAlias(d *latest.ArtifactDependency) { d.Alias = d.ImageName } } + +func setDefaultTestWorkspace(c *latest.SkaffoldConfig) { + for _, tc := range c.Test { + if tc == nil { + continue + } + tc.Workspace = valueOrDefault(tc.Workspace, ".") + } +} diff --git a/pkg/skaffold/schema/latest/config.go b/pkg/skaffold/schema/latest/config.go index 558b87a9f27..49bd5fef803 100644 --- a/pkg/skaffold/schema/latest/config.go +++ b/pkg/skaffold/schema/latest/config.go @@ -480,6 +480,10 @@ type TestCase struct { // For example: `gcr.io/k8s-skaffold/example`. ImageName string `yaml:"image" yamltags:"required"` + // Workspace is the directory containing the test sources. + // Defaults to `.`. + Workspace string `yaml:"context,omitempty" skaffold:"filepath"` + // CustomTests lists the set of custom tests to run after an artifact is built. CustomTests []CustomTest `yaml:"custom,omitempty"` @@ -1046,13 +1050,14 @@ type CustomTestDependencies struct { // Command represents a command that skaffold executes to obtain dependencies. The output of this command *must* be a valid JSON array. Command string `yaml:"command,omitempty" yamltags:"oneOf=dependency"` + // Paths locates the file dependencies for the command relative to workspace. // Paths should be set to the file dependencies for this command, so that the skaffold file watcher knows when to retest and perform file synchronization. // For example: `["src/test/**"]` - Paths []string `yaml:"paths,omitempty" yamltags:"oneOf=dependency" skaffold:"filepath"` + Paths []string `yaml:"paths,omitempty" yamltags:"oneOf=dependency"` // Ignore specifies the paths that should be ignored by skaffold's file watcher. If a file exists in both `paths` and in `ignore`, it will be ignored, and will be excluded from both retest and file synchronization. // Will only work in conjunction with `paths`. - Ignore []string `yaml:"ignore,omitempty" skaffold:"filepath"` + Ignore []string `yaml:"ignore,omitempty"` } // DockerfileDependency *beta* is used to specify a custom build artifact that is built from a Dockerfile. This allows skaffold to determine dependencies from the Dockerfile. diff --git a/pkg/skaffold/test/custom/custom.go b/pkg/skaffold/test/custom/custom.go index 410c778b459..dfb594b3669 100644 --- a/pkg/skaffold/test/custom/custom.go +++ b/pkg/skaffold/test/custom/custom.go @@ -42,17 +42,17 @@ var ( const Windows string = "windows" type Runner struct { - customTest latest.CustomTest - imageName string - testWorkingDir string + customTest latest.CustomTest + imageName string + workspace string } // New creates a new custom.Runner. -func New(cfg docker.Config, imageName string, wd string, ct latest.CustomTest) (*Runner, error) { +func New(cfg docker.Config, imageName string, ws string, ct latest.CustomTest) (*Runner, error) { return &Runner{ - imageName: imageName, - customTest: ct, - testWorkingDir: wd, + imageName: imageName, + customTest: ct, + workspace: ws, }, nil } @@ -146,7 +146,7 @@ func (ct *Runner) TestDependencies() ([]string, error) { return deps, nil case test.Dependencies.Paths != nil: - return list.Files(ct.testWorkingDir, test.Dependencies.Paths, test.Dependencies.Ignore) + return list.Files(ct.workspace, test.Dependencies.Paths, test.Dependencies.Ignore) } } return nil, nil @@ -169,7 +169,7 @@ func (ct *Runner) retrieveCmd(ctx context.Context, out io.Writer, command string } cmd.Env = env - dir, err := testContext(ct.testWorkingDir) + dir, err := testContext(ct.workspace) if err != nil { return nil, fmt.Errorf("getting context for test: %w", err) } @@ -179,7 +179,7 @@ func (ct *Runner) retrieveCmd(ctx context.Context, out io.Writer, command string } func (ct *Runner) getEnv(imageTag string) ([]string, error) { - testContext, err := testContext(ct.testWorkingDir) + testContext, err := testContext(ct.workspace) if err != nil { return nil, fmt.Errorf("getting absolute path for test context: %w", err) } diff --git a/pkg/skaffold/test/custom/custom_test.go b/pkg/skaffold/test/custom/custom_test.go index 5577522aeb7..325e908064d 100644 --- a/pkg/skaffold/test/custom/custom_test.go +++ b/pkg/skaffold/test/custom/custom_test.go @@ -51,16 +51,16 @@ func TestNewCustomTestRunner(t *testing.T) { testCase := &latest.TestCase{ ImageName: "image", + Workspace: tmpDir.Root(), CustomTests: []latest.CustomTest{custom}, } cfg := &mockConfig{ - workingDir: tmpDir.Root(), - tests: []*latest.TestCase{testCase}, + tests: []*latest.TestCase{testCase}, } testEvent.InitializeState([]latest.Pipeline{{}}) - testRunner, err := New(cfg, testCase.ImageName, cfg.workingDir, custom) + testRunner, err := New(cfg, testCase.ImageName, testCase.Workspace, custom) t.CheckNoError(err) err = testRunner.Test(context.Background(), ioutil.Discard, "image:tag") @@ -110,16 +110,16 @@ func TestCustomCommandError(t *testing.T) { testCase := &latest.TestCase{ ImageName: "image", + Workspace: tmpDir.Root(), CustomTests: []latest.CustomTest{test.custom}, } cfg := &mockConfig{ - workingDir: tmpDir.Root(), - tests: []*latest.TestCase{testCase}, + tests: []*latest.TestCase{testCase}, } testEvent.InitializeState([]latest.Pipeline{{}}) - testRunner, err := New(cfg, testCase.ImageName, cfg.workingDir, test.custom) + testRunner, err := New(cfg, testCase.ImageName, testCase.Workspace, test.custom) t.CheckNoError(err) err = testRunner.Test(context.Background(), ioutil.Discard, "image:tag") @@ -145,12 +145,12 @@ func TestTestDependenciesCommand(t *testing.T) { testCase := &latest.TestCase{ ImageName: "image", + Workspace: tmpDir.Root(), CustomTests: []latest.CustomTest{custom}, } cfg := &mockConfig{ - workingDir: tmpDir.Root(), - tests: []*latest.TestCase{testCase}, + tests: []*latest.TestCase{testCase}, } testEvent.InitializeState([]latest.Pipeline{{}}) @@ -167,7 +167,7 @@ func TestTestDependenciesCommand(t *testing.T) { } expected := []string{"file1", "file2", "file3"} - testRunner, err := New(cfg, testCase.ImageName, cfg.workingDir, custom) + testRunner, err := New(cfg, testCase.ImageName, testCase.Workspace, custom) t.CheckNoError(err) deps, err := testRunner.TestDependencies() @@ -229,16 +229,16 @@ func TestTestDependenciesPaths(t *testing.T) { testCase := &latest.TestCase{ ImageName: "image", + Workspace: tmpDir.Root(), CustomTests: []latest.CustomTest{custom}, } cfg := &mockConfig{ - workingDir: tmpDir.Root(), - tests: []*latest.TestCase{testCase}, + tests: []*latest.TestCase{testCase}, } testEvent.InitializeState([]latest.Pipeline{{}}) - testRunner, err := New(cfg, testCase.ImageName, cfg.workingDir, custom) + testRunner, err := New(cfg, testCase.ImageName, testCase.Workspace, custom) t.CheckNoError(err) deps, err := testRunner.TestDependencies() @@ -282,16 +282,16 @@ func TestGetEnv(t *testing.T) { testCase := &latest.TestCase{ ImageName: "image", + Workspace: tmpDir.Root(), CustomTests: []latest.CustomTest{custom}, } cfg := &mockConfig{ - workingDir: tmpDir.Root(), - tests: []*latest.TestCase{testCase}, + tests: []*latest.TestCase{testCase}, } testEvent.InitializeState([]latest.Pipeline{{}}) - testRunner, err := New(cfg, testCase.ImageName, cfg.workingDir, custom) + testRunner, err := New(cfg, testCase.ImageName, testCase.Workspace, custom) t.CheckNoError(err) actual, err := testRunner.getEnv(test.tag) @@ -303,6 +303,5 @@ func TestGetEnv(t *testing.T) { type mockConfig struct { runcontext.RunContext // Embedded to provide the default values. - workingDir string tests []*latest.TestCase } diff --git a/pkg/skaffold/test/structure/structure.go b/pkg/skaffold/test/structure/structure.go index 5162f0d8669..5037d5f3272 100644 --- a/pkg/skaffold/test/structure/structure.go +++ b/pkg/skaffold/test/structure/structure.go @@ -35,12 +35,12 @@ type Runner struct { structureTests []string imageName string imageIsLocal bool - testWorkingDir string + workspace string localDaemon docker.LocalDaemon } // New creates a new structure.Runner. -func New(cfg docker.Config, wd string, tc *latest.TestCase, imageIsLocal bool) (*Runner, error) { +func New(cfg docker.Config, tc *latest.TestCase, imageIsLocal bool) (*Runner, error) { localDaemon, err := docker.NewAPIClient(cfg) if err != nil { return nil, err @@ -48,7 +48,7 @@ func New(cfg docker.Config, wd string, tc *latest.TestCase, imageIsLocal bool) ( return &Runner{ structureTests: tc.StructureTests, imageName: tc.ImageName, - testWorkingDir: wd, + workspace: tc.Workspace, localDaemon: localDaemon, imageIsLocal: imageIsLocal, }, nil @@ -101,7 +101,7 @@ func (cst *Runner) runStructureTests(ctx context.Context, out io.Writer, imageTa // TestDependencies returns dependencies listed for the structure tests func (cst *Runner) TestDependencies() ([]string, error) { - files, err := util.ExpandPathsGlob(cst.testWorkingDir, cst.structureTests) + files, err := util.ExpandPathsGlob(cst.workspace, cst.structureTests) if err != nil { return nil, expandingFilePathsErr(err) } diff --git a/pkg/skaffold/test/structure/structure_test.go b/pkg/skaffold/test/structure/structure_test.go index 91c00ff0cde..bbca87a3f24 100644 --- a/pkg/skaffold/test/structure/structure_test.go +++ b/pkg/skaffold/test/structure/structure_test.go @@ -46,20 +46,21 @@ func TestNewRunner(t *testing.T) { t.Override(&util.DefaultExecCommand, testutil.CmdRun("container-structure-test test -v warn --image "+imageName+" --config "+tmpDir.Path("test.yaml"))) cfg := &mockConfig{ - workingDir: tmpDir.Root(), tests: []*latest.TestCase{{ ImageName: "image", + Workspace: tmpDir.Root(), StructureTests: []string{"test.yaml"}, }}, } testCase := &latest.TestCase{ ImageName: "image", + Workspace: tmpDir.Root(), StructureTests: []string{"test.yaml"}, } testEvent.InitializeState([]latest.Pipeline{{}}) - testRunner, err := New(cfg, cfg.workingDir, testCase, true) + testRunner, err := New(cfg, testCase, true) t.CheckNoError(err) err = testRunner.Test(context.Background(), ioutil.Discard, "image:tag") t.CheckNoError(err) @@ -74,19 +75,20 @@ func TestIgnoreDockerNotFound(t *testing.T) { }) cfg := &mockConfig{ - workingDir: tmpDir.Root(), tests: []*latest.TestCase{{ ImageName: "image", + Workspace: tmpDir.Root(), StructureTests: []string{"test.yaml"}, }}, } testCase := &latest.TestCase{ ImageName: "image", + Workspace: tmpDir.Root(), StructureTests: []string{"test.yaml"}, } - testRunner, err := New(cfg, cfg.workingDir, testCase, true) + testRunner, err := New(cfg, testCase, true) t.CheckError(true, err) t.CheckNil(testRunner) }) @@ -94,11 +96,10 @@ func TestIgnoreDockerNotFound(t *testing.T) { type mockConfig struct { runcontext.RunContext // Embedded to provide the default values. - workingDir string tests []*latest.TestCase muted config.Muted } -func (c *mockConfig) Muted() config.Muted { return c.muted } -func (c *mockConfig) GetWorkingDir() string { return c.workingDir } +func (c *mockConfig) Muted() config.Muted { return c.muted } + func (c *mockConfig) TestCases() []*latest.TestCase { return c.tests } diff --git a/pkg/skaffold/test/test_factory.go b/pkg/skaffold/test/test_factory.go index b9d120ef2f5..46db0d6868a 100644 --- a/pkg/skaffold/test/test_factory.go +++ b/pkg/skaffold/test/test_factory.go @@ -36,7 +36,6 @@ type Config interface { docker.Config TestCases() []*latest.TestCase - GetWorkingDir() string Muted() config.Muted } @@ -114,7 +113,7 @@ func (t FullTester) runTests(ctx context.Context, out io.Writer, bRes []graph.Ar return nil } -func getImageTesters(cfg Config, imagesAreLocal func(imageName string) (bool, error), tcs []*latest.TestCase) (ImageTesters, error) { +func getImageTesters(cfg docker.Config, imagesAreLocal func(imageName string) (bool, error), tcs []*latest.TestCase) (ImageTesters, error) { runners := make(map[string][]ImageTester) for _, tc := range tcs { isLocal, err := imagesAreLocal(tc.ImageName) @@ -123,7 +122,7 @@ func getImageTesters(cfg Config, imagesAreLocal func(imageName string) (bool, er } if len(tc.StructureTests) != 0 { - structureRunner, err := structure.New(cfg, cfg.GetWorkingDir(), tc, isLocal) + structureRunner, err := structure.New(cfg, tc, isLocal) if err != nil { return nil, err } @@ -131,7 +130,7 @@ func getImageTesters(cfg Config, imagesAreLocal func(imageName string) (bool, er } for _, customTest := range tc.CustomTests { - customRunner, err := custom.New(cfg, tc.ImageName, cfg.GetWorkingDir(), customTest) + customRunner, err := custom.New(cfg, tc.ImageName, tc.Workspace, customTest) if err != nil { return nil, err } diff --git a/pkg/skaffold/test/test_factory_test.go b/pkg/skaffold/test/test_factory_test.go index 7a6a5107736..1efd9e0423e 100644 --- a/pkg/skaffold/test/test_factory_test.go +++ b/pkg/skaffold/test/test_factory_test.go @@ -55,11 +55,10 @@ func TestTestDependencies(t *testing.T) { tmpDir := t.NewTempDir().Touch("tests/test1.yaml", "tests/test2.yaml", "test3.yaml") cfg := &mockConfig{ - workingDir: tmpDir.Root(), tests: []*latest.TestCase{ - {StructureTests: []string{"./tests/*"}, ImageName: "foo"}, + {StructureTests: []string{"./tests/*"}, Workspace: tmpDir.Root(), ImageName: "foo"}, {}, - {StructureTests: []string{"test3.yaml"}, ImageName: "foo"}, + {StructureTests: []string{"test3.yaml"}, Workspace: tmpDir.Root(), ImageName: "foo"}, }, } @@ -119,15 +118,16 @@ func TestTestSuccess(t *testing.T) { AndRun("container-structure-test test -v warn --image image:tag --config "+tmpDir.Path("test3.yaml"))) cfg := &mockConfig{ - workingDir: tmpDir.Root(), tests: []*latest.TestCase{ { ImageName: "image", + Workspace: tmpDir.Root(), StructureTests: []string{"./tests/*"}, }, {}, { ImageName: "image", + Workspace: tmpDir.Root(), StructureTests: []string{"test3.yaml"}, }, { @@ -240,9 +240,9 @@ func TestTestMuted(t *testing.T) { t.Override(&util.DefaultExecCommand, testutil.CmdRun("container-structure-test test -v warn --image image:tag --config "+tmpDir.Path("test.yaml"))) cfg := &mockConfig{ - workingDir: tmpDir.Root(), tests: []*latest.TestCase{{ ImageName: "image", + Workspace: tmpDir.Root(), StructureTests: []string{"test.yaml"}, }}, muted: config.Muted{ @@ -270,11 +270,10 @@ func fakeLocalDaemon(api client.CommonAPIClient) docker.LocalDaemon { type mockConfig struct { runcontext.RunContext // Embedded to provide the default values. - workingDir string tests []*latest.TestCase muted config.Muted } -func (c *mockConfig) Muted() config.Muted { return c.muted } -func (c *mockConfig) GetWorkingDir() string { return c.workingDir } +func (c *mockConfig) Muted() config.Muted { return c.muted } + func (c *mockConfig) TestCases() []*latest.TestCase { return c.tests }