Skip to content

Commit d1842a9

Browse files
author
Vitaly Markov
committed
Initial commit
1 parent 6faeb7e commit d1842a9

File tree

10 files changed

+262
-64
lines changed

10 files changed

+262
-64
lines changed

README.md

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
[![Cloud Posse][logo]](https://cpco.io/homepage)
4444

45-
# terraform-example-module [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-example-module.svg)](https://github.com/cloudposse/terraform-example-module/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) [![Discourse Forum](https://img.shields.io/discourse/https/ask.sweetops.com/posts.svg)](https://ask.sweetops.com/)
45+
# terraform-example-module [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-example-module.svg)](https://github.com/cloudposse/terraform-example-module/releases/latest)
4646

4747

4848
This is `terraform-example-module` project provides all the scaffolding for a typical well-built Cloud Posse module. It's a template repository you can
@@ -64,9 +64,9 @@ This project is part of our comprehensive ["SweetOps"](https://cpco.io/sweetops)
6464

6565

6666

67-
It's 100% Open Source and licensed under the [APACHE2](LICENSE).
6867

6968

69+
It's 100% Open Source and licensed under the [MIT](LICENSE).
7070

7171

7272

@@ -120,27 +120,35 @@ Available targets:
120120

121121
| Name | Version |
122122
|------|---------|
123-
| terraform | >= 0.12.0, < 0.14.0 |
124-
| local | ~> 1.2 |
125-
| random | ~> 2.2 |
123+
| terraform | >= 0.12.0, < 0.13.0 |
124+
| gitlab | >= 2.10 |
125+
| kubernetes | >= 1.11 |
126126

127127
## Providers
128128

129129
| Name | Version |
130130
|------|---------|
131-
| random | ~> 2.2 |
131+
| gitlab | >= 2.10 |
132+
| kubernetes | >= 1.11 |
132133

133134
## Inputs
134135

135136
| Name | Description | Type | Default | Required |
136137
|------|-------------|------|---------|:--------:|
137-
| example | Example variable | `string` | `"hello world"` | no |
138+
| cluster\_name | n/a | `string` | n/a | yes |
139+
| dns\_zone | (Required) specifies the DNS suffix for the externally-visible websites and services deployed in the cluster | `string` | n/a | yes |
140+
| enabled | n/a | `bool` | `true` | no |
141+
| group\_gitlab\_runner\_enabled | (Optional) Setup a gitlab group runner (will be used a group runner token to set GITLAB\_RUNNER\_TOKEN env variable) | `bool` | `false` | no |
142+
| kubernetes\_ca\_cert | (Required) PEM-encoded root certificates bundle for TLS authentication | `string` | n/a | yes |
143+
| kubernetes\_endpoint | (Required) The hostname (in form of URI) of Kubernetes master. | `string` | n/a | yes |
144+
| kubernetes\_token | (Required) Token of your service account, must have admin permission to create another service accounts | `string` | n/a | yes |
145+
| root\_gitlab\_group | (Semi-optional) A gitlab group id attach Kubernetes cluster to | `string` | `""` | no |
146+
| root\_gitlab\_project | (Semi-optional) A gitlab project id attach Kubernetes cluster to | `string` | `""` | no |
147+
| stage | (Required) Stage, e.g. 'prod', 'staging', 'dev' or 'testing' | `string` | n/a | yes |
138148

139149
## Outputs
140150

141-
| Name | Description |
142-
|------|-------------|
143-
| example | Example output |
151+
No output.
144152

145153

146154

@@ -249,31 +257,34 @@ Copyright © 2020-2020 [Cloud Posse, LLC](https://cloudposse.com)
249257

250258

251259

252-
## License
253260

254-
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
255261

256-
See [LICENSE](LICENSE) for full details.
257262

258-
Licensed to the Apache Software Foundation (ASF) under one
259-
or more contributor license agreements. See the NOTICE file
260-
distributed with this work for additional information
261-
regarding copyright ownership. The ASF licenses this file
262-
to you under the Apache License, Version 2.0 (the
263-
"License"); you may not use this file except in compliance
264-
with the License. You may obtain a copy of the License at
263+
## License
264+
265+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
265266

266-
https://www.apache.org/licenses/LICENSE-2.0
267+
The MIT License (MIT)
267268

268-
Unless required by applicable law or agreed to in writing,
269-
software distributed under the License is distributed on an
270-
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
271-
KIND, either express or implied. See the License for the
272-
specific language governing permissions and limitations
273-
under the License.
269+
Permission is hereby granted, free of charge, to any person obtaining a copy
270+
of this software and associated documentation files (the "Software"), to deal
271+
in the Software without restriction, including without limitation the rights
272+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
273+
copies of the Software, and to permit persons to whom the Software is
274+
furnished to do so, subject to the following conditions:
274275

276+
The above copyright notice and this permission notice shall be included in
277+
all copies or substantial portions of the Software.
275278

279+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
280+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
281+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
282+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
283+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
284+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
285+
THE SOFTWARE.
276286

287+
Source: <https://opensource.org/licenses/MIT>
277288

278289

279290

@@ -300,11 +311,11 @@ Check out [our other projects][github], [follow us on twitter][twitter], [apply
300311

301312
### Contributors
302313

303-
| [![Erik Osterman][osterman_avatar]][osterman_homepage]<br/>[Erik Osterman][osterman_homepage] |
314+
| [![Vitaly Markov][vymarkov_avatar]][vymarkov_homepage]<br/>[Vitaly Markov][vymarkov_homepage] |
304315
|---|
305316

306-
[osterman_homepage]: https://github.com/osterman
307-
[osterman_avatar]: https://img.cloudposse.com/150x150/https://github.com/osterman.png
317+
[vymarkov_homepage]: https://github.com/vymarkov
318+
[vymarkov_avatar]: https://img.cloudposse.com/150x150/https://github.com/vymarkov.png
308319

309320
[![README Footer][readme_footer_img]][readme_footer_link]
310321
[![Beacon][beacon]][website]

README.yaml

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ name: terraform-example-module
1111
#logo: docs/logo.png
1212

1313
# License of this project
14-
license: "APACHE2"
14+
license: "MIT"
1515

1616
# Copyrights
1717
copyrights:
@@ -27,12 +27,6 @@ badges:
2727
- name: "Latest Release"
2828
image: "https://img.shields.io/github/release/cloudposse/terraform-example-module.svg"
2929
url: "https://github.com/cloudposse/terraform-example-module/releases/latest"
30-
- name: "Slack Community"
31-
image: "https://slack.cloudposse.com/badge.svg"
32-
url: "https://slack.cloudposse.com"
33-
- name: "Discourse Forum"
34-
image: "https://img.shields.io/discourse/https/ask.sweetops.com/posts.svg"
35-
url: "https://ask.sweetops.com/"
3630

3731
# List any related terraform modules that this module may be used with or that this module depends on.
3832
related:
@@ -91,5 +85,5 @@ include:
9185

9286
# Contributors to this project
9387
contributors:
94-
- name: "Erik Osterman"
95-
github: "osterman"
88+
- name: "Vitaly Markov"
89+
github: "vymarkov"

docs/terraform.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,33 @@
22

33
| Name | Version |
44
|------|---------|
5-
| terraform | >= 0.12.0, < 0.14.0 |
6-
| local | ~> 1.2 |
7-
| random | ~> 2.2 |
5+
| terraform | >= 0.12.0, < 0.13.0 |
6+
| gitlab | >= 2.10 |
7+
| kubernetes | >= 1.11 |
88

99
## Providers
1010

1111
| Name | Version |
1212
|------|---------|
13-
| random | ~> 2.2 |
13+
| gitlab | >= 2.10 |
14+
| kubernetes | >= 1.11 |
1415

1516
## Inputs
1617

1718
| Name | Description | Type | Default | Required |
1819
|------|-------------|------|---------|:--------:|
19-
| example | Example variable | `string` | `"hello world"` | no |
20+
| cluster\_name | n/a | `string` | n/a | yes |
21+
| dns\_zone | (Required) specifies the DNS suffix for the externally-visible websites and services deployed in the cluster | `string` | n/a | yes |
22+
| enabled | n/a | `bool` | `true` | no |
23+
| group\_gitlab\_runner\_enabled | (Optional) Setup a gitlab group runner (will be used a group runner token to set GITLAB\_RUNNER\_TOKEN env variable) | `bool` | `false` | no |
24+
| kubernetes\_ca\_cert | (Required) PEM-encoded root certificates bundle for TLS authentication | `string` | n/a | yes |
25+
| kubernetes\_endpoint | (Required) The hostname (in form of URI) of Kubernetes master. | `string` | n/a | yes |
26+
| kubernetes\_token | (Required) Token of your service account, must have admin permission to create another service accounts | `string` | n/a | yes |
27+
| root\_gitlab\_group | (Semi-optional) A gitlab group id attach Kubernetes cluster to | `string` | `""` | no |
28+
| root\_gitlab\_project | (Semi-optional) A gitlab project id attach Kubernetes cluster to | `string` | `""` | no |
29+
| stage | (Required) Stage, e.g. 'prod', 'staging', 'dev' or 'testing' | `string` | n/a | yes |
2030

2131
## Outputs
2232

23-
| Name | Description |
24-
|------|-------------|
25-
| example | Example output |
33+
No output.
2634

main.tf

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,87 @@
1-
resource "random_integer" "example" {
2-
min = 1
3-
max = 50000
4-
keepers = {
5-
example = var.example
1+
locals {
2+
sa_name = "gitlab-admin"
3+
sa_namespace = "kube-system"
4+
5+
environment_scope = var.stage
6+
project_cluster_enabled = var.enabled && length(var.root_gitlab_project) > 0 ? 1 : 0
7+
group_cluster_enabled = var.enabled && length(var.root_gitlab_group) > 0 ? 1 : 0
8+
group_gitlab_runner_enabled = (var.group_gitlab_runner_enabled && length(var.root_gitlab_group) > 0) ? 1 : 0
9+
10+
cluster_name = var.cluster_name
11+
domain = var.dns_zone
12+
}
13+
14+
# In the next steps we will add a few env variables to Gitlab CI variables
15+
# to make possible run CI jobs that depends on these variables
16+
data "gitlab_project" "root" {
17+
count = local.project_cluster_enabled
18+
id = var.root_gitlab_project
19+
}
20+
21+
data "gitlab_group" "root" {
22+
count = length(var.root_gitlab_group) > 0 ? 1 : 0
23+
group_id = length(var.root_gitlab_group) > 0 ? var.root_gitlab_group : 0
24+
}
25+
26+
module "gitlab_admin_sa" {
27+
source = "./modules/gitlab-admin-service-account"
28+
29+
enabled = var.enabled
30+
31+
kubernetes_endpoint = var.kubernetes_endpoint
32+
kubernetes_token = var.kubernetes_token
33+
kubernetes_ca_cert = var.kubernetes_ca_cert
34+
}
35+
36+
# https://www.terraform.io/docs/providers/gitlab/r/project_cluster.html
37+
data "kubernetes_secret" "gitlab_admin_token" {
38+
count = var.enabled ? 1 : 0
39+
40+
metadata {
41+
name = module.gitlab_admin_sa.sa_name
42+
namespace = local.sa_namespace
643
}
744
}
845

9-
locals {
10-
example = format("%v %d", var.example, random_integer.example.result)
46+
resource "gitlab_project_cluster" "root" {
47+
count = local.project_cluster_enabled
48+
project = join("", data.gitlab_project.root.*.id)
49+
50+
name = local.cluster_name
51+
domain = local.domain
52+
53+
kubernetes_api_url = var.kubernetes_endpoint
54+
kubernetes_token = join(",", data.kubernetes_secret.gitlab_admin_token.*.data.token)
55+
kubernetes_ca_cert = base64decode(var.kubernetes_ca_cert)
56+
57+
environment_scope = local.environment_scope
58+
59+
lifecycle {
60+
ignore_changes = [kubernetes_ca_cert]
61+
}
62+
}
63+
64+
resource "gitlab_group_cluster" "root" {
65+
count = local.group_cluster_enabled
66+
67+
group = join("", data.gitlab_group.root.*.id)
68+
69+
name = local.cluster_name
70+
domain = local.domain
71+
72+
kubernetes_api_url = var.kubernetes_endpoint
73+
kubernetes_token = join(",", data.kubernetes_secret.gitlab_admin_token.*.data.token)
74+
kubernetes_ca_cert = base64decode(var.kubernetes_ca_cert)
75+
76+
## You can use only one Kubernetes cluster per a group/project when your team uses a free plan on Gitlab.com
77+
## If you will set explicitly env scope you can't use Auto DevOps feature
78+
##
79+
## References:
80+
## - https://docs.gitlab.com/12.5/ee/topics/autodevops/index.html#overview
81+
## - https://gitlab.com/gitlab-org/gitlab-foss/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
82+
environment_scope = local.environment_scope
83+
84+
lifecycle {
85+
ignore_changes = [kubernetes_ca_cert]
86+
}
1187
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
locals {
2+
sa_name = "gitlab-admin"
3+
sa_namespace = "kube-system"
4+
}
5+
6+
# This module create a service account with admin permissions for Gitlab Kubernetes integration
7+
#
8+
# - https://gitlab.com/help/user/project/clusters/add_remove_clusters#add-existing-cluster
9+
resource "kubernetes_service_account" "gitlab_admin_service_account" {
10+
count = var.enabled ? 1 : 0
11+
12+
metadata {
13+
name = local.sa_name
14+
namespace = local.sa_namespace
15+
}
16+
}
17+
18+
resource "kubernetes_cluster_role_binding" "gitlab_admin_cluster_role_binding" {
19+
count = var.enabled ? 1 : 0
20+
21+
metadata {
22+
name = local.sa_name
23+
}
24+
25+
role_ref {
26+
api_group = "rbac.authorization.k8s.io"
27+
kind = "ClusterRole"
28+
name = "cluster-admin"
29+
}
30+
31+
subject {
32+
kind = "ServiceAccount"
33+
name = "gitlab-admin"
34+
namespace = "kube-system"
35+
}
36+
}
37+
38+
output "sa_name" {
39+
value = join(",", kubernetes_service_account.gitlab_admin_service_account.*.default_secret_name)
40+
}
41+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
variable "enabled" {
2+
type = bool
3+
default = true
4+
}
5+
6+
variable "kubernetes_endpoint" {
7+
type = string
8+
}
9+
10+
variable "kubernetes_token" {
11+
type = string
12+
}
13+
14+
variable "kubernetes_ca_cert" {
15+
type = string
16+
}

outputs.tf

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +0,0 @@
1-
output "example" {
2-
description = "Example output"
3-
value = local.example
4-
}

providers.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# https://www.terraform.io/docs/providers/kubernetes/index.html
2+
3+
provider "kubernetes" {
4+
load_config_file = "false"
5+
6+
host = var.kubernetes_endpoint
7+
token = var.kubernetes_token
8+
cluster_ca_certificate = base64decode(var.kubernetes_ca_cert)
9+
}

0 commit comments

Comments
 (0)