diff --git a/.github/workflows/configurations.yaml b/.github/workflows/configurations.yaml index 9e0d2e82d..c534bdd09 100644 --- a/.github/workflows/configurations.yaml +++ b/.github/workflows/configurations.yaml @@ -52,7 +52,7 @@ jobs: for CONFIG_FILE in $(find configurations -mindepth 2 -maxdepth 2 -type f -name "*.yaml"); do FILENAME=$(basename -s ".yaml" "${CONFIG_FILE@L}") case "${FILENAME}" in - alerts | dashboards | healthchecks | metrics | services | slos) + alerts | dashboards | uptimechecks | metrics | services | slos) ;; *) echo "Unknown file ${CONFIG_FILE}" 1>&2 diff --git a/configurations/microservice-demo/.gitignore b/configurations/microservice-demo/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/configurations/test/dashboards.yaml b/configurations/test/dashboards.yaml index 7cdd56085..3d3f9cc5a 100644 --- a/configurations/test/dashboards.yaml +++ b/configurations/test/dashboards.yaml @@ -25,7 +25,7 @@ dashboards: - time-series: filter: query: "metric.type=\"compute.googleapis.com/instance/cpu/usage_time\" resource.type=\"gce_instance\"" - alignment: ALIGN_PERCENTILE_99 + aligner: ALIGN_PERCENTILE_99 unit-override: "cpu" min-alignment-period: "60s" diff --git a/configurations/test/healthchecks.yaml b/configurations/test/uptimechecks.yaml similarity index 100% rename from configurations/test/healthchecks.yaml rename to configurations/test/uptimechecks.yaml diff --git a/docs/README.md b/docs/README.md index db3fbe4ce..08b05d9b5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,9 +3,9 @@ ## Overview Cloud Ops Sandbox (**Sandbox** further in this document) lets you to trial -various services and instruments in the Google [Cloud Operations -suite][cloud-ops] of services by using a non-trivial microservice application -deployed on Kubernetes like [Online Boutique][ob]. +various services and instruments in the Google +[Cloud Operations suite][cloud-ops] of services by using a non-trivial +microservices application deployed on Kubernetes like [Online Boutique][ob]. With Sandbox you can experiment with existing tools to troubleshoot operational problems in a sandboxed environment or to have hands-on experience with creating new observability instruments. @@ -48,8 +48,8 @@ Or, by executing the following commands in your local environment: ```terminal git clone https://github.com/GoogleCloudPlatform/cloud-ops-sandbox -gcloud auth application-default loging -cloud-ops-sandbox/provisioning/sandboxctl -p PROJECT_ID +gcloud auth application-default login +cloud-ops-sandbox/provisioning/sandboxctl create -p PROJECT_ID ``` where `PROJECT_ID` identifies the Google Cloud project where you want to @@ -148,17 +148,17 @@ pricing [calculator]. [1]: https://cloud.google.com/resource-manager/docs/creating-managing-projects#console_1 [2]: https://console.cloud.google.com/?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fgooglecloudplatform%2Fcloud-ops-sandbox&cloudshell_git_branch=0.9.2&cloudshell_tutorial=docs/walkthrough.md -[cloud-ops]: < -[ob]: < -[ob-architecture]: < -[ob-screens]: < -[log-explorer]: < -[uptime-checks]: < -[custom-dashboards]: ")) -[slo-services]: -[gke_pricing]: -[asm_pricing]: -[ops_pricing]: -[estimate]: -[calculator]: -[gke]: +[cloud-ops]: http://cloud.google.com/products/operations +[ob]: https://github.com/GoogleCloudPlatform/microservices-demo +[ob-architecture]: https://github.com/GoogleCloudPlatform/microservices-demo#architecture +[ob-screens]: https://github.com/GoogleCloudPlatform/microservices-demo#screenshots +[log-explorer]: https://pantheon.corp.google.com/logs/query +[uptime-checks]: https://pantheon.corp.google.com/monitoring/uptime +[custom-dashboards]: https://console.cloud.google.com/monitoring/dashboards?pageState=("dashboards":("t":"Custom>")) +[slo-services]: https://console.cloud.google.com/monitoring/services +[gke_pricing]: https://cloud.google.com/gke/pricing +[asm_pricing]: https://cloud.google.com/service-mesh/pricing +[ops_pricing]: https://cloud.google.com/stackdriver/pricing +[estimate]: https://cloud.google.com/stackdriver/estimating-bills +[calculator]: https://cloud.google.com/products/calculator +[gke]: https://console.cloud.google.com/kubernetes/ diff --git a/provisioning/kustomize/online-boutique/kustomization.yaml b/provisioning/kustomize/microservice-demo/kustomization.yaml similarity index 96% rename from provisioning/kustomize/online-boutique/kustomization.yaml rename to provisioning/kustomize/microservice-demo/kustomization.yaml index 31e92231d..8873fe4e2 100644 --- a/provisioning/kustomize/online-boutique/kustomization.yaml +++ b/provisioning/kustomize/microservice-demo/kustomization.yaml @@ -18,6 +18,6 @@ resources: - github.com/GoogleCloudPlatform/microservices-demo/kustomize/base?version=v0.6.0 components: - github.com/GoogleCloudPlatform/microservices-demo/kustomize/components/google-cloud-operations?version=v0.6.0 -#!DO NOT REMOVE FOLLOWING COMMENTED LINES! +# !!DO NOT REMOVE THE COMMENTED LINES!! #- github.com/GoogleCloudPlatform/microservices-demo/kustomize/components/service-mesh-istio?version=v0.6.0 #- github.com/GoogleCloudPlatform/microservices-demo/kustomize/components/without-loadgenerator?version=v0.6.0 diff --git a/provisioning/sandboxctl b/provisioning/sandboxctl index 5546b50d3..1086b7548 100755 --- a/provisioning/sandboxctl +++ b/provisioning/sandboxctl @@ -29,12 +29,6 @@ else fi SCRIPT_NAME="${0##*/}"; readonly SCRIPT_NAME -SCRIPT_DIR="$(realpath "$(dirname "${0}")")"; readonly SCRIPT_DIR -SANDBOX_VERSION="$(tr -d '\n' < "${SCRIPT_DIR}/version.txt")"; readonly SANDBOX_VERSION -SANDBOX_SESSION="${SANDBOX_SESSION:-$(python3 -c 'import uuid; print(uuid.uuid4())')}"; readonly SANDBOX_SESSION -CLOUD_OPS_SANDBOX_DISABLE_TELEMETRY="${CLOUD_OPS_SANDBOX_DISABLE_TELEMETRY:-}"; readonly CLOUD_OPS_SANDBOX_DISABLE_TELEMETRY -AGCLOUD="" -ATERRAFORM="" main() { if [[ "${*}" = '' ]]; then @@ -168,6 +162,10 @@ help_subcommand() { } init() { + SCRIPT_DIR="$(realpath "$(dirname "${0}")")"; readonly SCRIPT_DIR + SANDBOX_VERSION="$(tr -d '\n' < "${SCRIPT_DIR}/version.txt")"; readonly SANDBOX_VERSION + SANDBOX_SESSION="${SANDBOX_SESSION:-$(python3 -c 'import uuid; print(uuid.uuid4())')}"; readonly SANDBOX_SESSION + CLOUD_OPS_SANDBOX_DISABLE_TELEMETRY="${CLOUD_OPS_SANDBOX_DISABLE_TELEMETRY:-}"; readonly CLOUD_OPS_SANDBOX_DISABLE_TELEMETRY ATERRAFORM="$(which terraform || true)"; readonly ATERRAFORM; AGCLOUD="$(which gcloud || true)"; readonly AGCLOUD; PROJECT_ID="" @@ -179,6 +177,7 @@ init() { VERBOSE=0 CLOUDOPS_SANDBOX_POOL_CFG=${CLOUDOPS_SANDBOX_POOL_CFG:-} TF_FILE_LOCATION="$(mktemp).tfvars"; readonly TF_FILE_LOCATION + MICROSERVICE_DEMO_KUSTOMIZE="kustomize/microservice-demo" } ### Support functions ### @@ -211,7 +210,7 @@ fatal_with_usage() { } version_message() { - echo "${VERSION}" + echo "${SANDBOX_VERSION}" } usage() { @@ -474,7 +473,7 @@ configure_terraform_input_vars() { state_bucket_name = "${TF_BUCKET_NAME}" state_prefix = "${TERRAFORM_PREFIX}" gcp_project_id = "${PROJECT_ID}" -filepath_manifest = "${SCRIPT_DIR}/kustomize/online-boutique/" +filepath_manifest = "${SCRIPT_DIR}/${MICROSERVICE_DEMO_KUSTOMIZE}/" EOF ) @@ -496,7 +495,7 @@ EOF } configure_kustomization() { - KUSTOMIZE_FILE="${SCRIPT_DIR}/kustomize/online-boutique/kustomization.yaml"; readonly KUSTOMIZE_FILE + KUSTOMIZE_FILE="${SCRIPT_DIR}/${MICROSERVICE_DEMO_KUSTOMIZE}/kustomization.yaml"; readonly KUSTOMIZE_FILE cp "${KUSTOMIZE_FILE}" "${KUSTOMIZE_FILE}.origin" > /dev/null local SED_EXPRESSION; SED_EXPRESSION="" diff --git a/provisioning/schemas/configuration/dashboards.json b/provisioning/schemas/configuration/dashboards.json index 52979216e..9dc540489 100644 --- a/provisioning/schemas/configuration/dashboards.json +++ b/provisioning/schemas/configuration/dashboards.json @@ -103,7 +103,7 @@ "type": "string", "description": "Identifies the metric types, resources, and projects to query" }, - "alignment": { + "aligner": { "enum": [ "ALIGN_NONE", "ALIGN_DELTA", diff --git a/provisioning/schemas/configuration/healthchecks.json b/provisioning/schemas/configuration/uptimechecks.json similarity index 100% rename from provisioning/schemas/configuration/healthchecks.json rename to provisioning/schemas/configuration/uptimechecks.json diff --git a/provisioning/terraform/alerts.tf b/provisioning/terraform/alerts.tf new file mode 100644 index 000000000..b5f43c8d5 --- /dev/null +++ b/provisioning/terraform/alerts.tf @@ -0,0 +1,60 @@ +# Copyright 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. + +locals { + alerts_config = yamldecode(templatefile("${locals.validated_configuration_path}/alerts.yaml", local.template_vars)) + alerts = { + for alert in local.alerts_config.alerts : alert.name => alert + } + channels = { + for channel in local.alerts_config.channels : channel.name => channel + } +} + +resource "google_monitoring_notification_channel" "channels" { + for_each = local.channels + display_name = each.value.display-name + type = each.value.type + labels = each.value.labels +} + +resource "google_monitoring_alert_policy" "alerts" { + for_each = local.alerts + display_name = each.value.display_name + combiner = each.value.combiner + documentation { + content = each.value.documentation != null ? each.value.documentation : "" + mime_type = "text/markdown" + } + notification_channels = (each.value.notification-channels != null ? + each.value.notification-channels : [] + ) + dynamic "conditions" { + for_each = each.value.conditions + content { + filter = each.value.condition.filter + threshold_value = each.value.condition.threshold + comparison = each.value.condition.comparison + duration = each.value.condition.duration + } + } + # only threshold condition is supported + condition_threshold { + filter = each.value.condition.filter + threshold_value = each.value.condition.threshold + comparison = each.value.condition.comparison + duration = each.value.condition.duration + } + depends_on = [google_monitoring_slo.service_slos, google_monitoring_uptime_check_config.uptime_checks] +} diff --git a/provisioning/terraform/dashboards.tf b/provisioning/terraform/dashboards.tf new file mode 100644 index 000000000..9732f4368 --- /dev/null +++ b/provisioning/terraform/dashboards.tf @@ -0,0 +1,25 @@ +# Copyright 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. + +locals { + dashboards_config = yamldecode(templatefile("${locals.validated_configuration_path}/dashboards.yaml", local.template_vars)) + dashboards = { + for dashboard in local.dashboards_config.dashboards : dashboard.name => dashboard + } +} + +resource "google_monitoring_dashboard" "dashboards" { + for_each = local.dashboards + dashboard_json = templatefile("dashboards.tftpl", merge(each.value, local.template_vars)) +} diff --git a/provisioning/terraform/dashboards.tftpl b/provisioning/terraform/dashboards.tftpl new file mode 100644 index 000000000..d9297bb11 --- /dev/null +++ b/provisioning/terraform/dashboards.tftpl @@ -0,0 +1,38 @@ +{"displayName": "${display-name}", + "gridLayout": { + "columns": "2", + "widgets": ${jsonencode([ + for widget in widgets: { + "title": "${widget.title}", + "xyChart": { + "xAxis": { + "label": "${widget.x-axis-label}", + "scale": "LINEAR" + }, + "yAxis": { + "label": "${widget.y-axis-label}", + "scale": "LINEAR" + }, + "chartOptions": { + "mode": "COLOR" + }, + "dataSets": [ + for ds in widget.datasets: { + "timeSeriesQuery": { + "timeSeriesFilter": { + "filter": "${ds.time-series.filter.query}", + "aggregation": { + "perSeriesAligner": "${ds.time_series.filter.aggregation.aligner}" + } + }, + "unitOverride": "${ds.time_series.unit-override}" + }, + "plotType": "LINE", + "minAlignmentPeriod": "${ds.min-alignment-period}" + } + ] + } + } + ])} + } +} diff --git a/provisioning/terraform/locals.tf b/provisioning/terraform/locals.tf new file mode 100644 index 000000000..4964a2952 --- /dev/null +++ b/provisioning/terraform/locals.tf @@ -0,0 +1,25 @@ +# Copyright 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. + +locals { + validated_configuration_path = (endswith(var.configuration_path, "/") + ? substr(var.configuration_path, 0, -1) : var.configuration_path + ) + template_vars = { + project_id = var.gcp_project_id + configuration_id = basename(local.validated_configuration_path) + # allow using prefix for terraform state as suffix in the resource names + state_suffix = var.state_prefix + } +} diff --git a/provisioning/terraform/microservices-demo/README.md b/provisioning/terraform/microservices-demo/README.md new file mode 100644 index 000000000..2abe2f9a9 --- /dev/null +++ b/provisioning/terraform/microservices-demo/README.md @@ -0,0 +1,59 @@ +# Module microservices-demo + +This is a terraform module for provisioning infrastructure for and installation +of the [Online Boutique][ob] microservices demo application. +The deployed version of Online Boutique uses a non-default setup that allows: + +* to run the microservices using Anthos Service Mesh (ASM) +* to customize the configuration of the node workpool +* to opt-out use of the Oline Boutique load generator + +[ob]: https://github.com/GoogleCloudPlatform/microservices-demo + +## Input parameters + +| Name | Required | Default value | Description | +| --- | --- | --- | --- | +| gcp_project_id | Yes | None | The GCP project ID to use in this module's resources | +| gke_cluster_name | No | "cloud-ops-sandbox" | Name of the GKE standard cluster hosting Online Boutique | +| gke_cluster_location | No | "us-central1" | Supports regions and zones. When the location is a zone, the zone cluster is provisioned. | +| gke_node_pool | No | | See [Node pool configuration](#node-pool-configuration) for the details. | +| enable_asm | No | true | Controls the provisioning and configuration of ASM for the Online Boutique microservices. | +| asm_channel | No | stable | If `enable_asm` is `true`, allows to define the release channel (version) of ASM. | +| name_suffix | No | Empty string | Custom suffix allowing provisioning multiple copies of the resource within the same GCP project. | +| sandbox_version | No | "unknown" | The version of the Cloud Ops Sandbox that provisions the module. Use /provisioning/version.txt for the version source. | + +## Output variables + +| Name | Description | +| --- | --- | +| frontend_external_ip | A public IP that is used to access the Web front-end application of the Online Boutique. | + +## Node pool configuration + +Some environments have resource constraints. +The `gke_node_pool` configuration allows to customize VM instances used in the GKE node pool. +The configuration is defined as a dictionary following this schema: + +```json +{ + "initial_node_count": number, + "labels": map(string), + "machine_type": string, + "autoscaling": { + "max_node_count": number, + "min_node_count": number + } +} +``` + +The default configuration uses the default node pool values: + +```json +{ + "initial_node_count": 4, + "labels": {}, + "machine_type": "e2-standard-4", + "autoscaling": null +} +``` diff --git a/provisioning/terraform/asm.tf b/provisioning/terraform/microservices-demo/asm.tf similarity index 100% rename from provisioning/terraform/asm.tf rename to provisioning/terraform/microservices-demo/asm.tf diff --git a/provisioning/terraform/gke.tf b/provisioning/terraform/microservices-demo/gke.tf similarity index 96% rename from provisioning/terraform/gke.tf rename to provisioning/terraform/microservices-demo/gke.tf index acc062b16..1f00abc85 100644 --- a/provisioning/terraform/gke.tf +++ b/provisioning/terraform/microservices-demo/gke.tf @@ -31,7 +31,7 @@ resource "google_container_cluster" "sandbox" { resource_labels = local.resource_labels - description = "Provisioned for Cloud Ops Sandbox version ${file("../version.txt")}" + description = "Provisioned for Cloud Ops Sandbox version ${var.sandbox_version}" # Enables Workload Identity workload_identity_config { diff --git a/provisioning/terraform/microservices-demo/google.tf b/provisioning/terraform/microservices-demo/google.tf new file mode 100644 index 000000000..fb9576d24 --- /dev/null +++ b/provisioning/terraform/microservices-demo/google.tf @@ -0,0 +1,42 @@ +# Copyright 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. + +# Enable Google Cloud APIs +locals { + base_apis = [ + "clouderrorreporting.googleapis.com", + "cloudprofiler.googleapis.com", + "container.googleapis.com", /* compute.googleapis.com is provisioned as a dependency */ + ] + mesh_apis = [ + "mesh.googleapis.com", + # "meshtelemetry.googleapis.com", + "cloudresourcemanager.googleapis.com", + ] +} + +# Enable Google Cloud APIs +module "enable_google_apis" { + source = "terraform-google-modules/project-factory/google//modules/project_services" + version = "~> 14.1.0" + + project_id = var.gcp_project_id + disable_services_on_destroy = false + + activate_apis = concat(local.base_apis, var.enable_asm ? local.mesh_apis : []) +} + +data "google_project" "info" { + project_id = var.gcp_project_id +} diff --git a/provisioning/terraform/online-boutique.tf b/provisioning/terraform/microservices-demo/online-boutique.tf similarity index 100% rename from provisioning/terraform/online-boutique.tf rename to provisioning/terraform/microservices-demo/online-boutique.tf diff --git a/provisioning/terraform/microservices-demo/output.tf b/provisioning/terraform/microservices-demo/output.tf new file mode 100644 index 000000000..11aa702b9 --- /dev/null +++ b/provisioning/terraform/microservices-demo/output.tf @@ -0,0 +1,17 @@ +# Copyright 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. + +output "frontend_external_ip" { + value = length(data.kubernetes_service.frontend_external_service.status) > 0 ? data.kubernetes_service.frontend_external_service.status[0].load_balancer[0].ingress[0].ip : null +} diff --git a/provisioning/terraform/microservices-demo/providers.tf b/provisioning/terraform/microservices-demo/providers.tf new file mode 100644 index 000000000..f511b97f6 --- /dev/null +++ b/provisioning/terraform/microservices-demo/providers.tf @@ -0,0 +1,60 @@ +# Copyright 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. + + +# We use gcs as our backend, so the state file will be stored +# in a storage bucket. Since the bucket must preexists, we will create +# the project and bucket outside Terraform. Also since the configuration +# of bucket can't be a variable, we create an empty config and modify it +# in the data section. + +terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "~> 4.54.0" + } + google-beta = { + source = "hashicorp/google-beta" + version = "4.54.0" + } + null = { + source = "hashicorp/null" + version = "~>3.2.1" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~>2.18.1" + } + } +} + +provider "google" { + project = var.gcp_project_id +} + +# Retrieve an access token as the Terraform runner +data "google_client_config" "default" {} + +provider "google-beta" { + project = var.gcp_project_id +} + +provider "kubernetes" { + host = "https://${resource.google_container_cluster.sandbox.endpoint}" + token = data.google_client_config.default.access_token + cluster_ca_certificate = base64decode( + resource.google_container_cluster.sandbox.master_auth[0].cluster_ca_certificate, + ) +} diff --git a/provisioning/terraform/scripts/install_asm.sh b/provisioning/terraform/microservices-demo/scripts/install_asm.sh similarity index 100% rename from provisioning/terraform/scripts/install_asm.sh rename to provisioning/terraform/microservices-demo/scripts/install_asm.sh diff --git a/provisioning/terraform/microservices-demo/variables.tf b/provisioning/terraform/microservices-demo/variables.tf new file mode 100644 index 000000000..336ea4920 --- /dev/null +++ b/provisioning/terraform/microservices-demo/variables.tf @@ -0,0 +1,86 @@ +# Copyright 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. + +# Required input variables +variable "gcp_project_id" { + type = string + description = "The GCP project ID to apply this config to" +} + +# Optional input variables +variable "gke_cluster_name" { + type = string + description = "Name given to the new GKE cluster" + default = "cloud-ops-sandbox" +} + +variable "gke_cluster_location" { + type = string + description = "Region or zone of the new GKE cluster" + default = "us-central1" +} + +# Default values for node pool support connecting the cluster to ASM +# https://cloud.google.com/service-mesh/docs/unified-install/anthos-service-mesh-prerequisites#cluster_requirements +variable "gke_node_pool" { + type = object({ + initial_node_count = number + labels = map(string) + machine_type = string + + autoscaling = object({ + max_node_count = number + min_node_count = number + }) + }) + description = "Initial settings and autoscale configuration of the GKE cluster's default node pool" + default = { + initial_node_count = 4 + labels = {} + machine_type = "e2-standard-4" + autoscaling = null + } +} + +variable "enable_asm" { + type = bool + description = "If true, installs Anthos Service Mesh (managed version of Istio) on the GKE cluster" + default = true +} + +variable "asm_channel" { + type = string + description = "Defines one of the following managed ASM channels/revisions: 'rapid', 'regular' or stable'" + default = "stable" + validation { + condition = can(regex("^(rapid|regular|stable)$", var.asm_channel)) + error_message = "ASM channel/revision can be only 'rapid', 'regular' or stable'" + } +} + +variable "sandbox_version" { + type = string + description = "Version of Cloud Ops Sandbox that provisions Online Boutique" + default = "unknown" +} + +variable "name_suffix" { + type = string + description = "Custom suffix to allow provisioning multiple copies of the resource within the same GCP project" + validation { + condition = can(regex("^$|^[\\w_-]{1,50}$", var.name_suffix)) + error_message = "The value should be a valid resource name with max length of 50 symbols" + } + default = "" +} diff --git a/provisioning/terraform/monitoring/variables.tf b/provisioning/terraform/monitoring/variables.tf index 46051fadb..5b01bc892 100644 --- a/provisioning/terraform/monitoring/variables.tf +++ b/provisioning/terraform/monitoring/variables.tf @@ -65,7 +65,7 @@ variable "name_suffix" { description = "Custom suffix to allow provisioning multiple copies of the resource within the same GCP project" validation { condition = can(regex("^$|^[\\w_-]{1,100}$", var.name_suffix)) - error_message = "The value should be a valid email address" + error_message = "The value should be a valid resource name" } default = "" } diff --git a/provisioning/terraform/output.tf b/provisioning/terraform/output.tf index 11aa702b9..5dcaa02d4 100644 --- a/provisioning/terraform/output.tf +++ b/provisioning/terraform/output.tf @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -output "frontend_external_ip" { - value = length(data.kubernetes_service.frontend_external_service.status) > 0 ? data.kubernetes_service.frontend_external_service.status[0].load_balancer[0].ingress[0].ip : null +output "microservice-demo-frontend-ip" { + value = (length(module.microservice_demo.frontend-ip) > 0 + ? module.microservice_demo.frontend-ip : "") } diff --git a/provisioning/terraform/project.tf b/provisioning/terraform/project.tf index fb9576d24..c9758cc94 100644 --- a/provisioning/terraform/project.tf +++ b/provisioning/terraform/project.tf @@ -19,11 +19,6 @@ locals { "cloudprofiler.googleapis.com", "container.googleapis.com", /* compute.googleapis.com is provisioned as a dependency */ ] - mesh_apis = [ - "mesh.googleapis.com", - # "meshtelemetry.googleapis.com", - "cloudresourcemanager.googleapis.com", - ] } # Enable Google Cloud APIs @@ -34,7 +29,7 @@ module "enable_google_apis" { project_id = var.gcp_project_id disable_services_on_destroy = false - activate_apis = concat(local.base_apis, var.enable_asm ? local.mesh_apis : []) + activate_apis = base_apis } data "google_project" "info" { diff --git a/provisioning/terraform/providers.tf b/provisioning/terraform/providers.tf index 4b8196acb..21cf14ba4 100644 --- a/provisioning/terraform/providers.tf +++ b/provisioning/terraform/providers.tf @@ -36,10 +36,6 @@ terraform { source = "hashicorp/null" version = "~>3.2.1" } - kubernetes = { - source = "hashicorp/kubernetes" - version = "~>2.18.1" - } } backend "gcs" {} } @@ -57,17 +53,6 @@ provider "google" { project = var.gcp_project_id } -# Retrieve an access token as the Terraform runner -data "google_client_config" "default" {} - provider "google-beta" { project = var.gcp_project_id } - -provider "kubernetes" { - host = "https://${resource.google_container_cluster.sandbox.endpoint}" - token = data.google_client_config.default.access_token - cluster_ca_certificate = base64decode( - resource.google_container_cluster.sandbox.master_auth[0].cluster_ca_certificate, - ) -} diff --git a/provisioning/terraform/uptimechecks.tf b/provisioning/terraform/uptimechecks.tf new file mode 100644 index 000000000..574236313 --- /dev/null +++ b/provisioning/terraform/uptimechecks.tf @@ -0,0 +1,44 @@ +# Copyright 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 { + ut_checks_config = yamldecode(templatefile("${var.validated_configuration_path}/uptimechecks.yaml", local.template_vars)) + ut_checks = { + for c in local.ut_checks_config.checks : c.name => c + } +} + +resource "google_monitoring_uptime_check_config" "uptime_checks" { + for_each = local.ut_checks + display_name = each.value.display-name + timeout = each.value.timeout + period = try(each.value.period, "300s") + dynamic "content_matchers" { + for_each = can(each.value.content_matcher) ? toset([1]) : toset([]) + content { + content = each.value.content_matcher.content + matcher = try(each.value.content_matcher.matcher, "CONTAINS_STRING") + } + } + http_check { + path = startswith(each.value.http_check.path, "/") ? each.value.http_check.path : "/${each.value.http_check.path}" + } + dynamic "monitored_resource" { + for_each = can(each.value.resource) ? toset([1]) : toset([]) + content { + type = each.value.resource.type + labels = each.value.resource.labels + } + } +} diff --git a/provisioning/terraform/variables.tf b/provisioning/terraform/variables.tf index bfbe19e0b..1593e5216 100644 --- a/provisioning/terraform/variables.tf +++ b/provisioning/terraform/variables.tf @@ -1,18 +1,16 @@ -/** - * Copyright 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. - */ +# Copyright 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. # Required input variables variable "gcp_project_id" { @@ -25,60 +23,12 @@ variable "state_bucket_name" { description = "The GCS bucket URL where Terraform stores the state" } -# Optional input variables -variable "asm_channel" { +variable "configuration_path" { type = string - description = "Defines one of the following managed ASM channels/revisions: 'rapid', 'regular' or stable'" - default = "stable" + description = "Relative path to Cloud Ops Sandbox configuration" validation { - condition = can(regex("^(rapid|regular|stable)$", var.asm_channel)) - error_message = "ASM channel/revision can be only 'rapid', 'regular' or stable'" - } -} - -variable "enable_asm" { - type = bool - description = "If true, installs Anthos Service Mesh (managed version of Istio) on the GKE cluster" - default = false -} - -variable "filepath_manifest" { - type = string - description = "Path to Kubernetes resources, written using Kustomize" - default = "../kustomize/online-boutique/" -} - -variable "gke_cluster_name" { - type = string - description = "Name given to the new GKE cluster" - default = "cloud-ops-sandbox" -} - -variable "gke_cluster_location" { - type = string - description = "Region or zone of the new GKE cluster" - default = "us-central1" -} - -# Default values for node pool support connecting the cluster to ASM -# https://cloud.google.com/service-mesh/docs/unified-install/anthos-service-mesh-prerequisites#cluster_requirements -variable "gke_node_pool" { - type = object({ - initial_node_count = number - labels = map(string) - machine_type = string - - autoscaling = object({ - max_node_count = number - min_node_count = number - }) - }) - description = "Initial settings and autoscale configuration of the GKE cluster's default node pool" - default = { - initial_node_count = 4 - labels = {} - machine_type = "e2-standard-4" - autoscaling = null + condition = can(regex("^configurations\\/((?!\\.\\.).)+$", var.configuration_path)) + error_message = "Path must start with 'configurations/' and cannot include parent redirects i.e. '..'" } } diff --git a/provisioning/version.txt b/provisioning/version.txt index f76f91317..6054db199 100644 --- a/provisioning/version.txt +++ b/provisioning/version.txt @@ -1 +1 @@ -0.9.2 \ No newline at end of file +0.10.0-dev \ No newline at end of file