diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 4f06497..70f793b 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,10 +1,6 @@ -template: | - ## What’s Changed - - $CHANGES -change-template: "- $TITLE @$AUTHOR (#$NUMBER)" name-template: "v$RESOLVED_VERSION" tag-template: "v$RESOLVED_VERSION" +change-template: "- $TITLE @$AUTHOR (#$NUMBER)" categories: - title: "Enhancements" labels: @@ -30,3 +26,40 @@ autolabeler: - label: "documentation" files: - "*.md" +template: | + ## What’s Changed + + $CHANGES + + ## Installation + + Download the appropriate binary for your system. + + ```console + $ curl -L https://github.com/NVIDIA/container-canary/releases/download/v$RESOLVED_VERSION/canary_linux_amd64 > canary_linux_amd64 + ``` + + Download and verify the SHA256 hash. + + ```console + $ curl -L https://github.com/NVIDIA/container-canary/releases/download/v$RESOLVED_VERSION/canary_linux_amd64.sha256sum > canary_linux_amd64.sha256sum + + $ sha256sum --check --status canary_linux_amd64.sha256sum + ``` + + Install the binary somewhere on your path. + + ```console + $ chmod +x canary_linux_amd64 + + $ mv canary_linux_amd64 /usr/local/bin/canary + ``` + + Verify things are working. + + ```console + $ canary version + Container Canary + Version: v$RESOLVED_VERSION + ... + ``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5f7da6a..673c6a2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,7 +26,6 @@ go test -v ./... PASS ``` - ## Signing Your Work * We require that all contributors "sign-off" on their commits. This certifies that the contribution is your original work, or you have rights to submit it under the same license, or a compatible license. @@ -34,10 +33,13 @@ PASS * Any contribution which contains commits that are not Signed-Off will not be accepted. * To sign off on a commit you simply use the `--signoff` (or `-s`) option when committing your changes: + ```bash - $ git commit -s -m "Add cool feature." + git commit -s -m "Add cool feature." ``` + This will append the following to your commit message: + ``` Signed-off-by: Your Name ``` @@ -47,25 +49,25 @@ PASS ``` Developer Certificate of Origin Version 1.1 - + Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 1 Letterman Drive Suite D4700 San Francisco, CA, 94129 - + Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. ``` ``` Developer's Certificate of Origin 1.1 - + By making a contribution to this project, I certify that: - + (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or - + (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or - + (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. - + (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. ``` diff --git a/MAINTAINING.md b/MAINTAINING.md new file mode 100644 index 0000000..2b30491 --- /dev/null +++ b/MAINTAINING.md @@ -0,0 +1,23 @@ +# Maintaining + +This file contains notes and checklists for Container Canary maintainers. + +For development guidelines see [CONTRIBUTING.md](CONTRIBUTING.md). + +## Releasing + +Draft releases are created automatically via the [release drafter GitHub Action](https://github.com/release-drafter/release-drafter) and kept up to date with each new PR. + +The action will generate a changelog based on PR labels. For configuration options and the release notes template see [release-drafter.yml](.github/release-drafter.yml). + +To publish a new release: + +- Head to [releases](https://github.com/NVIDIA/container-canary/releases) and find the most recent draft. +- Edit the draft. +- Check the title and tag match the desired version (release drafter will attempt to bump this automatically based on PR tags). +- Check the body text makes sense. +- Hit publish release! + +Once the release and tag have been created [a GitHub Actions workflow](.github/workflows/upload-release-assets.yaml) will run to build assets for the tagged commit and attach them to the release. + +_Under the hood this runs `make package` to generate binaries for all supported platforms, then generates sha256 sums for each file and uploads them._ diff --git a/README.md b/README.md index 44601d4..bc4e7a0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # Container Canary +[![Test](https://github.com/NVIDIA/container-canary/actions/workflows/test.yaml/badge.svg)](https://github.com/NVIDIA/container-canary/actions/workflows/test.yaml) +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/nvidia/container-canary) +![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/nvidia/container-canary?label=version) + A little bird to validate your container images. ```console @@ -13,11 +17,32 @@ PASSED Many modern compute platforms support bring-your-own-container models where the user can provide container images with their custom software environment. However platforms commonly have a set of requirements that the container must conform to, such as using a non-root user, having the home directory in a specific location, having certain packages installed or running web applications on specific ports. -Container Canary is a tool for recording those requirements in a YAML manifest and then validating containers against that manifest. This is particularly useful in CI environments to avoid regressions in containers. +Container Canary is a tool for recording those requirements as a manifest that can be versioned and then validating containers against that manifest. This is particularly useful in CI environments to avoid regressions in containers. + +- [Container Canary](#container-canary) + - [Installation](#installation) + - [Example (Kubeflow)](#example-kubeflow) + - [Validator reference](#validator-reference) + - [Metadata](#metadata) + - [Runtime options](#runtime-options) + - [Environment variables](#environment-variables) + - [Ports](#ports) + - [Volumes](#volumes) + - [Checks](#checks) + - [Exec](#exec) + - [HTTPGet](#httpget) + - [Delays, timeouts, periods and thresholds](#delays-timeouts-periods-and-thresholds) + - [Contributing](#contributing) + - [Maintaining](#maintaining) + - [License](#license) + +## Installation + +You can find binaries and instructions on [our releases page](https://github.com/NVIDIA/container-canary/releases). ## Example (Kubeflow) -The [Kubeflow](https://www.kubeflow.org/) documentation has a [list of requirements](https://www.kubeflow.org/docs/components/notebooks/container-images/#custom-images) for container images that can be used in the Kubeflow Notebooks service. +The [Kubeflow](https://www.kubeflow.org/) documentation has a [list of requirements](https://www.kubeflow.org/docs/components/notebooks/container-images/#custom-images) for container images that can be used in the [Kubeflow Notebooks](https://www.kubeflow.org/docs/components/notebooks/) service. That list looks like this: @@ -112,3 +137,137 @@ Validating public.ecr.aws/j1r0q0g6/notebooks/notebook-servers/jupyter-scipy:v1.5 πŸ”“ Sets 'Access-Control-Allow-Origin: *' header [true] PASSED ``` + +For more examples [see the examples directory](examples/). + +## Validator reference + +Validator manifests are YAML files that describe how to validate a container image. Check out the [examples](examples/) directory for real world applications. + +### Metadata + +Each manifests starts with some metadata. + +```yaml +# Manifest versioning +apiVersion: container-canary.nvidia.com/v1 +kind: Validator + +# Metadata +name: foo # The name of the platform that this manifest validates for +description: Foo runs containers for you # A description of that platform +documentation: https://example.com # A link to the documentation that defines the container requirements in prose +``` + +### Runtime options + +Next you can set runtime configuration for the container you are validating. You should set these to mimic the environment that the compute platform will create. When you validate a container it will be run locally using [Docker](https://www.docker.com/). + +#### Environment variables + +A list of environment variables that should be set on the container. + +```yaml +env: + - name: HELLO + value: world + - name: FOO + value: bar +``` + +#### Ports + +Ports that need to be exposed on the container. These need to be configured in order for Container Canary to perform connectivity tests. + +```yaml +ports: + - port: 8888 + protocol: TCP +``` + +#### Volumes + +Volumes to be mounted to the container. This is useful if the compute platform will always mount an empty volume to a specific location. + +```yaml +volumes: + - mountPath: /home/jovyan +``` + +### Checks + +Checks are the tests that we want to run against the container to ensure it is compliant. Each check contains a probe, and those probes are superset of the Kubernetes [probes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) API and so any valid Kubernetes probe can be used in a check. + +```yaml +checks: + - name: mycheck # Name of the check + description: Ensuring a thing # Descrption of what is being checked (will be used in output) + probe: + ... # A probe to run +``` + +#### Exec + +An exec check runs a command inside the running container. If the command exits with `0` the check will pass. + +```yaml +checks: + - name: uid + description: User ID is 1234 + probe: + exec: + command: + - /bin/sh + - -c + - "id | grep uid=1234" +``` + +#### HTTPGet + +An HTTP Get check will perform an HTTP GET request against your container. If the response code is `<300` and the optional response headers match the check will pass. + +```yaml +checks: + - name: http + description: Exposes an HTTP interface on port 80 + probe: + httpGet: + path: / + port: 80 + httpHeaders: # Optional, headers to set in the request + - name: Foo-Header + value: "myheader" + responseHttpHeaders: # Optional, headers that you expect to see in the response + - name: Access-Control-Allow-Origin + value: "*" +``` + +#### Delays, timeouts, periods and thresholds + +Checks also support the same delays, timeouts, periods and thresholds that Kubernetes probes do. + +```yaml +checks: + - name: uid + description: User ID is 1234 + probe: + exec: + command: [...] + initialDelaySeconds: 0 # Delay after starting the container before the check should be run + timeoutSeconds: 30 # Overall timeout for the check + successThreshold: 1 # Number of times the check must pass before moving on + failureThreshold: 1 # Number of times the check is allowed to fail before giving up + periodSeconds: 1 # Interval between runs if threasholds are >1 +``` + +## Contributing + +Contributions are very welcome, be sure to review the [contribution guidelines](./CONTRIBUTING.md). + +## Maintaining + +Maintenance steps [can be found here](./MAINTAINING.md). + +## License + +Apache License Version 2.0, see [LICENSE](./LICENSE). diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..f351385 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,19 @@ +# Examples + +This directory contains example validation manifests. You can download and adapt these manifests or use them directly from GitHub. + +For example the Kubeflow example from the README can be used directly like this. + +```console +$ canary validate --file https://raw.githubusercontent.com/NVIDIA/container-canary/main/examples/kubeflow.yaml public.ecr.aws/j1r0q0g6/notebooks/notebook-servers/jupyter-scipy:v1.5.0-rc.1 +Validating public.ecr.aws/j1r0q0g6/notebooks/notebook-servers/jupyter-scipy:v1.5.0-rc.1 against kubeflow + πŸ‘© User is jovyan [true] + πŸ†” User ID is 1000 [true] + 🏠 Home directory is /home/jovyan [true] + 🌏 Exposes an HTTP interface on port 8888 [true] + 🧭 Correctly routes the NB_PREFIX [true] + πŸ”“ Sets 'Access-Control-Allow-Origin: *' header [true] +PASSED +``` + +[Contributing](../CONTRIBUTING.md) more manifests here is highly encouraged! diff --git a/examples/kubeflow.yaml b/examples/kubeflow.yaml index f1816b9..c1538e4 100644 --- a/examples/kubeflow.yaml +++ b/examples/kubeflow.yaml @@ -2,6 +2,7 @@ apiVersion: container-canary.nvidia.com/v1 kind: Validator name: kubeflow description: Kubeflow notebooks +documentation: https://www.kubeflow.org/docs/components/notebooks/container-images/#custom-images env: - name: NB_PREFIX value: /hub/jovyan/ diff --git a/internal/apis/v1/types.go b/internal/apis/v1/types.go index 2b39d35..4c133be 100644 --- a/internal/apis/v1/types.go +++ b/internal/apis/v1/types.go @@ -29,6 +29,10 @@ type Validator struct { // +optional Description string + // A link to the documentation where the requirements are defined. + // +optional + Documentation string + // A list of checks to perform validation against. Checks []Check