TDD Zarf Components
tldr; Using the
wait
action to create simple end-to-end tests for Zarf components.
Overview
A little know and under-documented feature of Zarf components is the ability to wait on arbitrary Kubernetes resources to be ready during deploy actions. This is a very powerful feature as it allows for creating simple end-to-end tests that live in the same declarative land as the component it is testing.
under the hood this is a wrapper around the
kubectl wait
command, which can always be manually accessed via./zarf tools kubectl wait ...
inside of actions
Testing Helm Charts
Let's take a look at creating a Zarf package that deploys the base Helm chart w/ a simple NGINX server as well as podinfo
via OCI.
$ mkdir zarf-tdd
$ cd zarf-tdd
$ helm create local
Creating local
$ mv local chart
Then we'll add a zarf.yaml
file to the root of the package:
# zarf.yaml
kind: ZarfPackageConfig
metadata:
name: zarf-tdd
description: A simple TDD package
version: 0.0.1
components:
- name: simple-helm
required: true
charts:
- name: local
version: 0.1.0
namespace: simple-helm
localPath: chart
- name: oci-demo
version: 6.3.3
namespace: podinfo
url: oci://ghcr.io/stefanprodan/charts/podinfo
images:
- nginx:1.16.0
- ghcr.io/stefanprodan/podinfo:6.3.3
actions:
onDeploy:
after:
- wait:
cluster:
kind: deployment
name: local
namespace: simple-helm
condition: available
- wait:
cluster:
kind: pod
# `name` can be either a resource name or a label selector
name: app.kubernetes.io/name=oci-demo-podinfo
namespace: podinfo
condition: ready
Testing HTTP Endpoints
Sometimes you may want to test a network endpoint to ensure it is ready before continuing with the deployment (looking at you Registry1).
# using the same zarf.yaml as above
...
- name: image-from-registry1
required: true
images:
- registry1.dso.mil/ironbank/big-bang/base:2.0.0
actions:
onCreate:
before:
- wait:
network:
protocol: https
address: registry1.dso.mil
The world is your oyster, and the Zarf team cannot wait to see the innovative ways other Unicorns extend this feature. For more examples, I have mirrored the Zarf CLI docs below.
CLI Help
$ ./zarf tools wait-for --help
By default Zarf will wait for all Kubernetes resources to be ready before completion of a component during a deployment.
This command can be used to wait for a Kubernetes resources to exist and be ready that may be created by a Gitops tool or a Kubernetes operator.
You can also wait for aribtrary network endpoints using REST or TCP checks.
Usage:
zarf tools wait-for {KIND|PROTOCOL} {NAME|SELECTOR|URI} {CONDITION|HTTP_CODE} [flags]
Aliases:
wait-for, w, wait
Examples:
Wait for Kubernetes resources:
zarf tools wait-for pod my-pod-name ready -n default wait for pod my-pod-name in namespace default to be ready
zarf tools wait-for p cool-pod-name ready -n cool wait for pod (using p alias) cool-pod-name in namespace cool to be ready
zarf tools wait-for deployment podinfo available -n podinfo wait for deployment podinfo in namespace podinfo to be available
zarf tools wait-for pod app=podinfo ready -n podinfo wait for pod with label app=podinfo in namespace podinfo to be ready
zarf tools wait-for svc zarf-docker-registry exists -n zarf wait for service zarf-docker-registry in namespace zarf to exist
zarf tools wait-for svc zarf-docker-registry -n zarf same as above, except exists is the default condition
zarf tools wati-for crd addons.k3s.cattle.io wait for crd addons.k3s.cattle.io to exist
Wait for network endpoints:
zarf tools wait-for http localhost:8080 200 wait for a 200 response from http://localhost:8080
zarf tools wait-for tcp localhost:8080 wait for a connection to be established on localhost:8080
zarf tools wait-for https 1.1.1.1 200 wait for a 200 response from https://1.1.1.1
zarf tools wait-for http google.com wait for any 2xx response from http://google.com
zarf tools wait-for http google.com success wait for any 2xx response from http://google.com
Flags:
-h, --help help for wait-for
-n, --namespace string Specify the namespace of the resources to wait for.
--timeout string Specify the timeout duration for the wait command. (default "5m")