diff --git a/examples/terraform/inventory/classes/common.yml b/examples/terraform/inventory/classes/common.yml new file mode 100644 index 000000000..493352449 --- /dev/null +++ b/examples/terraform/inventory/classes/common.yml @@ -0,0 +1,29 @@ +# base class that should be imported on all cluster classes +# + +parameters: + + provider: + google: + project: ${name} + credentials: '~/.config/credentials.json' + version: 1.6.0 + region: ${main_region} + zone: ${main_zone} + + terraform: + backend: + gcs: + bucket: my_centralized_tf_bucket + project: centralized_gcloud_project + prefix: /${name}/ + + kapitan: + vars: + target: ${name} + compile: + - output_path: manifests + output_type: json + input_paths: + - templates/main.jsonnet + input_type: jsonnet diff --git a/examples/terraform/inventory/targets/project1.yml b/examples/terraform/inventory/targets/project1.yml new file mode 100644 index 000000000..089bff635 --- /dev/null +++ b/examples/terraform/inventory/targets/project1.yml @@ -0,0 +1,40 @@ +######################################## +# Classes to include in this target +######################################## +classes: + - common + +######################################## +# override variables defined in any of +# the classes above +######################################## +parameters: + name: project1 + main_region: europe-west2 + main_zone: europe-west2-a + + dns_default_ttl: 300 + + resources: + dns: + + google.com: + - name: www + type: A + ttl: ${dns_default_ttl} + rrdatas: + - 1.1.1.1 + - 2.2.2.2 + + - name: images + type: A + ttl: 60 + rrdatas: + - 3.3.3.3 + + google.co.uk: + - name: www + type: A + ttl: ${dns_default_ttl} + rrdatas: + - 4.4.4.4 diff --git a/examples/terraform/inventory/targets/project2.yml b/examples/terraform/inventory/targets/project2.yml new file mode 100644 index 000000000..7a01299e0 --- /dev/null +++ b/examples/terraform/inventory/targets/project2.yml @@ -0,0 +1,38 @@ +######################################## +# Classes to include in this target +######################################## +classes: + - common + +######################################## +# override variables defined in any of +# the classes above +######################################## +parameters: + name: project2 + main_region: europe-west2 + main_zone: europe-west2-a + + resources: + + container: + + cluster1: + min_master_version: 1.9.2-gke.1 + node_version: 1.9.2-gke.1 + pools: + pool1a: + disk_size_gb: 100 + image_type: COS + machine_type: n1-standard-2 + node_count: 3 + + cluster2: + min_master_version: 1.9.2-gke.1 + node_version: 1.9.2-gke.1 + pools: + pool2a: + disk_size_gb: 100 + image_type: COS + machine_type: n1-standard-2 + node_count: 3 diff --git a/examples/terraform/inventory/targets/project3.yml b/examples/terraform/inventory/targets/project3.yml new file mode 100644 index 000000000..28b23990a --- /dev/null +++ b/examples/terraform/inventory/targets/project3.yml @@ -0,0 +1,35 @@ +######################################## +# Classes to include in this target +######################################## +classes: + - common + +######################################## +# override variables defined in any of +# the classes above +######################################## +parameters: + name: project3 + main_region: europe-west2 + main_zone: europe-west2-a + + resources: + + container: + + cluster2: + min_master_version: 1.9.2-gke.1 + node_version: 1.9.2-gke.1 + pools: + + pool2a: + disk_size_gb: 100 + image_type: COS + machine_type: n1-standard-2 + node_count: 5 + + pool2b: + disk_size_gb: 100 + image_type: COS + machine_type: n1-standard-4 + node_count: 3 diff --git a/examples/terraform/templates/README.md.j2 b/examples/terraform/templates/README.md.j2 new file mode 100644 index 000000000..f7794078c --- /dev/null +++ b/examples/terraform/templates/README.md.j2 @@ -0,0 +1,29 @@ +# {{parameters.name}} +| | | +| - | - | +| **main_region** | {{parameters.main_region}} | +| **main_zone** | {{parameters.main_zone}} | +| **url** | https://console.cloud.google.com/home/dashboard?project={{parameters.name}} | + +Resources managed by terraform in this project: + +{% for item in parameters.resources %} + * {{ item }} +{% endfor %} + + +{% if parameters.resources.container is defined %} +## CONTAINER +{% for item in parameters.resources.container %} + * {{item}} + * endpoint: ${google_container_cluster.{{item}}.endpoint} + * setup command: `gcloud container clusters get-credentials {{item}} --zone europe-west2-a --project {{parameters.name}}` +{% endfor %} +{% endif %} + +{% if parameters.resources.dns is defined %} +## DNS +{% for zone in parameters.resources.dns %} + * {{zone}} +{% endfor %} +{% endif %} diff --git a/examples/terraform/templates/container.jsonnet b/examples/terraform/templates/container.jsonnet new file mode 100644 index 000000000..e9cf571ba --- /dev/null +++ b/examples/terraform/templates/container.jsonnet @@ -0,0 +1,65 @@ +local kap = import "lib/kapitan.libjsonnet"; +local inv = kap.inventory(); + +{ + + resource: { + google_container_cluster: { + [cluster]: { + initial_node_count: 1, + min_master_version: inv.parameters.resources.container[cluster].min_master_version, + name: cluster, + node_version: inv.parameters.resources.container[cluster].node_version, + } + for cluster in std.objectFields(inv.parameters.resources.container) + }, + + + google_container_node_pool: { + [pool]: { + cluster: cluster, + name: pool, + node_config: { + disk_size_gb: inv.parameters.resources.container[cluster].pools[pool].disk_size_gb, + image_type: inv.parameters.resources.container[cluster].pools[pool].image_type, + machine_type: inv.parameters.resources.container[cluster].pools[pool].machine_type, + 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", + ], + }, + node_count: inv.parameters.resources.container[cluster].pools[pool].node_count, + } + for cluster in std.objectFields(inv.parameters.resources.container) + for pool in std.objectFields(inv.parameters.resources.container[cluster].pools) + }, + + # Code below is weird but is only needed because when you create a new cluster, it ALWAYS creates + # a default-pool. Code below deletes the default-pool. + # exec will only run once on cluster creation + # More info on https://github.com/terraform-providers/terraform-provider-google/issues/773 + null_resource: { + [cluster + "_delete_default-node-pool"]: { + triggers: { + cluster_name: "${google_container_cluster." + cluster + ".name}", + }, + + provisioner: [ + { + "local-exec": { + command: "gcloud container node-pools --project=" + inv.parameters.name + + " --zone=" + inv.parameters.main_zone + + " --quiet delete default-pool --cluster " + cluster, + }, + }, + ], + depends_on: ["google_container_cluster." + cluster] + } + for cluster in std.objectFields(inv.parameters.resources.container) + }, + + }, + +} diff --git a/examples/terraform/templates/dns.jsonnet b/examples/terraform/templates/dns.jsonnet new file mode 100644 index 000000000..cdf5b00ef --- /dev/null +++ b/examples/terraform/templates/dns.jsonnet @@ -0,0 +1,32 @@ +local kap = import "lib/kapitan.libjsonnet"; +local inv = kap.inventory(); + +{ + + remove_dots(str):: + assert std.type(str) == "string"; + std.join("", std.split(str, ".")), + + + resource: { + + google_dns_managed_zone: { + [$.remove_dots(zone)]: { + name: $.remove_dots(zone), + dns_name: zone + ".", # add mandatory dot at the end of zone + description: "DNS zone for " + zone, + } + for zone in std.objectFields(inv.parameters.resources.dns) + }, + + google_dns_record_set: { + [$.remove_dots(zone + "_" + set.name + "_" + set.type)]: set { + managed_zone: $.remove_dots(zone), + } + for zone in std.objectFields(inv.parameters.resources.dns) + for set in inv.parameters.resources.dns[zone] + }, + + }, + +} diff --git a/examples/terraform/templates/main.jsonnet b/examples/terraform/templates/main.jsonnet new file mode 100644 index 000000000..b8721664a --- /dev/null +++ b/examples/terraform/templates/main.jsonnet @@ -0,0 +1,22 @@ +local kap = import "lib/kapitan.libjsonnet"; +local inv = kap.inventory(); + +local compute = import "compute.jsonnet"; +local container = import "container.jsonnet"; +local dns = import "dns.jsonnet"; +local iam = import "iam.jsonnet"; +local output = import "output.jsonnet"; +local provider = import "provider.jsonnet"; +local sql = import "sql.jsonnet"; +local storage = import "storage.jsonnet"; + +{ + "output.tf": output, + "provider.tf": provider, + [if "compute" in inv.parameters.resources then "compute.tf"]: compute, + [if "container" in inv.parameters.resources then "container.tf"]: container, + [if "dns" in inv.parameters.resources then "dns.tf"]: dns, + [if "iam" in inv.parameters.resources then "iam.tf"]: iam, + [if "sql" in inv.parameters.resources then "sql.tf"]: sql, + [if "storage" in inv.parameters.resources then "storage.tf"]: storage, +} diff --git a/examples/terraform/templates/output.jsonnet b/examples/terraform/templates/output.jsonnet new file mode 100644 index 000000000..684859aa5 --- /dev/null +++ b/examples/terraform/templates/output.jsonnet @@ -0,0 +1,37 @@ +local kap = import "lib/kapitan.libjsonnet"; +local inv = kap.inventory(); + +{ + data: { + template_file: { + readme: { + template: kap.jinja2_template("templates/README.md.j2", inv), + }, + }, + }, + + resource: { + null_resource: { + readme_generator: { + triggers: { + template_rendered: "${data.template_file.readme.rendered}", + }, + + provisioner: [ + { + "local-exec": { + command: "echo '${data.template_file.readme.rendered}' > ../README.md", + }, + }, + ], + }, + }, + }, + + output: { + "README.md": { + value: "\n${data.template_file.readme.rendered}", + }, + }, + +} diff --git a/examples/terraform/templates/provider.jsonnet b/examples/terraform/templates/provider.jsonnet new file mode 100644 index 000000000..d55c817c3 --- /dev/null +++ b/examples/terraform/templates/provider.jsonnet @@ -0,0 +1,20 @@ +local kap = import "lib/kapitan.libjsonnet"; +local inv = kap.inventory(); + + +{ + provider: { + google: { + credentials: '${file("' + inv.parameters.provider.google.credentials + '")}', + project: inv.parameters.provider.google.project, + region: inv.parameters.provider.google.region, + version: inv.parameters.provider.google.version, + zone: inv.parameters.provider.google.zone, + }, + }, + + + terraform: { + backend: inv.parameters.terraform.backend, + }, +}