added support 2nd generation cloud function (#872)
* added support 2nd generation cloud function * changed function_version to a simple boolean v2 removed memory_2ndGen * will use the var.v2 to add the invoker role * removed the list uisng compact and formated the code * formated the code and added conditional feature * formated the code * added formating * resolved the merge conflict * Update readme * Create local function object * added secret_volumes and secret_environment_variables for CF V2 Co-authored-by: Julio Castillo <jccb@google.com>
This commit is contained in:
parent
d885372f4e
commit
a12da693a3
|
@ -12,7 +12,7 @@
|
|||
# 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.
|
||||
#
|
||||
# CFv2 define whether to use Cloud function 2nd generation or 1st generation
|
||||
|
||||
from distutils.command.config import config
|
||||
import os
|
||||
|
@ -22,16 +22,20 @@ from google.protobuf import field_mask_pb2
|
|||
from googleapiclient import discovery
|
||||
from metrics import ilb_fwrules, instances, networks, metrics, limits, peerings, routes, subnets, vpc_firewalls
|
||||
|
||||
CFv2 = False
|
||||
if CFv2:
|
||||
import functions_framework
|
||||
|
||||
|
||||
def get_monitored_projects_list(config):
|
||||
'''
|
||||
Gets the projects to be monitored from the MONITORED_FOLDERS_LIST environment variable.
|
||||
Gets the projects to be monitored from the MONITORED_FOLDERS_LIST environment variable.
|
||||
|
||||
Parameters:
|
||||
config (dict): The dict containing config like clients and limits
|
||||
Returns:
|
||||
monitored_projects (List of strings): Full list of projects to be monitored
|
||||
'''
|
||||
Parameters:
|
||||
config (dict): The dict containing config like clients and limits
|
||||
Returns:
|
||||
monitored_projects (List of strings): Full list of projects to be monitored
|
||||
'''
|
||||
monitored_projects = config["monitored_projects"]
|
||||
monitored_folders = [] #os.environ.get("MONITORED_FOLDERS_LIST").split(",")
|
||||
|
||||
|
@ -68,10 +72,10 @@ def get_monitored_projects_list(config):
|
|||
|
||||
def monitoring_interval():
|
||||
'''
|
||||
Creates the monitoring interval of 24 hours
|
||||
Returns:
|
||||
monitoring_v3.TimeInterval: Monitoring time interval of 24h
|
||||
'''
|
||||
Creates the monitoring interval of 24 hours
|
||||
Returns:
|
||||
monitoring_v3.TimeInterval: Monitoring time interval of 24h
|
||||
'''
|
||||
now = time.time()
|
||||
seconds = int(now)
|
||||
nanos = int((now - seconds) * 10**9)
|
||||
|
@ -124,13 +128,13 @@ config = {
|
|||
|
||||
def main(event, context):
|
||||
'''
|
||||
Cloud Function Entry point, called by the scheduler.
|
||||
Parameters:
|
||||
event: Not used for now (Pubsub trigger)
|
||||
context: Not used for now (Pubsub trigger)
|
||||
Returns:
|
||||
'Function executed successfully'
|
||||
'''
|
||||
Cloud Function Entry point, called by the scheduler.
|
||||
Parameters:
|
||||
event: Not used for now (Pubsub trigger)
|
||||
context: Not used for now (Pubsub trigger)
|
||||
Returns:
|
||||
'Function executed successfully'
|
||||
'''
|
||||
# Handling empty monitored projects list
|
||||
if config["monitored_projects"] == ['']:
|
||||
config["monitored_projects"] = []
|
||||
|
@ -203,5 +207,11 @@ def main(event, context):
|
|||
return 'Function executed successfully'
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(None, None)
|
||||
if CFv2:
|
||||
|
||||
@functions_framework.http
|
||||
def main_http(request):
|
||||
main(None, None)
|
||||
else:
|
||||
if __name__ == "__main__":
|
||||
main(None, None)
|
|
@ -7,4 +7,5 @@ google-cloud-monitoring==2.9.1
|
|||
oauth2client==4.1.3
|
||||
google-api-core==2.7.0
|
||||
PyYAML==6.0
|
||||
google-cloud-asset==3.8.1
|
||||
google-cloud-asset==3.8.1
|
||||
functions-framework==3.*
|
|
@ -50,6 +50,8 @@ module "service-account-function" {
|
|||
# Required IAM permissions for this service account are:
|
||||
# 1) compute.networkViewer on projects to be monitored (I gave it at organization level for now for simplicity)
|
||||
# 2) monitoring viewer on the projects to be monitored (I gave it at organization level for now for simplicity)
|
||||
# 3) if you dont have permission to create service account and assign permission at organization Level, move these 3 roles to project level.
|
||||
|
||||
iam_organization_roles = {
|
||||
"${var.organization_id}" = [
|
||||
"roles/compute.networkViewer",
|
||||
|
@ -59,17 +61,20 @@ module "service-account-function" {
|
|||
}
|
||||
|
||||
iam_project_roles = {
|
||||
"${local.monitoring_project}" = [
|
||||
"roles/monitoring.metricWriter"
|
||||
]
|
||||
"${local.monitoring_project}" = compact([
|
||||
"roles/monitoring.metricWriter",
|
||||
var.v2 ? "roles/run.invoker" : ""
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
################################################
|
||||
# Cloud Function configuration (& Scheduler) #
|
||||
# you can comment out the pub/sub call in case of 2nd generation function
|
||||
################################################
|
||||
|
||||
module "pubsub" {
|
||||
|
||||
source = "../../../modules/pubsub"
|
||||
project_id = local.monitoring_project
|
||||
name = "network-dashboard-pubsub"
|
||||
|
@ -81,6 +86,7 @@ module "pubsub" {
|
|||
}
|
||||
|
||||
resource "google_cloud_scheduler_job" "job" {
|
||||
count = var.v2 ? 0 : 1
|
||||
project = local.monitoring_project
|
||||
region = var.region
|
||||
name = "network-dashboard-scheduler"
|
||||
|
@ -92,9 +98,28 @@ resource "google_cloud_scheduler_job" "job" {
|
|||
data = base64encode("test")
|
||||
}
|
||||
}
|
||||
#http trigger for 2nd generation function
|
||||
|
||||
resource "google_cloud_scheduler_job" "job_httptrigger" {
|
||||
count = var.v2 ? 1 : 0
|
||||
project = local.monitoring_project
|
||||
region = var.region
|
||||
name = "network-dashboard-scheduler"
|
||||
schedule = var.schedule_cron
|
||||
time_zone = "UTC"
|
||||
|
||||
http_target {
|
||||
http_method = "POST"
|
||||
uri = module.cloud-function.uri
|
||||
|
||||
oidc_token {
|
||||
service_account_email = module.service-account-function.email
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module "cloud-function" {
|
||||
v2 = var.v2
|
||||
source = "../../../modules/cloud-function"
|
||||
project_id = local.monitoring_project
|
||||
name = "network-dashboard-cloud-function"
|
||||
|
@ -115,7 +140,8 @@ module "cloud-function" {
|
|||
entry_point = "main"
|
||||
runtime = "python39"
|
||||
instances = 1
|
||||
memory = 256
|
||||
memory = 256 # Memory in MB
|
||||
|
||||
}
|
||||
|
||||
environment_variables = {
|
||||
|
|
|
@ -69,4 +69,9 @@ variable "project_monitoring_services" {
|
|||
variable "region" {
|
||||
description = "Region used to deploy the cloud functions and scheduler"
|
||||
default = "europe-west1"
|
||||
}
|
||||
variable "v2" {
|
||||
description = "Whether to use Cloud Function version 2nd Gen or 1st Gen."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
|
@ -167,7 +167,7 @@ module "cf-http" {
|
|||
| [bucket_config](variables.tf#L17) | Enable and configure auto-created bucket. Set fields to null to use defaults. | <code title="object({ location = string lifecycle_delete_age = number })">object({…})</code> | | <code>null</code> |
|
||||
| [description](variables.tf#L40) | Optional description. | <code>string</code> | | <code>"Terraform managed."</code> |
|
||||
| [environment_variables](variables.tf#L46) | Cloud function environment variables. | <code>map(string)</code> | | <code>{}</code> |
|
||||
| [function_config](variables.tf#L52) | Cloud function configuration. | <code title="object({ entry_point = string instances = number memory = number runtime = string timeout = number })">object({…})</code> | | <code title="{ entry_point = "main" instances = 1 memory = 256 runtime = "python37" timeout = 180 }">{…}</code> |
|
||||
| [function_config](variables.tf#L52) | Cloud function configuration. | <code title="object({ entry_point = string instances = number memory = number # Memory in MB runtime = string timeout = number })">object({…})</code> | | <code title="{ entry_point = "main" instances = 1 memory = 256 runtime = "python37" timeout = 180 }">{…}</code> |
|
||||
| [iam](variables.tf#L70) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [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 . | <code>string</code> | | <code>null</code> |
|
||||
| [labels](variables.tf#L82) | Resource labels. | <code>map(string)</code> | | <code>{}</code> |
|
||||
|
@ -177,6 +177,7 @@ module "cf-http" {
|
|||
| [service_account](variables.tf#L122) | Service account email. Unused if service account is auto-created. | <code>string</code> | | <code>null</code> |
|
||||
| [service_account_create](variables.tf#L128) | Auto-create service account. | <code>bool</code> | | <code>false</code> |
|
||||
| [trigger_config](variables.tf#L134) | Function trigger configuration. Leave null for HTTP trigger. | <code title="object({ event = string resource = string retry = bool })">object({…})</code> | | <code>null</code> |
|
||||
| [v2](variables.tf#L163) | Whether to use Cloud Function version 2nd Gen or 1st Gen. | <code>bool</code> | | <code>false</code> |
|
||||
| [vpc_connector](variables.tf#L144) | VPC connector configuration. Set create to 'true' if a new connector needs to be created. | <code title="object({ create = bool name = string egress_settings = string })">object({…})</code> | | <code>null</code> |
|
||||
| [vpc_connector_config](variables.tf#L154) | VPC connector network configuration. Must be provided if new VPC connector is being created. | <code title="object({ ip_cidr_range = string network = string })">object({…})</code> | | <code>null</code> |
|
||||
|
||||
|
@ -188,9 +189,10 @@ module "cf-http" {
|
|||
| [bucket_name](outputs.tf#L24) | Bucket name. | |
|
||||
| [function](outputs.tf#L29) | Cloud function resources. | |
|
||||
| [function_name](outputs.tf#L34) | Cloud function name. | |
|
||||
| [service_account](outputs.tf#L39) | Service account resource. | |
|
||||
| [service_account_email](outputs.tf#L44) | Service account email. | |
|
||||
| [service_account_iam_email](outputs.tf#L49) | Service account email. | |
|
||||
| [vpc_connector](outputs.tf#L57) | VPC connector resource if created. | |
|
||||
| [service_account](outputs.tf#L42) | Service account resource. | |
|
||||
| [service_account_email](outputs.tf#L47) | Service account email. | |
|
||||
| [service_account_iam_email](outputs.tf#L52) | Service account email. | |
|
||||
| [uri](outputs.tf#L38) | Cloud function service uri. | |
|
||||
| [vpc_connector](outputs.tf#L60) | VPC connector resource if created. | |
|
||||
|
||||
<!-- END TFDOC -->
|
||||
|
|
|
@ -24,6 +24,11 @@ locals {
|
|||
: null
|
||||
)
|
||||
)
|
||||
function = (
|
||||
var.v2
|
||||
? google_cloudfunctions2_function.function[0]
|
||||
: google_cloudfunctions_function.function[0]
|
||||
)
|
||||
prefix = var.prefix == null ? "" : "${var.prefix}-"
|
||||
service_account_email = (
|
||||
var.service_account_create
|
||||
|
@ -55,6 +60,7 @@ resource "google_vpc_access_connector" "connector" {
|
|||
}
|
||||
|
||||
resource "google_cloudfunctions_function" "function" {
|
||||
count = var.v2 ? 0 : 1
|
||||
project = var.project_id
|
||||
region = var.region
|
||||
name = "${local.prefix}${var.name}"
|
||||
|
@ -122,11 +128,74 @@ resource "google_cloudfunctions_function" "function" {
|
|||
|
||||
}
|
||||
|
||||
resource "google_cloudfunctions2_function" "function" {
|
||||
count = var.v2 ? 1 : 0
|
||||
provider = google-beta
|
||||
project = var.project_id
|
||||
location = var.region
|
||||
name = "${local.prefix}${var.name}"
|
||||
description = var.description
|
||||
build_config {
|
||||
runtime = var.function_config.runtime
|
||||
entry_point = "${var.function_config.entry_point}_http" # Set the entry point
|
||||
environment_variables = var.environment_variables
|
||||
source {
|
||||
storage_source {
|
||||
bucket = google_storage_bucket.bucket[0].name
|
||||
object = google_storage_bucket_object.bundle.name
|
||||
}
|
||||
}
|
||||
}
|
||||
service_config {
|
||||
max_instance_count = var.function_config.instances
|
||||
min_instance_count = 0
|
||||
available_memory = "${var.function_config.memory}M"
|
||||
timeout_seconds = var.function_config.timeout
|
||||
environment_variables = var.environment_variables
|
||||
ingress_settings = var.ingress_settings
|
||||
all_traffic_on_latest_revision = true
|
||||
service_account_email = local.service_account_email
|
||||
vpc_connector = local.vpc_connector
|
||||
vpc_connector_egress_settings = try(
|
||||
var.vpc_connector.egress_settings, null)
|
||||
|
||||
dynamic "secret_environment_variables" {
|
||||
for_each = { for k, v in var.secrets : k => v if !v.is_volume }
|
||||
iterator = secret
|
||||
content {
|
||||
key = secret.key
|
||||
project_id = secret.value.project_id
|
||||
secret = secret.value.secret
|
||||
version = try(secret.value.versions.0, "latest")
|
||||
}
|
||||
}
|
||||
|
||||
dynamic "secret_volumes" {
|
||||
for_each = { for k, v in var.secrets : k => v if v.is_volume }
|
||||
iterator = secret
|
||||
content {
|
||||
mount_path = secret.key
|
||||
project_id = secret.value.project_id
|
||||
secret = secret.value.secret
|
||||
dynamic "versions" {
|
||||
for_each = secret.value.versions
|
||||
iterator = version
|
||||
content {
|
||||
path = split(":", version)[1]
|
||||
version = split(":", version)[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
labels = var.labels
|
||||
}
|
||||
|
||||
resource "google_cloudfunctions_function_iam_binding" "default" {
|
||||
for_each = var.iam
|
||||
project = var.project_id
|
||||
region = var.region
|
||||
cloud_function = google_cloudfunctions_function.function.name
|
||||
cloud_function = local.function.name
|
||||
role = each.key
|
||||
members = each.value
|
||||
}
|
||||
|
|
|
@ -28,14 +28,17 @@ output "bucket_name" {
|
|||
|
||||
output "function" {
|
||||
description = "Cloud function resources."
|
||||
value = google_cloudfunctions_function.function
|
||||
value = local.function
|
||||
}
|
||||
|
||||
output "function_name" {
|
||||
description = "Cloud function name."
|
||||
value = google_cloudfunctions_function.function.name
|
||||
value = local.function.name
|
||||
}
|
||||
output "uri" {
|
||||
description = "Cloud function service uri."
|
||||
value = var.v2 ? google_cloudfunctions2_function.function[0].service_config[0].uri : null
|
||||
}
|
||||
|
||||
output "service_account" {
|
||||
description = "Service account resource."
|
||||
value = try(google_service_account.service_account[0], null)
|
||||
|
|
|
@ -54,7 +54,7 @@ variable "function_config" {
|
|||
type = object({
|
||||
entry_point = string
|
||||
instances = number
|
||||
memory = number
|
||||
memory = number # Memory in MB
|
||||
runtime = string
|
||||
timeout = number
|
||||
})
|
||||
|
@ -160,3 +160,9 @@ variable "vpc_connector_config" {
|
|||
default = null
|
||||
}
|
||||
|
||||
variable "v2" {
|
||||
description = "Whether to use Cloud Function version 2nd Gen or 1st Gen."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue