gator

package
v3.9.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 3, 2022 License: Apache-2.0 Imports: 26 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// Group is the API Group for Test YAML objects.
	Group = "test.gatekeeper.sh"
	// Kind is the Kind for Suite YAML objects.
	Kind = "Suite"
)

Variables

View Source
var (
	// ErrNotATemplate indicates the user-indicated file does not contain a
	// ConstraintTemplate.
	ErrNotATemplate = errors.New("not a ConstraintTemplate")
	// ErrNotAConstraint indicates the user-indicated file does not contain a
	// Constraint.
	ErrNotAConstraint = errors.New("not a Constraint")
	// ErrAddingTemplate indicates a problem instantiating a Suite's ConstraintTemplate.
	ErrAddingTemplate = errors.New("adding template")
	// ErrAddingConstraint indicates a problem instantiating a Suite's Constraint.
	ErrAddingConstraint = errors.New("adding constraint")
	// ErrInvalidSuite indicates a Suite does not define the required fields.
	ErrInvalidSuite = errors.New("invalid Suite")
	// ErrCreatingClient indicates an error instantiating the Client which compiles
	// Constraints and runs validation.
	ErrCreatingClient = errors.New("creating client")
	// ErrInvalidCase indicates a Case cannot be run due to not being configured properly.
	ErrInvalidCase = errors.New("invalid Case")
	// ErrNumViolations indicates an Object did not get the expected number of
	// violations.
	ErrNumViolations = errors.New("unexpected number of violations")
	// ErrInvalidRegex indicates a Case specified a Violation regex that could not
	// be compiled.
	ErrInvalidRegex = errors.New("message contains invalid regular expression")
	// ErrInvalidFilter indicates that Filter construction failed.
	ErrInvalidFilter = errors.New("invalid test filter")
	// ErrNoObjects indicates that a specified YAML file contained no objects.
	ErrNoObjects = errors.New("missing objects")
	// ErrMultipleObjects indicates that a specified YAML file contained multiple objects.
	ErrMultipleObjects = errors.New("object file must contain exactly one object")
	// ErrAddInventory indicates that an object that was declared to be part of
	// data.inventory was unable to be added.
	ErrAddInventory = errors.New("unable to add object to data.inventory")
	// ErrConvertingTemplate means we were able to parse a template, but not convert
	// it into the version-independent format.
	ErrConvertingTemplate = errors.New("unable to convert template")
)
View Source
var (
	// ErrNoFileSystem means a method which expects a filesystem got nil
	// instead. This is likely a bug in the code.
	ErrNoFileSystem = errors.New("no filesystem")
	// ErrNoTarget indicates that the user did not specify a target directory or
	// file.
	ErrNoTarget = errors.New("target not specified")
	// ErrUnsupportedExtension indicates that a user attempted to run tests in
	// a file type which is not supported.
	ErrUnsupportedExtension = errors.New("unsupported extension")
	// ErrInvalidYAML indicates that a .yaml/.yml file was not parseable.
	ErrInvalidYAML = errors.New("invalid yaml")
	// ErrNotADirectory indicates that a user is mistakenly attempting to
	// perform a directory-only action on a file (for example, recursively
	// traversing it).
	ErrNotADirectory = errors.New("not a directory")
)
View Source
var ErrWritingString = errors.New("writing output")

ErrWritingString means there was a problem writing output to the writer passed to Print.

Functions

func ReadK8sResources

func ReadK8sResources(r io.Reader) ([]*unstructured.Unstructured, error)

ReadK8sResources reads JSON or YAML k8s resources from an io.Reader, decoding them into Unstructured objects and returning those objects as a slice.

func ReadObject

func ReadObject(f fs.FS, path string) (*unstructured.Unstructured, error)

ReadObject reads a file from the filesystem abstraction at the specified path, and returns an unstructured.Unstructured object if the file can be successfully unmarshalled.

func ReadTemplate

func ReadTemplate(scheme *runtime.Scheme, f fs.FS, path string) (*templates.ConstraintTemplate, error)

ReadTemplate reads the contents of the path and returns the ConstraintTemplate it defines. Returns an error if the file does not define a ConstraintTemplate.

func ToTemplate

ToTemplate converts an unstructured template into a versionless ConstraintTemplate struct.

Types

type Assertion

type Assertion struct {
	// Violations, if set, indicates either whether there are violations, or how
	// many violations match this assertion.
	//
	// The value may be either an integer, of a string. If an integer, exactly
	// this number of violations must otherwise match this Assertion. If a string,
	// must be either "yes" or "no". If "yes" at least one violation must match
	// the Assertion to be satisfied. If "no", there must be zero violations
	// matching the Assertion to be satisfied.
	//
	// Defaults to "yes".
	Violations *intstr.IntOrString `json:"violations,omitempty"`

	// Message is a regular expression which matches the Msg field of individual
	// violations.
	//
	// If unset, has no effect and all violations match this Assertion.
	Message *string `json:"message,omitempty"`
	// contains filtered or unexported fields
}

