Skip to content

Commit

Permalink
feat: add kubectl-fleet-wrapper sub-module (#161)
Browse files Browse the repository at this point in the history
Co-authored-by: Awais Malik <awmalik@google.com>
  • Loading branch information
apeabody and g-awmalik authored Sep 25, 2023
1 parent 711c204 commit bc4076c
Show file tree
Hide file tree
Showing 9 changed files with 392 additions and 3 deletions.
43 changes: 40 additions & 3 deletions examples/kubectl_wrapper_example/main.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2020 Google LLC
* Copyright 2020-2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -30,6 +30,8 @@ module "enabled_google_apis" {
"monitoring.googleapis.com",
"container.googleapis.com",
"stackdriver.googleapis.com",
"gkehub.googleapis.com",
"connectgateway.googleapis.com",
]
}

Expand Down Expand Up @@ -97,7 +99,42 @@ module "kubectl-local-yaml" {
cluster_name = module.gke.name
cluster_location = module.gke.location
module_depends_on = [module.kubectl-imperative.wait, module.gke.endpoint]
kubectl_create_command = "kubectl apply -f ${local.manifest_path}"
kubectl_destroy_command = "kubectl delete -f ${local.manifest_path}"
kubectl_create_command = "kubectl apply -f ${local.manifest_path}/nginx.yaml"
kubectl_destroy_command = "kubectl delete -f ${local.manifest_path}/nginx.yaml"
skip_download = false
}

module "fleet" {
source = "terraform-google-modules/kubernetes-engine/google//modules/fleet-membership"
version = "~> 28.0"

depends_on = [module.gke]

project_id = var.project_id
cluster_name = module.gke.name
location = module.gke.location
}

module "kubectl-fleet-imperative" {
source = "../../modules/kubectl-fleet-wrapper"

membership_name = module.fleet.cluster_membership_id
membership_project_id = module.fleet.project_id
membership_location = module.fleet.location
module_depends_on = [module.kubectl-local-yaml.wait, module.fleet.wait]
kubectl_create_command = "kubectl run nginx-fleet-imperative --image=nginx"
kubectl_destroy_command = "kubectl delete pod nginx-fleet-imperative"
skip_download = false
}

module "kubectl-fleet-local-yaml" {
source = "../../modules/kubectl-fleet-wrapper"

membership_name = module.fleet.cluster_membership_id
membership_project_id = module.fleet.project_id
membership_location = module.fleet.location
module_depends_on = [module.kubectl-fleet-imperative.wait, module.gke.endpoint]
kubectl_create_command = "kubectl apply -f ${local.manifest_path}/nginx-fleet.yaml"
kubectl_destroy_command = "kubectl delete -f ${local.manifest_path}/nginx-fleet.yaml"
skip_download = true
}
22 changes: 22 additions & 0 deletions examples/kubectl_wrapper_example/manifests/nginx-fleet.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2020-2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: Pod
metadata:
name: nginx-fleet-declarative
spec:
containers:
- name: nginx
image: nginx
59 changes: 59 additions & 0 deletions modules/kubectl-fleet-wrapper/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# kubectl fleet wrapper

