Merge branch 'master' into lcaggio/fix-20221123

This commit is contained in:
lcaggio 2022-11-24 16:07:33 +01:00 committed by GitHub
commit d1cc0519d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
373 changed files with 20380 additions and 5610 deletions

View File

@ -11,3 +11,16 @@
# 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.
'on:blueprints':
- blueprints/**/*
'on:documentation':
- '**/*.md'
- assets/**/*
- tests/**/*
'on:FAST':
- fast/**/*
'on:modules':
- modules/**/*
'on:tools':
- tools/**/*

View File

@ -12,23 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import pytest
name: "Build and push the Squid container image"
on:
workflow_dispatch:
push:
branches:
- master
paths:
- 'modules/cloud-config-container/squid/docker/**'
@pytest.fixture
def resources(plan_runner):
_, resources = plan_runner()
return resources
def test_resource_count(resources):
"Test number of resources created."
assert len(resources) == 3
def test_iam(resources):
"Test IAM binding resources."
bindings = [r['values'] for r in resources if r['type']
== 'google_cloudfunctions_function_iam_binding']
assert len(bindings) == 1
assert bindings[0]['role'] == 'roles/cloudfunctions.invoker'
jobs:
build-push-squid-container-image:
uses: ./.github/workflows/container-image.yml
with:
image_name: fabric-squid
docker_context: modules/cloud-config-container/squid/docker

View File

@ -0,0 +1,30 @@
# Copyright 2022 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.
name: "Build and push the strongSwan container image"
on:
workflow_dispatch:
push:
branches:
- master
paths:
- 'modules/cloud-config-container/onprem/docker-images/strongswan/**'
jobs:
build-push-strongswan-container-image:
uses: ./.github/workflows/container-image.yml
with:
image_name: fabric-strongswan
docker_context: modules/cloud-config-container/onprem/docker-images/strongswan

View File

@ -0,0 +1,30 @@
# Copyright 2022 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.
name: "Build and push the Toolbox container image"
on:
workflow_dispatch:
push:
branches:
- master
paths:
- 'modules/cloud-config-container/onprem/docker-images/toolbox/**'
jobs:
build-push-toolbox-container-image:
uses: ./.github/workflows/container-image.yml
with:
image_name: fabric-toolbox
docker_context: modules/cloud-config-container/onprem/docker-images/toolbox

61
.github/workflows/container-image.yml vendored Normal file
View File

@ -0,0 +1,61 @@
# Copyright 2022 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.
name: "Build and push a generic container image"
on:
workflow_call:
inputs:
image_name:
required: true
type: string
docker_context:
required: true
type: string
permissions:
packages: write
env:
REGISTRY: ghcr.io
jobs:
build-push-generic-container-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%Y%m%d')"
- name: Normalise image name
run: |
echo IMAGE_NAME=$(echo '${{ github.repository_owner }}/${{ inputs.image_name }}' | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
- name: Login to GHCR
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v3
with:
context: ${{ inputs.docker_context }}
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.date.outputs.date }}

30
.github/workflows/labeler.yml vendored Normal file
View File

@ -0,0 +1,30 @@
# Copyright 2022 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.
name: "Label Pull Requests"
on:
pull_request_target:
jobs:
triage:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v4
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
sync-labels: true

5
.gitignore vendored
View File

@ -37,3 +37,8 @@ examples/cloud-operations/adfs/ansible/gssh.sh
examples/cloud-operations/multi-cluster-mesh-gke-fleet-api/ansible/vars.yaml
examples/cloud-operations/multi-cluster-mesh-gke-fleet-api/ansible/gssh.sh
blueprints/cloud-operations/network-dashboard/cloud-function.zip
blueprints/cloud-operations/apigee/bundle-export.zip
blueprints/cloud-operations/apigee/bundle-gcs2bq.zip
blueprints/cloud-operations/apigee/apiproxy.zip
blueprints/cloud-operations/apigee/create-datastore.sh
blueprints/cloud-operations/apigee/deploy-apiproxy.sh

View File

