Documentation ¶
Index ¶
- Constants
- Variables
- func ConditionDoesNotMatch(msg string) error
- func ConditionMatchInvalid(node *yaml.Node, err error) error
- func ConnectError(err error) error
- func EitherShortcutOrKubeSpecAt(node *yaml.Node) error
- func ExpectedMapOrYAMLStringAt(node *yaml.Node) error
- func ExpectedNotFound(msg string) error
- func InvalidResourceSpecifier(subject string, node *yaml.Node) error
- func InvalidResourceSpecifierOrFilepath(subject string, node *yaml.Node) error
- func InvalidWithLabels(err error, node *yaml.Node) error
- func KubeConfigNotFound(path string) error
- func MatchesInvalid(matches interface{}) error
- func MatchesInvalidUnmarshalError(err error) error
- func MatchesNotEqual(msg string) error
- func MoreThanOneKubeActionAt(node *yaml.Node) error
- func Plugin() api.Plugin
- func ResourceUnknown(arg string) error
- type Action
- type ConditionMatch
- type Defaults
- type Expect
- type KubeSpec
- type PlacementAssertion
- type ResourceIdentifier
- type ResourceIdentifierOrFile
- type Spec
- func (s *Spec) Base() *api.Spec
- func (s *Spec) Config(ctx context.Context) (*rest.Config, error)
- func (s *Spec) Eval(ctx context.Context) (*api.Result, error)
- func (s *Spec) Namespace() string
- func (s *Spec) Retry() *api.Retry
- func (s *Spec) SetBase(b api.Spec)
- func (s *Spec) Timeout() *api.Timeout
- func (s *Spec) Title() string
- func (s *Spec) UnmarshalYAML(node *yaml.Node) error
Constants ¶
const ( // StateKeyConfig holds a file path to a kubeconfig StateKeyConfig = "kube.config" // StateKeyConfigBytes holds a KUBECONFIG object in a bytearray StateKeyConfigBytes = "kube.config.bytes" // StateKeyContext holds a string kubecontext name StateKeyContext = "kube.context" )
Variables ¶
var ( // ErrExpectedMapOrYAMLString is returned when a field that can contain a // map[string]interface{} or an embedded YAML string did not contain either // of those things. // TODO(jaypipes): Move to gdt core? ErrExpectedMapOrYAMLString = fmt.Errorf( "%w: expected either map[string]interface{} "+ "or a string with embedded YAML", api.ErrParse, ) // ErrEitherShortcutOrKubeSpec is returned when the test author // included both a shortcut (e.g. `kube.create` or `kube.apply`) AND the // long-form `kube` object in the same test spec. ErrEitherShortcutOrKubeSpec = fmt.Errorf( "%w: either specify a full KubeSpec in the `kube` field or specify "+ "one of the shortcuts (e.g. `kube.create` or `kube.apply`", api.ErrParse, ) // ErrMoreThanOneKubeAction is returned when the test author // included more than one Kubernetes action (e.g. `create` or `apply`) in // the same KubeSpec. ErrMoreThanOneKubeAction = fmt.Errorf( "%w: you may only specify a single Kubernetes action field "+ "(e.g. `create`, `apply` or `delete`) in the `kube` object. ", api.ErrParse, ) // ErrKubeConfigNotFound is returned when a kubeconfig path points // to a file that does not exist. ErrKubeConfigNotFound = fmt.Errorf( "%w: specified kube config path not found", api.ErrParse, ) // ErrResourceSpecifier is returned when the test author uses a // resource specifier for the `kube.get` or `kube.delete` fields that is // not valid. ErrResourceSpecifierInvalid = fmt.Errorf( "%w: invalid resource specifier", api.ErrParse, ) // ErrResourceSpecifierOrFilepath is returned when the test author // uses a resource specifier for the `kube.delete` fields that is not valid // or is not a filepath. ErrResourceSpecifierInvalidOrFilepath = fmt.Errorf( "%w: invalid resource specifier or filepath", api.ErrParse, ) // ErrMatchesInvalid is returned when the `Kube.Assert.Matches` value is // malformed. ErrMatchesInvalid = fmt.Errorf( "%w: `kube.assert.matches` not well-formed", api.ErrParse, ) // ErrConditionMatchInvalid is returned when the `Kube.Assert.Conditions` // value is malformed. ErrConditionMatchInvalid = fmt.Errorf( "%w: `kube.assert.conditions` not well-formed", api.ErrParse, ) // ErrWithLabelsOnlyGetDelete is returned when the test author included // `kube.with.labels` but did not specify either `kube.get` or // `kube.delete`. ErrWithLabelsInvalid = fmt.Errorf( "%w: with labels invalid", api.ErrParse, ) // ErrWithLabelsOnlyGetDelete is returned when the test author included // `kube.with.labels` but did not specify either `kube.get` or // `kube.delete`. ErrWithLabelsOnlyGetDelete = fmt.Errorf( "%w: with labels may only be specified for "+ "`kube.get` or `kube.delete`", api.ErrParse, ) // ErrResourceUnknown is returned when an unknown resource kind is // specified for a create/apply/delete target. This is a runtime error // because we rely on the discovery client to determine whether a resource // kind is valid. ErrResourceUnknown = fmt.Errorf( "%w: resource unknown", api.ErrFailure, ) // ErrExpectedNotFound is returned when we expected to get either a // NotFound response code (get) or an empty set of results (list) but did // not find that. ErrExpectedNotFound = fmt.Errorf( "%w: expected not found", api.ErrFailure, ) // ErrMatchesNotEqual is returned when we failed to match a resource to an // object field in a `kube.assert.matches` object. ErrMatchesNotEqual = fmt.Errorf( "%w: match field not equal", api.ErrFailure, ) // ErrConditionDoesNotMatch is returned when we failed to match a resource to an // Condition match expression in a `kube.assert.matches` object. ErrConditionDoesNotMatch = fmt.Errorf( "%w: condition does not match expectation", api.ErrFailure, ) // ErrConnect is returned when we failed to create a client config to // connect to the Kubernetes API server. ErrConnect = fmt.Errorf( "%w: k8s connect failure", api.RuntimeError, ) )
var ( // DefaultTimeout is the default timeout used for each individual test // spec. Note that gdt's top-level Scenario.Run handles all timeout and // retry behaviour. DefaultTimeout = "5s" )
Functions ¶
func ConditionDoesNotMatch ¶
ConditionDoesNotMatch returns ErrConditionDoesNotMatch when a `kube.assert.conditions` object did not match the returned resource.
func ConditionMatchInvalid ¶
ConditionMatchInvalid returns ErrConditionMatchInvalid when a `kube.assert.conditions` field contains invalid YAML content.
func ConnectError ¶ added in v1.1.0
ConnectError returns ErrConnnect when an error is found trying to construct a Kubernetes client connection.
func EitherShortcutOrKubeSpecAt ¶ added in v1.3.0
func EitherShortcutOrKubeSpecAt(node *yaml.Node) error
EitherShortcutOrKubeSpecAt returns ErrEitherShortcutOrKubeSpec for a given YAML node
func ExpectedMapOrYAMLStringAt ¶ added in v1.1.1
func ExpectedMapOrYAMLStringAt(node *yaml.Node) error
ExpectedMapOrYAMLStringAt returns ErrExpectedMapOrYAMLString for a given YAML node
func ExpectedNotFound ¶
ExpectedNotFound returns ErrExpectedNotFound for a given status code or number of items.
func InvalidResourceSpecifier ¶
InvalidResourceSpecifier returns ErrResourceSpecifier for a given supplied resource specifier.
func InvalidResourceSpecifierOrFilepath ¶
InvalidResourceSpecifierOrFilepath returns ErrResourceSpecifierOrFilepath for a given supplied subject.
func InvalidWithLabels ¶
InvalidWithLabels returns ErrWithLabels with an error containing more context.
func KubeConfigNotFound ¶
KubeConfigNotFound returns ErrKubeConfigNotFound for a given filepath
func MatchesInvalid ¶
func MatchesInvalid(matches interface{}) error
MatchesInvalid returns ErrMatchesInvalid when a `kube.assert.matches` field is not well-formed.
func MatchesInvalidUnmarshalError ¶
MatchesInvalidUnmarshalError returns ErrMatchesInvalid when a `kube.assert.matches` field contains invalid YAML content.
func MatchesNotEqual ¶
MatchesNotEqual returns ErrMatchesNotEqual when a `kube.assert.matches` object did not match the returned resource.
func MoreThanOneKubeActionAt ¶ added in v1.3.0
func MoreThanOneKubeActionAt(node *yaml.Node) error
MoreThanOneKubeActionAt returns ErrMoreThanOneKubeAction for a given YAML node
func ResourceUnknown ¶
ResourceUnknown returns ErrRuntimeResourceUnknown for a given resource or kind arg string
Types ¶
type Action ¶ added in v1.3.0
type Action struct { // Create is a string containing a file path or raw YAML content describing // a Kubernetes resource to call `kubectl create` with. Create string `yaml:"create,omitempty"` // Apply is a string containing a file path or raw YAML content describing // a Kubernetes resource to call `kubectl apply` with. Apply string `yaml:"apply,omitempty"` // Delete is a string or object containing arguments to `kubectl delete`. // // It must be one of the following: // // - a file path to a manifest that will be read and the resources // described in the manifest will be deleted // - a resource kind or kind alias, e.g. "pods", "po", followed by one of // the following: // * a space or `/` character followed by the resource name to delete // only a resource with that name. // - an object with a `type` and optional `labels` field containing a label // selector that should be used to select that `type` of resource. Delete *ResourceIdentifierOrFile `yaml:"delete,omitempty"` // Get is a string or object containing arguments to `kubectl get`. // // It must be one of the following: // // - a string with a resource kind or kind alias, e.g. "pods", "po", // followed by one of the following: // * a space or `/` character followed by the resource name to get only a // resource with that name. // - an object with a `type` and optional `labels` field containing a label // selector that should be used to select that `type` of resource. Get *ResourceIdentifier `yaml:"get,omitempty"` }
Action describes the the Kubernetes-specific action that is performed by the test.
func (*Action) Do ¶ added in v1.3.0
Do performs a single kube command, returning any runtime error.
`kubeErr` will be filled with any error received from the Kubernetes client call.
`out` will be filled with the contents of the command's output, if any. When the command is a Get, `out` will be a `*unstructured.Unstructured`. When the command is a List, `out` will be a `*unstructured.UnstructuredList`.
func (*Action) UnmarshalYAML ¶ added in v1.3.0
type ConditionMatch ¶
type ConditionMatch struct {
// contains filtered or unexported fields
}
ConditionMatch can be a string (the ConditionStatus to match), a slice of strings (any of the ConditionStatus values to match) or an object with Status and Reason fields describing the Condition fields we want to match on.
func (*ConditionMatch) UnmarshalYAML ¶
func (m *ConditionMatch) UnmarshalYAML(node *yaml.Node) error
UnmarshalYAML is a custom unmarshaler that understands that the value of the ConditionMatch can be either a string, a slice of strings, or an object with .
type Defaults ¶
type Defaults struct {
// contains filtered or unexported fields
}
Defaults is the known HTTP plugin defaults collection
func (*Defaults) UnmarshalYAML ¶
type Expect ¶
type Expect struct { // Error is a string that is expected to be returned as an error string // from the client call // TODO(jaypipes): Make this polymorphic to be either a shortcut string // (like this) or a struct containing individual error assertion fields. Error string `yaml:"error,omitempty"` // Len is an integer that is expected to represent the number of items in // the response when the Get request was translated into a List operation // (i.e. when the resource specified was a plural kind Len *int `yaml:"len,omitempty"` // NotFound is a bool indicating the result of a call should be a // NotFound error. Alternately, the user can set `assert.len = 0` and for // single-object-returning calls (e.g. `get` or `delete`) the assertion is // equivalent to `assert.notfound = true` NotFound bool `yaml:"notfound,omitempty"` // Unknown is a bool indicating the test author expects that they will have // gotten an error ("the server could not find the requested resource") // from the Kubernetes API server. This is mostly good for unit/fuzz // testing CRDs. Unknown bool `yaml:"unknown,omitempty"` // Matches is either a string or a map[string]interface{} containing the // resource that the `Kube.Get` should match against. If Matches is a // string, the string can be either a file path to a YAML manifest or // inline an YAML string containing the resource fields to compare. // // Only fields present in the Matches resource are compared. There is a // check for existence in the retrieved resource as well as a check that // the value of the fields match. Only scalar fields are matched entirely. // In other words, you do not need to specify every field of a struct field // in order to compare the value of a single field in the nested struct. // // As an example, imagine you wanted to check that a Deployment resource's // `Status.ReadyReplicas` field was 2. You do not need to specify all other // `Deployment.Status` fields like `Status.Replicas` in order to match the // `Status.ReadyReplicas` field value. You only need to include the // `Status.ReadyReplicas` field in the `Matches` value as these examples // demonstrate: // // “`yaml // tests: // - name: check deployment's ready replicas is 2 // kube: // get: deployments/my-deployment // assert: // matches: | // kind: Deployment // metadata: // name: my-deployment // status: // readyReplicas: 2 // “` // // you don't even need to include the kind and metadata in `Matches`. If // missing, no kind and name matching will be performed. // // “`yaml // tests: // - name: check deployment's ready replicas is 2 // kube: // get: deployments/my-deployment // assert: // matches: | // status: // readyReplicas: 2 // “` // // In fact, you don't need to use an inline multiline YAML string. You can // use a `map[string]interface{}` as well: // // “`yaml // tests: // - name: check deployment's ready replicas is 2 // kube: // get: deployments/my-deployment // assert: // matches: // status: // readyReplicas: 2 // “` Matches interface{} `yaml:"matches,omitempty"` // JSON contains the assertions about JSON data in a response from the // Kubernetes API server. JSON *gdtjson.Expect `yaml:"json,omitempty"` // Conditions contains the assertions to make about a resource's // `Status.Conditions` collection. It is a map, keyed by the ConditionType // (matched case-insensitively), of assertions to make about that // Condition. The assertions can be: // // * a string which is the ConditionStatus that should be found for that // Condition // * a list of strings containing ConditionStatuses, any of which should be // found for that Condition. // * an object of type `ConditionExpect` that contains more fine-grained // assertions about that Condition. // // A simple example that asserts that a Pod's `Ready` Condition has a // status of `True`. Note that both the condition type ("Ready") and the // status ("True") are matched case-insensitively, which means you can just // use lowercase strings: // // “`yaml // tests: // - kube: // get: pods/nginx // assert: // conditions: // ready: true // “` // // If we wanted to assert that the `ContainersReady` Condition had a status // of either `False` or `Unknown`, we could write the test like this: // // “`yaml // tests: // - kube: // get: pods/nginx // assert: // conditions: // containersReady: // - false // - unknown // “` // // Finally, if we wanted to assert that a Deployment's `Progressing` // Condition had a Reason field with a value "NewReplicaSetAvailable" // (matched case-sensitively), we could do the following: // // “`yaml // tests: // - kube: // get: deployments/nginx // assert: // conditions: // progressing: // status: true // reason: NewReplicaSetAvailable // “` Conditions map[string]*ConditionMatch `yaml:"conditions,omitempty"` // Placement describes expected Pod scheduling spread or pack outcomes. Placement *PlacementAssertion `yaml:"placement,omitempty"` }
Expect contains one or more assertions about a kube client call
func (*Expect) UnmarshalYAML ¶ added in v1.1.1
type KubeSpec ¶
type KubeSpec struct { Action // Config is the path of the kubeconfig to use in executing Kubernetes // client calls for this Spec. If empty, the `kube` defaults' `config` // value will be used. If that is empty, the following precedence is used: // // 1) KUBECONFIG environment variable pointing at a file. // 2) In-cluster config if running in cluster. // 3) $HOME/.kube/config if exists. Config string `yaml:"config,omitempty"` // Context is the name of the kubecontext to use for this Spec. If empty, // the `kube` defaults' `context` value will be used. If that is empty, the // kubecontext marked default in the kubeconfig is used. Context string `yaml:"context,omitempty"` // Namespace is a string indicating the Kubernetes namespace to use when // calling the Kubernetes API. If empty, any namespace specified in the // Defaults is used and then the string "default" is used. Namespace string `yaml:"namespace,omitempty"` }
KubeSpec is the complex type containing all of the Kubernetes-specific actions. Most users will use the `kube.create`, `kube.apply` and `kube.describe` shortcut fields.
func (*KubeSpec) UnmarshalYAML ¶ added in v1.3.0
type PlacementAssertion ¶ added in v1.4.0
type PlacementAssertion struct { // Spread contains zero or more topology keys that gdt-kube will assert an // even spread across. Spread *api.FlexStrings `yaml:"spread,omitempty"` // Pack contains zero or more topology keys that gdt-kube will assert // bin-packing of resources within. Pack *api.FlexStrings `yaml:"pack,omitempty"` }
PlacementAssertion describes an expectation for Pod scheduling outcomes.
type ResourceIdentifier ¶ added in v1.3.0
type ResourceIdentifier struct { Arg string `yaml:"-"` Name string `yaml:"-"` Labels map[string]string `yaml:"-"` }
ResourceIdentifier is a struct used to parse an interface{} that can be either a string or a struct containing a selector with things like a label key/value map.
func NewResourceIdentifier ¶ added in v1.3.0
func NewResourceIdentifier( arg string, name string, labels map[string]string, ) *ResourceIdentifier
func (*ResourceIdentifier) Title ¶ added in v1.3.0
func (r *ResourceIdentifier) Title() string
Title returns the resource identifier's kind and name, if present
func (*ResourceIdentifier) UnmarshalYAML ¶ added in v1.3.0
func (r *ResourceIdentifier) UnmarshalYAML(node *yaml.Node) error
UnmarshalYAML is a custom unmarshaler that understands that the value of the ResourceIdentifier can be either a string or a selector.
type ResourceIdentifierOrFile ¶ added in v1.3.0
type ResourceIdentifierOrFile struct { Arg string `yaml:"-"` Name string `yaml:"-"` Labels map[string]string `yaml:"-"` // contains filtered or unexported fields }
ResourceIdentifierOrFile is a struct used to parse an interface{} that can be either a string, a filepath or a struct containing a selector with things like a label key/value map.
func NewResourceIdentifierOrFile ¶ added in v1.3.0
func (*ResourceIdentifierOrFile) FilePath ¶ added in v1.3.0
func (r *ResourceIdentifierOrFile) FilePath() string
FilePath returns the resource identifier's file path, if present
func (*ResourceIdentifierOrFile) Title ¶ added in v1.3.0
func (r *ResourceIdentifierOrFile) Title() string
Title returns the resource identifier's file name, if present, or the kind and name, if present
func (*ResourceIdentifierOrFile) UnmarshalYAML ¶ added in v1.3.0
func (r *ResourceIdentifierOrFile) UnmarshalYAML(node *yaml.Node) error
UnmarshalYAML is a custom unmarshaler that understands that the value of the ResourceIdentifierOrFile can be either a string or a selector.
type Spec ¶
type Spec struct { api.Spec // Kube is the complex type containing all of the Kubernetes-specific // actions and assertions. Most users will use the `kube.create`, // `kube.apply` and `kube.describe` shortcut fields. Kube *KubeSpec `yaml:"kube,omitempty"` // KubeCreate is a shortcut for the `KubeSpec.Create`. It can contain // either a file path or raw YAML content describing a Kubernetes resource // to call `kubectl create` with. KubeCreate string `yaml:"kube.create,omitempty"` // KubeGet is a string containing an argument to `kubectl get` and must be // one of the following: // // - a file path to a manifest that will be read and the resources within // retrieved via `kubectl get` // - a resource kind or kind alias, e.g. "pods", "po", followed by one of // the following: // * a space or `/` character followed by the resource name to get only a // resource with that name. // * a space followed by `-l ` followed by a label to get resources // having such a label. KubeGet string `yaml:"kube.get,omitempty"` // KubeApply is a shortcut for the `KubeSpec.Apply`. It is a string // containing a file path or raw YAML content describing a Kubernetes // resource to call `kubectl apply` with. KubeApply string `yaml:"kube.apply,omitempty"` // KubeDelete is a shortcut for the `KubeSpec.Delete`. It is a string // containing an argument to `kubectl delete` and must be one of the // following: // // - a file path to a manifest that will be read and the resources // described in the manifest will be deleted // - a resource kind or kind alias, e.g. "pods", "po", followed by one of // the following: // * a space or `/` character followed by the resource name to delete // only a resource with that name. // * a space followed by `-l ` followed by a label to delete resources // having such a label. // * the string `--all` to delete all resources of that kind. KubeDelete string `yaml:"kube.delete,omitempty"` // Assert houses the various assertions to be made about the kube client // call (Create, Apply, Get, etc) // TODO(jaypipes): Make this polymorphic to be either a single assertion // struct or a list of assertion structs Assert *Expect `yaml:"assert,omitempty"` }
Spec describes a test of a *single* Kubernetes API request and response.
func (*Spec) Config ¶
Config returns a Kubernetes client-go rest.Config to use for this Spec. We evaluate where to retrieve the Kubernetes config from by looking at the following things, in this order:
1) The Spec.Kube.Config value 2) Any Fixtures that return a `kube.config` or `kube.config.bytes` state key 3) The Defaults.Config value 4) KUBECONFIG environment variable pointing at a file. 5) In-cluster config if running in cluster. 6) $HOME/.kube/config if exists.
func (*Spec) Eval ¶ added in v1.1.0
Eval performs an action and evaluates the results of that action, returning a Result that informs the Scenario about what failed or succeeded. A new Kubernetes client request is made during this call.
func (*Spec) Namespace ¶
Namespace returns the Kubernetes namespace to use when calling the Kubernetes API server. We evaluate which namespace to use by looking at the following things, in this order:
1) The Spec.Kube.Namespace value 2) The Defaults.Namespace value 3) Use the string "default"