Skip to content

Commit

Permalink
E2E test optimization for multi-distro support (#319)
Browse files Browse the repository at this point in the history
* add kind testing
* add k3d testing
* add k3s testing
* remove chat based e2e test
* cleanup of e2e test code
* adr for e2e testing

Co-authored-by: Jeff McCoy <code@jeffm.us>
Co-authored-by: Minimind <882485+jeff-mccoy@users.noreply.github.com>
  • Loading branch information
3 people authored Mar 5, 2022
1 parent 8f394b2 commit ef8e280
Show file tree
Hide file tree
Showing 17 changed files with 1,007 additions and 1,193 deletions.
15 changes: 0 additions & 15 deletions .github/workflows/slash-command-dispatch.yml

This file was deleted.

651 changes: 0 additions & 651 deletions .github/workflows/test-command.yml

This file was deleted.

20 changes: 20 additions & 0 deletions .github/workflows/test-k3d.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: e2e-k3d
on:
- pull_request

jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Install GoLang
uses: actions/setup-go@v2
with:
go-version: 1.16.x
- name: Checkout Repo
uses: actions/checkout@v2
- name: Build CLI
run: make build-cli-linux
- name: Make Packages
run: make init-package package-example-game package-example-data-injection package-example-gitops-data
- name: Run Tests
run: TESTDISTRO=k3d make test-e2e
21 changes: 21 additions & 0 deletions .github/workflows/test-k3s.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: e2e-k3s
on:
- pull_request

jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Install GoLang
uses: actions/setup-go@v2
with:
go-version: 1.16.x
- name: Checkout Repo
uses: actions/checkout@v2
- name: Build CLI
run: make build-cli-linux
- name: Make Packages
run: make init-package package-example-game package-example-data-injection package-example-gitops-data
- name: Run Tests
# NOTE: "PATH=$PATH" preserves the default user $PATH. This is needed to maintain the version of go installed in a previous step
run: sudo env "PATH=$PATH" TESTDISTRO=k3s make test-e2e
20 changes: 20 additions & 0 deletions .github/workflows/test-kind.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: e2e-kind
on:
- pull_request

jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Install GoLang
uses: actions/setup-go@v2
with:
go-version: 1.16.x
- name: Checkout Repo
uses: actions/checkout@v2
- name: Build CLI
run: make build-cli-linux
- name: Make Packages
run: make init-package package-example-game package-example-data-injection package-example-gitops-data
- name: Run Tests
run: TESTDISTRO=kind make test-e2e
45 changes: 22 additions & 23 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ build-cli-linux: ## Build the Linux CLI
build-cli-mac: ## Build the Mac CLI
cd cli && $(MAKE) build-mac

build-cli: clean build-cli-linux build-cli-mac ## Build the CLI
build-cli: build-cli-linux build-cli-mac ## Build the CLI

init-package: ## Create the zarf init package, macos "brew install coreutils" first
$(ZARF_BIN) package create --confirm
Expand Down Expand Up @@ -78,25 +78,24 @@ package-example-gitops-data:
package-example-tiny-kafka:
cd examples/tiny-kafka && ../../$(ZARF_BIN) package create --confirm && mv zarf-package-* ../../build/

.PHONY: test-cloud-e2e-example-game
test-cloud-e2e-example-game: ## Runs the Doom game as an E2E test in the cloud. Requires access to an AWS account. Costs money. Make sure you ran the `build-cli`, `init-package`, and `package-example-game` targets first
cd test/e2e && go test ./... -run TestE2eExampleGame -v -timeout 1200s

.PHONY: test-cloud-e2e-gitea-and-grafana
test-cloud-e2e-gitea-and-grafana: ## E2E test of Gitea & Grafana. Requires access to an AWS account. Costs money. Make sure you ran the `build-cli` and `init-package` targets first
cd test/e2e && go test ./... -run TestGiteaAndGrafana -v -timeout 1200s

.PHONY: test-cloud-e2e-gitops
test-cloud-e2e-gitops: package-example-gitops-data ## E2E test of Gitops example. Requires access to an AWS account. Costs money. Make sure you ran the `build-cli` and `init-package` targets first
cd test/e2e && go test ./... -run TestGitopsExample -v -timeout 1200s

.PHONY: test-cloud-e2e-data-injection
test-cloud-e2e-data-injection: package-example-data-injection ## E2E test of the Data Injection example. Requires access to an AWS account. Costs money. Make sure you ran the `build-cli` and `init-package` targets first
cd test/e2e && go test ./... -run TestDataInjection -v -timeout 1200s

.PHONY: test-cloud-e2e-general-cli
test-cloud-e2e-general-cli: package-example-tiny-kafka ## Runs tests of the CLI that don't need a cluster
cd test/e2e && go test ./... -run TestGeneralCli -v -timeout 1200s

.PHONY: test-e2e
test-e2e: package-example-game test-cloud-e2e-example-game ## DEPRECATED - to be replaced by individual e2e test targets
# TODO: This can be cleaned up a little more when `zarf init` is able to provide the path to the `zarf-init.tar.zst`
.PHONY: test-new-e2e
test-e2e: ## Run e2e tests on a KiND cluster. All dependencies are assumed to be built and in the ./build directory
@ #Check to make sure all the packages we need exist
@if [ ! -f $(ZARF_BIN) ]; then\
$(MAKE) build-cli;\
fi
@if [ ! -f ./build/zarf-init.tar.zst ]; then\
$(MAKE) init-package;\
fi
@if [ ! -f ./build/zarf-package-appliance-demo-multi-games.tar.zst ]; then\
$(MAKE) package-example-game;\
fi
@if [ ! -f ./build/zarf-package-data-injection-demo.tar ]; then\
$(MAKE) package-example-data-injection;\
fi
@if [ ! -f ./build/zarf-package-gitops-service-data.tar.zst ]; then\
$(MAKE) package-example-gitops-data;\
fi

cd test/e2e && cp ../../build/zarf-init.tar.zst . && go test ./... -v -timeout 2400s && rm zarf-init.tar.zst
36 changes: 36 additions & 0 deletions docs/adr/0002-moving-e2e-tests-away-from-terratest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 2. Moving E2E Tests Away From Terratest

Date: 2022-03-04

## Status

Accepted

## Context

In previous releases of Zarf, the creation of the initialization package at the core of many of our E2E tests required repository secrets to login to registry1. Since this is an open-source project, anyone could submit a change to one of our GitHub workflows that could steal our secrets. In order to protect our secrets from any bad-actors we used [peter-evans/slash-command-dispatch@v2](https://github.com/peter-evans/slash-command-dispatch) so that only a maintainer would have the ability to run the E2E tests when a PR is submitted for review.

In the current version of Zarf (v0.15) images from registry1 are no longer needed to create the zarf-init.tar.zst. This means, given our current span of E2E tests, we no longer need to use repository secrets when running tests. This gives us the ability to reassess the way we do our E2E testing.

When considering how to handle the tests, some of the important additions we were considering were:
1. Ability to test against different kubernetes distributions
2. Ability to test against different linux distributions
3. Ability to run (at least some of) the E2E tests locally without relying on an ec2 instance - for quicker feedback loops when developing new features

## Decision

The previous E2E test code was not extensible enough to be reused to test Zarf against different kubernetes distributions. The test suite was refactored so that we could write a setup and teardown function for each kubernetes distribution we wanted to verify against and the test suite was then responsible for cycling through the different distributions. This gives us the ability to test multiple kubernetes distributions against the same exact test cases.

The individual test cases were also rewritten to not rely on terratest running a bash command over ssh. Instead, the test uses the locally built Zarf binary and example packages to validate expected behavior. This approach works both on local dev machines (linux/mac) and on the Ubuntu GitHub Runner that gets triggered when a pull request is created. This also has the positive side effect of not needing to wait several minutes for an ec2 instance to spin up for testing.

Since we no longer need repository secrets to run the E2E tests, we removed the requirement for a maintainer to use a `/test all` chatops command to dispatch the tests. Instead, there is a new test workflow defined for each kubernetes distribution we are verifying against and the tests get run automatically whenever a PR is created or updated.

When looking back at the list of 'important additions' we were considering above. All three are addressed with this approach. Testing against different kubernetes distributions is as simple as defining how to create and destroy the cluster. All of the test cases are runnable locally and then because of that testing on a linux distribution is possible by just switching over to another machine and running the same `make test-e2e` there. This also gives us the ability to test against cloud distributions like EKS! All you need is a valid kubeconfig and running `go test ./...` in the `./test/e2e` directory will run all of the test cases against the EKS cluster.

## Consequences

While it was not something we were doing before, testing directly on the GitHub Runner instead of using Terratest to test on an ec2 instance means that when we get around to adding automated testing of Zarf against different linux distrobutions we will want to have more discussions on if we want to use self-hosted runners of different OS's or if we want to go back to Terratest to stand up ec2 instances with different AMIs.

In the future, we will likely want to write E2E tests that use images that require repository secrets to access. When that happens we will want to bring back some form of 'maintainer action' to initiate the test workflow. Going back to [peter-evans/slash-command-dispatch@v2](https://github.com/peter-evans/slash-command-dispatch) might be the right answer for that but there will need to be more discussion to make sure the team agrees that's the best solution first.

As the amount of E2E tests we have grows, the longer it will take to get results back on each PR. Duhh! Paralyzing the tests on a single host will be difficult (but not impossible) because it means more logic will be needed in the test suite to make sure the host has enough resources to handle multiple clusters being run in parallel. The simpler solution would be to break out each of our tests into a new GitHub Workflow. This will easily mitigate the issue of tests taking long to run but also give us a lot more yaml to maintain. Either solution is valid but more team discussions will be needed as we get closer to needing it.
36 changes: 6 additions & 30 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@ go 1.16
require (
github.com/AlecAivazis/survey/v2 v2.3.2
github.com/alecthomas/jsonschema v0.0.0-20211228220459-151e3c21f49d
github.com/aws/aws-sdk-go v1.40.56 // indirect
github.com/derailed/k9s v0.25.18
github.com/distribution/distribution/v3 v3.0.0-20210804104954-38ab4c606ee3
github.com/docker/cli v20.10.12+incompatible
github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1 // indirect
github.com/fatih/color v1.13.0
github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 // indirect
github.com/go-git/go-git/v5 v5.4.2
github.com/go-logr/logr v1.2.2
github.com/goccy/go-yaml v1.9.5
github.com/google/go-containerregistry v0.8.0
github.com/gruntwork-io/terratest v0.38.2
github.com/mattn/go-colorable v0.1.12
github.com/mholt/archiver/v3 v3.5.1
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/otiai10/copy v1.7.0
github.com/pterm/pterm v0.12.33
github.com/rancher/k3d/v5 v5.2.1
github.com/spf13/cobra v1.3.0
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e
Expand All @@ -26,36 +30,8 @@ require (
k8s.io/apimachinery v0.22.5
k8s.io/client-go v0.22.5
k8s.io/klog/v2 v2.40.1
sigs.k8s.io/kind v0.11.1
sigs.k8s.io/kustomize/api v0.8.11
sigs.k8s.io/kustomize/kyaml v0.11.0
sigs.k8s.io/yaml v1.3.0
)

replace (
// https://github.com/kubernetes/kubernetes/issues/79384#issuecomment-505627280
k8s.io/api => k8s.io/api v0.22.5
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.22.5 // indirect
k8s.io/apimachinery => k8s.io/apimachinery v0.22.5 // indirect
k8s.io/apiserver => k8s.io/apiserver v0.22.5
k8s.io/cli-runtime => k8s.io/cli-runtime v0.22.5
k8s.io/client-go => k8s.io/client-go v0.22.5
k8s.io/cloud-provider => k8s.io/cloud-provider v0.22.5
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.22.5
k8s.io/code-generator => k8s.io/code-generator v0.22.5
k8s.io/component-base => k8s.io/component-base v0.22.5
k8s.io/component-helpers => k8s.io/component-helpers v0.22.5
k8s.io/controller-manager => k8s.io/controller-manager v0.22.5
k8s.io/cri-api => k8s.io/cri-api v0.22.5
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.22.5
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.22.5
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.22.5
k8s.io/kube-proxy => k8s.io/kube-proxy v0.22.5
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.22.5
k8s.io/kubectl => k8s.io/kubectl v0.22.5
k8s.io/kubelet => k8s.io/kubelet v0.22.5
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.22.5
k8s.io/metrics => k8s.io/metrics v0.22.5
k8s.io/mount-utils => k8s.io/mount-utils v0.22.5
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.22.5
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.22.5
)
Loading

0 comments on commit ef8e280

Please sign in to comment.