diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac0af7753..8f3be0538 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
- add support for IAM to `data-catalog-policy-tag` module
- add support for IAM additive to `folder` module, fixes #580
- **incompatible change** the variable for PSA ranges in the `net-vpc` module has changed to support configuring peering routes
+- optionally turn off gcplogs driver in COS modules
**FAST**
diff --git a/examples/cloud-operations/network-dashboard/README.md b/examples/cloud-operations/network-dashboard/README.md
index ee3167cc4..2f958375e 100644
--- a/examples/cloud-operations/network-dashboard/README.md
+++ b/examples/cloud-operations/network-dashboard/README.md
@@ -27,7 +27,6 @@ A dashboard called "quotas-utilization" should be created.
The Cloud Function runs every 5 minutes by default so you should start getting some data points after a few minutes.
You can change this frequency by modifying the "schedule_cron" variable in variables.tf.
-Note that we are using Google defined metrics that are populated only once a day so you might need to wait up to one day for some metrics.
Once done testing, you can clean up resources by running `terraform destroy`.
@@ -43,4 +42,13 @@ The Cloud Function currently tracks usage, limit and utilization of:
- internal forwarding rules for internal L4 load balancers per VPC peering group
- internal forwarding rules for internal L7 load balancers per VPC peering group
-It writes this values to custom metrics in Cloud Monitoring and creates a dashboard to visualize the current utilization of these metrics in Cloud Monitoring.
\ No newline at end of file
+It writes this values to custom metrics in Cloud Monitoring and creates a dashboard to visualize the current utilization of these metrics in Cloud Monitoring.
+
+## Next steps and ideas
+In a future release, we could support:
+- Static routes per VPC / per VPC peering group
+- Dynamic routes per VPC / per VPC peering group
+- Google managed VPCs that are peered with PSA (such as Cloud SQL or Memorystore)
+- Subnet IP ranges utilization
+
+If you are interested in this and/or would like to contribute, please contact legranda@google.com.
\ No newline at end of file
diff --git a/examples/cloud-operations/network-dashboard/cloud-function/main.py b/examples/cloud-operations/network-dashboard/cloud-function/main.py
index 0b1e3dff2..8875ff8d6 100644
--- a/examples/cloud-operations/network-dashboard/cloud-function/main.py
+++ b/examples/cloud-operations/network-dashboard/cloud-function/main.py
@@ -17,10 +17,15 @@
import os
import time
import yaml
+from collections import defaultdict
from google.api import metric_pb2 as ga_metric
-from google.cloud import monitoring_v3
+from google.api_core import protobuf_helpers
+from google.cloud import monitoring_v3, asset_v1
+from google.protobuf import field_mask_pb2
from googleapiclient import discovery
+# Organization ID containing the projects to be monitored
+ORGANIZATION_ID = os.environ.get("ORGANIZATION_ID")
# list of projects from which function will get quotas information
MONITORED_PROJECTS_LIST = os.environ.get("MONITORED_PROJECTS_LIST").split(",")
# project where the metrics and dahsboards will be created
@@ -28,25 +33,11 @@ MONITORING_PROJECT_ID = os.environ.get("MONITORING_PROJECT_ID")
MONITORING_PROJECT_LINK = f"projects/{MONITORING_PROJECT_ID}"
service = discovery.build('compute', 'v1')
-# DEFAULT LIMITS:
-LIMIT_INSTANCES = os.environ.get("LIMIT_INSTANCES").split(",")
-LIMIT_INSTANCES_PPG = os.environ.get("LIMIT_INSTANCES_PPG").split(",")
-LIMIT_L4 = os.environ.get("LIMIT_L4").split(",")
-LIMIT_L4_PPG = os.environ.get("LIMIT_L4_PPG").split(",")
-LIMIT_L7 = os.environ.get("LIMIT_L7").split(",")
-LIMIT_L7_PPG = os.environ.get("LIMIT_L7_PPG").split(",")
-LIMIT_SUBNETS = os.environ.get("LIMIT_SUBNETS").split(",")
-LIMIT_VPC_PEER = os.environ.get("LIMIT_VPC_PEER").split(",")
-
# Existing GCP metrics per network
GCE_INSTANCES_LIMIT_METRIC = "compute.googleapis.com/quota/instances_per_vpc_network/limit"
-GCE_INSTANCES_USAGE_METRIC = "compute.googleapis.com/quota/instances_per_vpc_network/usage"
L4_FORWARDING_RULES_LIMIT_METRIC = "compute.googleapis.com/quota/internal_lb_forwarding_rules_per_vpc_network/limit"
-L4_FORWARDING_RULES_USAGE_METRIC = "compute.googleapis.com/quota/internal_lb_forwarding_rules_per_vpc_network/usage"
L7_FORWARDING_RULES_LIMIT_METRIC = "compute.googleapis.com/quota/internal_managed_forwarding_rules_per_vpc_network/limit"
-L7_FORWARDING_RULES_USAGE_METRIC = "compute.googleapis.com/quota/internal_managed_forwarding_rules_per_vpc_network/usage"
SUBNET_RANGES_LIMIT_METRIC = "compute.googleapis.com/quota/subnet_ranges_per_vpc_network/limit"
-SUBNET_RANGES_USAGE_METRIC = "compute.googleapis.com/quota/subnet_ranges_per_vpc_network/usage"
def main(event, context):
@@ -59,39 +50,200 @@ def main(event, context):
Returns:
'Function executed successfully'
'''
+ metrics_dict, limits_dict = create_metrics()
- metrics_dict = create_metrics()
+ # Asset inventory queries
+ gce_instance_dict = get_gce_instance_dict()
+ l4_forwarding_rules_dict = get_l4_forwarding_rules_dict()
+ l7_forwarding_rules_dict = get_l7_forwarding_rules_dict()
+ subnet_range_dict = get_subnet_ranges_dict()
# Per Network metrics
- get_gce_instances_data(metrics_dict)
- get_l4_forwarding_rules_data(metrics_dict)
- get_vpc_peering_data(metrics_dict)
+ get_gce_instances_data(metrics_dict, gce_instance_dict,
+ limits_dict['number_of_instances_limit'])
+ get_l4_forwarding_rules_data(
+ metrics_dict, l4_forwarding_rules_dict,
+ limits_dict['internal_forwarding_rules_l4_limit'])
+ get_vpc_peering_data(metrics_dict,
+ limits_dict['number_of_vpc_peerings_limit'])
get_pgg_data(
metrics_dict["metrics_per_peering_group"]["instance_per_peering_group"],
- GCE_INSTANCES_USAGE_METRIC, GCE_INSTANCES_LIMIT_METRIC,
- LIMIT_INSTANCES_PPG)
+ gce_instance_dict, GCE_INSTANCES_LIMIT_METRIC,
+ limits_dict['number_of_instances_ppg_limit'])
get_pgg_data(
metrics_dict["metrics_per_peering_group"]
- ["l4_forwarding_rules_per_peering_group"],
- L4_FORWARDING_RULES_USAGE_METRIC, L4_FORWARDING_RULES_LIMIT_METRIC,
- LIMIT_L4_PPG)
+ ["l4_forwarding_rules_per_peering_group"], l4_forwarding_rules_dict,
+ L4_FORWARDING_RULES_LIMIT_METRIC,
+ limits_dict['internal_forwarding_rules_l4_ppg_limit'])
get_pgg_data(
metrics_dict["metrics_per_peering_group"]
- ["l7_forwarding_rules_per_peering_group"],
- L7_FORWARDING_RULES_USAGE_METRIC, L7_FORWARDING_RULES_LIMIT_METRIC,
- LIMIT_L7_PPG)
+ ["l7_forwarding_rules_per_peering_group"], l7_forwarding_rules_dict,
+ L7_FORWARDING_RULES_LIMIT_METRIC,
+ limits_dict['internal_forwarding_rules_l7_ppg_limit'])
get_pgg_data(
metrics_dict["metrics_per_peering_group"]
- ["subnet_ranges_per_peering_group"], SUBNET_RANGES_USAGE_METRIC,
- SUBNET_RANGES_LIMIT_METRIC, LIMIT_SUBNETS)
+ ["subnet_ranges_per_peering_group"], subnet_range_dict,
+ SUBNET_RANGES_LIMIT_METRIC,
+ limits_dict['number_of_subnet_IP_ranges_limit'])
return 'Function executed successfully'
+def get_l4_forwarding_rules_dict():
+ '''
+ Calls the Asset Inventory API to get all L4 Forwarding Rules under the GCP organization.
+
+ Parameters:
+ None
+ Returns:
+ forwarding_rules_dict (dictionary of string: int): Keys are the network links and values are the number of Forwarding Rules per network.
+ '''
+ client = asset_v1.AssetServiceClient()
+
+ read_mask = field_mask_pb2.FieldMask()
+ read_mask.FromJsonString('name,versionedResources')
+
+ forwarding_rules_dict = defaultdict(int)
+
+ response = client.search_all_resources(
+ request={
+ "scope": f"organizations/{ORGANIZATION_ID}",
+ "asset_types": ["compute.googleapis.com/ForwardingRule"],
+ "read_mask": read_mask,
+ })
+ for resource in response:
+ internal = False
+ network_link = ""
+ for versioned in resource.versioned_resources:
+ for field_name, field_value in versioned.resource.items():
+ if field_name == "loadBalancingScheme":
+ internal = (field_value == "INTERNAL")
+ if field_name == "network":
+ network_link = field_value
+ if internal:
+ if network_link in forwarding_rules_dict:
+ forwarding_rules_dict[network_link] += 1
+ else:
+ forwarding_rules_dict[network_link] = 1
+
+ return forwarding_rules_dict
+
+
+def get_l7_forwarding_rules_dict():
+ '''
+ Calls the Asset Inventory API to get all L7 Forwarding Rules under the GCP organization.
+
+ Parameters:
+ None
+ Returns:
+ forwarding_rules_dict (dictionary of string: int): Keys are the network links and values are the number of Forwarding Rules per network.
+ '''
+ client = asset_v1.AssetServiceClient()
+
+ read_mask = field_mask_pb2.FieldMask()
+ read_mask.FromJsonString('name,versionedResources')
+
+ forwarding_rules_dict = defaultdict(int)
+
+ response = client.search_all_resources(
+ request={
+ "scope": f"organizations/{ORGANIZATION_ID}",
+ "asset_types": ["compute.googleapis.com/ForwardingRule"],
+ "read_mask": read_mask,
+ })
+ for resource in response:
+ internal = False
+ network_link = ""
+ for versioned in resource.versioned_resources:
+ for field_name, field_value in versioned.resource.items():
+ if field_name == "loadBalancingScheme":
+ internal = (field_value == "INTERNAL_MANAGED")
+ if field_name == "network":
+ network_link = field_value
+ if internal:
+ if network_link in forwarding_rules_dict:
+ forwarding_rules_dict[network_link] += 1
+ else:
+ forwarding_rules_dict[network_link] = 1
+
+ return forwarding_rules_dict
+
+
+def get_gce_instance_dict():
+ '''
+ Calls the Asset Inventory API to get all GCE instances under the GCP organization.
+
+ Parameters:
+ None
+ Returns:
+ gce_instance_dict (dictionary of string: int): Keys are the network links and values are the number of GCE Instances per network.
+ '''
+ client = asset_v1.AssetServiceClient()
+
+ gce_instance_dict = defaultdict(int)
+
+ response = client.search_all_resources(
+ request={
+ "scope": f"organizations/{ORGANIZATION_ID}",
+ "asset_types": ["compute.googleapis.com/Instance"],
+ })
+ for resource in response:
+ for field_name, field_value in resource.additional_attributes.items():
+ if field_name == "networkInterfaceNetworks":
+ for network in field_value:
+ if network in gce_instance_dict:
+ gce_instance_dict[network] += 1
+ else:
+ gce_instance_dict[network] = 1
+
+ return gce_instance_dict
+
+
+def get_subnet_ranges_dict():
+ '''
+ Calls the Asset Inventory API to get all Subnet ranges under the GCP organization.
+
+ Parameters:
+ None
+ Returns:
+ subnet_range_dict (dictionary of string: int): Keys are the network links and values are the number of subnet ranges per network.
+ '''
+ client = asset_v1.AssetServiceClient()
+ subnet_range_dict = defaultdict(int)
+ read_mask = field_mask_pb2.FieldMask()
+ read_mask.FromJsonString('name,versionedResources')
+
+ response = client.search_all_resources(
+ request={
+ "scope": f"organizations/{ORGANIZATION_ID}",
+ "asset_types": ["compute.googleapis.com/Subnetwork"],
+ "read_mask": read_mask,
+ })
+ for resource in response:
+ ranges = 0
+ network_link = None
+
+ for versioned in resource.versioned_resources:
+ for field_name, field_value in versioned.resource.items():
+ if field_name == "network":
+ network_link = field_value
+ ranges += 1
+ if field_name == "secondaryIpRanges":
+ for range in field_value:
+ ranges += 1
+
+ if network_link in subnet_range_dict:
+ subnet_range_dict[network_link] += ranges
+ else:
+ subnet_range_dict[network_link] = ranges
+
+ return subnet_range_dict
+
+
def create_client():
'''
Creates the monitoring API client, that will be used to create, read and update custom metrics.
@@ -123,16 +275,41 @@ def create_client():
def create_metrics():
+ '''
+ Creates all Cloud Monitoring custom metrics based on the metric.yaml file
+
+ Parameters:
+ None
+
+ Returns:
+ metrics_dict (dictionary of dictionary of string: string): metrics names and descriptions
+ limits_dict (dictionary of dictionary of string: int): limits_dict[metric_name]: dict[network_name] = limit_value
+ '''
+ client = monitoring_v3.MetricServiceClient()
+ existing_metrics = []
+ for desc in client.list_metric_descriptors(name=MONITORING_PROJECT_LINK):
+ existing_metrics.append(desc.type)
+ limits_dict = {}
+
with open("metrics.yaml", 'r') as stream:
try:
metrics_dict = yaml.safe_load(stream)
for metric_list in metrics_dict.values():
for metric in metric_list.values():
- for sub_metric in metric.values():
- create_metric(sub_metric["name"], sub_metric["description"])
+ for sub_metric_key, sub_metric in metric.items():
+ metric_link = f"custom.googleapis.com/{sub_metric['name']}"
+ # If the metric doesn't exist yet, then we create it
+ if metric_link not in existing_metrics:
+ create_metric(sub_metric["name"], sub_metric["description"])
+ # Parse limits (both default values and network specific ones)
+ if sub_metric_key == "limit":
+ limits_dict_for_metric = {}
+ for network_link, limit_value in sub_metric["values"].items():
+ limits_dict_for_metric[network_link] = limit_value
+ limits_dict[sub_metric["name"]] = limits_dict_for_metric
- return metrics_dict
+ return metrics_dict, limits_dict
except yaml.YAMLError as exc:
print(exc)
@@ -150,76 +327,72 @@ def create_metric(metric_name, description):
'''
client = monitoring_v3.MetricServiceClient()
- metric_link = f"custom.googleapis.com/{metric_name}"
- types = []
- for desc in client.list_metric_descriptors(name=MONITORING_PROJECT_LINK):
- types.append(desc.type)
-
- # If the metric doesn't exist yet, then we create it
- if metric_link not in types:
- descriptor = ga_metric.MetricDescriptor()
- descriptor.type = f"custom.googleapis.com/{metric_name}"
- descriptor.metric_kind = ga_metric.MetricDescriptor.MetricKind.GAUGE
- descriptor.value_type = ga_metric.MetricDescriptor.ValueType.DOUBLE
- descriptor.description = description
- descriptor = client.create_metric_descriptor(name=MONITORING_PROJECT_LINK,
- metric_descriptor=descriptor)
- print("Created {}.".format(descriptor.name))
+ descriptor = ga_metric.MetricDescriptor()
+ descriptor.type = f"custom.googleapis.com/{metric_name}"
+ descriptor.metric_kind = ga_metric.MetricDescriptor.MetricKind.GAUGE
+ descriptor.value_type = ga_metric.MetricDescriptor.ValueType.DOUBLE
+ descriptor.description = description
+ descriptor = client.create_metric_descriptor(name=MONITORING_PROJECT_LINK,
+ metric_descriptor=descriptor)
+ print("Created {}.".format(descriptor.name))
-def get_gce_instances_data(metrics_dict):
+def get_gce_instances_data(metrics_dict, gce_instance_dict, limit_dict):
'''
Gets the data for GCE instances per VPC Network and writes it to the metric defined in instance_metric.
Parameters:
metrics_dict (dictionary of dictionary of string: string): metrics names and descriptions
+ gce_instance_dict (dictionary of string: int): Keys are the network links and values are the number of GCE Instances per network.
+ limit_dict (dictionary of string:int): Dictionary with the network link as key and the limit as value
Returns:
- None
+ gce_instance_dict
'''
# Existing GCP Monitoring metrics for GCE instances
- metric_instances_usage = "compute.googleapis.com/quota/instances_per_vpc_network/usage"
metric_instances_limit = "compute.googleapis.com/quota/instances_per_vpc_network/limit"
for project in MONITORED_PROJECTS_LIST:
network_dict = get_networks(project)
- current_quota_usage = get_quota_current_usage(f"projects/{project}",
- metric_instances_usage)
current_quota_limit = get_quota_current_limit(f"projects/{project}",
metric_instances_limit)
-
- current_quota_usage_view = customize_quota_view(current_quota_usage)
current_quota_limit_view = customize_quota_view(current_quota_limit)
for net in network_dict:
- set_usage_limits(net, current_quota_usage_view, current_quota_limit_view,
- LIMIT_INSTANCES)
+ set_limits(net, current_quota_limit_view, limit_dict)
+
+ network_link = f"https://www.googleapis.com/compute/v1/projects/{project}/global/networks/{net['network_name']}"
+
+ usage = 0
+ if network_link in gce_instance_dict:
+ usage = gce_instance_dict[network_link]
+
write_data_to_metric(
- project, net['usage'], metrics_dict["metrics_per_network"]
- ["instance_per_network"]["usage"]["name"], net['network name'])
+ project, usage, metrics_dict["metrics_per_network"]
+ ["instance_per_network"]["usage"]["name"], net['network_name'])
write_data_to_metric(
project, net['limit'], metrics_dict["metrics_per_network"]
- ["instance_per_network"]["limit"]["name"], net['network name'])
+ ["instance_per_network"]["limit"]["name"], net['network_name'])
write_data_to_metric(
- project, net['usage'] / net['limit'],
- metrics_dict["metrics_per_network"]["instance_per_network"]
- ["utilization"]["name"], net['network name'])
+ project, usage / net['limit'], metrics_dict["metrics_per_network"]
+ ["instance_per_network"]["utilization"]["name"], net['network_name'])
print(f"Wrote number of instances to metric for projects/{project}")
-def get_vpc_peering_data(metrics_dict):
+def get_vpc_peering_data(metrics_dict, limit_dict):
'''
Gets the data for VPC peerings (active or not) and writes it to the metric defined (vpc_peering_active_metric and vpc_peering_metric).
Parameters:
metrics_dict (dictionary of dictionary of string: string): metrics names and descriptions
+ limit_dict (dictionary of string:int): Dictionary with the network link as key and the limit as value
Returns:
None
'''
for project in MONITORED_PROJECTS_LIST:
active_vpc_peerings, vpc_peerings = gather_vpc_peerings_data(
- project, LIMIT_VPC_PEER)
+ project, limit_dict)
for peering in active_vpc_peerings:
write_data_to_metric(
project, peering['active_peerings'],
@@ -250,13 +423,13 @@ def get_vpc_peering_data(metrics_dict):
print("Wrote number of VPC peerings to custom metric for project:", project)
-def gather_vpc_peerings_data(project_id, limit_list):
+def gather_vpc_peerings_data(project_id, limit_dict):
'''
Gets the data for all VPC peerings (active or not) in project_id and writes it to the metric defined in vpc_peering_active_metric and vpc_peering_metric.
Parameters:
project_id (string): We will take all VPCs in that project_id and look for all peerings to these VPCs.
- limit_list (list of string): Used to get the limit per VPC or the default limit.
+ limit_dict (dictionary of string:int): Dictionary with the network link as key and the limit as value
Returns:
active_peerings_dict (dictionary of string: string): Contains project_id, network_name, network_limit for each active VPC peering.
peerings_dict (dictionary of string: string): Contains project_id, network_name, network_limit for each VPC peering.
@@ -279,96 +452,102 @@ def gather_vpc_peerings_data(project_id, limit_list):
peerings_count = 0
active_peerings_count = 0
+ network_link = f"https://www.googleapis.com/compute/v1/projects/{project_id}/global/networks/{network['name']}"
+ network_limit = get_limit_ppg(network_link, limit_dict)
+
active_d = {
'project_id': project_id,
'network_name': network['name'],
'active_peerings': active_peerings_count,
- 'network_limit': get_limit(network['name'], limit_list)
+ 'network_limit': network_limit
}
active_peerings_dict.append(active_d)
d = {
'project_id': project_id,
'network_name': network['name'],
'peerings': peerings_count,
- 'network_limit': get_limit(network['name'], limit_list)
+ 'network_limit': network_limit
}
peerings_dict.append(d)
return active_peerings_dict, peerings_dict
-def get_limit(network_name, limit_list):
+def get_limit_ppg(network_link, limit_dict):
'''
Checks if this network has a specific limit for a metric, if so, returns that limit, if not, returns the default limit.
Parameters:
- network_name (string): Name of the VPC network.
+ network_link (string): VPC network link.
limit_list (list of string): Used to get the limit per VPC or the default limit.
Returns:
- limit (int): Limit for that VPC and that metric.
+ limit_dict (dictionary of string:int): Dictionary with the network link as key and the limit as value
'''
- if network_name in limit_list:
- return int(limit_list[limit_list.index(network_name) + 1])
+ if network_link in limit_dict:
+ return limit_dict[network_link]
else:
- if 'default_value' in limit_list:
- return int(limit_list[limit_list.index('default_value') + 1])
+ if 'default_value' in limit_dict:
+ return limit_dict['default_value']
else:
+ print(f"Error: limit not found for {network_link}")
return 0
-def get_l4_forwarding_rules_data(metrics_dict):
+def get_l4_forwarding_rules_data(metrics_dict, forwarding_rules_dict,
+ limit_dict):
'''
Gets the data for L4 Internal Forwarding Rules per VPC Network and writes it to the metric defined in forwarding_rules_metric.
Parameters:
- metrics_dict (dictionary of dictionary of string: string): metrics names and descriptions
+ metrics_dict (dictionary of dictionary of string: string): metrics names and descriptions.
+ forwarding_rules_dict (dictionary of string: int): Keys are the network links and values are the number of Forwarding Rules per network.
+ limit_dict (dictionary of string:int): Dictionary with the network link as key and the limit as value.
Returns:
None
'''
- # Existing GCP Monitoring metrics for L4 Forwarding Rules
- l4_forwarding_rules_usage = "compute.googleapis.com/quota/internal_lb_forwarding_rules_per_vpc_network/usage"
- l4_forwarding_rules_limit = "compute.googleapis.com/quota/internal_lb_forwarding_rules_per_vpc_network/limit"
-
for project in MONITORED_PROJECTS_LIST:
network_dict = get_networks(project)
- current_quota_usage = get_quota_current_usage(f"projects/{project}",
- l4_forwarding_rules_usage)
- current_quota_limit = get_quota_current_limit(f"projects/{project}",
- l4_forwarding_rules_limit)
+ current_quota_limit = get_quota_current_limit(
+ f"projects/{project}", L4_FORWARDING_RULES_LIMIT_METRIC)
- current_quota_usage_view = customize_quota_view(current_quota_usage)
current_quota_limit_view = customize_quota_view(current_quota_limit)
for net in network_dict:
- set_usage_limits(net, current_quota_usage_view, current_quota_limit_view,
- LIMIT_L4)
+ set_limits(net, current_quota_limit_view, limit_dict)
+
+ network_link = f"https://www.googleapis.com/compute/v1/projects/{project}/global/networks/{net['network_name']}"
+
+ usage = 0
+ if network_link in forwarding_rules_dict:
+ usage = forwarding_rules_dict[network_link]
+
write_data_to_metric(
- project, net['usage'], metrics_dict["metrics_per_network"]
+ project, usage, metrics_dict["metrics_per_network"]
["l4_forwarding_rules_per_network"]["usage"]["name"],
- net['network name'])
+ net['network_name'])
write_data_to_metric(
project, net['limit'], metrics_dict["metrics_per_network"]
["l4_forwarding_rules_per_network"]["limit"]["name"],
- net['network name'])
+ net['network_name'])
write_data_to_metric(
- project, net['usage'] / net['limit'],
- metrics_dict["metrics_per_network"]["l4_forwarding_rules_per_network"]
- ["utilization"]["name"], net['network name'])
+ project, usage / net['limit'], metrics_dict["metrics_per_network"]
+ ["l4_forwarding_rules_per_network"]["utilization"]["name"],
+ net['network_name'])
print(
f"Wrote number of L4 forwarding rules to metric for projects/{project}")
-def get_pgg_data(metric_dict, usage_metric, limit_metric, limit_ppg):
+def get_pgg_data(metric_dict, usage_dict, limit_metric, limit_dict):
'''
This function gets the usage, limit and utilization per VPC peering group for a specific metric for all projects to be monitored.
Parameters:
- metric_dict (dictionary of string: string): A dictionary with the metric names and description, that will be used to populate the metrics
+ metric_dict (dictionary of string: string): Dictionary with the metric names and description, that will be used to populate the metrics
usage_metric (string): Name of the existing GCP metric for usage per VPC network.
- limit_metric (string): Name of the existing GCP metric for limit per VPC network.
- limit_ppg (list of string): List containing the limit per peering group (either VPC specific or default limit).
+ usage_dict (dictionnary of string:int): Dictionary with the network link as key and the number of resources as value
+ limit_dict (dictionary of string:int): Dictionary with the network link as key and the limit as value
Returns:
None
'''
@@ -382,38 +561,43 @@ def get_pgg_data(metric_dict, usage_metric, limit_metric, limit_ppg):
# For each network in this GCP project
for network_dict in network_dict_list:
- current_quota_usage = get_quota_current_usage(f"projects/{project}",
- usage_metric)
+ network_link = f"https://www.googleapis.com/compute/v1/projects/{project}/global/networks/{network_dict['network_name']}"
+
current_quota_limit = get_quota_current_limit(f"projects/{project}",
limit_metric)
-
- current_quota_usage_view = customize_quota_view(current_quota_usage)
current_quota_limit_view = customize_quota_view(current_quota_limit)
+ limit = get_limit_network(network_dict, network_link,
+ current_quota_limit_view, limit_dict)
+
+ usage = 0
+ if network_link in usage_dict:
+ usage = usage_dict[network_link]
- usage, limit = get_usage_limit(network_dict, current_quota_usage_view,
- current_quota_limit_view, limit_ppg)
# Here we add usage and limit to the network dictionary
network_dict["usage"] = usage
network_dict["limit"] = limit
# For every peered network, get usage and limits
- for peered_network in network_dict['peerings']:
- peering_project_usage = customize_quota_view(
- get_quota_current_usage(f"projects/{peered_network['project_id']}",
- usage_metric))
- peering_project_limit = customize_quota_view(
- get_quota_current_limit(f"projects/{peered_network['project_id']}",
- limit_metric))
+ for peered_network_dict in network_dict['peerings']:
+ peered_network_link = f"https://www.googleapis.com/compute/v1/projects/{peered_network_dict['project_id']}/global/networks/{peered_network_dict['network_name']}"
+ peered_usage = 0
+ if peered_network_link in usage_dict:
+ peered_usage = usage_dict[peered_network_link]
- usage, limit = get_usage_limit(peered_network, peering_project_usage,
- peering_project_limit, limit_ppg)
+ peering_project_limit = customize_quota_view(
+ get_quota_current_limit(
+ f"projects/{peered_network_dict['project_id']}", limit_metric))
+
+ peered_limit = get_limit_network(peered_network_dict,
+ peered_network_link,
+ peering_project_limit, limit_dict)
# Here we add usage and limit to the peered network dictionary
- peered_network["usage"] = usage
- peered_network["limit"] = limit
+ peered_network_dict["usage"] = peered_usage
+ peered_network_dict["limit"] = peered_limit
count_effective_limit(project, network_dict, metric_dict["usage"]["name"],
metric_dict["limit"]["name"],
- metric_dict["utilization"]["name"], limit_ppg)
+ metric_dict["utilization"]["name"], limit_dict)
print(
f"Wrote {metric_dict['usage']['name']} to metric for peering group {network_dict['network_name']} in {project}"
)
@@ -421,7 +605,7 @@ def get_pgg_data(metric_dict, usage_metric, limit_metric, limit_ppg):
def count_effective_limit(project_id, network_dict, usage_metric_name,
limit_metric_name, utilization_metric_name,
- limit_ppg):
+ limit_dict):
'''
Calculates the effective limits (using algorithm in the link below) for peering groups and writes data (usage, limit, utilization) to the custom metrics.
Source: https://cloud.google.com/vpc/docs/quota#vpc-peering-effective-limit
@@ -432,7 +616,7 @@ def count_effective_limit(project_id, network_dict, usage_metric_name,
usage_metric_name (string): Name of the custom metric to be populated for usage per VPC peering group.
limit_metric_name (string): Name of the custom metric to be populated for limit per VPC peering group.
utilization_metric_name (string): Name of the custom metric to be populated for utilization per VPC peering group.
- limit_ppg (list of string): List containing the limit per peering group (either VPC specific or default limit).
+ limit_dict (dictionary of string:int): Dictionary containing the limit per peering group (either VPC specific or default limit).
Returns:
None
'''
@@ -445,16 +629,20 @@ def count_effective_limit(project_id, network_dict, usage_metric_name,
for peered_network in network_dict['peerings']:
peering_group_usage += peered_network['usage']
+ network_link = f"https://www.googleapis.com/compute/v1/projects/{project_id}/global/networks/{network_dict['network_name']}"
+
# Calculates effective limit: Step 1: max(per network limit, per network_peering_group limit)
limit_step1 = max(network_dict['limit'],
- get_limit(network_dict['network_name'], limit_ppg))
+ get_limit_ppg(network_link, limit_dict))
# Calculates effective limit: Step 2: List of max(per network limit, per network_peering_group limit) for each peered network
limit_step2 = []
for peered_network in network_dict['peerings']:
+ peered_network_link = f"https://www.googleapis.com/compute/v1/projects/{peered_network['project_id']}/global/networks/{peered_network['network_name']}"
+
limit_step2.append(
max(peered_network['limit'],
- get_limit(peered_network['network_name'], limit_ppg)))
+ get_limit_ppg(peered_network_link, limit_dict)))
# Calculates effective limit: Step 3: Find minimum from the list created by Step 2
limit_step3 = min(limit_step2)
@@ -485,9 +673,39 @@ def get_networks(project_id):
network_dict = []
if 'items' in response:
for network in response['items']:
- NETWORK = network['name']
- ID = network['id']
- d = {'project_id': project_id, 'network name': NETWORK, 'network id': ID}
+ network_name = network['name']
+ network_id = network['id']
+ d = {
+ 'project_id': project_id,
+ 'network_name': network_name,
+ 'network_id': network_id
+ }
+ network_dict.append(d)
+ return network_dict
+
+
+# TODO: list all routers (https://cloud.google.com/compute/docs/reference/rest/v1/routers/list) then https://cloud.google.com/compute/docs/reference/rest/v1/routers/getRouterStatus
+def get_routes(project_id):
+ '''
+ Returns a dictionary of all dynamic routes in a project.
+
+ Parameters:
+ project_id (string): Project ID for the project containing the networks.
+ Returns:
+ network_dict (dictionary of string: string): Contains the project_id, network_name(s) and network_id(s)
+ '''
+ request = service.routers().list(project=project_id)
+ response = request.execute()
+ network_dict = []
+ if 'items' in response:
+ for router in response['items']:
+ network_name = router['name']
+ network_id = router['id']
+ d = {
+ 'project_id': project_id,
+ 'network name': network_name,
+ 'network id': network_id
+ }
network_dict.append(d)
return network_dict
@@ -564,29 +782,6 @@ def get_network_id(project_id, network_name):
return network_id
-def get_quota_current_usage(project_link, metric_name):
- '''
- Retrieves quota usage for a specific metric.
-
- Parameters:
- project_link (string): Project link.
- metric_name (string): Name of the metric.
- Returns:
- results_list (list of string): Current usage.
- '''
- client, interval = create_client()
-
- results = client.list_time_series(
- request={
- "name": project_link,
- "filter": f'metric.type = "{metric_name}"',
- "interval": interval,
- "view": monitoring_v3.ListTimeSeriesRequest.TimeSeriesView.FULL
- })
- results_list = list(results)
- return (results_list)
-
-
def get_quota_current_limit(project_link, metric_name):
'''
Retrieves limit for a specific metric.
@@ -630,98 +825,64 @@ def customize_quota_view(quota_results):
return quotaViewList
-def set_usage_limits(network_dict, quota_usage, quota_limit, limit_list):
+def set_limits(network_dict, quota_limit, limit_dict):
'''
- Updates the network dictionary with quota usage and limit values.
+ Updates the network dictionary with quota limit values.
Parameters:
network_dict (dictionary of string: string): Contains network information.
- quota_usage (list of dictionaries of string: string): Current quota usage.
quota_limit (list of dictionaries of string: string): Current quota limit.
- limit_list (list of string): List containing the limit per VPC (either VPC specific or default limit).
+ limit_dict (dictionary of string:int): Dictionary with the network link as key and the limit as value
Returns:
None
'''
- if quota_usage:
- for net in quota_usage:
- if net['network_id'] == network_dict[
- 'network id']: # if network ids in GCP quotas and in dictionary (using API) are the same
- network_dict['usage'] = net['value'] # set network usage in dictionary
- break
- else:
- network_dict['usage'] = 0 # if network does not appear in GCP quotas
- else:
- network_dict['usage'] = 0 # if quotas does not appear in GCP quotas
+
+ network_dict['limit'] = None
if quota_limit:
for net in quota_limit:
- if net['network_id'] == network_dict[
- 'network id']: # if network ids in GCP quotas and in dictionary (using API) are the same
- network_dict['limit'] = net['value'] # set network limit in dictionary
- break
- else:
- if network_dict[
- 'network name'] in limit_list: # if network limit is in the environmental variables
- network_dict['limit'] = int(
- limit_list[limit_list.index(network_dict['network name']) + 1])
- else:
- network_dict['limit'] = int(
- limit_list[limit_list.index('default_value') +
- 1]) # set default value
- else: # if quotas does not appear in GCP quotas
- if network_dict['network name'] in limit_list:
- network_dict['limit'] = int(
- limit_list[limit_list.index(network_dict['network name']) +
- 1]) # ["default", 100, "networkname", 200]
+ if net['network_id'] == network_dict['network_id']:
+ network_dict['limit'] = net['value']
+ return
+
+ network_link = f"https://www.googleapis.com/compute/v1/projects/{network_dict['project_id']}/global/networks/{network_dict['network_name']}"
+
+ if network_link in limit_dict:
+ network_dict['limit'] = limit_dict[network_link]
+ else:
+ if 'default_value' in limit_dict:
+ network_dict['limit'] = limit_dict['default_value']
else:
- network_dict['limit'] = int(limit_list[limit_list.index('default_value') +
- 1])
+ print(f"Error: Couldn't find limit for {network_link}")
+ network_dict['limit'] = 0
-def get_usage_limit(network, quota_usage, quota_limit, limit_list):
+def get_limit_network(network_dict, network_link, quota_limit, limit_dict):
'''
- Returns usage and limit for a specific network and metric.
+ Returns limit for a specific network and metric, using the GCP quota metrics or the values in the yaml file if not found.
Parameters:
network_dict (dictionary of string: string): Contains network information.
- quota_usage (list of dictionaries of string: string): Current quota usage for all networks in that project.
+ network_link (string): Contains network link
quota_limit (list of dictionaries of string: string): Current quota limit for all networks in that project.
- limit_list (list of string): List containing the limit per VPC (either VPC specific or default limit).
+ limit_dict (dictionary of string:int): Dictionary with the network link as key and the limit as value
Returns:
- usage (int): Current usage for that network.
- limit (int): Current usage for that network.
+ limit (int): Current limit for that network.
'''
- usage = 0
- limit = 0
-
- if quota_usage:
- for net in quota_usage:
- if net['network_id'] == network[
- 'network_id']: # if network ids in GCP quotas and in dictionary (using API) are the same
- usage = net['value'] # set network usage in dictionary
- break
-
if quota_limit:
for net in quota_limit:
- if net['network_id'] == network[
- 'network_id']: # if network ids in GCP quotas and in dictionary (using API) are the same
- limit = net['value'] # set network limit in dictionary
- break
- else:
- if network[
- 'network_name'] in limit_list: # if network limit is in the environmental variables
- limit = int(limit_list[limit_list.index(network['network_name']) + 1])
- else:
- limit = int(limit_list[limit_list.index('default_value') +
- 1]) # set default value
- else: # if quotas does not appear in GCP quotas
- if network['network_name'] in limit_list:
- limit = int(limit_list[limit_list.index(network['network_name']) +
- 1]) # ["default", 100, "networkname", 200]
- else:
- limit = int(limit_list[limit_list.index('default_value') + 1])
+ if net['network_id'] == network_dict['network_id']:
+ return net['value']
- return usage, limit
+ if network_link in limit_dict:
+ return limit_dict[network_link]
+ else:
+ if 'default_value' in limit_dict:
+ return limit_dict['default_value']
+ else:
+ print(f"Error: Couldn't find limit for {network_link}")
+
+ return 0
def write_data_to_metric(monitored_project_id, value, metric_name,
@@ -762,4 +923,10 @@ def write_data_to_metric(monitored_project_id, value, metric_name,
})
series.points = [point]
- client.create_time_series(name=MONITORING_PROJECT_LINK, time_series=[series])
+ # TODO: sometimes this cashes with 'DeadlineExceeded: 504 Deadline expired before operation could complete' error
+ # Implement exponential backoff retries?
+ try:
+ client.create_time_series(name=MONITORING_PROJECT_LINK,
+ time_series=[series])
+ except Exception as e:
+ print(e)
diff --git a/examples/cloud-operations/network-dashboard/cloud-function/metrics.yaml b/examples/cloud-operations/network-dashboard/cloud-function/metrics.yaml
index 233dc9be6..a9772b5c1 100644
--- a/examples/cloud-operations/network-dashboard/cloud-function/metrics.yaml
+++ b/examples/cloud-operations/network-dashboard/cloud-function/metrics.yaml
@@ -22,6 +22,8 @@ metrics_per_network:
limit:
name: number_of_instances_limit
description: Number of instances per VPC network - limit.
+ values:
+ default_value: 15000
utilization:
name: number_of_instances_utilization
description: Number of instances per VPC network - utilization.
@@ -32,6 +34,8 @@ metrics_per_network:
limit:
name: number_of_active_vpc_peerings_limit
description: Number of active VPC Peerings per VPC - limit.
+ values:
+ default_value: 25
utilization:
name: number_of_active_vpc_peerings_utilization
description: Number of active VPC Peerings per VPC - utilization.
@@ -42,6 +46,9 @@ metrics_per_network:
limit:
name: number_of_vpc_peerings_limit
description: Number of VPC Peerings per VPC - limit.
+ values:
+ default_value: 25
+ https://www.googleapis.com/compute/v1/projects/net-dash-test-host-prod/global/networks/vpc-prod: 40
utilization:
name: number_of_vpc_peerings_utilization
description: Number of VPC Peerings per VPC - utilization.
@@ -52,6 +59,8 @@ metrics_per_network:
limit:
name: internal_forwarding_rules_l4_limit
description: Number of Internal Forwarding Rules for Internal L4 Load Balancers - limit.
+ values:
+ default_value: 75
utilization:
name: internal_forwarding_rules_l4_utilization
description: Number of Internal Forwarding Rules for Internal L4 Load Balancers - utilization.
@@ -62,6 +71,8 @@ metrics_per_network:
limit:
name: internal_forwarding_rules_l7_limit
description: Number of Internal Forwarding Rules for Internal L7 Load Balancers per network - effective limit.
+ values:
+ default_value: 75
utilization:
name: internal_forwarding_rules_l7_utilization
description: Number of Internal Forwarding Rules for Internal L7 Load Balancers per Vnetwork - utilization.
@@ -73,6 +84,8 @@ metrics_per_peering_group:
limit:
name: internal_forwarding_rules_l4_ppg_limit
description: Number of Internal Forwarding Rules for Internal L4 Load Balancers per VPC peering group - effective limit.
+ values:
+ default_value: 175
utilization:
name: internal_forwarding_rules_l4_ppg_utilization
description: Number of Internal Forwarding Rules for Internal L4 Load Balancers per VPC peering group - utilization.
@@ -83,18 +96,22 @@ metrics_per_peering_group:
limit:
name: internal_forwarding_rules_l7_ppg_limit
description: Number of Internal Forwarding Rules for Internal L7 Load Balancers per VPC peering group - effective limit.
+ values:
+ default_value: 175
utilization:
name: internal_forwarding_rules_l7_ppg_utilization
description: Number of Internal Forwarding Rules for Internal L7 Load Balancers per VPC peering group - utilization.
subnet_ranges_per_peering_group:
usage:
- name: number_of_subnet_IP_ranges_usage
+ name: number_of_subnet_IP_ranges_ppg_usage
description: Number of Subnet Ranges per peering group - usage.
limit:
- name: number_of_subnet_IP_ranges_limit
+ name: number_of_subnet_IP_ranges_ppg_limit
description: Number of Subnet Ranges per peering group - effective limit.
+ values:
+ default_value: 400
utilization:
- name: number_of_subnet_IP_ranges_utilization
+ name: number_of_subnet_IP_ranges_ppg_utilization
description: Number of Subnet Ranges per peering group - utilization.
instance_per_peering_group:
usage:
@@ -103,6 +120,8 @@ metrics_per_peering_group:
limit:
name: number_of_instances_ppg_limit
description: Number of instances per peering group - limit.
+ values:
+ default_value: 15500
utilization:
name: number_of_instances_ppg_utilization
description: Number of instances per peering group - utilization.
\ No newline at end of file
diff --git a/examples/cloud-operations/network-dashboard/cloud-function/requirements.txt b/examples/cloud-operations/network-dashboard/cloud-function/requirements.txt
index 0888969cb..8a6a5960b 100644
--- a/examples/cloud-operations/network-dashboard/cloud-function/requirements.txt
+++ b/examples/cloud-operations/network-dashboard/cloud-function/requirements.txt
@@ -6,4 +6,5 @@ google-cloud-logging==3.0.0
google-cloud-monitoring==2.9.1
oauth2client==4.1.3
google-api-core==2.7.0
-PyYAML==6.0
\ No newline at end of file
+PyYAML==6.0
+google-cloud-asset==3.8.1
\ No newline at end of file
diff --git a/examples/cloud-operations/network-dashboard/dashboards/quotas-utilization.json b/examples/cloud-operations/network-dashboard/dashboards/quotas-utilization.json
index af812061f..794d61234 100644
--- a/examples/cloud-operations/network-dashboard/dashboards/quotas-utilization.json
+++ b/examples/cloud-operations/network-dashboard/dashboards/quotas-utilization.json
@@ -196,7 +196,7 @@
{
"height": 4,
"widget": {
- "title": "number_of_subnet_IP_ranges_utilization",
+ "title": "number_of_subnet_IP_ranges_ppg_utilization",
"xyChart": {
"chartOptions": {
"mode": "COLOR"
@@ -212,7 +212,7 @@
"alignmentPeriod": "3600s",
"perSeriesAligner": "ALIGN_NEXT_OLDER"
},
- "filter": "metric.type=\"custom.googleapis.com/number_of_subnet_IP_ranges_utilization\" resource.type=\"global\"",
+ "filter": "metric.type=\"custom.googleapis.com/number_of_subnet_IP_ranges_ppg_utilization\" resource.type=\"global\"",
"secondaryAggregation": {
"alignmentPeriod": "3600s",
"perSeriesAligner": "ALIGN_MEAN"
diff --git a/examples/cloud-operations/network-dashboard/main.tf b/examples/cloud-operations/network-dashboard/main.tf
index 152bb3609..8fb7963cd 100644
--- a/examples/cloud-operations/network-dashboard/main.tf
+++ b/examples/cloud-operations/network-dashboard/main.tf
@@ -17,23 +17,6 @@
locals {
project_id_list = toset(var.monitored_projects_list)
projects = join(",", local.project_id_list)
-
- limit_instances = join(",", local.limit_instances_list)
- limit_instances_list = tolist(var.limit_instances)
- limit_instances_ppg = join(",", local.limit_instances_ppg_list)
- limit_instances_ppg_list = tolist(var.limit_instances_ppg)
- limit_l4 = join(",", local.limit_l4_list)
- limit_l4_list = tolist(var.limit_l4)
- limit_l4_ppg = join(",", local.limit_l4_ppg_list)
- limit_l4_ppg_list = tolist(var.limit_l4_ppg)
- limit_l7 = join(",", local.limit_l7_list)
- limit_l7_list = tolist(var.limit_l7)
- limit_l7_ppg = join(",", local.limit_l7_ppg_list)
- limit_l7_ppg_list = tolist(var.limit_l7_ppg)
- limit_subnets = join(",", local.limit_subnets_list)
- limit_subnets_list = tolist(var.limit_subnets)
- limit_vpc_peer = join(",", local.limit_vpc_peer_list)
- limit_vpc_peer_list = tolist(var.limit_vpc_peer)
}
################################################
@@ -66,6 +49,7 @@ module "service-account-function" {
"${var.organization_id}" = [
"roles/compute.networkViewer",
"roles/monitoring.viewer",
+ "roles/cloudasset.viewer"
]
}
@@ -129,16 +113,9 @@ module "cloud-function" {
}
environment_variables = {
- LIMIT_INSTANCES = local.limit_instances
- LIMIT_INSTANCES_PPG = local.limit_instances_ppg
- LIMIT_L4 = local.limit_l4
- LIMIT_L4_PPG = local.limit_l4_ppg
- LIMIT_L7 = local.limit_l7
- LIMIT_L7_PPG = local.limit_l7_ppg
- LIMIT_SUBNETS = local.limit_subnets
- LIMIT_VPC_PEER = local.limit_vpc_peer
MONITORED_PROJECTS_LIST = local.projects
MONITORING_PROJECT_ID = module.project-monitoring.project_id
+ ORGANIZATION_ID = var.organization_id
}
service_account = module.service-account-function.email
diff --git a/examples/cloud-operations/network-dashboard/tests/test.tf b/examples/cloud-operations/network-dashboard/tests/test.tf
index 8161af65b..791d68b06 100644
--- a/examples/cloud-operations/network-dashboard/tests/test.tf
+++ b/examples/cloud-operations/network-dashboard/tests/test.tf
@@ -270,7 +270,6 @@ resource "google_compute_instance" "test-vm-hub1" {
}
# Forwarding Rules
-
resource "google_compute_forwarding_rule" "forwarding-rule-dev" {
count = 10
name = "forwarding-rule-dev${count.index}"
diff --git a/examples/cloud-operations/network-dashboard/variables.tf b/examples/cloud-operations/network-dashboard/variables.tf
index 7170a513f..7e4237ca8 100644
--- a/examples/cloud-operations/network-dashboard/variables.tf
+++ b/examples/cloud-operations/network-dashboard/variables.tf
@@ -75,69 +75,4 @@ variable "region" {
variable "zone" {
description = "Zone used to deploy vms"
default = "europe-west1-b"
-}
-
-variable "limit_l4" {
- description = "Maximum number of forwarding rules for Internal TCP/UDP Load Balancing per network."
- type = list(string)
- default = [
- "default_value", "75",
- ]
-}
-
-variable "limit_l7" {
- description = "Maximum number of forwarding rules for Internal HTTP(S) Load Balancing per network."
- type = list(string)
- default = [
- "default_value", "75",
- ]
-}
-
-variable "limit_subnets" {
- description = "Maximum number of subnet IP ranges (primary and secondary) per peering group"
- type = list(string)
- default = [
- "default_value", "400",
- ]
-}
-
-variable "limit_instances" {
- description = "Maximum number of instances per network"
- type = list(string)
- default = [
- "default_value", "15000",
- ]
-}
-
-variable "limit_instances_ppg" {
- description = "Maximum number of instances per peering group."
- type = list(string)
- default = [
- "default_value", "15000",
- ]
-}
-
-variable "limit_vpc_peer" {
- description = "Maximum number of peering VPC peerings per network."
- type = list(string)
- default = [
- "default_value", "25",
- "test-vpc", "40",
- ]
-}
-
-variable "limit_l4_ppg" {
- description = "Maximum number of forwarding rules for Internal TCP/UDP Load Balancing per network."
- type = list(string)
- default = [
- "default_value", "175",
- ]
-}
-
-variable "limit_l7_ppg" {
- description = "Maximum number of forwarding rules for Internal HTTP(S) Load Balancing per network."
- type = list(string)
- default = [
- "default_value", "175",
- ]
}
\ No newline at end of file
diff --git a/examples/serverless/api-gateway/function/package-lock.json b/examples/serverless/api-gateway/function/package-lock.json
index 6bf7ab5c1..da027c38b 100644
--- a/examples/serverless/api-gateway/function/package-lock.json
+++ b/examples/serverless/api-gateway/function/package-lock.json
@@ -896,9 +896,9 @@
}
},
"node_modules/minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"node_modules/ms": {
"version": "2.0.0",
@@ -2125,9 +2125,9 @@
}
},
"minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"ms": {
"version": "2.0.0",
diff --git a/fast/stages/02-networking-vpn/vpn-spoke-prod.tf b/fast/stages/02-networking-vpn/vpn-spoke-prod.tf
index ff635194c..3001c4ec9 100644
--- a/fast/stages/02-networking-vpn/vpn-spoke-prod.tf
+++ b/fast/stages/02-networking-vpn/vpn-spoke-prod.tf
@@ -82,7 +82,7 @@ module "landing-to-prod-ew4-vpn" {
source = "../../../modules/net-vpn-ha"
project_id = module.landing-project.project_id
network = module.landing-vpc.self_link
- region = "europe-west1"
+ region = "europe-west4"
name = "vpn-to-prod-ew4"
router_create = true
router_name = "landing-vpn-ew4"
@@ -112,7 +112,7 @@ module "prod-to-landing-ew4-vpn" {
source = "../../../modules/net-vpn-ha"
project_id = module.prod-spoke-project.project_id
network = module.prod-spoke-vpc.self_link
- region = "europe-west1"
+ region = "europe-west4"
name = "vpn-to-landing-ew4"
router_create = true
router_name = "prod-spoke-vpn-ew4"
diff --git a/modules/bigquery-dataset/README.md b/modules/bigquery-dataset/README.md
index 59a692415..139ef9a57 100644
--- a/modules/bigquery-dataset/README.md
+++ b/modules/bigquery-dataset/README.md
@@ -15,7 +15,7 @@ Access configuration defaults to using the separate `google_bigquery_dataset_acc
You can choose to manage the `google_bigquery_dataset` access rules instead via the `dataset_access` variable, but be sure to always have at least one `OWNER` access and to avoid duplicating accesses, or `terraform apply` will fail.
-The access variables are split into `access_roles` and `access_identities` variables, so that dynamic values can be passed in for identities (eg a service account email generated by a different module or resource). The `access_views` variable is separate, so as to allow proper type constraints.
+The access variables are split into `access` and `access_identities` variables, so that dynamic values can be passed in for identities (eg a service account email generated by a different module or resource).
```hcl
module "bigquery-dataset" {
@@ -54,8 +54,6 @@ module "bigquery-dataset" {
# tftest modules=1 resources=2
```
-roles/bigquery.dataOwner
-
### Dataset options
Dataset options are set via the `options` variable. all options must be specified, but a `null` value can be set to options that need to use defaults.
@@ -182,7 +180,7 @@ module "bigquery-dataset" {
| [id](variables.tf#L69) | Dataset id. | string | ✓ | |
| [project_id](variables.tf#L100) | Id of the project where datasets will be created. | string | ✓ | |
| [access](variables.tf#L17) | Map of access rules with role and identity type. Keys are arbitrary and must match those in the `access_identities` variable, types are `domain`, `group`, `special_group`, `user`, `view`. | map(object({…})) | | {} |
-| [access_identities](variables.tf#L33) | Map of access identities used for basic access roles. View identities have the format 'project_id|dataset_id|table_id'. | map(string) | | {} |
+| [access_identities](variables.tf#L33) | Map of access identities used for basic access roles. View identities have the format 'project_id\|dataset_id\|table_id'. | map(string) | | {} |
| [dataset_access](variables.tf#L39) | Set access in the dataset resource instead of using separate resources. | bool | | false |
| [description](variables.tf#L45) | Optional description. | string | | "Terraform managed." |
| [encryption_key](variables.tf#L51) | Self link of the KMS key that will be used to protect destination table. | string | | null |
diff --git a/modules/cloud-config-container/coredns/README.md b/modules/cloud-config-container/coredns/README.md
index 09cc44916..8099aee5c 100644
--- a/modules/cloud-config-container/coredns/README.md
+++ b/modules/cloud-config-container/coredns/README.md
@@ -77,8 +77,9 @@ module "cos-coredns" {
| [cloud_config](variables.tf#L17) | Cloud config template path. If null default will be used. | string | | null |
| [config_variables](variables.tf#L23) | Additional variables used to render the cloud-config and CoreDNS templates. | map(any) | | {} |
| [coredns_config](variables.tf#L29) | CoreDNS configuration path, if null default will be used. | string | | null |
-| [file_defaults](variables.tf#L35) | Default owner and permissions for files. | object({…}) | | {…} |
-| [files](variables.tf#L47) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | map(object({…})) | | {} |
+| [docker_logging](variables.tf#L35) | Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead. | bool | | true |
+| [file_defaults](variables.tf#L41) | Default owner and permissions for files. | object({…}) | | {…} |
+| [files](variables.tf#L53) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | map(object({…})) | | {} |
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | object({…}) | | null |
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | object({…}) | | {…} |
diff --git a/modules/cloud-config-container/coredns/cloud-config.yaml b/modules/cloud-config-container/coredns/cloud-config.yaml
index 0796fc6b9..1fe9a0043 100644
--- a/modules/cloud-config-container/coredns/cloud-config.yaml
+++ b/modules/cloud-config-container/coredns/cloud-config.yaml
@@ -58,7 +58,10 @@ write_files:
Wants=gcr-online.target docker.socket docker-events-collector.service
[Service]
ExecStart=/usr/bin/docker run --rm --name=coredns \
- --log-driver=gcplogs --network host \
+ %{~ if docker_logging ~}
+ --log-driver=gcplogs \
+ %{~ endif ~}
+ --network host \
-v /etc/coredns:/etc/coredns \
coredns/coredns -conf /etc/coredns/Corefile
ExecStop=/usr/bin/docker stop coredns
diff --git a/modules/cloud-config-container/coredns/main.tf b/modules/cloud-config-container/coredns/main.tf
index 789168ca4..422882963 100644
--- a/modules/cloud-config-container/coredns/main.tf
+++ b/modules/cloud-config-container/coredns/main.tf
@@ -16,8 +16,9 @@
locals {
cloud_config = templatefile(local.template, merge(var.config_variables, {
- corefile = templatefile(local.corefile, var.config_variables)
- files = local.files
+ corefile = templatefile(local.corefile, var.config_variables)
+ docker_logging = var.docker_logging
+ files = local.files
}))
corefile = (
var.coredns_config == null ? "${path.module}/Corefile" : var.coredns_config
diff --git a/modules/cloud-config-container/coredns/variables.tf b/modules/cloud-config-container/coredns/variables.tf
index c323017fc..bc9be06ef 100644
--- a/modules/cloud-config-container/coredns/variables.tf
+++ b/modules/cloud-config-container/coredns/variables.tf
@@ -32,6 +32,12 @@ variable "coredns_config" {
default = null
}
+variable "docker_logging" {
+ description = "Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead."
+ type = bool
+ default = true
+}
+
variable "file_defaults" {
description = "Default owner and permissions for files."
type = object({
diff --git a/modules/cloud-config-container/cos-generic-metadata/README.md b/modules/cloud-config-container/cos-generic-metadata/README.md
index 5a01b43ec..fef183862 100644
--- a/modules/cloud-config-container/cos-generic-metadata/README.md
+++ b/modules/cloud-config-container/cos-generic-metadata/README.md
@@ -64,7 +64,7 @@ module "cos-envoy" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [container_image](variables.tf#L42) | Container image. | string | ✓ | |
-| [authenticate_gcr](variables.tf#L112) | Setup docker to pull images from private GCR. Requires at least one user since the token is stored in the home of the first user defined. | bool | | false |
+| [authenticate_gcr](variables.tf#L118) | Setup docker to pull images from private GCR. Requires at least one user since the token is stored in the home of the first user defined. | bool | | false |
| [boot_commands](variables.tf#L17) | List of cloud-init `bootcmd`s. | list(string) | | [] |
| [cloud_config](variables.tf#L23) | Cloud config template path. If provided, takes precedence over all other arguments. | string | | null |
| [config_variables](variables.tf#L29) | Additional variables used to render the template passed via `cloud_config`. | map(any) | | {} |
@@ -72,11 +72,12 @@ module "cos-envoy" {
| [container_name](variables.tf#L47) | Name of the container to be run. | string | | "container" |
| [container_volumes](variables.tf#L53) | List of volumes. | list(object({…})) | | [] |
| [docker_args](variables.tf#L62) | Extra arguments to be passed for docker. | string | | null |
-| [file_defaults](variables.tf#L68) | Default owner and permissions for files. | object({…}) | | {…} |
-| [files](variables.tf#L80) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | map(object({…})) | | {} |
-| [gcp_logging](variables.tf#L90) | Should container logs be sent to Google Cloud Logging. | bool | | true |
-| [run_commands](variables.tf#L96) | List of cloud-init `runcmd`s. | list(string) | | [] |
-| [users](variables.tf#L102) | List of usernames to be created. If provided, first user will be used to run the container. | list(object({…})) | | […] |
+| [docker_logging](variables.tf#L68) | Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead. | bool | | true |
+| [file_defaults](variables.tf#L74) | Default owner and permissions for files. | object({…}) | | {…} |
+| [files](variables.tf#L86) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | map(object({…})) | | {} |
+| [gcp_logging](variables.tf#L96) | Should container logs be sent to Google Cloud Logging. | bool | | true |
+| [run_commands](variables.tf#L102) | List of cloud-init `runcmd`s. | list(string) | | [] |
+| [users](variables.tf#L108) | List of usernames to be created. If provided, first user will be used to run the container. | list(object({…})) | | […] |
## Outputs
diff --git a/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml b/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml
index fc75616a5..d516a1ded 100644
--- a/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml
+++ b/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml
@@ -44,26 +44,26 @@ write_files:
After=gcr-online.target docker.socket
Wants=gcr-online.target docker.socket docker-events-collector.service
[Service]
-%{ if authenticate_gcr && length(users) > 0 ~}
+ %{ if authenticate_gcr && length(users) > 0 ~}
Environment="HOME=/home/${users[0].username}"
ExecStartPre=/usr/bin/docker-credential-gcr configure-docker
-%{ endif ~}
+ %{ endif ~}
ExecStart=/usr/bin/docker run --rm --name=${container_name} \
-%{ if length(users) > 0 ~}
+ %{ if length(users) > 0 ~}
--user=${users[0].uid} \
-%{ endif ~}
-%{ if gcp_logging == true ~}
+ %{ endif ~}
+ %{~ if docker_logging ~}
--log-driver=gcplogs \
-%{ endif ~}
-%{ if docker_args != null ~}
+ %{~ endif ~}
+ %{~ if docker_args != null ~}
${docker_args} \
-%{ endif ~}
-%{ for volume in container_volumes ~}
+ %{~ endif ~}
+ %{ for volume in container_volumes ~}
-v ${volume.host}:${volume.container} \
-%{ endfor ~}
+ %{ endfor ~}
${container_image} ${container_args}
ExecStop=/usr/bin/docker stop ${container_name}
-%{ for path, data in files ~}
+ %{ for path, data in files ~}
- path: ${path}
owner: ${lookup(data, "owner", "root")}
permissions: ${lookup(data, "permissions", "0644")}
diff --git a/modules/cloud-config-container/cos-generic-metadata/main.tf b/modules/cloud-config-container/cos-generic-metadata/main.tf
index 5019fa097..835183f3d 100644
--- a/modules/cloud-config-container/cos-generic-metadata/main.tf
+++ b/modules/cloud-config-container/cos-generic-metadata/main.tf
@@ -22,6 +22,7 @@ locals {
container_name = var.container_name
container_volumes = var.container_volumes
docker_args = var.docker_args
+ docker_logging = var.docker_logging
files = local.files
gcp_logging = var.gcp_logging
run_commands = var.run_commands
diff --git a/modules/cloud-config-container/cos-generic-metadata/variables.tf b/modules/cloud-config-container/cos-generic-metadata/variables.tf
index e9aa051a0..b84842f57 100644
--- a/modules/cloud-config-container/cos-generic-metadata/variables.tf
+++ b/modules/cloud-config-container/cos-generic-metadata/variables.tf
@@ -65,6 +65,12 @@ variable "docker_args" {
default = null
}
+variable "docker_logging" {
+ description = "Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead."
+ type = bool
+ default = true
+}
+
variable "file_defaults" {
description = "Default owner and permissions for files."
type = object({
diff --git a/modules/cloud-config-container/envoy-traffic-director/README.md b/modules/cloud-config-container/envoy-traffic-director/README.md
index 4493e9ba7..c18df6e44 100644
--- a/modules/cloud-config-container/envoy-traffic-director/README.md
+++ b/modules/cloud-config-container/envoy-traffic-director/README.md
@@ -50,8 +50,8 @@ module "vm-cos" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
+| [docker_logging](variables.tf#L23) | Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead. | bool | | true |
| [envoy_image](variables.tf#L17) | Envoy Proxy container image to use. | string | | "envoyproxy/envoy:v1.14.1" |
-| [gcp_logging](variables.tf#L23) | Should container logs be sent to Google Cloud Logging. | bool | | true |
## Outputs
diff --git a/modules/cloud-config-container/envoy-traffic-director/main.tf b/modules/cloud-config-container/envoy-traffic-director/main.tf
index cdb805c6b..bc8bd7c3b 100644
--- a/modules/cloud-config-container/envoy-traffic-director/main.tf
+++ b/modules/cloud-config-container/envoy-traffic-director/main.tf
@@ -44,7 +44,7 @@ module "cos-envoy-td" {
}
}
- gcp_logging = var.gcp_logging
+ gcp_logging = var.docker_logging
run_commands = [
"iptables -t nat -N ENVOY_IN_REDIRECT",
diff --git a/modules/cloud-config-container/envoy-traffic-director/variables.tf b/modules/cloud-config-container/envoy-traffic-director/variables.tf
index b43b3c5ec..8135a48a1 100644
--- a/modules/cloud-config-container/envoy-traffic-director/variables.tf
+++ b/modules/cloud-config-container/envoy-traffic-director/variables.tf
@@ -20,8 +20,8 @@ variable "envoy_image" {
default = "envoyproxy/envoy:v1.14.1"
}
-variable "gcp_logging" {
- description = "Should container logs be sent to Google Cloud Logging."
+variable "docker_logging" {
+ description = "Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead."
type = bool
default = true
}
diff --git a/modules/cloud-config-container/mysql/README.md b/modules/cloud-config-container/mysql/README.md
index 4c99d5042..3dc4e7919 100644
--- a/modules/cloud-config-container/mysql/README.md
+++ b/modules/cloud-config-container/mysql/README.md
@@ -79,13 +79,14 @@ module "cos-mysql" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [mysql_password](variables.tf#L58) | MySQL root password. If an encrypted password is set, use the kms_config variable to specify KMS configuration. | string | ✓ | |
+| [mysql_password](variables.tf#L64) | MySQL root password. If an encrypted password is set, use the kms_config variable to specify KMS configuration. | string | ✓ | |
| [cloud_config](variables.tf#L17) | Cloud config template path. If null default will be used. | string | | null |
| [config_variables](variables.tf#L23) | Additional variables used to render the cloud-config template. | map(any) | | {} |
-| [image](variables.tf#L29) | MySQL container image. | string | | "mysql:5.7" |
-| [kms_config](variables.tf#L35) | Optional KMS configuration to decrypt passed-in password. Leave null if a plaintext password is used. | object({…}) | | null |
-| [mysql_config](variables.tf#L46) | MySQL configuration file content, if null container default will be used. | string | | null |
-| [mysql_data_disk](variables.tf#L52) | MySQL data disk name in /dev/disk/by-id/ including the google- prefix. If null the boot disk will be used for data. | string | | null |
+| [docker_logging](variables.tf#L29) | Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead. | bool | | true |
+| [image](variables.tf#L35) | MySQL container image. | string | | "mysql:5.7" |
+| [kms_config](variables.tf#L41) | Optional KMS configuration to decrypt passed-in password. Leave null if a plaintext password is used. | object({…}) | | null |
+| [mysql_config](variables.tf#L52) | MySQL configuration file content, if null container default will be used. | string | | null |
+| [mysql_data_disk](variables.tf#L58) | MySQL data disk name in /dev/disk/by-id/ including the google- prefix. If null the boot disk will be used for data. | string | | null |
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | object({…}) | | null |
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | object({…}) | | {…} |
diff --git a/modules/cloud-config-container/mysql/cloud-config.yaml b/modules/cloud-config-container/mysql/cloud-config.yaml
index 1c792a744..e3bf831f1 100644
--- a/modules/cloud-config-container/mysql/cloud-config.yaml
+++ b/modules/cloud-config-container/mysql/cloud-config.yaml
@@ -96,7 +96,9 @@ write_files:
ExecStartPre=/bin/chown -R 2000 /run/mysql/secrets /run/mysql/data
ExecStart=/usr/bin/docker run --rm --name=mysql \
--user 2000:2000 \
+ %{~ if docker_logging ~}
--log-driver=gcplogs \
+ %{~ endif ~}
--network host \
-e MYSQL_ROOT_PASSWORD_FILE=/etc/secrets/mysql-passwd.txt \
-v /run/mysql/secrets:/etc/secrets \
diff --git a/modules/cloud-config-container/mysql/main.tf b/modules/cloud-config-container/mysql/main.tf
index 4e44c4693..1dc3908d4 100644
--- a/modules/cloud-config-container/mysql/main.tf
+++ b/modules/cloud-config-container/mysql/main.tf
@@ -16,6 +16,7 @@
locals {
cloud_config = templatefile(local.template, merge(var.config_variables, {
+ docker_logging = var.docker_logging
image = var.image
kms_config = var.kms_config
mysql_config = var.mysql_config
diff --git a/modules/cloud-config-container/mysql/variables.tf b/modules/cloud-config-container/mysql/variables.tf
index 52bb3dbbd..d15ecfdd2 100644
--- a/modules/cloud-config-container/mysql/variables.tf
+++ b/modules/cloud-config-container/mysql/variables.tf
@@ -26,6 +26,12 @@ variable "config_variables" {
default = {}
}
+variable "docker_logging" {
+ description = "Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead."
+ type = bool
+ default = true
+}
+
variable "image" {
description = "MySQL container image."
type = string
diff --git a/modules/cloud-config-container/nginx/README.md b/modules/cloud-config-container/nginx/README.md
index c993eb72e..317f6b565 100644
--- a/modules/cloud-config-container/nginx/README.md
+++ b/modules/cloud-config-container/nginx/README.md
@@ -59,10 +59,11 @@ module "cos-nginx" {
|---|---|:---:|:---:|:---:|
| [cloud_config](variables.tf#L17) | Cloud config template path. If null default will be used. | string | | null |
| [config_variables](variables.tf#L23) | Additional variables used to render the cloud-config and Nginx templates. | map(any) | | {} |
-| [file_defaults](variables.tf#L41) | Default owner and permissions for files. | object({…}) | | {…} |
-| [files](variables.tf#L53) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | map(object({…})) | | {} |
-| [image](variables.tf#L29) | Nginx container image. | string | | "nginxdemos/hello:plain-text" |
-| [nginx_config](variables.tf#L35) | Nginx configuration path, if null container default will be used. | string | | null |
+| [docker_logging](variables.tf#L29) | Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead. | bool | | true |
+| [file_defaults](variables.tf#L47) | Default owner and permissions for files. | object({…}) | | {…} |
+| [files](variables.tf#L59) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | map(object({…})) | | {} |
+| [image](variables.tf#L35) | Nginx container image. | string | | "nginxdemos/hello:plain-text" |
+| [nginx_config](variables.tf#L41) | Nginx configuration path, if null container default will be used. | string | | null |
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | object({…}) | | null |
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | object({…}) | | {…} |
diff --git a/modules/cloud-config-container/nginx/cloud-config.yaml b/modules/cloud-config-container/nginx/cloud-config.yaml
index d061e0376..f7be84dfb 100644
--- a/modules/cloud-config-container/nginx/cloud-config.yaml
+++ b/modules/cloud-config-container/nginx/cloud-config.yaml
@@ -53,7 +53,10 @@ write_files:
Wants=gcr-online.target docker.socket docker-events-collector.service
[Service]
ExecStart=/usr/bin/docker run --rm --name=nginx \
- --log-driver=gcplogs --network host \
+ %{~ if docker_logging ~}
+ --log-driver=gcplogs \
+ %{~ endif ~}
+ --network host \
%{~ if etc_mount ~}
-v /etc/nginx/conf.d:/etc/nginx/conf.d \
%{~ endif ~}
diff --git a/modules/cloud-config-container/nginx/main.tf b/modules/cloud-config-container/nginx/main.tf
index a2fce41b8..688545d74 100644
--- a/modules/cloud-config-container/nginx/main.tf
+++ b/modules/cloud-config-container/nginx/main.tf
@@ -16,6 +16,7 @@
locals {
cloud_config = templatefile(local.template, merge(var.config_variables, {
+ docker_logging = var.docker_logging
etc_mount = (
var.nginx_config != null || length([
for name in keys(var.files) :
diff --git a/modules/cloud-config-container/nginx/variables.tf b/modules/cloud-config-container/nginx/variables.tf
index dec89cc2b..c0ad3f6e5 100644
--- a/modules/cloud-config-container/nginx/variables.tf
+++ b/modules/cloud-config-container/nginx/variables.tf
@@ -26,6 +26,12 @@ variable "config_variables" {
default = {}
}
+variable "docker_logging" {
+ description = "Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead."
+ type = bool
+ default = true
+}
+
variable "image" {
description = "Nginx container image."
type = string
diff --git a/modules/cloud-config-container/onprem/README.md b/modules/cloud-config-container/onprem/README.md
index 222d25b04..5033dcc97 100644
--- a/modules/cloud-config-container/onprem/README.md
+++ b/modules/cloud-config-container/onprem/README.md
@@ -81,3 +81,4 @@ module "on-prem" {
| [test_instance](outputs-instance.tf#L17) | Optional test instance name and address. | |
+
diff --git a/modules/cloud-config-container/squid/README.md b/modules/cloud-config-container/squid/README.md
index 912c52622..7f2f45db7 100644
--- a/modules/cloud-config-container/squid/README.md
+++ b/modules/cloud-config-container/squid/README.md
@@ -61,15 +61,16 @@ module "cos-squid" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [allow](variables.tf#L57) | List of domains Squid will allow connections to. | list(string) | | [] |
-| [clients](variables.tf#L69) | List of CIDR ranges from which Squid will allow connections. | list(string) | | [] |
+| [allow](variables.tf#L63) | List of domains Squid will allow connections to. | list(string) | | [] |
+| [clients](variables.tf#L75) | List of CIDR ranges from which Squid will allow connections. | list(string) | | [] |
| [cloud_config](variables.tf#L17) | Cloud config template path. If null default will be used. | string | | null |
| [config_variables](variables.tf#L23) | Additional variables used to render the cloud-config and Squid templates. | map(any) | | {} |
-| [default_action](variables.tf#L75) | Default action for domains not matching neither the allow or deny lists. | string | | "deny" |
-| [deny](variables.tf#L63) | List of domains Squid will deny connections to. | list(string) | | [] |
-| [file_defaults](variables.tf#L35) | Default owner and permissions for files. | object({…}) | | {…} |
-| [files](variables.tf#L47) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | map(object({…})) | | {} |
-| [squid_config](variables.tf#L29) | Squid configuration path, if null default will be used. | string | | null |
+| [default_action](variables.tf#L81) | Default action for domains not matching neither the allow or deny lists. | string | | "deny" |
+| [deny](variables.tf#L69) | List of domains Squid will deny connections to. | list(string) | | [] |
+| [docker_logging](variables.tf#L29) | Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead. | bool | | true |
+| [file_defaults](variables.tf#L41) | Default owner and permissions for files. | object({…}) | | {…} |
+| [files](variables.tf#L53) | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | map(object({…})) | | {} |
+| [squid_config](variables.tf#L35) | Squid configuration path, if null default will be used. | string | | null |
| [test_instance](variables-instance.tf#L17) | Test/development instance attributes, leave null to skip creation. | object({…}) | | null |
| [test_instance_defaults](variables-instance.tf#L30) | Test/development instance defaults used for optional configuration. If image is null, COS stable will be used. | object({…}) | | {…} |
diff --git a/modules/cloud-config-container/squid/cloud-config.yaml b/modules/cloud-config-container/squid/cloud-config.yaml
index b0c4b7fe3..8fef77b35 100644
--- a/modules/cloud-config-container/squid/cloud-config.yaml
+++ b/modules/cloud-config-container/squid/cloud-config.yaml
@@ -71,7 +71,10 @@ write_files:
Environment="HOME=/home/squid"
ExecStartPre=/usr/bin/docker-credential-gcr configure-docker
ExecStart=/usr/bin/docker run --rm --name=squid \
- --log-driver=gcplogs --network host \
+ %{~ if docker_logging ~}
+ --log-driver=gcplogs \
+ %{~ endif ~}
+ --network host \
-v /etc/squid:/etc/squid \
gcr.io/pso-cft-fabric/squid:0.10
ExecStop=/usr/bin/docker stop squid
diff --git a/modules/cloud-config-container/squid/main.tf b/modules/cloud-config-container/squid/main.tf
index ad895c178..81538c60b 100644
--- a/modules/cloud-config-container/squid/main.tf
+++ b/modules/cloud-config-container/squid/main.tf
@@ -16,8 +16,9 @@
locals {
cloud_config = templatefile(local.template, merge(local.config_variables, {
- squid_config = templatefile(local.squid_config, local.config_variables)
- files = local.files
+ docker_logging = var.docker_logging
+ squid_config = templatefile(local.squid_config, local.config_variables)
+ files = local.files
}))
squid_config = (
var.squid_config == null ? "${path.module}/squid.conf" : var.squid_config
diff --git a/modules/cloud-config-container/squid/variables.tf b/modules/cloud-config-container/squid/variables.tf
index 5180c6d32..6e65e779d 100644
--- a/modules/cloud-config-container/squid/variables.tf
+++ b/modules/cloud-config-container/squid/variables.tf
@@ -26,6 +26,12 @@ variable "config_variables" {
default = {}
}
+variable "docker_logging" {
+ description = "Log via the Docker gcplogs driver. Disable if you use the legacy Logging Agent instead."
+ type = bool
+ default = true
+}
+
variable "squid_config" {
description = "Squid configuration path, if null default will be used."
type = string
diff --git a/modules/cloud-function/README.md b/modules/cloud-function/README.md
index 46a5b4586..6eac68bf1 100644
--- a/modules/cloud-function/README.md
+++ b/modules/cloud-function/README.md
@@ -169,7 +169,7 @@ module "cf-http" {
| [environment_variables](variables.tf#L46) | Cloud function environment variables. | map(string) | | {} |
| [function_config](variables.tf#L52) | Cloud function configuration. | object({…}) | | {…} |
| [iam](variables.tf#L70) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} |
-| [ingress_settings](variables.tf#L76) | Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL and ALLOW_INTERNAL_ONLY. | string | | null |
+| [ingress_settings](variables.tf#L76) | Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL, ALLOW_INTERNAL_AND_GCLB and ALLOW_INTERNAL_ONLY . | string | | null |
| [labels](variables.tf#L82) | Resource labels. | map(string) | | {} |
| [prefix](variables.tf#L93) | Optional prefix used for resource names. | string | | null |
| [region](variables.tf#L104) | Region used for all resources. | string | | "europe-west1" |
diff --git a/modules/cloud-function/main.tf b/modules/cloud-function/main.tf
index 3a37a63f1..949cb69b1 100644
--- a/modules/cloud-function/main.tf
+++ b/modules/cloud-function/main.tf
@@ -103,9 +103,10 @@ resource "google_cloudfunctions_function_iam_binding" "default" {
}
resource "google_storage_bucket" "bucket" {
- count = var.bucket_config == null ? 0 : 1
- project = var.project_id
- name = "${local.prefix}${var.bucket_name}"
+ count = var.bucket_config == null ? 0 : 1
+ project = var.project_id
+ name = "${local.prefix}${var.bucket_name}"
+ uniform_bucket_level_access = true
location = (
var.bucket_config.location == null
? var.region
@@ -117,7 +118,17 @@ resource "google_storage_bucket" "bucket" {
for_each = var.bucket_config.lifecycle_delete_age == null ? [] : [""]
content {
action { type = "Delete" }
- condition { age = var.bucket_config.lifecycle_delete_age }
+ condition {
+ age = var.bucket_config.lifecycle_delete_age
+ with_state = "ARCHIVED"
+ }
+ }
+ }
+
+ dynamic "versioning" {
+ for_each = var.bucket_config.lifecycle_delete_age == null ? [] : [""]
+ content {
+ enabled = true
}
}
}
diff --git a/modules/cloud-function/variables.tf b/modules/cloud-function/variables.tf
index 2ac663b13..a613b2f68 100644
--- a/modules/cloud-function/variables.tf
+++ b/modules/cloud-function/variables.tf
@@ -74,7 +74,7 @@ variable "iam" {
}
variable "ingress_settings" {
- description = "Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL and ALLOW_INTERNAL_ONLY."
+ description = "Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL, ALLOW_INTERNAL_AND_GCLB and ALLOW_INTERNAL_ONLY ."
type = string
default = null
}
diff --git a/tools/tfdoc.py b/tools/tfdoc.py
index 68bbe00cc..b4d36fb55 100755
--- a/tools/tfdoc.py
+++ b/tools/tfdoc.py
@@ -206,7 +206,7 @@ def parse_variables(basepath, exclude_files=None):
except (IOError, OSError) as e:
raise SystemExit(f'Cannot open variables file {shortname}.')
for item in _parse(body):
- description = ''.join(item['description'])
+ description = (''.join(item['description'])).replace('|', '\\|')
vtype = '\n'.join(item['type'])
default = HEREDOC_RE.sub(r'\1', '\n'.join(item['default']))
required = not item['default']