Merge branch 'master' into lcaggio/shieldedfolder

This commit is contained in:
lcaggio 2023-01-30 23:52:46 +01:00
commit a166c612d5
128 changed files with 2657 additions and 1646 deletions

View File

@ -69,4 +69,7 @@ jobs:
- name: Check python formatting
id: yapf
run: |
yapf --style="{based_on_style: google, indent_width: 2, SPLIT_BEFORE_NAMED_ASSIGNS: false}" -p -d tools/*.py
yapf --style="{based_on_style: google, indent_width: 2, SPLIT_BEFORE_NAMED_ASSIGNS: false}" -p -d \
tools/*.py \
blueprints/cloud-operations/network-dashboard/src/*py \
blueprints/cloud-operations/network-dashboard/src/plugins/*py

View File

@ -8,6 +8,15 @@ All notable changes to this project will be documented in this file.
### BLUEPRINTS
- [[#1106](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1106)] Network Dashboard: PSA support for Filestore and Memorystore ([aurelienlegrand](https://github.com/aurelienlegrand)) <!-- 2023-01-25 15:02:31+00:00 -->
- [[#1110](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1110)] Bump cookiejar from 2.1.3 to 2.1.4 in /blueprints/apigee/bigquery-analytics/functions/export ([dependabot[bot]](https://github.com/dependabot[bot])) <!-- 2023-01-24 15:07:12+00:00 -->
- [[#1097](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1097)] Use terraform resource to activate Anthos Service Mesh ([wiktorn](https://github.com/wiktorn)) <!-- 2023-01-23 08:25:31+00:00 -->
- [[#1104](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1104)] Updated apigee hybrid for gke README ([apichick](https://github.com/apichick)) <!-- 2023-01-22 10:34:48+00:00 -->
- [[#1107](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1107)] Check linting for Python dashboard files ([ludoo](https://github.com/ludoo)) <!-- 2023-01-21 16:17:52+00:00 -->
- [[#1102](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1102)] Improvements in apigee hybrid-gke: now using workload identity and GLB ([apichick](https://github.com/apichick)) <!-- 2023-01-20 12:32:08+00:00 -->
- [[#1098](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1098)] Add shared-vpc support on data-playground blueprint ([lcaggio](https://github.com/lcaggio)) <!-- 2023-01-19 08:08:29+00:00 -->
- [[#1095](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1095)] [Data Platform] Fix Table in readme ([lcaggio](https://github.com/lcaggio)) <!-- 2023-01-17 12:39:56+00:00 -->
- [[#1089](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1089)] Update Data Platform ([lcaggio](https://github.com/lcaggio)) <!-- 2023-01-12 22:17:05+00:00 -->
- [[#1081](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1081)] Apigee hybrid on GKE ([apichick](https://github.com/apichick)) <!-- 2023-01-05 08:23:33+00:00 -->
- [[#1082](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1082)] Fixes in Apigee Bigquery Analytics blueprint ([apichick](https://github.com/apichick)) <!-- 2023-01-04 16:42:50+00:00 -->
- [[#1071](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1071)] Moved apigee bigquery analytics blueprint, added apigee network patterns ([apichick](https://github.com/apichick)) <!-- 2022-12-23 15:16:45+00:00 -->
@ -20,6 +29,8 @@ All notable changes to this project will be documented in this file.
### DOCUMENTATION
- [[#1101](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1101)] First batch of testing updates to core modules ([juliocc](https://github.com/juliocc)) <!-- 2023-01-20 06:49:41+00:00 -->
- [[#1089](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1089)] Update Data Platform ([lcaggio](https://github.com/lcaggio)) <!-- 2023-01-12 22:17:05+00:00 -->
- [[#1084](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1084)] Fixes in Apigee blueprints README files ([apichick](https://github.com/apichick)) <!-- 2023-01-05 11:00:46+00:00 -->
- [[#1081](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1081)] Apigee hybrid on GKE ([apichick](https://github.com/apichick)) <!-- 2023-01-05 08:23:33+00:00 -->
- [[#1074](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1074)] Adding new section for Authentication issues ([agutta](https://github.com/agutta)) <!-- 2022-12-29 15:50:23+00:00 -->
@ -28,6 +39,9 @@ All notable changes to this project will be documented in this file.
### FAST
- [[#1118](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1118)] Add missing logging admin role for initial user ([ludoo](https://github.com/ludoo)) <!-- 2023-01-28 08:41:23+00:00 -->
- [[#1099](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1099)] Fix destroy in stage 1 outputs ([ludoo](https://github.com/ludoo)) <!-- 2023-01-19 09:35:41+00:00 -->
- [[#1089](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1089)] Update Data Platform ([lcaggio](https://github.com/lcaggio)) <!-- 2023-01-12 22:17:05+00:00 -->
- [[#1085](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1085)] fix restricted services not being added to the perimeter configurations ([drebes](https://github.com/drebes)) <!-- 2023-01-06 12:25:31+00:00 -->
- [[#1057](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1057)] Adding new file FAQ and an image ([agutta](https://github.com/agutta)) <!-- 2022-12-22 14:00:22+00:00 -->
- [[#1054](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1054)] FAST: fix typo in bootstrap stage README ([agutta](https://github.com/agutta)) <!-- 2022-12-16 16:00:00+00:00 -->
@ -35,6 +49,14 @@ All notable changes to this project will be documented in this file.
### MODULES
- [[#1116](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1116)] Include cloudbuild API in project module ([aymanfarhat](https://github.com/aymanfarhat)) <!-- 2023-01-27 20:38:01+00:00 -->
- [[#1115](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1115)] add new parameters support in apigee module ([blackillzone](https://github.com/blackillzone)) <!-- 2023-01-27 16:39:46+00:00 -->
- [[#1112](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1112)] Add HTTPS frontend with SNEG example ([juliodiez](https://github.com/juliodiez)) <!-- 2023-01-26 19:17:31+00:00 -->
- [[#1097](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1097)] Use terraform resource to activate Anthos Service Mesh ([wiktorn](https://github.com/wiktorn)) <!-- 2023-01-23 08:25:31+00:00 -->
- [[#1101](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1101)] First batch of testing updates to core modules ([juliocc](https://github.com/juliocc)) <!-- 2023-01-20 06:49:41+00:00 -->
- [[#1098](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1098)] Add shared-vpc support on data-playground blueprint ([lcaggio](https://github.com/lcaggio)) <!-- 2023-01-19 08:08:29+00:00 -->
- [[#1096](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1096)] [VPC-SC] Add support for scoped Policies ([lcaggio](https://github.com/lcaggio)) <!-- 2023-01-17 14:30:34+00:00 -->
- [[#1093](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1093)] Added tags to gke-cluster module ([apichick](https://github.com/apichick)) <!-- 2023-01-13 12:12:17+00:00 -->
- [[#1078](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1078)] Fixed delete_rule in compute-mig module for stateful disks ([rosmo](https://github.com/rosmo)) <!-- 2023-01-04 08:14:40+00:00 -->
- [[#1080](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1080)] Added device_name field to compute-vm attached_disks parameter ([rosmo](https://github.com/rosmo)) <!-- 2023-01-03 20:53:48+00:00 -->
- [[#1079](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1079)] Reorder org policy rules ([juliocc](https://github.com/juliocc)) <!-- 2023-01-03 16:11:29+00:00 -->
@ -53,6 +75,8 @@ All notable changes to this project will be documented in this file.
### TOOLS
- [[#1107](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1107)] Check linting for Python dashboard files ([ludoo](https://github.com/ludoo)) <!-- 2023-01-21 16:17:52+00:00 -->
- [[#1101](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1101)] First batch of testing updates to core modules ([juliocc](https://github.com/juliocc)) <!-- 2023-01-20 06:49:41+00:00 -->
- [[#1091](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1091)] Fix check_documentation output ([juliocc](https://github.com/juliocc)) <!-- 2023-01-12 14:43:13+00:00 -->
- [[#1053](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1053)] Extend inventory-based testing to examples ([juliocc](https://github.com/juliocc)) <!-- 2022-12-18 19:50:34+00:00 -->

View File

@ -754,7 +754,7 @@ def test_name(plan_summary, tfvars_to_yaml, tmp_path):
assert s.values[address]['project'] == 'my-project'
```
For more examples on how to write python tests, the tests for [`organization`](./tests/modules/organization/test_plan_org_policies.py) and [`net-vpc`](./tests/modules/net_vpc/test_routes.py) modules.
For more examples on how to write python tests, check the tests for the [`organization`](./tests/modules/organization/test_plan_org_policies.py) module.
#### Testing documentation examples

View File

@ -826,9 +826,9 @@
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"node_modules/cookiejar": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz",
"integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ=="
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw=="
},
"node_modules/debug": {
"version": "2.6.9",
@ -3783,9 +3783,9 @@
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"cookiejar": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz",
"integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ=="
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw=="
},
"debug": {
"version": "2.6.9",

View File

@ -25,20 +25,24 @@ The diagram below depicts the architecture.
terraform apply
```
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.
5. Install Apigee hybrid using de ansible playbook that is in the ansible folder by running this command
ansible-playbook playbook.yaml -vvvß
## Testing the blueprint
2. Deploy an api proxy
```
./deploy-apiproxy.sh
./deploy-apiproxy.sh apis-test
```
3. In the console check the IP address that has been allocated to the Apigee ingress gateway and send some traffic to the deployed API proxy.
3. Send a request
```
curl -k -v -H "Host:HOSTNAME" \
--resolve HOSTNAME:443:IP_ADDRESS \
https://HOSTNAME/httpbin/headers
curl -v https://HOSTNAME/httpbin/headers
```
<!-- BEGIN TFDOC -->
@ -56,4 +60,10 @@ The diagram below depicts the architecture.
| [region](variables.tf#L84) | Region. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [zone](variables.tf#L90) | Zone. | <code>string</code> | | <code>&#34;europe-west1-c&#34;</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [ip_address](outputs.tf#L17) | GLB IP address. | |
<!-- END TFDOC -->

View File

@ -18,12 +18,13 @@
resource "local_file" "vars_file" {
content = yamlencode({
cluster = module.cluster.name
region = var.region
project_id = module.project.project_id
envgroup = local.envgroup
env = local.environment
hostname = var.hostname
cluster = module.cluster.name
region = var.region
project_id = module.project.project_id
envgroups = local.envgroups
environments = local.environments
service_accounts = local.google_sas
ingress_ip_name = local.ingress_ip_name
})
filename = "${path.module}/ansible/vars/vars.yaml"
file_permission = "0666"

View File

@ -0,0 +1,28 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
- name: Create and annotate k8s service account
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: ServiceAccount
metadata:
name: "{{ k8s_service_account }}"
namespace: apigee
annotations:
iam.gke.io/gcp-service-account: "{{ google_service_account }}@{{ project_id }}.iam.gserviceaccount.com"
with_items: "{{ k8s_service_accounts }}"
loop_control:
loop_var: k8s_service_account

View File

@ -1,11 +1,11 @@
# Copyright 2023 Google LLC
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -19,18 +19,27 @@
--project {{ project_id }} \
--internal-ip
- name: Install cert-manager
shell: >
kubectl apply \
--validate=false \
-f https://github.com/jetstack/cert-manager/releases/download/v1.7.2/cert-manager.yaml
- name: Download cert-manager
uri:
url: https://github.com/jetstack/cert-manager/releases/download/v1.7.2/cert-manager.yaml
dest: ~/cert-manager.yaml
- name: Wait until pods are ready in cert-manager namespace
shell: >
kubectl wait --for=condition=ready pods \
-l app.kubernetes.io/instance=cert-manager \
-n cert-manager \
--timeout=90s
- name: Apply metrics-server manifest to the cluster.
kubernetes.core.k8s:
state: present
src: ~/cert-manager.yaml
- name:
kubernetes.core.k8s_info:
kind: Pod
wait: yes
label_selectors:
- "app.kubernetes.io/instance=cert-manager"
namespace: cert-manager
wait_timeout: 90
wait_condition:
type: Ready
status: True
- name: Fetch apigeectl version
uri:
@ -48,7 +57,7 @@
unarchive:
src: "~/apigeectl.tar.gz"
dest: "~"
remote_src: yes
remote_src: yes
- name: Move apigeectl folder
shell: >
@ -66,25 +75,69 @@
file:
src: ~/apigeectl/{{ item }}
dest: "~/hybrid-files/{{ item }}"
state: link
state: link
with_items:
- tools
- config
- templates
- plugins
- plugins
- name: Create service accounts
shell: >
~/hybrid-files/tools/create-service-account -i {{ project_id }} -e non-prod -d ~/hybrid-files/service-accounts
- name: Create apigee namespace
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Namespace
metadata:
name: apigee
- name: Create certificates
- name: Create k8s service accounts
include_tasks: k8s_service_accounts.yaml
vars:
google_service_account: "{{ item.key }}"
k8s_service_accounts: "{{ item.value }}"
with_dict: "{{ service_accounts }}"
- name: Set hostnames
set_fact:
hostnames: "{{ hostnames | default([]) + item.value }}"
with_dict: "{{ envgroups }}"
- name: Create certificate and private key
shell: >
openssl req \
-nodes \
-new \
-x509 \
-keyout ~/hybrid-files/certs/{{ envgroup }}.key \
-out ~/hybrid-files/certs/{{ envgroup }}.cert -subj '/CN='{{ hostname }}'' -days 3650
-keyout ~/hybrid-files/certs/server.key \
-out ~/hybrid-files/certs/server.crt \
-subj "/CN=apigee.com' \
-addext "subjectAltName={{ hostnames | map('regex_replace', '^', 'DNS:') | join(',') }}""
-days 3650
- name: Read certificate
slurp:
src: ~/hybrid-files/certs/server.crt
register: certificate_output
- name: Read private ket
slurp:
src: ~/hybrid-files/certs/server.key
register: privatekey_output
- name: Create secret
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Secret
metadata:
name: tls-hybrid-ingress
namespace: apigee
type: kubernetes.io/tls
data:
tls.crt: "{{ certificate_output.content }}"
tls.key: "{{ privatekey_output.content }}"
- name: Create overrides.yaml
template:
@ -96,48 +149,185 @@
curl -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type:application/json" \
"https://apigee.googleapis.com/v1/organizations/{{ project_id }}:setSyncAuthorization" \
-d '{"identities":["'"serviceAccount:apigee-non-prod@{{ project_id }}.iam.gserviceaccount.com"'"]}'
-d '{"identities":["'"serviceAccount:apigee-synchronizer@{{ project_id }}.iam.gserviceaccount.com"'"]}'
- name: Dry-run (init)
shell: >
~/apigeectl/apigeectl init -f overrides/overrides.yaml --dry-run=client
~/apigeectl/apigeectl init -f overrides/overrides.yaml --dry-run=client
args:
chdir: ~/hybrid-files
- name: Install the Apigee deployment services Apigee Deployment Controller and Apigee Admission Webhook.
shell: >
~/apigeectl/apigeectl init -f overrides/overrides.yaml
~/apigeectl/apigeectl init -f overrides/overrides.yaml
args:
chdir: ~/hybrid-files
chdir: ~/hybrid-files
- name: Wait until pods are ready in apigee-system namespace
shell: >
kubectl wait --for=condition=ready pods \
-l app=apigee-controller \
-n apigee-system \
--timeout=300s
- name: Wait for apigee-controller pod to be ready
kubernetes.core.k8s_info:
kind: Pod
wait: yes
label_selectors:
- "app=apigee-controller"
namespace: apigee-system
wait_timeout: 600
wait_condition:
type: Ready
status: True
- name: Wait until pods are ready in apigee namespace
shell: >
kubectl wait --for=condition=ready pods \
-l app=apigee-ingressgateway-manager \
-n apigee \
--timeout=300s
- name: Wait for apigee-selfsigned-issuer issuer to be ready
kubernetes.core.k8s_info:
kind: Issuer
wait: yes
name: apigee-selfsigned-issuer
namespace: apigee-system
wait_timeout: 600
wait_condition:
type: Ready
status: True
- name: Wait for apigee-serving-cert certificate to be ready
kubernetes.core.k8s_info:
kind: Certificate
wait: yes
name: apigee-serving-cert
namespace: apigee-system
wait_timeout: 600
wait_condition:
type: Ready
status: True
- name: Wait for apigee-resources-install job to be complete
kubernetes.core.k8s_info:
kind: Job
wait: yes
name: apigee-resources-install
namespace: apigee-system
wait_timeout: 360
wait_condition:
type: Complete
status: True
- name: Dry-run (apply)
shell: >
~/apigeectl/apigeectl apply -f overrides/overrides.yaml --dry-run=client
~/apigeectl/apigeectl apply -f overrides/overrides.yaml --dry-run=client
args:
chdir: ~/hybrid-files
- name: Install the Apigee runtime components
shell: >
~/apigeectl/apigeectl apply -f overrides/overrides.yaml
~/apigeectl/apigeectl apply -f overrides/overrides.yaml
args:
chdir: ~/hybrid-files
chdir: ~/hybrid-files
- name: Check status of the deployment
shell: >
while [ -n "$(kubectl get pods -n apigee | tail -n +2 | grep -v Running | grep -v Completed)" ]; do sleep 1; done
args:
chdir: ~/hybrid-files
- name: Wait for apigee-runtime pod to be ready
kubernetes.core.k8s_info:
kind: Pod
wait: yes
label_selectors:
- "app=apigee-runtime"
namespace: apigee
wait_timeout: 360
wait_condition:
type: Ready
status: True
- name:
kubernetes.core.k8s:
state: present
definition:
apiVersion: apigee.cloud.google.com/v1alpha1
kind: ApigeeRoute
metadata:
name: apigee-wildcard
namespace: apigee
spec:
hostnames:
- '*'
ports:
- number: 443
protocol: HTTPS
tls:
credentialName: tls-hybrid-ingress
mode: SIMPLE
selector:
app: apigee-ingressgateway
enableNonSniClient: true
- name: Create google-managed certificate
kubernetes.core.k8s:
state: present
definition:
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
name: "apigee-cert-hybrid"
namespace: apigee
spec:
domains: "{{ hostnames }}"
- name: Create backend config
kubernetes.core.k8s:
state: present
definition:
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: apigee-ingress-backendconfig
namespace: apigee
spec:
healthCheck:
requestPath: /healthz/ready
port: 15021
type: HTTP
logging:
enable: true
sampleRate: 0.5
- name: Create service
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: apigee-ingressgateway-hybrid
namespace: apigee
annotations:
cloud.google.com/backend-config: '{"default": "apigee-ingress-backendconfig"}'
cloud.google.com/neg: '{"ingress": true}'
cloud.google.com/app-protocols: '{"https":"HTTPS", "status-port": "HTTP"}'
labels:
app: apigee-ingressgateway-hybrid
spec:
ports:
- name: status-port
port: 15021
targetPort: 15021
- name: https
port: 443
targetPort: 8443
selector:
app: apigee-ingressgateway
ingress_name: ingress
type: ClusterIP
- name: Create ingress
kubernetes.core.k8s:
state: present
definition:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
networking.gke.io/managed-certificates: "apigee-cert-hybrid"
kubernetes.io/ingress.global-static-ip-name: "{{ ingress_ip_name }}"
kubernetes.io/ingress.allow-http: "false"
name: xlb-apigee
namespace: apigee
spec:
defaultBackend:
service:
name: apigee-ingressgateway-hybrid
port:
number: 443

View File

@ -1,29 +1,26 @@
gcp:
region: {{ region }}
projectID: {{ project_id }}
workloadIdentityEnabled: true
k8sCluster:
name: {{ cluster }}
region: CLUSTER_LOCATION # Must be the closest Google Cloud region to your cluster.
region: {{ region }} # Must be the closest Google Cloud region to your cluster.
org: {{ project_id }}
instanceID: "instance-1"
instanceID: "{{ cluster }}-{{ region }}"
cassandra:
hostNetwork: false
# Set to false for single region installations and multi-region installations
# with connectivity between pods in different clusters, for example GKE installations.
# Set to true for multi-region installations with no communication between
# pods in different clusters, for example GKE On-prem, GKE on AWS, Anthos on bare metal,
# AKS, EKS, and OpenShift installations.
# See Multi-region deployment: Prerequisites
virtualhosts:
- name: {{ envgroup }}
{% for k in envgroups %}
- name: {{ k }}
sslSecret: tls-hybrid-ingress
additionalGateways: ["apigee-wildcard"]
selector:
app: apigee-ingressgateway
sslCertPath: ./certs/{{ envgroup }}.cert
sslKeyPath: ./certs/{{ envgroup }}.key
{% endfor %}
ao:
args:
@ -37,27 +34,9 @@ ingressGateways:
replicaCountMax: 10
envs:
- name: {{ env }}
serviceAccountPaths:
synchronizer: ./service-accounts/{{ project_id }}-apigee-non-prod.json
udca: ./service-accounts/{{ project_id }}-apigee-non-prod.json
runtime: ./service-accounts/{{ project_id }}-apigee-non-prod.json
mart:
serviceAccountPath: ./service-accounts/{{ project_id }}-apigee-non-prod.json
connectAgent:
serviceAccountPath: ./service-accounts/{{ project_id }}-apigee-non-prod.json
metrics:
serviceAccountPath: ./service-accounts/{{ project_id }}-apigee-non-prod.json
udca:
serviceAccountPath: ./service-accounts/{{ project_id }}-apigee-non-prod.json
watcher:
serviceAccountPath: ./service-accounts/{{ project_id }}-apigee-non-prod.json
{% for k in environments %}
- name: {{ k }}
{% endfor %}
logger:
enabled: true
serviceAccountPath: ./service-accounts/{{ project_id }}-apigee-non-prod.json
enabled: false

View File

@ -15,8 +15,51 @@
*/
locals {
envgroup = "test"
environment = "apis-test"
envgroups = {
test = [var.hostname]
}
environments = {
apis-test = {
envgroups = ["test"]
}
}
org_short_name = (length(module.project.project_id) < 16 ?
module.project.project_id :
substr(module.project.project_id, 0, 15))
org_hash = format("%s-%s", local.org_short_name, substr(sha256(module.project.project_id), 0, 7))
org_env_hashes = {
for k, v in local.environments :
k => format("%s-%s-%s", local.org_short_name, length(k) < 16 ? k : substr(k, 0, 15), substr(sha256("${module.project.project_id}:${k}"), 0, 7))
}
google_sas = {
apigee-metrics = [
"apigee-metrics-sa"
]
apigee-cassandra = [
"apigee-cassandra-schema-setup-${local.org_hash}-sa",
"apigee-cassandra-user-setup-${local.org_hash}-sa"
]
apigee-mart = [
"apigee-mart-${local.org_hash}-sa",
"apigee-connect-agent-${local.org_hash}-sa"
]
apigee-watcher = [
"apigee-watcher-${local.org_hash}-sa"
]
apigee-udca = concat([
"apigee-udca-${local.org_hash}-sa"
],
[for k, v in local.org_env_hashes :
"apigee-udca-${local.org_env_hashes[k]}-sa"
])
apigee-synchronizer = [
for k, v in local.org_env_hashes :
"apigee-synchronizer-${local.org_env_hashes[k]}-sa"
]
apigee-runtime = [for k, v in local.org_env_hashes :
"apigee-runtime-${local.org_env_hashes[k]}-sa"
]
}
}
module "apigee" {
@ -26,20 +69,24 @@ module "apigee" {
analytics_region = var.region
runtime_type = "HYBRID"
}
envgroups = {
(local.envgroup) = [var.hostname]
}
environments = {
(local.environment) = {
envgroups = [local.envgroup]
}
envgroups = local.envgroups
environments = local.environments
}
module "sas" {
for_each = local.google_sas
source = "../../../modules/iam-service-account"
project_id = module.project.project_id
name = each.key
# authoritative roles granted *on* the service accounts to other identities
iam = {
"roles/iam.workloadIdentityUser" = [for v in each.value : "serviceAccount:${module.project.project_id}.svc.id.goog[apigee/${v}]"]
}
}
resource "local_file" "deploy_apiproxy_file" {
content = templatefile("${path.module}/templates/deploy-apiproxy.sh.tpl", {
org = module.project.project_id
env = local.environment
})
filename = "${path.module}/deploy-apiproxy.sh"
file_permission = "0777"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,14 +14,12 @@
* limitations under the License.
*/
module "test" {
source = "../../../../modules/dns"
project_id = "my-project"
name = "test"
domain = "test.example."
client_networks = var.client_networks
type = var.type
forwarders = var.forwarders
peer_network = var.peer_network
recordsets = var.recordsets
locals {
ingress_ip_name = "apigee"
}
module "addresses" {
source = "../../../modules/net-address"
project_id = module.project.project_id
global_addresses = [local.ingress_ip_name]
}

View File

@ -40,5 +40,12 @@ module "project" {
"roles/resourcemanager.projectIamAdmin" = [module.mgmt_server.service_account_iam_email]
"roles/iam.serviceAccountAdmin" = [module.mgmt_server.service_account_iam_email]
"roles/iam.serviceAccountKeyAdmin" = [module.mgmt_server.service_account_iam_email]
"roles/monitoring.metricWriter" = [module.sas["apigee-metrics"].iam_email]
"roles/storage.objectAdmin" = [module.sas["apigee-cassandra"].iam_email]
"roles/apigeeconnect.Agent" = [module.sas["apigee-mart"].iam_email]
"roles/apigee.runtimeAgent" = [module.sas["apigee-watcher"].iam_email]
"roles/apigee.analyticsAgent" = [module.sas["apigee-udca"].iam_email]
"roles/apigee.synchronizerManager" = [module.sas["apigee-synchronizer"].iam_email]
"roles/cloudtrace.agent" = [module.sas["apigee-runtime"].iam_email]
}
}
}

View File

@ -34,4 +34,12 @@ module "mgmt_server" {
type = var.mgmt_server_config.disk_type
size = var.mgmt_server_config.disk_size
}
}
metadata = {
startup-script = <<EOT
#!/bin/bash
apt update -y
apt install python3-pip -y
pip3 install kubernetes
EOT
}
}