An Assertion is a declaration about the data returned by running an object against a Constraint.

func (*Assertion) Run

func (a *Assertion) Run(results []*types.Result) error

type Case

type Case struct {
	Name string `json:"name"`

	// Object is the path to the file containing a Kubernetes object to test.
	Object string `json:"object"`

	// Inventory is a list of paths to files containing Kubernetes objects to put
	// in data.inventory for testing referential constraints.
	Inventory []string `json:"inventory"`

	// Assertions are statements which must be true about the result of running
	// Review with the Test's Constraint on the Case's Object.
	//
	// All Assertions must succeed in order for the test to pass.
	// If no assertions are present, assumes reviewing Object produces no
	// violations.
	Assertions []Assertion `json:"assertions"`

	// Skip, if true, skips this Case.
	Skip bool `json:"skip"`
}

Case runs Constraint against a YAML object.

type CaseResult

type CaseResult struct {
	// Name is the name given to this test for the Constraint under test.
	Name string

	// Skipped is whether this Case was skipped while running its parent Test.
	Skipped bool

	// Error is the either:
	// 1) why this case failed, or
	// 2) the error which prevented running this case.
	// We don't need to distinguish between 1 and 2 - they are both treated as
	// failures.
	Error error

	// Runtime is the time it took for this Case to run.
	Runtime Duration
}

CaseResult is the result of evaluating a Constraint against a kubernetes object, and comparing the result with the expected result.

func (*CaseResult) IsFailure

func (r *CaseResult) IsFailure() bool

IsFailure returns true if the test failed to execute or produced an unexpected result.

type Client

type Client interface {
	// AddTemplate adds a Template to the Client. Templates define the structure
	// and parameters of potential Constraints.
	AddTemplate(ctx context.Context, templ *templates.ConstraintTemplate) (*types.Responses, error)

	// AddConstraint adds a Constraint to the Client. Must map to one of the
	// previously-added Templates.
	//
	// Returns an error if the referenced Template does not exist, or the
	// Constraint does not match the structure defined by the referenced Template.
	AddConstraint(ctx context.Context, constraint *unstructured.Unstructured) (*types.Responses, error)

	// AddData adds the state of the cluster. For use in referential Constraints.
	AddData(ctx context.Context, data interface{}) (*types.Responses, error)

	// RemoveData removes objects from the state of the cluster. For use in
	// referential constraints.
	RemoveData(ctx context.Context, data interface{}) (*types.Responses, error)

	// Review runs all Constraints against obj.
	Review(ctx context.Context, obj interface{}, opts ...drivers.QueryOpt) (*types.Responses, error)
}

func NewOPAClient

func NewOPAClient() (Client, error)

type Duration

type Duration time.Duration

Duration is an alias of time.Duration to allow for custom formatting. Otherwise time formatting must be done inline everywhere.

func (Duration) String

func (d Duration) String() string

type Filter

type Filter interface {
	// MatchesTest returns true if the Test should be run.
	MatchesTest(Test) bool
	// MatchesCase returns true if Case caseName in Test testName should be run.
	MatchesCase(testName, caseName string) bool
}

func NewFilter

func NewFilter(filter string) (Filter, error)

NewFilter parses run into a Filter for selecting constraint tests and individual cases to run.

Empty string results in a Filter which matches all tests and their cases.

Examples: 1) NewFiler("require-foo-label//missing-label") Matches tests containing the string "require-foo-label" and cases containing the string "missing-label". So this would match all of the following: - Test: "require-foo-label", Case: "missing-label" - Test: "not-require-foo-label, Case: "not-missing-label" - Test: "require-foo-label", Case: "missing-label-and-annotation"

2) NewFilter("missing-label") Matches cases which either have a name containing "missing-label" or which are in a test named "missing-label". Matches the following: - Test: "forbid-missing-label", Case: "with-foo-label" - Test: "required-labels", Case: "missing-label"

3) NewFilter("^require-foo-label$//") Matches tests which exactly match "require-foo-label". Matches the following: - Test: "require-foo-label", Case: "with-foo-label" - Test: "require-foo-label", Case: "no-labels"

4) NewFilter("//empty-object") Matches tests whose names contain the string "empty-object". Matches the following: - Test: "forbid-foo-label", Case: "empty-object" - Test: "forbid-foo-label", Case: "another-empty-object" - Test: "require-bar-annotation", Case: "empty-object".

