Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
- master

env:
TERRAFORM_DOCS_VERSION: v0.16.0
TERRAFORM_DOCS_VERSION: v0.24.0
TFLINT_VERSION: v0.44.1

jobs:
Expand Down
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ The CronJob is rendered from `templates/lean-backup-cronjob.yaml.tpl` and applie
image tag is resolved automatically from the deployed release's GitLab application version (the
chart's appVersion / `global.gitlabVersion`) — so no version needs to be maintained here.

Secrets the release mounts one file at a time are not discovered automatically: list each one in
`extra_secret_projections` (`secret_name`, `key`, `path`) so the pod finds every file its rendered
config expects, otherwise it fails to start.

> **Chart upgrades:** because the template mirrors the chart's rendered toolbox backup pod spec, it
> must be re-synced after major GitLab chart upgrades that change the toolbox secret/volume topology.
> Regenerate it from the live CronJob: `kubectl -n <ns> get cronjob <release>-toolbox-backup -o yaml`.
Expand All @@ -45,7 +49,7 @@ chart's appVersion / `global.gitlabVersion`) — so no version needs to be maint
## Requirements

| Name | Version |
|------|---------|
| ---- | ------- |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.7 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.0 |
| <a name="requirement_helm"></a> [helm](#requirement\_helm) | 2.11.0 |
Expand All @@ -56,24 +60,24 @@ chart's appVersion / `global.gitlabVersion`) — so no version needs to be maint
## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | 6.55.0 |
| ---- | ------- |
| <a name="provider_aws"></a> [aws](#provider\_aws) | 6.64.0 |
| <a name="provider_helm"></a> [helm](#provider\_helm) | 2.11.0 |
| <a name="provider_kubectl"></a> [kubectl](#provider\_kubectl) | 2.4.1 |
| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | 3.2.1 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| ---- | ------ | ------- |
| <a name="module_gitlab_policy"></a> [gitlab\_policy](#module\_gitlab\_policy) | terraform-aws-modules/iam/aws//modules/iam-policy | v6.4.0 |
| <a name="module_gitlab_role"></a> [gitlab\_role](#module\_gitlab\_role) | terraform-aws-modules/iam/aws//modules/iam-role | v6.4.0 |
| <a name="module_s3_bucket"></a> [s3\_bucket](#module\_s3\_bucket) | terraform-aws-modules/s3-bucket/aws | 5.10.0 |

## Resources

| Name | Type |
|------|------|
| ---- | ---- |
| [helm_release.gitlab](https://registry.terraform.io/providers/hashicorp/helm/2.11.0/docs/resources/release) | resource |
| [kubectl_manifest.lean_backup](https://registry.terraform.io/providers/alekc/kubectl/latest/docs/resources/manifest) | resource |
| [kubernetes_namespace_v1.gitlab](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace_v1) | resource |
Expand All @@ -92,15 +96,15 @@ chart's appVersion / `global.gitlabVersion`) — so no version needs to be maint
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| ---- | ----------- | ---- | ------- | :------: |
| <a name="input_bucket_prefix"></a> [bucket\_prefix](#input\_bucket\_prefix) | Prefix used for S3 buckets | `string` | `""` | no |
| <a name="input_buckets_lifecycles"></a> [buckets\_lifecycles](#input\_buckets\_lifecycles) | Lifecycle rules for buckets | `map(string)` | `{}` | no |
| <a name="input_buckets_versioning"></a> [buckets\_versioning](#input\_buckets\_versioning) | Versioning for buckets | `map(bool)` | `{}` | no |
| <a name="input_cluster_name"></a> [cluster\_name](#input\_cluster\_name) | EKS cluster name where you want to deploy the release | `string` | n/a | yes |
| <a name="input_database_password"></a> [database\_password](#input\_database\_password) | Password to access PostgreSQL database | `string` | n/a | yes |
| <a name="input_gitlab_chart_version"></a> [gitlab\_chart\_version](#input\_gitlab\_chart\_version) | Version of the gitlab chart | `string` | `"7.8.1"` | no |
| <a name="input_ldap_password"></a> [ldap\_password](#input\_ldap\_password) | LDAP password | `string` | `""` | no |
| <a name="input_lean_backup"></a> [lean\_backup](#input\_lean\_backup) | Optional intraday "lean full" backup CronJob (db + repositories only; object-storage/blob<br>components skipped). Rendered as a clone of the chart's toolbox backup CronJob with only the<br>scheduling, resources and `--skip` arguments changed, so env/secrets/volumes stay faithful to<br>the chart. Disabled by default; set `enabled = true` to create it.<br><br>Images default to the toolbox/certificates/gitlab-base repositories taken from `values`, tagged<br>with the GitLab application version resolved from the deployed Helm release (the chart's<br>appVersion, or `global.gitlabVersion` if set) — so there is no image version to maintain here.<br>Supply the full `*_image` fields only to override. `name` defaults to<br>"<release\_name>-toolbox-backup-lean" and `service_account_name` to "<release\_name>-toolbox". | <pre>object({<br> enabled = optional(bool, false)<br> schedule = optional(string, "0 6,12,18 * * *")<br> name = optional(string, null)<br> toolbox_image = optional(string, null)<br> certificates_image = optional(string, null)<br> configure_image = optional(string, null)<br> service_account_name = optional(string, null)<br> rails_secret_name = optional(string, null)<br> concurrency_policy = optional(string, "Forbid")<br> restart_policy = optional(string, "Never")<br> active_deadline_seconds = optional(number, 2700)<br> backoff_limit = optional(number, 0)<br> successful_jobs_history_limit = optional(number, 1)<br> failed_jobs_history_limit = optional(number, 3)<br> ttl_seconds_after_finished = optional(number, 86400)<br> tmp_storage_size = optional(string, "30Gi")<br> skip = optional(list(string), [<br> "registry", "uploads", "pages", "packages", "external_diffs",<br> "ci_secure_files", "lfs", "artifacts", "terraform_state",<br> ])<br> node_selector = optional(map(string), {<br> provisioner = "gitlab-base"<br> nodetype = "gitlab-base"<br> })<br> tolerations = optional(list(object({<br> key = string<br> value = optional(string)<br> effect = string<br> operator = optional(string)<br> })), [{ key = "gitlab-base", value = "true", effect = "NoSchedule" }])<br> pod_annotations = optional(map(string), { "karpenter.sh/do-not-disrupt" = "true" })<br> resources = optional(any, { requests = { cpu = "500m", memory = "1G" } })<br> })</pre> | `{}` | no |
| <a name="input_lean_backup"></a> [lean\_backup](#input\_lean\_backup) | Optional intraday "lean full" backup CronJob (db + repositories only; object-storage/blob<br/>components skipped). Rendered as a clone of the chart's toolbox backup CronJob with only the<br/>scheduling, resources and `--skip` arguments changed, so env/secrets/volumes stay faithful to<br/>the chart. Disabled by default; set `enabled = true` to create it.<br/><br/>Images default to the toolbox/certificates/gitlab-base repositories taken from `values`, tagged<br/>with the GitLab application version resolved from the deployed Helm release (the chart's<br/>appVersion, or `global.gitlabVersion` if set) — so there is no image version to maintain here.<br/>Supply the full `*_image` fields only to override. `name` defaults to<br/>"<release\_name>-toolbox-backup-lean" and `service_account_name` to "<release\_name>-toolbox".<br/><br/>`extra_secret_projections` appends entries to the pod's projected secret volume, for secrets the<br/>chart mounts one file at a time and whose set the module cannot infer. Each entry projects<br/>`secret_name`'s `key` at `path`, relative to the config directory. The pod fails to render its<br/>config when a file the release expects is absent, so pass the complete set. | <pre>object({<br/> enabled = optional(bool, false)<br/> schedule = optional(string, "0 6,12,18 * * *")<br/> name = optional(string, null)<br/> toolbox_image = optional(string, null)<br/> certificates_image = optional(string, null)<br/> configure_image = optional(string, null)<br/> service_account_name = optional(string, null)<br/> rails_secret_name = optional(string, null)<br/> extra_secret_projections = optional(list(object({<br/> secret_name = string<br/> key = string<br/> path = string<br/> })), [])<br/> concurrency_policy = optional(string, "Forbid")<br/> restart_policy = optional(string, "Never")<br/> active_deadline_seconds = optional(number, 2700)<br/> backoff_limit = optional(number, 0)<br/> successful_jobs_history_limit = optional(number, 1)<br/> failed_jobs_history_limit = optional(number, 3)<br/> ttl_seconds_after_finished = optional(number, 86400)<br/> tmp_storage_size = optional(string, "30Gi")<br/> skip = optional(list(string), [<br/> "registry", "uploads", "pages", "packages", "external_diffs",<br/> "ci_secure_files", "lfs", "artifacts", "terraform_state",<br/> ])<br/> node_selector = optional(map(string), {<br/> provisioner = "gitlab-base"<br/> nodetype = "gitlab-base"<br/> })<br/> tolerations = optional(list(object({<br/> key = string<br/> value = optional(string)<br/> effect = string<br/> operator = optional(string)<br/> })), [{ key = "gitlab-base", value = "true", effect = "NoSchedule" }])<br/> pod_annotations = optional(map(string), { "karpenter.sh/do-not-disrupt" = "true" })<br/> resources = optional(any, { requests = { cpu = "500m", memory = "1G" } })<br/> })</pre> | `{}` | no |
| <a name="input_namespace_labels"></a> [namespace\_labels](#input\_namespace\_labels) | Labels for GitLab namespace | `map(string)` | `{}` | no |
| <a name="input_omniauth_providers"></a> [omniauth\_providers](#input\_omniauth\_providers) | OmniAuth providers | `map(string)` | `{}` | no |
| <a name="input_redis_password"></a> [redis\_password](#input\_redis\_password) | Password to access Redis database | `string` | n/a | yes |
Expand All @@ -118,7 +122,7 @@ chart's appVersion / `global.gitlabVersion`) — so no version needs to be maint
## Outputs

| Name | Description |
|------|-------------|
| ---- | ----------- |
| <a name="output_buckets"></a> [buckets](#output\_buckets) | List of buckets created |
| <a name="output_lean_backup_cronjob_name"></a> [lean\_backup\_cronjob\_name](#output\_lean\_backup\_cronjob\_name) | Name of the lean backup CronJob, or null when lean\_backup is disabled |
| <a name="output_role_arn"></a> [role\_arn](#output\_role\_arn) | ARN of IAM role |
Expand Down
4 changes: 2 additions & 2 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
## Requirements

| Name | Version |
|------|---------|
| ---- | ------- |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.5.7 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 6.0 |
| <a name="requirement_helm"></a> [helm](#requirement\_helm) | 2.11.0 |
Expand All @@ -17,7 +17,7 @@ No providers.
## Modules

| Name | Source | Version |
|------|--------|---------|
| ---- | ------ | ------- |
| <a name="module_gitlab"></a> [gitlab](#module\_gitlab) | ../ | n/a |

## Resources
Expand Down
13 changes: 13 additions & 0 deletions locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,20 @@ locals {
"logging/type" = "gitlab"
}, local.lean.pod_annotations)

# Caller-supplied projections appended to the pod's projected secret volume. The release mounts
# some secrets one file at a time and fails to render its config when an expected file is absent,
# so the set is passed in rather than assumed - one entry, several, or none all render correctly.
lean_extra_secret_projections = [
for s in local.lean.extra_secret_projections : {
secret = {
name = s.secret_name
items = [{ key = s.key, path = s.path }]
}
}
]

# Pre-indented YAML fragments injected into the CronJob template.
lean_extra_sources_yaml = length(local.lean_extra_secret_projections) > 0 ? indent(14, trimspace(yamlencode(local.lean_extra_secret_projections))) : ""
lean_node_selector_yaml = indent(12, trimspace(yamlencode(local.lean.node_selector)))
lean_tolerations_yaml = indent(12, trimspace(yamlencode(local.lean_tolerations)))
lean_pod_annotations_yaml = indent(12, trimspace(yamlencode(local.lean_pod_annotations)))
Expand Down
1 change: 1 addition & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ resource "kubectl_manifest" "lean_backup" {
tolerations_yaml = local.lean_tolerations_yaml
pod_annotations_yaml = local.lean_pod_annotations_yaml
resources_yaml = local.lean_resources_yaml
extra_sources_yaml = local.lean_extra_sources_yaml
})

server_side_apply = true
Expand Down
6 changes: 1 addition & 5 deletions templates/lean-backup-cronjob.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -303,11 +303,7 @@ spec:
- key: connection
path: objectstorage/ci_secure_files
name: ${release_name}-rails-storage
- secret:
items:
- key: provider
path: omniauth/gitlab-google-oauth2/provider
name: gitlab-google-oauth2
${extra_sources_yaml}
- name: toolbox-secrets
emptyDir:
medium: Memory
Expand Down
26 changes: 18 additions & 8 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -132,17 +132,27 @@ variable "lean_backup" {
appVersion, or `global.gitlabVersion` if set) — so there is no image version to maintain here.
Supply the full `*_image` fields only to override. `name` defaults to
"<release_name>-toolbox-backup-lean" and `service_account_name` to "<release_name>-toolbox".

`extra_secret_projections` appends entries to the pod's projected secret volume, for secrets the
chart mounts one file at a time and whose set the module cannot infer. Each entry projects
`secret_name`'s `key` at `path`, relative to the config directory. The pod fails to render its
config when a file the release expects is absent, so pass the complete set.
EOT

type = object({
enabled = optional(bool, false)
schedule = optional(string, "0 6,12,18 * * *")
name = optional(string, null)
toolbox_image = optional(string, null)
certificates_image = optional(string, null)
configure_image = optional(string, null)
service_account_name = optional(string, null)
rails_secret_name = optional(string, null)
enabled = optional(bool, false)
schedule = optional(string, "0 6,12,18 * * *")
name = optional(string, null)
toolbox_image = optional(string, null)
certificates_image = optional(string, null)
configure_image = optional(string, null)
service_account_name = optional(string, null)
rails_secret_name = optional(string, null)
extra_secret_projections = optional(list(object({
secret_name = string
key = string
path = string
})), [])
concurrency_policy = optional(string, "Forbid")
restart_policy = optional(string, "Never")
active_deadline_seconds = optional(number, 2700)
Expand Down
Loading