Skip to content

Commit

Permalink
Allow creating repositories in Gitlab via Terraform.
Browse files Browse the repository at this point in the history
  • Loading branch information
rosmo committed Jun 21, 2022
1 parent e0b1231 commit ddfec7f
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 4 deletions.
21 changes: 21 additions & 0 deletions fast/stages/00-bootstrap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,20 @@ federated_identity_providers = {
github-sample = {
attribute_condition = "attribute.repository_owner==\"my-github-org\""
issuer = "github"
issuer_uri = null
allowed_audiences = null
}
gitlab-sample = {
attribute_condition = "attribute.namespace_path==\"my-gitlab-org\""
issuer = "gitlab"
issuer_uri = null
allowed_audiences = null
}
gitlab-ce-sample = {
attribute_condition = "attribute.namespace_path==\"my-gitlab-org\""
issuer = "gitlab-ce"
issuer_uri = "https://gitlab.fast.example.com"
allowed_audiences = ["https://gitlab.fast.example.com"]
}
}
```
Expand All @@ -380,21 +390,32 @@ cicd_repositories = {
branch = null
identity_provider = "github-sample"
name = "my-gh-org/fast-bootstrap"
description = "Google Cloud organization bootstrapping"
type = "github"
}
resman = {
branch = "main"
identity_provider = "github-sample"
name = "my-gh-org/fast-resman"
description = "Google Cloud organization resource management"
type = "github"
}
networking = null
security = null
}
```

The `type` attribute can be set to one of the supported repository types: `github`, `gitlab`, or `sourcerepo`.

Once the stage is applied the generated output files will contain pre-configured workflow files for each repository, that will use Workload Identity Federation via a dedicated service account for each repository to impersonate the automation service account for the stage.

For Gitlab, you can use Terraform to automate creation of the repositories:

- Set `gitlab_url` if you are using Gitlab CE (self-hosted)
- Set `create = true` (and/or `create_group = false`) in `cicd_repositories`
- Set `GITLAB_TOKEN` environment variable with a Gitlab access token that has the
necessary permissions to create the groups and projects

The remaining configuration is manual, as it regards the repositories themselves:

- create a repository for modules
Expand Down
28 changes: 25 additions & 3 deletions fast/stages/00-bootstrap/cicd.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,26 @@ locals {
v != null
&&
(
v.type == "sourcerepo"
try(v.type, null) == "sourcerepo"
||
contains(keys(local.identity_providers), coalesce(v.identity_provider, ":"))
contains(keys(local.identity_providers), coalesce(try(v.identity_provider, null), ":"))
)
&&
fileexists("${path.module}/templates/workflow-${v.type}.yaml")
fileexists(format("${path.module}/templates/workflow-%s.yaml", try(v.type, "")))
)
}
gitlab_cicd_repositories = {
for k, v in coalesce(var.cicd_repositories, {}) : k => v
if(
v != null
&&
(
try(v.type, null) == "gitlab"
||
contains(keys(local.identity_providers), coalesce(try(v.identity_provider, null), ":"))
)
&&
fileexists(format("${path.module}/templates/workflow-%s.yaml", try(v.type, "")))
)
}
cicd_workflow_providers = {
Expand Down Expand Up @@ -117,3 +131,11 @@ module "automation-tf-cicd-sa" {
(module.automation-tf-output-gcs.name) = ["roles/storage.objectViewer"]
}
}

