Skip to content

Commit

Permalink
tests(e2e): add helm install e2e test
Browse files Browse the repository at this point in the history
  • Loading branch information
Michelle Noorali committed Oct 22, 2020
1 parent 58dc0a0 commit 997a479
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 28 deletions.
14 changes: 14 additions & 0 deletions tests/e2e/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# E2E OSM Testing

## Table of Contents

- [Overview](#overview)
- [Files and structure](#files-and-structure)
- [Running the tests](#running-the-tests)
Expand All @@ -8,24 +10,30 @@
- [Flags](#flags)

## Overview

End-to-end tests verify the behavior of the entire system. For OSM, e2e tests will install a control plane, install test workloads and SMI policies, and check that the workload is behaving as expected.

## Files and structure

OSM's e2e tests are located in `tests/e2e`.
The tests are written using Ginkgo and Gomega so they may also be directly invoked using `go test`. Be sure to build the `osm-controller` and `init` container images and `osm` CLI before directly invoking the tests ([see instructions below](#running-the-tests)).

OSM's framework has an init mechanism which will automatically initialize and parse flags and variables from both `env` and `go test flags` if any are passed to the test. The hooks for initialization and cleanup are set at Ginkgo's `BeforeEach` at the top level of test execution (between Ginkgo `Describes`); we henceforth recommend keeping every test in its own `Describe` section, as well as on a separate file for clarity. You can refer to [suite_test](tests/e2e/suite_test.go) for more details about the init process.

## Running the tests

Running the tests will require a running Kubernetes cluster. If you do not have a Kubernetes cluster to run the tests onto, you can choose to run them using `Kind`, which will make the test framework initialize a cluster on a local accessible docker client.

Running the tests will also require the [Helm](https://helm.sh/) CLI to be installed on your machine.

The tests can be run using the `test-e2e` Makefile target at repository root level (which defaults to use Kind), or alternatively `go test` targetting the test folder, which gives more flexibility but depends on related `env` flags given or parsed by the test.

Please refer to the [Kind cluster](#kind-cluster) or [Other K8s deployment](#other-k8s-eployment) and follow the instructions to setup potential env flags required by either option.

In addition to the flags provided by `go test` and Ginkgo, there are several custom command line flags that may be used for e2e tests to configure global parameters like container image locations and cleanup behavior. You can see the list of flags under the [flag section](#flags) below.

### Kind cluster

The following `make` target will create local containers for the OSM components, tagging them with `CTR_TAG`, and will launch the tests using Kind cluster. A Kind cluster is created at test start, and requires a docker interface to be available on the host running the test.
When using Kind, we load the images onto the Kind nodes directly (as opposed to providing a registry to pull the images from).
```
Expand All @@ -34,6 +42,7 @@ CTR_TAG=not-latest make test-e2e
Note: If you use `latest` tag, K8s will try to pull the image by default. If the images are not pushed to a registry accessible by the kind cluster, image pull errors will occur. Or, if an image with the same name is available, like `openservicemesh/init:latest`, then that publicly available image will be pulled and started instead, which may not be as up-to-date as the local image already loaded onto the cluster.

### Other K8s deployment

Have your Kubeconfig file point to your testing cluster of choice.
The following code uses `latest` tag by default. Non-Kind deployments do not push the images on the nodes, so make sure to set the registry accordingly.
```
Expand All @@ -44,11 +53,14 @@ go test ./tests/e2e -test.v -ginkgo.v -ginkgo.progress
```

### Flags

#### (TODO) Kubeconf selection

Currently, test init will load a `Kubeconf` based on Defalut Kubeconf Loading rules.
If Kind is used, the kubeconf is temporarily replaced and Kind's kubeconf is used instead.

#### Container registry

A container registry where to load the images from (OSM, init container, etc.). Credentials are optional if the container registry allows pulling the images publicly:
```
-ctrRegistry string
Expand All @@ -67,6 +79,7 @@ export CTR_REGISTRY_PASSWORD=<password> # opt
```

#### OSM Tag

The following flag will refer to the version of the OSM platform containers (OSM and init) for test to use:
```
-osmImageTag string
Expand All @@ -80,6 +93,7 @@ make docker-push-init docker-push-osm-controller. # Use docker-build-* target
```

#### Use Kind for testing

Testing implements support for Kind. If `kindCluster` is enabled, a new Kind cluster will be provisioned and it will be automatically used for the test.
```
-kindCluster
Expand Down
82 changes: 54 additions & 28 deletions tests/e2e/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,38 +190,31 @@ func (td *OsmTestData) GetOSMInstallOpts() InstallOSMOpts {
}
}

// HelmInstallOSM installs an osm control plane using the osm chart which lives in charts/osm
func (td *OsmTestData) HelmInstallOSM() error {
if td.kindCluster {
if err := td.loadOSMImagesIntoKind(); err != nil {
return err
}
}

values := fmt.Sprintf("OpenServiceMesh.image.registry=%s,OpenServiceMesh.image.tag=%s", td.ctrRegistryServer, td.osmImageTag)
args := []string{"install", "osm", "../../charts/osm", "--set", values, "--namespace", td.osmNamespace, "--create-namespace", "--wait"}
stdout, stderr, err := td.RunLocal("helm", args)
if err != nil {
td.T.Logf("stdout:\n%s", stdout)
return errors.Errorf("failed to run helm install with osm chart: %s", stderr)
}

return nil
}

// InstallOSM installs OSM. Right now relies on externally calling the binary and a subset of possible opts
// TODO: refactor install to be able to call it directly here vs. exec-ing CLI.
func (td *OsmTestData) InstallOSM(instOpts InstallOSMOpts) error {
if td.kindCluster {
td.T.Log("Getting image data")
imageNames := []string{
"osm-controller",
"init",
}
docker, err := client.NewClientWithOpts(client.WithAPIVersionNegotiation())
if err != nil {
return errors.Wrap(err, "failed to create docker client")
}
var imageIDs []string
for _, name := range imageNames {
imageName := fmt.Sprintf("%s/%s:%s", td.ctrRegistryServer, name, td.osmImageTag)
imageIDs = append(imageIDs, imageName)
}
imageData, err := docker.ImageSave(context.TODO(), imageIDs)
if err != nil {
return errors.Wrap(err, "failed to get image data")
}
defer imageData.Close()
nodes, err := td.clusterProvider.ListNodes(td.clusterName)
if err != nil {
return errors.Wrap(err, "failed to list kind nodes")
}
for _, n := range nodes {
td.T.Log("Loading images onto node", n)
if err := nodeutils.LoadImageArchive(n, imageData); err != nil {
return errors.Wrap(err, "failed to load images")
}
if err := td.loadOSMImagesIntoKind(); err != nil {
return err
}
}

Expand Down Expand Up @@ -284,6 +277,39 @@ func (td *OsmTestData) InstallOSM(instOpts InstallOSMOpts) error {
return nil
}

func (td *OsmTestData) loadOSMImagesIntoKind() error {
td.T.Log("Getting image data")
imageNames := []string{
"osm-controller",
"init",
}
docker, err := client.NewClientWithOpts(client.WithAPIVersionNegotiation())
if err != nil {
return errors.Wrap(err, "failed to create docker client")
}
var imageIDs []string
for _, name := range imageNames {
imageName := fmt.Sprintf("%s/%s:%s", td.ctrRegistryServer, name, td.osmImageTag)
imageIDs = append(imageIDs, imageName)
}
imageData, err := docker.ImageSave(context.TODO(), imageIDs)
if err != nil {
return errors.Wrap(err, "failed to get image data")
}
defer imageData.Close()
nodes, err := td.clusterProvider.ListNodes(td.clusterName)
if err != nil {
return errors.Wrap(err, "failed to list kind nodes")
}
for _, n := range nodes {
td.T.Log("Loading images onto node", n)
if err := nodeutils.LoadImageArchive(n, imageData); err != nil {
return errors.Wrap(err, "failed to load images")
}
}
return nil
}

func (td *OsmTestData) installVault(instOpts InstallOSMOpts) error {
td.T.Log("Installing Vault")
replicas := int32(1)
Expand Down
18 changes: 18 additions & 0 deletions tests/e2e/e2e_helm_install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package e2e

import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

var _ = Describe("Test osm control plane installation with Helm", func() {
Context("Using default values", func() {

It("installs osm control plane sucessfully", func() {

// Install OSM with Helm
Expect(td.HelmInstallOSM()).To(Succeed())

})
})
})

0 comments on commit 997a479

Please sign in to comment.