v0.0.6
Release v0.0.6
This project is fast moving. As with previous releases, members of the community has contributed a set of great new features. Thank you to everyone involved 😃
YAML/JSON decoder
This release introduces package klient/decoder
to help test writers to create Kubernetes API objects from YMAL or JSON snippets. This provides a convenient method to programmatically generate API objects from YAML or JSON string values. The decoder supports the followings:
- Decoding single-document YAML/JSON input
- Decoding a multi-document YAML/JSON input
- Ability to decode from a Go
io.Reader
For detail, see the design doc.
Example
Given file testdata/config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
data:
example.yaml: |
key: value
The following can be used to decode and create API objects from a file:
func main {
f, err := os.Open("testdata/config.yaml")
if err != nil {
t.Fatal(err)
}
obj, err := decoder.DecodeAny(f)
if err != nil {
log.Fatal(err)
}
configMap, ok := obj.(*v1.ConfigMap)
if !ok {
log.Fatal("object decoded to unexpected type")
}
}
Alternatively, the package supports the use of handler functions to provider decoder logic for objects. For instance, assuming directory testdata
has several YMAL files, the following snippet would automatically decode each object and insert them (using the CreateHandler
handler function) in the API server.
func main() {
r, err := resources.New(cfg.Client().RESTConfig())
if err != nil {
log.Fatal(err)
}
if err := decoder.DecodeEachFile(ctx, os.DirFS("testdata"), "*",
decoder.CreateHandler(r), // try to CREATE objects after decoding
decoder.MutateNamespace(namespace), // inject a namespace into decoded objects, before CREATE
); err != nil {
log.Fatal(err)
}
}
See YMAL/JSON decoder example here.
Parallel feature tests
New with this release is the ability to test multiple features in parallel. When a test environment receives multiple features, the test features can be executed in parallel either by using a CLI argument flag:
go test -v . -args --parallel
Or, the parallel test execution can be triggered programmatically with Environment.TestInParallel
method:
func TestPodBringUp(t *testing.T) {
featureOne := features.New("Feature One").
Assess("Create Nginx Deployment 1", func(ctx context.Context, t *testing.T, config *envconf.Config) context.Context {
deployment := newDeployment(namespace, "deployment-1", 2)
if err := config.Client().Resources().Create(ctx, deployment); err != nil
t.Error("failed to create test pod for deployment-1")
}
return ctx
}).Feature()
featureTwo := features.New("Feature Two").
Assess("Create Nginx Deployment 2", func(ctx context.Context, t *testing.T, config *envconf.Config) context.Context {
deployment := newDeployment(namespace, "deployment-2", 2)
if err := config.Client().Resources().Create(ctx, deployment); err != nil {
t.Error("failed to create test pod for deployment-2")
}
return ctx
}).Feature()
testEnv.TestInParallel(t, featureOne, featureTwo)
}
See parallel feature test example.
Third-party tool support (Helm)
This release introduces the notion of third-party tool support, found in the third_party
directory. The first tool supported is Helm. The release introduces the ability to integrate Helm-managed deployments programmatically into the e2e tests as shown below.
func TestHelmChartRepoWorkflow(t *testing.T) {
feature := features.New("Repo based helm chart workflow").
Setup(func(ctx context.Context, t *testing.T, config *envconf.Config) context.Context {
manager := helm.New(config.KubeconfigFile())
if err := manager.RunRepo(helm.WithArgs("add", "nginx-stable", "https://helm.nginx.com/stable")); err != nil {
t.Fatal("failed to add nginx helm chart repo")
}
if err := manager.RunRepo(helm.WithArgs("update")); err != nil {
t.Fatal("failed to upgrade helm repo")
}
if err := manager.RunInstall(helm.WithName("nginx"), helm.WithNamespace(namespace), helm.WithReleaseName("nginx-stable/nginx-ingress")); err != nil {
t.Fatal("failed to install nginx Helm chart")
}
return ctx
}).Feature()
...
}
See Helm support example here.
Test hooks have access *testing.T
In this release, test environment hooks Environment.BeforeEachTest
/Environment.AfterEachTest
and Environment.BeforeEachFeature
/Environment.AfterEachFeature
will now receive *testing.T
. This is useful for test features that are interested in receiving pass/fail status for instance.
func TestMain(m *testing.M) {
testenv = env.New()
testenv.Setup(
envfuncs.CreateKindCluster(kindClusterName),
)
testenv.BeforeEachFeature(func(ctx context.Context, _ *envconf.Config, t *testing.T, info features.Feature) (context.Context, error) {
return envfuncs.CreateNamespace("ns-name")
})
testenv.AfterEachFeature(func(ctx context.Context, _ *envconf.Config, _ *testing.T, info features.Feature) (context.Context, error) {
if t.Failed() {
return envfuncs.DeleteNamespace("ns-name")
}
return ctx, nil
})
testenv.Finish(
envfuncs.DestroyKindCluster(kindClusterName),
)
os.Exit(testenv.Run(m))
}
Other updates
- Support for controller-runtime version 0.11.0
- Update to use golangci-lint v1.44.0
- Enhancement to KinD support when tearing down clusters
Changelog
c1aec2e Update controller-runtime to 0.11.0 and their dependencies
b7a8a56 update golangci-lint to v1.44.0
f431b0b update repo infra to release v0.2.5
72e1963 Add *testing.T to before/after feature hooks
0c8ca84 GIT-83: enable helm support for test workflow
301dd09 GIT-49: enable paralle run of test features
0970afe add yaml and json helpers
bd4c3cd match on exact cluster names