GithubHelp home page GithubHelp logo

googlecontainertools / container-structure-test Goto Github PK

View Code? Open in Web Editor NEW
2.2K 55.0 189.0 5.65 MB

validate the structure of your container images

License: Apache License 2.0

Makefile 1.44% Go 79.37% Shell 7.19% Dockerfile 0.40% Starlark 11.59%

container-structure-test's Introduction

Container Structure Tests

The Container Structure Tests provide a powerful framework to validate the structure of a container image. These tests can be used to check the output of commands in an image, as well as verify metadata and contents of the filesystem.

Tests can be run either through a standalone binary, or through a Docker image.

Note: container-structure-test is not an officially supported Google project, and is currently in maintainence mode. Contributions are still welcome!

Installation

OS X

Install via brew:

$ brew install container-structure-test
curl -LO https://github.com/GoogleContainerTools/container-structure-test/releases/latest/download/container-structure-test-darwin-arm64 && chmod +x container-structure-test-darwin-amd64 && sudo mv container-structure-test-darwin-amd64 /usr/local/bin/container-structure-test

Linux

curl -LO https://github.com/GoogleContainerTools/container-structure-test/releases/latest/download/container-structure-test-linux-amd64 && chmod +x container-structure-test-linux-amd64 && sudo mv container-structure-test-linux-amd64 /usr/local/bin/container-structure-test

If you want to avoid using sudo:

curl -LO https://github.com/GoogleContainerTools/container-structure-test/releases/latest/download/container-structure-test-linux-amd64 && chmod +x container-structure-test-linux-amd64 && mkdir -p $HOME/bin && export PATH=$PATH:$HOME/bin && mv container-structure-test-linux-amd64 $HOME/bin/container-structure-test

Warning

Container builds are currently not updated with new releases

Additionally, a container image for running tests through Google Cloud Builder can be found at gcr.io/gcp-runtimes/container-structure-test:latest.

Setup

To use container structure tests to validate your containers, you'll need the following:

  • The container structure test binary or docker image
  • A container image to test against
  • A test .yaml or .json file with user defined structure tests to run inside of the specified container image

Note that the test framework looks for the provided image in the local Docker daemon (if it is not provided as a tar). The --pull flag can optionally be provided to force a pull of a remote image before running the tests.

Example Run

An example run of the test framework:

container-structure-test test --image gcr.io/registry/image:latest \
--config config.yaml

