Skip to content

Commit

Permalink
feat: Add config sync module (#493)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The ACM module has been refactored and resources will be recreated. This will show up in Terraform plans but is a safe no-op for Kubernetes.
  • Loading branch information
linde committed Apr 28, 2020
1 parent 54eca6b commit c090d5b
Show file tree
Hide file tree
Showing 16 changed files with 514 additions and 85 deletions.
2 changes: 2 additions & 0 deletions modules/acm/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# This fill will be always downloaded by terraform local-exec command from gc bucket
config-management-operator.yaml
/terraform.tfvars
/apply.out
/local.tfvars
4 changes: 3 additions & 1 deletion modules/acm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ By default, this module will attempt to download the ACM operator from Google di
| operator\_path | Path to the operator yaml config. If unset, will download from GCS releases. | string | `"null"` | no |
| policy\_dir | Subfolder containing configs in ACM Git repo | string | n/a | yes |
| project\_id | The project in which the resource belongs. | string | n/a | yes |
| secret\_type | git authentication secret type, is passed through to ConfigManagement spec.git.secretType. Overriden to value 'ssh' if `create_ssh_key` is true | string | `"ssh"` | no |
| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud and kubectl already available outside the module) | bool | `"false"` | no |
| ssh\_auth\_key | Key for Git authentication. Overrides 'create_ssh_key' variable. Can be set using 'file(path/to/file)'-function. | string | `"null"` | no |
| sync\_branch | ACM repo Git branch | string | `"master"` | no |
| sync\_repo | ACM Git repo address | string | n/a | yes |
Expand All @@ -61,6 +63,6 @@ By default, this module will attempt to download the ACM operator from Google di

| Name | Description |
|------|-------------|
| git\_creds\_public | Public key of SSH keypair to allow the Anthos Operator to authenticate to your Git repository. |
| git\_creds\_public | Public key of SSH keypair to allow the Anthos Config Management Operator to authenticate to your Git repository. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
102 changes: 21 additions & 81 deletions modules/acm/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,87 +14,27 @@
* limitations under the License.
*/

locals {
cluster_endpoint = "https://${var.cluster_endpoint}"
token = data.google_client_config.default.access_token
cluster_ca_certificate = data.google_container_cluster.primary.master_auth.0.cluster_ca_certificate
private_key = var.create_ssh_key && var.ssh_auth_key == null ? tls_private_key.git_creds[0].private_key_pem : var.ssh_auth_key
download_operator = var.operator_path == null ? true : false
operator_path = local.download_operator ? "${path.module}/config-management-operator.yaml" : var.operator_path
}

data "google_container_cluster" "primary" {
name = var.cluster_name
project = var.project_id
location = var.location
}

data "google_client_config" "default" {
}

resource "tls_private_key" "git_creds" {
count = var.create_ssh_key ? 1 : 0
algorithm = "RSA"
rsa_bits = 4096
}

module "acm_operator_config" {
source = "terraform-google-modules/gcloud/google"
version = "~> 0.5"
enabled = local.download_operator

create_cmd_entrypoint = "gsutil"
create_cmd_body = "cp gs://config-management-release/released/latest/config-management-operator.yaml ${path.module}/config-management-operator.yaml"
destroy_cmd_entrypoint = "rm"
destroy_cmd_body = "-f ${path.module}/config-management-operator.yaml"
}

module "acm_operator" {
source = "terraform-google-modules/gcloud/google"
version = "~> 0.5"
module_depends_on = [module.acm_operator_config.wait, data.google_client_config.default.project, data.google_container_cluster.primary.name]
additional_components = ["kubectl"]

create_cmd_entrypoint = "${path.module}/scripts/kubectl_wrapper.sh"
create_cmd_body = "${local.cluster_endpoint} ${local.token} ${local.cluster_ca_certificate} kubectl apply -f ${local.operator_path}"
destroy_cmd_entrypoint = "${path.module}/scripts/kubectl_wrapper.sh"
destroy_cmd_body = "${local.cluster_endpoint} ${local.token} ${local.cluster_ca_certificate} kubectl delete -f ${local.operator_path}"
}

module "git_creds_secret" {
source = "terraform-google-modules/gcloud/google"
version = "~> 0.5"
module_depends_on = [module.acm_operator.wait]
additional_components = ["kubectl"]

create_cmd_entrypoint = "${path.module}/scripts/kubectl_wrapper.sh"
create_cmd_body = "${local.cluster_endpoint} ${local.token} ${local.cluster_ca_certificate} kubectl create secret generic git-creds -n=config-management-system --from-literal=ssh='${local.private_key}'"
destroy_cmd_entrypoint = "${path.module}/scripts/kubectl_wrapper.sh"
destroy_cmd_body = "${local.cluster_endpoint} ${local.token} ${local.cluster_ca_certificate} kubectl delete secret git-creds -n=config-management-system"
}

