diff --git a/.tflint.hcl b/.tflint.hcl index 81e0b17..e5c757b 100644 --- a/.tflint.hcl +++ b/.tflint.hcl @@ -5,9 +5,9 @@ plugin "aws" { } config { -#Enables module inspection -module = false -force = false + # Enables module inspection (Updated to the correct attribute) + call_module_type = "none" + force = false } # Required that all AWS resources have specified tags. @@ -19,94 +19,93 @@ rule "aws_resource_missing_tags" { ] } -# Disallow deprecated (0.11-style) interpolation +# Disallow deprecated (0.11-style) interpolation. rule "terraform_deprecated_interpolation" { -enabled = true + enabled = true } # Disallow legacy dot index syntax. rule "terraform_deprecated_index" { -enabled = true + enabled = true } # Disallow variables, data sources, and locals that are declared but never used. rule "terraform_unused_declarations" { -enabled = true + enabled = true } # Disallow // comments in favor of #. rule "terraform_comment_syntax" { -enabled = false + enabled = false } # Disallow output declarations without description. rule "terraform_documented_outputs" { -enabled = true + enabled = true } # Disallow variable declarations without description. rule "terraform_documented_variables" { -enabled = true + enabled = true } # Disallow variable declarations without type. rule "terraform_typed_variables" { -enabled = true + enabled = true } # Disallow specifying a git or mercurial repository as a module source without pinning to a version. rule "terraform_module_pinned_source" { -enabled = true + enabled = true } -# Enforces naming conventions +# Enforces naming conventions. rule "terraform_naming_convention" { -enabled = true + enabled = true -#Require specific naming structure -variable { -format = "snake_case" -} + # Require specific naming structure. + variable { + format = "snake_case" + } -locals { -format = "snake_case" -} + locals { + format = "snake_case" + } -output { -format = "snake_case" -} + output { + format = "snake_case" + } -#Allow any format -resource { -format = "none" -} + # Allow any format. + resource { + format = "none" + } -module { -format = "none" -} - -data { -format = "none" -} + module { + format = "none" + } + data { + format = "none" + } } # Disallow terraform declarations without require_version. rule "terraform_required_version" { -enabled = true + enabled = true } # Require that all providers have version constraints through required_providers. rule "terraform_required_providers" { -enabled = true + enabled = true } -# Ensure that a module complies with the Terraform Standard Module Structure +# Ensure that a module complies with the Terraform Standard Module Structure. rule "terraform_standard_module_structure" { -enabled = true + enabled = true } # terraform.workspace should not be used with a "remote" backend with remote execution. rule "terraform_workspace_remote" { -enabled = true + enabled = true } diff --git a/README.md b/README.md index fa14041..27c35cd 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,9 @@ No modules. | Name | Type | |------|------| | [helm_release.sonarqube](https://registry.terraform.io/providers/hashicorp/helm/latest/docs/resources/release) | resource | +| [kubernetes_manifest.migration_job](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource | | [kubernetes_namespace.sonarqube](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource | +| [random_password.monitoringPasscode](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | | [random_password.postgresql_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | | [random_password.sonarqube_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | @@ -80,9 +82,13 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [chart\_version](#input\_chart\_version) | Version of the Jenkins chart that will be used to deploy Jenkins application. | `string` | `"10.6.1"` | no | +| [chart\_version](#input\_chart\_version) | Version of the Jenkins chart that will be used to deploy Jenkins application. | `string` | `"2025.2.0"` | no | | [namespace](#input\_namespace) | Name of the Kubernetes namespace where the Jenkins deployment will be deployed. | `string` | `"sonarqube"` | no | -| [sonarqube\_config](#input\_sonarqube\_config) | Specify the configuration settings for Sonarqube, including the hostname, storage options, and custom YAML values. | `any` |
{
"grafana_monitoring_enabled": false,
"hostname": "",
"postgresql_external_server_url": "",
"postgresql_password_external": "",
"postgresql_volume_size": "",
"sonarqube_volume_size": "",
"storage_class_name": "",
"values_yaml": ""
}
| no | +<<<<<<< HEAD +| [sonarqube\_config](#input\_sonarqube\_config) | Specify the configuration settings for Sonarqube, including the hostname, storage options, and custom YAML values. | `any` |
{
"grafana_monitoring_enabled": false,
"hostname": "",
"postgresql_external_server_url": "",
"postgresql_password_external": "",
"postgresql_volume_size": "",
"sonarqube_volume_size": "",
"storage_class_name": "",
"updateExistingSonarqube": false,
"values_yaml": ""
}
| no | +======= +| [sonarqube\_config](#input\_sonarqube\_config) | Specify the configuration settings for Sonarqube, including the hostname, storage options, and custom YAML values. | `any` |
{
"grafana_monitoring_enabled": false,
"hostname": "",
"postgresql_external_server_url": "",
"postgresql_password_external": "",
"postgresql_volume_size": "",
"sonarqube_volume_size": "",
"storage_class_name": "",
"values_yaml": ""
}
| no | +>>>>>>> 2d71186b50e076f45ab7e6a587037b5bb0c435ff ## Outputs diff --git a/examples/complete/aws/README.md b/examples/complete/aws/README.md index 4b9f10e..def54f5 100644 --- a/examples/complete/aws/README.md +++ b/examples/complete/aws/README.md @@ -50,8 +50,7 @@ No requirements. | Name | Source | Version | |------|--------|---------| - -| [sonarqube](#module\_sonarqube) | squareops/sonarqube/kubernetes | 3.0.1 | +| [sonarqube](#module\_sonarqube) | squareops/sonarqube/kubernetes | 3.1.0 | ## Resources diff --git a/examples/complete/aws/helm/values.yaml b/examples/complete/aws/helm/values.yaml index 9c49a96..5180589 100644 --- a/examples/complete/aws/helm/values.yaml +++ b/examples/complete/aws/helm/values.yaml @@ -1,10 +1,11 @@ resources: limits: - cpu: 500m - memory: 2Gi + cpu: 700m + memory: 6144M requests: - cpu: 200m - memory: 1.5Gi + cpu: 300m + memory: 2048M + affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: diff --git a/examples/complete/aws/main.tf b/examples/complete/aws/main.tf index be1e964..a2f415c 100644 --- a/examples/complete/aws/main.tf +++ b/examples/complete/aws/main.tf @@ -8,18 +8,24 @@ locals { Department = "Engineering" } } - module "sonarqube" { - source = "squareops/sonarqube/kubernetes" - version = "3.0.1" + source = "squareops/sonarqube/kubernetes" + version = "3.1.1" sonarqube_config = { hostname = "sonarqube.squareops.in" values_yaml = file("./helm/values.yaml") storage_class_name = "gp2" sonarqube_volume_size = "5Gi" - postgresql_volume_size = "20Gi" + postgresql_volume_size = "10Gi" grafana_monitoring_enabled = false + monitoringPasscode = "" postgresql_password_external = "" postgresql_external_server_url = "" + sonarqube_password = "xxxxx" + + updateExistingSonarqube = false # if you have existing sonarqube and want to upgrade,then enable it. + updateExistingSonarqubePassword = false #if you want to update password,enable it and pass sonarqube_current_password(old),sonarqube_password(new) + sonarqube_current_password = "xxxxxx" # if you upgrade sonarqube then you have to provide your previous sonarqube password ##Secret name=sonarqube-sonarqube-admin-password + postgresql_current_password = "xxxxxxx" # if you upgrade sonarqube then you have to provide your previous postgresql password ##Secret name=sonarqube-postgresql } } diff --git a/examples/complete/azure/README.md b/examples/complete/azure/README.md index d24986f..6467b76 100644 --- a/examples/complete/azure/README.md +++ b/examples/complete/azure/README.md @@ -50,7 +50,7 @@ No requirements. | Name | Source | Version | |------|--------|---------| -| [sonarqube](#module\_sonarqube) | squareops/sonarqube/kubernetes | 3.0.1 | +| [sonarqube](#module\_sonarqube) | squareops/sonarqube/kubernetes | 3.1.0 | ## Resources diff --git a/examples/complete/azure/main.tf b/examples/complete/azure/main.tf index 426d042..c6213b2 100644 --- a/examples/complete/azure/main.tf +++ b/examples/complete/azure/main.tf @@ -1,7 +1,7 @@ locals { - name = "sonarqube" + name = "" region = "" - environment = "prod" + environment = "" additional_tags = { Owner = "organization_name" Expires = "Never" @@ -10,16 +10,23 @@ locals { } module "sonarqube" { - source = "squareops/sonarqube/kubernetes" - version = "3.0.1" + source = "squareops/sonarqube/kubernetes" + version = "3.1.1" sonarqube_config = { - hostname = "sonarqube.skaf.squareops.in" + hostname = "sonarqube.squareops.in" values_yaml = file("./helm/values.yaml") - storage_class_name = "infra-service-sc" + storage_class_name = "gp2" sonarqube_volume_size = "5Gi" - postgresql_volume_size = "20Gi" + postgresql_volume_size = "10Gi" grafana_monitoring_enabled = false - postgresql_password_external = "admin" + monitoringPasscode = "" + postgresql_password_external = "" postgresql_external_server_url = "" + sonarqube_password = "" + + updateExistingSonarqube = false # if you have existing sonarqube and want to upgrade,then enable it. + updateExistingSonarqubePassword = false #if you want to update password,enable it and pass sonarqube_current_password(old),sonarqube_password(new) + sonarqube_current_password = "xxxxxx" # if you upgrade sonarqube then you have to provide your previous sonarqube password ##Secret name=sonarqube-sonarqube-admin-password + postgresql_current_password = "xxxxxxx" # if you upgrade sonarqube then you have to provide your previous postgresql password ##Secret name=sonarqube-postgresql } } diff --git a/examples/complete/gcp/README.md b/examples/complete/gcp/README.md index f198771..e21b219 100644 --- a/examples/complete/gcp/README.md +++ b/examples/complete/gcp/README.md @@ -50,7 +50,7 @@ No requirements. | Name | Source | Version | |------|--------|---------| -| [sonarqube](#module\_sonarqube) | squareops/sonarqube/kubernetes | 3.0.1 | +| [sonarqube](#module\_sonarqube) | squareops/sonarqube/kubernetes | 3.1.0 | ## Resources diff --git a/examples/complete/gcp/main.tf b/examples/complete/gcp/main.tf index f12a286..c6213b2 100644 --- a/examples/complete/gcp/main.tf +++ b/examples/complete/gcp/main.tf @@ -1,7 +1,7 @@ locals { - name = "sonarqube" + name = "" region = "" - environment = "prod" + environment = "" additional_tags = { Owner = "organization_name" Expires = "Never" @@ -10,16 +10,23 @@ locals { } module "sonarqube" { - source = "squareops/sonarqube/kubernetes" - version = "3.0.1" + source = "squareops/sonarqube/kubernetes" + version = "3.1.1" sonarqube_config = { hostname = "sonarqube.squareops.in" values_yaml = file("./helm/values.yaml") storage_class_name = "gp2" sonarqube_volume_size = "5Gi" - postgresql_volume_size = "20Gi" + postgresql_volume_size = "10Gi" grafana_monitoring_enabled = false + monitoringPasscode = "" postgresql_password_external = "" postgresql_external_server_url = "" + sonarqube_password = "" + + updateExistingSonarqube = false # if you have existing sonarqube and want to upgrade,then enable it. + updateExistingSonarqubePassword = false #if you want to update password,enable it and pass sonarqube_current_password(old),sonarqube_password(new) + sonarqube_current_password = "xxxxxx" # if you upgrade sonarqube then you have to provide your previous sonarqube password ##Secret name=sonarqube-sonarqube-admin-password + postgresql_current_password = "xxxxxxx" # if you upgrade sonarqube then you have to provide your previous postgresql password ##Secret name=sonarqube-postgresql } } diff --git a/helm/values.yaml b/helm/values.yaml index 5a1e353..b40ac17 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -1,65 +1,67 @@ +community: + enabled: true + +setAdminPassword: + newPassword: "${sonarqube_password}" + currentPassword: "${sonarqube_current_password}" + +monitoringPasscode: "${monitoringPasscode}" + +postgresql: + enabled: "${postgresql_enable}" + postgresqlPassword: "${postgresql_password}" + persistence: + storageClass: "${sonarqube_sc}" + size: 20Gi + resources: + limits: + cpu: 200m + memory: 1Gi + requests: + cpu: 100m + memory: 200Mi + +persistence: + enabled: true + storageClass: "${sonarqube_sc}" + accessMode: ReadWriteOnce + size: "${volume_size}" + uid: 1000 + guid: 0 + resources: limits: cpu: 800m - memory: 4Gi + memory: 6144M requests: - cpu: 100m - memory: 2Gi + cpu: 400m + memory: 2048M annotations: co.elastic.logs/enabled: "true" -persistence: - enabled: true - storageClass: ${sonarqube_sc} - accessMode: ReadWriteOnce - size: ${volume_size} - uid: 1000 - ingress: enabled: true hosts: - - name: ${hostname} - + - name: "${hostname}" annotations: kubernetes.io/ingress.class: "nginx" kubernetes.io/tls-acme: "true" cert-manager.io/cluster-issuer: "letsencrypt-prod" nginx.ingress.kubernetes.io/proxy-body-size: "500m" - tls: - secretName: sonarqube hosts: - - ${hostname} + - "${hostname}" affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: - matchExpressions: - key: "Addons-Services" operator: In values: - - "true" - -account: - adminPassword: "${sonarqube_password}" - + - "true" prometheusExporter: enabled: "${prometheus_exporter_enable}" - -postgresql: -# # Enable to deploy the PostgreSQL chart - enabled: ${postgresql_enable} - postgresqlPassword: "${postgresql_password}" - persistence: - enabled: true - size: ${postgresql_disk_size} - storageClass: ${sonarqube_sc} - resources: - limits: - cpu: 200m - memory: 1Gi - requests: - cpu: 100m - memory: 200Mi diff --git a/main.tf b/main.tf index 4a258c2..88b1440 100644 --- a/main.tf +++ b/main.tf @@ -1,15 +1,22 @@ locals { count = var.sonarqube_config.postgresql_external_server_url != "" ? [] : [1] + + effective_sonarqube_password = var.sonarqube_config.sonarqube_password != "" ? var.sonarqube_config.sonarqube_password : random_password.sonarqube_password.result + + effective_postgresql_password = var.sonarqube_config.postgresql_current_password != "" && var.sonarqube_config.updateExistingSonarqube == true ? var.sonarqube_config.postgresql_current_password : random_password.postgresql_password.result } resource "random_password" "sonarqube_password" { length = 20 - special = false + special = true } resource "random_password" "postgresql_password" { length = 20 - special = false + special = true +} +resource "random_password" "monitoringPasscode" { + length = 20 + special = true } - resource "kubernetes_namespace" "sonarqube" { metadata { name = var.namespace @@ -26,16 +33,18 @@ resource "helm_release" "sonarqube" { repository = "https://sonarsource.github.io/helm-chart-sonarqube" values = [ templatefile("${path.module}/helm/values.yaml", { + monitoringPasscode = var.sonarqube_config.monitoringPasscode != "" ? var.sonarqube_config.monitoringPasscode : random_password.monitoringPasscode.result hostname = var.sonarqube_config.hostname volume_size = var.sonarqube_config.sonarqube_volume_size sonarqube_sc = var.sonarqube_config.storage_class_name postgresql_enable = var.sonarqube_config.postgresql_external_server_url != "" ? false : true - sonarqube_password = random_password.sonarqube_password.result - postgresql_password = random_password.postgresql_password.result + sonarqube_password = local.effective_sonarqube_password + sonarqube_current_password = var.sonarqube_config.updateExistingSonarqube == true ? var.sonarqube_config.sonarqube_current_password : "admin" + postgresql_password = local.effective_postgresql_password postgresql_disk_size = var.sonarqube_config.postgresql_volume_size prometheus_exporter_enable = var.sonarqube_config.grafana_monitoring_enabled - postgresql_password_external = var.sonarqube_config.postgresql_password_external postgresql_external_server_url = var.sonarqube_config.postgresql_external_server_url + postgresql_password_external = var.sonarqube_config.postgresql_password_external }), var.sonarqube_config.values_yaml @@ -56,3 +65,82 @@ resource "helm_release" "sonarqube" { } } } +resource "kubernetes_manifest" "migration_job" { + count = var.sonarqube_config.updateExistingSonarqube ? 1 : 0 + manifest = { + apiVersion = "batch/v1" + kind = "Job" + metadata = { + name = "db-migration-watcher-job" + namespace = "sonarqube" + } + spec = { + backoffLimit = 4 + completions = 1 + parallelism = 1 + template = { + spec = { + restartPolicy = "Never" + containers = [ + { + name = "db-migration-watcher" + image = "alpine:latest" + command = [ + "/bin/sh", "-c", <<-EOT + sleep 180 && + apk add --no-cache curl && + curl -s -X POST -u admin:"${var.sonarqube_config.sonarqube_current_password}" "http://sonarqube-sonarqube:9000/api/system/migrate_db" && + echo "DB Migration triggered. Exiting watcher." + EOT + ] + } + ] + } + } + } + } +} + + +resource "kubernetes_manifest" "sonarqube_password_reset_job" { + count = var.sonarqube_config.updateExistingSonarqubePassword ? 1 : 0 + + manifest = { + apiVersion = "batch/v1" + kind = "Job" + metadata = { + name = "sonarqube-password-reset" + namespace = "sonarqube" + } + spec = { + backoffLimit = 4 + completions = 1 + parallelism = 1 + ttlSecondsAfterFinished: 60 + template = { + spec = { + restartPolicy = "Never" + containers = [ + { + name = "password-reset" + image = "curlimages/curl:8.5.0" + command = [ + "sh", "-c", <<-EOT + echo "Resetting SonarQube admin password..." && + curl -s -X POST -u admin:"${var.sonarqube_config.sonarqube_current_password}" \ + "http://sonarqube-sonarqube:9000/api/users/change_password" \ + --data-urlencode "login=admin" \ + --data-urlencode "previousPassword=${var.sonarqube_config.sonarqube_current_password}" \ + --data-urlencode "password=${var.sonarqube_config.sonarqube_password}" \ + -w "%%{http_code}" -o /dev/null + echo "Password change complete." + EOT + ] + } + ] + } + } + } + } +} + diff --git a/outputs.tf b/outputs.tf index 5d69399..832267d 100644 --- a/outputs.tf +++ b/outputs.tf @@ -2,13 +2,13 @@ output "sonarqube" { description = "Sonarqube Credentials " value = { username = "admin", - password = nonsensitive(random_password.sonarqube_password.result), + password = nonsensitive(local.effective_sonarqube_password), url = var.sonarqube_config.hostname } } output "sonarqube_postgresql_password" { - value = random_password.postgresql_password.result + value = nonsensitive(local.effective_postgresql_password) description = "Password for the PostgreSQL database deployed with SonarQube" sensitive = true } diff --git a/variables.tf b/variables.tf index de8fc93..07eaa35 100644 --- a/variables.tf +++ b/variables.tf @@ -9,16 +9,18 @@ variable "sonarqube_config" { grafana_monitoring_enabled = false postgresql_password_external = "" postgresql_external_server_url = "" + updateExistingSonarqube = false } description = "Specify the configuration settings for Sonarqube, including the hostname, storage options, and custom YAML values." } variable "chart_version" { type = string - default = "10.6.1" + default = "2025.2.0" description = "Version of the Jenkins chart that will be used to deploy Jenkins application." } + variable "namespace" { type = string default = "sonarqube"