Merge branch 'master' into serverless-program

This commit is contained in:
Julio Diez 2023-05-05 19:42:59 +02:00 committed by GitHub
commit 76ce3e8b3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1083 additions and 13 deletions

View File

@ -75,3 +75,8 @@ jobs:
tools/*.py \
blueprints/cloud-operations/network-dashboard/src/*py \
blueprints/cloud-operations/network-dashboard/src/plugins/*py
- name: Check blueprint metadata
id: metadata
run: |
python tools/validate_metadata.py -v blueprints

View File

@ -129,7 +129,7 @@ spec:
type: string
default: null
required: false
- name: service_encryption_keys
- name: service_encryption_keys
description: Cloud KMS to use to encrypt different services. Key location should match service region.
type: |-
object({

View File

@ -247,9 +247,9 @@ module "gke" {
|---|---|:---:|:---:|:---:|
| [billing_account_id](variables.tf#L17) | Billing account id. | <code>string</code> | ✓ | |
| [folder_id](variables.tf#L132) | Folder used for the GKE project in folders/nnnnnnnnnnn format. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L179) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L188) | ID of the project that will contain all the clusters. | <code>string</code> | ✓ | |
| [vpc_config](variables.tf#L200) | Shared VPC project and VPC details. | <code title="object&#40;&#123;&#10; host_project_id &#61; string&#10; vpc_self_link &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [prefix](variables.tf#L183) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L192) | ID of the project that will contain all the clusters. | <code>string</code> | ✓ | |
| [vpc_config](variables.tf#L204) | Shared VPC project and VPC details. | <code title="object&#40;&#123;&#10; host_project_id &#61; string&#10; vpc_self_link &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [clusters](variables.tf#L22) | Clusters configuration. Refer to the gke-cluster module for type details. | <code title="map&#40;object&#40;&#123;&#10; cluster_autoscaling &#61; optional&#40;any&#41;&#10; description &#61; optional&#40;string&#41;&#10; enable_addons &#61; optional&#40;any, &#123;&#10; horizontal_pod_autoscaling &#61; true, http_load_balancing &#61; true&#10; &#125;&#41;&#10; enable_features &#61; optional&#40;any, &#123;&#10; workload_identity &#61; true&#10; &#125;&#41;&#10; issue_client_certificate &#61; optional&#40;bool, false&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; location &#61; string&#10; logging_config &#61; optional&#40;list&#40;string&#41;, &#91;&#34;SYSTEM_COMPONENTS&#34;&#93;&#41;&#10; maintenance_config &#61; optional&#40;any, &#123;&#10; daily_window_start_time &#61; &#34;03:00&#34;&#10; recurring_window &#61; null&#10; maintenance_exclusion &#61; &#91;&#93;&#10; &#125;&#41;&#10; max_pods_per_node &#61; optional&#40;number, 110&#41;&#10; min_master_version &#61; optional&#40;string&#41;&#10; monitoring_config &#61; optional&#40;object&#40;&#123;&#10; enable_components &#61; optional&#40;list&#40;string&#41;, &#91;&#34;SYSTEM_COMPONENTS&#34;&#93;&#41;&#10; managed_prometheus &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; node_locations &#61; optional&#40;list&#40;string&#41;&#41;&#10; private_cluster_config &#61; optional&#40;any&#41;&#10; release_channel &#61; optional&#40;string&#41;&#10; vpc_config &#61; object&#40;&#123;&#10; subnetwork &#61; string&#10; network &#61; optional&#40;string&#41;&#10; secondary_range_blocks &#61; optional&#40;object&#40;&#123;&#10; pods &#61; string&#10; services &#61; string&#10; &#125;&#41;&#41;&#10; secondary_range_names &#61; optional&#40;object&#40;&#123;&#10; pods &#61; string&#10; services &#61; string&#10; &#125;&#41;, &#123; pods &#61; &#34;pods&#34;, services &#61; &#34;services&#34; &#125;&#41;&#10; master_authorized_ranges &#61; optional&#40;map&#40;string&#41;&#41;&#10; master_ipv4_cidr_block &#61; optional&#40;string&#41;&#10; &#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [fleet_configmanagement_clusters](variables.tf#L70) | Config management features enabled on specific sets of member clusters, in config name => [cluster name] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [fleet_configmanagement_templates](variables.tf#L77) | Sets of config management configurations that can be applied to member clusters, in config name => {options} format. | <code title="map&#40;object&#40;&#123;&#10; binauthz &#61; bool&#10; config_sync &#61; object&#40;&#123;&#10; git &#61; object&#40;&#123;&#10; gcp_service_account_email &#61; string&#10; https_proxy &#61; string&#10; policy_dir &#61; string&#10; secret_type &#61; string&#10; sync_branch &#61; string&#10; sync_repo &#61; string&#10; sync_rev &#61; string&#10; sync_wait_secs &#61; number&#10; &#125;&#41;&#10; prevent_drift &#61; string&#10; source_format &#61; string&#10; &#125;&#41;&#10; hierarchy_controller &#61; object&#40;&#123;&#10; enable_hierarchical_resource_quota &#61; bool&#10; enable_pod_tree_labels &#61; bool&#10; &#125;&#41;&#10; policy_controller &#61; object&#40;&#123;&#10; audit_interval_seconds &#61; number&#10; exemptable_namespaces &#61; list&#40;string&#41;&#10; log_denies_enabled &#61; bool&#10; referential_rules_enabled &#61; bool&#10; template_library_installed &#61; bool&#10; &#125;&#41;&#10; version &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
@ -258,8 +258,8 @@ module "gke" {
| [group_iam](variables.tf#L137) | Project-level IAM bindings for groups. Use group emails as keys, list of roles as values. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [iam](variables.tf#L144) | Project-level authoritative IAM bindings for users and service accounts in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [labels](variables.tf#L151) | Project-level labels. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [nodepools](variables.tf#L157) | Nodepools configuration. Refer to the gke-nodepool module for type details. | <code title="map&#40;map&#40;object&#40;&#123;&#10; gke_version &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; max_pods_per_node &#61; optional&#40;number&#41;&#10; name &#61; optional&#40;string&#41;&#10; node_config &#61; optional&#40;any, &#123; disk_type &#61; &#34;pd-balanced&#34; &#125;&#41;&#10; node_count &#61; optional&#40;map&#40;number&#41;, &#123; initial &#61; 1 &#125;&#41;&#10; node_locations &#61; optional&#40;list&#40;string&#41;&#41;&#10; nodepool_config &#61; optional&#40;any&#41;&#10; pod_range &#61; optional&#40;any&#41;&#10; reservation_affinity &#61; optional&#40;any&#41;&#10; service_account &#61; optional&#40;any&#41;&#10; sole_tenant_nodegroup &#61; optional&#40;string&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10; taints &#61; optional&#40;list&#40;any&#41;&#41;&#10;&#125;&#41;&#41;&#41;">map&#40;map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [project_services](variables.tf#L193) | Additional project services to enable. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [nodepools](variables.tf#L157) | Nodepools configuration. Refer to the gke-nodepool module for type details. | <code title="map&#40;map&#40;object&#40;&#123;&#10; gke_version &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; max_pods_per_node &#61; optional&#40;number&#41;&#10; name &#61; optional&#40;string&#41;&#10; node_config &#61; optional&#40;any, &#123; disk_type &#61; &#34;pd-balanced&#34; &#125;&#41;&#10; node_count &#61; optional&#40;map&#40;number&#41;, &#123; initial &#61; 1 &#125;&#41;&#10; node_locations &#61; optional&#40;list&#40;string&#41;&#41;&#10; nodepool_config &#61; optional&#40;any&#41;&#10; pod_range &#61; optional&#40;any&#41;&#10; reservation_affinity &#61; optional&#40;any&#41;&#10; service_account &#61; optional&#40;any&#41;&#10; sole_tenant_nodegroup &#61; optional&#40;string&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10; taints &#61; optional&#40;list&#40;object&#40;&#123;&#10; key &#61; string&#10; value &#61; string&#10; effect &#61; string&#10; &#125;&#41;&#41;&#41;&#10;&#125;&#41;&#41;&#41;">map&#40;map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [project_services](variables.tf#L197) | Additional project services to enable. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
## Outputs

View File

@ -170,7 +170,11 @@ variable "nodepools" {
service_account = optional(any)
sole_tenant_nodegroup = optional(string)
tags = optional(list(string))
taints = optional(list(any))
taints = optional(list(object({
key = string
value = string
effect = string
})))
})))
default = {}
nullable = false

View File

@ -166,8 +166,8 @@ Leave all these variables unset (or set to `null`) to disable fleet management.
| [billing_account](variables.tf#L29) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | <code title="object&#40;&#123;&#10; id &#61; string&#10; is_org_level &#61; optional&#40;bool, true&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>0-bootstrap</code> |
| [folder_ids](variables.tf#L153) | Folders to be used for the networking resources in folders/nnnnnnnnnnn format. If null, folder will be created. | <code title="object&#40;&#123;&#10; gke-dev &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>1-resman</code> |
| [host_project_ids](variables.tf#L168) | Host project for the shared VPC. | <code title="object&#40;&#123;&#10; dev-spoke-0 &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>2-networking</code> |
| [prefix](variables.tf#L217) | Prefix used for resources that need unique names. | <code>string</code> | ✓ | | |
| [vpc_self_links](variables.tf#L233) | Self link for the shared VPC. | <code title="object&#40;&#123;&#10; dev-spoke-0 &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>2-networking</code> |
| [prefix](variables.tf#L221) | Prefix used for resources that need unique names. | <code>string</code> | ✓ | | |
| [vpc_self_links](variables.tf#L237) | Self link for the shared VPC. | <code title="object&#40;&#123;&#10; dev-spoke-0 &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | | <code>2-networking</code> |
| [clusters](variables.tf#L42) | Clusters configuration. Refer to the gke-cluster module for type details. | <code title="map&#40;object&#40;&#123;&#10; cluster_autoscaling &#61; optional&#40;any&#41;&#10; description &#61; optional&#40;string&#41;&#10; enable_addons &#61; optional&#40;any, &#123;&#10; horizontal_pod_autoscaling &#61; true, http_load_balancing &#61; true&#10; &#125;&#41;&#10; enable_features &#61; optional&#40;any, &#123;&#10; workload_identity &#61; true&#10; &#125;&#41;&#10; issue_client_certificate &#61; optional&#40;bool, false&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; location &#61; string&#10; logging_config &#61; optional&#40;list&#40;string&#41;, &#91;&#34;SYSTEM_COMPONENTS&#34;&#93;&#41;&#10; maintenance_config &#61; optional&#40;any, &#123;&#10; daily_window_start_time &#61; &#34;03:00&#34;&#10; recurring_window &#61; null&#10; maintenance_exclusion &#61; &#91;&#93;&#10; &#125;&#41;&#10; max_pods_per_node &#61; optional&#40;number, 110&#41;&#10; min_master_version &#61; optional&#40;string&#41;&#10; monitoring_config &#61; optional&#40;object&#40;&#123;&#10; enable_components &#61; optional&#40;list&#40;string&#41;, &#91;&#34;SYSTEM_COMPONENTS&#34;&#93;&#41;&#10; managed_prometheus &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; node_locations &#61; optional&#40;list&#40;string&#41;&#41;&#10; private_cluster_config &#61; optional&#40;any&#41;&#10; release_channel &#61; optional&#40;string&#41;&#10; vpc_config &#61; object&#40;&#123;&#10; subnetwork &#61; string&#10; network &#61; optional&#40;string&#41;&#10; secondary_range_blocks &#61; optional&#40;object&#40;&#123;&#10; pods &#61; string&#10; services &#61; string&#10; &#125;&#41;&#41;&#10; secondary_range_names &#61; optional&#40;object&#40;&#123;&#10; pods &#61; string&#10; services &#61; string&#10; &#125;&#41;, &#123; pods &#61; &#34;pods&#34;, services &#61; &#34;services&#34; &#125;&#41;&#10; master_authorized_ranges &#61; optional&#40;map&#40;string&#41;&#41;&#10; master_ipv4_cidr_block &#61; optional&#40;string&#41;&#10; &#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
| [fleet_configmanagement_clusters](variables.tf#L90) | Config management features enabled on specific sets of member clusters, in config name => [cluster name] format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
| [fleet_configmanagement_templates](variables.tf#L98) | Sets of config management configurations that can be applied to member clusters, in config name => {options} format. | <code title="map&#40;object&#40;&#123;&#10; binauthz &#61; bool&#10; config_sync &#61; object&#40;&#123;&#10; git &#61; object&#40;&#123;&#10; gcp_service_account_email &#61; string&#10; https_proxy &#61; string&#10; policy_dir &#61; string&#10; secret_type &#61; string&#10; sync_branch &#61; string&#10; sync_repo &#61; string&#10; sync_rev &#61; string&#10; sync_wait_secs &#61; number&#10; &#125;&#41;&#10; prevent_drift &#61; string&#10; source_format &#61; string&#10; &#125;&#41;&#10; hierarchy_controller &#61; object&#40;&#123;&#10; enable_hierarchical_resource_quota &#61; bool&#10; enable_pod_tree_labels &#61; bool&#10; &#125;&#41;&#10; policy_controller &#61; object&#40;&#123;&#10; audit_interval_seconds &#61; number&#10; exemptable_namespaces &#61; list&#40;string&#41;&#10; log_denies_enabled &#61; bool&#10; referential_rules_enabled &#61; bool&#10; template_library_installed &#61; bool&#10; &#125;&#41;&#10; version &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
@ -176,9 +176,9 @@ Leave all these variables unset (or set to `null`) to disable fleet management.
| [group_iam](variables.tf#L161) | Project-level authoritative IAM bindings for groups in {GROUP_EMAIL => [ROLES]} format. Use group emails as keys, list of roles as values. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
| [iam](variables.tf#L176) | Project-level authoritative IAM bindings for users and service accounts in {ROLE => [MEMBERS]} format. | <code>map&#40;list&#40;string&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
| [labels](variables.tf#L183) | Project-level labels. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> | |
| [nodepools](variables.tf#L189) | Nodepools configuration. Refer to the gke-nodepool module for type details. | <code title="map&#40;map&#40;object&#40;&#123;&#10; gke_version &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; max_pods_per_node &#61; optional&#40;number&#41;&#10; name &#61; optional&#40;string&#41;&#10; node_config &#61; optional&#40;any, &#123; disk_type &#61; &#34;pd-balanced&#34; &#125;&#41;&#10; node_count &#61; optional&#40;map&#40;number&#41;, &#123; initial &#61; 1 &#125;&#41;&#10; node_locations &#61; optional&#40;list&#40;string&#41;&#41;&#10; nodepool_config &#61; optional&#40;any&#41;&#10; pod_range &#61; optional&#40;any&#41;&#10; reservation_affinity &#61; optional&#40;any&#41;&#10; service_account &#61; optional&#40;any&#41;&#10; sole_tenant_nodegroup &#61; optional&#40;string&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10; taints &#61; optional&#40;list&#40;any&#41;&#41;&#10;&#125;&#41;&#41;&#41;">map&#40;map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
| [outputs_location](variables.tf#L211) | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | |
| [project_services](variables.tf#L226) | Additional project services to enable. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> | |
| [nodepools](variables.tf#L189) | Nodepools configuration. Refer to the gke-nodepool module for type details. | <code title="map&#40;map&#40;object&#40;&#123;&#10; gke_version &#61; optional&#40;string&#41;&#10; labels &#61; optional&#40;map&#40;string&#41;, &#123;&#125;&#41;&#10; max_pods_per_node &#61; optional&#40;number&#41;&#10; name &#61; optional&#40;string&#41;&#10; node_config &#61; optional&#40;any, &#123; disk_type &#61; &#34;pd-balanced&#34; &#125;&#41;&#10; node_count &#61; optional&#40;map&#40;number&#41;, &#123; initial &#61; 1 &#125;&#41;&#10; node_locations &#61; optional&#40;list&#40;string&#41;&#41;&#10; nodepool_config &#61; optional&#40;any&#41;&#10; pod_range &#61; optional&#40;any&#41;&#10; reservation_affinity &#61; optional&#40;any&#41;&#10; service_account &#61; optional&#40;any&#41;&#10; sole_tenant_nodegroup &#61; optional&#40;string&#41;&#10; tags &#61; optional&#40;list&#40;string&#41;&#41;&#10; taints &#61; optional&#40;list&#40;object&#40;&#123;&#10; key &#61; string&#10; value &#61; string&#10; effect &#61; string&#10; &#125;&#41;&#41;&#41;&#10;&#125;&#41;&#41;&#41;">map&#40;map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;&#41;</code> | | <code>&#123;&#125;</code> | |
| [outputs_location](variables.tf#L215) | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | <code>string</code> | | <code>null</code> | |
| [project_services](variables.tf#L230) | Additional project services to enable. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> | |
## Outputs

View File

@ -202,7 +202,11 @@ variable "nodepools" {
service_account = optional(any)
sole_tenant_nodegroup = optional(string)
tags = optional(list(string))
taints = optional(list(any))
taints = optional(list(object({
key = string
value = string
effect = string
})))
})))
default = {}
nullable = false

966
tools/bpmetadataschema.json Normal file
View File

@ -0,0 +1,966 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/cli/bpmetadata/blueprint-metadata",
"$ref": "#/$defs/BlueprintMetadata",
"$defs": {
"BlueprintActuationTool": {
"properties": {
"type": {
"type": "string"
},
"version": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintArchitecture": {
"properties": {
"diagram": {
"type": "string"
},
"description": {
"items": {
"type": "string"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"diagram",
"description"
]
},
"BlueprintAuthor": {
"properties": {
"title": {
"type": "string"
},
"description": {
"type": "string"
},
"url": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"title"
]
},
"BlueprintCloudProduct": {
"properties": {
"productId": {
"type": "string"
},
"pageUrl": {
"type": "string"
},
"label": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"pageUrl"
]
},
"BlueprintContent": {
"properties": {
"architecture": {
"$ref": "#/$defs/BlueprintArchitecture"
},
"diagrams": {
"items": {
"$ref": "#/$defs/BlueprintDiagram"
},
"type": "array"
},
"documentation": {
"items": {
"$ref": "#/$defs/BlueprintListContent"
},
"type": "array"
},
"subBlueprints": {
"items": {
"$ref": "#/$defs/BlueprintMiscContent"
},
"type": "array"
},
"examples": {
"items": {
"$ref": "#/$defs/BlueprintMiscContent"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintCostEstimate": {
"properties": {
"description": {
"type": "string"
},
"url": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"description",
"url"
]
},
"BlueprintDescription": {
"properties": {
"tagline": {
"type": "string"
},
"detailed": {
"type": "string"
},
"preDeploy": {
"type": "string"
},
"html": {
"type": "string"
},
"eulaUrls": {
"items": {
"type": "string"
},
"type": "array"
},
"architecture": {
"items": {
"type": "string"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintDiagram": {
"properties": {
"name": {
"type": "string"
},
"altText": {
"type": "string"
},
"description": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"name"
]
},
"BlueprintInfo": {
"properties": {
"title": {
"type": "string"
},
"source": {
"$ref": "#/$defs/BlueprintRepoDetail"
},
"version": {
"type": "string"
},
"actuationTool": {
"$ref": "#/$defs/BlueprintActuationTool"
},
"description": {
"$ref": "#/$defs/BlueprintDescription"
},
"icon": {
"type": "string"
},
"deploymentDuration": {
"$ref": "#/$defs/BlueprintTimeEstimate"
},
"costEstimate": {
"$ref": "#/$defs/BlueprintCostEstimate"
},
"cloudProducts": {
"items": {
"$ref": "#/$defs/BlueprintCloudProduct"
},
"type": "array"
},
"quotaDetails": {
"items": {
"$ref": "#/$defs/BlueprintQuotaDetail"
},
"type": "array"
},
"author": {
"$ref": "#/$defs/BlueprintAuthor"
},
"softwareGroups": {
"items": {
"$ref": "#/$defs/BlueprintSoftwareGroup"
},
"type": "array"
},
"supportInfo": {
"$ref": "#/$defs/BlueprintSupport"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"title",
"source"
]
},
"BlueprintInterface": {
"properties": {
"variables": {
"items": {
"$ref": "#/$defs/BlueprintVariable"
},
"type": "array"
},
"variableGroups": {
"items": {
"$ref": "#/$defs/BlueprintVariableGroup"
},
"type": "array"
},
"outputs": {
"items": {
"$ref": "#/$defs/BlueprintOutput"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintListContent": {
"properties": {
"title": {
"type": "string"
},
"url": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"title"
]
},
"BlueprintMetadata": {
"properties": {
"apiVersion": {
"type": "string"
},
"kind": {
"type": "string"
},
"metadata": {
"$ref": "#/$defs/ObjectMeta"
},
"spec": {
"$ref": "#/$defs/BlueprintMetadataSpec"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"spec"
]
},
"BlueprintMetadataSpec": {
"properties": {
"info": {
"$ref": "#/$defs/BlueprintInfo"
},
"content": {
"$ref": "#/$defs/BlueprintContent"
},
"interfaces": {
"$ref": "#/$defs/BlueprintInterface"
},
"requirements": {
"$ref": "#/$defs/BlueprintRequirements"
},
"ui": {
"$ref": "#/$defs/BlueprintUI"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintMiscContent": {
"properties": {
"name": {
"type": "string"
},
"location": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"name"
]
},
"BlueprintOutput": {
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"name"
]
},
"BlueprintQuotaDetail": {
"properties": {
"variable": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"GCE_INSTANCE",
"GCE_DISK"
]
},
"quotaType": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"type",
"quotaType"
]
},
"BlueprintRepoDetail": {
"properties": {
"repo": {
"type": "string"
},
"sourceType": {
"type": "string"
},
"dir": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"repo",
"sourceType"
]
},
"BlueprintRequirements": {
"properties": {
"roles": {
"items": {
"$ref": "#/$defs/BlueprintRoles"
},
"type": "array"
},
"services": {
"items": {
"type": "string"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintRoles": {
"properties": {
"level": {
"type": "string"
},
"roles": {
"items": {
"type": "string"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"level",
"roles"
]
},
"BlueprintSoftware": {
"properties": {
"title": {
"type": "string"
},
"version": {
"type": "string"
},
"url": {
"type": "string"
},
"licenseUrl": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"title"
]
},
"BlueprintSoftwareGroup": {
"properties": {
"type": {
"type": "string",
"enum": [
"UNSPECIFIED",
"OS"
]
},
"software": {
"items": {
"$ref": "#/$defs/BlueprintSoftware"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintSupport": {
"properties": {
"description": {
"type": "string"
},
"url": {
"type": "string"
},
"entity": {
"type": "string"
},
"showSupportId": {
"type": "boolean"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"description"
]
},
"BlueprintTimeEstimate": {
"properties": {
"configuration": {
"type": "integer"
},
"deployment": {
"type": "integer"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintUI": {
"properties": {
"input": {
"$ref": "#/$defs/BlueprintUIInput"
},
"runtime": {
"$ref": "#/$defs/BlueprintUIOutput"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintUIInput": {
"properties": {
"variables": {
"patternProperties": {
".*": {
"$ref": "#/$defs/DisplayVariable"
}
},
"type": "object"
},
"sections": {
"items": {
"$ref": "#/$defs/DisplaySection"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintUIOutput": {
"properties": {
"outputMessage": {
"type": "string"
},
"suggestedActions": {
"items": {
"$ref": "#/$defs/UIActionItem"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintVariable": {
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"type": {
"type": "string"
},
"default": true,
"required": {
"type": "boolean"
}
},
"additionalProperties": false,
"type": "object"
},
"BlueprintVariableGroup": {
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"variables": {
"items": {
"type": "string"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"name"
]
},
"DisplaySection": {
"properties": {
"name": {
"type": "string"
},
"title": {
"type": "string"
},
"tooltip": {
"type": "string"
},
"subtext": {
"type": "string"
},
"parent": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"name"
]
},
"DisplayVariable": {
"properties": {
"name": {
"type": "string"
},
"title": {
"type": "string"
},
"invisible": {
"type": "boolean"
},
"tooltip": {
"type": "string"
},
"placeholder": {
"type": "string"
},
"regexValidation": {
"type": "string"
},
"minItems": {
"type": "integer"
},
"maxItems": {
"type": "integer"
},
"minLength": {
"type": "integer"
},
"maxLength": {
"type": "integer"
},
"min": {
"type": "integer"
},
"max": {
"type": "integer"
},
"section": {
"type": "string"
},
"x-googleProperty": {
"$ref": "#/$defs/GooglePropertyExtension"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"name"
]
},
"GCEDiskSizeExtension": {
"properties": {
"diskTypeVariable": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"diskTypeVariable"
]
},
"GCEExternalIPExtension": {
"properties": {
"networkVariable": {
"type": "string"
},
"externalIpType": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"networkVariable"
]
},
"GCEFirewallExtension": {
"properties": {
"networkVariable": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"networkVariable"
]
},
"GCEFirewallRangeExtension": {
"properties": {
"firewallVariable": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"firewallVariable"
]
},
"GCEGPUCountExtension": {
"properties": {
"machineTypeVariable": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"machineTypeVariable"
]
},
"GCEGPUTypeExtension": {
"properties": {
"machineType": {
"type": "string"
},
"gpuType": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"machineType"
]
},
"GCEGenericResourceExtension": {
"properties": {
"resourceVariable": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"resourceVariable"
]
},
"GCEIPForwardingExtension": {
"properties": {
"networkVariable": {
"type": "string"
},
"notConfigurable": {
"type": "boolean"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"networkVariable"
]
},
"GCELocationExtension": {
"properties": {
"allowlistedZones": {
"items": {
"type": "string"
},
"type": "array"
},
"allowlistedRegions": {
"items": {
"type": "string"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"GCEMachineTypeExtension": {
"properties": {
"minCpu": {
"type": "integer"
},
"minRamGb": {
"type": "integer"
},
"disallowCustomMachineTypes": {
"type": "boolean"
}
},
"additionalProperties": false,
"type": "object"
},
"GCENetworkExtension": {
"properties": {
"allowSharedVpcs": {
"type": "boolean"
},
"machineTypeVariable": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"machineTypeVariable"
]
},
"GCESubnetworkExtension": {
"properties": {
"networkVariable": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"networkVariable"
]
},
"GooglePropertyExtension": {
"properties": {
"type": {
"type": "string",
"enum": [
"EMAIL_ADDRESS",
"MULTI_LINE_STRING",
"GCE_DISK_IMAGE",
"GCE_DISK_TYPE",
"GCE_DISK_SIZE",
"GCE_MACHINE_TYPE",
"GCE_NETWORK",
"GCE_ZONE",
"GCE_SUBNETWORK",
"GCE_REGION",
"GCE_GPU_TYPE",
"GCE_GPU_COUNT",
"GCE_EXTERNAL_IP",
"GCE_IP_FORWARDING",
"GCE_FIREWALL",
"GCE_FIREWALL_RANGE",
"GCE_GENERIC_RESOURCE",
"GCS_BUCKET",
"IAM_SERVICE_ACCOUNT"
]
},
"zoneProperty": {
"type": "string"
},
"gceMachineType": {
"$ref": "#/$defs/GCEMachineTypeExtension"
},
"gceDiskSize": {
"$ref": "#/$defs/GCEDiskSizeExtension"
},
"gceSubnetwork": {
"$ref": "#/$defs/GCESubnetworkExtension"
},
"gceResource": {
"$ref": "#/$defs/GCEGenericResourceExtension"
},
"gceGpuType": {
"$ref": "#/$defs/GCEGPUTypeExtension"
},
"gceGpuCount": {
"$ref": "#/$defs/GCEGPUCountExtension"
},
"gceNetwork": {
"$ref": "#/$defs/GCENetworkExtension"
},
"gceExternalIp": {
"$ref": "#/$defs/GCEExternalIPExtension"
},
"gceIpForwarding": {
"$ref": "#/$defs/GCEIPForwardingExtension"
},
"gceFirewall": {
"$ref": "#/$defs/GCEFirewallExtension"
},
"gceFirewallRange": {
"$ref": "#/$defs/GCEFirewallRangeExtension"
},
"gceZone": {
"$ref": "#/$defs/GCELocationExtension"
},
"gceRegion": {
"$ref": "#/$defs/GCELocationExtension"
},
"iamServiceAccount": {
"$ref": "#/$defs/IAMServiceAccountExtension"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"type"
]
},
"IAMServiceAccountExtension": {
"properties": {
"roles": {
"items": {
"type": "string"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"roles"
]
},
"ObjectMeta": {
"properties": {
"name": {
"type": "string"
},
"namespace": {
"type": "string"
},
"labels": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object"
},
"annotations": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object"
}
},
"additionalProperties": false,
"type": "object"
},
"UIActionItem": {
"properties": {
"heading": {
"type": "string"
},
"description": {
"type": "string"
},
"snippet": {
"type": "string"
},
"showIf": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"heading"
]
}
}
}

View File

@ -6,3 +6,4 @@ marko
requests
yamale
yapf
jsonschema

90
tools/validate_metadata.py Executable file
View File

@ -0,0 +1,90 @@
#!/usr/bin/env python3
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://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.
'''Validate a YAML file against the standard blueprint metadata schema[1]
[1] https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/master/cli/bpmetadata/schema/bpmetadataschema.json
'''
import enum
import json
import sys
from dataclasses import dataclass
from pathlib import Path
import click
import jsonschema
import yaml
SCHEMA_PATH = Path(__file__).parent / 'bpmetadataschema.json'
class State(enum.Enum):
INVALID: int = 0
OK: int = 1
@dataclass
class ValidationResult:
state: State
errors: dict[str, str]
def _validate(path: Path, validator) -> ValidationResult:
with open(path) as f:
metadata = yaml.safe_load(f)
errors = {
error.json_path: error.message
for error in validator.iter_errors(metadata)
}
state = State.OK if not errors else State.INVALID
return ValidationResult(state=state, errors=errors)
@click.command()
@click.argument('dirs', type=click.Path(exists=True, file_okay=False), nargs=-1)
@click.option('-v', '--verbose', is_flag=True, default=False,
help='Print additional validation details.')
def main(dirs: list[str], verbose: bool) -> int:
instances = set()
for dir_name in dirs:
instances |= set(Path(dir_name).glob("**/metadata.yaml"))
with open(SCHEMA_PATH) as f:
schema = json.load(f)
validator = jsonschema.validators.Draft202012Validator(schema)
failed_files = {}
for instance in instances:
result = _validate(instance, validator)
if result.state == State.OK:
print(f'[✓] {instance}')
else:
print(f'[✗] {instance}')
failed_files[instance] = result.errors
if verbose:
for file_path, errors in failed_files.items():
print(f"\n====== {file_path!s} ======")
for path, message in errors.items():
print(f"{path}: {message}")
return 0 if not failed_files else 1
if __name__ == '__main__':
sys.exit(main())