View File

@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -14,16 +14,7 @@
* limitations under the License.
*/
module "test" {
source = "../../../../modules/gke-cluster"
project_id = "my-project"
name = "cluster-1"
location = "europe-west1-b"
vpc_config = {
network = "mynetwork"
subnetwork = "mysubnet"
}
enable_addons = var.enable_addons
enable_features = var.enable_features
tags = var.tags
output "ip_address" {
description = "GLB IP address."
value = module.addresses.global_addresses["apigee"].address
}

View File

@ -14,8 +14,13 @@
#!/bin/bash
if [ $# -lt 1 ]; then
echo "Usage: $0 ENVIRONMENT"
exit 1
fi
ORG_NAME=${org}
ENV_NAME=${env}
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

View File

@ -1,5 +1,4 @@
{
"category": "CUSTOM",
"displayName": "quotas_utilization",
"mosaicLayout": {
"columns": 12,
@ -18,7 +17,6 @@
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "3600s",
@ -40,9 +38,7 @@
}
}
},
"width": 6,
"xPos": 0,
"yPos": 0
"width": 6
},
{
"height": 4,
@ -58,7 +54,6 @@
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "3600s",
@ -81,7 +76,6 @@
}
},
"width": 6,
"xPos": 0,
"yPos": 12
},
{
@ -98,7 +92,6 @@
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "3600s",
@ -121,7 +114,6 @@
}
},
"width": 6,
"xPos": 0,
"yPos": 8
},
{
@ -138,7 +130,6 @@
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "3600s",
@ -178,7 +169,6 @@
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "3600s",
@ -201,7 +191,6 @@
}
},
"width": 6,
"xPos": 0,
"yPos": 4
},
{
@ -218,7 +207,6 @@
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "3600s",
@ -241,8 +229,7 @@
}
},
"width": 6,
"xPos": 6,
"yPos": 0
"xPos": 6
},
{
"height": 4,
@ -258,7 +245,6 @@
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "3600s",
@ -298,7 +284,6 @@
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "3600s",
@ -330,17 +315,19 @@
},
"dataSets": [
{
"minAlignmentPeriod": "60s",
"minAlignmentPeriod": "3600s",
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "60s",
"perSeriesAligner": "ALIGN_MEAN"
"alignmentPeriod": "3600s",
"perSeriesAligner": "ALIGN_NEXT_OLDER"
},
"filter": "metric.type=\"custom.googleapis.com/netmon/peering_group/routes_dynamic_used_ratio\" resource.type=\"global\""
"filter": "metric.type=\"custom.googleapis.com/netmon/peering_group/routes_dynamic_used_ratio\" resource.type=\"global\"",
"secondaryAggregation": {
"alignmentPeriod": "60s"
}
}
}
}
@ -353,7 +340,6 @@
}
},
"width": 6,
"xPos": 0,
"yPos": 20
},
{
@ -366,21 +352,23 @@
},
"dataSets": [
{
"minAlignmentPeriod": "60s",
"minAlignmentPeriod": "3600s",
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "60s",
"alignmentPeriod": "3600s",
"crossSeriesReducer": "REDUCE_SUM",
"groupByFields": [
"metric.label.\"project\""
],
"perSeriesAligner": "ALIGN_MEAN"
"perSeriesAligner": "ALIGN_NEXT_OLDER"
},
"filter": "metric.type=\"custom.googleapis.com/netmon/project/firewall_rules_used_ratio\" resource.type=\"global\""
"filter": "metric.type=\"custom.googleapis.com/netmon/project/firewall_rules_used_ratio\" resource.type=\"global\"",
"secondaryAggregation": {
"alignmentPeriod": "60s"
}
}
}
}
@ -393,8 +381,7 @@
}
},
"width": 6,
"xPos": 0,
"yPos": 32
"yPos": 28
},
{
"height": 4,
@ -406,17 +393,19 @@
},
"dataSets": [
{
"minAlignmentPeriod": "60s",
"minAlignmentPeriod": "3600s",
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "60s",
"perSeriesAligner": "ALIGN_MEAN"
"alignmentPeriod": "3600s",
"perSeriesAligner": "ALIGN_NEXT_OLDER"
},
"filter": "metric.type=\"custom.googleapis.com/netmon/firewall_policy/tuples_used_ratio\" resource.type=\"global\""
"filter": "metric.type=\"custom.googleapis.com/netmon/firewall_policy/tuples_used_ratio\" resource.type=\"global\"",
"secondaryAggregation": {
"alignmentPeriod": "60s"
}
}
}
}
@ -430,7 +419,7 @@
},
"width": 6,
"xPos": 6,
"yPos": 28
"yPos": 24
},
{
"height": 4,
@ -442,17 +431,135 @@
},
"dataSets": [
{
"minAlignmentPeriod": "60s",
"minAlignmentPeriod": "3600s",
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "60s",
"perSeriesAligner": "ALIGN_MEAN"
"alignmentPeriod": "3600s",
"perSeriesAligner": "ALIGN_NEXT_OLDER"
},
"filter": "metric.type=\"custom.googleapis.com/netmon/subnetwork/addresses_used_ratio\" resource.type=\"global\""
"filter": "metric.type=\"custom.googleapis.com/netmon/subnetwork/addresses_used_ratio\" resource.type=\"global\"",
"secondaryAggregation": {
"alignmentPeriod": "60s"
}
}
}
}
],
"timeshiftDuration": "0s",
"yAxis": {
"label": "y1Axis",
"scale": "LINEAR"
}
}
},
"width": 6,
"yPos": 16
},
{
"height": 4,
"widget": {
"title": "Project static routes used",
"xyChart": {
"chartOptions": {
"mode": "COLOR"
},
"dataSets": [
{
"minAlignmentPeriod": "3600s",
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "3600s",
"crossSeriesReducer": "REDUCE_SUM",
"groupByFields": [
"metric.label.\"project\""
],
"perSeriesAligner": "ALIGN_NEXT_OLDER"
},
"filter": "metric.type=\"custom.googleapis.com/netmon/project/routes_static_used_ratio\" resource.type=\"global\"",
"secondaryAggregation": {
"alignmentPeriod": "60s"
}
}
}
}
],
"timeshiftDuration": "0s",
"yAxis": {
"label": "y1Axis",
"scale": "LINEAR"
}
}
},
"width": 6,
"xPos": 6,
"yPos": 20
},
{
"height": 4,
"widget": {
"title": "Peering group static routes used",
"xyChart": {
"chartOptions": {
"mode": "COLOR"
},
"dataSets": [
{
"minAlignmentPeriod": "3600s",
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "3600s",
"perSeriesAligner": "ALIGN_NEXT_OLDER"
},
"filter": "metric.type=\"custom.googleapis.com/netmon/peering_group/routes_static_used_ratio\" resource.type=\"global\"",
"secondaryAggregation": {
"alignmentPeriod": "60s"
}
}
}
}
],
"timeshiftDuration": "0s",
"yAxis": {
"label": "y1Axis",
"scale": "LINEAR"
}
}
},
"width": 6,
"yPos": 24
},
{
"height": 4,
"widget": {
"title": "Addresses used ratio per psa range [NEXT OLDER]",
"xyChart": {
"chartOptions": {
"mode": "COLOR"
},
"dataSets": [
{
"minAlignmentPeriod": "3600s",
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "3600s",
"perSeriesAligner": "ALIGN_NEXT_OLDER"
},
"filter": "metric.type=\"custom.googleapis.com/netmon/network/psa/addresses_used_ratio\" resource.type=\"global\"",
"secondaryAggregation": {
"alignmentPeriod": "60s"
}
}
}
}
@ -467,88 +574,6 @@
"width": 6,
"xPos": 6,
"yPos": 16
},
{
"height": 4,
"widget": {
"title": "Project static routes used",
"xyChart": {
"chartOptions": {
"mode": "COLOR"
},
"dataSets": [
{
"minAlignmentPeriod": "60s",
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "60s",
"crossSeriesReducer": "REDUCE_SUM",
"groupByFields": [
"metric.label.\"project\""
],
"perSeriesAligner": "ALIGN_MEAN"
},
"filter": "metric.type=\"custom.googleapis.com/netmon/project/routes_static_used_ratio\" resource.type=\"global\"",
"secondaryAggregation": {
"alignmentPeriod": "60s",
"perSeriesAligner": "ALIGN_NONE"
}
}
}
}
],
"thresholds": [],
"timeshiftDuration": "0s",
"yAxis": {
"label": "y1Axis",
"scale": "LINEAR"
}
}
},
"width": 6,
"xPos": 0,
"yPos": 24
},
{
"height": 4,
"widget": {
"title": "Peering group static routes used",
"xyChart": {
"chartOptions": {
"mode": "COLOR"
},
"dataSets": [
{
"minAlignmentPeriod": "60s",
"plotType": "LINE",
"targetAxis": "Y1",
"timeSeriesQuery": {
"apiSource": "DEFAULT_CLOUD",
"timeSeriesFilter": {
"aggregation": {
"alignmentPeriod": "60s",
"perSeriesAligner": "ALIGN_MEAN"
},
"filter": "metric.type=\"custom.googleapis.com/netmon/peering_group/routes_static_used_ratio\" resource.type=\"global\""
}
}
}
],
"thresholds": [],
"timeshiftDuration": "0s",
"yAxis": {
"label": "y1Axis",
"scale": "LINEAR"
}
}
},
"width": 6,
"xPos": 0,
"yPos": 28
}
]
}

