This repo is written in the Go programming language, which can be installed from their installation page. The version it was developed with was v1.18, which is the minimum required version for this SDK.
The SDK developed in this repo is tested by shellspec, which can be installed as documented in their README.
The SDK is linted by golangci-lint, which can be installed as documented in their local installation page.
The folder structure in this repository is:
│
└───builtins - rego builtins for custom functionality
│
└───cmd - commands and subcommands to register with the cobra CLI
│ root.go - the root command which needs each subcommand to be registered to
│
└───internal - internal implementation of OPA related functionality
│
└───fixtures - test fixtures
│
└───scripts - scripts for CircleCI or GitHub action
│
└───spec - shellspec tests
│ └─── e2e - shellspec end-to-end tests
| |
│ └─── contract - shellspec contract tests
│
└───util - other utility functions used throughout the code
To add a new command, you will need to add new files in various of the folders mentioned above so follow the steps below:
- Add a new file with the name of the command under
cmd
- The minimal file should contain:
package cmd
import (
"fmt"
"time"
"github.com/spf13/cobra"
"github.com/snyk/snyk-iac-rules/internal"
"github.com/snyk/snyk-iac-rules/util"
)
var <command>Command = &cobra.Command{
Use: "<command>",
Short: "",
Long: ``,
SilenceUsage: true, // disables help from being printed if command fails
RunE: func(cmd *cobra.Command, args []string) error {
return internal.Run<Command>(args, <command>Params)
},
}
func new<Command>CommandParams() *internal.<Command>CommandParams {
return &internal.<Command>CommandParams{
}
}
var <command>Params = new<Command>CommandParams()
func init() {
// initialise flags for the command
RootCommand.AddCommand(<command>Command)
}
- Add a new file with the name of the command under
internal
- this will contain the implementation forRun<Command>
package internal
import (
"errors"
"fmt"
"os"
"strings"
)
type <Command>CommandParams struct {
}
func Run<Command>(args []string, params *<Command>CommandParams) error {
return nil
}
- Add a basic test to with the name of the command under
spec
:
#!/bin/bash
Describe './snyk-iac-rules <command>'
It 'returns passing test status'
When call ./snyk-iac-rules <command>
The status should be success
The output should include ''
End
End
- Clone the repository
- Build and run the binary:
go build -o snyk-iac-rules .
. Or, alternatively,go run main.go {command}
. - Run the command:
$ ./snyk-iac-rules {command}
Make sure to build the Golang binary first by following the instructions in the README.
Note These instructions are for internal use only, as the feature is behind a feature flag and entitlement.
To run shellspec
tests, set the following environment variables based on the registry you want to push your bundle to:
export OS=<your OS>
export OCI_REGISTRY_NAME=<e.g. docker.io/<username>/<repo>:latest>
export OCI_REGISTRY_USERNAME=<username>
export OCI_REGISTRY_PASSWORD=<password>
From the project's root folder, run shellspec "spec/e2e"
to run shellspec tests for the end-to-end flow. This will verify the behaviour of the commands against the fixtures in the ./fixtures
folder and make sure the output and exit codes are correct.
These tests run as part of the entire CI/CD for our three supported OS's (Linux, MacOs, and Windows), apart from when we release a new version of the SDK.
Note These instructions are for internal use only, as the feature is behind a feature flag and entitlement.
To run the contract tests with Snyk, install Snyk by running npm i -g snyk
and set the SNYK_TOKEN
to the Auth Token from https://app.snyk.io/account.
Finally, run shellspec "spec/contract"
to verify if the generated bundle from the SDK is valid for the Snyk CLI.
These tests run as part of the entire CI/CD for our three supported OS's (Linux, MacOs, and Windows), apart from when we release a new version of the SDK.
Note These instructions are for internal use only, as the feature is behind a feature flag and entitlement.
To run the tests for supported registries, follow the same steps as the contract tests but also set the following environment variables and log into the registries manually:
export OCI_DOCKERHUB_REGISTRY_NAME=docker.io/<repo name>:<repo tag>
export OCI_DOCKERHUB_REGISTRY_URL=https://registry-1.${OCI_DOCKERHUB_REGISTRY_NAME}
export OCI_DOCKERHUB_REGISTRY_USERNAME=
export OCI_DOCKERHUB_REGISTRY_PASSWORD=
export OCI_AZURE_REGISTRY_NAME=<registry>/<account name>/<repo name>:<repo tag>
export OCI_AZURE_REGISTRY_URL=https://${OCI_AZURE_REGISTRY_NAME}
export OCI_AZURE_REGISTRY_USERNAME=<client id>
export OCI_AZURE_REGISTRY_PASSWORD=<client secret>
export OCI_HARBOR_REGISTRY_NAME=<registry>/<account name>/<repo name>:<repo tag>
export OCI_HARBOR_REGISTRY_URL=https://${OCI_HARBOR_REGISTRY_NAME}
export OCI_HARBOR_REGISTRY_USERNAME=
export OCI_HARBOR_REGISTRY_PASSWORD=
export OCI_GITHUB_REGISTRY_NAME=<registry>/<repo name>:<repo tag>
export OCI_ELASTIC_REGISTRY_URL=https://${OCI_GITHUB_REGISTRY_NAME}
export OCI_GITHUB_REGISTRY_USERNAME=<GitHub username>
export OCI_GITHUB_REGISTRY_PASSWORD=<personal access token>
export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=
export OCI_ELASTIC_REGISTRY_NAME=<registry>/<repo name>:<repo tag>
export OCI_ELASTIC_REGISTRY_URL=https://${OCI_ELASTIC_REGISTRY_NAME}
export OCI_ELASTIC_REGISTRY_USERNAME=AWS
Note To run one test at a time, only set the environment variables for one of these registries.
Make sure to have the aws CLI installed locally if you're running the Elastic tests and to do a docker login -u <username> -p <password>
prior to running the test
Finally, run shellspec "spec/registries"
to verify if the generated bundle from the SDK is valid for the Snyk CLI.
These tests run as part of the CI/CD for the main
branch on Linux only.
Alternatively, you can run go test ./...
for Golang unit tests. These test the files under ./internal
and ./util
and make sure complex behaviour is maintained between code changes.
For test coverage, run go test -coverprofile cover.out fmt ./...
and then go tool cover -html=cover.out
to see what is missing.
These tests run as part of the entire CI/CD, apart from when we release a new version of the SDK.
Note
All the fixtures under the ./fixture
folder are used for all Shellspec tests.
To format all files in the current directory and subdirectories, run go fmt ./...
from the root directory.
To run the linter, run golangci-lint run -v --timeout 10m
from the root directory.