type Printer

type Printer interface {
	// Print formats and writes SuiteResult to w. If verbose it true, prints more
	// extensive output (behavior is specific to the printer). Returns an error
	// if there is a problem writing to w.
	Print(w StringWriter, r []SuiteResult, verbose bool) error
}

Printer knows how to print the results of running a Suite.

type PrinterGo

type PrinterGo struct{}

func (PrinterGo) Print

func (p PrinterGo) Print(w StringWriter, r []SuiteResult, verbose bool) error

func (PrinterGo) PrintCase

func (p PrinterGo) PrintCase(w StringWriter, r *CaseResult, verbose bool) error

func (PrinterGo) PrintSuite

func (p PrinterGo) PrintSuite(w StringWriter, r *SuiteResult, verbose bool) error

func (PrinterGo) PrintTest

func (p PrinterGo) PrintTest(w StringWriter, r *TestResult, verbose bool) error

type Runner

type Runner struct {
	// contains filtered or unexported fields
}

Runner defines logic independent of how tests are run and the results are printed.

func NewRunner

func NewRunner(filesystem fs.FS, newClient func() (Client, error)) (*Runner, error)

func (*Runner) Run

func (r *Runner) Run(ctx context.Context, filter Filter, s *Suite) SuiteResult

Run executes all Tests in the Suite and returns the results.

type StringWriter

type StringWriter interface {
	WriteString(s string) (int, error)
}

StringWriter knows how to write a string to a Writer.

Note: StringBuffer meets this interface.

type Suite

type Suite struct {
	metav1.ObjectMeta

	// Tests is a list of Template&Constraint pairs, with tests to run on
	// each.
	Tests []Test `json:"tests"`

	// Path is the filepath of this Suite on disk.
	Path string `json:"-"`

	// Skip, if true, skips this Suite.
	Skip bool `json:"skip"`
}

Suite defines a set of Constraint tests.

func ReadSuites

func ReadSuites(f fs.FS, target string, recursive bool) ([]*Suite, error)

ReadSuites returns the set of test Suites selected by path.

  1. If path is a path to a Suite, parses and returns the Suite.
  2. If the path is a directory and recursive is false, returns only the Suites defined in that directory.
  3. If the path is a directory and recursive is true returns all Suites in that directory and its subdirectories.

Returns an error if: - path is a file that does not define a Suite - any matched files containing Suites are not parseable.

type SuiteResult

type SuiteResult struct {
	// Path is the absolute path to the file which defines Suite.
	Path string

	// Error is the error which stopped the Suite from executing.
	// If defined, TestResults is empty.
	Error error

	// Runtime is the time it took for this Suite of tests to run.
	Runtime Duration

	// TestResults are the results of running the tests for each defined
	// Template/Constraint pair.
	TestResults []TestResult

	// Skipped is whether this Suite was skipped and not run.
	Skipped bool
}

SuiteResult is the Result of running a Suite of tests.

func (*SuiteResult) IsFailure

func (r *SuiteResult) IsFailure() bool

IsFailure returns true if there was a problem running the Suite, or one of the Constraint tests failed.

type Test

type Test struct {
	Name string `json:"name"`

	// Template is the path to the ConstraintTemplate, relative to the file
	// defining the Suite.
	Template string `json:"template"`

	// Constraint is the path to the Constraint, relative to the file defining
	// the Suite. Must be an instance of Template.
	Constraint string `json:"constraint"`

	// Cases are the test cases to run on the instantiated Constraint.
	Cases []*Case `json:"cases,omitempty"`

	// Skip, if true, skips this Test.
	Skip bool `json:"skip"`
}

Test defines a Template&Constraint pair to instantiate, and Cases to run on the instantiated Constraint.

type TestResult

type TestResult struct {
	// Name is the name given to the Template/Constraint pair under test.
	Name string

	// Skipped is whether this Test was skipped while running its parent Suite.
	Skipped bool

	// Error is the error which prevented running tests for this Constraint.
	// If defined, CaseResults is empty.
	Error error

	// Runtime is the time it took for the Template/Constraint to be compiled, and
	// the test Cases to run.
	Runtime Duration

	// CaseResults are individual results for all tests defined for this Constraint.
	CaseResults []CaseResult
}

TestResult is the results of: 1) Compiling the ConstraintTemplate, 2) Instantiating the Constraint, and 3) Running all Tests defined for the Constraint.

func (*TestResult) IsFailure

func (r *TestResult) IsFailure() bool

IsFailure returns true if there was a problem running the Constraint tests, or one of its Tests failed.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL