Skip to content

Commit

Permalink
Add back testing and test-infra directories
Browse files Browse the repository at this point in the history
  • Loading branch information
jrhouston committed Jan 14, 2025
1 parent 94874e6 commit a334109
Show file tree
Hide file tree
Showing 7 changed files with 356 additions and 0 deletions.
25 changes: 25 additions & 0 deletions helm/test-infra/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Testing Infrastructure

Testing the Helm provider should not require more than a working Kubernetes cluster,
so any testing environment from the Kubernetes provider should work.

To keep this provider self-contained we provide code for one of these environments, GKE.
Please follow instructions in the `gke` directory to spin up GKE.

## Helm installation

It is necessary to install Helm after spinning up the GKE cluster.
We provide a shell script which leverages Docker, for convenience.

Here we assume that you chose to store kubeconfig in `./gke/kubedir`,
feel free to change this location accordingly, if necessary.

```sh
KUBE_DIR=./gke/kubedir HELM_VERSION=2.13.0 HELM_HOME=./helm-home HYPERKUBE_VERSION=v1.11.8 ./install-helm-via-docker.sh
```

Then you're ready to run acceptance tests.

```sh
HELM_HOME=./helm-home KUBECONFIG=./gke/kubedir/config make testacc
```
38 changes: 38 additions & 0 deletions helm/test-infra/gke/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# GKE (Google Container Engine)

You will need the following environment variables to be set:

- `GOOGLE_CREDENTIALS`
- `GOOGLE_PROJECT`
- `GOOGLE_REGION`

