Skip to content

Commit

Permalink
Add terratest to gha (#16)
Browse files Browse the repository at this point in the history
Add terratest to gha
  • Loading branch information
gkocur authored Jun 11, 2024
1 parent 8c63be2 commit 1f2958d
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 75 deletions.
31 changes: 28 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
if: ${{ github.event_name == 'pull_request' }}
with:
ref: ${{ github.event.pull_request.head.ref }}
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
if: ${{ github.event_name == 'push' }}
with:
ref: ${{ github.ref_name }}
- name: Setup terraform
uses: hashicorp/setup-terraform@v1
uses: hashicorp/setup-terraform@v3
- name: Terraform Init
run: terraform init
- name: Terraform Format
Expand All @@ -32,3 +32,28 @@ jobs:
config-file: .terraform-docs.yml
working-dir: .
git-push: "true"
terratest:
needs: ["terraform"]
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v4
with:
cache-dependency-path: test/go.sum
go-version-file: test/go.mod
- name: Authenticate to GCP
uses: google-github-actions/auth@v2
with:
workload_identity_provider: 'projects/1071668732006/locations/global/workloadIdentityPools/github/providers/terraform-gke-bootstrap'
- name: Run Terratest
env:
TF_VAR_org_id: ${{ secrets.ORG_ID }}
TF_VAR_billing_account: ${{ secrets.BILLING_ACCOUNT }}
TF_VAR_project_id: ${{ secrets.PROJECT_ID }}
run: go test -v -timeout 30m -skip TestNewProject
working-directory: test
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ No requirements.
| Name | Type |
|------|------|
| [google-beta_google_container_node_pool.pools](https://registry.terraform.io/providers/hashicorp/google-beta/latest/docs/resources/google_container_node_pool) | resource |
| [google_artifact_registry_repository.my-repo](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/artifact_registry_repository) | resource |
| [google_compute_address.cloud_nat_address](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_address) | resource |
| [google_container_cluster.gke](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/container_cluster) | resource |

Expand All @@ -99,7 +100,10 @@ No requirements.
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_activate_apis"></a> [activate\_apis](#input\_activate\_apis) | List of Google APIs activated in new or existing project. | `list(string)` | <pre>[<br> "compute.googleapis.com",<br> "container.googleapis.com"<br>]</pre> | no |
| <a name="input_artifact_registry_name"></a> [artifact\_registry\_name](#input\_artifact\_registry\_name) | The name of the artifact registry repository | `string` | `"my-repository"` | no |
| <a name="input_billing_account"></a> [billing\_account](#input\_billing\_account) | YOU NEED TO HAVE PERMISSION TO BILLING ACCOUNT, The billing account to witch the new project should be connected. Required if `create_project` set to `true`. | `string` | `""` | no |
| <a name="input_cluster_deletion_protection"></a> [cluster\_deletion\_protection](#input\_cluster\_deletion\_protection) | Whether or not to allow Terraform to destroy the cluster. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the cluster will fail. | `bool` | `true` | no |
| <a name="input_create_artifact_registry"></a> [create\_artifact\_registry](#input\_create\_artifact\_registry) | Whether to create Artifact Registry for docker images | `bool` | `false` | no |
| <a name="input_create_project"></a> [create\_project](#input\_create\_project) | Defines if create the project. All resources are created this project. If `false` - the project\_id is required. | `bool` | `false` | no |
| <a name="input_default_node_pools_oauth_scopes"></a> [default\_node\_pools\_oauth\_scopes](#input\_default\_node\_pools\_oauth\_scopes) | Default node pool oauth scopes added to all node pools | `list(string)` | <pre>[<br> "https://www.googleapis.com/auth/cloud-platform"<br>]</pre> | no |
| <a name="input_default_pool_machine_type"></a> [default\_pool\_machine\_type](#input\_default\_pool\_machine\_type) | In some cases the GKE won't be created unless the default pool uses specific machine type (for example confidential nodes) so we have to set the type even if the default pool is removed. | `string` | `"e2-small"` | no |
Expand Down
23 changes: 12 additions & 11 deletions examples/autopilot/main.tf
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
module "gke" {
source = "../../"
create_project = true
enable_autopilot = true
billing_account = var.billing_account
org_id = var.org_id
k8s_network_base = "10.100.0.0/16"
platform_name = var.platform_name
region = "europe-central2"
subnet_network = "10.1.0.0/20"
regional = true
node_pools = {}
source = "../../"
create_project = false
project_id = var.project_id
enable_autopilot = true
disable_services_on_destroy = false
k8s_network_base = "10.100.0.0/16"
platform_name = var.platform_name
region = "europe-central2"
subnet_network = "10.1.0.0/20"
regional = true
node_pools = {}
cluster_deletion_protection = false
}
7 changes: 2 additions & 5 deletions examples/autopilot/variables.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
variable "billing_account" {
variable "platform_name" {
type = string
}
variable "org_id" {
variable "project_id" {
type = string
}
variable "platform_name" {
type = string
}
1 change: 1 addition & 0 deletions examples/existing-project/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module "gke" {
k8s_network_base = "10.100.0.0/16"
regional = false
zones = ["europe-central2-a"]
cluster_deletion_protection = false
node_pools = {
default-pool = {
disk_size_gb = 50
Expand Down
5 changes: 2 additions & 3 deletions examples/existing-project/variables.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
variable "project_id" {
type = string
default = "sml-internal"
type = string
}
variable "platform_name" {
type = string
}
}
9 changes: 9 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ resource "google_container_cluster" "gke" {
remove_default_node_pool = var.enable_autopilot == null ? true : null
enable_autopilot = var.enable_autopilot
initial_node_count = 1
deletion_protection = var.cluster_deletion_protection
node_config {
machine_type = var.default_pool_machine_type
}
Expand Down Expand Up @@ -164,3 +165,11 @@ resource "google_container_node_pool" "pools" {
create_before_destroy = true
}
}

resource "google_artifact_registry_repository" "my-repo" {
count = var.create_artifact_registry ? 1 : 0
location = var.region
repository_id = var.artifact_registry_name
description = "Docker repository"
format = "DOCKER"
}
52 changes: 0 additions & 52 deletions test/terratest_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"google.golang.org/api/container/v1"
appsv1 "k8s.io/api/apps/v1"
apiv1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/kubernetes"
Expand Down Expand Up @@ -132,55 +131,10 @@ func createTestService(clientset *kubernetes.Clientset, serviceName string, depl
return result, nil
}

func createTestIngress(clientset *kubernetes.Clientset, ingressName string, servicName string) (*networkingv1.Ingress, error) {
ingressClient := clientset.NetworkingV1().Ingresses(apiv1.NamespaceDefault)
pathType := networkingv1.PathTypePrefix
ingress := &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{Name: ingressName},
Spec: networkingv1.IngressSpec{
Rules: []networkingv1.IngressRule{
{
IngressRuleValue: networkingv1.IngressRuleValue{
HTTP: &networkingv1.HTTPIngressRuleValue{
Paths: []networkingv1.HTTPIngressPath{
{
Path: "/",
PathType: &pathType,
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
Name: servicName,
Port: networkingv1.ServiceBackendPort{
Number: 80,
},
},
},
},
},
},
},
},
},
},
}

result, err := ingressClient.Create(context.TODO(), ingress, metav1.CreateOptions{})

if err != nil {
return nil, err
}
return result, nil
}

func deleteIngress(clientset *kubernetes.Clientset, ingressName string) {
ingressClient := clientset.NetworkingV1().Ingresses(apiv1.NamespaceDefault)
ingressClient.Delete(context.TODO(), ingressName, metav1.DeleteOptions{})
}

func testExample(t *testing.T, exampleDir string) {
randId := strings.ToLower(random.UniqueId())
deplName := "nginx-" + randId
serviceName := deplName
ingressName := deplName

platformName := "test-platform-" + randId

Expand Down Expand Up @@ -215,14 +169,8 @@ func testExample(t *testing.T, exampleDir string) {
service, err := createTestService(k8sClientSet, serviceName, deplName)
assert.NoError(t, err)

// Remove ingress to avoid existing NEG after cluster deletion
defer deleteIngress(k8sClientSet, ingressName)
ingress, err := createTestIngress(k8sClientSet, ingressName, serviceName)
assert.NoError(t, err)

kubectlOptions := k8s.NewKubectlOptionsWithRestConfig(restConfig, apiv1.NamespaceDefault)

k8s.WaitUntilDeploymentAvailable(t, kubectlOptions, deployment.Name, 20, 10*time.Second)
k8s.WaitUntilServiceAvailable(t, kubectlOptions, service.Name, 10, 10*time.Second)
k8s.WaitUntilIngressAvailable(t, kubectlOptions, ingress.Name, 30, 10*time.Second)
}
20 changes: 19 additions & 1 deletion variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ variable "activate_apis" {
type = list(string)
default = [
"compute.googleapis.com",
"container.googleapis.com"
"container.googleapis.com",
]
description = "List of Google APIs activated in new or existing project."
}
Expand Down Expand Up @@ -155,3 +155,21 @@ variable "subnet_private_access" {
default = true
description = "Whether to enable google private IP access for the subnet"
}

variable "create_artifact_registry" {
type = bool
default = false
description = "Whether to create Artifact Registry for docker images"
}

variable "artifact_registry_name" {
type = string
default = "my-repository"
description = "The name of the artifact registry repository"
}

variable "cluster_deletion_protection" {
type = bool
default = true
description = "Whether or not to allow Terraform to destroy the cluster. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the cluster will fail."
}

0 comments on commit 1f2958d

Please sign in to comment.