data "template_file" "acm_config" {
template = file("${path.module}/templates/acm-config.yml.tpl")

vars = {
cluster_name = var.cluster_name
sync_repo = var.sync_repo
sync_branch = var.sync_branch
policy_dir = var.policy_dir
secret_type = var.create_ssh_key ? "ssh" : "none"
enable_policy_controller = var.enable_policy_controller ? "true" : "false"
install_template_library = var.install_template_library ? "true" : "false"
}
}

module "acm_config" {
source = "terraform-google-modules/gcloud/google"
version = "~> 0.5"
module_depends_on = [module.acm_operator.wait, module.git_creds_secret.wait]
additional_components = ["kubectl"]

create_cmd_entrypoint = "echo"
create_cmd_body = "'${data.template_file.acm_config.rendered}' | ${path.module}/scripts/kubectl_wrapper.sh ${local.cluster_endpoint} ${local.token} ${local.cluster_ca_certificate} kubectl apply -f -"
destroy_cmd_entrypoint = "echo"
destroy_cmd_body = "'${data.template_file.acm_config.rendered}' | ${path.module}/scripts/kubectl_wrapper.sh ${local.cluster_endpoint} ${local.token} ${local.cluster_ca_certificate} kubectl delete -f -"
source = "../k8s-operator-crd-support"

cluster_name = var.cluster_name
project_id = var.project_id
location = var.location
operator_path = var.operator_path
sync_repo = var.sync_repo
sync_branch = var.sync_branch
policy_dir = var.policy_dir
cluster_endpoint = var.cluster_endpoint
create_ssh_key = var.create_ssh_key
secret_type = var.secret_type
ssh_auth_key = var.ssh_auth_key
enable_policy_controller = var.enable_policy_controller
install_template_library = var.install_template_library
skip_gcloud_download = var.skip_gcloud_download

operator_latest_manifest_url = "gs://config-management-release/released/latest/config-management-operator.yaml"
operator_cr_template_path = "${path.module}/templates/acm-config.yml.tpl"
operator_credential_namespace = "config-management-system"
operator_credential_name = "git-creds"
}
5 changes: 2 additions & 3 deletions modules/acm/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/

output "git_creds_public" {
description = "Public key of SSH keypair to allow the Anthos Operator to authenticate to your Git repository."
value = var.create_ssh_key ? tls_private_key.git_creds.*.public_key_openssh : null
description = "Public key of SSH keypair to allow the Anthos Config Management Operator to authenticate to your Git repository."
value = module.acm_operator.git_creds_public
}

12 changes: 12 additions & 0 deletions modules/acm/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ variable "create_ssh_key" {
default = true
}

variable "secret_type" {
description = "git authentication secret type, is passed through to ConfigManagement spec.git.secretType. Overriden to value 'ssh' if `create_ssh_key` is true"
type = string
default = "ssh"
}