See [Google Cloud Provider docs](https://www.terraform.io/docs/providers/google/index.html#configuration-reference) for more details about these variables.

```
terraform init
terraform apply -var=kubernetes_version=1.7.12-gke.1
```

## Versions

See https://cloud.google.com/kubernetes-engine/versioning-and-upgrades#versions_available_for_new_cluster_masters for currently available versions.

## Exporting K8S variables
To access the cluster you need to export the `KUBECONFIG` variable pointing to the `kubeconfig` file for the current cluster.
```
export KUBECONFIG="$(terraform output kubeconfig_path)"
export GOOGLE_ZONE=$(terraform output google_zone)
```

Now you can access the cluster via `kubectl` and you can run acceptance tests against it.

To run acceptance tests, your the following command in the root of the repository.
```
TESTARGS="-run '^TestAcc'" make testacc
```

To run only a specific set of tests, you can replace `^TestAcc` with any regular expression to filter tests by name.
For example, to run tests for Pod resources, you can do:
```
TESTARGS="-run '^TestAccKubernetesPod_'" make testacc
```
26 changes: 26 additions & 0 deletions helm/test-infra/gke/kubeconfig-template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0

apiVersion: v1
kind: Config
preferences:
colors: true
current-context: tf-helm-gcp-test
contexts:
- context:
cluster: ${cluster_name}
namespace: default
user: ${user_name}
name: tf-helm-gcp-test
clusters:
- cluster:
server: https://${endpoint}
certificate-authority-data: ${cluster_ca}
name: ${cluster_name}
users:
- name: ${user_name}
user:
password: ${user_password}
username: ${user_name}
client-certificate-data: ${client_cert}
client-key-data: ${client_cert_key}
89 changes: 89 additions & 0 deletions helm/test-infra/gke/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0

provider "google" {
version = "~> 2.0"
// Provider settings to be provided via ENV variables
}

data "google_compute_zones" "available" {}

resource "random_id" "cluster_name" {
byte_length = 10
}

resource "random_id" "username" {
byte_length = 14
}

resource "random_id" "password" {
byte_length = 16
}

# See https://cloud.google.com/container-engine/supported-versions
variable "kubernetes_version" {
default = ""
}
variable "workers_count" {
default = "3"
}
variable "kube_config_dir" {
default = ""
}

data "google_container_engine_versions" "supported" {
zone = data.google_compute_zones.available.names[0]
version_prefix = var.kubernetes_version
}

resource "google_container_cluster" "primary" {
name = "tf-acc-test-${random_id.cluster_name.hex}"
zone = data.google_compute_zones.available.names[0]
initial_node_count = var.workers_count
min_master_version = data.google_container_engine_versions.supported.latest_master_version

additional_zones = [
"${data.google_compute_zones.available.names[1]}",
]

master_auth {
username = random_id.username.hex
password = random_id.password.hex
}

node_config {
machine_type = "n1-standard-4"

oauth_scopes = [
"https://www.googleapis.com/auth/compute",
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring",
]
}
}

resource "local_file" "kubeconfig" {
content = templatefile("${path.module}/kubeconfig-template.yaml", {
cluster_name = "${google_container_cluster.primary.name}"
user_name = "${google_container_cluster.primary.master_auth.0.username}"
user_password = "${google_container_cluster.primary.master_auth.0.password}"
endpoint = "${google_container_cluster.primary.endpoint}"
cluster_ca = "${google_container_cluster.primary.master_auth.0.cluster_ca_certificate}"
client_cert = "${google_container_cluster.primary.master_auth.0.client_certificate}"
client_cert_key = "${google_container_cluster.primary.master_auth.0.client_key}"
})
filename = "${var.kube_config_dir}/config"
}

output "google_zone" {
value = data.google_compute_zones.available.names[0]
}

output "node_version" {
value = google_container_cluster.primary.node_version
}

output "kubeconfig_path" {
value = local_file.kubeconfig.filename
}
65 changes: 65 additions & 0 deletions helm/test-infra/install-helm-via-docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/bash
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0

set -e

which docker > /dev/null
if [ "$?" != "0" ]; then
echo "Error: Docker not found"
exit 1
fi
if [ "$KUBE_DIR" == "" ]; then
echo "Error: Please specify KUBE_DIR"
exit 1
fi
if [ "$HELM_VERSION" == "" ]; then
echo "Error: Please specify HELM_VERSION"
exit 1
fi
if [ "$HELM_HOME" == "" ]; then
HELM_HOME=~/.helm
fi
if [ "$HYPERKUBE_VERSION" == "" ]; then
URL="https://console.cloud.google.com/gcr/images/google-containers/GLOBAL/hyperkube"
echo "Error: Please specify HYPERKUBE_VERSION"
echo " - Available versions: $URL"
exit 1
fi

echo "HELM_HOME=${HELM_HOME}"

docker version

DOCKER_KUBECTL="docker run -i --rm \
-v ${KUBE_DIR}:/root/.kube \
gcr.io/google-containers/hyperkube:${HYPERKUBE_VERSION} \
kubectl"

$DOCKER_KUBECTL version

echo "Creating Tiller service account ..."
$DOCKER_KUBECTL --namespace kube-system create sa tiller

echo "Creating ClusterRoleBinding for Tiller ..."
$DOCKER_KUBECTL create clusterrolebinding tiller \
--clusterrole cluster-admin \
--serviceaccount=kube-system:tiller

mkdir -p $HELM_HOME
ls -la $HELM_HOME
DOCKER_HELM="docker run -i --rm \
-v $(pwd):/apps \
-v ${HELM_HOME}:/.helm \
-v ${KUBE_DIR}:/.kube \
--user $(id -u):$(id -g) \
alpine/helm:${HELM_VERSION}"

echo "Helm client version:"
$DOCKER_HELM version -c

echo "Initializing Helm ..."
$DOCKER_HELM init --service-account tiller

echo "Verifying Helm ..."
$DOCKER_KUBECTL get deploy,svc tiller-deploy -n kube-system
29 changes: 29 additions & 0 deletions helm/testing/config-da-basic/test.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: MPL-2.0

terraform {
required_providers {
kind = {
source = "tehcyx/kind"
}
}
}

resource "kind_cluster" "demo" {
name = "tfacc"
}

provider "helm" {
kubernetes {
host = kind_cluster.demo.endpoint
cluster_ca_certificate = kind_cluster.demo.cluster_ca_certificate
client_certificate = kind_cluster.demo.client_certificate
client_key = kind_cluster.demo.client_key
}
}

resource "helm_release" "test-release" {
name = "test-hello"
repository = "https://cloudecho.github.io/charts/"
chart = "hello"
}
84 changes: 84 additions & 0 deletions helm/testing/deferred_actions_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package testing

import (
"testing"

"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/plancheck"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
"github.com/hashicorp/terraform-plugin-testing/tfversion"
"github.com/hashicorp/terraform-provider-helm/helm"
)

var providerFactory = map[string]func() (tfprotov6.ProviderServer, error){
"helm": providerserver.NewProtocol6WithError(helm.New()()),
}

func TestAccDeferredActions_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
TerraformVersionChecks: []tfversion.TerraformVersionCheck{
tfversion.SkipBelow(tfversion.Version1_9_0),
},
AdditionalCLIOptions: &resource.AdditionalCLIOptions{
Plan: resource.PlanOptions{AllowDeferral: true},
Apply: resource.ApplyOptions{AllowDeferral: true},
},
Steps: []resource.TestStep{
{
ProtoV6ProviderFactories: providerFactory,
ConfigDirectory: func(tscr config.TestStepConfigRequest) string {
return "config-da-basic"
},
ExpectNonEmptyPlan: true,
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction("kind_cluster.demo", plancheck.ResourceActionCreate),
plancheck.ExpectDeferredChange("helm_release.test-release", plancheck.DeferredReasonProviderConfigUnknown),
},
PostApplyPostRefresh: []plancheck.PlanCheck{
plancheck.ExpectResourceAction("helm_release.test-release", plancheck.ResourceActionCreate),
},
},
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue("kind_cluster.demo", tfjsonpath.New("endpoint"), knownvalue.NotNull()),
statecheck.ExpectKnownValue("kind_cluster.demo", tfjsonpath.New("cluster_ca_certificate"), knownvalue.NotNull()),
statecheck.ExpectKnownValue("kind_cluster.demo", tfjsonpath.New("client_certificate"), knownvalue.NotNull()),
statecheck.ExpectKnownValue("kind_cluster.demo", tfjsonpath.New("client_key"), knownvalue.NotNull()),
},
},
{
ProtoV6ProviderFactories: providerFactory,
ConfigDirectory: func(tscr config.TestStepConfigRequest) string {
return "config-da-basic"
},
ExpectNonEmptyPlan: false,
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction("helm_release.test-release", plancheck.ResourceActionCreate),
},
PostApplyPostRefresh: []plancheck.PlanCheck{
plancheck.ExpectEmptyPlan(),
},
},
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue("kind_cluster.demo", tfjsonpath.New("endpoint"), knownvalue.NotNull()),
statecheck.ExpectKnownValue("kind_cluster.demo", tfjsonpath.New("cluster_ca_certificate"), knownvalue.NotNull()),
statecheck.ExpectKnownValue("kind_cluster.demo", tfjsonpath.New("client_certificate"), knownvalue.NotNull()),
statecheck.ExpectKnownValue("kind_cluster.demo", tfjsonpath.New("client_key"), knownvalue.NotNull()),
statecheck.ExpectKnownValue("helm_release.test-release", tfjsonpath.New("name"), knownvalue.StringExact("test-hello")),
statecheck.ExpectKnownValue("helm_release.test-release", tfjsonpath.New("chart"), knownvalue.StringExact("hello")),
statecheck.ExpectKnownValue("helm_release.test-release", tfjsonpath.New("repository"), knownvalue.StringExact("https://cloudecho.github.io/charts/")),
statecheck.ExpectKnownValue("helm_release.test-release", tfjsonpath.New("status"), knownvalue.StringExact("deployed")),
},
},
},
})
}

0 comments on commit a334109

Please sign in to comment.