Skip to content
This repository was archived by the owner on Dec 16, 2020. It is now read-only.

Commit 58ca6bd

Browse files
committed
Add test for checking create_resources does not actually create any resources
1 parent 1bd61be commit 58ca6bd

File tree

10 files changed

+98
-57
lines changed

10 files changed

+98
-57
lines changed

examples/k8s-namespace-with-service-account/main.tf

+10-7
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ module "namespace" {
2828
# source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-namespace?ref=v0.0.1"
2929
source = "../../modules/k8s-namespace"
3030

31-
name = var.name
31+
create_resources = var.create_resources
32+
name = var.name
3233
}
3334

3435
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -41,9 +42,10 @@ module "service_account_access_all" {
4142
# source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-service-account?ref=v0.0.1"
4243
source = "../../modules/k8s-service-account"
4344

44-
name = "${var.name}-admin"
45-
namespace = module.namespace.name
46-
num_rbac_roles = 1
45+
create_resources = var.create_resources
46+
name = "${var.name}-admin"
47+
namespace = module.namespace.name
48+
num_rbac_roles = 1
4749

4850
rbac_roles = [
4951
{
@@ -64,9 +66,10 @@ module "service_account_access_read_only" {
6466
# source = "git::https://github.com/gruntwork-io/terraform-kubernetes-helm.git//modules/k8s-service-account?ref=v0.0.1"
6567
source = "../../modules/k8s-service-account"
6668

67-
name = "${var.name}-read-only"
68-
namespace = module.namespace.name
69-
num_rbac_roles = 1
69+
create_resources = var.create_resources
70+
name = "${var.name}-read-only"
71+
namespace = module.namespace.name
72+
num_rbac_roles = 1
7073

7174
rbac_roles = [
7275
{

examples/k8s-namespace-with-service-account/variables.tf

+11
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,14 @@ variable "kubectl_config_path" {
1919
type = string
2020
default = "~/.kube/config"
2121
}
22+
23+
# ---------------------------------------------------------------------------------------------------------------------
24+
# TEST PARAMETERS
25+
# These variables are only used for testing purposes and should not be touched in normal operations.
26+
# ---------------------------------------------------------------------------------------------------------------------
27+
28+
variable "create_resources" {
29+
description = "Set to false to have this module create no resources."
30+
type = bool
31+
default = true
32+
}

modules/k8s-service-account/main.tf

+4-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ resource "null_resource" "dependency_getter" {
3131
# ---------------------------------------------------------------------------------------------------------------------
3232

3333
resource "kubernetes_service_account" "service_account" {
34+
count = var.create_resources ? 1 : 0
35+
3436
metadata {
3537
name = var.name
3638
namespace = var.namespace
@@ -62,7 +64,7 @@ resource "kubernetes_service_account" "service_account" {
6264
# ---------------------------------------------------------------------------------------------------------------------
6365

6466
resource "kubernetes_role_binding" "service_account_role_binding" {
65-
count = var.num_rbac_roles
67+
count = var.create_resources ? var.num_rbac_roles : 0
6668

6769
metadata {
6870
name = "${var.name}-${var.rbac_roles[count.index]["name"]}-role-binding"
@@ -80,7 +82,7 @@ resource "kubernetes_role_binding" "service_account_role_binding" {
8082
subject {
8183
api_group = ""
8284
kind = "ServiceAccount"
83-
name = kubernetes_service_account.service_account.metadata[0].name
85+
name = kubernetes_service_account.service_account[0].metadata[0].name
8486
namespace = var.namespace
8587
}
8688

modules/k8s-service-account/outputs.tf

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
output "name" {
22
description = "The name of the created service account"
3-
value = kubernetes_service_account.service_account.metadata[0].name
3+
value = var.create_resources ? kubernetes_service_account.service_account[0].metadata[0].name : ""
44

55
depends_on = [kubernetes_role_binding.service_account_role_binding]
66
}
77

88
output "token_secret_name" {
99
description = "The name of the secret that holds the default ServiceAccount token that can be used to authenticate to the Kubernetes API."
10-
value = kubernetes_service_account.service_account.default_secret_name
10+
value = var.create_resources ? kubernetes_service_account.service_account[0].default_secret_name : ""
1111

1212
depends_on = [kubernetes_role_binding.service_account_role_binding]
1313
}

modules/k8s-service-account/variables.tf

+6
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ variable "secrets_for_pods" {
6868
default = []
6969
}
7070

71+
variable "create_resources" {
72+
description = "Set to false to have this module create no resources. This weird parameter exists solely because Terraform does not support conditional modules. Therefore, this is a hack to allow you to conditionally decide if the Namespace should be created or not."
73+
type = bool
74+
default = true
75+
}
76+
7177
# ---------------------------------------------------------------------------------------------------------------------
7278
# MODULE DEPENDENCIES
7379
# Workaround Terraform limitation where there is no module depends_on.

test/Gopkg.lock

+5-30
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/Gopkg.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
[[constraint]]
2929
name = "github.com/gruntwork-io/terratest"
30-
version = "0.16.0"
30+
version = "0.20.1"
3131

3232
[prune]
3333
go-tests = true

test/k8s_namespace_with_service_account_test.go

+52-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"github.com/gruntwork-io/terratest/modules/logger"
1414
"github.com/gruntwork-io/terratest/modules/random"
1515
"github.com/gruntwork-io/terratest/modules/terraform"
16-
"github.com/gruntwork-io/terratest/modules/test-structure"
16+
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
1717
"github.com/stretchr/testify/assert"
1818
"github.com/stretchr/testify/require"
1919
authv1 "k8s.io/api/authorization/v1"
@@ -25,6 +25,53 @@ type TemplateArgs struct {
2525
ServiceAccountName string
2626
}
2727

28+
func TestK8SNamespaceWithServiceAccountNoCreate(t *testing.T) {
29+
t.Parallel()
30+
31+
// Uncomment any of the following to skip that section during the test
32+
// os.Setenv("SKIP_foo", "true") // This stage doesn't exist, but is useful in ensuring the test directory isn't copied
33+
// os.Setenv("SKIP_create_test_copy_of_examples", "true")
34+
// os.Setenv("SKIP_create_terratest_options", "true")
35+
// os.Setenv("SKIP_terraform_apply", "true")
36+
// os.Setenv("SKIP_validate", "true")
37+
// os.Setenv("SKIP_cleanup", "true")
38+
39+
// Create a directory path that won't conflict
40+
workingDir := filepath.Join(".", "stages", t.Name())
41+
42+
test_structure.RunTestStage(t, "create_test_copy_of_examples", func() {
43+
testFolder := test_structure.CopyTerraformFolderToTemp(t, "..", "examples")
44+
logger.Logf(t, "path to test folder %s\n", testFolder)
45+
k8sNamespaceTerraformModulePath := filepath.Join(testFolder, "k8s-namespace-with-service-account")
46+
test_structure.SaveString(t, workingDir, "k8sNamespaceTerraformModulePath", k8sNamespaceTerraformModulePath)
47+
})
48+
49+
test_structure.RunTestStage(t, "create_terratest_options", func() {
50+
k8sNamespaceTerraformModulePath := test_structure.LoadString(t, workingDir, "k8sNamespaceTerraformModulePath")
51+
uniqueID := random.UniqueId()
52+
k8sNamespaceTerratestOptions := createExampleK8SNamespaceTerraformOptions(
53+
t, uniqueID, k8sNamespaceTerraformModulePath)
54+
k8sNamespaceTerratestOptions.Vars["create_resources"] = 0
55+
test_structure.SaveString(t, workingDir, "uniqueID", uniqueID)
56+
test_structure.SaveTerraformOptions(t, workingDir, k8sNamespaceTerratestOptions)
57+
})
58+
59+
defer test_structure.RunTestStage(t, "cleanup", func() {
60+
k8sNamespaceTerratestOptions := test_structure.LoadTerraformOptions(t, workingDir)
61+
terraform.Destroy(t, k8sNamespaceTerratestOptions)
62+
})
63+
64+
test_structure.RunTestStage(t, "terraform_apply", func() {
65+
k8sNamespaceTerratestOptions := test_structure.LoadTerraformOptions(t, workingDir)
66+
counts := terraform.GetResourceCount(t, terraform.InitAndPlan(t, k8sNamespaceTerratestOptions))
67+
assert.Equal(t, 0, counts.Change)
68+
assert.Equal(t, 0, counts.Destroy)
69+
// IMPORTANT NOTE: we don't expect any resources to create, but because of how the dependencies system works, we
70+
// expect to see 4 resources created: the 4 null_resources that act as a dependency getter.
71+
assert.Equal(t, 4, counts.Add)
72+
})
73+
}
74+
2875
func TestK8SNamespaceWithServiceAccount(t *testing.T) {
2976
t.Parallel()
3077

@@ -88,15 +135,15 @@ func TestK8SNamespaceWithServiceAccount(t *testing.T) {
88135
// validateNamespace verifies that the namespace was created and is active.
89136
func validateNamespace(t *testing.T, k8sNamespaceTerratestOptions *terraform.Options) {
90137
namespace := terraform.Output(t, k8sNamespaceTerratestOptions, "name")
91-
kubectlOptions := k8s.NewKubectlOptions("", "")
138+
kubectlOptions := k8s.NewKubectlOptions("", "", "default")
92139
k8sNamespace := k8s.GetNamespace(t, kubectlOptions, namespace)
93140
assert.Equal(t, k8sNamespace.Name, namespace)
94141
assert.Equal(t, k8sNamespace.Status.Phase, corev1.NamespaceActive)
95142
}
96143

97144
// validateRbacAccessAll verifies that the access all RBAC role has read and write privileges to the namespace
98145
func validateRbacAccessAll(t *testing.T, k8sNamespaceTerratestOptions *terraform.Options) {
99-
kubectlOptions := k8s.NewKubectlOptions("", "")
146+
kubectlOptions := k8s.NewKubectlOptions("", "", "default")
100147
namespace := terraform.Output(t, k8sNamespaceTerratestOptions, "name")
101148
serviceAccountName := terraform.Output(t, k8sNamespaceTerratestOptions, "service_account_access_all")
102149
templateArgs := TemplateArgs{
@@ -128,7 +175,7 @@ func validateRbacAccessAll(t *testing.T, k8sNamespaceTerratestOptions *terraform
128175

129176
// validateRbacAccessReadOnly verifies that the access read only RBAC role has read only privileges to the namespace
130177
func validateRbacAccessReadOnly(t *testing.T, k8sNamespaceTerratestOptions *terraform.Options) {
131-
kubectlOptions := k8s.NewKubectlOptions("", "")
178+
kubectlOptions := k8s.NewKubectlOptions("", "", "default")
132179
namespace := terraform.Output(t, k8sNamespaceTerratestOptions, "name")
133180
serviceAccountName := terraform.Output(t, k8sNamespaceTerratestOptions, "service_account_access_read_only")
134181
templateArgs := TemplateArgs{
@@ -181,8 +228,7 @@ func checkAccessForServiceAccount(
181228
// Wait for up to 5 minutes for pod to start (60 tries, 5 seconds inbetween each trial)
182229
// We explicitly set the namespace to default here, because the Kubernetes API requires an explicit namespace when
183230
// looking up pods by name.
184-
namespacedKubectlOptions := k8s.NewKubectlOptions("", "")
185-
namespacedKubectlOptions.Namespace = namespace
231+
namespacedKubectlOptions := k8s.NewKubectlOptions("", "", namespace)
186232
k8s.WaitUntilPodAvailable(t, namespacedKubectlOptions, curlPodName, 60, 5*time.Second)
187233

188234
// Run the check function while the curl pod is up

test/k8s_tiller_kubergrunt_test.go

+5-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/gruntwork-io/terratest/modules/random"
1313
"github.com/gruntwork-io/terratest/modules/shell"
1414
"github.com/gruntwork-io/terratest/modules/terraform"
15-
"github.com/gruntwork-io/terratest/modules/test-structure"
15+
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
1616
"github.com/stretchr/testify/require"
1717
)
1818

@@ -48,7 +48,7 @@ func TestK8STillerKubergrunt(t *testing.T) {
4848
testServiceAccountName := fmt.Sprintf("%s-test-account", strings.ToLower(uniqueID))
4949
testServiceAccountNamespace := fmt.Sprintf("%s-test-account-namespace", strings.ToLower(uniqueID))
5050
tmpConfigPath := k8s.CopyHomeKubeConfigToTemp(t)
51-
kubectlOptions := k8s.NewKubectlOptions("", tmpConfigPath)
51+
kubectlOptions := k8s.NewKubectlOptions("", tmpConfigPath, "default")
5252

5353
k8s.CreateNamespace(t, kubectlOptions, testServiceAccountNamespace)
5454
kubectlOptions.Namespace = testServiceAccountNamespace
@@ -84,7 +84,7 @@ func TestK8STillerKubergrunt(t *testing.T) {
8484
terraform.Destroy(t, k8sTillerTerratestOptions)
8585

8686
testServiceAccountNamespace := test_structure.LoadString(t, workingDir, "testServiceAccountNamespace")
87-
kubectlOptions := k8s.NewKubectlOptions("", "")
87+
kubectlOptions := k8s.NewKubectlOptions("", "", "default")
8888
k8s.DeleteNamespace(t, kubectlOptions, testServiceAccountNamespace)
8989
})
9090

@@ -99,8 +99,7 @@ func TestK8STillerKubergrunt(t *testing.T) {
9999
resourceNamespace := k8sTillerTerratestOptions.Vars["resource_namespace"].(string)
100100
tmpConfigPath := test_structure.LoadString(t, workingDir, "tmpKubectlConfigPath")
101101
testServiceAccountName := test_structure.LoadString(t, workingDir, "testServiceAccountName")
102-
kubectlOptions := k8s.NewKubectlOptions(testServiceAccountName, tmpConfigPath)
103-
kubectlOptions.Namespace = resourceNamespace
102+
kubectlOptions := k8s.NewKubectlOptions(testServiceAccountName, tmpConfigPath, resourceNamespace)
104103

105104
runHelm(
106105
t,
@@ -116,7 +115,7 @@ func TestK8STillerKubergrunt(t *testing.T) {
116115
// Make sure the upgrade command mentioned in the docs actually works
117116
helmHome := test_structure.LoadString(t, workingDir, "helmHome")
118117
tmpConfigPath := test_structure.LoadString(t, workingDir, "tmpKubectlConfigPath")
119-
kubectlOptions := k8s.NewKubectlOptions("", tmpConfigPath)
118+
kubectlOptions := k8s.NewKubectlOptions("", tmpConfigPath, "default")
120119

121120
runHelm(
122121
t,

test/k8s_tiller_test.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func TestK8STiller(t *testing.T) {
115115

116116
test_structure.RunTestStage(t, "setup_helm_client", func() {
117117
helmHome := test_structure.LoadString(t, workingDir, "helmHome")
118-
kubectlOptions := k8s.NewKubectlOptions("", "")
118+
kubectlOptions := k8s.NewKubectlOptions("", "", "default")
119119
k8sTillerTerratestOptions := test_structure.LoadTerraformOptions(t, workingDir)
120120
tillerNamespace := terraform.OutputRequired(t, k8sTillerTerratestOptions, "tiller_namespace")
121121
resourceNamespace := terraform.OutputRequired(t, k8sTillerTerratestOptions, "resource_namespace")
@@ -129,8 +129,7 @@ func TestK8STiller(t *testing.T) {
129129
helmHome := test_structure.LoadString(t, workingDir, "helmHome")
130130
k8sTillerTerratestOptions := test_structure.LoadTerraformOptions(t, workingDir)
131131
resourceNamespace := terraform.OutputRequired(t, k8sTillerTerratestOptions, "resource_namespace")
132-
kubectlOptions := k8s.NewKubectlOptions("", "")
133-
kubectlOptions.Namespace = resourceNamespace
132+
kubectlOptions := k8s.NewKubectlOptions("", "", resourceNamespace)
134133

135134
runHelm(
136135
t,

0 commit comments

Comments
 (0)