@ -5,15 +5,22 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
<!-- None < 2022-09-09 18:02:15+00:00 -->
- [[#913](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/913)] Adding support for PSA ranges, starting with Redis instances. ([aurelienlegrand](https://github.com/aurelienlegrand)) <!-- 2022-11-09 11:07:41+00:00 -->
- [[#939](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/939)] Temporarily duplicate cloud armor example ([ludoo](https://github.com/ludoo)) <!-- 2022-11-02 09:36:04+00:00 -->
### BLUEPRINTS
- [[#1003](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1003)] Normalize prefix handling in blueprints ([kunzese](https://github.com/kunzese)) <!-- 2022-11-23 10:09:00+00:00 -->
- [[#995](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/995)] Push container images to GitHub instead of Google Container Registry ([kunzese](https://github.com/kunzese)) <!-- 2022-11-21 14:53:52+00:00 -->
- [[#984](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/984)] **incompatible change:** Apigee module and blueprint ([apichick](https://github.com/apichick)) <!-- 2022-11-17 16:20:27+00:00 -->
- [[#980](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/980)] Have Squid log to /dev/stdout to stream logs to Cloud Logging ([kunzese](https://github.com/kunzese)) <!-- 2022-11-16 13:41:26+00:00 -->
- [[#929](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/929)] Updated list of enabled APIs for network dashboard ([maunope](https://github.com/maunope)) <!-- 2022-11-16 09:27:44+00:00 -->
- [[#968](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/968)] Enforce PROXY protocol in `filtering-proxy-psc` blueprint ([kunzese](https://github.com/kunzese)) <!-- 2022-11-15 07:18:58+00:00 -->
- [[#962](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/962)] Add filtering-proxy-psc blueprint ([kunzese](https://github.com/kunzese)) <!-- 2022-11-11 10:24:38+00:00 -->
- [[#913](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/913)] Adding support for PSA ranges, starting with Redis instances. ([aurelienlegrand](https://github.com/aurelienlegrand)) <!-- 2022-11-09 11:07:41+00:00 -->
- [[#952](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/952)] Remove duplicate GLB+CA blueprint folder ([ludoo](https://github.com/ludoo)) <!-- 2022-11-07 12:46:22+00:00 -->
- [[#949](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/949)] **incompatible change:** Refactor VPC firewall module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) <!-- 2022-11-04 12:56:08+00:00 -->
- [[#945](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/945)] Org policy factory ([juliocc](https://github.com/juliocc)) <!-- 2022-11-03 11:30:58+00:00 -->
- [[#941](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/941)] **incompatible change:** Refactor ILB module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) <!-- 2022-11-02 17:05:21+00:00 -->
- [[#939](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/939)] Temporarily duplicate cloud armor example ([ludoo](https://github.com/ludoo)) <!-- 2022-11-02 09:36:04+00:00 -->
- [[#936](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/936)] Enable org policy service and add README notice to modules ([ludoo](https://github.com/ludoo)) <!-- 2022-11-01 13:25:08+00:00 -->
- [[#931](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/931)] **incompatible change:** Refactor compute-mig module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) <!-- 2022-11-01 08:39:00+00:00 -->
- [[#932](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/932)] feat(project-factory): introduce additive iam bindings to project-fac… ([Malet](https://github.com/Malet)) <!-- 2022-10-31 17:24:25+00:00 -->
@ -53,6 +60,10 @@ All notable changes to this project will be documented in this file.
### DOCUMENTATION
- [[#1007](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1007)] fast README, one line fix: 00-cicd stage got moved to extras/ ([skalolazka](https://github.com/skalolazka)) <!-- 2022-11-23 15:31:01+00:00 -->
- [[#1003](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1003)] Normalize prefix handling in blueprints ([kunzese](https://github.com/kunzese)) <!-- 2022-11-23 10:09:00+00:00 -->
- [[#987](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/987)] Add tests to factory examples ([juliocc](https://github.com/juliocc)) <!-- 2022-11-18 17:01:41+00:00 -->
- [[#972](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/972)] Add note about TF_PLUGIN_CACHE_DIR ([wiktorn](https://github.com/wiktorn)) <!-- 2022-11-14 10:21:37+00:00 -->
- [[#961](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/961)] Remove extra file from root ([ludoo](https://github.com/ludoo)) <!-- 2022-11-09 07:53:11+00:00 -->
- [[#943](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/943)] Update bootstrap README.md with unique project id requirements ([KPRepos](https://github.com/KPRepos)) <!-- 2022-11-03 22:22:22+00:00 -->
- [[#937](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/937)] Fix typos in blueprints README.md ([kumar-dhanagopal](https://github.com/kumar-dhanagopal)) <!-- 2022-11-02 07:39:26+00:00 -->
@ -64,6 +75,9 @@ All notable changes to this project will be documented in this file.
### FAST
- [[#1007](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1007)] fast README, one line fix: 00-cicd stage got moved to extras/ ([skalolazka](https://github.com/skalolazka)) <!-- 2022-11-23 15:31:01+00:00 -->
- [[#976](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/976)] FAST: fixes to GitHub workflow and 02/net outputs ([ludoo](https://github.com/ludoo)) <!-- 2022-11-15 07:48:32+00:00 -->
- [[#966](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/966)] FAST: improve GitHub workflow, stage 01 output fixes ([ludoo](https://github.com/ludoo)) <!-- 2022-11-11 07:55:58+00:00 -->
- [[#963](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/963)] **incompatible change:** Refactor vps-sc module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) <!-- 2022-11-10 18:34:45+00:00 -->
- [[#956](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/956)] FAST: bootstrap and extra stage CI/CD improvements and fixes ([ludoo](https://github.com/ludoo)) <!-- 2022-11-08 08:38:16+00:00 -->
- [[#949](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/949)] **incompatible change:** Refactor VPC firewall module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) <!-- 2022-11-04 12:56:08+00:00 -->
@ -94,6 +108,25 @@ All notable changes to this project will be documented in this file.
### MODULES
- [[#999](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/999)] Default nodepool creation fix ([astianseb](https://github.com/astianseb)) <!-- 2022-11-22 18:17:58+00:00 -->
- [[#1005](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1005)] Only set partitioned table when sink type is bigquery ([juliocc](https://github.com/juliocc)) <!-- 2022-11-22 16:13:53+00:00 -->
- [[#997](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/997)] Add BigQuery subcriptions to Pubsub module. ([iht](https://github.com/iht)) <!-- 2022-11-21 17:26:52+00:00 -->
- [[#995](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/995)] Push container images to GitHub instead of Google Container Registry ([kunzese](https://github.com/kunzese)) <!-- 2022-11-21 14:53:52+00:00 -->
- [[#994](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/994)] Add schemas to Pubsub topic module. ([iht](https://github.com/iht)) <!-- 2022-11-20 16:56:03+00:00 -->
- [[#979](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/979)] Add network tags support to the organization module ([LucaPrete](https://github.com/LucaPrete)) <!-- 2022-11-18 14:56:29+00:00 -->
- [[#991](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/991)] Allow cross-project backend services in ILB L7 module ([ludoo](https://github.com/ludoo)) <!-- 2022-11-18 08:48:41+00:00 -->
- [[#984](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/984)] **incompatible change:** Apigee module and blueprint ([apichick](https://github.com/apichick)) <!-- 2022-11-17 16:20:27+00:00 -->
- [[#988](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/988)] Merge cloud function v1 and v2 tests ([juliocc](https://github.com/juliocc)) <!-- 2022-11-17 10:18:57+00:00 -->
- [[#965](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/965)] **incompatible change:** Add triggers to Cloud Functions v2 ([wiktorn](https://github.com/wiktorn)) <!-- 2022-11-16 16:00:03+00:00 -->
- [[#980](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/980)] Have Squid log to /dev/stdout to stream logs to Cloud Logging ([kunzese](https://github.com/kunzese)) <!-- 2022-11-16 13:41:26+00:00 -->
- [[#983](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/983)] **incompatible change:** Add support for serverless NEGs to ILB L7 module ([ludoo](https://github.com/ludoo)) <!-- 2022-11-16 13:14:05+00:00 -->
- [[#978](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/978)] Worker pool support for `cloud-function` ([maunope](https://github.com/maunope)) <!-- 2022-11-15 16:38:42+00:00 -->
- [[#977](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/977)] Replace Docker's `gcplogs` driver with the GCP COS logging agent ([kunzese](https://github.com/kunzese)) <!-- 2022-11-15 12:19:52+00:00 -->
- [[#975](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/975)] Add validation for health check port specification to ILB L7 module ([ludoo](https://github.com/ludoo)) <!-- 2022-11-14 15:20:01+00:00 -->
- [[#974](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/974)] **incompatible change:** Refactor net-ilb-l7 module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) <!-- 2022-11-14 13:39:00+00:00 -->
- [[#970](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/970)] Update logging sinks to tf1.3 in resman modules ([juliocc](https://github.com/juliocc)) <!-- 2022-11-12 18:36:59+00:00 -->
- [[#969](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/969)] Update folder and project org policy tests ([juliocc](https://github.com/juliocc)) <!-- 2022-11-11 17:01:26+00:00 -->
- [[#964](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/964)] prefix variable consistency across modules ([skalolazka](https://github.com/skalolazka)) <!-- 2022-11-11 13:38:51+00:00 -->
- [[#963](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/963)] **incompatible change:** Refactor vps-sc module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) <!-- 2022-11-10 18:34:45+00:00 -->
- [[#958](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/958)] Add support for org policy custom constraints ([averbuks](https://github.com/averbuks)) <!-- 2022-11-09 09:07:46+00:00 -->
- [[#960](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/960)] Fix README typo in firewall module ([valeriobponza](https://github.com/valeriobponza)) <!-- 2022-11-08 23:25:34+00:00 -->
@ -147,6 +180,10 @@ All notable changes to this project will be documented in this file.
### TOOLS
- [[#1004](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1004)] Use `actions/labeler` to automatically label pull requests ([kunzese](https://github.com/kunzese)) <!-- 2022-11-22 14:42:47+00:00 -->
- [[#998](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/998)] Add missing `write_package` permission ([kunzese](https://github.com/kunzese)) <!-- 2022-11-22 08:32:42+00:00 -->
- [[#996](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/996)] Fix `repository name must be lowercase` on docker build ([kunzese](https://github.com/kunzese)) <!-- 2022-11-21 16:04:57+00:00 -->
- [[#993](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/993)] Fix variable and output sort check ([juliocc](https://github.com/juliocc)) <!-- 2022-11-21 13:32:56+00:00 -->
- [[#950](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/950)] Add a pytest fixture to convert tfvars to yaml ([ludoo](https://github.com/ludoo)) <!-- 2022-11-04 17:37:24+00:00 -->
- [[#942](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/942)] Bump tftest and improve dns tests ([juliocc](https://github.com/juliocc)) <!-- 2022-11-02 19:38:01+00:00 -->
- [[#919](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/919)] Rename workflow names ([juliocc](https://github.com/juliocc)) <!-- 2022-10-25 15:22:51+00:00 -->

View File

@ -71,6 +71,16 @@ pytest tests/examples
Once everything looks good, add/commit any pending changes then push and open a PR on GitHub. We typically enforce a set of design and style conventions, so please make sure you have familiarized yourself with the following sections and implemented them in your code, to avoid lengthy review cycles.
HINT: if you work on high-latency or low-bandwidth network use `TF_PLUGIN_CACHE_DIR` environment variable to dramatically speed up the tests, for example:
```bash
TF_PLUGIN_CACHE_DIR=/tmp/tfcache pytest tests
```
Or just add into your [terraformrc](https://developer.hashicorp.com/terraform/cli/config/config-file):
```
plugin_cache_dir = "$HOME/.terraform.d/plugin-cache"
```
## Developer's handbook
Over the years we have assembled a specific set of design principles and style conventions that allow for better readability and make understanding and changing code more predictable.
@ -199,7 +209,7 @@ module "project" {
]
}
iam = {
"roles/editor" = [
"roles/editor" = [
"serviceAccount:${module.project.service_accounts.cloud_services}"
]
}
@ -226,7 +236,7 @@ module "project" {
source = "./modules/project"
name = "project-example"
iam = {
"roles/editor" = [
"roles/editor" = [
"serviceAccount:${module.project.service_accounts.cloud_services}"
]
}
@ -531,6 +541,39 @@ locals {
}
```
#### The `prefix` variable
If you would like to use a "prefix" variable for resource names, please keep its definition consistent across all modules:
```hcl
# variables.tf
variable "prefix" {
description = "Optional prefix used for resource names."
type = string
default = null
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty, please use null instead."
}
}
# main.tf
locals {
prefix = var.prefix == null ? "" : "${var.prefix}-"
}
```
For blueprints the prefix is mandatory:
```hcl
variable "prefix" {
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
```
### Interacting with checks, tests and tools
Our modules are designed for composition and live in a monorepo together with several end-to-end blueprints, so it was inevitable that over time we found ways of ensuring that a change does not break consumers.

View File

@ -33,7 +33,7 @@ Currently available modules:
- **networking** - [DNS](./modules/dns), [Cloud Endpoints](./modules/endpoints), [address reservation](./modules/net-address), [NAT](./modules/net-cloudnat), [Global Load Balancer (classic)](./modules/net-glb/), [L4 ILB](./modules/net-ilb), [L7 ILB](./modules/net-ilb-l7), [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC peering](./modules/net-vpc-peering), [VPN dynamic](./modules/net-vpn-dynamic), [HA VPN](./modules/net-vpn-ha), [VPN static](./modules/net-vpn-static), [Service Directory](./modules/service-directory)
- **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [COS container](./modules/cloud-config-container/cos-generic-metadata/) (coredns, mysql, onprem, squid), [GKE cluster](./modules/gke-cluster), [GKE hub](./modules/gke-hub), [GKE nodepool](./modules/gke-nodepool)
- **data** - [BigQuery dataset](./modules/bigquery-dataset), [Bigtable instance](./modules/bigtable-instance), [Cloud SQL instance](./modules/cloudsql-instance), [Data Catalog Policy Tag](./modules/data-catalog-policy-tag), [Datafusion](./modules/datafusion), [GCS](./modules/gcs), [Pub/Sub](./modules/pubsub)
- **development** - [API Gateway](./modules/api-gateway), [Apigee Organization](./modules/apigee-organization), [Apigee X Instance](./modules/apigee-x-instance), [Artifact Registry](./modules/artifact-registry), [Container Registry](./modules/container-registry), [Cloud Source Repository](./modules/source-repository)
- **development** - [API Gateway](./modules/api-gateway), [Apigee](./modules/apigee), [Artifact Registry](./modules/artifact-registry), [Container Registry](./modules/container-registry), [Cloud Source Repository](./modules/source-repository)
- **security** - [Binauthz](./modules/binauthz/), [KMS](./modules/kms), [SecretManager](./modules/secret-manager), [VPC Service Control](./modules/vpc-sc)
- **serverless** - [Cloud Function](./modules/cloud-function), [Cloud Run](./modules/cloud-run)

View File

@ -8,7 +8,7 @@ Currently available blueprints:
- **data solutions** - [GCE and GCS CMEK via centralized Cloud KMS](./data-solutions/cmek-via-centralized-kms), [Cloud Composer version 2 private instance, supporting Shared VPC and external CMEK key](./data-solutions/composer-2), [Cloud SQL instance with multi-region read replicas](./data-solutions/cloudsql-multiregion), [Data Platform](./data-solutions/data-platform-foundations), [Spinning up a foundation data pipeline on Google Cloud using Cloud Storage, Dataflow and BigQuery](./data-solutions/gcs-to-bq-with-least-privileges), [#SQL Server Always On Groups blueprint](./data-solutions/sqlserver-alwayson), [Data Playground](./data-solutions/data-playground)
- **factories** - [The why and the how of Resource Factories](./factories), [Google Cloud Identity Group Factory](./factories/cloud-identity-group-factory), [Google Cloud BQ Factory](./factories/bigquery-factory), [Google Cloud VPC Firewall Factory](./factories/net-vpc-firewall-yaml), [Minimal Project Factory](./factories/project-factory)
- **GKE** - [Binary Authorization Pipeline Blueprint](./gke/binauthz), [Storage API](./gke/binauthz/image), [Multi-cluster mesh on GKE (fleet API)](./gke/multi-cluster-mesh-gke-fleet-api), [GKE Multitenant Blueprint](./gke/multitenant-fleet), [Shared VPC with GKE support](./networking/shared-vpc-gke/)
- **networking** - [Decentralized firewall management](./networking/decentralized-firewall), [Decentralized firewall validator](./networking/decentralized-firewall/validator), [Network filtering with Squid](./networking/filtering-proxy), [HTTP Load Balancer with Cloud Armor](./networking/glb-and-armor), [Hub and Spoke via VPN](./networking/hub-and-spoke-vpn), [Hub and Spoke via VPC Peering](./networking/hub-and-spoke-peering), [Internal Load Balancer as Next Hop](./networking/ilb-next-hop), [Nginx-based reverse proxy cluster](./networking/nginx-reverse-proxy-cluster), [On-prem DNS and Google Private Access](./networking/onprem-google-access-dns), [Calling a private Cloud Function from On-premises](./networking/private-cloud-function-from-onprem), [Hybrid connectivity to on-premise services through PSC](./networking/psc-hybrid), [PSC Producer](./networking/psc-hybrid/psc-producer), [PSC Consumer](./networking/psc-hybrid/psc-consumer), [Shared VPC with optional GKE cluster](./networking/shared-vpc-gke)
- **networking** - [Decentralized firewall management](./networking/decentralized-firewall), [Decentralized firewall validator](./networking/decentralized-firewall/validator), [Network filtering with Squid](./networking/filtering-proxy), [Network filtering with Squid with isolated VPCs using Private Service Connect](./networking/filtering-proxy-psc), [HTTP Load Balancer with Cloud Armor](./networking/glb-and-armor), [Hub and Spoke via VPN](./networking/hub-and-spoke-vpn), [Hub and Spoke via VPC Peering](./networking/hub-and-spoke-peering), [Internal Load Balancer as Next Hop](./networking/ilb-next-hop), [Nginx-based reverse proxy cluster](./networking/nginx-reverse-proxy-cluster), [On-prem DNS and Google Private Access](./networking/onprem-google-access-dns), [Calling a private Cloud Function from On-premises](./networking/private-cloud-function-from-onprem), [Hybrid connectivity to on-premise services through PSC](./networking/psc-hybrid), [PSC Producer](./networking/psc-hybrid/psc-producer), [PSC Consumer](./networking/psc-hybrid/psc-consumer), [Shared VPC with optional GKE cluster](./networking/shared-vpc-gke)
- **serverless** - [Creating multi-region deployments for API Gateway](./serverless/api-gateway)
- **third party solutions** - [OpenShift on GCP user-provisioned infrastructure](./third-party-solutions/openshift), [Wordpress deployment on Cloud Run](./third-party-solutions/wordpress/cloudrun)

View File

@ -52,20 +52,20 @@ Once done testing, you can clean up resources by running `terraform destroy`.
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [ad_dns_domain_name](variables.tf#L44) | AD DNS domain name. | <code>string</code> | ✓ | |
| [adfs_dns_domain_name](variables.tf#L49) | ADFS DNS domain name. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L24) | Host project ID. | <code>string</code> | ✓ | |
| [ad_ip_cidr_block](variables.tf#L90) | Managed AD IP CIDR block. | <code>string</code> | | <code>&#34;10.0.0.0&#47;24&#34;</code> |
| [disk_size](variables.tf#L54) | Disk size. | <code>number</code> | | <code>50</code> |
| [disk_type](variables.tf#L60) | Disk type. | <code>string</code> | | <code>&#34;pd-ssd&#34;</code> |
| [image](variables.tf#L66) | Image. | <code>string</code> | | <code>&#34;projects&#47;windows-cloud&#47;global&#47;images&#47;family&#47;windows-2022&#34;</code> |
| [instance_type](variables.tf#L72) | Instance type. | <code>string</code> | | <code>&#34;n1-standard-2&#34;</code> |
| [network_config](variables.tf#L35) | Network configuration | <code title="object&#40;&#123;&#10; network &#61; string&#10; subnet &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [prefix](variables.tf#L29) | Prefix for the resources created. | <code>string</code> | | <code>null</code> |
| [project_create](variables.tf#L15) | Parameters for the creation of the new project. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L78) | Region. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [subnet_ip_cidr_block](variables.tf#L96) | Subnet IP CIDR block. | <code>string</code> | | <code>&#34;10.0.1.0&#47;28&#34;</code> |
| [zone](variables.tf#L84) | Zone. | <code>string</code> | | <code>&#34;europe-west1-c&#34;</code> |
| [ad_dns_domain_name](variables.tf#L15) | AD DNS domain name. | <code>string</code> | ✓ | |
| [adfs_dns_domain_name](variables.tf#L26) | ADFS DNS domain name. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L64) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L82) | Host project ID. | <code>string</code> | | |
| [ad_ip_cidr_block](variables.tf#L20) | Managed AD IP CIDR block. | <code>string</code> | | <code>&#34;10.0.0.0&#47;24&#34;</code> |
| [disk_size](variables.tf#L31) | Disk size. | <code>number</code> | | <code>50</code> |
| [disk_type](variables.tf#L37) | Disk type. | <code>string</code> | | <code>&#34;pd-ssd&#34;</code> |
| [image](variables.tf#L43) | Image. | <code>string</code> | | <code>&#34;projects&#47;windows-cloud&#47;global&#47;images&#47;family&#47;windows-2022&#34;</code> |
| [instance_type](variables.tf#L49) | Instance type. | <code>string</code> | | <code>&#34;n1-standard-2&#34;</code> |
| [network_config](variables.tf#L55) | Network configuration | <code title="object&#40;&#123;&#10; network &#61; string&#10; subnet &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [project_create](variables.tf#L73) | Parameters for the creation of the new project. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L87) | Region. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [subnet_ip_cidr_block](variables.tf#L93) | Subnet IP CIDR block. | <code>string</code> | | <code>&#34;10.0.1.0&#47;28&#34;</code> |
| [zone](variables.tf#L99) | Zone. | <code>string</code> | | <code>&#34;europe-west1-c&#34;</code> |
## Outputs

View File

@ -12,10 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
locals {
prefix = (var.prefix == null || var.prefix == "") ? "" : "${var.prefix}-"
}
module "project" {
source = "../../../modules/project"
billing_account = (
@ -41,7 +37,7 @@ module "vpc" {
count = var.network_config == null ? 1 : 0
source = "../../../modules/net-vpc"
project_id = module.project.project_id
name = "${local.prefix}vpc"
name = "${var.prefix}-vpc"
subnets = [
{
ip_cidr_range = var.subnet_ip_cidr_block
@ -98,7 +94,7 @@ module "server" {
module "glb" {
source = "../../../modules/net-glb"
name = "${local.prefix}glb"
name = "${var.prefix}-glb"
project_id = module.project.project_id
https = true

View File

@ -12,40 +12,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
variable "project_create" {
description = "Parameters for the creation of the new project."
type = object({
billing_account_id = string
parent = string
})
default = null
}
variable "project_id" {
description = "Host project ID."
type = string
}
variable "prefix" {
description = "Prefix for the resources created."
type = string
default = null
}
variable "network_config" {
description = "Network configuration"
type = object({
network = string
subnet = string
})
default = null
}
variable "ad_dns_domain_name" {
description = "AD DNS domain name."
type = string
}
variable "ad_ip_cidr_block" {
description = "Managed AD IP CIDR block."
type = string
default = "10.0.0.0/24"
}
variable "adfs_dns_domain_name" {
description = "ADFS DNS domain name."
type = string
@ -75,26 +52,52 @@ variable "instance_type" {
default = "n1-standard-2"
}
variable "network_config" {
description = "Network configuration"
type = object({
network = string
subnet = string
})
default = null
}
variable "prefix" {
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_create" {
description = "Parameters for the creation of the new project."
type = object({
billing_account_id = string
parent = string
})
default = null
}
variable "project_id" {
description = "Host project ID."
type = string
}
variable "region" {
description = "Region."
type = string
default = "europe-west1"
}
variable "subnet_ip_cidr_block" {
description = "Subnet IP CIDR block."
type = string
default = "10.0.1.0/28"
}
variable "zone" {
description = "Zone."
type = string
default = "europe-west1-c"
}
variable "ad_ip_cidr_block" {
description = "Managed AD IP CIDR block."
type = string
default = "10.0.0.0/24"
}
variable "subnet_ip_cidr_block" {
description = "Subnet IP CIDR block."
type = string
default = "10.0.1.0/28"
}

View File

@ -0,0 +1,78 @@
# Apigee X Analytics in Bigquery
The following blueprint shows to how to create an Apigee X trial organization, with an environment group, an environment attached to that environment group and an instance attached to that environment. It creates a NEG that exposes Apigee service attachment. The NEG is added as a backend to a GLB. API proxy requests will pass through the GLB.
![Analytics northbound networking](diagram1.png)
In addition to this it also creates the setup depicted in the diagram below to export the Apigee analytics of an organization daily to a BigQuery table.
![Apigee analytics in BigQuery](diagram2.png)
Find below a description on how the analytics export to BigQuery works:
1. A Cloud Scheduler Job runs daily at a selected time, publishing a message to a Pub/Sub topic.
2. The message published triggers the execution of a function that makes a call to the Apigee Analytics Export API to export the analytical data available for the previous day.
3. The export function is passed the Apigee organization, environments, datastore name as environment variables. The service account used to run the function needs to be granted the Apigee Admin role on the project. The Apigee Analytics engine asynchronously exports the analytical data to a GCS bucket. This requires the _Apigee Service Agent_ service account to be granted the _Storage Admin_ role on the project.
4. A notification of the files created on GCS is received in a Pub/Sub topic that triggers the execution of the cloud function in charge of loading the data from GCS to the right BigQuery table partition. This function is passed the name of the BigQuery dataset, its location and the name of the table inside that dataset as environment variables. The service account used to run the function needs to be granted the _Storage Object Viewer_ role on the GCS bucket, the _BigQuery Job User_ role on the project and the _BigQuery Data Editor_ role on the table.
Note: This setup only works if you are not using custom analytics.
## Running the blueprint
1. Clone this repository or [open it in cloud shell](https://ssh.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fterraform-google-modules%2Fcloud-foundation-fabric&cloudshell_print=cloud-shell-readme.txt&cloudshell_working_dir=blueprints%2Fcloud-operations%apigee), then go through the following steps to create resources:
2. Copy the file [terraform.tfvars.sample](./terraform.tfvars.sample) to a file called ```terraform.tfvars``` and update the values if required.
3. Initialize the terraform configuration
```terraform init```
4. Apply the terraform configuration
```terraform apply```
Once the resources have been created, do the following:
Create an A record in your DNS registrar to point the environment group hostname to the public IP address returned after the terraform configuration was applied. You might need to wait some time until the certificate is provisioned.
## Testing the blueprint
Do the following to verify that everything works as expected.
1. Create an Apigee datastore
```./create-datastore.sh```
2. Deploy an api proxy
```./deploy-apiproxy.sh test```
3. Send some traffic to the proxy
```./send-requests.sh test.my-domain.com 1000```
4. At 4am (UTC) every day the Cloud Scheduler will run and will export the analytics to the BigQuery table. Double-check they are there.
<!-- BEGIN TFDOC -->
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [envgroups](variables.tf#L24) | Environment groups (NAME => [HOSTNAMES]). | <code>map&#40;list&#40;string&#41;&#41;</code> | ✓ | |
| [environments](variables.tf#L30) | Environments. | <code title="map&#40;object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string&#41;&#10; node_config &#61; optional&#40;object&#40;&#123;&#10; min_node_count &#61; optional&#40;number&#41;&#10; max_node_count &#61; optional&#40;number&#41;&#10; current_aggregate_node_count &#61; number&#10; &#125;&#41;&#41;&#10; iam &#61; optional&#40;map&#40;list&#40;string&#41;&#41;&#41;&#10; envgroups &#61; list&#40;string&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | ✓ | |
| [instances](variables.tf#L46) | Instance. | <code title="map&#40;object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string&#41;&#10; region &#61; string&#10; environments &#61; list&#40;string&#41;&#10; psa_ip_cidr_range &#61; string&#10; disk_encryption_key &#61; optional&#40;string&#41;&#10; consumer_accept_list &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | ✓ | |
| [project_id](variables.tf#L92) | Project ID. | <code>string</code> | ✓ | |
| [psc_config](variables.tf#L98) | PSC configuration. | <code>map&#40;string&#41;</code> | ✓ | |
| [datastore_name](variables.tf#L17) | Datastore | <code>string</code> | | <code>&#34;gcs&#34;</code> |
| [organization](variables.tf#L60) | Apigee organization. | <code title="object&#40;&#123;&#10; display_name &#61; optional&#40;string, &#34;Apigee organization created by tf module&#34;&#41;&#10; description &#61; optional&#40;string, &#34;Apigee organization created by tf module&#34;&#41;&#10; authorized_network &#61; optional&#40;string, &#34;vpc&#34;&#41;&#10; runtime_type &#61; optional&#40;string, &#34;CLOUD&#34;&#41;&#10; billing_type &#61; optional&#40;string&#41;&#10; database_encryption_key &#61; optional&#40;string&#41;&#10; analytics_region &#61; optional&#40;string, &#34;europe-west1&#34;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [path](variables.tf#L76) | Bucket path. | <code>string</code> | | <code>&#34;&#47;analytics&#34;</code> |
| [project_create](variables.tf#L83) | Parameters for the creation of the new project. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [vpc_create](variables.tf#L104) | Boolean flag indicating whether the VPC should be created or not. | <code>bool</code> | | <code>true</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [ip_address](outputs.tf#L17) | IP address. | |
<!-- END TFDOC -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -0,0 +1,103 @@
// 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.
const functions = require("@google-cloud/functions-framework");
const superagent = require("superagent");
const { LoggingBunyan } = require("@google-cloud/logging-bunyan");
const bunyan = require("bunyan");
const { GoogleAuth } = require("google-auth-library");
const loggingBunyan = new LoggingBunyan();
const logger = bunyan.createLogger({
name: "analyticsExport",
streams: [
{ stream: process.stdout, level: "info" },
loggingBunyan.stream("info"),
],
});
const ORGANIZATION = process.env.ORGANIZATION;
const ENVIRONMENTS = process.env.ENVIRONMENTS.split(',');
const DATASTORE = process.env.DATASTORE;
const MANAGEMENT_API_URL = "https://apigee.googleapis.com/v1";
function formatDate(date) {
var d = new Date(date),
month = "" + (d.getMonth() + 1),
day = "" + d.getDate(),
year = d.getFullYear();
if (month.length < 2) month = "0" + month;
if (day.length < 2) day = "0" + day;
return [year, month, day].join("-");
}
async function getAccessToken() {
logger.info("Requesting access token...");
const auth = new GoogleAuth();
const token = await auth.getAccessToken();
logger.info("Got access token ");
return token;
}
async function scheduleAnalyticsExport(org, env, token, startDate, endDate) {
logger.info(
`Sending request for an analytics export from ${startDate} to ${endDate} for environment ${env}`
);
try {
const response = await superagent
.post(
`${MANAGEMENT_API_URL}/organizations/${org}/environments/${env}/analytics/exports`
)
.send({
name: `Analytics from ${startDate} to ${endDate}`,
description: `Analytics from ${startDate} to ${endDate}`,
dateRange: {
start: startDate,
end: endDate,
},
outputFormat: "csv",
csvDelimiter: ",",
datastoreName: DATASTORE,
})
.set('Authorization', `Bearer ${token}`)
.accept('json');
logger.info('Analytics export scheduled');
return response;
} catch (error) {
logger.error('Error scheduling analytics export');
logger.error(error);
throw error;
}
}
functions.cloudEvent("export", async (cloudEvent) => {
const today = new Date();
const endDate = formatDate(today);
const yesterday = new Date(today.setDate(today.getDate() - 1));
const startDate = formatDate(yesterday);
const token = await getAccessToken();
try {
for(let i = 0; i < ENVIRONMENTS.length; i++) {
const env = ENVIRONMENTS[i];
const response = await scheduleAnalyticsExport(ORGANIZATION, env, token, startDate, endDate);
logger.error('Export scheduled: ' + response.body.self);
}
} catch (error) {
logger.error('Analytics exports was not scheduled');
logger.error(error);
}
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
{
"name": "export",
"version": "1.0.0",
"description": "Apigee analytics export to GCS",
"main": "index.js",
"engines": {
"node": ">=16.0.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@google-cloud/functions-framework": "^3.1.2",
"@google-cloud/logging-bunyan": "^4.2.0",
"bunyan": "^1.8.15",
"express": "^4.18.2",
"google-auth-library": "^8.6.0",
"superagent": "^8.0.3"
}
}

View File

@ -0,0 +1,76 @@
/**
* 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.
*/
const functions = require("@google-cloud/functions-framework");
const { Storage } = require('@google-cloud/storage');
const { BigQuery } = require('@google-cloud/bigquery');
const bunyan = require('bunyan');
const schema = require('./schema.json');
const { LoggingBunyan } = require('@google-cloud/logging-bunyan');
const loggingBunyan = new LoggingBunyan();
const logger = bunyan.createLogger({
name: 'gcs2bq',
streams: [
{ stream: process.stdout, level: 'info' },
loggingBunyan.stream('info')
],
});
const DATASET = process.env.DATASET
const TABLE = process.env.TABLE
const LOCATION = process.env.LOCATION
async function loadCSVFromGCS(datasetId, tableId, timePartition, bucket, filename) {
const metadata = {
sourceFormat: 'CSV',
skipLeadingRows: 1,
maxBadRecords: 1000,
schema: {
fields: schema
},
location: LOCATION
};
logger.info(`Trying to load ${bucket}/${filename} in ${timePartition} time partition of table ${tableId}...`);
const bigquery = new BigQuery();
const storage = new Storage();
const [job] = await bigquery
.dataset(datasetId)
.table(`${tableId}\$${timePartition}`)
.load(storage.bucket(bucket).file(filename), metadata);
logger.info(`Job ${job.id} completed.`);
const errors = job.status.errors;
if (errors && errors.length > 0) {
logger.info('Errors occurred:' + JSON.stringify(errors));
throw new Error('File could not be loaded in time partition');
}
}
functions.cloudEvent("gcs2bq", async (cloudEvent) => {
const data = JSON.parse(Buffer.from(cloudEvent.data.message.data, 'base64').toString());
logger.info('Notification received');
logger.info(data);
const pattern = /([^/]+\/)?[0-9]{14}\-[0-9a-z]{8}\-[0-9a-z]{4}\-[0-9a-z]{4}\-[0-9a-z]{4}\-[0-9a-z]{12}\-api\-from\-([0-9]{8})0000\-to\-([0-9]{8})0000\/result\-[0-9]+\.csv\.gz/
const result = data.name.match(pattern);
const timePartition = result[2];
await loadCSVFromGCS(DATASET, TABLE, timePartition, data.bucket, data.name)
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
{
"name": "gcs2bq",
"version": "1.0.0",
"description": "",
"main": "index.js",
"engines": {
"node": ">=16.0.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@google-cloud/bigquery": "^6.0.3",
"@google-cloud/functions-framework": "^3.1.2",
"@google-cloud/logging-bunyan": "^4.2.0",
"@google-cloud/storage": "^6.7.0",
"bunyan": "^1.8.15"
}
}

View File

@ -0,0 +1,447 @@
[
{
"mode": "NULLABLE",
"name": "organization",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "environment",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "apiproxy",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "request_uri",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "proxy",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "proxy_basepath",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "request_verb",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "request_size",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "response_status_code",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "is_error",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "client_received_start_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "client_received_end_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "target_sent_start_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "target_sent_end_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "target_received_start_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "target_received_end_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "client_sent_start_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "client_sent_end_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "client_ip",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "client_id",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "developer",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "developer_app",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "api_product",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "flow_resource",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "target",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "target_url",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "target_host",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "apiproxy_revision",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "proxy_pathsuffix",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "proxy_client_ip",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "target_basepath",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "target_ip",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "request_path",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "response_size",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "developer_email",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "virtual_host",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "gateway_flow_id",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "message_count",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "total_response_time",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "request_processing_latency",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "response_processing_latency",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "target_response_time",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "cache_hit",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "x_forwarded_for_ip",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "useragent",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "target_response_code",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "target_error",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "policy_error",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "ax_created_time",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "ax_ua_agent_type",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_ua_os_version",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_ua_os_family",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_ua_agent_version",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_ua_device_category",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_ua_agent_family",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "gateway_source",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_month_of_year",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_hour_of_day",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_week_of_month",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_day_of_week",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_cache_key",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_cache_l1_count",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "ax_cache_source",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_cache_executed",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "ax_cache_name",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_edge_execution_fault_code",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_edge_is_apigee_fault",
"type": "INTEGER"
},
{
"mode": "NULLABLE",
"name": "ax_execution_fault_policy_name",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_execution_fault_flow_state",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_execution_fault_flow_name",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_dn_region",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_true_client_ip",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "x_apigee_edge_execution_stats_request_flow_end_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "x_apigee_edge_execution_stats_request_flow_start_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "x_apigee_edge_execution_stats_response_flow_end_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "x_apigee_edge_execution_stats_response_flow_start_timestamp",
"type": "TIMESTAMP"
},
{
"mode": "NULLABLE",
"name": "x_apigee_edge_stats_steps",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "senseaction",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "ax_resolved_client_ip",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "x_forwarded_proto",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "x_apigee_intelligence_service",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "envgroup_hostname",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "x_apigee_mintng_rate",
"type": "NUMERIC"
},
{
"mode": "NULLABLE",
"name": "x_apigee_mintng_rate_plan_id",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "x_apigee_mintng_dev_share",
"type": "NUMERIC"
},
{
"mode": "NULLABLE",
"name": "x_apigee_mintng_currency",
"type": "STRING"
},
{
"mode": "NULLABLE",
"name": "x_apigee_mintng_price",
"type": "NUMERIC"
},
{
"mode": "NULLABLE",
"name": "x_apigee_mintng_tx_success",
"type": "BOOLEAN"
},
{
"mode": "NULLABLE",
"name": "x_apigee_mintng_price_multiplier",
"type": "NUMERIC"
}
]

View File

@ -0,0 +1,311 @@
/**
* Copyright 2022 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 "project" {
source = "../../../modules/project"
billing_account = (var.project_create != null
? var.project_create.billing_account_id
: null
)
parent = (var.project_create != null
? var.project_create.parent
: null
)
name = var.project_id
project_create = var.project_create == null ? false : true
services = [
"apigee.googleapis.com",
"bigquery.googleapis.com",
"cloudbuild.googleapis.com",
"cloudfunctions.googleapis.com",
"cloudscheduler.googleapis.com",
"logging.googleapis.com",
"compute.googleapis.com",
"pubsub.googleapis.com",
"servicenetworking.googleapis.com",
"storage.googleapis.com"
]
iam = {
"roles/bigquery.jobUser" = [module.function_gcs2bq.service_account_iam_email]
"roles/logging.logWriter" = [module.function_export.service_account_iam_email]
"roles/logging.logWriter" = [module.function_gcs2bq.service_account_iam_email]
"roles/apigee.admin" = [module.function_export.service_account_iam_email]
"roles/storage.admin" = ["serviceAccount:${module.project.service_accounts.robots.apigee}"]
}
}
module "vpc" {
source = "../../../modules/net-vpc"
project_id = module.project.project_id
name = var.organization.authorized_network
vpc_create = var.vpc_create
subnets_psc = [for k, v in var.psc_config :
{
ip_cidr_range = v
name = "subnet-psc-${k}"
region = k
}
]
psa_config = {
ranges = { for k, v in var.instances :
"apigee-${k}" => v.psa_ip_cidr_range
}
}
}
module "apigee" {
source = "../../../modules/apigee"
project_id = module.project.project_id
organization = var.organization
envgroups = var.envgroups
environments = var.environments
instances = var.instances
depends_on = [
module.vpc
]
}
resource "google_compute_region_network_endpoint_group" "neg" {
for_each = var.instances
name = "apigee-neg-${each.key}"
project = module.project.project_id
region = each.value.region
network_endpoint_type = "PRIVATE_SERVICE_CONNECT"
psc_target_service = module.apigee.instances[each.key].service_attachment
network = module.vpc.network.self_link
subnetwork = module.vpc.subnets_psc["${each.value.region}/subnet-psc-${each.value.region}"].self_link
}
module "glb" {
source = "../../../modules/net-glb"
name = "glb"
project_id = module.project.project_id
https = true
reserve_ip_address = true
ssl_certificates_config = { for k, v in var.envgroups :
"${k}-domain" => {
domains = v,
unmanaged_config = null
}
}
target_proxy_https_config = {
ssl_certificates = [for k, v in var.envgroups : "${k}-domain"]
}
health_checks_config_defaults = null
backend_services_config = {
apigee = {
bucket_config = null
enable_cdn = false
cdn_config = null
group_config = {
backends = [for k, v in google_compute_region_network_endpoint_group.neg :
{
group = v.id
options = null
}
],
health_checks = []
log_config = null
options = {
affinity_cookie_ttl_sec = null
custom_request_headers = null
custom_response_headers = null
connection_draining_timeout_sec = null
load_balancing_scheme = "EXTERNAL_MANAGED"
locality_lb_policy = null
port_name = null
security_policy = null
session_affinity = null
timeout_sec = null
circuits_breakers = null
consistent_hash = null
iap = null
protocol = "HTTPS"
}
}
}
}
global_forwarding_rule_config = {
load_balancing_scheme = "EXTERNAL_MANAGED"
ip_protocol = "TCP"
ip_version = "IPV4"
port_range = null
}
}
module "pubsub_export" {
source = "../../../modules/pubsub"
project_id = module.project.project_id
name = "topic-export"
}
module "bucket_export" {
source = "../../../modules/gcs"
project_id = module.project.project_id
name = "${module.project.project_id}-export"
iam = {
"roles/storage.objectViewer" = [module.function_gcs2bq.service_account_iam_email]
}
notification_config = {
enabled = true
payload_format = "JSON_API_V1"
sa_email = module.project.service_accounts.robots.storage
topic_name = "topic-gcs2bq"
event_types = ["OBJECT_FINALIZE"]
custom_attributes = {}
}
}
module "function_export" {
source = "../../../modules/cloud-function"
project_id = module.project.project_id
name = "export"
bucket_name = "${module.project.project_id}-code-export"
region = var.organization.analytics_region
ingress_settings = "ALLOW_INTERNAL_ONLY"
bucket_config = {
location = null
lifecycle_delete_age = 1
}
bundle_config = {
source_dir = "${path.module}/functions/export"
output_path = "${path.module}/bundle-export.zip"
excludes = null
}
function_config = {
entry_point = "export"
instances = null
memory = null
runtime = "nodejs16"
timeout = 180
}
environment_variables = {
ORGANIZATION = module.apigee.org_name,
ENVIRONMENTS = join(",", [for k, v in module.apigee.environments : k])
DATASTORE = var.datastore_name
}
trigger_config = {
event = "google.pubsub.topic.publish"
resource = module.pubsub_export.id
retry = null
}
service_account_create = true
}
module "function_gcs2bq" {
source = "../../../modules/cloud-function"
project_id = module.project.project_id
name = "gcs2bq"
bucket_name = "${module.project.project_id}-code-gcs2bq"
region = var.organization.analytics_region
ingress_settings = "ALLOW_INTERNAL_ONLY"
bucket_config = {
location = null
lifecycle_delete_age = 1
}
bundle_config = {
source_dir = "${path.module}/functions/gcs2bq"
output_path = "${path.module}/bundle-gcs2bq.zip"
excludes = null
}
function_config = {
entry_point = "gcs2bq"
instances = null
memory = null
runtime = "nodejs16"
timeout = 180
}
environment_variables = {
DATASET = module.bigquery_dataset.dataset_id
TABLE = module.bigquery_dataset.tables["analytics"].table_id
LOCATION = var.organization.analytics_region
}
trigger_config = {
event = "google.pubsub.topic.publish"
resource = module.bucket_export.topic
retry = null
}
service_account_create = true
}
module "bigquery_dataset" {
source = "../../../modules/bigquery-dataset"
project_id = module.project.project_id
id = "apigee"
location = var.organization.analytics_region
tables = {
analytics = {
friendly_name = "analytics"
labels = {}
options = null
partitioning = {
field = "client_received_end_timestamp"
range = null
time = { type = "DAY", expiration_ms = null }
}
schema = file("${path.module}/functions/gcs2bq/schema.json")
deletion_protection = false
}
}
iam = {
"roles/bigquery.dataEditor" = [module.function_gcs2bq.service_account_iam_email]
}
}
resource "google_app_engine_application" "app" {
project = module.project.project_id
location_id = ((var.organization.analytics_region == "europe-west1" || var.organization.analytics_region == "us-central1") ?
substr(var.organization.analytics_region, 0, length(var.organization.analytics_region) - 1) :
var.organization.analytics_region)
}
resource "google_cloud_scheduler_job" "job" {
name = "export"
schedule = "0 4 * * *"
time_zone = "Etc/UTC"
attempt_deadline = "320s"
project = module.project.project_id
region = var.organization.analytics_region
pubsub_target {
topic_name = module.pubsub_export.id
data = base64encode("test")
}
}
resource "local_file" "create_datastore_file" {
content = templatefile("${path.module}/templates/create-datastore.sh.tpl", {
org_name = module.apigee.org_name
project_id = module.project.project_id
datastore_name = var.datastore_name
bucket_name = module.bucket_export.name
path = var.path
})
filename = "${path.module}/create-datastore.sh"
file_permission = "0777"
}
resource "local_file" "deploy_apiproxy_file" {
content = templatefile("${path.module}/templates/deploy-apiproxy.sh.tpl", {
org_name = module.apigee.org_name
})
filename = "${path.module}/deploy-apiproxy.sh"
file_permission = "0777"
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*/
variable "bucket_name" {
type = string
default = "test"
output "ip_address" {
description = "IP address."
value = module.glb.ip_address
}

View File

@ -0,0 +1,251 @@
{
"name": "apigee",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"dependencies": {
"superagent-debugger": "^1.2.9"
}
},
"node_modules/ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
"dependencies": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
"dependencies": {
"ansi-regex": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
"engines": {
"node": "*"
}
},
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/query-string": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
"integrity": "sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==",
"dependencies": {
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"dependencies": {
"ansi-regex": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/superagent-debugger": {
"version": "1.2.9",
"resolved": "https://registry.npmjs.org/superagent-debugger/-/superagent-debugger-1.2.9.tgz",
"integrity": "sha512-iH4NvJl1utorgRbrsYoOM8yoeTbS7YWLoDkAwRy2rgB6aP5Lr36XxmpE8GbgvmUY6R4QmYr+4R4IdAGMPmwR9g==",
"dependencies": {
"chalk": "^1.1.3",
"debug": "^2.6.0",
"lodash": "^4.17.4",
"moment": "^2.17.1",
"query-string": "^4.3.1"
}
},
"node_modules/supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==",
"engines": {
"node": ">=0.8.0"
}
}
},
"dependencies": {
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="
},
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
"requires": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
}
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
},
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
"requires": {
"ansi-regex": "^2.0.0"
}
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
},
"query-string": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
"integrity": "sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==",
"requires": {
"object-assign": "^4.1.0",
"strict-uri-encode": "^1.0.0"
}
},
"strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
"integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ=="
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"requires": {
"ansi-regex": "^2.0.0"
}
},
"superagent-debugger": {
"version": "1.2.9",
"resolved": "https://registry.npmjs.org/superagent-debugger/-/superagent-debugger-1.2.9.tgz",
"integrity": "sha512-iH4NvJl1utorgRbrsYoOM8yoeTbS7YWLoDkAwRy2rgB6aP5Lr36XxmpE8GbgvmUY6R4QmYr+4R4IdAGMPmwR9g==",
"requires": {
"chalk": "^1.1.3",
"debug": "^2.6.0",
"lodash": "^4.17.4",
"moment": "^2.17.1",
"query-string": "^4.3.1"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g=="
}
}
}

View File

@ -0,0 +1,28 @@
# Copyright 2022 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.
#!/bin/bash
if [ $# -lt 2 ]; then
echo "Usage: $0 ENVGROUP_HOSTNAME NUM_REQUESTS"
exit 1
fi
ENVGROUP_HOSTNAME=$1
NUM_REQUESTS=$2
for i in $(seq 1 $NUM_REQUESTS)
do
curl -v https://$ENVGROUP_HOSTNAME/httpbin/headers
done

View File

@ -0,0 +1,30 @@
# Copyright 2022 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.
#!/bin/bash
curl "https://apigee.googleapis.com/v1/organizations/${org_name}/analytics/datastores" \
-X POST \
-H "Content-type:application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-d \
'{
"displayName": "${datastore_name}",
"targetType": "gcs",
"datastoreConfig": {
"projectId": "${project_id}",
"bucketName": "${bucket_name}",
"path": "${path}"
}
}'

View File

@ -0,0 +1,41 @@
# Copyright 2022 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.
#!/bin/bash
if [ $# -lt 1 ]; then
echo "Usage: $0 ENV_NAME"
exit 1
fi
ORG_NAME=${org_name}
ENV_NAME=$1
wget https://github.com/apigee/api-platform-samples/raw/master/sample-proxies/apigee-quickstart/httpbin_rev1_2020_02_02.zip -O apiproxy.zip
export TOKEN=$(gcloud auth print-access-token)
curl -v -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type:application/octet-stream" \
-T 'apiproxy.zip' \
"https://apigee.googleapis.com/v1/organizations/$ORG_NAME/apis?name=httpbin&action=import"
curl -v -X POST \
-H "Authorization: Bearer $TOKEN" \
"https://apigee.googleapis.com/v1/organizations/$ORG_NAME/environments/$ENV_NAME/apis/httpbin/revisions/1/deployments"
curl -v \
-H "Authorization: Bearer $TOKEN" \
"https://apigee.googleapis.com/v1/organizations/$ORG_NAME/environments/$ENV_NAME/apis/httpbin/revisions/1/deployments"

View File

@ -0,0 +1,23 @@
project_create = {
billing_account_id = "011D94-9C86C1-ADD197"
parent = "folders/586929298360"
}
project_id = "g-prj-cd-sb-apigee-bq-10"
envgroups = {
test = ["test.cool-demos.space"]
}
environments = {
apis-test = {
envgroups = ["test"]
}
}
instances = {
instance-ew1 = {
region = "europe-west1"
environments = ["apis-test"]
psa_ip_cidr_range = "10.0.4.0/22"
}
}
psc_config = {
europe-west1 = "10.0.0.0/28"
}

View File

@ -0,0 +1,108 @@
/**
* Copyright 2022 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 "datastore_name" {
description = "Datastore"
type = string
nullable = false
default = "gcs"
}
variable "envgroups" {
description = "Environment groups (NAME => [HOSTNAMES])."
type = map(list(string))
nullable = false
}
variable "environments" {
description = "Environments."
type = map(object({
display_name = optional(string)
description = optional(string)
node_config = optional(object({
min_node_count = optional(number)
max_node_count = optional(number)
current_aggregate_node_count = number
}))
iam = optional(map(list(string)))
envgroups = list(string)
}))
nullable = false
}
variable "instances" {
description = "Instance."
type = map(object({
display_name = optional(string)
description = optional(string)
region = string
environments = list(string)
psa_ip_cidr_range = string
disk_encryption_key = optional(string)
consumer_accept_list = optional(list(string))
}))
nullable = false
}
variable "organization" {
description = "Apigee organization."
type = object({
display_name = optional(string, "Apigee organization created by tf module")
description = optional(string, "Apigee organization created by tf module")
authorized_network = optional(string, "vpc")
runtime_type = optional(string, "CLOUD")
billing_type = optional(string)
database_encryption_key = optional(string)
analytics_region = optional(string, "europe-west1")
})
nullable = false
default = {
}
}
variable "path" {
description = "Bucket path."
type = string
default = "/analytics"
nullable = false
}
variable "project_create" {
description = "Parameters for the creation of the new project."
type = object({
billing_account_id = string
parent = string
})
default = null
}
variable "project_id" {
description = "Project ID."
type = string
nullable = false
}
variable "psc_config" {
description = "PSC configuration."
type = map(string)
nullable = false
}
variable "vpc_create" {
description = "Boolean flag indicating whether the VPC should be created or not."
type = bool
default = true
}

View File

@ -79,19 +79,18 @@ module "cf" {
name = var.name
bucket_name = "${var.name}-${random_pet.random.id}"
bucket_config = {
location = var.region
lifecycle_delete_age = null
location = var.region
}
bundle_config = {
source_dir = "cf"
output_path = var.bundle_path
excludes = null
}
service_account = module.service-account.email
trigger_config = {
event = "google.pubsub.topic.publish"
resource = module.pubsub.topic.id
retry = null
v1 = {
event = "google.pubsub.topic.publish"
resource = module.pubsub.topic.id
}
}
}

View File

@ -26,11 +26,11 @@ Note that Terraform 0.13 at least is required due to the use of `for_each` with
|---|---|:---:|:---:|:---:|
| [billing_account_id](variables.tf#L17) | Billing account associated with the GCP Projects that will be created for each team. | <code>string</code> | ✓ | |
| [folder_id](variables.tf#L28) | Folder ID in which DNS projects will be created. | <code>string</code> | ✓ | |
| [shared_vpc_link](variables.tf#L48) | Shared VPC self link, used for DNS peering. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L33) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [shared_vpc_link](variables.tf#L51) | Shared VPC self link, used for DNS peering. | <code>string</code> | ✓ | |
| [dns_domain](variables.tf#L22) | DNS domain under which each application team DNS domain will be created. | <code>string</code> | | <code>&#34;example.org&#34;</code> |
| [prefix](variables.tf#L33) | Customer name to use as prefix for resources' naming. | <code>string</code> | | <code>&#34;test-dns&#34;</code> |
| [project_services](variables.tf#L39) | Service APIs enabled by default. | <code>list&#40;string&#41;</code> | | <code title="&#91;&#10; &#34;compute.googleapis.com&#34;,&#10; &#34;dns.googleapis.com&#34;,&#10;&#93;">&#91;&#8230;&#93;</code> |
| [teams](variables.tf#L53) | List of application teams requiring their own Cloud DNS instance. | <code>list&#40;string&#41;</code> | | <code title="&#91;&#10; &#34;team1&#34;,&#10; &#34;team2&#34;,&#10;&#93;">&#91;&#8230;&#93;</code> |
| [project_services](variables.tf#L42) | Service APIs enabled by default. | <code>list&#40;string&#41;</code> | | <code title="&#91;&#10; &#34;compute.googleapis.com&#34;,&#10; &#34;dns.googleapis.com&#34;,&#10;&#93;">&#91;&#8230;&#93;</code> |
| [teams](variables.tf#L56) | List of application teams requiring their own Cloud DNS instance. | <code>list&#40;string&#41;</code> | | <code title="&#91;&#10; &#34;team1&#34;,&#10; &#34;team2&#34;,&#10;&#93;">&#91;&#8230;&#93;</code> |
## Outputs

View File

@ -50,8 +50,12 @@ variable "billing_account" {
}
variable "prefix" {
description = "Customer name to use as prefix for resources' naming."
default = "test-dns"
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "dns_domain" {

View File

@ -31,9 +31,12 @@ variable "folder_id" {
}
variable "prefix" {
description = "Customer name to use as prefix for resources' naming."
description = "Prefix used for resource names."
type = string
default = "test-dns"
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_services" {

View File

@ -27,13 +27,12 @@ By changing the `restricted_role_grant`, the blueprint can be used to grant admi
You can easily configure the blueprint for this use case:
```hcl
```tfvars
# terraform.tfvars
delegated_role_grants = ["roles/compute.networkUser"]
direct_role_grants = []
direct_role_grants = []
restricted_role_grant = "roles/compute.networkAdmin"
# tftest skip
```
This diagram shows the resources and expected behaviour:

View File

@ -16,20 +16,25 @@ Three metric descriptors are created for each monitored resource: usage, limit a
Clone this repository, then go through the following steps to create resources:
- Create a terraform.tfvars file with the following content:
```tfvars
organization_id = "<YOUR-ORG-ID>"
billing_account = "<YOUR-BILLING-ACCOUNT>"
monitoring_project_id = "project-0" # Monitoring project where the dashboard will be created and the solution deployed
monitored_projects_list = ["project-1", "project2"] # Projects to be monitored by the solution
monitored_folders_list = ["folder_id"] # Folders to be monitored by the solution
v2 = false # Set to true to use V2 Cloud Functions environment
```
organization_id = "<YOUR-ORG-ID>"
billing_account = "<YOUR-BILLING-ACCOUNT>"
monitoring_project_id = "<YOUR-MONITORING-PROJECT>"
# Monitoring project where the dashboard will be created and the solution deployed, a project named "mon-network-dahshboard" will be created if left blank
monitored_projects_list = ["project-1", "project2"]
# Projects to be monitored by the solution
monitored_folders_list = ["folder_id"]
# Folders to be monitored by the solution
prefix = "<YOUR-PREFIX>"
# Monitoring project name prefix, monitoring project name is <YOUR-PREFIX>-network-dashboard, ignored if monitoring_project_id variable is provided
cf_version = V1|V2
# Set to V2 to use V2 Cloud Functions environment
```
- `terraform init`
- `terraform apply`
Note: Org level viewing permission is required for some metrics such as firewall policies.
Once the resources are deployed, go to the following page to see the dashboard: https://console.cloud.google.com/monitoring/dashboards?project=<YOUR-MONITORING-PROJECT>.
A dashboard called "quotas-utilization" should be created.
Once the resources are deployed, go to the following page to see the dashboard: https://console.cloud.google.com/monitoring/dashboards?project=<YOUR-MONITORING-PROJECT> a dashboard called "quotas-utilization" should be created.
The Cloud Function runs every 10 minutes by default so you should start getting some data points after a few minutes.
You can use the metric explorer to view the data points for the different custom metrics created: https://console.cloud.google.com/monitoring/metrics-explorer?project=<YOUR-MONITORING-PROJECT>.
@ -69,7 +74,6 @@ Note that metrics are created in the cloud-function/metrics.yaml file. You can a
- The CF assumes custom routes importing/exporting is ON, this impacts static and dynamic routes usage calculation
- The CF assumes all networks in peering groups have the same global routing and custom routes sharing configuration
## Next steps and ideas
In a future release, we could support:
- Google managed VPCs that are peered with PSA (such as Cloud SQL or Memorystore)
@ -87,13 +91,13 @@ If you are interested in this and/or would like to contribute, please contact le
|---|---|:---:|:---:|:---:|
| [billing_account](variables.tf#L17) | The ID of the billing account to associate this project with | <code></code> | ✓ | |
| [monitored_projects_list](variables.tf#L36) | ID of the projects to be monitored (where limits and quotas data will be pulled) | <code>list&#40;string&#41;</code> | ✓ | |
| [organization_id](variables.tf#L47) | The organization id for the associated services | <code></code> | ✓ | |
| [prefix](variables.tf#L51) | Customer name to use as prefix for monitoring project | <code></code> | ✓ | |
| [organization_id](variables.tf#L46) | The organization id for the associated services | <code></code> | ✓ | |
| [prefix](variables.tf#L50) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [cf_version](variables.tf#L21) | Cloud Function version 2nd Gen or 1st Gen. Possible options: 'V1' or 'V2'.Use CFv2 if your Cloud Function timeouts after 9 minutes. By default it is using CFv1. | <code></code> | | <code>V1</code> |
| [monitored_folders_list](variables.tf#L30) | ID of the projects to be monitored (where limits and quotas data will be pulled) | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [monitoring_project_id](variables.tf#L41) | Monitoring project where the dashboard will be created and the solution deployed; a project will be created if set to empty string | <code></code> | | |
| [project_monitoring_services](variables.tf#L55) | Service APIs enabled in the monitoring project if it will be created. | <code></code> | | <code title="&#91;&#10; &#34;artifactregistry.googleapis.com&#34;,&#10; &#34;cloudasset.googleapis.com&#34;,&#10; &#34;cloudbilling.googleapis.com&#34;,&#10; &#34;cloudbuild.googleapis.com&#34;,&#10; &#34;cloudresourcemanager.googleapis.com&#34;,&#10; &#34;cloudscheduler.googleapis.com&#34;,&#10; &#34;compute.googleapis.com&#34;,&#10; &#34;cloudfunctions.googleapis.com&#34;,&#10; &#34;iam.googleapis.com&#34;,&#10; &#34;iamcredentials.googleapis.com&#34;,&#10; &#34;logging.googleapis.com&#34;,&#10; &#34;monitoring.googleapis.com&#34;,&#10; &#34;run.googleapis.com&#34;,&#10; &#34;serviceusage.googleapis.com&#34;&#10;&#93;">&#91;&#8230;&#93;</code> |
| [region](variables.tf#L75) | Region used to deploy the cloud functions and scheduler | <code></code> | | <code>europe-west1</code> |
| [schedule_cron](variables.tf#L80) | Cron format schedule to run the Cloud Function. Default is every 10 minutes. | <code></code> | | <code>&#42;&#47;10 &#42; &#42; &#42; &#42;</code> |
| [project_monitoring_services](variables.tf#L59) | Service APIs enabled in the monitoring project if it will be created. | <code></code> | | <code title="&#91;&#10; &#34;artifactregistry.googleapis.com&#34;,&#10; &#34;cloudasset.googleapis.com&#34;,&#10; &#34;cloudbilling.googleapis.com&#34;,&#10; &#34;cloudbuild.googleapis.com&#34;,&#10; &#34;cloudfunctions.googleapis.com&#34;,&#10; &#34;cloudresourcemanager.googleapis.com&#34;,&#10; &#34;cloudscheduler.googleapis.com&#34;,&#10; &#34;compute.googleapis.com&#34;,&#10; &#34;iam.googleapis.com&#34;,&#10; &#34;iamcredentials.googleapis.com&#34;,&#10; &#34;logging.googleapis.com&#34;,&#10; &#34;monitoring.googleapis.com&#34;,&#10; &#34;pubsub.googleapis.com&#34;,&#10; &#34;run.googleapis.com&#34;,&#10; &#34;servicenetworking.googleapis.com&#34;,&#10; &#34;serviceusage.googleapis.com&#34;,&#10; &#34;storage-component.googleapis.com&#34;&#10;&#93;">&#91;&#8230;&#93;</code> |
| [region](variables.tf#L81) | Region used to deploy the cloud functions and scheduler | <code></code> | | <code>europe-west1</code> |
| [schedule_cron](variables.tf#L86) | Cron format schedule to run the Cloud Function. Default is every 10 minutes. | <code></code> | | <code>&#42;&#47;10 &#42; &#42; &#42; &#42;</code> |
<!-- END TFDOC -->

View File

@ -187,7 +187,7 @@ def count_effective_limit(config, project_id, network_dict, usage_metric_name,
for peered_network in network_dict['peerings']:
if 'usage' not in peered_network:
print(
f"Can not add metrics for peered network in projects/{project_id} as no usage metrics exist due to missing permissions"
f"Cannot add metrics for peered network in projects/{project_id} as no usage metrics exist due to missing permissions"
)
continue
peering_group_usage += peered_network['usage']

View File

@ -30,7 +30,7 @@ locals {
module "project-monitoring" {
count = var.monitoring_project_id == "" ? 1 : 0
source = "../../../modules/project"
name = "monitoring"
name = "network-dashboards"
parent = "organizations/${var.organization_id}"
prefix = var.prefix
billing_account = var.billing_account
@ -137,15 +137,13 @@ module "cloud-function" {
name = "network-dashboard-cloud-function"
bucket_name = "${local.monitoring_project}-network-dashboard-bucket"
bucket_config = {
location = var.region
lifecycle_delete_age = null
location = var.region
}
region = var.region
bundle_config = {
source_dir = "cloud-function"
output_path = "cloud-function.zip"
excludes = null
}
function_config = {
@ -153,7 +151,7 @@ module "cloud-function" {
entry_point = "main"
runtime = "python39"
instances = 1
memory = 256 # Memory in MB
memory_mb = 256
}
@ -169,10 +167,17 @@ module "cloud-function" {
# Internal only doesn't seem to work with CFv2:
ingress_settings = var.cf_version == "V2" ? "ALLOW_ALL" : "ALLOW_INTERNAL_ONLY"
trigger_config = {
event = "google.pubsub.topic.publish"
resource = module.pubsub.topic.id
retry = null
trigger_config = var.cf_version == "V2" ? {
v2 = {
event_type = "google.cloud.pubsub.topic.v1.messagePublished"
pubsub_topic = module.pubsub.topic.id
service_account_create = true
}
} : {
v1 = {
event = "google.pubsub.topic.publish"
resource = module.pubsub.topic.id
}
}
}

View File

@ -23,7 +23,12 @@ variable "billing_account" {
}
variable "prefix" {
description = "Customer name to use as prefix for resources' naming"
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_vm_services" {
@ -36,7 +41,6 @@ variable "project_vm_services" {
"servicenetworking.googleapis.com",
]
}
variable "region" {
description = "Region used to deploy subnets"
default = "europe-west1"
@ -45,4 +49,4 @@ variable "region" {
variable "zone" {
description = "Zone used to deploy vms"
default = "europe-west1-b"
}
}

View File

@ -43,13 +43,17 @@ variable "monitoring_project_id" {
default = ""
}
variable "organization_id" {
description = "The organization id for the associated services"
}
variable "prefix" {
description = "Customer name to use as prefix for monitoring project"
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_monitoring_services" {
@ -59,19 +63,21 @@ variable "project_monitoring_services" {
"cloudasset.googleapis.com",
"cloudbilling.googleapis.com",
"cloudbuild.googleapis.com",
"cloudfunctions.googleapis.com",
"cloudresourcemanager.googleapis.com",
"cloudscheduler.googleapis.com",
"compute.googleapis.com",
"cloudfunctions.googleapis.com",
"iam.googleapis.com",
"iamcredentials.googleapis.com",
"logging.googleapis.com",
"monitoring.googleapis.com",
"pubsub.googleapis.com",
"run.googleapis.com",
"serviceusage.googleapis.com"
"servicenetworking.googleapis.com",
"serviceusage.googleapis.com",
"storage-component.googleapis.com"
]
}
variable "region" {
description = "Region used to deploy the cloud functions and scheduler"
default = "europe-west1"

View File

@ -52,13 +52,11 @@ module "cf" {
name = var.name
bucket_name = "${var.name}-${random_pet.random.id}"
bucket_config = {
location = var.region
lifecycle_delete_age = null
location = var.region
}
bundle_config = {
source_dir = "cf"
output_path = var.bundle_path
excludes = null
}
# https://github.com/hashicorp/terraform-provider-archive/issues/40
# https://issuetracker.google.com/issues/155215191
@ -68,9 +66,10 @@ module "cf" {
}
service_account_create = true
trigger_config = {
event = "google.pubsub.topic.publish"
resource = module.pubsub.topic.id
retry = null
v1 = {
event = "google.pubsub.topic.publish"
resource = module.pubsub.topic.id
}
}
}

View File

@ -91,19 +91,18 @@ module "cf" {
name = var.name
bucket_name = "${var.name}-${random_pet.random.id}"
bucket_config = {
location = var.region
lifecycle_delete_age = null
location = var.region
}
bundle_config = {
source_dir = "cf"
output_path = var.bundle_path
excludes = null
}
service_account = module.service-account.email
trigger_config = {
event = "google.pubsub.topic.publish"
resource = module.pubsub.topic.id
retry = null
v1 = {
event = "google.pubsub.topic.publish"
resource = module.pubsub.topic.id
}
}
}
@ -115,8 +114,8 @@ module "cffile" {
name = var.name_cffile
bucket_name = "${var.name_cffile}-${random_pet.random.id}"
bucket_config = {
location = var.region
lifecycle_delete_age = null
location = var.region
lifecycle_delete_age_days = null
}
bundle_config = {
source_dir = "cffile"
@ -125,9 +124,11 @@ module "cffile" {
}
service_account = module.service-account.email
trigger_config = {
event = "google.pubsub.topic.publish"
resource = module.pubsub_file.topic.id
retry = null
v1 = {
event = "google.pubsub.topic.publish"
resource = module.pubsub_file.topic.id
retry = null
}
}
}

View File

@ -11,8 +11,8 @@ The codebase provisions the following list of resources:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [impersonate_service_account_email](variables.tf#L21) | Service account to be impersonated by workload identity. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L16) | GCP project ID. | <code>string</code> | ✓ | |
| [impersonate_service_account_email](variables.tf#L16) | Service account to be impersonated by workload identity. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L21) | GCP project ID. | <code>string</code> | ✓ | |
| [workload_identity_pool_provider_id](variables.tf#L26) | GCP workload identity pool provider ID. | <code>string</code> | ✓ | |
<!-- END TFDOC -->

View File

@ -27,9 +27,9 @@ provider "google-beta" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [impersonate_service_account_email](variables.tf#L22) | Service account to be impersonated by workload identity federation. | <code>string</code> | ✓ | |
| [workload_identity_pool_provider_id](variables.tf#L17) | GCP workload identity pool provider ID. | <code>string</code> | ✓ | |
| [tmp_oidc_token_path](variables.tf#L27) | Name of the temporary file where TFC OIDC token will be stored to authentificate terraform provider google. | <code>string</code> | | <code>&#34;.oidc_token&#34;</code> |
| [impersonate_service_account_email](variables.tf#L17) | Service account to be impersonated by workload identity federation. | <code>string</code> | ✓ | |
| [workload_identity_pool_provider_id](variables.tf#L28) | GCP workload identity pool provider ID. | <code>string</code> | ✓ | |
| [tmp_oidc_token_path](variables.tf#L22) | Name of the temporary file where TFC OIDC token will be stored to authentificate terraform provider google. | <code>string</code> | | <code>&#34;.oidc_token&#34;</code> |
## Outputs

View File

@ -14,11 +14,6 @@
* limitations under the License.
*/
variable "workload_identity_pool_provider_id" {
description = "GCP workload identity pool provider ID."
type = string
}
variable "impersonate_service_account_email" {
description = "Service account to be impersonated by workload identity federation."
type = string
@ -29,3 +24,8 @@ variable "tmp_oidc_token_path" {
type = string
default = ".oidc_token"
}
variable "workload_identity_pool_provider_id" {
description = "GCP workload identity pool provider ID."
type = string
}

View File

@ -13,13 +13,13 @@
# limitations under the License.
variable "project_id" {
description = "GCP project ID."
variable "impersonate_service_account_email" {
description = "Service account to be impersonated by workload identity."
type = string
}
variable "impersonate_service_account_email" {
description = "Service account to be impersonated by workload identity."
variable "project_id" {
description = "GCP project ID."
type = string
}

View File

@ -99,13 +99,13 @@ gcloud compute ssh --zone europe-west1-b nginx-test -- 'uptime'
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [billing_account](variables.tf#L16) | Billing account id used as default for new projects. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L33) | Project id to create a project when `project_create` is `true`, or to be used when `false`. | <code>string</code> | ✓ | |
| [grace_period](variables.tf#L56) | Grace period for an instance startup. | <code>string</code> | | <code>&#34;180s&#34;</code> |
| [location](variables.tf#L21) | App Engine location used in the example (required for CloudFunctions). | <code>string</code> | | <code>&#34;europe-west&#34;</code> |
| [project_create](variables.tf#L27) | Create project instead of using an existing one. | <code>bool</code> | | <code>false</code> |
| [region](variables.tf#L38) | Compute region used in the example. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [root_node](variables.tf#L44) | The resource name of the parent folder or organization for project creation, in 'folders/folder_id' or 'organizations/org_id' format. | <code>string</code> | | <code>null</code> |
| [schedule](variables.tf#L50) | Cron schedule for executing compute instances healthcheck. | <code>string</code> | | <code>&#34;&#42;&#47;5 &#42; &#42; &#42; &#42;&#34; &#35; every five minutes&#34;</code> |
| [project_id](variables.tf#L39) | Project id to create a project when `project_create` is `true`, or to be used when `false`. | <code>string</code> | ✓ | |
| [grace_period](variables.tf#L21) | Grace period for an instance startup. | <code>string</code> | | <code>&#34;180s&#34;</code> |
| [location](variables.tf#L27) | App Engine location used in the example (required for CloudFunctions). | <code>string</code> | | <code>&#34;europe-west&#34;</code> |
| [project_create](variables.tf#L33) | Create project instead of using an existing one. | <code>bool</code> | | <code>false</code> |
| [region](variables.tf#L44) | Compute region used in the example. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [root_node](variables.tf#L50) | The resource name of the parent folder or organization for project creation, in 'folders/folder_id' or 'organizations/org_id' format. | <code>string</code> | | <code>null</code> |
| [schedule](variables.tf#L56) | Cron schedule for executing compute instances healthcheck. | <code>string</code> | | <code>&#34;&#42;&#47;5 &#42; &#42; &#42; &#42;&#34; &#35; every five minutes&#34;</code> |
| [tcp_port](variables.tf#L62) | TCP port to run healthcheck against. | <code>string</code> | | <code>&#34;80&#34; &#35;http&#34;</code> |
| [timeout](variables.tf#L68) | TCP probe timeout. | <code>string</code> | | <code>&#34;1000ms&#34;</code> |

View File

@ -114,29 +114,28 @@ module "cf-restarter" {
region = var.region
bucket_name = "cf-bundle-bucket-${random_pet.random.id}"
bucket_config = {
location = var.region
lifecycle_delete_age = null
location = var.region
}
bundle_config = {
source_dir = "${path.module}/function/restarter"
output_path = "restarter.zip"
excludes = []
}
service_account = module.service-account-restarter.email
function_config = {
entry_point = "RestartInstance"
ingress_settings = null
instances = 1
memory = 256
instance_count = 1
memory_mb = 256
runtime = "go116"
timeout = 300
}
trigger_config = {
event = "google.pubsub.topic.publish"
resource = module.pubsub.topic.id
retry = null
v1 = {
event = "google.pubsub.topic.publish"
resource = module.pubsub.topic.id
}
}
}
@ -151,15 +150,14 @@ module "cf-healthchecker" {
bundle_config = {
source_dir = "${path.module}/function/healthchecker"
output_path = "healthchecker.zip"
excludes = []
}
service_account = module.service-account-healthchecker.email
function_config = {
entry_point = "HealthCheck"
ingress_settings = null
instances = 1
memory = 256
instance_count = 1
memory_mb = 256
runtime = "go116"
timeout = 300
}

View File

@ -18,6 +18,12 @@ variable "billing_account" {
type = string
}
variable "grace_period" {
description = "Grace period for an instance startup."
type = string
default = "180s"
}
variable "location" {
description = "App Engine location used in the example (required for CloudFunctions)."
type = string
@ -53,12 +59,6 @@ variable "schedule" {
default = "*/5 * * * *" # every five minutes
}
variable "grace_period" {
description = "Grace period for an instance startup."
type = string
default = "180s"
}
variable "tcp_port" {
description = "TCP port to run healthcheck against."
type = string

View File

@ -143,25 +143,25 @@ The above command will delete the associated resources so there will be no billa
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [postgres_user_password](variables.tf#L40) | `postgres` user password. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L51) | Unique prefix used for resource names. Not used for project if 'project_create' is null. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L65) | Project id, references existing project if `project_create` is null. | <code>string</code> | ✓ | |
| [data_eng_principals](variables.tf#L23) | Groups with Service Account Token creator role on service accounts in IAM format, only user supported on CloudSQL, eg 'user@domain.com'. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [network_config](variables.tf#L29) | Shared VPC network configurations to use. If null networks will be created in projects with preconfigured values. | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; network_self_link &#61; string&#10; subnet_self_link &#61; string&#10; cloudsql_psa_range &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [postgres_database](variables.tf#L45) | `postgres` database. | <code>string</code> | | <code>&#34;guestbook&#34;</code> |
| [project_create](variables.tf#L56) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [regions](variables.tf#L70) | Map of instance_name => location where instances will be deployed. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; primary &#61; &#34;europe-west1&#34;&#10; replica &#61; &#34;europe-west3&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [service_encryption_keys](variables.tf#L17) | Cloud KMS keys to use to encrypt resources. Provide a key for each reagion configured. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [sql_configuration](variables.tf#L84) | Cloud SQL configuration | <code title="object&#40;&#123;&#10; availability_type &#61; string&#10; database_version &#61; string&#10; psa_range &#61; string&#10; tier &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; availability_type &#61; &#34;REGIONAL&#34;&#10; database_version &#61; &#34;POSTGRES_13&#34;&#10; psa_range &#61; &#34;10.60.0.0&#47;16&#34;&#10; tier &#61; &#34;db-g1-small&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [prefix](variables.tf#L45) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L63) | Project id, references existing project if `project_create` is null. | <code>string</code> | ✓ | |
| [data_eng_principals](variables.tf#L17) | Groups with Service Account Token creator role on service accounts in IAM format, only user supported on CloudSQL, eg 'user@domain.com'. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [network_config](variables.tf#L23) | Shared VPC network configurations to use. If null networks will be created in projects with preconfigured values. | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; network_self_link &#61; string&#10; subnet_self_link &#61; string&#10; cloudsql_psa_range &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [postgres_database](variables.tf#L34) | `postgres` database. | <code>string</code> | | <code>&#34;guestbook&#34;</code> |
| [project_create](variables.tf#L54) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [regions](variables.tf#L68) | Map of instance_name => location where instances will be deployed. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; primary &#61; &#34;europe-west1&#34;&#10; replica &#61; &#34;europe-west3&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [service_encryption_keys](variables.tf#L81) | Cloud KMS keys to use to encrypt resources. Provide a key for each reagion configured. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [sql_configuration](variables.tf#L87) | Cloud SQL configuration | <code title="object&#40;&#123;&#10; availability_type &#61; string&#10; database_version &#61; string&#10; psa_range &#61; string&#10; tier &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; availability_type &#61; &#34;REGIONAL&#34;&#10; database_version &#61; &#34;POSTGRES_13&#34;&#10; psa_range &#61; &#34;10.60.0.0&#47;16&#34;&#10; tier &#61; &#34;db-g1-small&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [bucket](outputs.tf#L22) | Cloud storage bucket to import/export data from Cloud SQL. | |
| [connection_names](outputs.tf#L17) | Connection name of each instance. | |
| [demo_commands](outputs.tf#L37) | Demo commands. | |
| [ips](outputs.tf#L27) | IP address of each instance. | |
| [project_id](outputs.tf#L32) | ID of the project containing all the instances. | |
| [bucket](outputs.tf#L17) | Cloud storage bucket to import/export data from Cloud SQL. | |
| [connection_names](outputs.tf#L22) | Connection name of each instance. | |
| [demo_commands](outputs.tf#L27) | Demo commands. | |
| [ips](outputs.tf#L36) | IP address of each instance. | |
| [project_id](outputs.tf#L41) | ID of the project containing all the instances. | |
| [service_accounts](outputs.tf#L46) | Service Accounts. | |
<!-- END TFDOC -->

View File

@ -14,14 +14,23 @@
* limitations under the License.
*/
output "bucket" {
description = "Cloud storage bucket to import/export data from Cloud SQL."
value = module.gcs.name
}
output "connection_names" {
description = "Connection name of each instance."
value = module.db.connection_names
}
output "bucket" {
description = "Cloud storage bucket to import/export data from Cloud SQL."
value = module.gcs.name
output "demo_commands" {
description = "Demo commands."
value = {
"01_ssh" = "gcloud compute ssh ${module.test-vm.instance.name} --project ${module.project.name} --zone ${var.regions.primary}-b"
"02_cloud_sql_proxy" = "cloud_sql_proxy -enable_iam_login -instances=${module.db.connection_name}=tcp:5432 &"
"03_psql" = "psql 'host=127.0.0.1 port=5432 sslmode=disable dbname=${var.postgres_database} user=postgres password=PASSWORD'"
}
}
output "ips" {
@ -34,15 +43,6 @@ output "project_id" {
value = module.project.project_id
}
output "demo_commands" {
description = "Demo commands."
value = {
"01_ssh" = "gcloud compute ssh ${module.test-vm.instance.name} --project ${module.project.name} --zone ${var.regions.primary}-b"
"02_cloud_sql_proxy" = "cloud_sql_proxy -enable_iam_login -instances=${module.db.connection_name}=tcp:5432 &"
"03_psql" = "psql 'host=127.0.0.1 port=5432 sslmode=disable dbname=${var.postgres_database} user=postgres password=PASSWORD'"
}
}
output "service_accounts" {
description = "Service Accounts."
value = {

View File

@ -14,12 +14,6 @@
* limitations under the License.
*/
variable "service_encryption_keys" {
description = "Cloud KMS keys to use to encrypt resources. Provide a key for each reagion configured."
type = map(string)
default = null
}
variable "data_eng_principals" {
description = "Groups with Service Account Token creator role on service accounts in IAM format, only user supported on CloudSQL, eg 'user@domain.com'."
type = list(string)
@ -37,22 +31,26 @@ variable "network_config" {
default = null
}
variable "postgres_user_password" {
description = "`postgres` user password."
type = string
}
variable "postgres_database" {
description = "`postgres` database."
type = string
default = "guestbook"
}
variable "prefix" {
description = "Unique prefix used for resource names. Not used for project if 'project_create' is null."
variable "postgres_user_password" {
description = "`postgres` user password."
type = string
}
variable "prefix" {
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_create" {
description = "Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format."
type = object({
@ -80,6 +78,11 @@ variable "regions" {
}
}
variable "service_encryption_keys" {
description = "Cloud KMS keys to use to encrypt resources. Provide a key for each reagion configured."
type = map(string)
default = null
}
variable "sql_configuration" {
description = "Cloud SQL configuration"

View File

@ -96,14 +96,14 @@ service_encryption_keys = {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [prefix](variables.tf#L78) | Unique prefix used for resource names. Not used for project if 'project_create' is null. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L92) | Project id, references existing project if `project_create` is null. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L78) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L96) | Project id, references existing project if `project_create` is null. | <code>string</code> | ✓ | |
| [composer_config](variables.tf#L17) | Composer environment configuration. It accepts only following attributes: `environment_size`, `software_config` and `workloads_config`. See [attribute reference](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/composer_environment#argument-reference---cloud-composer-2) for details on settings variables. | <code title="object&#40;&#123;&#10; environment_size &#61; string&#10; software_config &#61; any&#10; workloads_config &#61; object&#40;&#123;&#10; scheduler &#61; object&#40;&#10; &#123;&#10; cpu &#61; number&#10; memory_gb &#61; number&#10; storage_gb &#61; number&#10; count &#61; number&#10; &#125;&#10; &#41;&#10; web_server &#61; object&#40;&#10; &#123;&#10; cpu &#61; number&#10; memory_gb &#61; number&#10; storage_gb &#61; number&#10; &#125;&#10; &#41;&#10; worker &#61; object&#40;&#10; &#123;&#10; cpu &#61; number&#10; memory_gb &#61; number&#10; storage_gb &#61; number&#10; min_count &#61; number&#10; max_count &#61; number&#10; &#125;&#10; &#41;&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; environment_size &#61; &#34;ENVIRONMENT_SIZE_SMALL&#34;&#10; software_config &#61; &#123;&#10; image_version &#61; &#34;composer-2-airflow-2&#34;&#10; &#125;&#10; workloads_config &#61; null&#10;&#125;">&#123;&#8230;&#125;</code> |
| [iam_groups_map](variables.tf#L58) | Map of Role => groups to be added on the project. Example: { \"roles/composer.admin\" = [\"group:gcp-data-engineers@example.com\"]}. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>null</code> |
| [network_config](variables.tf#L64) | Shared VPC network configurations to use. If null networks will be created in projects with preconfigured values. | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; network_self_link &#61; string&#10; subnet_self_link &#61; string&#10; composer_secondary_ranges &#61; object&#40;&#123;&#10; pods &#61; string&#10; services &#61; string&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [project_create](variables.tf#L83) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L97) | Reagion where instances will be deployed. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [service_encryption_keys](variables.tf#L103) | Cloud KMS keys to use to encrypt resources. Provide a key for each reagion in use. | <code>map&#40;string&#41;</code> | | <code>null</code> |
| [project_create](variables.tf#L87) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L101) | Reagion where instances will be deployed. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [service_encryption_keys](variables.tf#L107) | Cloud KMS keys to use to encrypt resources. Provide a key for each reagion in use. | <code>map&#40;string&#41;</code> | | <code>null</code> |
## Outputs

View File

@ -22,7 +22,6 @@ locals {
},
var.iam_groups_map
)
# Adding Roles on Service Identities Service account as per documentation: https://cloud.google.com/composer/docs/composer-2/configure-shared-vpc#edit_permissions_for_the_google_apis_service_account
_shared_vpc_bindings = {
"roles/compute.networkUser" = [

View File

@ -76,8 +76,12 @@ variable "network_config" {
}
variable "prefix" {
description = "Unique prefix used for resource names. Not used for project if 'project_create' is null."
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_create" {

View File

@ -135,7 +135,6 @@ service_encryption_keys = {
storage = "KEY_URL_MULTIREGIONAL"
pubsub = "KEY_URL_MULTIREGIONAL"
}
# tftest skip
```
This step is optional and depends on customer policies and security best practices.
@ -198,8 +197,7 @@ billing_account_id = "111111-222222-333333"
older_id = "folders/123456789012"
organization_domain = "domain.com"
prefix = "myco"
# tftest skip`
``
```
For more fine details check variables on [`variables.tf`](./variables.tf) and update according to the desired configuration. Remember to create team groups described [below](#groups).
@ -251,29 +249,29 @@ You can find examples in the `[demo](./demo)` folder.
| [billing_account_id](variables.tf#L17) | Billing account id. | <code>string</code> | ✓ | |
| [folder_id](variables.tf#L53) | Folder to be used for the networking resources in folders/nnnn format. | <code>string</code> | ✓ | |
| [organization_domain](variables.tf#L98) | Organization domain. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L103) | Unique prefix used for resource names. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L103) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [composer_config](variables.tf#L22) | Cloud Composer config. | <code title="object&#40;&#123;&#10; node_count &#61; number&#10; airflow_version &#61; string&#10; env_variables &#61; map&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; node_count &#61; 3&#10; airflow_version &#61; &#34;composer-1-airflow-2&#34;&#10; env_variables &#61; &#123;&#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [data_catalog_tags](variables.tf#L36) | List of Data Catalog Policy tags to be created with optional IAM binging configuration in {tag => {ROLE => [MEMBERS]}} format. | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code title="&#123;&#10; &#34;3_Confidential&#34; &#61; null&#10; &#34;2_Private&#34; &#61; null&#10; &#34;1_Sensitive&#34; &#61; null&#10;&#125;">&#123;&#8230;&#125;</code> |
| [data_force_destroy](variables.tf#L47) | Flag to set 'force_destroy' on data services like BiguQery or Cloud Storage. | <code>bool</code> | | <code>false</code> |
| [groups](variables.tf#L58) | User groups. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; data-analysts &#61; &#34;gcp-data-analysts&#34;&#10; data-engineers &#61; &#34;gcp-data-engineers&#34;&#10; data-security &#61; &#34;gcp-data-security&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [location](variables.tf#L68) | Location used for multi-regional resources. | <code>string</code> | | <code>&#34;eu&#34;</code> |
| [network_config](variables.tf#L74) | Shared VPC network configurations to use. If null networks will be created in projects with preconfigured values. | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; network_self_link &#61; string&#10; subnet_self_links &#61; object&#40;&#123;&#10; load &#61; string&#10; transformation &#61; string&#10; orchestration &#61; string&#10; &#125;&#41;&#10; composer_ip_ranges &#61; object&#40;&#123;&#10; cloudsql &#61; string&#10; gke_master &#61; string&#10; web_server &#61; string&#10; &#125;&#41;&#10; composer_secondary_ranges &#61; object&#40;&#123;&#10; pods &#61; string&#10; services &#61; string&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [project_services](variables.tf#L108) | List of core services enabled on all projects. | <code>list&#40;string&#41;</code> | | <code title="&#91;&#10; &#34;cloudresourcemanager.googleapis.com&#34;,&#10; &#34;iam.googleapis.com&#34;,&#10; &#34;serviceusage.googleapis.com&#34;,&#10; &#34;stackdriver.googleapis.com&#34;&#10;&#93;">&#91;&#8230;&#93;</code> |
| [project_suffix](variables.tf#L119) | Suffix used only for project ids. | <code>string</code> | | <code>null</code> |
| [region](variables.tf#L125) | Region used for regional resources. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [service_encryption_keys](variables.tf#L131) | Cloud KMS to use to encrypt different services. Key location should match service region. | <code title="object&#40;&#123;&#10; bq &#61; string&#10; composer &#61; string&#10; dataflow &#61; string&#10; storage &#61; string&#10; pubsub &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [project_services](variables.tf#L112) | List of core services enabled on all projects. | <code>list&#40;string&#41;</code> | | <code title="&#91;&#10; &#34;cloudresourcemanager.googleapis.com&#34;,&#10; &#34;iam.googleapis.com&#34;,&#10; &#34;serviceusage.googleapis.com&#34;,&#10; &#34;stackdriver.googleapis.com&#34;&#10;&#93;">&#91;&#8230;&#93;</code> |
| [project_suffix](variables.tf#L123) | Suffix used only for project ids. | <code>string</code> | | <code>null</code> |
| [region](variables.tf#L129) | Region used for regional resources. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [service_encryption_keys](variables.tf#L135) | Cloud KMS to use to encrypt different services. Key location should match service region. | <code title="object&#40;&#123;&#10; bq &#61; string&#10; composer &#61; string&#10; dataflow &#61; string&#10; storage &#61; string&#10; pubsub &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [bigquery-datasets](outputs.tf#L17) | BigQuery datasets. | |
| [demo_commands](outputs.tf#L93) | Demo commands. | |
| [gcs-buckets](outputs.tf#L28) | GCS buckets. | |
| [kms_keys](outputs.tf#L42) | Cloud MKS keys. | |
| [projects](outputs.tf#L47) | GCP Projects informations. | |
| [vpc_network](outputs.tf#L75) | VPC network. | |
| [vpc_subnet](outputs.tf#L84) | VPC subnetworks. | |
| [demo_commands](outputs.tf#L28) | Demo commands. | |
| [gcs-buckets](outputs.tf#L41) | GCS buckets. | |
| [kms_keys](outputs.tf#L55) | Cloud MKS keys. | |
| [projects](outputs.tf#L60) | GCP Projects informations. | |
| [vpc_network](outputs.tf#L88) | VPC network. | |
| [vpc_subnet](outputs.tf#L97) | VPC subnetworks. | |
<!-- END TFDOC -->
## TODOs

View File

@ -25,6 +25,19 @@ output "bigquery-datasets" {
}
}
output "demo_commands" {
description = "Demo commands."
value = {
01 = "gsutil -i ${module.drop-sa-cs-0.email} cp demo/data/*.csv gs://${module.drop-cs-0.name}"
02 = "gsutil -i ${module.orch-sa-cmp-0.email} cp demo/data/*.j* gs://${module.orch-cs-0.name}"
03 = "gsutil -i ${module.orch-sa-cmp-0.email} cp demo/*.py ${google_composer_environment.orch-cmp-0.config[0].dag_gcs_prefix}/"
04 = "Open ${google_composer_environment.orch-cmp-0.config.0.airflow_uri} and run uploaded DAG."
05 = <<EOT
bq query --project_id=${module.dwh-conf-project.project_id} --use_legacy_sql=false 'SELECT * EXCEPT (name, surname) FROM `${module.dwh-conf-project.project_id}.${module.dwh-conf-bq-0.dataset_id}.customer_purchase` LIMIT 1000'"
EOT
}
}
output "gcs-buckets" {
description = "GCS buckets."
value = {
@ -89,16 +102,3 @@ output "vpc_subnet" {
transformation = local.transf_subnet
}
}
output "demo_commands" {
description = "Demo commands."
value = {
01 = "gsutil -i ${module.drop-sa-cs-0.email} cp demo/data/*.csv gs://${module.drop-cs-0.name}"
02 = "gsutil -i ${module.orch-sa-cmp-0.email} cp demo/data/*.j* gs://${module.orch-cs-0.name}"
03 = "gsutil -i ${module.orch-sa-cmp-0.email} cp demo/*.py ${google_composer_environment.orch-cmp-0.config[0].dag_gcs_prefix}/"
04 = "Open ${google_composer_environment.orch-cmp-0.config.0.airflow_uri} and run uploaded DAG."
05 = <<EOT
bq query --project_id=${module.dwh-conf-project.project_id} --use_legacy_sql=false 'SELECT * EXCEPT (name, surname) FROM `${module.dwh-conf-project.project_id}.${module.dwh-conf-bq-0.dataset_id}.customer_purchase` LIMIT 1000'"
EOT
}
}

View File

@ -101,8 +101,12 @@ variable "organization_domain" {
}
variable "prefix" {
description = "Unique prefix used for resource names."
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_services" {

View File

@ -47,12 +47,12 @@ You can now connect to the Vertex AI notbook to perform your data analysy.
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [prefix](variables.tf#L36) | Unique prefix used for resource names. Not used for project if 'project_create' is null. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L22) | Project id, references existing project if `project_create` is null. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L22) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L40) | Project id, references existing project if `project_create` is null. | <code>string</code> | ✓ | |
| [location](variables.tf#L16) | The location where resources will be deployed. | <code>string</code> | | <code>&#34;EU&#34;</code> |
| [project_create](variables.tf#L27) | Provide values if project creation is needed, uses existing project if null. Parent format: folders/folder_id or organizations/org_id | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L41) | The region where resources will be deployed. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [vpc_config](variables.tf#L57) | Parameters to create a VPC. | <code title="object&#40;&#123;&#10; ip_cidr_range &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; ip_cidr_range &#61; &#34;10.0.0.0&#47;20&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [project_create](variables.tf#L31) | Provide values if project creation is needed, uses existing project if null. Parent format: folders/folder_id or organizations/org_id | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L45) | The region where resources will be deployed. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [vpc_config](variables.tf#L61) | Parameters to create a VPC. | <code title="object&#40;&#123;&#10; ip_cidr_range &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; ip_cidr_range &#61; &#34;10.0.0.0&#47;20&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
## Outputs

View File

@ -19,9 +19,13 @@ variable "location" {
default = "EU"
}
variable "project_id" {
description = "Project id, references existing project if `project_create` is null."
variable "prefix" {
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_create" {
@ -33,8 +37,8 @@ variable "project_create" {
default = null
}
variable "prefix" {
description = "Unique prefix used for resource names. Not used for project if 'project_create' is null."
variable "project_id" {
description = "Project id, references existing project if `project_create` is null."
type = string
}

View File

@ -193,14 +193,14 @@ The above command will delete the associated resources so there will be no billa
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [prefix](variables.tf#L36) | Unique prefix used for resource names. Not used for project if 'project_create' is null. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L50) | Project id, references existing project if `project_create` is null. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L36) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L54) | Project id, references existing project if `project_create` is null. | <code>string</code> | ✓ | |
| [cmek_encryption](variables.tf#L15) | Flag to enable CMEK on GCP resources created. | <code>bool</code> | | <code>false</code> |
| [data_eng_principals](variables.tf#L21) | Groups with Service Account Token creator role on service accounts in IAM format, eg 'group:group@domain.com'. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [network_config](variables.tf#L27) | Shared VPC network configurations to use. If null networks will be created in projects with preconfigured values. | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; subnet_self_link &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [project_create](variables.tf#L41) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L55) | The region where resources will be deployed. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [vpc_subnet_range](variables.tf#L61) | Ip range used for the VPC subnet created for the example. | <code>string</code> | | <code>&#34;10.0.0.0&#47;20&#34;</code> |
| [project_create](variables.tf#L45) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L59) | The region where resources will be deployed. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [vpc_subnet_range](variables.tf#L65) | Ip range used for the VPC subnet created for the example. | <code>string</code> | | <code>&#34;10.0.0.0&#47;20&#34;</code> |
## Outputs
@ -208,10 +208,10 @@ The above command will delete the associated resources so there will be no billa
|---|---|:---:|
| [bq_tables](outputs.tf#L15) | Bigquery Tables. | |
| [buckets](outputs.tf#L20) | GCS bucket Cloud KMS crypto keys. | |
| [command_01_gcs](outputs.tf#L43) | gcloud command to copy data into the created bucket impersonating the service account. | |
| [command_02_dataflow](outputs.tf#L48) | Command to run Dataflow template impersonating the service account. | |
| [command_03_bq](outputs.tf#L69) | BigQuery command to query imported data. | |
| [project_id](outputs.tf#L28) | Project id. | |
| [service_accounts](outputs.tf#L33) | Service account. | |
| [command_01_gcs](outputs.tf#L28) | gcloud command to copy data into the created bucket impersonating the service account. | |
| [command_02_dataflow](outputs.tf#L33) | Command to run Dataflow template impersonating the service account. | |
| [command_03_bq](outputs.tf#L54) | BigQuery command to query imported data. | |
| [project_id](outputs.tf#L64) | Project id. | |
| [service_accounts](outputs.tf#L69) | Service account. | |
<!-- END TFDOC -->

View File

@ -25,21 +25,6 @@ output "buckets" {
}
}
output "project_id" {
description = "Project id."
value = module.project.project_id
}
output "service_accounts" {
description = "Service account."
value = {
bq = module.service-account-bq.email
df = module.service-account-df.email
orch = module.service-account-orch.email
landing = module.service-account-landing.email
}
}
output "command_01_gcs" {
description = "gcloud command to copy data into the created bucket impersonating the service account."
value = "gsutil -i ${module.service-account-landing.email} cp data-demo/* ${module.gcs-data.url}"
@ -75,3 +60,18 @@ output "command_03_bq" {
sql_limit = 1000
})
}
output "project_id" {
description = "Project id."
value = module.project.project_id
}
output "service_accounts" {
description = "Service account."
value = {
bq = module.service-account-bq.email
df = module.service-account-df.email
orch = module.service-account-orch.email
landing = module.service-account-landing.email
}
}

View File

@ -34,8 +34,12 @@ variable "network_config" {
}
variable "prefix" {
description = "Unique prefix used for resource names. Not used for project if 'project_create' is null."
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_create" {

View File

@ -35,32 +35,32 @@ and to `C:\GcpSetupLog.txt` file.
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [ad_domain_fqdn](variables.tf#L111) | Active Directory domain (FQDN) | <code>string</code> | ✓ | |
| [ad_domain_netbios](variables.tf#L120) | Active Directory domain (NetBIOS) | <code>string</code> | ✓ | |
| [network](variables.tf#L38) | Network to use in the project | <code>string</code> | ✓ | |
| [project_id](variables.tf#L27) | Google Cloud project ID | <code>string</code> | ✓ | |
| [sql_admin_password](variables.tf#L102) | Password for the SQL admin user to be created | <code>string</code> | ✓ | |
| [subnetwork](variables.tf#L43) | Subnetwork to use in the project | <code>string</code> | ✓ | |
| [always_on_groups](variables.tf#L135) | List of Always On Groups | <code>list&#40;string&#41;</code> | | <code>&#91;&#34;bookshelf&#34;&#93;</code> |
| [boot_disk_size](variables.tf#L90) | Boot disk size in GB | <code>number</code> | | <code>50</code> |
| [cluster_name](variables.tf#L48) | Cluster name (prepended with prefix) | <code>string</code> | | <code>&#34;cluster&#34;</code> |
| [data_disk_size](variables.tf#L96) | Database disk size in GB | <code>number</code> | | <code>200</code> |
| [health_check_config](variables.tf#L147) | Health check configuration | <code title="object&#40;&#123; check_interval_sec &#61; number,&#10; healthy_threshold &#61; number,&#10; unhealthy_threshold &#61; number,&#10; timeout_sec &#61; number,&#10;&#125;&#41;">&#8230;</code> | | <code title="&#123;&#10; check_interval_sec &#61; 2&#10; healthy_threshold &#61; 1&#10; unhealthy_threshold &#61; 2&#10; timeout_sec &#61; 1&#10;&#125;">&#123;&#8230;&#125;</code> |
| [health_check_port](variables.tf#L141) | Health check port | <code>number</code> | | <code>59997</code> |
| [health_check_ranges](variables.tf#L60) | Health check ranges | <code>list&#40;string&#41;</code> | | <code>&#91;&#34;35.191.0.0&#47;16&#34;, &#34;209.85.152.0&#47;22&#34;, &#34;209.85.204.0&#47;22&#34;&#93;</code> |
| [managed_ad_dn](variables.tf#L129) | Managed Active Directory domain (eg. OU=Cloud,DC=example,DC=com) | <code>string</code> | | <code>&#34;&#34;</code> |
| [node_image](variables.tf#L78) | SQL Server node machine image | <code>string</code> | | <code>&#34;projects&#47;windows-sql-cloud&#47;global&#47;images&#47;family&#47;sql-ent-2019-win-2019&#34;</code> |
| [node_instance_type](variables.tf#L66) | SQL Server database node instance type | <code>string</code> | | <code>&#34;n2-standard-8&#34;</code> |
| [node_name](variables.tf#L162) | Node base name | <code>string</code> | | <code>&#34;node&#34;</code> |
| [prefix](variables.tf#L15) | Prefix used for resources (for multiple clusters in a project) | <code>string</code> | | <code>&#34;aog&#34;</code> |
| [project_create](variables.tf#L174) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L21) | Region for resources | <code>string</code> | | <code>&#34;europe-west4&#34;</code> |
| [shared_vpc_project_id](variables.tf#L32) | Shared VPC project ID for firewall rules | <code>string</code> | | <code>null</code> |
| [sql_client_cidrs](variables.tf#L54) | CIDR ranges that are allowed to connect to SQL Server | <code>list&#40;string&#41;</code> | | <code>&#91;&#34;0.0.0.0&#47;0&#34;&#93;</code> |
| [vpc_ip_cidr_range](variables.tf#L183) | Ip range used in the subnet deployef in the Service Project. | <code>string</code> | | <code>&#34;10.0.0.0&#47;20&#34;</code> |
| [witness_image](variables.tf#L84) | SQL Server witness machine image | <code>string</code> | | <code>&#34;projects&#47;windows-cloud&#47;global&#47;images&#47;family&#47;windows-2019&#34;</code> |
| [witness_instance_type](variables.tf#L72) | SQL Server witness node instance type | <code>string</code> | | <code>&#34;n2-standard-2&#34;</code> |
| [witness_name](variables.tf#L168) | Witness base name | <code>string</code> | | <code>&#34;witness&#34;</code> |
| [ad_domain_fqdn](variables.tf#L15) | Active Directory domain (FQDN) | <code>string</code> | ✓ | |
| [ad_domain_netbios](variables.tf#L24) | Active Directory domain (NetBIOS) | <code>string</code> | ✓ | |
| [network](variables.tf#L90) | Network to use in the project | <code>string</code> | ✓ | |
| [prefix](variables.tf#L113) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L131) | Google Cloud project ID | <code>string</code> | ✓ | |
| [sql_admin_password](variables.tf#L148) | Password for the SQL admin user to be created | <code>string</code> | ✓ | |
| [subnetwork](variables.tf#L163) | Subnetwork to use in the project | <code>string</code> | ✓ | |
| [always_on_groups](variables.tf#L33) | List of Always On Groups | <code>list&#40;string&#41;</code> | | <code>&#91;&#34;bookshelf&#34;&#93;</code> |
| [boot_disk_size](variables.tf#L39) | Boot disk size in GB | <code>number</code> | | <code>50</code> |
| [cluster_name](variables.tf#L45) | Cluster name (prepended with prefix) | <code>string</code> | | <code>&#34;cluster&#34;</code> |
| [data_disk_size](variables.tf#L51) | Database disk size in GB | <code>number</code> | | <code>200</code> |
| [health_check_config](variables.tf#L57) | Health check configuration | <code title="object&#40;&#123; check_interval_sec &#61; number,&#10; healthy_threshold &#61; number,&#10; unhealthy_threshold &#61; number,&#10; timeout_sec &#61; number,&#10;&#125;&#41;">&#8230;</code> | | <code title="&#123;&#10; check_interval_sec &#61; 2&#10; healthy_threshold &#61; 1&#10; unhealthy_threshold &#61; 2&#10; timeout_sec &#61; 1&#10;&#125;">&#123;&#8230;&#125;</code> |
| [health_check_port](variables.tf#L72) | Health check port | <code>number</code> | | <code>59997</code> |
| [health_check_ranges](variables.tf#L78) | Health check ranges | <code>list&#40;string&#41;</code> | | <code>&#91;&#34;35.191.0.0&#47;16&#34;, &#34;209.85.152.0&#47;22&#34;, &#34;209.85.204.0&#47;22&#34;&#93;</code> |
| [managed_ad_dn](variables.tf#L84) | Managed Active Directory domain (eg. OU=Cloud,DC=example,DC=com) | <code>string</code> | | <code>&#34;&#34;</code> |
| [node_image](variables.tf#L95) | SQL Server node machine image | <code>string</code> | | <code>&#34;projects&#47;windows-sql-cloud&#47;global&#47;images&#47;family&#47;sql-ent-2019-win-2019&#34;</code> |
| [node_instance_type](variables.tf#L101) | SQL Server database node instance type | <code>string</code> | | <code>&#34;n2-standard-8&#34;</code> |
| [node_name](variables.tf#L107) | Node base name | <code>string</code> | | <code>&#34;node&#34;</code> |
| [project_create](variables.tf#L122) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L136) | Region for resources | <code>string</code> | | <code>&#34;europe-west4&#34;</code> |
| [shared_vpc_project_id](variables.tf#L142) | Shared VPC project ID for firewall rules | <code>string</code> | | <code>null</code> |
| [sql_client_cidrs](variables.tf#L157) | CIDR ranges that are allowed to connect to SQL Server | <code>list&#40;string&#41;</code> | | <code>&#91;&#34;0.0.0.0&#47;0&#34;&#93;</code> |
| [vpc_ip_cidr_range](variables.tf#L168) | Ip range used in the subnet deployef in the Service Project. | <code>string</code> | | <code>&#34;10.0.0.0&#47;20&#34;</code> |
| [witness_image](variables.tf#L174) | SQL Server witness machine image | <code>string</code> | | <code>&#34;projects&#47;windows-cloud&#47;global&#47;images&#47;family&#47;windows-2019&#34;</code> |
| [witness_instance_type](variables.tf#L180) | SQL Server witness node instance type | <code>string</code> | | <code>&#34;n2-standard-2&#34;</code> |
| [witness_name](variables.tf#L186) | Witness base name | <code>string</code> | | <code>&#34;witness&#34;</code> |
## Outputs

View File

@ -30,8 +30,8 @@ locals {
managed_ad_dn_path = var.managed_ad_dn != "" ? "-Path \"${var.managed_ad_dn}\"" : ""
health_check_port = var.health_check_port
sql_admin_password_secret = local._secret_parts[length(local._secret_parts) - 1]
cluster_ip = module.ip-addresses.internal_addresses["${local.prefix}cluster"].address
loadbalancer_ips = jsonencode({ for aog in var.always_on_groups : aog => module.ip-addresses.internal_addresses["${local.prefix}lb-${aog}"].address })
cluster_ip = module.ip-addresses.internal_addresses["${var.prefix}-cluster"].address
loadbalancer_ips = jsonencode({ for aog in var.always_on_groups : aog => module.ip-addresses.internal_addresses["${var.prefix}-lb-${aog}"].address })
sql_cluster_name = local.cluster_netbios_name
sql_cluster_full = local.cluster_full_name
node_netbios_1 = local.node_netbios_names[0]
@ -43,7 +43,7 @@ locals {
_template_vars = merge(local._template_vars0, {
functions = local._functions
})
_user_name = "${local.prefix}sqlserver"
_user_name = "${var.prefix}-sqlserver"
scripts = {
for script in local._scripts :
script => templatefile("${path.module}/scripts/${script}.ps1", local._template_vars)

View File

@ -14,14 +14,14 @@
locals {
ad_user_password_secret = "${local.cluster_full_name}-password"
cluster_full_name = "${local.prefix}${var.cluster_name}"
cluster_full_name = "${var.prefix}-${var.cluster_name}"
cluster_netbios_name = (
length(local.cluster_full_name) > 15
? substr(local.cluster_full_name, 0, 15)
: local.cluster_full_name
)
network = module.vpc.self_link
node_base = "${local.prefix}${var.node_name}"
node_base = "${var.prefix}-${var.node_name}"
node_prefix = (
length(local.node_base) > 12
? substr(local.node_base, 0, 12)
@ -39,7 +39,6 @@ locals {
(local.witness_netbios_name) = local.zones[length(local.zones) - 1]
}
)
prefix = var.prefix != "" ? "${var.prefix}-" : ""
subnetwork = (
var.project_create != null
? module.vpc.subnet_self_links["${var.region}/${var.subnetwork}"]
@ -50,7 +49,7 @@ locals {
? var.shared_vpc_project_id
: module.project.project_id
)
witness_name = "${local.prefix}${var.witness_name}"
witness_name = "${var.prefix}-${var.witness_name}"
witness_netbios_name = (
length(local.witness_name) > 15
? substr(local.witness_name, 0, 15)

View File

@ -19,7 +19,7 @@
module "compute-service-account" {
source = "../../../modules/iam-service-account"
project_id = var.project_id
name = format("%swsfc", local.prefix)
name = "${var.prefix}-wsfc"
iam_project_roles = {
(var.project_id) = [
@ -35,7 +35,7 @@ module "compute-service-account" {
module "witness-service-account" {
source = "../../../modules/iam-service-account"
project_id = var.project_id
name = format("%swsfc-witness", local.prefix)
name = "${var.prefix}-wsfc-witness"
iam_project_roles = {
(var.project_id) = [

View File

@ -12,102 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
variable "prefix" {
description = "Prefix used for resources (for multiple clusters in a project)"
type = string
default = "aog"
}
variable "region" {
description = "Region for resources"
type = string
default = "europe-west4"
}
variable "project_id" {
description = "Google Cloud project ID"
type = string
}
variable "shared_vpc_project_id" {
description = "Shared VPC project ID for firewall rules"
type = string
default = null
}
variable "network" {
description = "Network to use in the project"
type = string
}
variable "subnetwork" {
description = "Subnetwork to use in the project"
type = string
}
variable "cluster_name" {
description = "Cluster name (prepended with prefix)"
type = string
default = "cluster"
}
variable "sql_client_cidrs" {
description = "CIDR ranges that are allowed to connect to SQL Server"
type = list(string)
default = ["0.0.0.0/0"]
}
variable "health_check_ranges" {
description = "Health check ranges"
type = list(string)
default = ["35.191.0.0/16", "209.85.152.0/22", "209.85.204.0/22"]
}
variable "node_instance_type" {
description = "SQL Server database node instance type"
type = string
default = "n2-standard-8"
}
variable "witness_instance_type" {
description = "SQL Server witness node instance type"
type = string
default = "n2-standard-2"
}
variable "node_image" {
description = "SQL Server node machine image"
type = string
default = "projects/windows-sql-cloud/global/images/family/sql-ent-2019-win-2019"
}
variable "witness_image" {
description = "SQL Server witness machine image"
type = string
default = "projects/windows-cloud/global/images/family/windows-2019"
}
variable "boot_disk_size" {
description = "Boot disk size in GB"
type = number
default = 50
}
variable "data_disk_size" {
description = "Database disk size in GB"
type = number
default = 200
}
variable "sql_admin_password" {
description = "Password for the SQL admin user to be created"
type = string
validation {
condition = length(var.sql_admin_password) > 0
error_message = "SQL administrator password needs to be specified."
}
}
variable "ad_domain_fqdn" {
description = "Active Directory domain (FQDN)"
type = string
@ -126,22 +30,28 @@ variable "ad_domain_netbios" {
}
}
variable "managed_ad_dn" {
description = "Managed Active Directory domain (eg. OU=Cloud,DC=example,DC=com)"
type = string
default = ""
}
variable "always_on_groups" {
description = "List of Always On Groups"
type = list(string)
default = ["bookshelf"]
}
variable "health_check_port" {
description = "Health check port"
variable "boot_disk_size" {
description = "Boot disk size in GB"
type = number
default = 59997
default = 50
}
variable "cluster_name" {
description = "Cluster name (prepended with prefix)"
type = string
default = "cluster"
}
variable "data_disk_size" {
description = "Database disk size in GB"
type = number
default = 200
}
variable "health_check_config" {
@ -159,16 +69,54 @@ variable "health_check_config" {
}
}
variable "health_check_port" {
description = "Health check port"
type = number
default = 59997
}
variable "health_check_ranges" {
description = "Health check ranges"
type = list(string)
default = ["35.191.0.0/16", "209.85.152.0/22", "209.85.204.0/22"]
}
variable "managed_ad_dn" {
description = "Managed Active Directory domain (eg. OU=Cloud,DC=example,DC=com)"
type = string
default = ""
}
variable "network" {
description = "Network to use in the project"
type = string
}
variable "node_image" {
description = "SQL Server node machine image"
type = string
default = "projects/windows-sql-cloud/global/images/family/sql-ent-2019-win-2019"
}
variable "node_instance_type" {
description = "SQL Server database node instance type"
type = string
default = "n2-standard-8"
}
variable "node_name" {
description = "Node base name"
type = string
default = "node"
}
variable "witness_name" {
description = "Witness base name"
variable "prefix" {
description = "Prefix used for resource names."
type = string
default = "witness"
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_create" {
@ -180,8 +128,63 @@ variable "project_create" {
default = null
}
variable "project_id" {
description = "Google Cloud project ID"
type = string
}
variable "region" {
description = "Region for resources"
type = string
default = "europe-west4"
}
variable "shared_vpc_project_id" {
description = "Shared VPC project ID for firewall rules"
type = string
default = null
}
variable "sql_admin_password" {
description = "Password for the SQL admin user to be created"
type = string
validation {
condition = length(var.sql_admin_password) > 0
error_message = "SQL administrator password needs to be specified."
}
}
variable "sql_client_cidrs" {
description = "CIDR ranges that are allowed to connect to SQL Server"
type = list(string)
default = ["0.0.0.0/0"]
}
variable "subnetwork" {
description = "Subnetwork to use in the project"
type = string
}
variable "vpc_ip_cidr_range" {
description = "Ip range used in the subnet deployef in the Service Project."
type = string
default = "10.0.0.0/20"
}
variable "witness_image" {
description = "SQL Server witness machine image"
type = string
default = "projects/windows-cloud/global/images/family/windows-2019"
}
variable "witness_instance_type" {
description = "SQL Server witness node instance type"
type = string
default = "n2-standard-2"
}
variable "witness_name" {
description = "Witness base name"
type = string
default = "witness"
}

View File

@ -19,7 +19,7 @@ locals {
local.listeners,
local.node_ips,
{
"${local.prefix}cluster" = {
"${var.prefix}-cluster" = {
region = var.region
subnetwork = local.subnetwork
}
@ -34,7 +34,7 @@ locals {
k => v.address
}
listeners = {
for aog in var.always_on_groups : "${local.prefix}lb-${aog}" => {
for aog in var.always_on_groups : "${var.prefix}-lb-${aog}" => {
region = var.region
subnetwork = local.subnetwork
}
@ -83,7 +83,7 @@ module "firewall" {
disabled = true
}
ingress_rules = {
"${local.prefix}allow-all-between-wsfc-nodes" = {
"${var.prefix}-allow-all-between-wsfc-nodes" = {
description = "Allow all between WSFC nodes"
sources = [module.compute-service-account.email]
targets = [module.compute-service-account.email]
@ -94,7 +94,7 @@ module "firewall" {
{ protocol = "icmp" }
]
}
"${local.prefix}allow-all-between-wsfc-witness" = {
"${var.prefix}-allow-all-between-wsfc-witness" = {
description = "Allow all between WSFC witness nodes"
sources = [module.compute-service-account.email]
targets = [module.witness-service-account.email]
@ -105,7 +105,7 @@ module "firewall" {
{ protocol = "icmp" }
]
}
"${local.prefix}allow-sql-to-wsfc-nodes" = {
"${var.prefix}-allow-sql-to-wsfc-nodes" = {
description = "Allow SQL connections to WSFC nodes"
targets = [module.compute-service-account.email]
ranges = var.sql_client_cidrs
@ -114,7 +114,7 @@ module "firewall" {
{ protocol = "tcp", ports = [1433] },
]
}
"${local.prefix}allow-health-check-to-wsfc-nodes" = {
"${var.prefix}-allow-health-check-to-wsfc-nodes" = {
description = "Allow health checks to WSFC nodes"
targets = [module.compute-service-account.email]
ranges = var.health_check_ranges
@ -139,7 +139,7 @@ module "listener-ilb" {
region = var.region
name = "${var.prefix}-${each.value}-ilb"
service_label = "${var.prefix}-${each.value}-ilb"
address = local.internal_address_ips["${local.prefix}lb-${each.value}"]
address = local.internal_address_ips["${var.prefix}-lb-${each.value}"]
vpc_config = {
network = local.network
subnetwork = local.subnetwork

View File

@ -67,20 +67,17 @@ labels: # not required, defaults to {}, Example: {"a":"thisislabela","b":"thisis
use_legacy_sql: bool # not required, defaults to false
deletion_protection: bool # not required, defaults to false
```
<!-- BEGIN TFDOC -->
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [project_id](variables.tf#L27) | Project ID | <code>string</code> | ✓ | |
| [project_id](variables.tf#L17) | Project ID | <code>string</code> | ✓ | |
| [tables_dir](variables.tf#L22) | Relative path for the folder storing table data. | <code>string</code> | ✓ | |
| [views_dir](variables.tf#L17) | Relative path for the folder storing view data. | <code>string</code> | ✓ | |
| [views_dir](variables.tf#L27) | Relative path for the folder storing view data. | <code>string</code> | ✓ | |
<!-- END TFDOC -->
## TODO
- [ ] add external table support

View File

@ -14,8 +14,8 @@
* limitations under the License.
*/
variable "views_dir" {
description = "Relative path for the folder storing view data."
variable "project_id" {
description = "Project ID"
type = string
}
@ -24,8 +24,7 @@ variable "tables_dir" {
type = string
}
variable "project_id" {
description = "Project ID"
variable "views_dir" {
description = "Relative path for the folder storing view data."
type = string
}

View File

@ -1,6 +1,6 @@
# Google Cloud VPC Firewall Factory
This module allows creation and management of different types of firewall rules by defining them in well formatted `yaml` files.
This module allows creation and management of different types of firewall rules by defining them in well formatted `yaml` files.
Yaml abstraction for FW rules can simplify users onboarding and also makes rules definition simpler and clearer comparing to HCL.
@ -79,10 +79,10 @@ rule-name: # descriptive name, naming convention is adjusted by the module
destination_ranges: # list of destination ranges, should be specified only for `EGRESS` rule
- 0.0.0.0/0
source_tags: ['some-tag'] # list of source tags, should be specified only for `INGRESS` rule
source_service_accounts: # list of source service accounts, should be specified only for `INGRESS` rule, can not be specified together with `source_tags` or `target_tags`
source_service_accounts: # list of source service accounts, should be specified only for `INGRESS` rule, cannot be specified together with `source_tags` or `target_tags`
- myapp@myproject-id.iam.gserviceaccount.com
target_tags: ['some-tag'] # list of target tags
target_service_accounts: # list of target service accounts, , can not be specified together with `source_tags` or `target_tags`
target_service_accounts: # list of target service accounts, , cannot be specified together with `source_tags` or `target_tags`
- myapp@myproject-id.iam.gserviceaccount.com
```

View File

@ -69,6 +69,7 @@ module "projects" {
kms_service_agents = try(each.value.kms, {})
labels = try(each.value.labels, {})
org_policies = try(each.value.org_policies, {})
prefix = each.value.prefix
service_accounts = try(each.value.service_accounts, {})
services = try(each.value.services, [])
service_identities_iam = try(each.value.service_identities_iam, {})
@ -109,9 +110,9 @@ vpc_host_project: project-example-host-project
# [opt] Billing account id - overrides default if set
billing_account_id: 012345-67890A-BCDEF0
# [opt] Billing alerts config - overrides default if set
billing_alert:
billing_alert:
amount: 10
thresholds:
current:
@ -119,42 +120,42 @@ billing_alert:
- 0.8
forecasted: []
# [opt] DNS zones to be created as children of the environment_dns_zone defined in defaults
dns_zones:
# [opt] DNS zones to be created as children of the environment_dns_zone defined in defaults
dns_zones:
- lorem
- ipsum
# [opt] Contacts for billing alerts and important notifications
essential_contacts:
# [opt] Contacts for billing alerts and important notifications
essential_contacts:
- team-a-contacts@example.com
# Folder the project will be created as children of
folder_id: folders/012345678901
# [opt] Authoritative IAM bindings in group => [roles] format
group_iam:
group_iam:
test-team-foobar@fast-lab-0.gcp-pso-italy.net:
- roles/compute.admin
# [opt] Authoritative IAM bindings in role => [principals] format
# Generally used to grant roles to service accounts external to the project
iam:
iam:
roles/compute.admin:
- serviceAccount:service-account
# [opt] Service robots and keys they will be assigned as cryptoKeyEncrypterDecrypter
# [opt] Service robots and keys they will be assigned as cryptoKeyEncrypterDecrypter
# in service => [keys] format
kms_service_agents:
kms_service_agents:
compute: [key1, key2]
storage: [key1, key2]
# [opt] Labels for the project - merged with the ones defined in defaults
labels:
labels:
environment: prod
# [opt] Org policy overrides defined at project level
org_policies:
constraints/compute.disableGuestAttributesAccess:
constraints/compute.disableGuestAttributesAccess:
enforce: true
constraints/compute.trustedImageProjects:
allow:
@ -166,7 +167,7 @@ org_policies:
# [opt] Service account to create for the project and their roles on the project
# in name => [roles] format
service_accounts:
service_accounts:
another-service-account:
- roles/compute.admin
my-service-account:
@ -179,37 +180,37 @@ service_accounts_iam:
- roles/iam.serviceAccountTokenCreator:
- group: app-team-1@example.com
# [opt] APIs to enable on the project.
services:
# [opt] APIs to enable on the project.
services:
- storage.googleapis.com
- stackdriver.googleapis.com
- compute.googleapis.com
# [opt] Roles to assign to the robots service accounts in robot => [roles] format
services_iam:
services_iam:
compute:
- roles/storage.objectViewer
# [opt] VPC setup.
# If set enables the `compute.googleapis.com` service and configures
# [opt] VPC setup.
# If set enables the `compute.googleapis.com` service and configures
# service project attachment
vpc:
vpc:
# [opt] If set, enables the container API
gke_setup:
gke_setup:
# Grants "roles/container.hostServiceAgentUser" to the container robot if set
# Grants "roles/container.hostServiceAgentUser" to the container robot if set
enable_host_service_agent: false
# Grants "roles/compute.securityAdmin" to the container robot if set
# Grants "roles/compute.securityAdmin" to the container robot if set
enable_security_admin: true
# Host project the project will be service project of
# Host project the project will be service project of
host_project: fast-prod-net-spoke-0
# [opt] Subnets in the host project where principals will be granted networkUser
# in region/subnet-name => [principals]
subnets_iam:
# in region/subnet-name => [principals]
subnets_iam:
europe-west1/prod-default-ew1:
- user:foobar@example.com
- serviceAccount:service-account1@my-project.iam.gserviceaccount.com
@ -221,7 +222,8 @@ vpc:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [billing_account_id](variables.tf#L17) | Billing account id. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L157) | Project id. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L151) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L160) | Project id. | <code>string</code> | ✓ | |
| [billing_alert](variables.tf#L22) | Billing alert configuration. | <code title="object&#40;&#123;&#10; amount &#61; number&#10; thresholds &#61; object&#40;&#123;&#10; current &#61; list&#40;number&#41;&#10; forecasted &#61; list&#40;number&#41;&#10; &#125;&#41;&#10; credit_treatment &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [defaults](variables.tf#L35) | Project factory default values. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; billing_alert &#61; object&#40;&#123;&#10; amount &#61; number&#10; thresholds &#61; object&#40;&#123;&#10; current &#61; list&#40;number&#41;&#10; forecasted &#61; list&#40;number&#41;&#10; &#125;&#41;&#10; credit_treatment &#61; string&#10; &#125;&#41;&#10; environment_dns_zone &#61; string&#10; essential_contacts &#61; list&#40;string&#41;&#10; labels &#61; map&#40;string&#41;&#10; notification_channels &#61; list&#40;string&#41;&#10; shared_vpc_self_link &#61; string&#10; vpc_host_project &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [dns_zones](variables.tf#L57) | DNS private zones to create as child of var.defaults.environment_dns_zone. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
@ -234,15 +236,14 @@ vpc:
| [kms_service_agents](variables.tf#L99) | KMS IAM configuration in as service => [key]. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [labels](variables.tf#L105) | Labels to be assigned at project level. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [org_policies](variables.tf#L111) | Org-policy overrides at project level. | <code title="map&#40;object&#40;&#123;&#10; inherit_from_parent &#61; optional&#40;bool&#41; &#35; for list policies only.&#10; reset &#61; optional&#40;bool&#41;&#10; allow &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; deny &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; enforce &#61; optional&#40;bool, true&#41; &#35; for boolean policies only.&#10; rules &#61; optional&#40;list&#40;object&#40;&#123;&#10; allow &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; deny &#61; optional&#40;object&#40;&#123;&#10; all &#61; optional&#40;bool&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10; enforce &#61; optional&#40;bool, true&#41; &#35; for boolean policies only.&#10; condition &#61; object&#40;&#123;&#10; description &#61; optional&#40;string&#41;&#10; expression &#61; optional&#40;string&#41;&#10; location &#61; optional&#40;string&#41;&#10; title &#61; optional&#40;string&#41;&#10; &#125;&#41;&#10; &#125;&#41;&#41;, &#91;&#93;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [prefix](variables.tf#L151) | Prefix used for the project id. | <code>string</code> | | <code>null</code> |
| [service_accounts](variables.tf#L162) | Service accounts to be created, and roles assigned them on the project. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_additive](variables.tf#L168) | Service accounts to be created, and roles assigned them on the project additively. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_iam](variables.tf#L174) | IAM bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]} | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_iam_additive](variables.tf#L181) | IAM additive bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]} | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_identities_iam](variables.tf#L195) | Custom IAM settings for service identities in service => [role] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_identities_iam_additive](variables.tf#L202) | Custom additive IAM settings for service identities in service => [role] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [services](variables.tf#L188) | Services to be enabled for the project. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc](variables.tf#L209) | VPC configuration for the project. | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; gke_setup &#61; object&#40;&#123;&#10; enable_security_admin &#61; bool&#10; enable_host_service_agent &#61; bool&#10; &#125;&#41;&#10; subnets_iam &#61; map&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [service_accounts](variables.tf#L165) | Service accounts to be created, and roles assigned them on the project. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_additive](variables.tf#L171) | Service accounts to be created, and roles assigned them on the project additively. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_iam](variables.tf#L177) | IAM bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]} | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_accounts_iam_additive](variables.tf#L184) | IAM additive bindings on service account resources. Format is KEY => {ROLE => [MEMBERS]} | <code>map&#40;map&#40;list&#40;string&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_identities_iam](variables.tf#L191) | Custom IAM settings for service identities in service => [role] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_identities_iam_additive](variables.tf#L198) | Custom additive IAM settings for service identities in service => [role] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [services](variables.tf#L205) | Services to be enabled for the project. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [vpc](variables.tf#L212) | VPC configuration for the project. | <code title="object&#40;&#123;&#10; host_project &#61; string&#10; gke_setup &#61; object&#40;&#123;&#10; enable_security_admin &#61; bool&#10; enable_host_service_agent &#61; bool&#10; &#125;&#41;&#10; subnets_iam &#61; map&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

View File

@ -29,11 +29,7 @@ locals {
}
_group_iam_bindings = distinct(flatten(values(var.group_iam)))
_group_iam_additive_bindings = distinct(flatten(values(var.group_iam_additive)))
_project_id = (
var.prefix == null || var.prefix == ""
? var.project_id
: "${var.prefix}-${var.project_id}"
)
_service_accounts_iam = {
for r in local._service_accounts_iam_bindings : r => [
for k, v in var.service_accounts :

View File

@ -25,4 +25,5 @@ labels:
# [opt] Additional notification channels for billing
notification_channels: []
shared_vpc_self_link: projects/foo/networks/bar
prefix: test
vpc_host_project:

View File

@ -58,6 +58,9 @@ org_policies:
deny:
all: true
# [opt] Prefix - overrides default if set
prefix: test1
# [opt] Service account to create for the project and their roles on the project
# in name => [roles] format
service_accounts:

View File

@ -149,9 +149,12 @@ variable "org_policies" {
}
variable "prefix" {
description = "Prefix used for the project id."
description = "Prefix used for resource names."
type = string
default = null
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_id" {
@ -185,13 +188,6 @@ variable "service_accounts_iam_additive" {
nullable = false
}
variable "services" {
description = "Services to be enabled for the project."
type = list(string)
default = []
nullable = false
}
variable "service_identities_iam" {
description = "Custom IAM settings for service identities in service => [role] format."
type = map(list(string))
@ -206,6 +202,13 @@ variable "service_identities_iam_additive" {
nullable = false
}
variable "services" {
description = "Services to be enabled for the project."
type = list(string)
default = []
nullable = false
}
variable "vpc" {
description = "VPC configuration for the project."
type = object({

View File

@ -107,21 +107,21 @@ Once done testing, you can clean up resources by running `terraform destroy`.
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [project_id](variables.tf#L26) | Project ID. | <code>string</code> | ✓ | |
| [master_cidr_block](variables.tf#L49) | Master CIDR block. | <code>string</code> | | <code>&#34;10.0.0.0&#47;28&#34;</code> |
| [pods_cidr_block](variables.tf#L37) | Pods CIDR block. | <code>string</code> | | <code>&#34;172.16.0.0&#47;20&#34;</code> |
| [prefix](variables.tf#L31) | Prefix for resources created. | <code>string</code> | | <code>null</code> |
| [project_create](variables.tf#L17) | Parameters for the creation of the new project. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L61) | Region. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [services_cidr_block](variables.tf#L43) | Services CIDR block. | <code>string</code> | | <code>&#34;192.168.0.0&#47;24&#34;</code> |
| [subnet_cidr_block](variables.tf#L55) | Subnet CIDR block. | <code>string</code> | | <code>&#34;10.0.1.0&#47;24&#34;</code> |
| [zone](variables.tf#L67) | Zone. | <code>string</code> | | <code>&#34;europe-west1-c&#34;</code> |
| [prefix](variables.tf#L29) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L47) | Project ID. | <code>string</code> | | |
| [master_cidr_block](variables.tf#L17) | Master CIDR block. | <code>string</code> | | <code>&#34;10.0.0.0&#47;28&#34;</code> |
| [pods_cidr_block](variables.tf#L23) | Pods CIDR block. | <code>string</code> | | <code>&#34;172.16.0.0&#47;20&#34;</code> |
| [project_create](variables.tf#L38) | Parameters for the creation of the new project. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L52) | Region. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [services_cidr_block](variables.tf#L58) | Services CIDR block. | <code>string</code> | | <code>&#34;192.168.0.0&#47;24&#34;</code> |
| [subnet_cidr_block](variables.tf#L64) | Subnet CIDR block. | <code>string</code> | | <code>&#34;10.0.1.0&#47;24&#34;</code> |
| [zone](variables.tf#L70) | Zone. | <code>string</code> | | <code>&#34;europe-west1-c&#34;</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [app_repo_url](outputs.tf#L22) | App source repository url. | |
| [image_repo_url](outputs.tf#L17) | Image source repository url. | |
| [app_repo_url](outputs.tf#L17) | App source repository url. | |
| [image_repo_url](outputs.tf#L22) | Image source repository url. | |
<!-- END TFDOC -->

View File

@ -15,7 +15,6 @@
*/
locals {
prefix = (var.prefix == null || var.prefix == "") ? "" : "${var.prefix}-"
k8s_ns = "apis"
k8s_sa = "storage-api-sa"
image = (
@ -60,7 +59,7 @@ module "project" {
module "vpc" {
source = "../../../modules/net-vpc"
project_id = module.project.project_id
name = "${local.prefix}vpc"
name = "${var.prefix}-vpc"
subnets = [
{
ip_cidr_range = var.subnet_cidr_block
@ -78,14 +77,14 @@ module "nat" {
source = "../../../modules/net-cloudnat"
project_id = module.project.project_id
region = var.region
name = "${local.prefix}nat"
name = "${var.prefix}-nat"
router_network = module.vpc.name
}
module "cluster" {
source = "../../../modules/gke-cluster"
project_id = module.project.project_id
name = "${local.prefix}cluster"
name = "${var.prefix}-cluster"
location = var.zone
vpc_config = {
master_ipv4_cidr_block = var.master_cidr_block
@ -173,7 +172,7 @@ module "docker_artifact_registry" {
project_id = module.project.project_id
location = var.region
format = "DOCKER"
id = "${local.prefix}registry"
id = "${var.prefix}-registry"
iam = {
"roles/artifactregistry.writer" = [module.image_cb_sa.iam_email]
"roles/artifactregistry.reader" = [module.cluster_nodepool.service_account_iam_email]
@ -189,7 +188,7 @@ module "image_cb_sa" {
module "image_repo" {
source = "../../../modules/source-repository"
project_id = module.project.project_id
name = "${local.prefix}image"
name = "${var.prefix}-image"
triggers = {
image-trigger = {
filename = "cloudbuild.yaml"
@ -221,7 +220,7 @@ module "app_cb_sa" {
module "app_repo" {
source = "../../../modules/source-repository"
project_id = module.project.project_id
name = "${local.prefix}app"
name = "${var.prefix}-app"
triggers = {
app-trigger = {
filename = "cloudbuild.yaml"

View File

@ -14,12 +14,12 @@
* limitations under the License.
*/
output "image_repo_url" {
description = "Image source repository url."
value = "ssh://<USER>@source.developers.google.com:2022/p/${module.project.project_id}/r/${module.image_repo.name}"
}
output "app_repo_url" {
description = "App source repository url."
value = "ssh://<USER>@source.developers.google.com:2022/p/${module.project.project_id}/r/${module.app_repo.name}"
}
output "image_repo_url" {
description = "Image source repository url."
value = "ssh://<USER>@source.developers.google.com:2022/p/${module.project.project_id}/r/${module.image_repo.name}"
}

View File

@ -14,6 +14,27 @@
* limitations under the License.
*/
variable "master_cidr_block" {
description = "Master CIDR block."
type = string
default = "10.0.0.0/28"
}
variable "pods_cidr_block" {
description = "Pods CIDR block."
type = string
default = "172.16.0.0/20"
}
variable "prefix" {
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_create" {
description = "Parameters for the creation of the new project."
type = object({
@ -28,16 +49,10 @@ variable "project_id" {
type = string
}
variable "prefix" {
description = "Prefix for resources created."
variable "region" {
description = "Region."
type = string
default = null
}
variable "pods_cidr_block" {
description = "Pods CIDR block."
type = string
default = "172.16.0.0/20"
default = "europe-west1"
}
variable "services_cidr_block" {
@ -46,24 +61,12 @@ variable "services_cidr_block" {
default = "192.168.0.0/24"
}
variable "master_cidr_block" {
description = "Master CIDR block."
type = string
default = "10.0.0.0/28"
}
variable "subnet_cidr_block" {
description = "Subnet CIDR block."
type = string
default = "10.0.1.0/24"
}
variable "region" {
description = "Region."
type = string
default = "europe-west1"
}
variable "zone" {
description = "Zone."
type = string

View File

@ -64,14 +64,14 @@ Once done testing, you can clean up resources by running `terraform destroy`.
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [billing_account_id](variables.tf#L17) | Billing account id. | <code>string</code> | ✓ | |
| [fleet_project_id](variables.tf#L32) | Management Project ID. | <code>string</code> | ✓ | |
| [host_project_id](variables.tf#L27) | Project ID. | <code>string</code> | ✓ | |
| [mgmt_project_id](variables.tf#L37) | Management Project ID. | <code>string</code> | ✓ | |
| [parent](variables.tf#L22) | Parent. | <code>string</code> | ✓ | |
| [clusters_config](variables.tf#L54) | Clusters configuration. | <code title="map&#40;object&#40;&#123;&#10; subnet_cidr_block &#61; string&#10; master_cidr_block &#61; string&#10; services_cidr_block &#61; string&#10; pods_cidr_block &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; cluster-a &#61; &#123;&#10; subnet_cidr_block &#61; &#34;10.0.1.0&#47;24&#34;&#10; master_cidr_block &#61; &#34;10.16.0.0&#47;28&#34;&#10; services_cidr_block &#61; &#34;192.168.1.0&#47;24&#34;&#10; pods_cidr_block &#61; &#34;172.16.0.0&#47;20&#34;&#10; &#125;&#10; cluster-b &#61; &#123;&#10; subnet_cidr_block &#61; &#34;10.0.2.0&#47;24&#34;&#10; master_cidr_block &#61; &#34;10.16.0.16&#47;28&#34;&#10; services_cidr_block &#61; &#34;192.168.2.0&#47;24&#34;&#10; pods_cidr_block &#61; &#34;172.16.16.0&#47;20&#34;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [istio_version](variables.tf#L98) | ASM version | <code>string</code> | | <code>&#34;1.14.1-asm.3&#34;</code> |
| [mgmt_server_config](variables.tf#L78) | Mgmt server configuration | <code title="object&#40;&#123;&#10; disk_size &#61; number&#10; disk_type &#61; string&#10; image &#61; string&#10; instance_type &#61; string&#10; region &#61; string&#10; zone &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; disk_size &#61; 50&#10; disk_type &#61; &#34;pd-ssd&#34;&#10; image &#61; &#34;projects&#47;ubuntu-os-cloud&#47;global&#47;images&#47;family&#47;ubuntu-2204-lts&#34;&#10; instance_type &#61; &#34;n1-standard-2&#34;&#10; region &#61; &#34;europe-west1&#34;&#10; zone &#61; &#34;europe-west1-c&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [mgmt_subnet_cidr_block](variables.tf#L42) | Management subnet CIDR block. | <code>string</code> | | <code>&#34;10.0.0.0&#47;28&#34;</code> |
| [region](variables.tf#L48) | Region. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [fleet_project_id](variables.tf#L46) | Management Project ID. | <code>string</code> | ✓ | |
| [host_project_id](variables.tf#L51) | Project ID. | <code>string</code> | ✓ | |
| [mgmt_project_id](variables.tf#L63) | Management Project ID. | <code>string</code> | ✓ | |
| [parent](variables.tf#L94) | Parent. | <code>string</code> | ✓ | |
| [clusters_config](variables.tf#L22) | Clusters configuration. | <code title="map&#40;object&#40;&#123;&#10; subnet_cidr_block &#61; string&#10; master_cidr_block &#61; string&#10; services_cidr_block &#61; string&#10; pods_cidr_block &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code title="&#123;&#10; cluster-a &#61; &#123;&#10; subnet_cidr_block &#61; &#34;10.0.1.0&#47;24&#34;&#10; master_cidr_block &#61; &#34;10.16.0.0&#47;28&#34;&#10; services_cidr_block &#61; &#34;192.168.1.0&#47;24&#34;&#10; pods_cidr_block &#61; &#34;172.16.0.0&#47;20&#34;&#10; &#125;&#10; cluster-b &#61; &#123;&#10; subnet_cidr_block &#61; &#34;10.0.2.0&#47;24&#34;&#10; master_cidr_block &#61; &#34;10.16.0.16&#47;28&#34;&#10; services_cidr_block &#61; &#34;192.168.2.0&#47;24&#34;&#10; pods_cidr_block &#61; &#34;172.16.16.0&#47;20&#34;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [istio_version](variables.tf#L57) | ASM version | <code>string</code> | | <code>&#34;1.14.1-asm.3&#34;</code> |
| [mgmt_server_config](variables.tf#L68) | Mgmt server configuration | <code title="object&#40;&#123;&#10; disk_size &#61; number&#10; disk_type &#61; string&#10; image &#61; string&#10; instance_type &#61; string&#10; region &#61; string&#10; zone &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; disk_size &#61; 50&#10; disk_type &#61; &#34;pd-ssd&#34;&#10; image &#61; &#34;projects&#47;ubuntu-os-cloud&#47;global&#47;images&#47;family&#47;ubuntu-2204-lts&#34;&#10; instance_type &#61; &#34;n1-standard-2&#34;&#10; region &#61; &#34;europe-west1&#34;&#10; zone &#61; &#34;europe-west1-c&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [mgmt_subnet_cidr_block](variables.tf#L88) | Management subnet CIDR block. | <code>string</code> | | <code>&#34;10.0.0.0&#47;28&#34;</code> |
| [region](variables.tf#L99) | Region. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
<!-- END TFDOC -->

View File

@ -19,38 +19,6 @@ variable "billing_account_id" {
type = string
}
variable "parent" {
description = "Parent."
type = string
}
variable "host_project_id" {
description = "Project ID."
type = string
}
variable "fleet_project_id" {
description = "Management Project ID."
type = string
}
variable "mgmt_project_id" {
description = "Management Project ID."
type = string
}
variable "mgmt_subnet_cidr_block" {
description = "Management subnet CIDR block."
type = string
default = "10.0.0.0/28"
}
variable "region" {
description = "Region."
type = string
default = "europe-west1"
}
variable "clusters_config" {
description = "Clusters configuration."
type = map(object({
@ -75,6 +43,28 @@ variable "clusters_config" {
}
}
variable "fleet_project_id" {
description = "Management Project ID."
type = string
}
variable "host_project_id" {
description = "Project ID."
type = string
}
variable "istio_version" {
description = "ASM version"
type = string
default = "1.14.1-asm.3"
}
variable "mgmt_project_id" {
description = "Management Project ID."
type = string
}
variable "mgmt_server_config" {
description = "Mgmt server configuration"
type = object({
@ -95,8 +85,19 @@ variable "mgmt_server_config" {
}
}
variable "istio_version" {
description = "ASM version"
variable "mgmt_subnet_cidr_block" {
description = "Management subnet CIDR block."
type = string
default = "1.14.1-asm.3"
default = "10.0.0.0/28"
}
variable "parent" {
description = "Parent."
type = string
}
variable "region" {
description = "Region."
type = string
default = "europe-west1"
}

View File

@ -247,9 +247,9 @@ module "gke" {
|---|---|:---:|:---:|:---:|
| [billing_account_id](variables.tf#L17) | Billing account id. | <code>string</code> | ✓ | |
| [folder_id](variables.tf#L132) | Folder used for the GKE project in folders/nnnnnnnnnnn format. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L179) | Prefix used for resources that need unique names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L184) | ID of the project that will contain all the clusters. | <code>string</code> | ✓ | |
| [vpc_config](variables.tf#L196) | Shared VPC project and VPC details. | <code title="object&#40;&#123;&#10; host_project_id &#61; string&#10; vpc_self_link &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [prefix](variables.tf#L179) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L188) | ID of the project that will contain all the clusters. | <code>string</code> | ✓ | |
| [vpc_config](variables.tf#L200) | Shared VPC project and VPC details. | <code title="object&#40;&#123;&#10; host_project_id &#61; string&#10; vpc_self_link &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [clusters](variables.tf#L22) | Clusters configuration. Refer to the gke-cluster module for type details. | <code title="map&#40;object&#40;&#123;&#10; cluster_autoscaling &#61; optional&#40;any&#41;&#10; description &#61; optional&#40;string&#41;&#10; enable_addons &#61; optional&#40;any, &#123;&#10; horizontal_pod_autoscaling &#61; true, http_load_balancing &#61; true&#10; &#125;&#41;&#10; enable_features &#61; optional&#40;any, &#123;&#10; workload_identity &#61; true&#10; &#125;&#41;&#10; issue_client_certificate &#61; optional&#40;bool, false&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; location &#61; string&#10; logging_config &#61; optional&#40;list&#40;string&#41;, &#91;&#34;SYSTEM_COMPONENTS&#34;&#93;&#41;&#10; maintenance_config &#61; optional&#40;any, &#123;&#10; daily_window_start_time &#61; &#34;03:00&#34;&#10; recurring_window &#61; null&#10; maintenance_exclusion &#61; &#91;&#93;&#10; &#125;&#41;&#10; max_pods_per_node &#61; optional&#40;number, 110&#41;&#10; min_master_version &#61; optional&#40;string&#41;&#10; monitoring_config &#61; optional&#40;object&#40;&#123;&#10; enable_components &#61; optional&#40;list&#40;string&#41;, &#91;&#34;SYSTEM_COMPONENTS&#34;&#93;&#41;&#10; managed_prometheus &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; node_locations &#61; optional&#40;list&#40;string&#41;&#41;&#10; private_cluster_config &#61; optional&#40;any&#41;&#10; release_channel &#61; optional&#40;string&#41;&#10; vpc_config &#61; object&#40;&#123;&#10; subnetwork &#61; string&#10; network &#61; optional&#40;string&#41;&#10; secondary_range_blocks &#61; optional&#40;object&#40;&#123;&#10; pods &#61; string&#10; services &#61; string&#10; &#125;&#41;&#41;&#10; secondary_range_names &#61; optional&#40;object&#40;&#123;&#10; pods &#61; string&#10; services &#61; string&#10; &#125;&#41;, &#123; pods &#61; &#34;pods&#34;, services &#61; &#34;services&#34; &#125;&#41;&#10; master_authorized_ranges &#61; optional&#40;map&#40;string&#41;&#41;&#10; master_ipv4_cidr_block &#61; optional&#40;string&#41;&#10; &#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [fleet_configmanagement_clusters](variables.tf#L70) | Config management features enabled on specific sets of member clusters, in config name => [cluster name] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [fleet_configmanagement_templates](variables.tf#L77) | Sets of config management configurations that can be applied to member clusters, in config name => {options} format. | <code title="map&#40;object&#40;&#123;&#10; binauthz &#61; bool&#10; config_sync &#61; object&#40;&#123;&#10; git &#61; object&#40;&#123;&#10; gcp_service_account_email &#61; string&#10; https_proxy &#61; string&#10; policy_dir &#61; string&#10; secret_type &#61; string&#10; sync_branch &#61; string&#10; sync_repo &#61; string&#10; sync_rev &#61; string&#10; sync_wait_secs &#61; number&#10; &#125;&#41;&#10; prevent_drift &#61; string&#10; source_format &#61; string&#10; &#125;&#41;&#10; hierarchy_controller &#61; object&#40;&#123;&#10; enable_hierarchical_resource_quota &#61; bool&#10; enable_pod_tree_labels &#61; bool&#10; &#125;&#41;&#10; policy_controller &#61; object&#40;&#123;&#10; audit_interval_seconds &#61; number&#10; exemptable_namespaces &#61; list&#40;string&#41;&#10; log_denies_enabled &#61; bool&#10; referential_rules_enabled &#61; bool&#10; template_library_installed &#61; bool&#10; &#125;&#41;&#10; version &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
@ -259,14 +259,14 @@ module "gke" {
| [iam](variables.tf#L144) | Project-level authoritative IAM bindings for users and service accounts in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [labels](variables.tf#L151) | Project-level labels. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [nodepools](variables.tf#L157) | Nodepools configuration. Refer to the gke-nodepool module for type details. | <code title="map&#40;map&#40;object&#40;&#123;&#10; gke_version &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; max_pods_per_node &#61; optional&#40;number&#41;&#10; name &#61; optional&#40;string&#41;&#10; node_config &#61; optional&#40;any, &#123; disk_type &#61; &#34;pd-balanced&#34; &#125;&#41;&#10; node_count &#61; optional&#40;map&#40;number&#41;, &#123; initial &#61; 1 &#125;&#41;&#10; node_locations &#61; optional&#40;list&#40;string&#41;&#41;&#10; nodepool_config &#61; optional&#40;any&#41;&#10; pod_range &#61; optional&#40;any&#41;&#10; reservation_affinity &#61; optional&#40;any&#41;&#10; service_account &#61; optional&#40;any&#41;&#10; sole_tenant_nodegroup &#61; optional&#40;string&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10; taints &#61; optional&#40;list&#40;any&#41;&#41;&#10;&#125;&#41;&#41;&#41;">map&#40;map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [project_services](variables.tf#L189) | Additional project services to enable. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [project_services](variables.tf#L193) | Additional project services to enable. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [cluster_ids](outputs.tf#L22) | Cluster ids. | |
| [clusters](outputs.tf#L17) | Cluster resources. | |
| [cluster_ids](outputs.tf#L17) | Cluster ids. | |
| [clusters](outputs.tf#L24) | Cluster resources. | |
| [project_id](outputs.tf#L29) | GKE project id. | |
<!-- END TFDOC -->

View File

@ -14,11 +14,6 @@
# tfdoc:file:description Output variables.
output "clusters" {
description = "Cluster resources."
value = module.gke-cluster
}
output "cluster_ids" {
description = "Cluster ids."
value = {
@ -26,6 +21,11 @@ output "cluster_ids" {
}
}
output "clusters" {
description = "Cluster resources."
value = module.gke-cluster
}
output "project_id" {
description = "GKE project id."
value = module.gke-project-0.project_id

View File

@ -177,8 +177,12 @@ variable "nodepools" {
}
variable "prefix" {
description = "Prefix used for resources that need unique names."
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_id" {

View File

@ -26,11 +26,11 @@ in the [`validator/`](validator/) subdirectory, which can be integrated as part
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [billing_account_id](variables.tf#L15) | Billing account id used as default for new projects. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L29) | Prefix used for resources that need unique names. | <code>string</code> | ✓ | |
| [root_node](variables.tf#L50) | Hierarchy node where projects will be created, 'organizations/org_id' or 'folders/folder_id'. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L29) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [root_node](variables.tf#L54) | Hierarchy node where projects will be created, 'organizations/org_id' or 'folders/folder_id'. | <code>string</code> | ✓ | |
| [ip_ranges](variables.tf#L20) | Subnet IP CIDR ranges. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; prod &#61; &#34;10.0.16.0&#47;24&#34;&#10; dev &#61; &#34;10.0.32.0&#47;24&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [project_services](variables.tf#L34) | Service APIs enabled by default in new projects. | <code>list&#40;string&#41;</code> | | <code title="&#91;&#10; &#34;container.googleapis.com&#34;,&#10; &#34;dns.googleapis.com&#34;,&#10; &#34;stackdriver.googleapis.com&#34;,&#10;&#93;">&#91;&#8230;&#93;</code> |
| [region](variables.tf#L44) | Region used. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [project_services](variables.tf#L38) | Service APIs enabled by default in new projects. | <code>list&#40;string&#41;</code> | | <code title="&#91;&#10; &#34;container.googleapis.com&#34;,&#10; &#34;dns.googleapis.com&#34;,&#10; &#34;stackdriver.googleapis.com&#34;,&#10;&#93;">&#91;&#8230;&#93;</code> |
| [region](variables.tf#L48) | Region used. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
## Outputs

View File

@ -27,8 +27,12 @@ variable "ip_ranges" {
}
variable "prefix" {
description = "Prefix used for resources that need unique names."
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_services" {

View File

@ -0,0 +1,28 @@
# Network filtering with Squid with isolated VPCs using Private Service Connect
This blueprint shows how to deploy a filtering HTTP proxy to restrict Internet access. Here we show one way to do this using isolated VPCs and Private Service Connect:
- The `app` subnet hosts the consumer VMs that will have their Internet access tightly controlled by a non-caching filtering forward proxy.
- The `proxy` subnet hosts a Cloud NAT instance and a [Squid](http://www.squid-cache.org/) server.
- The `psc` subnet is reserved for the Private Service Connect.
The reason for using Privat Service Connect in this setup is to have a common proxy setup between all environments without having to share a VPC between projects. This allows us to enforce the `compute.vmExternalIpAccess` [organization policy](https://cloud.google.com/resource-manager/docs/organization-policy/org-policy-constraints), which prevents the service projects from having external IPs, thus forcing all outbound Internet connections through the proxy.
To allow Internet connectivity to the proxy subnet, a Cloud NAT instance is configured to allow usage from [that subnet only](https://cloud.google.com/nat/docs/using-nat#specify_subnet_ranges_for_nat). All other subnets are not allowed to use the Cloud NAT instance.
To simplify the usage of the proxy, a Cloud DNS private zone is created in each consumer VPC and the IP address of the proxy is exposed with the FQDN `proxy.internal`. In addition, system-wide `http_proxy` and `https_proxy` environment variables and an APT configuration are rolled out via a [startup script](startup.sh).
<!-- BEGIN TFDOC -->
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [prefix](variables.tf#L44) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L70) | Project id used for all resources. | <code>string</code> | ✓ | |
| [allowed_domains](variables.tf#L17) | List of domains allowed by the squid proxy. | <code>list&#40;string&#41;</code> | | <code title="&#91;&#10; &#34;.google.com&#34;,&#10; &#34;.github.com&#34;,&#10; &#34;.fastlydns.net&#34;,&#10; &#34;.debian.org&#34;&#10;&#93;">&#91;&#8230;&#93;</code> |
| [cidrs](variables.tf#L28) | CIDR ranges for subnets. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; app &#61; &#34;10.0.0.0&#47;24&#34;&#10; proxy &#61; &#34;10.0.2.0&#47;28&#34;&#10; psc &#61; &#34;10.0.3.0&#47;28&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [nat_logging](variables.tf#L38) | Enables Cloud NAT logging if not null, value is one of 'ERRORS_ONLY', 'TRANSLATIONS_ONLY', 'ALL'. | <code>string</code> | | <code>&#34;ERRORS_ONLY&#34;</code> |
| [project_create](variables.tf#L53) | Set to non null if project needs to be created. | <code title="object&#40;&#123;&#10; billing_account &#61; string&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L75) | Default region for resources. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
<!-- END TFDOC -->

View File

@ -0,0 +1,105 @@
/**
* Copyright 2022 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.
*/
###############################################################################
# Consumer project and VPC #
###############################################################################
module "vpc-consumer" {
source = "../../../modules/net-vpc"
project_id = module.project.project_id
name = "${var.prefix}-app"
subnets = [
{
name = "${var.prefix}-app"
ip_cidr_range = var.cidrs.app
region = var.region
}
]
}
###############################################################################
# Test VM #
###############################################################################
module "test-vm-consumer" {
source = "../../../modules/compute-vm"
project_id = module.project.project_id
zone = "${var.region}-b"
name = "${var.prefix}-test-vm"
instance_type = "e2-micro"
tags = ["ssh"]
network_interfaces = [{
network = module.vpc-consumer.self_link
subnetwork = module.vpc-consumer.subnet_self_links["${var.region}/${var.prefix}-app"]
nat = false
addresses = null
}]
boot_disk = {
image = "debian-cloud/debian-10"
type = "pd-standard"
size = 10
}
service_account_create = true
metadata = {
startup-script = templatefile("${path.module}/startup.sh", { proxy_url = "http://proxy.internal:3128" })
}
}
###############################################################################
# PSC Consuner #
###############################################################################
resource "google_compute_address" "psc_endpoint_address" {
name = "${var.prefix}-psc-proxy-address"
project = module.project.project_id
address_type = "INTERNAL"
subnetwork = module.vpc-consumer.subnet_self_links["${var.region}/${var.prefix}-app"]
region = var.region
}
resource "google_compute_forwarding_rule" "psc_ilb_consumer" {
name = "${var.prefix}-psc-proxy-fw-rule"
project = module.project.project_id
region = var.region
target = google_compute_service_attachment.service_attachment.id
load_balancing_scheme = ""
network = module.vpc-consumer.self_link
ip_address = google_compute_address.psc_endpoint_address.id
}
###############################################################################
# DNS and Firewall #
###############################################################################
module "private-dns" {
source = "../../../modules/dns"
project_id = module.project.project_id
type = "private"
name = "${var.prefix}-internal"
domain = "internal."
client_networks = [module.vpc-consumer.self_link]
recordsets = {
"A squid" = { ttl = 60, records = [google_compute_address.psc_endpoint_address.address] }
"CNAME proxy" = { ttl = 3600, records = ["squid.internal."] }
}
}
module "firewall-consumer" {
source = "../../../modules/net-vpc-firewall"
project_id = module.project.project_id
network = module.vpc-consumer.name
}

View File

@ -0,0 +1,218 @@
/**
* Copyright 2022 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.
*/
###############################################################################
# Host project and VPC resources #
###############################################################################
module "project" {
source = "../../../modules/project"
project_create = var.project_create != null
billing_account = try(var.project_create.billing_account, null)
parent = try(var.project_create.parent, null)
name = var.project_id
services = [
"dns.googleapis.com",
"compute.googleapis.com",
"logging.googleapis.com",
"monitoring.googleapis.com"
]
}
module "vpc" {
source = "../../../modules/net-vpc"
project_id = module.project.project_id
name = "${var.prefix}-vpc"
subnets = [
{
name = "proxy"
ip_cidr_range = var.cidrs.proxy
region = var.region
}
]
subnets_psc = [
{
name = "psc"
ip_cidr_range = var.cidrs.psc
region = var.region
}
]
}
module "firewall" {
source = "../../../modules/net-vpc-firewall"
project_id = module.project.project_id
network = module.vpc.name
ingress_rules = {
allow-ingress-squid = {
description = "Allow squid ingress traffic"
source_ranges = [
var.cidrs.psc, "35.191.0.0/16", "130.211.0.0/22"
]
targets = [module.service-account-squid.email]
use_service_accounts = true
rules = [{
protocol = "tcp"
ports = [3128]
}]
}
}
}
module "nat" {
source = "../../../modules/net-cloudnat"
project_id = module.project.project_id
region = var.region
name = "default"
router_network = module.vpc.name
config_source_subnets = "LIST_OF_SUBNETWORKS"
# 64512/11 = 5864 . 11 is the number of usable IPs in the proxy subnet
config_min_ports_per_vm = 5864
subnetworks = [
{
self_link = module.vpc.subnet_self_links["${var.region}/proxy"]
config_source_ranges = ["ALL_IP_RANGES"]
secondary_ranges = null
}
]
logging_filter = var.nat_logging
}
###############################################################################
# PSC resources #
###############################################################################
resource "google_compute_service_attachment" "service_attachment" {
name = "psc"
project = module.project.project_id
region = var.region
enable_proxy_protocol = true
connection_preference = "ACCEPT_MANUAL"
nat_subnets = [module.vpc.subnets_psc["${var.region}/psc"].self_link]
target_service = module.squid-ilb.forwarding_rule_self_link
consumer_accept_lists {
project_id_or_num = module.project.project_id
connection_limit = 10
}
}
###############################################################################
# Squid resources #
###############################################################################
module "service-account-squid" {
source = "../../../modules/iam-service-account"
project_id = module.project.project_id
name = "svc-squid"
iam_project_roles = {
(module.project.project_id) = [
"roles/logging.logWriter",
"roles/monitoring.metricWriter",
]
}
}
module "cos-squid" {
source = "../../../modules/cloud-config-container/squid"
allow = var.allowed_domains
clients = [var.cidrs.app]
squid_config = "${path.module}/squid.conf"
config_variables = {
psc_cidr = var.cidrs.psc
}
}
module "squid-vm" {
source = "../../../modules/compute-vm"
project_id = module.project.project_id
zone = "${var.region}-b"
name = "squid-vm"
instance_type = "e2-medium"
create_template = true
network_interfaces = [{
network = module.vpc.self_link
subnetwork = module.vpc.subnet_self_links["${var.region}/proxy"]
}]
boot_disk = {
image = "cos-cloud/cos-stable"
}
service_account = module.service-account-squid.email
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
metadata = {
user-data = module.cos-squid.cloud_config
google-logging-enabled = true
}
}
module "squid-mig" {
source = "../../../modules/compute-mig"
project_id = module.project.project_id
location = "${var.region}-b"
name = "squid-mig"
instance_template = module.squid-vm.template.self_link
target_size = 1
auto_healing_policies = {
initial_delay_sec = 60
}
autoscaler_config = {
max_replicas = 10
min_replicas = 1
cooldown_period = 30
scaling_signals = {
cpu_utilization = {
target = 0.65
}
}
}
health_check_config = {
enable_logging = true
tcp = {
port = 3128
proxy_header = "PROXY_V1"
}
}
update_policy = {
minimal_action = "REPLACE"
type = "PROACTIVE"
max_surge = {
fixed = 3
}
min_ready_sec = 60
}
}
module "squid-ilb" {
source = "../../../modules/net-ilb"
project_id = module.project.project_id
region = var.region
name = "squid-ilb"
ports = [3128]
service_label = "squid-ilb"
vpc_config = {
network = module.vpc.self_link
subnetwork = module.vpc.subnet_self_links["${var.region}/proxy"]
}
backends = [{
group = module.squid-mig.group_manager.instance_group
}]
health_check_config = {
enable_logging = true
tcp = {
port = 3128
proxy_header = "PROXY_V1"
}
}
}

View File

@ -0,0 +1,60 @@
# bind to port 3128 and require PROXY protocol
http_port 0.0.0.0:3128 require-proxy-header
# only proxy, don't cache
cache deny all
# redirect all logs to /dev/stdout
logfile_rotate 0
cache_log stdio:/dev/stdout
access_log stdio:/dev/stdout
cache_store_log stdio:/dev/stdout
pid_filename /var/run/squid/squid.pid
acl ssl_ports port 443
acl safe_ports port 80
acl safe_ports port 443
acl CONNECT method CONNECT
acl to_metadata dst 169.254.169.254
acl from_healthchecks src 130.211.0.0/22 35.191.0.0/16
acl psc src ${psc_cidr}
# read client CIDR ranges from clients.txt
acl clients src "/etc/squid/clients.txt"
# read allowed domains from allowlist.txt
acl allowlist dstdomain "/etc/squid/allowlist.txt"
# read denied domains from denylist.txt
acl denylist dstdomain "/etc/squid/denylist.txt"
# allow PROXY protocol from the PSC subnet
proxy_protocol_access allow psc
# allow PROXY protocol from the LB health checks
proxy_protocol_access allow from_healthchecks
# deny access to anything other than ports 80 and 443
http_access deny !safe_ports
# deny CONNECT if connection is not using ssl
http_access deny CONNECT !ssl_ports
# deny acccess to cachemgr
http_access deny manager
# deny access to localhost through the proxy
http_access deny to_localhost
# deny access to the local metadata server through the proxy
http_access deny to_metadata
# deny connection from allowed clients to any denied domains
http_access deny clients denylist
# allow connection from allowed clients only to the allowed domains
http_access allow clients allowlist
# deny everything else
http_access ${default_action} all

View File

@ -0,0 +1,26 @@
# Copyright 2022 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.
cat <<EOF > /etc/apt/apt.conf.d/proxy.conf
Acquire {
HTTP::proxy "${proxy_url}";
HTTPS::proxy "${proxy_url}";
}
EOF
cat <<EOF > /etc/profile.d/proxy.sh
export http_proxy="${proxy_url}"
export https_proxy="${proxy_url}"
export no_proxy="127.0.0.1,localhost"
EOF

View File

@ -0,0 +1,79 @@
/**
* Copyright 2022 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 "allowed_domains" {
description = "List of domains allowed by the squid proxy."
type = list(string)
default = [
".google.com",
".github.com",
".fastlydns.net",
".debian.org"
]
}
variable "cidrs" {
description = "CIDR ranges for subnets."
type = map(string)
default = {
app = "10.0.0.0/24"
proxy = "10.0.2.0/28"
psc = "10.0.3.0/28"
}
}
variable "nat_logging" {
description = "Enables Cloud NAT logging if not null, value is one of 'ERRORS_ONLY', 'TRANSLATIONS_ONLY', 'ALL'."
type = string
default = "ERRORS_ONLY"
}
variable "prefix" {
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "project_create" {
description = "Set to non null if project needs to be created."
type = object({
billing_account = string
parent = string
})
default = null
validation {
condition = (
var.project_create == null
? true
: can(regex("(organizations|folders)/[0-9]+", var.project_create.parent))
)
error_message = "Project parent must be of the form folders/folder_id or organizations/organization_id."
}
}
variable "project_id" {
description = "Project id used for all resources."
type = string
}
variable "region" {
description = "Default region for resources."
type = string
default = "europe-west1"
}

View File

@ -21,13 +21,13 @@ You can optionally deploy the Squid server as [Managed Instance Group](https://c
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [billing_account](variables.tf#L26) | Billing account id used as default for new projects. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L52) | Prefix used for resources that need unique names. | <code>string</code> | ✓ | |
| [root_node](variables.tf#L63) | Root node for the new hierarchy, either 'organizations/org_id' or 'folders/folder_id'. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L52) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [root_node](variables.tf#L67) | Root node for the new hierarchy, either 'organizations/org_id' or 'folders/folder_id'. | <code>string</code> | ✓ | |
| [allowed_domains](variables.tf#L17) | List of domains allowed by the squid proxy. | <code>list&#40;string&#41;</code> | | <code title="&#91;&#10; &#34;.google.com&#34;,&#10; &#34;.github.com&#34;&#10;&#93;">&#91;&#8230;&#93;</code> |
| [cidrs](variables.tf#L31) | CIDR ranges for subnets. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; apps &#61; &#34;10.0.0.0&#47;24&#34;&#10; proxy &#61; &#34;10.0.1.0&#47;28&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [mig](variables.tf#L40) | Enables the creation of an autoscaling managed instance group of squid instances. | <code>bool</code> | | <code>false</code> |
| [nat_logging](variables.tf#L46) | Enables Cloud NAT logging if not null, value is one of 'ERRORS_ONLY', 'TRANSLATIONS_ONLY', 'ALL'. | <code>string</code> | | <code>&#34;ERRORS_ONLY&#34;</code> |
| [region](variables.tf#L57) | Default region for resources. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [region](variables.tf#L61) | Default region for resources. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
## Outputs

View File

@ -50,8 +50,12 @@ variable "nat_logging" {
}
variable "prefix" {
description = "Prefix used for resources that need unique names."
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "region" {

Some files were not shown because too many files have changed in this diff Show More