Skip to content

Commit

Permalink
added support 2nd generation cloud function (#872)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
som-nitjsr and juliocc committed Oct 13, 2022
1 parent d885372 commit a12da69
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -22,16 +22,20 @@
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(",")

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -124,13 +128,13 @@ def monitoring_interval():

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"] = []
Expand Down Expand Up @@ -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)
Original file line number Diff line number Diff line change
Expand Up @@ -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.*
34 changes: 30 additions & 4 deletions blueprints/cloud-operations/network-dashboard/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"
Expand All @@ -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"
Expand All @@ -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"
Expand All @@ -115,7 +140,8 @@ module "cloud-function" {
entry_point = "main"
runtime = "python39"
instances = 1
memory = 256
memory = 256 # Memory in MB

}

environment_variables = {
Expand Down
5 changes: 5 additions & 0 deletions blueprints/cloud-operations/network-dashboard/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
12 changes: 7 additions & 5 deletions modules/cloud-function/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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&#40;&#123;&#10; location &#61; string&#10; lifecycle_delete_age &#61; number&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [description](variables.tf#L40) | Optional description. | <code>string</code> | | <code>&#34;Terraform managed.&#34;</code> |
| [environment_variables](variables.tf#L46) | Cloud function environment variables. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [function_config](variables.tf#L52) | Cloud function configuration. | <code title="object&#40;&#123;&#10; entry_point &#61; string&#10; instances &#61; number&#10; memory &#61; number&#10; runtime &#61; string&#10; timeout &#61; number&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; entry_point &#61; &#34;main&#34;&#10; instances &#61; 1&#10; memory &#61; 256&#10; runtime &#61; &#34;python37&#34;&#10; timeout &#61; 180&#10;&#125;">&#123;&#8230;&#125;</code> |
| [function_config](variables.tf#L52) | Cloud function configuration. | <code title="object&#40;&#123;&#10; entry_point &#61; string&#10; instances &#61; number&#10; memory &#61; number &#35; Memory in MB&#10; runtime &#61; string&#10; timeout &#61; number&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; entry_point &#61; &#34;main&#34;&#10; instances &#61; 1&#10; memory &#61; 256&#10; runtime &#61; &#34;python37&#34;&#10; timeout &#61; 180&#10;&#125;">&#123;&#8230;&#125;</code> |
| [iam](variables.tf#L70) | IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</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&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
Expand All @@ -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&#40;&#123;&#10; event &#61; string&#10; resource &#61; string&#10; retry &#61; bool&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</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&#40;&#123;&#10; create &#61; bool&#10; name &#61; string&#10; egress_settings &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</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&#40;&#123;&#10; ip_cidr_range &#61; string&#10; network &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |

Expand All @@ -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 -->
71 changes: 70 additions & 1 deletion modules/cloud-function/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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}"
Expand Down Expand Up @@ -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
}
Expand Down
9 changes: 6 additions & 3 deletions modules/cloud-function/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 7 additions & 1 deletion modules/cloud-function/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
})
Expand Down Expand Up @@ -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
}

0 comments on commit a12da69

Please sign in to comment.