Tests within this framework are specified through a YAML or JSON config file, which is provided to the test driver via a CLI flag. Multiple config files may be specified in a single test run. The config file will be loaded in by the test driver, which will execute the tests in order. Within this config file, four types of tests can be written:

  • Command Tests (testing output/error of a specific command issued)
  • File Existence Tests (making sure a file is, or isn't, present in the file system of the image)
  • File Content Tests (making sure files in the file system of the image contain, or do not contain, specific contents)
  • Metadata Test, singular (making sure certain container metadata is correct)

Command Tests

Command tests ensure that certain commands run properly in the target image. Regexes can be used to check for expected or excluded strings in both stdout and stderr. Additionally, any number of flags can be passed to the argument as normal. Each command in the setup section will run in a separate container and then commits a modified image to be the new base image for the test run.

Supported Fields:

NOTE: schemaVersion must be specified in all container-structure-test yamls. The current version is 2.0.0.

  • Name (string, required): The name of the test
  • Setup ([][]string, optional): A list of commands (each with optional flags) to run before the actual command under test.
  • Teardown ([][]string, optional): A list of commands (each with optional flags) to run after the actual command under test.
  • Command (string, required): The command to run in the test.
  • Args ([]string, optional): The arguments to pass to the command.
  • EnvVars ([]EnvVar, optional): A list of environment variables to set for the individual test. See the Environment Variables section for more info.
  • Expected Output ([]string, optional): List of regexes that should match the stdout from running the command.
  • Excluded Output ([]string, optional): List of regexes that should not match the stdout from running the command.
  • Expected Error ([]string, optional): List of regexes that should match the stderr from running the command.
  • Excluded Error ([]string, optional): List of regexes that should not match the stderr from running the command.
  • Exit Code (int, optional): Exit code that the command should exit with.

Example:

commandTests:
  - name: "gunicorn flask"
    setup: [["virtualenv", "/env"], ["pip", "install", "gunicorn", "flask"]]
    command: "which"
    args: ["gunicorn"]
    expectedOutput: ["/env/bin/gunicorn"]
  - name:  "apt-get upgrade"
    command: "apt-get"
    args: ["-qqs", "upgrade"]
    excludedOutput: [".*Inst.*Security.* | .*Security.*Inst.*"]
    excludedError: [".*Inst.*Security.* | .*Security.*Inst.*"]

Depending on your command the argument section can get quite long. Thus, you can make use of YAML's list style option for separation of arguments and the literal style option to preserve newlines like so:

commandTests:
  - name: "say hello world"
    command: "bash"
    args:
      - -c
      - |
         echo hello &&
         echo world

Image Entrypoint

To avoid unexpected behavior and output when running commands in the containers, all entrypoints are overwritten by default. If your entrypoint is necessary for the structure of your container, use the setup field to call any scripts or commands manually before running the tests.

commandTests:
  ...
  setup: [["my_image_entrypoint.sh"]]
  ...

Intermediate Artifacts

Each command test run creates either a container (with the docker driver) or tar artifact (with the tar driver). By default, these are deleted after the test run finishes, but the --save flag can optionally be passed to keep these around. This would normally be used for debugging purposes.

File Existence Tests

File existence tests check to make sure a specific file (or directory) exist within the file system of the image. No contents of the files or directories are checked. These tests can also be used to ensure a file or directory is not present in the file system.

Supported Fields:

  • Name (string, required): The name of the test
  • Path (string, required): Path to the file or directory under test
  • ShouldExist (boolean, required): Whether or not the specified file or directory should exist in the file system
  • Permissions (string, optional): The expected Unix permission string (e.g. drwxrwxrwx) of the files or directory.
  • Uid (int, optional): The expected Unix user ID of the owner of the file or directory.
  • Gid (int, optional): The expected Unix group ID of the owner of the file or directory.
  • IsExecutableBy (string, optional): Checks if file is executable by a given user. One of owner, group, other or any

Example:

fileExistenceTests:
- name: 'Root'
  path: '/'
  shouldExist: true
  permissions: '-rw-r--r--'
  uid: 1000
  gid: 1000
  isExecutableBy: 'group'

File Content Tests

File content tests open a file on the file system and check its contents. These tests assume the specified file is a file, and that it exists (if unsure about either or these criteria, see the above File Existence Tests section). Regexes can again be used to check for expected or excluded content in the specified file.

Supported Fields:

  • Name (string, required): The name of the test
  • Path (string, required): Path to the file under test
  • ExpectedContents (string[], optional): List of regexes that should match the contents of the file
  • ExcludedContents (string[], optional): List of regexes that should not match the contents of the file

Example:

fileContentTests:
- name: 'Debian Sources'
  path: '/etc/apt/sources.list'
  expectedContents: ['.*httpredir\.debian\.org.*']
  excludedContents: ['.*gce_debian_mirror.*']

Metadata Test

The Metadata test ensures the container is configured correctly. All of these checks are optional.

Supported Fields:

  • EnvVars ([]EnvVar): A list of environment variable key/value pairs that should be set in the container. isRegex (optional) interpretes the value as regex.
  • UnboundEnvVars ([]EnvVar): A list of environment variable keys that should NOT be set in the container.
  • Labels ([]Label): A list of image labels key/value pairs that should be set on the container. isRegex (optional) interpretes the value as regex.
  • Entrypoint ([]string): The entrypoint of the container.
  • Cmd ([]string): The CMD specified in the container.
  • Exposed Ports ([]string): The ports exposed in the container.
  • Unexposed Ports ([]string): The ports NOT exposed in the container.
  • Volumes ([]string): The volumes exposed in the container.
  • UnmountedVolumes ([]string): The volumes NOT exposed in the container.
  • Workdir (string): The default working directory of the container.
  • User (user): The default user of the container.

Example:

metadataTest:
  envVars:
    - key: foo
      value: baz
  labels:
    - key: 'com.example.vendor'
      value: 'ACME Incorporated'
    - key: 'build-date'
      value: '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}$'
      isRegex: true
  exposedPorts: ["8080", "2345"]
  volumes: ["/test"]
  entrypoint: []
  cmd: ["/bin/bash"]
  workdir: "/app"
  user: "luke"

License Tests

License tests check a list of copyright files and makes sure all licenses are allowed at Google. By default it will look at where Debian lists all copyright files, but can also look at an arbitrary list of files.

Supported Fields:

  • Debian (bool, required): If the image is based on Debian, check where Debian lists all licenses.
  • Files (string[], optional): A list of other files to check.

Example:

licenseTests:
- debian: true
  files: ["/foo/bar", "/baz/bat"]

Environment Variables

A list of environment variables can optionally be specified as part of the test setup. They can either be set up globally (for all test runs), or test-local as part of individual command test runs (see the Command Tests section above). Each environment variable is specified as a key-value pair. Unix-style environment variable substitution is supported.

To specify, add a section like this to your config:

globalEnvVars:
  - key: "VIRTUAL_ENV"
    value: "/env"
  - key: "PATH"
    value: "/env/bin:$PATH"

Additional Options

The following fields are used to control various options and flags that may be desirable to set for the running container used to perform a structure test against an image. This allows an image author to validate certain runtime behavior that cannot be modified in the image-under-test such as running a container with an alternative user/UID or mounting a volume.

Note that these options are currently only supported with the docker driver.

The following list of options are currently supported:

containerRunOptions:
  user: "root"                  # set the --user/-u flag
  privileged: true              # set the --privileged flag (default: false)
  allocateTty: true             # set the --tty flag (default: false)
  envFile: path/to/.env         # load environment variables from file and pass to container (equivalent to --env-file)
  envVars:                      # if not empty, read each envVar from the environment and pass to test (equivalent to --env/e)
    - SECRET_KEY_FOO
    - OTHER_SECRET_BAR
  capabilities:                 # Add list of Linux capabilities (--cap-add)
    - NET_BIND_SERVICE
  bindMounts:                   # Bind mount a volume (--volume, -v)
    - /etc/example/dir:/etc/dir

Running Tests On Google Cloud Build

This tool is released as a builder image, tagged as gcr.io/gcp-runtimes/container-structure-test, so you can specify tests in your cloudbuild.yaml:

steps:
# Build an image.
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-t', 'gcr.io/$PROJECT_ID/image', '.']
# Test the image.
- name: 'gcr.io/gcp-runtimes/container-structure-test'
  args: ['test', '--image', 'gcr.io/$PROJECT_ID/image', '--config', 'test_config.yaml']

# Push the image.
images: ['gcr.io/$PROJECT_ID/image']

Running File Tests Without Docker

Container images can be represented in multiple formats, and the Docker image is just one of them. At their core, images are just a series of layers, each of which is a tarball, and so can be interacted with without a working Docker daemon. While running command tests currently requires a functioning Docker daemon on the host machine, File Existence/Content tests do not. This can be useful when dealing with images which have been docker exported or saved in a different image format than the Docker format, or when you're simply trying to run structure tests in an environment where Docker can't be installed.

To run tests without using a Docker daemon, users can specify a different "driver" to use in the tests, with the --driver flag.

An example test run with a different driver looks like:

container-structure-test test --driver tar --image gcr.io/registry/image:latest \
--config config.yaml

The currently supported drivers in the framework are:

  • docker: the default driver. Supports all tests, and uses the Docker daemon on the host to run them. You can set the runtime to use (by example runsc to run with gVisor) using --runtime flag.
  • tar: a tar driver, which extracts an image filesystem to wherever tests are running, and runs file/metadata tests against it. Does not support command tests.

Running Structure Tests Through Bazel

Structure tests can also be run through bazel.

With Bazel 6 and bzlmod, just see https://registry.bazel.build/modules/container_structure_test. Otherwise, load the rule and its dependencies in your WORKSPACE, see bazel/test/WORKSPACE.bazel in this repo.

Load the rule definition in your BUILD file and declare a container_structure_test target, passing in your image and config file as parameters:

load("@container_structure_test//:defs.bzl", "container_structure_test")

container_structure_test(
    name = "hello_test",
    configs = ["testdata/hello.yaml"],
    image = ":hello",
)

Flags:

container-structure-test test -h

  -c, --config stringArray             test config files
      --default-image-tag string       default image tag to used when loading images to the daemon. required when --image-from-oci-layout refers to a oci layout lacking the reference annotation.
  -d, --driver string                  driver to use when running tests (default "docker")
  -f, --force                          force run of host driver (without user prompt)
  -h, --help                           help for test
  -i, --image string                   path to test image
      --image-from-oci-layout string   path to the oci layout to test against
      --metadata string                path to image metadata file
      --no-color                       no color in the output
  -o, --output string                  output format for the test report (available format: text, json, junit) (default "text")
      --platform string                Set platform if host is multi-platform capable (default "linux/amd64")
      --pull                           force a pull of the image before running tests
  -q, --quiet                          flag to suppress output
      --runtime string                 runtime to use with docker driver
      --save                           preserve created containers after test run
      --test-report string             generate test report and write it to specified file (supported format: json, junit; default: json)

See this example repo for a full working example.

Output formats

Reports are generated using one of the following output formats: text, json or junit. Formats like json and junit can also be used to write a report to a specified file using the --test-report.

Output samples

Text

====================================
====== Test file: config.yaml ======
====================================
=== RUN: File Existence Test: whoami
--- PASS
duration: 0s
=== RUN: Metadata Test
--- PASS
duration: 0s

=====================================
============== RESULTS ==============
=====================================
Passes:      2
Failures:    0
Duration:    0s
Total tests: 2

PASS

JSON

The following sample has been formatted.

{
  "Pass": 2,
  "Fail": 0,
  "Total": 2,
  "Duration": 0,
  "Results": [
    {
      "Name": "File Existence Test: whoami",
      "Pass": true,
      "Duration": 0
    },
    {
      "Name": "Metadata Test",
      "Pass": true,
      "Duration": 0
    }
  ]
}

JUnit

The following sample has been formatted.

<?xml version="1.0"?>
<testsuites failures="0" tests="2" time="0">
  <testsuite>
    <testcase name="File Existence Test: whoami" time="0"/>
    <testcase name="Metadata Test" time="0"/>
  </testsuite>
</testsuites>

container-structure-test's People

Contributors

aaron-prindle avatar abbytiz avatar alexeagle avatar androbin avatar arg2009 avatar bananaappletw avatar barthy1 avatar charlyx avatar coopernetes avatar dependabot[bot] avatar djuelg avatar dlorenc avatar ebriand avatar erain avatar eunomie avatar evesy avatar globegitter avatar loosebazooka avatar mattmoor avatar nateinaction avatar nkubala avatar olivernocon avatar olvesh avatar peter-evans avatar scele avatar sharifelgamal avatar tejal29 avatar thesayyn avatar tklauser avatar xingao267 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

container-structure-test's Issues

Error parsing YAML config

On Ubuntu 17.10 with the latest binary (22 Jan)(https://storage.googleapis.com/container-structure-test/latest/container-structure-test)

Using one of the config files in this repo (https://github.com/GoogleCloudPlatform/container-structure-test/blob/master/tests/debian_test.yaml)

The following command:
container-structure-test -test.v -image ubuntu:16.04 debian-test.yml

Returns the following error:
2018/02/22 17:48:51 Error parsing config file: Please provide valid JSON or YAML config file

File existence tests `shouldExist` defaults to False

If this field isn't specified in the config, it default to False, which is counterintuitive.

The issue here is that we can't set default values on the struct in go, but when the fields get unmarshaled into the struct go chooses False as the default. We could init the holder struct with default values first, and then unmarshal, but the problem with that is that we don't know how many defaulted structs to put in each place (e.g. if we init with two FileExistenceTest structs, and the config specifies three, the third one doesn't get the default values). We might need to override the unmarshalling method to use an explicit constructor for each struct here.

Add support for including files in test image

We might want a way to include external files into the image under test before running the test. This used to be possible with the --workspace flag which would mount the workspace as a volume in the container.

Feature Request: Support alpine 3.7

Tried to use container-structure-test in an alpine 3.7 container, got error "/bin/sh: container-structure-test: not found". (Everything works fine in Ubuntu and Redhat Linux containers).

apk add --no-cache ca-certificates
apk add --no-cache wget
wget -O container-structure-test https://storage.googleapis.com/container-structure-test/latest/container-structure-
test
chmod +x container-structure-test
container-structure-test --help
/bin/sh: container-structure-test: not found

`structure_test` rule doesn't work

First of all, nice framework for docker image testing!

I tried to use structure_test rule with bazel with my image (produced by bazel container_image rule). However, I got the following error msg:

ERROR: <my-project>/BUILD:119:1: every rule of type structure_test implicitly depends upon the target '@structure_test//structure_tests:go_default_test', but this target could not be found because of: no such package '@structure_test//structure_tests': BUILD file not found on package path

When I looked into it, in tests.bzl, the target Label("//structure_tests:go_default_test") is obviously missing.

I guess the fix would be:

  • renamed BUILD.oss to BUILD
  • have Label("//structure_tests:go_default_test") properly reference to it (maybe Label("//:go_default_test"))

Inconsistent behaviour with ENTRYPOINT

Not sure if this utility (which is excellent BTW) is capable of working with images/containers which have a defined ENTRYPOINT, or whether there's is anything additional to define if the image being used has one ?

I have an image which executes Terraform and uses an ENTRYPOINT script. I created some simple command tests for other binaries that are present within the image and they ran successfully:

    # check the terraform binary is the correct version
  - name: "terraform core"
    command: "terraform"
    args: ["-v"]
    expectedOutput: ["v0.10.8"]

    # check the rancher-cli binary is the correct version
  - name: "rancher-cli"
    command: "rancher"
    args: ["-v"]
    expectedOutput: ["v0.6.7"]

    # check the docker client is the correct version
  - name: "docker client"
    command: "docker"
    args: ["-v"]
    expectedOutput: ["17.09.1-ce"]

however, if I add something like checking that the HTTP_PROXY env var is set to what I expect

    # check the HTTP_PROXY value
  - name: "HTTP_PROXY"
    command: "echo"
    args: ["$HTTP_PROXY"]
    expectedOutput: ["http://xxx-yyy.zzz.com:80"]

That test FAILS ... it is trying to run Terraform not the test:

NOTE: I did notice the metadataTests section in the docs but I couldn't get these to run (raised a separate issue for that), so treat the above as a simple example of any command I might want to run 'echo' in this case

$ structure-test -test.v -image 300820918606.dkr.ecr.eu-west-1.amazonaws.com/digital-web-mobile/terraform-aws:0.10.8 cmd_tests.yaml
Using driver docker
=== RUN   TestAll
2018/01/21 19:47:07 Running tests for file cmd_tests.yaml
=== RUN   TestAll/Command_Test:_terraform_core
=== RUN   TestAll/Command_Test:_rancher-cli
=== RUN   TestAll/Command_Test:_docker_client
=== RUN   TestAll/Command_Test:_HTTP_PROXY
--- FAIL: TestAll (1.54s)
    --- PASS: TestAll/Command_Test:_terraform_core (0.50s)
        docker_driver.go:72: stdout: Terraform v0.10.8

                Terraform v0.10.8

    --- PASS: TestAll/Command_Test:_rancher-cli (0.37s)
        docker_driver.go:72: stdout: Terraform v0.10.8

                rancher version v0.6.7
    --- PASS: TestAll/Command_Test:_docker_client (0.38s)
        docker_driver.go:72: stdout: Terraform v0.10.8

                Docker version 17.09.1-ce, build 19e2cf6
    --- FAIL: TestAll/Command_Test:_HTTP_PROXY (0.28s)
        docker_driver.go:72: stdout: Terraform initialized in an empty directory!

                The directory has no Terraform configuration files. You may begin working
                with Terraform immediately by creating Terraform configuration files.
                $HTTP_PROXY
        utils.go:29: Expected string 'http://xxx-yyy.zzzs.com:80' not found in output!
        structure_test.go:46: Total tests run: 4
FAIL

Is it possible to run such a test when the image has an ENTRYPOINT (the tests before all worked happily enough) ?

Kind Regards

Fraser.

Support for checking image labels

Add support for adding metadata image label tests.
Enables testing of required label metadata prior to publishing containers.

Includes supporting regex expressions for label values.

Related prerequisite PR 181 in container-diff, which added Label metadata to the image config. This PR has now been merged into container-structure-test master.

Add mode to persist driver between test runs to avoid recreating filesystem

Currently, a new driver is created for each individual test as a way to run tests in isolation. This is fine for the docker driver, but for the tar driver this requires us to recreate the filesystem for every test, which can take on the order of half a second. Since the tar driver is incapable of running commands anyway, tests can't interfere with each other, so we should have a way to persist the driver between tests.

`--pull` option results in error when host:port/path/to/image:tag is used

When including the --pull option in the test command a failure is encountered if the host is running the docker registery on a different port (in this use case GitLab, which exposes the registry on port 8443 by default).

The error presented is: API error (400): {"message":"invalid tag format"}

I believe this is being caused by https://github.com/GoogleCloudPlatform/container-structure-test/blob/c6a7fafe63565669bf924e8c70b9a9dfef0130c8/cmd/test.go#L164, which is simply splitting on : and has an inherent assumption there is only one present.

ExpectedError appears to only work without brackets

- name: ensure nomad version
  command: '/usr/local/bin/nomad'
  args: ['--version']
  expectedError: 'Nomad v0.7.1+ent (83ac1d7316a79aacb09d349298e14e23a0aa9853)'

works:

--- PASS: TestAll/Command_Test:_ensure_nomad_version (0.41s)
docker_driver.go:88: stderr: Nomad v0.7.1+ent (83ac1d7316a79aacb09d349298e14e23a0aa9853)

- name: ensure nomad version
  command: '/usr/local/bin/nomad'
  args: ['--version']
  expectedError: ['Nomad v0.7.1+ent (83ac1d7316a79aacb09d349298e14e23a0aa9853)']

doesn't:

--- FAIL: TestAll/Command_Test:_ensure_nomad_version (0.38s)
docker_driver.go:88: stderr: Nomad v0.7.1+ent (83ac1d7316a79aacb09d349298e14e23a0aa9853)
utils.go:33: Expected string 'Nomad v0.7.1+ent (83ac1d7316a79aacb09d349298e14e23a0aa9853)' not found in error!

setup for commandTests appears to be broken

- name: curl localhost
  setup: [['/app-cfg/entrypoint.sh']]
  command: ['/usr/bin/curl']
  args: ['localhost']
  expectedOutput: ['.*OK.']

--- FAIL: TestAll/Command_Test:_curl_localhost (0.00s)
command.go:43: Please provide a valid entrypoint to run for test curl localhost

Also fails if setup appears as it does in the Dockerfile:
setup: [["/app-cfg/entrypoint.sh"]]

or

setup: ["/app-cfg/entrypoint.sh"]

Defer causes tar driver to eat up all disk space

Hi, I am trying to use container-structure-test to test our images.
I am running 1.1.0 binary in a custom container and using tar driver (I don't want to start containers for image under test)
When running the binary, container keeps growing in size, until one of the tests fails.
How this looks:
image A - image running the test
image B - image under test

Now, when running, container A pulls B, unpacks it, runs test 1, pulls B again, unpacks it, runs test 2, pulls B again, unpacks it, runs test 3 ...

As a result, if I e.g. want to test solr image, that is 700MB for starters, container size will be at least 700MB * number of tests.
I have quite sizable image and ~ 15 tests to run, which causes in the end the driver to run out of disk space.

I am no go expert, but I was able to track this to usage of defer, like here: https://github.com/GoogleCloudPlatform/container-structure-test/blob/e0fde8f8122656083dba6a22ac45b0da21175780/pkg/types/v2/structure.go#L96

This pattern repeats over most of the RunXXXTests both for v1 and v2 in structure.go file(s).

Also, what is the benefit of creating a new driver for each test?
Shouldn't the code be something like:

  • create driver
  • run all tests (for loop)
  • teardown / destroy driver
    ?

Output of list with empty string is the same to empty list

Entrypoint in the image is []. If I create the following metadata test:

metadataTest:
  entrypoint: [""]

it will fail with error message:

    --- FAIL: TestAll/Metadata_Test (0.00s)
        structure.go:179: Image entrypoint [] does not match expected entrypoint: []

Provide option to pull image if not present

Currently the docker driver assumes that the image to use for tests is already present, f.e. from a recent build. To support the use case of running tests on a separate machine than the one used to build the image it might make sense to provide pulling of the image if it is not present.

Feature request: Regex in file existence permissions tests/'should be executable' test

Hi,

Having come from using Serverspec/Inspec I am missing not having a test directive similar to be_executable (https://www.inspec.io/docs/reference/resources/file/).

In often cases I am not ultimately concerned about exact file permissions on certain binaries within a container, but just that they are executable by user/group/other. Due to environment differences file permissions between local dev environments & ci environments are frequently different (i.e. due to different umask settings).

In these cases I care in the tests that the files are still executable (as this permission is tracked in github), and not about rw permissions.

I think supporting wildcard matching in the permissions string (i.e. -rwx**x**x), or adding an additional field to the fileExistance struct that can be used to just check for executable bits would be beneficial.

Cheers,
Mike

Updated Release Binary

I notice that there have been recent commits to resolve issues (now closed) for over-riding entrypoint and tidying up intermediate containers. However I downloaded the release binary from the link in this repo: https://storage.googleapis.com/container-structure-test/latest/container-structure-test but it looks like this is the same binary that I had previously been using when I raised those and running it the behaviours don't seem to have changed.

Is the release binary not yet updated to include those changes ?

Thx

Fraser

tar option failing to pull image layer

I have the container-structure-test working on xubuntu 16.04 64 bit for a couple of simple file existence tests for the default docker driver but I haven't been able to get the tar driver to pull the image.
I'm getting errors like:
ERRO[0110] Failed to pull image layer: Get https://dseasb33srnrn.cloudfront.net/registry-v2/docker/registry/v2/blobs...

I've tried on different machines and different locations.
Is there a trick to getting the tar option to work?

My command line is:
sudo ./container-structure-test -test.v -driver tar -image python python_file_test.yaml

Can -pull work with non-public images?

I have an image that is not publicly accessible. I can pull it via gcloud docker -- pull blah, which is probably translated to docker login under the covers. Is there a way to make this work with the structure test -pull flag?

If so, maybe document how do that. Maybe I need to fiddle with permissions or environment variables.

If not, maybe document that, because the error message is really vague (Step #0: docker_driver.go:241: Error creating container: no such image) and doesn't log the actual image name it's trying.

Luckily, the workaround is fairly easy -- for my case, where I'm invoking from a cloudbuild.yaml, I add a cloudbuild step before the structure test step, that explicitly pulls the image and runs /bin/true in it.

Repro:

$ gcloud container builds submit --config=cloudbuild_test.yaml --substitutions=_DOCKER_NAMESPACE=gcr.io/cloud-python-runtime-qa,_TAG=2018-03-08-174800-ubuntu16 .
<snip>
Step #0: e116a9187528: Pull complete
Step #0: Digest: sha256:3e6162829f0adafeb764883a715628c91c09a5a01c5bb5a25f1662ac76bb173b
Step #0: Status: Downloaded newer image for gcr.io/gcp-runtimes/container-structure-test:v0.2.1
Step #0: Error pulling remote image gcr.io/cloud-python-runtime-qa/python:2018-03-08-174800-ubuntu16: API error (404): {"message":"pull access denied for gcr.io/cloud-python-runtime-qa/python, repository does not exist or may require 'docker login'"}

cloudbuild_test.yaml:

steps:
- name: gcr.io/gcp-runtimes/container-structure-test:v0.2.1
  args: [
   '-pull',
    '-test.v',
    '-image', 'gcr.io/cloud-python-runtime-qa/python:2018-03-08-174800-ubuntu16',
    '/workspace/tests/virtualenv/virtualenv_default.yaml',
    ]

runtime error: invalid memory address or nil pointer dereference

Hi,

I'm seeing the below using gcr.io/gcp-runtimes/container-structure-test:v0.1.3 with the docker driver:

Unable to find image 'gcr.io/gcp-runtimes/container-structure-test:v0.1.3' locally
v0.1.3: Pulling from gcp-runtimes/container-structure-test
cd2f5b7886e9: Already exists
9be56f236f9a: Pulling fs layer
9be56f236f9a: Verifying Checksum
9be56f236f9a: Download complete
9be56f236f9a: Pull complete
Digest: sha256:15ae6f3996ebc05b657a042bd5dd8f4d4d66b015effea5fd024c70b8a1f9c42a
Status: Downloaded newer image for gcr.io/gcp-runtimes/container-structure-test:v0.1.3
Using driver docker
=== RUN   TestAll
2018/02/12 15:53:06 Running tests for file tests/container_tests.yaml
=== RUN   TestAll/Command_Test:_Nginx_version_is_correct
=== RUN   TestAll/Command_Test:_Nginx_config_test_passes
=== RUN   TestAll/Command_Test:_Can_bind_to_low_ports
=== RUN   TestAll/File_Existence_Test:_Nginx_config_exists
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x30 pc=0x769b58]

goroutine 26 [running]:
testing.tRunner.func1(0xc42005d450)
	/builder/home/.cache/bazel/_bazel_root/eab0d61a99b6696edb3d2aff87b585e8/external/go1_8_3_linux_amd64/src/testing/testing.go:622 +0x29d
panic(0x7d1d60, 0xa04db0)
	/builder/home/.cache/bazel/_bazel_root/eab0d61a99b6696edb3d2aff87b585e8/external/go1_8_3_linux_amd64/src/runtime/panic.go:489 +0x2cf
github.com/GoogleCloudPlatform/container-structure-test/types/v2.(*StructureTest).RunFileExistenceTests.func1(0xc42005d450)
	types/v2/structure.go:101 +0x278
testing.tRunner(0xc42005d450, 0xc4201b9220)
	/builder/home/.cache/bazel/_bazel_root/eab0d61a99b6696edb3d2aff87b585e8/external/go1_8_3_linux_amd64/src/testing/testing.go:657 +0x96
created by testing.(*T).Run
	/builder/home/.cache/bazel/_bazel_root/eab0d61a99b6696edb3d2aff87b585e8/external/go1_8_3_linux_amd64/src/testing/testing.go:697 +0x2ca

If I remove all fileExistenceTests I do not see the error. Test yaml is below:

schemaVersion: 2.0.0

globalEnvVars:
  - key: 'UPSTREAM'
    value: '127.0.0.1:8080'

fileExistenceTests:
- name: 'Nginx config exists'
  path: '/etc/nginx/nginx.conf'
  shouldExist: true
  permissions: '-rw-r--r--'
- name: 'Proxy config exists'
  path: '/etc/nginx/conf.d/proxy.conf'
  shouldExist: true
  permissions: '-rw-r--r--'
- name: 'Certs directory exists'
  path: '/etc/nginx/certs'
  shouldExist: true
  permissions: 'drwxr-xr-x'
- name: 'Pid directory exists'
  path: '/var/run/nginx'
  shouldExist: true
  permissions: 'drwxr-xr-x'
- name: 'Setup script exists'
  path: '/usr/local/bin/setup.sh'
  shouldExist: true
  permissions: '-rwxr-xr-x'
- name: 'Start script exists'
  path: '/usr/local/bin/start.sh'
  shouldExist: true
  permissions: '-rwxr-xr-x'

commandTests:
- name: 'Nginx version is correct'
  command: 'nginx'
  args: ['-v']
  expectedError: ['1.13.7']
- name: 'Nginx config test passes'
  command: 'nginx'
  setup: [['/usr/local/bin/setup.sh']]
  args: ['-t', '-c', '/etc/nginx/nginx.conf']
  exitCode: '0'
- name: 'Can bind to low ports'
  command: 'getcap'
  args: ['/usr/sbin/nginx']
  expectedOutput: ['cap_net_bind_service\+ep']

fileContentTests:
- name: 'Correct directives in nginx.conf'
  path: '/etc/nginx/nginx.conf'
  expectedContents: [
    'user nginx;',
    'pid /var/run/nginx/nginx.pid',
    'include /etc/nginx/conf.d/\*.conf'
  ]
- name: 'Correct redirects & proxying'
  path: '/etc/nginx/conf.d/proxy.conf'
  expectedContents: [
    'listen 443 ssl',
    'return  301 https://\$host\$request_uri',
    'proxy_pass          http://\$UPSTREAM'
  ]

metadataTest:
  exposedPorts: ['80', '443']
  cmd: ['/usr/local/bin/start.sh']

Any help is appreciated

Cheers,
Mike

405 error when pulling image

When trying to pull the image listed in the README:

$ docker pull gcr.io/gcp-runtimes/container-structure-test
Using default tag: latest
Pulling repository gcr.io/gcp-runtimes/container-structure-test
Error: Status 405 trying to pull repository gcp-runtimes/container-structure-test: "v1 Registry API is disabled. If you are not explicitly using the v1 Registry API, it is possible your v2 image could not be found. Verify that your image is available, or retry with `dockerd --disable-legacy-registry`. See https://cloud.google.com/container-registry/docs/support/deprecation-notices"

Docker image `v0.2.0` is broken

What is broken

docker run -i --rm gcr.io/gcp-runtimes/container-structure-test:v0.2.0 --help
/go_default_test: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory

Probably wrong base image...I am bit confused by your bazel machinery.

What I expect

Same thing as for v0.1.3

docker run -i --rm gcr.io/gcp-runtimes/container-structure-test:v0.1.3 --help                                                                                                      2s 
Usage of /go_default_test:
  -driver string
        driver to use when running tests (default "docker")
  -image string
        path to test image
  -pull
        force a pull of the image before running tests
  -save
        preserve created containers after test run
  -test.bench regexp
        run only benchmarks matching regexp
  -test.benchmem
        print memory allocations for benchmarks
  -test.benchtime d
        run each benchmark for duration d (default 1s)
...

Passing arguments to the docker run command

When we're using the docker driver, is there anyway to currently pass arguments to the docker run command? for example if i have a container that needs extra capabilites, or you want to add a volume mount to test a command with some custom config?

Add useful `version` and `help` commands

We should have useful output for container-structure-test --help that gives the user small examples of the different flags the tool accepts, as well as a way to quickly figure out which binary version is being run.

Run locally via Docker?

I'm trying to set this up via Docker in our CI (Buildkite) and it's not working.

I'm following the documentation and the error I'm getting is that my config file is not found.
I've tried mounting my local directory at /workspace and /workspace/structure_test to no avail.

I've tried with the released versions v1.0.0, v0.3.0 and v0.2.1.

Using this config file.

docker run --rm -i gcr.io/gcp-runtimes/container-structure-test:v0.3.0 -test.v -image ubuntu:16.04 debian-test.yaml

Using driver docker
=== RUN   TestAll
2018/03/21 15:44:52 Error parsing config file: open debian-test.yaml: no such file or directory
docker run --rm -i gcr.io/gcp-runtimes/container-structure-test:v1.0.0 test -v --image=ubuntu:16.04 --config debian-test.yaml

time="2018-03-21T15:50:40Z" level=fatal msg="Error parsing config file: open debian-test.yaml: no such file or directory"

Feature request: support copyfile from local to container

When testing some image, we need copy some local file to the image and verify whether it work well or not.

The "Setup" field was a set of command running in the container before we testing the image, it will better if we support "COPY" direc in the "Setup" field.

Remove temporary containers

Is it possible to configure the removal of the containers used to run each test ?

I realise that if I wrapped my tests in a script or was running as part of a CI piepline I could do that myself, but I was wondering whether it was possible as part of the test definition itself.

I tried this (as the final test) in a container that includes the docker client binary (other docker commands work fine as tests) a but it didn't work:

    # prune all containers used for tests
  - name: "prune"
    command: "docker"
    args: ["container","prune","-f"]

I also tried using a teardown in the final test. The test ran successfully but the docker prune did not do anything:

    # check the docker client is the correct version
  - name: "docker client"
    teardown: [["docker container prune -f"]]
    command: "docker"
    args: ["-v"]
    expectedOutput: ["17.09.1-ce"]

Any suggestions

Kind Regards

Fraser

Tar driver panics when unable to find provided tar file

Example with debian tests running through bazel (note the relative path of the tar file provided):

➜  container-structure-test git:(master) ./out/structure-test -test.v -driver tar -image reproducible/intermediate_bundle_debian9_structure_test.tar /usr/local/google/home/nkubala/Development/debian-docker/bazel-out/local-fastbuild/bin/reproducible/debian9_structure_test.runfiles/debian_docker/tests/debian_9_test.yaml 
Using driver tar
=== RUN   TestAll
2017/11/08 14:49:43 Running tests for file /usr/local/google/home/nkubala/Development/debian-docker/bazel-out/local-fastbuild/bin/reproducible/debian9_structure_test.runfiles/debian_docker/tests/debian_9_test.yaml
=== RUN   TestAll/File_Content_Test:_Debian_Sources_Version
Retrieving image reproducible/intermediate_bundle_debian9_structure_test.tar from source Tar Archive
INFO[0000] Extracting image tar to obtain image file system 
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x75b6cd]

goroutine 7 [running]:
testing.tRunner.func1(0xc42045a1e0)
	/usr/lib/google-golang/src/testing/testing.go:711 +0x2d2
panic(0x7c3e60, 0xa67cd0)
	/usr/lib/google-golang/src/runtime/panic.go:491 +0x283
github.com/GoogleCloudPlatform/container-structure-test/types/v2.(*StructureTest).RunFileContentTests.func1(0xc42045a1e0)
	/usr/local/google/home/nkubala/Development/go/src/github.com/GoogleCloudPlatform/container-structure-test/types/v2/structure.go:119 +0xbd
testing.tRunner(0xc42045a1e0, 0xc42045e3e0)
	/usr/lib/google-golang/src/testing/testing.go:746 +0xd0
created by testing.(*T).Run
	/usr/lib/google-golang/src/testing/testing.go:789 +0x2de

This should exit gracefully with a message telling the user the tar file was not found.

Licence_check doesn't support symbolic links?

I'm building a new Python image on top of the gcr.io/gcp-runtimes/ubuntu_16_0_4 base, and I get these errors from licence_check:

Step #4:     	licenses.go:70: libssl-dev
Step #4:     	licenses.go:46: Error reading license file for /usr/share/doc/libssl-dev/copyright: API error (404): {"message":"Could not find the file ../libssl1.0.0/copyright in container f901a2834bcdbb685f7b2887e48680445b0bbb0008d8441955ed2f3764d4a350"}

Step #4:     	licenses.go:70: openssl
Step #4:     	licenses.go:46: Error reading license file for /usr/share/doc/openssl/copyright: API error (404): {"message":"Could not find the file ../libssl1.0.0/copyright in container 3678efba6b806b7817848917bfcfbf8334b74477d4bff5e99cbc91c8a5fe341b"}

The noteworthy thing is that these seem to be the only license files that are symbolic links instead of regular files.

$ docker run -it my_container /bin/bash -c 'ls -l /usr/share/doc/*/copyright | grep -- "->"'
lrwxrwxrwx 1 root root     24 Dec  7 21:09 /usr/share/doc/libssl-dev/copyright -> ../libssl1.0.0/copyright
lrwxrwxrwx 1 root root     24 Jan  1  1970 /usr/share/doc/openssl/copyright -> ../libssl1.0.0/copyright

Env variables are not being substituted by its actual value in commandTests

It seems like when running the tool inside Docker it's not using the defined env variables nor the existing ones. For example, for plain alpine images we have $HOME defined:

$ docker run -it --rm alpine /bin/sh
/ # echo $HOME
/root
/ #

But when trying to use it in a test it's not being substituted by its /root value. Neither the defined ones (both locally and global variables) seem to work. Having a test file like this:

schemaVersion: "2.0.0"
globalEnvVars:
  - key: "GLOBAL_VAR"
    value: "GLOBAL_VALUE"
commandTests:
  - name: "existing env variable"
    command: "echo"
    args: ["$HOME"]
    expectedOutput: ["/root"]
  - name: "local env variable"
    envVars:
      - key: "SOME_ENV"
        value: "someValue"
    command: "echo"
    args: ["$SOME_ENV"]
    expectedOutput: ["someValue"]
  - name: "global env variable"  
    command: "echo"
    args: ["$GLOBAL_VAR"]
    expectedOutput: ["GLOBAL_VALUE"]

and executing the tests with

docker run --rm \
    -v `pwd`:/tests \
    -v /var/run/docker.sock:/var/run/docker.sock \
    gcr.io/gcp-runtimes/container-structure-test:v1.0.0 \
    test \
    --image alpine \
    --config /tests/tests.yaml \
    -v

not a single tests pass:

===================================
====== Test file: tests.yaml ======
===================================
Total tests run: 3

=== RUN: [Command Test: existing env variable]
--- FAIL
stdout: $HOME

Error: Expected string '/root' not found in output

=== RUN: [Command Test: local env variable]
--- FAIL
stdout: $SOME_ENV

Error: Expected string 'someValue' not found in output

=== RUN: [Command Test: global env variable]
--- FAIL
stdout: $GLOBAL_VAR

Error: Expected string 'GLOBAL_VALUE' not found in output

FAILURES: 3
FAIL

How we can test daemons?

I have a very simple container with nginx which serves static content. I want to verify that nginx starts with proper virtual host configuration and returns index.html with all headers properly set. Since this PR is merged
With #43 merged entrypoint is empty and my nginx is not started. I was trying to start nginx as a daemon or as a detached process but I can't see how to do it. Seems like all processes started in setup stage are killed?

With this code I see that no nginx is running

- name: "nginx is running and returns index.html page"
  setup: [["apk", "--no-cache", "add", "curl"], ["nginx"]]
  command: "ps"
  args: ["aux"]
  expectedOutput: ["nginx"]

Test result:

    --- FAIL: TestAll/Command_Test:_nginx_is_running_and_returns_index.html_page (3.90s)
        docker_driver.go:85: stdout: PID   USER     TIME   COMMAND
                    1 root       0:00 ps aux
        utils.go:33: Expected string 'nginx' not found in output!

I also tried to run nginx not as daemon but detached ["nginx", "-g", "daemon off", "&"] - test result is the same. If I run nginx in foreground with ["nginx", "-g", "daemon off", "&"] then setup commands is hanging. I think you should fix logic of the setup command to allow it spawn daemons, detached processes or maybe don't wait for it to finish before running main command (for foreground commands).

File Content Tests should allow to check owner and group

I'm building a base docker image with nginx which should run all processes as nginx users (to be able to use this docker in openshift). I need to verify that certain directories/files are owned by nginx user to allow child images put files there.

-save flag not working

The readme mentions the -save flag, but I get this error message when trying to use it:

flag provided but not defined: -save

Different test results from tar driver for file exists test

Using Xubuntu 16.04 64 bit on a laptop.

My yaml file has the following:
schemaVersion: '2.0.0'
fileExistenceTests:

  • name: 'Root'
    isDirectory: true
    path: '/'
    shouldExist: true
  • name: 'python'
    isDirectory: true
    path: '/usr/local/bin/python'
    shouldExist: true

Running with the default docker driver the test passes.
$ sudo ./container-structure-test -test.v -image python python_file_test.yaml
Using driver docker
=== RUN TestAll
2018/02/28 17:18:52 Running tests for file python_file_test.yaml
=== RUN TestAll/File_Existence_Test:_Root
=== RUN TestAll/File_Existence_Test:_python
=== RUN TestAll/Metadata_Test
--- PASS: TestAll (2.46s)
--- PASS: TestAll/File_Existence_Test:_Root (2.29s)
--- PASS: TestAll/File_Existence_Test:_python (0.17s)
--- PASS: TestAll/Metadata_Test (0.00s)
structure_test.go:49: Total tests run: 3

When running with the tar driver the test fails.
$ sudo ./container-structure-test -test.v -driver tar -image python python_file_test.yaml
Using driver tar
=== RUN TestAll
2018/02/28 17:09:22 Running tests for file python_file_test.yaml
=== RUN TestAll/File_Existence_Test:_Root
Retrieving image python from source Cloud Registry
ERRO[0043] remove /tmp/python986107156/etc/dpkg/.wh.shlibs.default: no such file or directory
...
INFO[0164] Finished prepping image python
INFO[0164] Removing image filesystem directory /tmp/python885077350 from system
--- FAIL: TestAll (164.98s)
--- PASS: TestAll/File_Existence_Test:_Root (55.45s)
--- FAIL: TestAll/File_Existence_Test:_python (55.48s)
structure.go:94: File /usr/local/bin/python should exist but does not, got error: stat /tmp/python174701923/usr/local/bin/python: no such file or directory!
--- PASS: TestAll/Metadata_Test (54.06s)
structure_test.go:49: Total tests run: 2
FAIL

Using the tar driver should be consistent with the docker driver.

error while loading shared libraries: libstdc++.so.6

Hi,

I have attempted to upgrade to the latest container-structure-test version 0.2.0 however I am now receiving the below:

$ docker run --rm  -v /var/run/docker.sock:/var/run/docker.sock -v `pwd`/tests:/tests:ro gcr.io/gcp-runtimes/container-structure-test:v0.2.0 -test.v --image eu.gcr.io/k8-discovery-185615/platform-reverse-proxy:latest `ls tests/*.yaml`
/go_default_test: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory

I do not see the same running version 0.1.3 of the container image.

Docker version: 17.09.1 & 17.12.0

Cheers,
Mike

Empty args or commands are not properly validated

Currently there is code for each test type to validate input slice. The validation code only checks if a slice is nil or not, however, it does not check if the content of the slice is empty or not.

Example, this code will not be nil and will pass validation but will result in false negatives or panics.

metadataTest.Cmd := []string{""} 

Desired behaviour:

Content of args or any string slice should be properly checked not to include empty strings.

Metadata tests are not executed with RunAll()

I have noticed that metadata tests are not executed along with the other tests, is this intended behaviour?

	results := make([]*types.TestResult, 0)
	results = append(results, st.RunCommandTests()...)
	results = append(results, st.RunFileExistenceTests()...)
	results = append(results, st.RunFileContentTests()...)
	results = append(results, st.RunLicenseTests()...)
        results = append(results, st.RunMetadataTests()) //<- **Missing** 

MetadataTests report No tests to run!

Running the file below returns No tests to run!

This appears to comply with the example in the docs ??

$ structure-test -test.v -image busybox:latest meta_tests.yaml
Using driver docker
=== RUN   TestAll
2018/01/21 20:17:22 Running tests for file meta_tests.yaml
--- FAIL: TestAll (0.00s)
        structure_test.go:44: No tests run! Check config file format.
FAIL
schemaVersion: "2.0.0"

#globalEnvVars:
#  - key: "VIRTUAL_ENV"
#    value: "/env"
#  - key: "PATH"
#    value: "/env/bin:$PATH"

metadataTest:
  env:
    - key: "HTTP_PROXY"
      value: "http://myproxyproxy.myorg.com:80"
  exposedPorts: ["8080", "2345"]
  volumes: []
  entrypoint: ["entrypoint.sh"]
  cmd: []
  workdir: []

Kind Regards

Fraser.

Infer bazel-bin directory in release automation

We should be able to infer the output directory for the binary when building with bazel, so we don't have to keep changing the hardcoded name whenever we make a change to the build process. Something like

bazel info | grep bazel-bin | cut -d' ' -f2
or
bazel info bazel-bin

should give us enough to work with.

Feature request: Output format option

It would be useful to be able to output test results in a machine processable standard format (say) JSON or TAPS.

That would allow easier integration with build pipelines where test result would be more easily parsed and the build allowed to continue to fail based on results.

Regards

Fraser.

Fix bazel cross-compilation

Let's check to see if we can get the bazel cross compilation to work. If so we can start releasing this tool for OS X, and possible Windows.

stderr output instead of stdout for cmd test

I have an image that I am testing which includes the AWS CLI binary. I want to test that the version is what I expect. I have this command ...

    # check the aws-cli binary is the correct version
  - name: "aws-cli"
    command: "aws"
    args: ["--version"]
    expectedOutput: ["1.14.17"]

This test fails ... (some output elided for brevity)

Using driver docker
=== RUN   TestAll
2018/01/29 23:41:31 Running tests for file cmd_tests.yaml
...
=== RUN   TestAll/Command_Test:_aws-cli
--- FAIL: TestAll (1.96s)
...
    --- FAIL: TestAll/Command_Test:_aws-cli (1.07s)
        docker_driver.go:88: stderr: aws-cli/1.14.17 Python/2.7.13 Linux/3.10.0-514.26.2.el7.x86_64 botocore/1.8.21
        utils.go:33: Expected string '1.14.17' not found in output!
FAIL

As we can see the AWS cli version string was output, but it was sent to stderr rather than stdout ?
If I exec into this container and run aws --version it returns the expected string as above to the console.

Of course I could get a PASS for the test by changing expectedOutput to expectedError but I'm curious why this has happened (there are other similar tests I use inside the same image and they all return successfully thru stdout).

Any ideas ?

Regards

Fraser.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.