This submodule aims to make interactions with [GKE clusters with Fleet memberships](https://cloud.google.com/anthos/fleet-management/docs) using kubectl easier by utilizing the gcloud module and the kubectl_fleet_wrapper script.

This module can be used to deploy any Kubernetes resource using imperative commands or declarative yaml files. An example can be found [here](../../examples/kubectl_wrapper_example).

## Usage

Basic imperative usage of this module is as follows:

```hcl
module "kubectl" {
source = "terraform-google-modules/gcloud/google//modules/kubectl-fleet-wrapper"
membership_project_id = var.project_id
membership_name = var.cluster_name
membership_location = var.cluster_location
kubectl_create_command = "kubectl create deploy nginx --image=nginx"
kubectl_destroy_command = "kubectl delete deploy nginx"
}
```

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| additional\_components | Additional gcloud CLI components to install. Valid value are components listed in `gcloud components list` | `list(string)` | <pre>[<br> "kubectl"<br>]</pre> | no |
| create\_cmd\_triggers | List of any additional triggers for the create command execution. | `map(any)` | `{}` | no |
| enabled | Flag to optionally disable usage of this module. | `bool` | `true` | no |
| gcloud\_sdk\_version | The gcloud sdk version to download. | `string` | `"434.0.0"` | no |
| impersonate\_service\_account | An optional service account to impersonate for gcloud commands. If this service account is not specified, the module will use Application Default Credentials. | `string` | `null` | no |
| kubectl\_create\_command | The kubectl command to create resources. | `string` | n/a | yes |
| kubectl\_destroy\_command | The kubectl command to destroy resources. | `string` | n/a | yes |
| membership\_location | Membership location (Global/Region). | `string` | n/a | yes |
| membership\_name | Membership name. | `string` | n/a | yes |
| membership\_project\_id | Membership project ID. | `string` | n/a | yes |
| module\_depends\_on | List of modules or resources this module depends on. | `list(any)` | `[]` | no |
| service\_account\_key\_file | Path to service account key file to auth as for running `gcloud container clusters get-credentials`. | `string` | `""` | no |
| skip\_download | Whether to skip downloading gcloud (assumes `gcloud` and `kubectl` are already available outside the module). | `bool` | `true` | no |
| upgrade | Whether to upgrade gcloud at runtime. | `bool` | `true` | no |
| use\_tf\_google\_credentials\_env\_var | Use `GOOGLE_CREDENTIALS` environment variable to run `gcloud auth activate-service-account` with. Optional. | `bool` | `false` | no |

## Outputs

| Name | Description |
|------|-------------|
| bin\_dir | The full bin path of the modules executables |
| create\_cmd\_bin | The full bin path & command used on create |
| destroy\_cmd\_bin | The full bin path & command used on destroy |
| wait | An output to use when you want to depend on cmd finishing |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

To provision this example, run the following from within this directory:
- `terraform init` to get the plugins
- `terraform plan` to see the infrastructure plan
- `terraform apply` to apply the infrastructure build
- `terraform destroy` to destroy the built infrastructure
37 changes: 37 additions & 0 deletions modules/kubectl-fleet-wrapper/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright 2020-2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

locals {
base_cmd = "${var.membership_name} ${var.membership_location} ${var.membership_project_id} ${coalesce(var.impersonate_service_account, "false")}"
}

module "gcloud_kubectl" {
source = "../.."
module_depends_on = var.module_depends_on
additional_components = var.additional_components
skip_download = var.skip_download
gcloud_sdk_version = var.gcloud_sdk_version
enabled = var.enabled
upgrade = var.upgrade
service_account_key_file = var.service_account_key_file
use_tf_google_credentials_env_var = var.use_tf_google_credentials_env_var

create_cmd_entrypoint = "${path.module}/scripts/kubectl_fleet_wrapper.sh"
create_cmd_body = "${local.base_cmd} ${var.kubectl_create_command}"
create_cmd_triggers = var.create_cmd_triggers
destroy_cmd_entrypoint = "${path.module}/scripts/kubectl_fleet_wrapper.sh"
destroy_cmd_body = "${local.base_cmd} ${var.kubectl_destroy_command}"
}
35 changes: 35 additions & 0 deletions modules/kubectl-fleet-wrapper/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

output "create_cmd_bin" {
description = "The full bin path & command used on create"
value = module.gcloud_kubectl.create_cmd_bin
}

output "destroy_cmd_bin" {
description = "The full bin path & command used on destroy"
value = module.gcloud_kubectl.destroy_cmd_bin
}

output "bin_dir" {
description = "The full bin path of the modules executables"
value = module.gcloud_kubectl.bin_dir
}

output "wait" {
description = "An output to use when you want to depend on cmd finishing"
value = module.gcloud_kubectl.wait
}
52 changes: 52 additions & 0 deletions modules/kubectl-fleet-wrapper/scripts/kubectl_fleet_wrapper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# Copyright 2020-2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


set -xeo pipefail

if [ "$#" -lt 4 ]; then
>&2 echo "Not all expected arguments set."
exit 1
fi

NAME=$1
LOCATION=$2
PROJECT_ID=$3
IMPERSONATE_SERVICE_ACCOUNT=$4

shift 4

RANDOM_ID="${RANDOM}_${RANDOM}"
export TMPDIR="/tmp/kubectl_fleet_wrapper_${RANDOM_ID}"

function cleanup {
rm -rf "${TMPDIR}"
}
trap cleanup EXIT

mkdir "${TMPDIR}"

export KUBECONFIG="${TMPDIR}/config"

CMD="gcloud container fleet memberships get-credentials ${NAME} --project ${PROJECT_ID} --location ${LOCATION}"

if [[ "${IMPERSONATE_SERVICE_ACCOUNT}" != false ]]; then
CMD+=" --impersonate-service-account ${IMPERSONATE_SERVICE_ACCOUNT}"
shift 2
fi

$CMD

"$@"
100 changes: 100 additions & 0 deletions modules/kubectl-fleet-wrapper/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* Copyright 2020-2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

variable "membership_project_id" {
type = string
description = "Membership project ID."
}

variable "membership_name" {
type = string
description = "Membership name."
}

variable "membership_location" {
type = string
description = "Membership location (Global/Region)."
}

variable "kubectl_create_command" {
type = string
description = "The kubectl command to create resources."
}

variable "kubectl_destroy_command" {
type = string
description = "The kubectl command to destroy resources."
}

variable "enabled" {
description = "Flag to optionally disable usage of this module."
type = bool
default = true
}

variable "module_depends_on" {
description = "List of modules or resources this module depends on."
type = list(any)
default = []
}

variable "create_cmd_triggers" {
description = "List of any additional triggers for the create command execution."
type = map(any)
default = {}
}

variable "additional_components" {
description = "Additional gcloud CLI components to install. Valid value are components listed in `gcloud components list`"
type = list(string)
default = ["kubectl"]
}

variable "skip_download" {
description = "Whether to skip downloading gcloud (assumes `gcloud` and `kubectl` are already available outside the module)."
type = bool
default = true
}

variable "gcloud_sdk_version" {
description = "The gcloud sdk version to download."
type = string
default = "434.0.0"
}

variable "upgrade" {
description = "Whether to upgrade gcloud at runtime."
type = bool
default = true
}

variable "service_account_key_file" {
description = "Path to service account key file to auth as for running `gcloud container clusters get-credentials`."
type = string
default = ""
}

variable "use_tf_google_credentials_env_var" {
description = "Use `GOOGLE_CREDENTIALS` environment variable to run `gcloud auth activate-service-account` with. Optional."
type = bool
default = false
}

variable "impersonate_service_account" {
type = string
description = "An optional service account to impersonate for gcloud commands. If this service account is not specified, the module will use Application Default Credentials."
default = null
}
Loading

0 comments on commit bc4076c

Please sign in to comment.