variable "ssh_auth_key" {
description = "Key for Git authentication. Overrides 'create_ssh_key' variable. Can be set using 'file(path/to/file)'-function."
type = string
Expand All @@ -79,3 +85,9 @@ variable "install_template_library" {
type = bool
default = true
}

variable "skip_gcloud_download" {
description = "Whether to skip downloading gcloud (assumes gcloud and kubectl already available outside the module)"
type = bool
default = false
}
5 changes: 5 additions & 0 deletions modules/config-sync/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# This fill will be always downloaded by terraform local-exec command from gc bucket
config-management-operator.yaml
/terraform.tfvars
/apply.out
/local.tfvars
69 changes: 69 additions & 0 deletions modules/config-sync/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Terraform Kubernetes Engine Config Sync Submodule

This module installs [Config Sync](https://cloud.google.com/kubernetes-engine/docs/add-on/config-sync) in a Kubernetes cluster.

Specifically, this module automates the following steps for [installing Config
Sync](https://cloud.google.com/kubernetes-engine/docs/add-on/config-sync/how-to/installing):
1. Installing the Config Sync Operator manifest onto your cluster.
2. Using an existing or generating a new SSH key for accessing Git and providing it to the Operator
3. Configuring the Operator to connect to your git repository

## Usage

The following is an example minimal usage. Please see the
[variables.tf](variables.tf) file for more details and expected values and
types.

```tf
module "config_sync" {
source = "terraform-google-modules/kubernetes-engine/google//modules/config-sync"
project_id = "my-project-id"
cluster_name = "my-cluster-name"
location = module.gke.location
cluster_endpoint = module.gke.endpoint
sync_repo = "git@github.com:GoogleCloudPlatform/csp-config-management.git"
sync_branch = "1.0.0"
policy_dir = "foo-corp"
}
```

To deploy this config:
1. Run `terraform apply`
2. Inspect the `git_creds_public` [output](#outputs) to retrieve the public key
used for accessing Git. Whitelist this key for access to your Git
repo. Instructions for some popular Git hosting providers are included for
convenience:

* [Cloud Souce Repositories](https://cloud.google.com/source-repositories/docs/authentication#ssh)
* [Bitbucket](https://confluence.atlassian.com/bitbucket/set-up-an-ssh-key-728138079.html)
* [GitHub](https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/)
* [Gitlab](https://docs.gitlab.com/ee/ssh/)


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

| Name | Description | Type | Default | Required |
|------|-------------|:----:|:-----:|:-----:|
| cluster\_endpoint | Kubernetes cluster endpoint. | string | n/a | yes |
| cluster\_name | The unique name to identify the cluster in ACM. | string | n/a | yes |
| create\_ssh\_key | Controls whether a key will be generated for Git authentication | bool | `"true"` | no |
| location | The location (zone or region) this cluster has been created in. | string | n/a | yes |
| operator\_path | Path to the operator yaml config. If unset, will download from GCS releases. | string | `"null"` | no |
| policy\_dir | Subfolder containing configs in ACM Git repo | string | n/a | yes |
| project\_id | The project in which the resource belongs. | string | n/a | yes |
| secret\_type | credential secret type, passed through to ConfigManagement spec.git.secretType. Overriden to value 'ssh' if `create_ssh_key` is true | string | n/a | yes |
| skip\_gcloud\_download | Whether to skip downloading gcloud (assumes gcloud and kubectl already available outside the module) | bool | `"false"` | no |
| ssh\_auth\_key | Key for Git authentication. Overrides 'create_ssh_key' variable. Can be set using 'file(path/to/file)'-function. | string | `"null"` | no |
| sync\_branch | ACM repo Git branch | string | `"master"` | no |
| sync\_repo | ACM Git repo address | string | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| git\_creds\_public | Public key of SSH keypair to allow the Config Sync Operator to authenticate to your Git repository. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
38 changes: 38 additions & 0 deletions modules/config-sync/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Copyright 2018 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.
*/

module "configsync_operator" {

source = "../k8s-operator-crd-support"

cluster_name = var.cluster_name
project_id = var.project_id
location = var.location
operator_path = var.operator_path
sync_repo = var.sync_repo
sync_branch = var.sync_branch
policy_dir = var.policy_dir
cluster_endpoint = var.cluster_endpoint
create_ssh_key = var.create_ssh_key
secret_type = var.secret_type
ssh_auth_key = var.ssh_auth_key
skip_gcloud_download = var.skip_gcloud_download

operator_latest_manifest_url = "gs://config-management-release/released/latest/config-sync-operator.yaml"
operator_cr_template_path = "${path.module}/templates/config-sync-config.yml.tpl"
operator_credential_namespace = "config-management-system"
operator_credential_name = "git-creds"
}
21 changes: 21 additions & 0 deletions modules/config-sync/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Copyright 2018 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 "git_creds_public" {
description = "Public key of SSH keypair to allow the Config Sync Operator to authenticate to your Git repository."
value = module.configsync_operator.git_creds_public
}

12 changes: 12 additions & 0 deletions modules/config-sync/templates/config-sync-config.yml.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: configmanagement.gke.io/v1
kind: ConfigManagement
metadata:
name: config-management
spec:
# clusterName is required and must be unique among all managed clusters
clusterName: ${cluster_name}
git:
syncRepo: ${sync_repo}
syncBranch: ${sync_branch}
secretType: ${secret_type}
policyDir: ${policy_dir}
80 changes: 80 additions & 0 deletions modules/config-sync/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Copyright 2018 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 "cluster_name" {
description = "The unique name to identify the cluster in ACM."
type = string
}

variable "project_id" {
description = "The project in which the resource belongs."
type = string
}

variable "location" {
description = "The location (zone or region) this cluster has been created in."
type = string
}

variable "operator_path" {
description = "Path to the operator yaml config. If unset, will download from GCS releases."
type = string
default = null
}

variable "sync_repo" {
description = "ACM Git repo address"
type = string
}

variable "sync_branch" {
description = "ACM repo Git branch"
type = string
default = "master"
}

variable "policy_dir" {
description = "Subfolder containing configs in ACM Git repo"
type = string
}

variable "cluster_endpoint" {
description = "Kubernetes cluster endpoint."
type = string
}

variable "create_ssh_key" {
description = "Controls whether a key will be generated for Git authentication"
type = bool
default = true
}

variable "secret_type" {
description = "credential secret type, passed through to ConfigManagement spec.git.secretType. Overriden to value 'ssh' if `create_ssh_key` is true"
type = string
}

variable "ssh_auth_key" {
description = "Key for Git authentication. Overrides 'create_ssh_key' variable. Can be set using 'file(path/to/file)'-function."
type = string
default = null
}

variable "skip_gcloud_download" {
description = "Whether to skip downloading gcloud (assumes gcloud and kubectl already available outside the module)"
type = bool
default = false
}
Loading

0 comments on commit c090d5b

Please sign in to comment.