View File

@ -74,7 +74,7 @@ dashboard_json_path = "../dashboards/quotas-utilization.json"
| [name](variables.tf#L75) | Name used to create Cloud Function related resources. | <code>string</code> | | <code>&#34;net-dash&#34;</code> |
| [project_create_config](variables.tf#L81) | Optional configuration if project creation is required. | <code title="object&#40;&#123;&#10; billing_account_id &#61; string&#10; parent_id &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L95) | Compute region where the Cloud Function will be deployed. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
| [schedule_config](variables.tf#L101) | Schedule timer configuration in crontab format. | <code>string</code> | | <code>&#34;0&#47;30 &#42; &#42; &#42; &#42;&#34;</code> |
| [schedule_config](variables.tf#L101) | Schedule timer configuration in crontab format. | <code>string</code> | | <code>&#34;&#42;&#47;30 &#42; &#42; &#42; &#42;&#34;</code> |
## Outputs

View File

@ -101,5 +101,5 @@ variable "region" {
variable "schedule_config" {
description = "Schedule timer configuration in crontab format."
type = string
default = "0/30 * * * *"
default = "*/30 * * * *"
}

View File

@ -84,8 +84,8 @@ def do_discovery(resources):
{k: len(v) for k, v in resources.items() if not isinstance(v, str)}))
def do_init(resources, discovery_root, monitoring_project, folders=None, projects=None,
custom_quota=None):
def do_init(resources, discovery_root, monitoring_project, folders=None,
projects=None, custom_quota=None):
'''Calls init plugins to configure keys in the shared resource map.
Args:

View File

@ -39,7 +39,9 @@ TYPES = {
'subnetworks': 'compute.googleapis.com/Subnetwork',
'routers': 'compute.googleapis.com/Router',
'routes': 'compute.googleapis.com/Route',
'sql_instances': 'sqladmin.googleapis.com/Instance'
'sql_instances': 'sqladmin.googleapis.com/Instance',
'filestore_instances': 'file.googleapis.com/Instance',
'memorystore_instances': 'redis.googleapis.com/Instance',
}
NAMES = {v: k for k, v in TYPES.items()}
@ -62,8 +64,8 @@ def _handle_discovery(resources, response, data):
'Processes the asset API response and returns parsed resources or next URL.'
LOGGER.info('discovery handle request')
for result in parse_cai_results(data, 'cai-compute', method='list'):
resource = _handle_resource(
resources, result['assetType'], result['resource'])
resource = _handle_resource(resources, result['assetType'],
result['resource'])
if not resource:
continue
yield resource
@ -82,10 +84,16 @@ def _handle_resource(resources, asset_type, data):
# e.g. assetType = GlobalAddress but discoveryName = Address
resource_name = NAMES[asset_type]
resource = {
'id': attrs.get('id'),
'name': attrs['name'],
'self_link': _self_link(attrs['selfLink']),
'assetType': asset_type
'id':
attrs.get('id'),
'name':
attrs['name'],
# Some resources (ex: Filestore) don't have a self_link, using parent + name in that case
'self_link':
f'{data["parent"]}/{attrs["name"]}'
if not 'selfLink' in attrs else _self_link(attrs['selfLink']),
'assetType':
asset_type
}
# derive parent type and id and skip if parent is not within scope
parent_data = _get_parent(data['parent'], resources)
@ -212,8 +220,41 @@ def _handle_sql_instances(resource, data):
],
'region': data['region'],
'availabilityType': data['settings']['availabilityType'],
'network': data['settings']['ipConfiguration']['privateNetwork']
}
def _handle_filestore_instances(resource, data):
'Handles filestore instance type resource data.'
return {
# Getting only the instance name, removing the rest
'name': data['name'].split('/')[-1],
# Is a list but for now, only one network is supported for Filestore
'network': data['networks'][0]['network'],
'reservedIpRange': data['networks'][0]['reservedIpRange'],
'ipAddresses': data['networks'][0]['ipAddresses']
}
def _handle_memorystore_instances(resource, data):
'Handles Memorystore (Redis) instance type resource data.'
return {
# Getting only the instance name, removing the rest
'name':
data['name'].split('/')[-1],
'locationId':
data['locationId'],
'replicaCount':
0 if not 'replicaCount' in data else data['replicaCount'],
'network':
data['authorizedNetwork'],
'reservedIpRange':
'' if not 'reservedIpRange' in data else data['reservedIpRange'],
'host':
'' if not 'host' in data else data['host'],
}
def _handle_subnetworks(resource, data):
'Handles subnetwork type resource data.'
secondary_ranges = [{
@ -237,8 +278,7 @@ def _self_link(s):
def _url(resources):
'Returns discovery URL'
discovery_root = resources['config:discovery_root']
asset_types = '&'.join(
f'assetTypes={t}' for t in TYPES.values())
asset_types = '&'.join(f'assetTypes={t}' for t in TYPES.values())
return CAI_URL.format(root=discovery_root, asset_types=asset_types)

View File

@ -34,7 +34,28 @@ def _sql_addresses(sql_instances):
if not v['ipAddresses']:
continue
# 1 IP for the instance + 1 IP for the ILB + 1 IP if HA
yield v['ipAddresses'][0], 2 if v['availabilityType'] != 'REGIONAL' else 3
yield v['ipAddresses'][
0], 2 if v['availabilityType'] != 'REGIONAL' else 3, v['network']
def _filestore_addresses(filestore_instances):
'Returns counts of Filestore instances per PSA range.'
for v in filestore_instances.values():
if not v['ipAddresses'] or not v['reservedIpRange']:
continue
# Subnet size (reservedIpRange) can be /29, /26 or /24
yield v['ipAddresses'][0], ipaddress.ip_network(
v['reservedIpRange']).num_addresses, v['network']
def _memorystore_addresses(memorystore_instances):
'Returns counts of Memorystore (Redis) instances per PSA range.'
for v in memorystore_instances.values():
if not v['reservedIpRange'] or v['reservedIpRange'] == '':
continue
# Subnet size (reservedIpRange) can be minimum /28 or /29
yield v['host'], ipaddress.ip_network(
v['reservedIpRange']).num_addresses, v['network']
@register_timeseries
@ -46,25 +67,34 @@ def timeseries(resources):
('project', 'network', 'subnetwork'),
dtype.endswith('ratio'))
psa_nets = {
k: ipaddress.ip_network('{}/{}'.format(v['address'], v['prefixLength']))
for k, v in resources['global_addresses'].items() if v['prefixLength']
k: {
'network_link':
v['network'],
'network_prefix':
ipaddress.ip_network('{}/{}'.format(v['address'],
v['prefixLength']))
} for k, v in resources['global_addresses'].items() if v['prefixLength']
}
psa_counts = {}
for address, ip_count in _sql_addresses(resources.get('sql_instances', {})):
for address, ip_count, network in itertools.chain(
_sql_addresses(resources.get('sql_instances', {})),
_filestore_addresses(resources.get('filestore_instances', {})),
_memorystore_addresses(resources.get('memorystore_instances', {}))):
ip_address = ipaddress.ip_address(address)
for k, v in psa_nets.items():
if ip_address in v:
if network == v['network_link'] and ip_address in v['network_prefix']:
psa_counts[k] = psa_counts.get(k, 0) + ip_count
break
for k, v in psa_counts.items():
max_ips = psa_nets[k].num_addresses - 4
max_ips = psa_nets[k]['network_prefix'].num_addresses - 4
psa_range = resources['global_addresses'][k]
labels = {
'network': psa_range['network'],
'project': psa_range['project_id'],
'psa_range': psa_range['name']
}
yield TimeSeries('network/psa/addresses_available', max_ips, labels)
yield TimeSeries('network/psa/addresses_used', v, labels)
yield TimeSeries('network/psa/addresses_used_ratio',

View File

@ -219,7 +219,7 @@ module "data-platform" {
prefix = "myprefix"
}
# tftest modules=39 resources=286
# tftest modules=39 resources=287
```
## Customizations

View File

@ -23,25 +23,6 @@
set_fact:
context: "gke_{{ project_id }}_{{ region }}_{{ cluster }}"
- name: Install ASM in cluster
shell: >
gcloud container fleet mesh update \
--control-plane automatic \
--memberships {{ cluster }} \
--project {{ project_id }}
- name: Wait until MCP is provisioned
shell: >
for i in $(seq 12); do
result=$(gcloud container fleet mesh describe --project {{ project_id }} --format json \
| jq -r '.membershipStates | to_entries[] | select(.key | endswith("{{ cluster }}")) | .value.servicemesh.controlPlaneManagement.state')
if [ "$result" = "ACTIVE" ]; then
break
fi
echo "ASM control plane is not ready yet..."
sleep 60
done
- name: Get endpoint IP
shell: >
gcloud container clusters describe "{{ cluster }}" \

View File

@ -224,7 +224,7 @@ module "gke" {
}
}
# tftest modules=8 resources=35
# tftest modules=8 resources=37
```
<!-- TFDOC OPTS files:1 -->

View File

@ -264,6 +264,7 @@ terraform init
terraform apply \
-var bootstrap_user=$(gcloud config list --format 'value(core.account)')
```
> If you see an error related to project name already exists, please make sure the project name is unique or the project was not deleted recently
Once the initial `apply` completes successfully, configure a remote backend using the new GCS bucket, and impersonation on the automation service account for this stage. To do this you can use the generated `providers.tf` file if you have configured output files as described above, or extract its contents from Terraform's output, then migrate state with `terraform init`:

View File

@ -23,9 +23,10 @@ locals {
"roles/browser" = [
"domain:${var.organization.domain}"
]
"roles/logging.admin" = [
module.automation-tf-bootstrap-sa.iam_email
]
"roles/logging.admin" = concat(
[module.automation-tf-bootstrap-sa.iam_email],
local._iam_bootstrap_user
)
"roles/owner" = local._iam_bootstrap_user
"roles/resourcemanager.folderAdmin" = [
module.automation-tf-resman-sa.iam_email

View File

@ -1,4 +1,4 @@
# Api Gateway
# API Gateway
This module allows creating an API with its associated API config and API gateway. It also allows you grant IAM roles on the created resources.
# Examples
@ -15,46 +15,46 @@ module "gateway" {
# ...
EOT
}
# tftest modules=1 resources=4
# tftest modules=1 resources=4 inventory=basic.yaml
```
## Basic example + customer service account
## Use existing service account
```hcl
module "gateway" {
source = "./fabric/modules/api-gateway"
project_id = "my-project"
api_id = "api"
region = "europe-west1"
spec = <<EOT
# The OpenAPI spec contents
# ...
EOT
service_account_email = "sa@my-project.iam.gserviceaccount.com"
iam = {
"roles/apigateway.admin" = ["user:user@example.com"]
}
spec = <<EOT
# The OpenAPI spec contents
# ...
EOT
}
# tftest modules=1 resources=7
# tftest modules=1 resources=7 inventory=existing-sa.yaml
```
## Basic example + service account creation
## Create service account
```hcl
module "gateway" {
source = "./fabric/modules/api-gateway"
project_id = "my-project"
api_id = "api"
region = "europe-west1"
spec = <<EOT
# The OpenAPI spec contents
# ...
EOT
service_account_create = true
iam = {
"roles/apigateway.admin" = ["user:mirene@google.com"]
"roles/apigateway.viewer" = ["user:mirene@google.com"]
}
spec = <<EOT
# The OpenAPI spec contents
# ...
EOT
}
# tftest modules=1 resources=11
# tftest modules=1 resources=11 inventory=create-sa.yaml
```
<!-- BEGIN TFDOC -->

View File

@ -25,14 +25,18 @@ module "apigee" {
}
environments = {
apis-test = {
display_name = "APIs test"
description = "APIs Test"
envgroups = ["test"]
display_name = "APIs test"
description = "APIs Test"
deployment_type = "ARCHIVE"
api_proxy_type = "PROGRAMMABLE"
envgroups = ["test"]
}
apis-prod = {
display_name = "APIs prod"
description = "APIs prod"
envgroups = ["prod"]
display_name = "APIs prod"
description = "APIs prod"
deployment_type = "PROXY"
api_proxy_type = "CONFIGURABLE"
envgroups = ["prod"]
iam = {
"roles/viewer" = ["group:devops@myorg.com"]
}
@ -169,12 +173,12 @@ module "apigee" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [project_id](variables.tf#L75) | Project ID. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L77) | Project ID. | <code>string</code> | ✓ | |
| [endpoint_attachments](variables.tf#L17) | Endpoint attachments. | <code title="map&#40;object&#40;&#123;&#10; region &#61; string&#10; service_attachment &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [envgroups](variables.tf#L26) | Environment groups (NAME => [HOSTNAMES]). | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>null</code> |
| [environments](variables.tf#L32) | Environments. | <code title="map&#40;object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#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; &#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> | | <code>null</code> |
| [instances](variables.tf#L47) | Instances. | <code title="map&#40;object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#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> | | <code>null</code> |
| [organization](variables.tf#L61) | Apigee organization. If set to null the organization must already exist. | <code title="object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#41;&#10; authorized_network &#61; optional&#40;string&#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>null</code> |
| [environments](variables.tf#L32) | Environments. | <code title="map&#40;object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#41;&#10; deployment_type &#61; optional&#40;string&#41;&#10; api_proxy_type &#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; &#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> | | <code>null</code> |
| [instances](variables.tf#L49) | Instances. | <code title="map&#40;object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#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> | | <code>null</code> |
| [organization](variables.tf#L63) | Apigee organization. If set to null the organization must already exist. | <code title="object&#40;&#123;&#10; display_name &#61; optional&#40;string&#41;&#10; description &#61; optional&#40;string, &#34;Terraform-managed&#34;&#41;&#10; authorized_network &#61; optional&#40;string&#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>null</code> |
## Outputs

View File

@ -40,10 +40,12 @@ resource "google_apigee_envgroup" "envgroups" {
}
resource "google_apigee_environment" "environments" {
for_each = local.environments
name = each.key
display_name = each.value.display_name
description = each.value.description
for_each = local.environments
name = each.key
display_name = each.value.display_name
description = each.value.description
deployment_type = each.value.deployment_type
api_proxy_type = each.value.api_proxy_type
dynamic "node_config" {
for_each = try(each.value.node_config, null) != null ? [""] : []
content {

View File

@ -32,8 +32,10 @@ variable "envgroups" {
variable "environments" {
description = "Environments."
type = map(object({
display_name = optional(string)
description = optional(string, "Terraform-managed")
display_name = optional(string)
description = optional(string, "Terraform-managed")
deployment_type = optional(string)
api_proxy_type = optional(string)
node_config = optional(object({
min_node_count = optional(number)
max_node_count = optional(number)

View File

@ -21,7 +21,7 @@ module "private-dns" {
"A myhost" = { ttl = 600, records = ["10.0.0.120"] }
}
}
# tftest modules=1 resources=3
# tftest modules=1 resources=3 inventory=private-zone.yaml
```
### Forwarding Zone
@ -36,7 +36,7 @@ module "private-dns" {
client_networks = [var.vpc.self_link]
forwarders = { "10.0.1.1" = null, "1.2.3.4" = "private" }
}
# tftest modules=1 resources=1
# tftest modules=1 resources=1 inventory=forwarding-zone.yaml
```
### Peering Zone
@ -47,11 +47,12 @@ module "private-dns" {
project_id = "myproject"
type = "peering"
name = "test-example"
domain = "test.example."
domain = "."
description = "Forwarding zone for ."
client_networks = [var.vpc.self_link]
peer_network = var.vpc2.self_link
}
# tftest modules=1 resources=1
# tftest modules=1 resources=1 inventory=peering-zone.yaml
```
### Routing Policies
@ -84,7 +85,7 @@ module "private-dns" {
}
}
}
# tftest modules=1 resources=4
# tftest modules=1 resources=4 inventory=routing-policies.yaml
```
### Reverse Lookup Zone
@ -98,7 +99,23 @@ module "private-dns" {
domain = "0.0.10.in-addr.arpa."
client_networks = [var.vpc.self_link]
}
# tftest modules=1 resources=1
# tftest modules=1 resources=1 inventory=reverse-zone.yaml
```
### Public Zone
```hcl
module "public-dns" {
source = "./fabric/modules/dns"
project_id = "myproject"
type = "public"
name = "example"
domain = "example.com."
recordsets = {
"A myhost" = { ttl = 300, records = ["127.0.0.1"] }
}
}
# tftest modules=1 resources=3 inventory=public-zone.yaml
```
<!-- BEGIN TFDOC -->

View File

@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -8,50 +8,46 @@ module "bucket" {
project_id = "myproject"
prefix = "test"
name = "my-bucket"
versioning = true
iam = {
"roles/storage.admin" = ["group:storage@example.com"]
}
labels = {
cost-center = "devops"
}
}
# tftest modules=1 resources=2
# tftest modules=1 resources=2 inventory=simple.yaml
```
### Example with Cloud KMS
```hcl
module "bucket" {
source = "./fabric/modules/gcs"
project_id = "myproject"
prefix = "test"
name = "my-bucket"
iam = {
"roles/storage.admin" = ["group:storage@example.com"]
}
source = "./fabric/modules/gcs"
project_id = "myproject"
name = "my-bucket"
encryption_key = "my-encryption-key"
}
# tftest modules=1 resources=2
# tftest modules=1 resources=1 inventory=cmek.yaml
```
### Example with retention policy
### Example with retention policy and logging
```hcl
module "bucket" {
source = "./fabric/modules/gcs"
project_id = "myproject"
prefix = "test"
name = "my-bucket"
iam = {
"roles/storage.admin" = ["group:storage@example.com"]
}
retention_policy = {
retention_period = 100
is_locked = true
}
logging_config = {
log_bucket = var.bucket
log_bucket = "log-bucket"
log_object_prefix = null
}
}
# tftest modules=1 resources=2
# tftest modules=1 resources=1 inventory=retention-logging.yaml
```
### Example with lifecycle rule
@ -60,11 +56,7 @@ module "bucket" {
module "bucket" {
source = "./fabric/modules/gcs"
project_id = "myproject"
prefix = "test"
name = "my-bucket"
iam = {
"roles/storage.admin" = ["group:storage@example.com"]
}
lifecycle_rules = {
lr-0 = {
action = {
@ -77,7 +69,7 @@ module "bucket" {
}
}
}
# tftest modules=1 resources=2
# tftest modules=1 resources=1 inventory=lifecycle.yaml
```
### Minimal example with GCS notifications
@ -86,7 +78,6 @@ module "bucket" {
module "bucket-gcs-notification" {
source = "./fabric/modules/gcs"
project_id = "myproject"
prefix = "test"
name = "my-bucket"
notification_config = {
enabled = true
@ -97,7 +88,7 @@ module "bucket-gcs-notification" {
custom_attributes = {}
}
}
# tftest modules=1 resources=4
# tftest modules=1 resources=4 inventory=notification.yaml
```
<!-- BEGIN TFDOC -->

View File

@ -33,7 +33,7 @@ module "cluster-1" {
environment = "dev"
}
}
# tftest modules=1 resources=1
# tftest modules=1 resources=1 inventory=basic.yaml
```
### GKE Cluster with Dataplane V2 enabled
@ -42,7 +42,7 @@ module "cluster-1" {
module "cluster-1" {
source = "./fabric/modules/gke-cluster"
project_id = "myproject"
name = "cluster-1"
name = "cluster-dataplane-v2"
location = "europe-west1-b"
vpc_config = {
network = var.vpc.self_link
@ -68,8 +68,36 @@ module "cluster-1" {
environment = "dev"
}
}
# tftest modules=1 resources=1
# tftest modules=1 resources=1 inventory=dataplane-v2.yaml
```
### Autopilot Cluster
```hcl
module "cluster-autopilot" {
source = "./fabric/modules/gke-cluster"
project_id = "myproject"
name = "cluster-autopilot"
location = "europe-west1-b"
vpc_config = {
network = var.vpc.self_link
subnetwork = var.subnet.self_link
secondary_range_names = {
pods = "pods"
services = "services"
}
master_authorized_ranges = {
internal-vms = "10.0.0.0/8"
}
master_ipv4_cidr_block = "192.168.0.0/28"
}
enable_features = {
autopilot = true
}
}
# tftest modules=1 resources=1 inventory=autopilot.yaml
```
<!-- BEGIN TFDOC -->
## Variables

View File

@ -295,7 +295,7 @@ module "hub" {
]
}
# tftest modules=8 resources=28
# tftest modules=8 resources=30
```
<!-- BEGIN TFDOC -->

View File

@ -70,6 +70,20 @@ resource "google_gke_hub_feature" "default" {
}
}
resource "google_gke_hub_feature_membership" "servicemesh" {
provider = google-beta
for_each = var.features.servicemesh ? var.clusters : {}
project = var.project_id
location = "global"
feature = google_gke_hub_feature.default["servicemesh"].name
membership = google_gke_hub_membership.default[each.key].membership_id
mesh {
management = "MANAGEMENT_AUTOMATIC"
control_plane = "AUTOMATIC"
}
}
resource "google_gke_hub_feature_membership" "default" {
provider = google-beta
for_each = local.cluster_cm_config

View File

@ -16,7 +16,7 @@ module "cluster-1-nodepool-1" {
location = "europe-west1-b"
name = "nodepool-1"
}
# tftest modules=1 resources=1
# tftest modules=1 resources=1 inventory=basic.yaml
```
### Internally managed service account
@ -27,22 +27,11 @@ If you create a new service account, its resource and email (in both plain and I
#### GCE default service account
To use the GCE default service account, you can ignore the variable which is equivalent to `{ create = null, email = null }`.
```hcl
module "cluster-1-nodepool-1" {
source = "./fabric/modules/gke-nodepool"
project_id = "myproject"
cluster_name = "cluster-1"
location = "europe-west1-b"
name = "nodepool-1"
}
# tftest modules=1 resources=1
```
To use the GCE default service account, you can ignore the variable which is equivalent to `{ create = null, email = null }`. This is what the first example of this document does.
#### Externally defined service account
To use an existing service account, pass in just the `email` attribute.
To use an existing service account, pass in just the `email` attribute. If you do this, will most likely want to use the `cloud-platform` scope.
```hcl
module "cluster-1-nodepool-1" {
@ -52,10 +41,11 @@ module "cluster-1-nodepool-1" {
location = "europe-west1-b"
name = "nodepool-1"
service_account = {
email = "foo-bar@myproject.iam.gserviceaccount.com"
email = "foo-bar@myproject.iam.gserviceaccount.com"
oauth_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
}
}
# tftest modules=1 resources=1
# tftest modules=1 resources=1 inventory=external-sa.yaml
```
#### Auto-created service account
@ -70,12 +60,48 @@ module "cluster-1-nodepool-1" {
location = "europe-west1-b"
name = "nodepool-1"
service_account = {
create = true
# optional
email = "spam-eggs"
create = true
email = "spam-eggs" # optional
oauth_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
}
}
# tftest modules=1 resources=2
# tftest modules=1 resources=2 inventory=create-sa.yaml
```
### Node & node pool configuration
```hcl
module "cluster-1-nodepool-1" {
source = "./fabric/modules/gke-nodepool"
project_id = "myproject"
cluster_name = "cluster-1"
location = "europe-west1-b"
name = "nodepool-1"
labels = { environment = "dev" }
service_account = {
create = true
email = "nodepool-1" # optional
oauth_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
}
node_config = {
machine_type = "n2-standard-2"
disk_size_gb = 50
disk_type = "pd-ssd"
ephemeral_ssd_count = 1
gvnic = true
spot = true
}
nodepool_config = {
autoscaling = {
max_node_count = 10
min_node_count = 1
}
management = {
auto_repair = true
auto_upgrade = false
}
}
}
# tftest modules=1 resources=2 inventory=config.yaml
```
<!-- BEGIN TFDOC -->
@ -97,7 +123,7 @@ module "cluster-1-nodepool-1" {
| [nodepool_config](variables.tf#L115) | Nodepool-level configuration. | <code title="object&#40;&#123;&#10; autoscaling &#61; optional&#40;object&#40;&#123;&#10; location_policy &#61; optional&#40;string&#41;&#10; max_node_count &#61; optional&#40;number&#41;&#10; min_node_count &#61; optional&#40;number&#41;&#10; use_total_nodes &#61; optional&#40;bool, false&#41;&#10; &#125;&#41;&#41;&#10; management &#61; optional&#40;object&#40;&#123;&#10; auto_repair &#61; optional&#40;bool&#41;&#10; auto_upgrade &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; upgrade_settings &#61; optional&#40;object&#40;&#123;&#10; max_surge &#61; number&#10; max_unavailable &#61; number&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [pod_range](variables.tf#L137) | Pod secondary range configuration. | <code title="object&#40;&#123;&#10; secondary_pod_range &#61; object&#40;&#123;&#10; cidr &#61; optional&#40;string&#41;&#10; create &#61; optional&#40;bool&#41;&#10; name &#61; string&#10; &#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [reservation_affinity](variables.tf#L154) | Configuration of the desired reservation which instances could take capacity from. | <code title="object&#40;&#123;&#10; consume_reservation_type &#61; string&#10; key &#61; optional&#40;string&#41;&#10; values &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [service_account](variables.tf#L164) | Nodepool service account. If this variable is set to null, the default GCE service account will be used. If set and email is null, a service account will be created. If scopes are null a default will be used. | <code title="object&#40;&#123;&#10; create &#61; optional&#40;bool, false&#41;&#10; email &#61; optional&#40;string, null&#41;&#10; oauth_scopes &#61; optional&#40;list&#40;string&#41;, null&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [service_account](variables.tf#L164) | Nodepool service account. If this variable is set to null, the default GCE service account will be used. If set and email is null, a service account will be created. If scopes are null a default will be used. | <code title="object&#40;&#123;&#10; create &#61; optional&#40;bool, false&#41;&#10; email &#61; optional&#40;string&#41;&#10; oauth_scopes &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [sole_tenant_nodegroup](variables.tf#L175) | Sole tenant node group. | <code>string</code> | | <code>null</code> |
| [tags](variables.tf#L181) | Network tags applied to nodes. | <code>list&#40;string&#41;</code> | | <code>null</code> |
| [taints](variables.tf#L187) | Kubernetes taints applied to all nodes. | <code title="list&#40;object&#40;&#123;&#10; key &#61; string&#10; value &#61; string&#10; effect &#61; string&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |

View File

@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -165,8 +165,8 @@ variable "service_account" {
description = "Nodepool service account. If this variable is set to null, the default GCE service account will be used. If set and email is null, a service account will be created. If scopes are null a default will be used."
type = object({
create = optional(bool, false)
email = optional(string, null)
oauth_scopes = optional(list(string), null)
email = optional(string)
oauth_scopes = optional(list(string))
})
default = {}
nullable = false

View File

@ -438,6 +438,46 @@ module "glb-0" {
# tftest modules=1 resources=5
```
Serverless NEGs don't use the port name but it should be set to `http`. An HTTPS frontend requires the protocol to be set to `HTTPS`, and the port name field will infer this value if omitted so you need to set it explicitly:
```hcl
module "glb-0" {
source = "./fabric/modules/net-glb"
project_id = "myprj"
name = "glb-test-0"
backend_service_configs = {
default = {
backends = [
{ backend = "neg-0" }
]
health_checks = []
port_name = "http"
}
}
# with a single serverless NEG the implied default health check is not needed
health_check_configs = {}
neg_configs = {
neg-0 = {
cloudrun = {
region = "europe-west8"
target_service = {
name = "hello"
}
}
}
}
protocol = "HTTPS"
ssl_certificates = {
managed_configs = {
default = {
domains = ["glb-test-0.example.org"]
}
}
}
}
# tftest modules=1 resources=6 inventory=https-sneg.yaml
```
### URL Map
The module exposes the full URL map resource configuration, with some minor changes to the interface to decrease verbosity, and support for aliasing backend services via keys.

View File

@ -30,7 +30,88 @@ module "vpc" {
}
]
}
# tftest modules=1 resources=3
# tftest modules=1 resources=3 inventory=simple.yaml
```
### Subnet Options
```hcl
module "vpc" {
source = "./fabric/modules/net-vpc"
project_id = "my-project"
name = "my-network"
subnets = [
# simple subnet
{
name = "simple"
region = "europe-west1"
ip_cidr_range = "10.0.0.0/24"
},
# custom description and PGA disabled
{
name = "no-pga"
region = "europe-west1"
ip_cidr_range = "10.0.1.0/24",
description = "Subnet b"
enable_private_access = false
},
# secondary ranges
{
name = "with-secondary-ranges"
region = "europe-west1"
ip_cidr_range = "10.0.2.0/24"
secondary_ip_ranges = {
a = "192.168.0.0/24"
b = "192.168.1.0/24"
}
},
# enable flow logs
{
name = "with-flow-logs"
region = "europe-west1"
ip_cidr_range = "10.0.3.0/24"
flow_logs_config = {
flow_sampling = 0.5
aggregation_interval = "INTERVAL_10_MIN"
}
}
]
}
# tftest modules=1 resources=5 inventory=subnet-options.yaml
```
### Subnet IAM
```hcl
module "vpc" {
source = "./fabric/modules/net-vpc"
project_id = "my-project"
name = "my-network"
subnets = [
{
name = "subnet-1"
region = "europe-west1"
ip_cidr_range = "10.0.1.0/24"
},
{
name = "subnet-2"
region = "europe-west1"
ip_cidr_range = "10.0.1.0/24"
}
]
subnet_iam = {
"europe-west1/subnet-1" = {
"roles/compute.networkUser" = [
"user:user1@example.com", "group:group1@example.com"
]
}
"europe-west1/subnet-2" = {
"roles/compute.networkUser" = [
"user:user2@example.com", "group:group2@example.com"
]
}
}
}
# tftest modules=1 resources=5 inventory=subnet-iam.yaml
```
### Peering
@ -65,7 +146,7 @@ module "vpc-spoke-1" {
import_routes = true
}
}
# tftest modules=2 resources=6
# tftest modules=2 resources=6 inventory=peering.yaml
```
### Shared VPC
@ -116,7 +197,7 @@ module "vpc-host" {
}
}
}
# tftest modules=1 resources=7
# tftest modules=1 resources=7 inventory=shared-vpc.yaml
```
### Private Service Networking
@ -137,7 +218,7 @@ module "vpc" {
ranges = { myrange = "10.0.1.0/24" }
}
}
# tftest modules=1 resources=5
# tftest modules=1 resources=5 inventory=psc.yaml
```
### Private Service Networking with peering routes
@ -162,7 +243,7 @@ module "vpc" {
import_routes = true
}
}
# tftest modules=1 resources=5
# tftest modules=1 resources=5 inventory=psc-routes.yaml
```
### Subnets for Private Service Connect, Proxy-only subnets
@ -194,7 +275,7 @@ module "vpc" {
}
]
}
# tftest modules=1 resources=3
# tftest modules=1 resources=3 inventory=proxy-only-subnets.yaml
```
### DNS Policies
@ -219,7 +300,7 @@ module "vpc" {
}
]
}
# tftest modules=1 resources=3
# tftest modules=1 resources=3 inventory=dns-policies.yaml
```
### Subnet Factory
@ -233,11 +314,17 @@ module "vpc" {
name = "my-network"
data_folder = "config/subnets"
}
# tftest modules=1 resources=2 files=subnets
# tftest modules=1 resources=3 files=subnet-simple,subnet-detailed inventory=factory.yaml
```
```yaml
# tftest-file id=subnets path=config/subnets/subnet-name.yaml
# tftest-file id=subnet-simple path=config/subnets/subnet-simple.yaml
region: europe-west4
ip_cidr_range: 10.0.1.0/24
```
```yaml
# tftest-file id=subnet-detailed path=config/subnets/subnet-detailed.yaml
region: europe-west1
description: Sample description
ip_cidr_range: 10.0.0.0/24
@ -254,7 +341,45 @@ flow_logs: # enable, set to empty map to use defaults
metadata: "INCLUDE_ALL_METADATA"
filter_expression: null
```
<!-- BEGIN TFDOC -->
### Custom Routes
VPC routes can be configured through the `routes` variable.
```hcl
locals {
route_types = {
gateway = "global/gateways/default-internet-gateway"
instance = "zones/europe-west1-b/test"
ip = "192.168.0.128"
ilb = "regions/europe-west1/forwardingRules/test"
vpn_tunnel = "regions/europe-west1/vpnTunnels/foo"
}
}
module "vpc" {
source = "./fabric/modules/net-vpc"
for_each = local.route_types
project_id = "my-project"
name = "my-network-with-route-${replace(each.key, "_", "-")}"
routes = {
next-hop = {
dest_range = "192.168.128.0/24"
tags = null
next_hop_type = each.key
next_hop = each.value
}
gateway = {
dest_range = "0.0.0.0/0",
priority = 100
tags = ["tag-a"]
next_hop_type = "gateway",
next_hop = "global/gateways/default-internet-gateway"
}
}
}
# tftest modules=5 resources=15 inventory=routes.yaml
```
## Variables

View File

@ -1,5 +1,5 @@
/**
* Copyright 2022 Google LLC
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -109,7 +109,7 @@ resource "google_dns_policy" "default" {
)
iterator = ns
content {
ipv4_address = ns.key
ipv4_address = ns.value
forwarding_path = "private"
}
}
@ -121,7 +121,7 @@ resource "google_dns_policy" "default" {
)
iterator = ns
content {
ipv4_address = ns.key
ipv4_address = ns.value
}
}
}

View File

@ -75,7 +75,8 @@ locals {
"gkehub.googleapis.com",
"pubsub.googleapis.com",
"secretmanager.googleapis.com",
"sqladmin.googleapis.com"
"sqladmin.googleapis.com",
"cloudbuild.googleapis.com",
]
service_accounts_cmek_service_keys = distinct(flatten([
for s in keys(var.service_encryption_key_ids) : [

View File

@ -14,4 +14,4 @@
counts:
modules: 9
resources: 60
resources: 61

View File

@ -13,5 +13,5 @@
# limitations under the License.
counts:
modules: 9
resources: 37
modules: 17
resources: 59

View File

@ -16,4 +16,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner()
assert len(modules) == 6
assert len(resources) == 18
assert len(resources) == 19

View File

@ -16,4 +16,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner()
assert len(modules) == 7
assert len(resources) == 29
assert len(resources) == 30

View File

@ -16,4 +16,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner()
assert len(modules) == 10
assert len(resources) == 31
assert len(resources) == 32

View File

@ -22,4 +22,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner(FIXTURES_DIR)
assert len(modules) == 38
assert len(resources) == 285
assert len(resources) == 286

View File

@ -16,4 +16,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner()
assert len(modules) == 13
assert len(resources) == 43
assert len(resources) == 44

View File

@ -16,4 +16,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner()
assert len(modules) == 12
assert len(resources) == 53
assert len(resources) == 55

View File

@ -16,4 +16,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner()
assert len(modules) == 10
assert len(resources) == 38
assert len(resources) == 39

View File

@ -16,4 +16,4 @@ def test_resources(e2e_plan_runner):
"Test that plan works and the numbers of resources is as expected."
modules, resources = e2e_plan_runner()
assert len(modules) == 7
assert len(resources) == 31
assert len(resources) == 32

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -21,7 +21,7 @@ import marko
FABRIC_ROOT = Path(__file__).parents[2]
FILE_TEST_RE = re.compile(r'# tftest-file +id=(\w+) +path=([\S]+)')
FILE_TEST_RE = re.compile(r'# tftest-file +id=([\w_.-]+) +path=([\S]+)')
Example = collections.namedtuple('Example', 'name code module files')
File = collections.namedtuple('File', 'path content')

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -18,7 +18,7 @@ from pathlib import Path
BASE_PATH = Path(__file__).parent
COUNT_TEST_RE = re.compile(r'# tftest +modules=(\d+) +resources=(\d+)' +
r'(?: +files=([\w,-.]+))?' +
r'(?: +files=([\w,_-]+))?' +
r'(?: +inventory=([\w\-.]+))?')

View File

@ -24,7 +24,7 @@ counts:
google_project_iam_binding: 9
google_project_iam_member: 1
google_project_service: 29
google_project_service_identity: 2
google_project_service_identity: 3
google_service_account: 3
google_service_account_iam_binding: 3
google_storage_bucket: 4

View File

@ -0,0 +1,42 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.gateway.google_api_gateway_api.api:
api_id: api
display_name: api
project: my-project
module.gateway.google_api_gateway_api_config.api_config:
api: api
gateway_config: []
grpc_services: []
labels: null
managed_service_configs: []
project: my-project
module.gateway.google_api_gateway_gateway.gateway:
display_name: gw-api
gateway_id: gw-api
labels: null
project: my-project
region: europe-west1
module.gateway.google_project_service.service:
disable_dependent_services: true
disable_on_destroy: true
project: my-project
counts:
google_api_gateway_api: 1
google_api_gateway_api_config: 1
google_api_gateway_gateway: 1
google_project_service: 1

View File

@ -0,0 +1,90 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.gateway.google_api_gateway_api.api:
api_id: api
display_name: api
labels: null
project: my-project
module.gateway.google_api_gateway_api_config.api_config:
api: api
grpc_services: []
labels: null
managed_service_configs: []
project: my-project
module.gateway.google_api_gateway_api_config_iam_binding.api_config_iam_bindings["roles/apigateway.admin"]:
api: api
condition: []
members:
- user:mirene@google.com
project: my-project
role: roles/apigateway.admin
module.gateway.google_api_gateway_api_config_iam_binding.api_config_iam_bindings["roles/apigateway.viewer"]:
api: api
condition: []
members:
- user:mirene@google.com
project: my-project
role: roles/apigateway.viewer
module.gateway.google_api_gateway_api_iam_binding.api_iam_bindings["roles/apigateway.admin"]:
api: api
condition: []
members:
- user:mirene@google.com
project: my-project
role: roles/apigateway.admin
module.gateway.google_api_gateway_api_iam_binding.api_iam_bindings["roles/apigateway.viewer"]:
api: api
condition: []
members:
- user:mirene@google.com
project: my-project
role: roles/apigateway.viewer
module.gateway.google_api_gateway_gateway.gateway:
display_name: gw-api
gateway_id: gw-api
labels: null
project: my-project
region: europe-west1
module.gateway.google_api_gateway_gateway_iam_binding.gateway_iam_bindings["roles/apigateway.admin"]:
condition: []
gateway: gw-api
members:
- user:mirene@google.com
project: my-project
region: europe-west1
role: roles/apigateway.admin
module.gateway.google_api_gateway_gateway_iam_binding.gateway_iam_bindings["roles/apigateway.viewer"]:
condition: []
gateway: gw-api
members:
- user:mirene@google.com
project: my-project
region: europe-west1
role: roles/apigateway.viewer
module.gateway.google_project_service.service: {}
module.gateway.google_service_account.service_account[0]:
account_id: sa-api-cfg-api
project: my-project
counts:
google_api_gateway_api: 1
google_api_gateway_api_config: 1
google_api_gateway_api_config_iam_binding: 2
google_api_gateway_api_iam_binding: 2
google_api_gateway_gateway: 1
google_api_gateway_gateway_iam_binding: 2
google_project_service: 1
google_service_account: 1

View File

@ -0,0 +1,71 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.gateway.google_api_gateway_api.api:
api_id: api
display_name: api
labels: null
project: my-project
module.gateway.google_api_gateway_api_config.api_config:
api: api
gateway_config:
- backend_config:
- google_service_account: sa@my-project.iam.gserviceaccount.com
grpc_services: []
labels: null
managed_service_configs: []
project: my-project
module.gateway.google_api_gateway_api_config_iam_binding.api_config_iam_bindings["roles/apigateway.admin"]:
api: api
api_config: api-cfg-api-8656c6040d6d9ba18a8b9b5f3955c223
condition: []
members:
- user:user@example.com
project: my-project
role: roles/apigateway.admin
module.gateway.google_api_gateway_api_iam_binding.api_iam_bindings["roles/apigateway.admin"]:
api: api
condition: []
members:
- user:user@example.com
project: my-project
role: roles/apigateway.admin
module.gateway.google_api_gateway_gateway.gateway:
display_name: gw-api
gateway_id: gw-api
labels: null
project: my-project
region: europe-west1
module.gateway.google_api_gateway_gateway_iam_binding.gateway_iam_bindings["roles/apigateway.admin"]:
condition: []
gateway: gw-api
members:
- user:user@example.com
project: my-project
region: europe-west1
role: roles/apigateway.admin
module.gateway.google_project_service.service:
disable_dependent_services: true
disable_on_destroy: true
project: my-project
counts:
google_api_gateway_api: 1
google_api_gateway_api_config: 1
google_api_gateway_api_config_iam_binding: 1
google_api_gateway_api_iam_binding: 1
google_api_gateway_gateway: 1
google_api_gateway_gateway_iam_binding: 1
google_project_service: 1

View File

@ -1,26 +0,0 @@
/**
* 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 "gateway" {
source = "../../../../modules/api-gateway"
api_id = var.api_id
project_id = var.project_id
labels = var.labels
iam = var.iam
region = var.region
spec = var.spec
service_account_create = true
}

View File

@ -1,55 +0,0 @@
/**
* 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 "api_id" {
type = string
default = "my-api"
}
variable "iam" {
type = map(list(string))
default = null
}
variable "labels" {
type = map(string)
default = null
}
variable "project_id" {
type = string
default = "my-project"
}
variable "region" {
type = string
default = "europe-west1"
}
variable "service_account_create" {
type = bool
default = true
}
variable "service_account_email" {
type = string
default = null
}
variable "spec" {
type = string
default = "Spec contents"
}

View File

@ -0,0 +1,13 @@
project_id = "my-project"
environments = {
apis-test = {
display_name = "APIs test"
description = "APIs Test"
api_proxy_type = "PROGRAMMABLE"
envgroups = ["test"]
node_config = {
min_node_count = 2
max_node_count = 5
}
}
}

View File

@ -0,0 +1,13 @@
project_id = "my-project"
environments = {
apis-test = {
display_name = "APIs test"
description = "APIs Test"
deployment_type = "ARCHIVE"
envgroups = ["test"]
node_config = {
min_node_count = 2
max_node_count = 5
}
}
}

View File

@ -32,8 +32,10 @@ variable "envgroups" {
variable "environments" {
description = "Environments."
type = map(object({
display_name = optional(string)
description = optional(string, "Terraform-managed")
display_name = optional(string)
description = optional(string, "Terraform-managed")
deployment_type = optional(string)
api_proxy_type = optional(string)
node_config = optional(object({
min_node_count = optional(number)
max_node_count = optional(number)

View File

@ -54,6 +54,18 @@ def test_env_only(plan_runner):
'google_apigee_envgroup_attachment.envgroup_attachments': 1,
}
def test_env_only_with_deployment_type(plan_runner):
"Test that creates an environment in an existing environment group, with deployment_type set."
_, resources = plan_runner(tf_var_file='test.env_only_with_deployment_type.tfvars')
assert [r['values'].get('deployment_type') for r in resources
] == [None, 'ARCHIVE']
def test_env_only_with_api_proxy_type(plan_runner):
"Test that creates an environment in an existing environment group, with api_proxy_type set."
_, resources = plan_runner(tf_var_file='test.env_only_with_api_proxy_type.tfvars')
assert [r['values'].get('api_proxy_type') for r in resources
] == [None, 'PROGRAMMABLE']
def test_instance_only(plan_runner):
"Test that creates only an instance."
_, resources = plan_runner(tf_var_file='test.instance_only.tfvars')

View File

@ -0,0 +1,34 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.private-dns.google_dns_managed_zone.non-public[0]:
dns_name: test.example.
forwarding_config:
- target_name_servers:
- forwarding_path: ''
ipv4_address: 10.0.1.1
- forwarding_path: private
ipv4_address: 1.2.3.4
name: test-example
private_visibility_config:
- gke_clusters: []
networks:
- network_url: projects/xxx/global/networks/aaa
project: myproject
visibility: private
counts:
google_dns_managed_zone: 1

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -13,24 +13,22 @@
# limitations under the License.
values:
google_compute_network.network[0]:
auto_create_subnetworks: false
delete_default_routes_on_create: false
description: Terraform-managed.
name: test
project: test-project
routing_mode: GLOBAL
module.private-dns.google_dns_managed_zone.non-public[0]:
description: Forwarding zone for .
dns_name: .
forwarding_config: []
name: test-example
peering_config:
- target_network:
- network_url: projects/xxx/global/networks/ccc
private_visibility_config:
- gke_clusters: []
networks:
- network_url: projects/xxx/global/networks/aaa
project: myproject
visibility: private
counts:
google_compute_network: 1
google_dns_managed_zone: 1
outputs:
bindings: {}
project_id: test-project
subnet_ips: {}
subnet_regions: {}
subnet_secondary_ranges: {}
subnet_self_links: {}
subnets: {}
subnets_proxy_only: {}
subnets_psc: {}
outputs: {}

View File

@ -0,0 +1,50 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.private-dns.google_dns_managed_zone.non-public[0]:
description: Terraform managed.
dns_name: test.example.
force_destroy: false
forwarding_config: []
name: test-example
peering_config: []
private_visibility_config:
- gke_clusters: []
networks:
- network_url: projects/xxx/global/networks/aaa
project: myproject
visibility: private
module.private-dns.google_dns_record_set.cloud-static-records["A localhost"]:
managed_zone: test-example
name: localhost.test.example.
project: myproject
routing_policy: []
rrdatas:
- 127.0.0.1
ttl: 300
type: A
module.private-dns.google_dns_record_set.cloud-static-records["A myhost"]:
managed_zone: test-example
name: myhost.test.example.
project: myproject
routing_policy: []
rrdatas:
- 10.0.0.120
ttl: 600
type: A
counts:
google_dns_managed_zone: 1
google_dns_record_set: 2

View File

@ -0,0 +1,38 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.public-dns.google_dns_managed_zone.public[0]:
dns_name: example.com.
name: example
project: myproject
visibility: public
module.public-dns.google_dns_record_set.cloud-static-records["A myhost"]:
managed_zone: example
name: myhost.example.com.
project: myproject
routing_policy: []
rrdatas:
- 127.0.0.1
ttl: 300
type: A
counts:
google_dns_keys: 1
google_dns_managed_zone: 1
google_dns_record_set: 1
modules: 1
resources: 3
outputs: {}

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -12,12 +12,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
region: europe-west1
description: Sample description
ip_cidr_range: 10.128.0.0/24
enable_private_access: false
iam_users: ["foobar@example.com"]
iam_groups: ["lorem@example.com"]
iam_service_accounts: ["foobar@project-id.iam.gserviceaccount.com"]
secondary_ip_ranges:
secondary-range-a: 192.168.128.0/24
values:
module.private-dns.google_dns_managed_zone.non-public[0]:
description: Terraform managed.
dns_name: 0.0.10.in-addr.arpa.
name: test-example
project: myproject
reverse_lookup: true
visibility: private
counts:
google_dns_managed_zone: 1
outputs: {}

View File

@ -0,0 +1,80 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.private-dns.google_dns_managed_zone.non-public[0]:
dns_name: test.example.
name: test-example
project: myproject
module.private-dns.google_dns_record_set.cloud-geo-records["A geo"]:
managed_zone: test-example
name: geo.test.example.
project: myproject
routing_policy:
- enable_geo_fencing: null
geo:
- health_checked_targets: []
location: europe-west1
rrdatas:
- 10.0.0.1
- health_checked_targets: []
location: europe-west2
rrdatas:
- 10.0.0.2
- health_checked_targets: []
location: europe-west3
rrdatas:
- 10.0.0.3
primary_backup: []
wrr: []
rrdatas: null
ttl: 300
type: A
module.private-dns.google_dns_record_set.cloud-static-records["A regular"]:
managed_zone: test-example
name: regular.test.example.
project: myproject
routing_policy: []
rrdatas:
- 10.20.0.1
ttl: 300
type: A
module.private-dns.google_dns_record_set.cloud-wrr-records["A wrr"]:
managed_zone: test-example
name: wrr.test.example.
project: myproject
routing_policy:
- enable_geo_fencing: null
geo: []
primary_backup: []
wrr:
- health_checked_targets: []
rrdatas:
- 10.10.0.1
weight: 0.6
- health_checked_targets: []
rrdatas:
- 10.10.0.2
weight: 0.2
- health_checked_targets: []
rrdatas:
- 10.10.0.3
weight: 0.2
rrdatas: null
ttl: 600
type: A
counts:
google_dns_managed_zone: 1
google_dns_record_set: 3

View File

@ -1,62 +0,0 @@
/**
* 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 "client_networks" {
type = list(string)
default = [
"https://www.googleapis.com/compute/v1/projects/my-project/global/networks/default"
]
}
variable "forwarders" {
type = map(string)
default = {}
}
variable "peer_network" {
type = string
default = null
}
variable "recordsets" {
type = any
default = {
"A localhost" = { ttl = 300, records = ["127.0.0.1"] }
"A local-host.test.example." = { ttl = 300, records = ["127.0.0.2"] }
"CNAME *" = { ttl = 300, records = ["localhost.example.org."] }
"A " = { ttl = 300, records = ["127.0.0.3"] }
"A geo" = {
geo_routing = [
{ location = "europe-west1", records = ["127.0.0.4"] },
{ location = "europe-west2", records = ["127.0.0.5"] },
{ location = "europe-west3", records = ["127.0.0.6"] }
]
}
"A wrr" = {
ttl = 600
wrr_routing = [
{ weight = 0.6, records = ["127.0.0.7"] },
{ weight = 0.2, records = ["127.0.0.8"] },
{ weight = 0.2, records = ["127.0.0.9"] }
]
}
}
}
variable "type" {
type = string
default = "private"
}

View File

@ -0,0 +1,5 @@
type = "private"
domain = "test.example."
name = "test"
project_id = "my-project"
client_networks = []

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -13,18 +13,13 @@
# limitations under the License.
values:
google_storage_bucket.bucket:
google_dns_managed_zone.non-public[0]:
dns_name: test.example.
name: test
google_storage_bucket_iam_binding.bindings["roles/storage.admin"]:
bucket: test
condition: []
members:
- user:a@example.org
role: roles/storage.admin
private_visibility_config: []
visibility: private
counts:
google_storage_bucket: 1
google_storage_bucket_iam_binding: 1
google_dns_managed_zone: 1
modules: 0
resources: 2
resources: 1

View File

@ -0,0 +1,4 @@
type = "forwarding"
domain = "test.example."
name = "test"
project_id = "my-project"

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -12,6 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
region: europe-west4
description: Sample description
ip_cidr_range: 10.129.0.0/24
values:
google_dns_managed_zone.non-public[0]:
forwarding_config: []
counts:
google_dns_managed_zone: 1

View File

@ -1,138 +0,0 @@
# 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.
def test_private(plan_runner):
"Test private zone with three recordsets."
_, resources = plan_runner()
assert len(resources) == 7
assert set(r['type'] for r in resources) == {
'google_dns_record_set', 'google_dns_managed_zone'
}
for r in resources:
if r['type'] != 'google_dns_managed_zone':
continue
assert r['values']['visibility'] == 'private'
assert len(r['values']['private_visibility_config']) == 1
def test_private_recordsets(plan_runner):
"Test recordsets in private zone."
_, resources = plan_runner()
recordsets = [
r['values'] for r in resources if r['type'] == 'google_dns_record_set'
]
assert set(r['name'] for r in recordsets) == {
'localhost.test.example.', 'local-host.test.example.', '*.test.example.',
"test.example.", "geo.test.example.", "wrr.test.example."
}
for r in recordsets:
if r['name'] not in ['wrr.test.example.', 'geo.test.example.']:
assert r['routing_policy'] == []
assert r['rrdatas'] != []
def test_routing_policies(plan_runner):
"Test recordsets with routing policies."
_, resources = plan_runner()
recordsets = [
r['values'] for r in resources if r['type'] == 'google_dns_record_set'
]
geo_zone = [
r['values'] for r in resources if r['address'] ==
'module.test.google_dns_record_set.cloud-geo-records["A geo"]'
][0]
assert geo_zone['name'] == 'geo.test.example.'
assert geo_zone['routing_policy'][0]['wrr'] == []
geo_policy = geo_zone['routing_policy'][0]['geo']
assert geo_policy[0]['location'] == 'europe-west1'
assert geo_policy[0]['rrdatas'] == ['127.0.0.4']
assert geo_policy[1]['location'] == 'europe-west2'
assert geo_policy[1]['rrdatas'] == ['127.0.0.5']
assert geo_policy[2]['location'] == 'europe-west3'
assert geo_policy[2]['rrdatas'] == ['127.0.0.6']
wrr_zone = [
r['values'] for r in resources if r['address'] ==
'module.test.google_dns_record_set.cloud-wrr-records["A wrr"]'
][0]
assert wrr_zone['name'] == 'wrr.test.example.'
wrr_policy = wrr_zone['routing_policy'][0]['wrr']
assert wrr_policy[0]['weight'] == 0.6
assert wrr_policy[0]['rrdatas'] == ['127.0.0.7']
assert wrr_policy[1]['weight'] == 0.2
assert wrr_policy[1]['rrdatas'] == ['127.0.0.8']
assert wrr_policy[2]['weight'] == 0.2
assert wrr_policy[2]['rrdatas'] == ['127.0.0.9']
assert wrr_zone['routing_policy'][0]['geo'] == []
def test_private_no_networks(plan_runner):
"Test private zone not exposed to any network."
_, resources = plan_runner(client_networks='[]')
for r in resources:
if r['type'] != 'google_dns_managed_zone':
continue
assert r['values']['visibility'] == 'private'
assert len(r['values']['private_visibility_config']) == 0
def test_forwarding_recordsets_null_forwarders(plan_runner):
"Test forwarding zone with wrong set of attributes does not break."
_, resources = plan_runner(type='forwarding')
assert len(resources) == 1
resource = resources[0]
assert resource['type'] == 'google_dns_managed_zone'
assert resource['values']['forwarding_config'] == []
def test_forwarding(plan_runner):
"Test forwarding zone with single forwarder."
_, resources = plan_runner(type='forwarding', recordsets='null',
forwarders='{ "1.2.3.4" = null }')
assert len(resources) == 1
resource = resources[0]
assert resource['type'] == 'google_dns_managed_zone'
assert resource['values']['forwarding_config'] == [{
'target_name_servers': [{
'forwarding_path': '',
'ipv4_address': '1.2.3.4'
}]
}]
def test_peering(plan_runner):
"Test peering zone."
_, resources = plan_runner(type='peering', recordsets='null',
peer_network='dummy-vpc-self-link')
assert len(resources) == 1
resource = resources[0]
assert resource['type'] == 'google_dns_managed_zone'
assert resource['values']['peering_config'] == [{
'target_network': [{
'network_url': 'dummy-vpc-self-link'
}]
}]
def test_public(plan_runner):
"Test public zone with two recordsets."
_, resources = plan_runner(type='public')
for r in resources:
if r['type'] != 'google_dns_managed_zone':
continue
assert r['values']['visibility'] == 'public'
assert r['values']['private_visibility_config'] == []

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -12,9 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
module: modules/gcs
common_tfvars:
- common.tfvars
module: modules/dns
tests:
prefix:
iam:
no_clients:
null_forwarders:

View File

@ -1,13 +0,0 @@
force_destroy = true
labels = { environment = "test" }
logging_config = {
log_bucket = "foo"
}
name = "test"
project_id = "test-project"
retention_policy = {
retention_period = 5
is_locked = false
}
storage_class = "MULTI_REGIONAL"
versioning = true

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -12,8 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.bucket.google_storage_bucket.bucket:
encryption:
- default_kms_key_name: my-encryption-key
name: my-bucket
project: myproject
def test_resource_count(plan_runner):
"Test number of resources created."
_, resources = plan_runner()
assert len(resources) == 5
counts:
google_storage_bucket: 1

View File

@ -1,4 +1,4 @@
# Copyright 2022 Google LLC
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -13,32 +13,26 @@
# limitations under the License.
values:
google_storage_bucket.bucket:
force_destroy: true
labels:
environment: test
location: EU
logging:
- log_bucket: foo
name: foo-test
project: test-project
retention_policy:
- is_locked: false
retention_period: 5
storage_class: MULTI_REGIONAL
uniform_bucket_level_access: true
versioning:
- enabled: true
module.bucket.google_storage_bucket.bucket:
lifecycle_rule:
- action:
- storage_class: STANDARD
type: SetStorageClass
condition:
- age: 30
created_before: ''
custom_time_before: ''
days_since_custom_time: null
days_since_noncurrent_time: null
matches_prefix: []
matches_storage_class: []
matches_suffix: []
noncurrent_time_before: ''
num_newer_versions: null
name: my-bucket
project: myproject
counts:
google_storage_bucket: 1
modules: 0
resources: 1
outputs:
bucket: __missing__
id: foo-test
name: foo-test
notification: null
topic: null
url: __missing__
outputs: {}

View File

@ -0,0 +1,31 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.bucket-gcs-notification.google_pubsub_topic.topic[0]: {}
module.bucket-gcs-notification.google_pubsub_topic_iam_binding.binding[0]: {}
module.bucket-gcs-notification.google_storage_bucket.bucket:
name: my-bucket
project: myproject
module.bucket-gcs-notification.google_storage_notification.notification[0]:
bucket: my-bucket
event_types:
- OBJECT_FINALIZE
payload_format: JSON_API_V1
counts:
google_pubsub_topic: 1
google_pubsub_topic_iam_binding: 1
google_storage_bucket: 1
google_storage_notification: 1

View File

@ -0,0 +1,26 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.bucket.google_storage_bucket.bucket:
logging:
- log_bucket: log-bucket
name: my-bucket
project: myproject
retention_policy:
- is_locked: true
retention_period: 100
counts:
google_storage_bucket: 1

View File

@ -0,0 +1,46 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.bucket.google_storage_bucket.bucket:
autoclass: []
cors: []
custom_placement_config: []
default_event_based_hold: null
encryption: []
force_destroy: false
labels:
cost-center: devops
lifecycle_rule: []
location: EU
logging: []
name: test-my-bucket
project: myproject
requester_pays: null
retention_policy: []
storage_class: MULTI_REGIONAL
timeouts: null
uniform_bucket_level_access: true
versioning:
- enabled: true
module.bucket.google_storage_bucket_iam_binding.bindings["roles/storage.admin"]:
bucket: test-my-bucket
condition: []
members:
- group:storage@example.com
role: roles/storage.admin
counts:
google_storage_bucket: 1
google_storage_bucket_iam_binding: 1

View File

@ -1,3 +0,0 @@
iam = {
"roles/storage.admin" = ["user:a@example.org"]
}

View File

@ -1 +0,0 @@
prefix = "foo"

View File

@ -0,0 +1,32 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.cluster-autopilot.google_container_cluster.cluster:
enable_autopilot: true
ip_allocation_policy:
- cluster_secondary_range_name: pods
services_secondary_range_name: services
location: europe-west1-b
master_authorized_networks_config:
- cidr_blocks:
- cidr_block: 10.0.0.0/8
display_name: internal-vms
name: cluster-autopilot
network: projects/xxx/global/networks/aaa
project: myproject
subnetwork: subnet_self_link
counts:
google_container_cluster: 1

View File

@ -0,0 +1,42 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.cluster-1.google_container_cluster.cluster:
default_max_pods_per_node: 32
ip_allocation_policy:
- cluster_secondary_range_name: pods
services_secondary_range_name: services
location: europe-west1-b
master_authorized_networks_config:
- cidr_blocks:
- cidr_block: 10.0.0.0/8
display_name: internal-vms
name: cluster-1
network: projects/xxx/global/networks/aaa
private_cluster_config:
- enable_private_endpoint: true
enable_private_nodes: true
master_global_access_config:
- enabled: false
master_ipv4_cidr_block: 192.168.0.0/28
private_endpoint_subnetwork: null
project: myproject
remove_default_node_pool: true
resource_labels:
environment: dev
subnetwork: subnet_self_link
counts:
google_container_cluster: 1

View File

@ -0,0 +1,45 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.cluster-1.google_container_cluster.cluster:
datapath_provider: ADVANCED_DATAPATH
ip_allocation_policy:
- cluster_secondary_range_name: pods
services_secondary_range_name: services
location: europe-west1-b
master_authorized_networks_config:
- cidr_blocks:
- cidr_block: 10.0.0.0/8
display_name: internal-vms
min_master_version: null
name: cluster-dataplane-v2
network: projects/xxx/global/networks/aaa
private_cluster_config:
- enable_private_endpoint: true
enable_private_nodes: true
master_global_access_config:
- enabled: false
master_ipv4_cidr_block: 192.168.0.0/28
private_endpoint_subnetwork: null
project: myproject
remove_default_node_pool: true
resource_labels:
environment: dev
subnetwork: subnet_self_link
workload_identity_config:
- workload_pool: myproject.svc.id.goog
counts:
google_container_cluster: 1

View File

@ -1,43 +0,0 @@
/**
* 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 "enable_addons" {
type = any
default = {
horizontal_pod_autoscaling = true
http_load_balancing = true
}
}
variable "enable_features" {
type = any
default = {
workload_identity = true
}
}
variable "monitoring_config" {
type = any
default = {
managed_prometheus = true
}
}
variable "tags" {
description = "Network tags applied to nodes."
type = list(string)
default = null
}

View File

@ -1,38 +0,0 @@
# 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.
def test_standard(plan_runner):
"Test resources created with variable defaults."
_, resources = plan_runner()
assert len(resources) == 1
cluster_config = resources[0]['values']
assert cluster_config['name'] == "cluster-1"
assert cluster_config['network'] == "mynetwork"
assert cluster_config['subnetwork'] == "mysubnet"
assert cluster_config['enable_autopilot'] is None
# assert 'service_account' not in node_config
def test_autopilot(plan_runner):
"Test resources created with variable defaults."
_, resources = plan_runner(enable_features='{ autopilot=true }')
assert len(resources) == 1
cluster_config = resources[0]['values']
assert cluster_config['name'] == "cluster-1"
assert cluster_config['network'] == "mynetwork"
assert cluster_config['subnetwork'] == "mysubnet"
assert cluster_config['enable_autopilot'] == True
# assert 'service_account' not in node_config

View File

@ -31,7 +31,7 @@ variable "features" {
configmanagement = true
identityservice = false
multiclusteringress = null
servicemesh = false
servicemesh = true
multiclusterservicediscovery = false
}
}

View File

@ -23,11 +23,14 @@ def resources(plan_runner):
def test_resource_count(resources):
"Test number of resources created."
assert len(resources) == 5
assert len(resources) == 8
assert sorted(r['address'] for r in resources) == [
'module.hub.google_gke_hub_feature.default["configmanagement"]',
'module.hub.google_gke_hub_feature.default["servicemesh"]',
'module.hub.google_gke_hub_feature_membership.default["cluster-1"]',
'module.hub.google_gke_hub_feature_membership.default["cluster-2"]',
'module.hub.google_gke_hub_feature_membership.servicemesh["cluster-1"]',
'module.hub.google_gke_hub_feature_membership.servicemesh["cluster-2"]',
'module.hub.google_gke_hub_membership.default["cluster-1"]',
'module.hub.google_gke_hub_membership.default["cluster-2"]'
]

View File

@ -0,0 +1,23 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.cluster-1-nodepool-1.google_container_node_pool.nodepool:
cluster: cluster-1
location: europe-west1-b
name: nodepool-1
project: myproject
counts:
google_container_node_pool: 1

View File

@ -0,0 +1,60 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.cluster-1-nodepool-1.google_container_node_pool.nodepool:
autoscaling:
- location_policy: null
max_node_count: 10
min_node_count: 1
total_max_node_count: null
total_min_node_count: null
cluster: cluster-1
initial_node_count: 1
location: europe-west1-b
management:
- auto_repair: true
auto_upgrade: false
name: nodepool-1
node_config:
- boot_disk_kms_key: null
disk_size_gb: 50
disk_type: pd-ssd
ephemeral_storage_config:
- local_ssd_count: 1
gcfs_config: []
gvnic: []
kubelet_config: []
labels:
environment: dev
linux_node_config: []
logging_variant: DEFAULT
machine_type: n2-standard-2
node_group: null
oauth_scopes:
- https://www.googleapis.com/auth/cloud-platform
preemptible: false
reservation_affinity: []
resource_labels: null
sandbox_config: []
spot: true
tags: null
taint: []
placement_policy: []
project: myproject
module.cluster-1-nodepool-1.google_service_account.service_account[0]: {}
counts:
google_container_node_pool: 1
google_service_account: 1

View File

@ -0,0 +1,52 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.cluster-1-nodepool-1.google_container_node_pool.nodepool:
cluster: cluster-1
location: europe-west1-b
name: nodepool-1
node_config:
- boot_disk_kms_key: null
disk_type: pd-balanced
ephemeral_storage_config: []
gcfs_config: []
gvnic: []
kubelet_config: []
linux_node_config: []
logging_variant: DEFAULT
node_group: null
oauth_scopes:
- https://www.googleapis.com/auth/cloud-platform
preemptible: false
reservation_affinity: []
resource_labels: null
sandbox_config: []
spot: false
tags: null
taint: []
placement_policy: []
project: myproject
timeouts: null
module.cluster-1-nodepool-1.google_service_account.service_account[0]:
account_id: spam-eggs
description: null
disabled: false
display_name: Terraform GKE cluster-1 nodepool-1.
project: myproject
timeouts: null
counts:
google_container_node_pool: 1
google_service_account: 1

View File

@ -0,0 +1,43 @@
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
values:
module.cluster-1-nodepool-1.google_container_node_pool.nodepool:
cluster: cluster-1
location: europe-west1-b
name: nodepool-1
node_config:
- boot_disk_kms_key: null
disk_type: pd-balanced
ephemeral_storage_config: []
gcfs_config: []
gvnic: []
kubelet_config: []
linux_node_config: []
logging_variant: DEFAULT
node_group: null
oauth_scopes:
- https://www.googleapis.com/auth/cloud-platform
preemptible: false
reservation_affinity: []
resource_labels: null
sandbox_config: []
service_account: foo-bar@myproject.iam.gserviceaccount.com
spot: false
tags: null
taint: []
project: myproject
counts:
google_container_node_pool: 1

View File

@ -1,45 +0,0 @@
/**
* 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.
*/
resource "google_service_account" "test" {
project = "my-project"
account_id = "gke-nodepool-test"
display_name = "Test Service Account"
}
module "test" {
source = "../../../../modules/gke-nodepool"
project_id = "my-project"
cluster_name = "cluster-1"
location = "europe-west1-b"
name = "nodepool-1"
gke_version = var.gke_version
labels = var.labels
max_pods_per_node = var.max_pods_per_node
node_config = var.node_config
node_count = var.node_count
node_locations = var.node_locations
nodepool_config = var.nodepool_config
pod_range = var.pod_range
reservation_affinity = var.reservation_affinity
service_account = {
create = var.service_account_create
email = google_service_account.test.email
}
sole_tenant_nodegroup = var.sole_tenant_nodegroup
tags = var.tags
taints = var.taints
}

View File

@ -1,86 +0,0 @@
/**
* 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 "gke_version" {
type = string
default = null
}
variable "labels" {
type = map(string)
default = {}
nullable = false
}
variable "max_pods_per_node" {
type = number
default = null
}
variable "node_config" {
type = any
default = {
disk_type = "pd-balanced"
}
}
variable "node_count" {
type = any
default = {
initial = 1
}
nullable = false
}
variable "node_locations" {
type = list(string)
default = null
}
variable "nodepool_config" {
type = any
default = null
}
variable "pod_range" {
type = any
default = null
}
variable "reservation_affinity" {
type = any
default = null
}
variable "service_account_create" {
type = bool
default = false
}
variable "sole_tenant_nodegroup" {
type = string
default = null
}
variable "tags" {
type = list(string)
default = null
}
variable "taints" {
type = any
default = null
}

View File

@ -1,67 +0,0 @@
# 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.
def test_defaults(plan_runner):
"Test resources created with variable defaults."
_, resources = plan_runner()
assert len(resources) == 1
assert resources[0]['values']['autoscaling'] == []
def test_service_account(plan_runner):
_, resources = plan_runner()
assert len(resources) == 1
_, resources = plan_runner(service_account_create='true')
assert len(resources) == 2
assert 'google_service_account' in [r['type'] for r in resources]
def test_nodepool_config(plan_runner):
nodepool_config = '''{
autoscaling = { use_total_nodes = true, max_node_count = 3}
management = {}
upgrade_settings = { max_surge = 3, max_unavailable = 3 }
}'''
_, resources = plan_runner(nodepool_config=nodepool_config)
assert resources[0]['values']['autoscaling'] == [{
'location_policy': None,
'max_node_count': None,
'min_node_count': None,
'total_max_node_count': 3,
'total_min_node_count': None
}]
nodepool_config = '{ autoscaling = { max_node_count = 3} }'
_, resources = plan_runner(nodepool_config=nodepool_config)
assert resources[0]['values']['autoscaling'] == [{
'location_policy': None,
'max_node_count': 3,
'min_node_count': None,
'total_max_node_count': None,
'total_min_node_count': None
}]
def test_node_config(plan_runner):
node_config = '''{
gcfs = true
metadata = { foo = "bar" }
}'''
_, resources = plan_runner(node_config=node_config)
values = resources[0]['values']['node_config'][0]
assert values['gcfs_config'] == [{'enabled': True}]
assert values['metadata'] == {
'disable-legacy-endpoints': 'true',
'foo': 'bar'
}

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