CI/CD support for Source Repository and Cloud Build (#669)
* add id to outputs * initial cloud build implementation for stage 0 * comments * stage 0 * stage 1, untested * add support for IAM and CB triggers to source repository module * refactor stage 0 to use sourcerepo module * refactor stage 1 to use sourcerepo module * file descriptions * fix gitlab pipeline
This commit is contained in:
committed by
GitHub
parent
0d670afb7e
commit
44ae2671b0
@@ -63,9 +63,10 @@ module "myproject-default-service-accounts" {
|
||||
|---|---|:---:|
|
||||
| [email](outputs.tf#L17) | Service account email. | |
|
||||
| [iam_email](outputs.tf#L25) | IAM-format service account email. | |
|
||||
| [key](outputs.tf#L33) | Service account key. | ✓ |
|
||||
| [name](outputs.tf#L39) | Service account id. | |
|
||||
| [service_account](outputs.tf#L44) | Service account resource. | |
|
||||
| [service_account_credentials](outputs.tf#L49) | Service account json credential templates for uploaded public keys data. | |
|
||||
| [id](outputs.tf#L33) | Service account id. | |
|
||||
| [key](outputs.tf#L38) | Service account key. | ✓ |
|
||||
| [name](outputs.tf#L44) | Service account name. | |
|
||||
| [service_account](outputs.tf#L49) | Service account resource. | |
|
||||
| [service_account_credentials](outputs.tf#L54) | Service account json credential templates for uploaded public keys data. | |
|
||||
|
||||
<!-- END TFDOC -->
|
||||
|
||||
@@ -30,6 +30,11 @@ output "iam_email" {
|
||||
]
|
||||
}
|
||||
|
||||
output "id" {
|
||||
description = "Service account id."
|
||||
value = local.service_account.id
|
||||
}
|
||||
|
||||
output "key" {
|
||||
description = "Service account key."
|
||||
sensitive = true
|
||||
@@ -37,7 +42,7 @@ output "key" {
|
||||
}
|
||||
|
||||
output "name" {
|
||||
description = "Service account id."
|
||||
description = "Service account name."
|
||||
value = local.service_account.name
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
# Google Cloud Source Repository Module
|
||||
|
||||
This module allows managing a single Cloud Source Repository, including IAM bindings.
|
||||
|
||||
This module allows managing a single Cloud Source Repository, including IAM bindings and basic Cloud Build triggers.
|
||||
|
||||
## Examples
|
||||
|
||||
### Simple repository with IAM
|
||||
### Repository with IAM
|
||||
|
||||
```hcl
|
||||
module "repo" {
|
||||
@@ -18,21 +17,64 @@ module "repo" {
|
||||
}
|
||||
# tftest modules=1 resources=2
|
||||
```
|
||||
|
||||
### Repository with Cloud Build trigger
|
||||
|
||||
```hcl
|
||||
module "repo" {
|
||||
source = "./modules/source-repository"
|
||||
project_id = "my-project"
|
||||
name = "my-repo"
|
||||
triggers = {
|
||||
foo = {
|
||||
filename = "ci/workflow-foo.yaml"
|
||||
included_files = ["**/*tf"]
|
||||
service_account = null
|
||||
substitutions = {
|
||||
BAR = 1
|
||||
}
|
||||
template = {
|
||||
branch_name = "main"
|
||||
project_id = null
|
||||
tag_name = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# tftest modules=1 resources=2
|
||||
```
|
||||
|
||||
<!-- TFDOC OPTS files:1 -->
|
||||
<!-- BEGIN TFDOC -->
|
||||
|
||||
## Files
|
||||
|
||||
| name | description | resources |
|
||||
|---|---|---|
|
||||
| [iam.tf](./iam.tf) | IAM resources. | <code>google_sourcerepo_repository_iam_binding</code> · <code>google_sourcerepo_repository_iam_member</code> |
|
||||
| [main.tf](./main.tf) | Module-level locals and resources. | <code>google_cloudbuild_trigger</code> · <code>google_sourcerepo_repository</code> |
|
||||
| [outputs.tf](./outputs.tf) | Module outputs. | |
|
||||
| [variables.tf](./variables.tf) | Module variables. | |
|
||||
| [versions.tf](./versions.tf) | Version pins. | |
|
||||
|
||||
## Variables
|
||||
|
||||
| name | description | type | required | default |
|
||||
|---|---|:---:|:---:|:---:|
|
||||
| [name](variables.tf#L23) | Repository name. | <code>string</code> | ✓ | |
|
||||
| [project_id](variables.tf#L28) | Project used for resources. | <code>string</code> | ✓ | |
|
||||
| [iam](variables.tf#L17) | IAM bindings in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [name](variables.tf#L44) | Repository name. | <code>string</code> | ✓ | |
|
||||
| [project_id](variables.tf#L49) | Project used for resources. | <code>string</code> | ✓ | |
|
||||
| [group_iam](variables.tf#L17) | Authoritative IAM binding for organization groups, in {GROUP_EMAIL => [ROLES]} format. Group emails need to be static. Can be used in combination with the `iam` variable. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam](variables.tf#L24) | IAM bindings in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_additive](variables.tf#L31) | IAM additive bindings in {ROLE => [MEMBERS]} format. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [iam_additive_members](variables.tf#L38) | IAM additive bindings in {MEMBERS => [ROLE]} format. This might break if members are dynamic values. | <code>map(list(string))</code> | | <code>{}</code> |
|
||||
| [triggers](variables.tf#L54) | Cloud Build triggers. | <code title="map(object({ filename = string included_files = list(string) service_account = string substitutions = map(string) template = object({ branch_name = string project_id = string tag_name = string }) }))">map(object({…}))</code> | | <code>{}</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
| name | description | sensitive |
|
||||
|---|---|:---:|
|
||||
| [id](outputs.tf#L17) | Repository id. | |
|
||||
| [url](outputs.tf#L22) | Repository URL. | |
|
||||
| [name](outputs.tf#L22) | Repository name. | |
|
||||
| [url](outputs.tf#L27) | Repository URL. | |
|
||||
|
||||
<!-- END TFDOC -->
|
||||
|
||||
67
modules/source-repository/iam.tf
Normal file
67
modules/source-repository/iam.tf
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
# tfdoc:file:description IAM resources.
|
||||
|
||||
locals {
|
||||
_group_iam_roles = distinct(flatten(values(var.group_iam)))
|
||||
_group_iam = {
|
||||
for r in local._group_iam_roles : r => [
|
||||
for k, v in var.group_iam : "group:${k}" if try(index(v, r), null) != null
|
||||
]
|
||||
}
|
||||
_iam_additive_pairs = flatten([
|
||||
for role, members in var.iam_additive : [
|
||||
for member in members : { role = role, member = member }
|
||||
]
|
||||
])
|
||||
_iam_additive_member_pairs = flatten([
|
||||
for member, roles in var.iam_additive_members : [
|
||||
for role in roles : { role = role, member = member }
|
||||
]
|
||||
])
|
||||
iam = {
|
||||
for role in distinct(concat(keys(var.iam), keys(local._group_iam))) :
|
||||
role => concat(
|
||||
try(var.iam[role], []),
|
||||
try(local._group_iam[role], [])
|
||||
)
|
||||
}
|
||||
iam_additive = {
|
||||
for pair in concat(local._iam_additive_pairs, local._iam_additive_member_pairs) :
|
||||
"${pair.role}-${pair.member}" => pair
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_sourcerepo_repository_iam_binding" "authoritative" {
|
||||
for_each = local.iam
|
||||
project = var.project_id
|
||||
repository = google_sourcerepo_repository.default.name
|
||||
role = each.key
|
||||
members = each.value
|
||||
}
|
||||
|
||||
resource "google_sourcerepo_repository_iam_member" "additive" {
|
||||
for_each = (
|
||||
length(var.iam_additive) + length(var.iam_additive_members) > 0
|
||||
? local.iam_additive
|
||||
: {}
|
||||
)
|
||||
project = var.project_id
|
||||
repository = google_sourcerepo_repository.default.name
|
||||
role = each.value.role
|
||||
member = each.value.member
|
||||
}
|
||||
@@ -19,14 +19,18 @@ resource "google_sourcerepo_repository" "default" {
|
||||
name = var.name
|
||||
}
|
||||
|
||||
resource "google_sourcerepo_repository_iam_binding" "default" {
|
||||
for_each = var.iam
|
||||
project = var.project_id
|
||||
repository = google_sourcerepo_repository.default.name
|
||||
role = each.key
|
||||
members = each.value
|
||||
|
||||
depends_on = [
|
||||
google_sourcerepo_repository.default
|
||||
]
|
||||
resource "google_cloudbuild_trigger" "default" {
|
||||
for_each = coalesce(var.triggers, {})
|
||||
project = var.project_id
|
||||
name = each.key
|
||||
filename = each.value.filename
|
||||
included_files = each.value.included_files
|
||||
service_account = each.value.service_account
|
||||
substitutions = each.value.substitutions
|
||||
trigger_template {
|
||||
project_id = try(each.value.template.project_id, var.project_id)
|
||||
branch_name = try(each.value.template.branch_name, null)
|
||||
repo_name = google_sourcerepo_repository.default.name
|
||||
tag_name = try(each.value.template.tag_name, null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,11 @@ output "id" {
|
||||
value = google_sourcerepo_repository.default.id
|
||||
}
|
||||
|
||||
output "name" {
|
||||
description = "Repository name."
|
||||
value = google_sourcerepo_repository.default.name
|
||||
}
|
||||
|
||||
output "url" {
|
||||
description = "Repository URL."
|
||||
value = google_sourcerepo_repository.default.url
|
||||
|
||||
@@ -14,10 +14,31 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
variable "group_iam" {
|
||||
description = "Authoritative IAM binding for organization groups, in {GROUP_EMAIL => [ROLES]} format. Group emails need to be static. Can be used in combination with the `iam` variable."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "iam" {
|
||||
description = "IAM bindings in {ROLE => [MEMBERS]} format."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "iam_additive" {
|
||||
description = "IAM additive bindings in {ROLE => [MEMBERS]} format."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "iam_additive_members" {
|
||||
description = "IAM additive bindings in {MEMBERS => [ROLE]} format. This might break if members are dynamic values."
|
||||
type = map(list(string))
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "name" {
|
||||
@@ -29,3 +50,20 @@ variable "project_id" {
|
||||
description = "Project used for resources."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "triggers" {
|
||||
description = "Cloud Build triggers."
|
||||
type = map(object({
|
||||
filename = string
|
||||
included_files = list(string)
|
||||
service_account = string
|
||||
substitutions = map(string)
|
||||
template = object({
|
||||
branch_name = string
|
||||
project_id = string
|
||||
tag_name = string
|
||||
})
|
||||
}))
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user