cloud-foundation-fabric/blueprints/cloud-operations/network-dashboard/cloud-function/metrics/networks.py

161 lines
5.3 KiB
Python

#
# 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.
#
from code import interact
from collections import defaultdict
from google.protobuf import field_mask_pb2
from googleapiclient import errors
import http
def get_subnet_ranges_dict(config: dict):
'''
Calls the Asset Inventory API to get all Subnet ranges under the GCP organization.
Parameters:
config (dict): The dict containing config like clients and limits
Returns:
subnet_range_dict (dictionary of string: int): Keys are the network links and values are the number of subnet ranges per network.
'''
subnet_range_dict = defaultdict(int)
read_mask = field_mask_pb2.FieldMask()
read_mask.FromJsonString('name,versionedResources')
response = config["clients"]["asset_client"].search_all_resources(
request={
"scope": f"organizations/{config['organization']}",
"asset_types": ["compute.googleapis.com/Subnetwork"],
"read_mask": read_mask,
"page_size": config["page_size"],
})
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 get_networks(config, project_id):
'''
Returns a dictionary of all networks in a project.
Parameters:
config (dict): The dict containing config like clients and limits
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 = config["clients"]["discovery_client"].networks().list(
project=project_id)
response = request.execute()
network_dict = []
if 'items' in response:
for network in response['items']:
network_name = network['name']
network_id = network['id']
self_link = network['selfLink']
d = {
'project_id': project_id,
'network_name': network_name,
'network_id': network_id,
'self_link': self_link
}
network_dict.append(d)
return network_dict
def get_network_id(config, project_id, network_name):
'''
Returns the network_id for a specific project / network name.
Parameters:
config (dict): The dict containing config like clients and limits
project_id (string): Project ID for the project containing the networks.
network_name (string): Name of the network
Returns:
network_id (int): Network ID.
'''
request = config["clients"]["discovery_client"].networks().list(
project=project_id)
try:
response = request.execute()
except errors.HttpError as err:
# TODO: log proper warning
if err.resp.status == http.HTTPStatus.FORBIDDEN:
print(
f"Warning: error reading networks for {project_id}. " +
f"This can happen if you don't have permissions on the project, for example if the project is in another organization or a Google managed project"
)
else:
print(f"Warning: error reading networks for {project_id}: {err}")
return 0
network_id = 0
if 'items' in response:
for network in response['items']:
if network['name'] == network_name:
network_id = network['id']
break
if network_id == 0:
print(f"Error: network_id not found for {network_name} in {project_id}")
return network_id
def get_limit_network(network_dict, network_link, quota_limit, limit_dict):
'''
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.
network_link (string): Contains network link
quota_limit (list of dictionaries of string: string): Current quota limit for all networks in that project.
limit_dict (dictionary of string:int): Dictionary with the network link as key and the limit as value
Returns:
limit (int): Current limit for that network.
'''
if quota_limit:
for net in quota_limit:
if net['network_id'] == network_dict['network_id']:
return net['value']
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