Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add custom parameters to structured tests #6055

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/content/en/docs/pipeline-stages/testers/structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,8 @@ In order to restrict the executed structure tests, a `profile` section can overr

{{% readfile file="samples/testers/structure/testProfile.yaml" %}}

User can customize `container-structure-test` behavior by passing a list of configuration flags as a value of `structureTestsArgs` yaml property in `skaffold.yaml`, e.g.:

{{% readfile file="samples/testers/structure/structureTestArgs.yaml" %}}

To execute the tests once, run `skaffold test --profile quickcheck`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
test:
- image: gcr.io/k8s-skaffold/skaffold-example
structureTests:
- './structure-test/*'
structureTestsArgs:
- --driver tar
- -q
- --no-color
- --test-report TEST_REPORT_NAME
15 changes: 14 additions & 1 deletion docs/content/en/schemas/v2beta18.json
Original file line number Diff line number Diff line change
Expand Up @@ -3146,13 +3146,26 @@
"examples": [
"[\"./test/*\"]"
]
},
"structureTestsArgs": {
"items": {
"type": "string"
},
"type": "array",
"description": "additional configuration arguments passed to `container-structure-test` binary.",
"x-intellij-html-description": "additional configuration arguments passed to <code>container-structure-test</code> binary.",
"default": "[]",
"examples": [
"[\"--driver tar\", \"--no-color\", \"-q\"]"
]
}
},
"preferredOrder": [
"image",
"context",
"custom",
"structureTests"
"structureTests",
"structureTestsArgs"
],
"additionalProperties": false,
"type": "object",
Expand Down
4 changes: 4 additions & 0 deletions pkg/skaffold/schema/latest/v1/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,10 @@ type TestCase struct {
// to run on that artifact.
// For example: `["./test/*"]`.
StructureTests []string `yaml:"structureTests,omitempty" skaffold:"filepath"`

// StructureTestArgs lists additional configuration arguments passed to `container-structure-test` binary.
// For example: `["--driver tar", "--no-color", "-q"]`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I mention elsewhere in this review, we don't want to do arg parsing. But most long-form arguments support using an = so we should be able to use:

Suggested change
// For example: `["--driver tar", "--no-color", "-q"]`.
// For example: `["--driver=tar", "--no-color", "-q"]`.

StructureTestArgs []string `yaml:"structureTestsArgs,omitempty"`
}

// DeployConfig contains all the configuration needed by the deploy steps.
Expand Down
28 changes: 17 additions & 11 deletions pkg/skaffold/test/structure/structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"io"
"os"
"os/exec"
"strings"

"github.com/sirupsen/logrus"

Expand All @@ -32,11 +33,12 @@ import (
)

type Runner struct {
structureTests []string
imageName string
imageIsLocal bool
workspace string
localDaemon docker.LocalDaemon
structureTests []string
imageName string
imageIsLocal bool
workspace string
localDaemon docker.LocalDaemon
structureTestArgs []string
}

// New creates a new structure.Runner.
Expand All @@ -46,11 +48,12 @@ func New(cfg docker.Config, tc *latestV1.TestCase, imageIsLocal bool) (*Runner,
return nil, err
}
return &Runner{
structureTests: tc.StructureTests,
imageName: tc.ImageName,
workspace: tc.Workspace,
localDaemon: localDaemon,
imageIsLocal: imageIsLocal,
structureTests: tc.StructureTests,
imageName: tc.ImageName,
workspace: tc.Workspace,
localDaemon: localDaemon,
imageIsLocal: imageIsLocal,
structureTestArgs: tc.StructureTestArgs,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be better to move this up below line 51 with the structureTests to keep the parameters together. localDaemon and imageIsLocal are internal matters.

}, nil
}

Expand Down Expand Up @@ -86,7 +89,10 @@ func (cst *Runner) runStructureTests(ctx context.Context, out io.Writer, imageTa
for _, f := range files {
args = append(args, "--config", f)
}

for _, customArg := range cst.structureTestArgs {
splittedCustomArg := strings.Fields(customArg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We require the user to be responsible for splitting arguments properly. Otherwise we need to deal with quoting issues, and YAML already makes that hard enough. Docker uses this approach too.

args = append(args, splittedCustomArg...)
}
cmd := exec.CommandContext(ctx, "container-structure-test", args...)
cmd.Stdout = out
cmd.Stderr = out
Expand Down
38 changes: 38 additions & 0 deletions pkg/skaffold/test/structure/structure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,44 @@ func TestIgnoreDockerNotFound(t *testing.T) {
})
}

func TestCustomParams(t *testing.T) {
const (
imageName = "image:tag"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just inline this: you're using the string inline anyways further below.

)

testutil.Run(t, "", func(t *testutil.T) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be useful to have tests here for: nil and an empty array too.

tmpDir := t.NewTempDir().Touch("test.yaml")
t.Override(&cluster.FindMinikubeBinary, func() (string, semver.Version, error) { return "", semver.Version{}, errors.New("not found") })

expectedBaseCmd := "container-structure-test test -v warn --image " + imageName + " --config " + tmpDir.Path("test.yaml")
t.Override(&util.DefaultExecCommand, testutil.CmdRun(expectedBaseCmd+" --driver tar --force --no-color -q --save"))

structureTestArgs := []string{"--driver tar", "--force", "--no-color", "-q", "--save"}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
expectedBaseCmd := "container-structure-test test -v warn --image " + imageName + " --config " + tmpDir.Path("test.yaml")
t.Override(&util.DefaultExecCommand, testutil.CmdRun(expectedBaseCmd+" --driver tar --force --no-color -q --save"))
structureTestArgs := []string{"--driver tar", "--force", "--no-color", "-q", "--save"}
expectedBaseCmd := "container-structure-test test -v warn --image image:tag --config " + tmpDir.Path("test.yaml")
t.Override(&util.DefaultExecCommand, testutil.CmdRun(expectedBaseCmd+" --driver=tar --force --no-color -q --save"))
structureTestArgs := []string{"--driver=tar", "--force", "--no-color", "-q", "--save"}


cfg := &mockConfig{
tests: []*latestV1.TestCase{{
ImageName: "image",
Workspace: tmpDir.Root(),
StructureTests: []string{"test.yaml"},
StructureTestArgs: structureTestArgs,
}},
}

testCase := &latestV1.TestCase{
ImageName: "image",
Workspace: tmpDir.Root(),
StructureTests: []string{"test.yaml"},
StructureTestArgs: structureTestArgs,
}
testEvent.InitializeState([]latestV1.Pipeline{{}})

testRunner, err := New(cfg, testCase, true)
t.CheckNoError(err)
err = testRunner.Test(context.Background(), ioutil.Discard, "image:tag")
t.CheckNoError(err)
})
}

type mockConfig struct {
runcontext.RunContext // Embedded to provide the default values.
tests []*latestV1.TestCase
Expand Down