# gitlab
module "automation-tf-gitlab-cicd-repo" {
source = "./modules/gitlab"

gitlab_url = var.gitlab_url
cicd_repositories = local.gitlab_cicd_repositories
}
4 changes: 3 additions & 1 deletion fast/stages/00-bootstrap/identity-providers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
locals {
identity_providers = {
for k, v in var.federated_identity_providers : k => merge(
v, lookup(local.identity_providers_defs, v.issuer, {})
v, lookup(local.identity_providers_defs, v.issuer, {}),
{ issuer_uri = lookup(v, "issuer_uri", v.issuer_uri) },
{ allowed_audiences = lookup(v, "allowed_audiences", v.allowed_audiences) }
)
}
identity_providers_defs = {
Expand Down
61 changes: 61 additions & 0 deletions fast/stages/00-bootstrap/modules/gitlab/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* 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.
*/

locals {
cicd_repositories = { for k, v in var.cicd_repositories : k => merge(v,
{ group = join("/", slice(split("/", v.name), 0, length(split("/", v.name)) - 1)) },
{ name = element(split("/", v.name), length(split("/", v.name)) - 1) },
{ create_group = try(v.create_group, true) })
if v != null }
gitlab_create_groups = distinct([for k, v in local.cicd_repositories : v.group if try(v.create_group, false)])
gitlab_existing_groups = distinct([for k, v in local.cicd_repositories : v.group if !try(v.create_group, false)])
}

provider "gitlab" {
base_url = var.gitlab_url
}

data "gitlab_group" "group" {
for_each = toset(local.gitlab_existing_groups)
full_path = each.value
}

data "gitlab_project" "projects" {
for_each = { for name, repo in local.cicd_repositories : name => repo if !try(repo.create, true) }
id = format("%s/%s", each.value.group, each.value.name)
}

resource "gitlab_group" "group" {
for_each = toset(local.gitlab_create_groups)

name = each.value
path = each.value
description = "Cloud Foundation Fabric FAST: github.com/GoogleCloudPlatform/cloud-foundation-fabric/tree/master/fast/"
}

resource "gitlab_project" "projects" {
for_each = { for name, repo in local.cicd_repositories : name => repo if try(repo.create, true) }

name = each.value.name
namespace_id = each.value.create_group ? gitlab_group.group[each.value.group].id : data.gitlab_group.group[each.value.group].id
description = each.value.description

visibility_level = var.gitlab_project_visibility
auto_devops_enabled = false
}



30 changes: 30 additions & 0 deletions fast/stages/00-bootstrap/modules/gitlab/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* 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.
*/

locals {
repository_urls = { for k, v in local.cicd_repositories : k => v.create ? gitlab_project.projects[k].http_url_to_repo : data.gitlab_project.projects[k].http_url_to_repo }
repository_ssh = { for k, v in local.cicd_repositories : k => v.create ? gitlab_project.projects[k].ssh_url_to_repo : data.gitlab_project.projects[k].ssh_url_to_repo }
}

output "repository_urls" {
description = "Repository HTTPS clone URLs"
value = local.repository_urls
}

output "repository_ssh" {
description = "Repository SSH clone URLs"
value = local.repository_ssh
}
31 changes: 31 additions & 0 deletions fast/stages/00-bootstrap/modules/gitlab/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* 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.
*/

variable "gitlab_url" {
description = "Gitlab URL"
type = string
}

variable "cicd_repositories" {
description = "CI/CD repository configuration."
type = any
}

variable "gitlab_project_visibility" {
description = "Project visibility setting for FAST projects"
type = string
default = "private"
}
23 changes: 23 additions & 0 deletions fast/stages/00-bootstrap/modules/gitlab/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 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
#
# 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.

terraform {
required_version = ">= 1.1.0"
required_providers {
gitlab = {
source = "gitlabhq/gitlab"
version = ">= 3.15.0"
}
}
}
30 changes: 30 additions & 0 deletions fast/stages/00-bootstrap/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,35 @@ variable "cicd_repositories" {
branch = string
identity_provider = string
name = string
description = string
type = string
create = bool
})
resman = object({
branch = string
identity_provider = string
name = string
description = string
type = string
create = bool
})
networking = object({
branch = string
identity_provider = string
name = string
description = string
type = string
create = bool
create_group = bool
})
security = object({
branch = string
identity_provider = string
name = string
description = string
type = string
create = bool
create_group = bool
})
})
default = null
Expand Down Expand Up @@ -74,6 +96,12 @@ variable "cicd_repositories" {
}
}

variable "gitlab_url" {
description = "Gitlab URL."
type = string
default = "https://gitlab.com"
}

variable "custom_role_names" {
description = "Names of custom roles defined at the org level."
type = object({
Expand All @@ -91,6 +119,8 @@ variable "federated_identity_providers" {
type = map(object({
attribute_condition = string
issuer = string
allowed_audiences = list(string)
issuer_uri = string
}))
default = {}
nullable = false
Expand Down

0 comments on commit ddfec7f

Please sign in to comment.