From be04a91be357a1b71b94ca90b3ffada87a8f4c03 Mon Sep 17 00:00:00 2001 From: Joseph Page Date: Mon, 25 Sep 2023 18:19:14 +0200 Subject: [PATCH] ci: add Terraform to configure Scalingo and MEP --- .env.scalingo | 29 +++++ .github/renovate.json | 5 +- .github/workflows/mise-en-production.yml | 68 +++++++++++ .github/workflows/release-please.yml | 9 +- .../{test-ci.yml => run-unit-tests.yml} | 11 +- .github/workflows/terraform-pr.yml | 24 ++++ .github/workflows/terraform-recette.yml | 19 +++ .gitignore | 7 ++ config/database.ts | 26 ++-- config/sentry/index.ts | 2 +- package.json | 5 +- terraform/.terraform.lock.hcl | 115 ++++++++++++++++++ terraform/app.tf | 48 ++++++++ terraform/cdn.tf | 16 +++ terraform/locals.tf | 22 ++++ terraform/variables.tf | 33 +++++ terraform/versions.tf | 74 +++++++++++ 17 files changed, 489 insertions(+), 24 deletions(-) create mode 100644 .env.scalingo create mode 100644 .github/workflows/mise-en-production.yml rename .github/workflows/{test-ci.yml => run-unit-tests.yml} (51%) create mode 100644 .github/workflows/terraform-pr.yml create mode 100644 .github/workflows/terraform-recette.yml create mode 100644 terraform/.terraform.lock.hcl create mode 100644 terraform/app.tf create mode 100644 terraform/cdn.tf create mode 100644 terraform/locals.tf create mode 100644 terraform/variables.tf create mode 100644 terraform/versions.tf diff --git a/.env.scalingo b/.env.scalingo new file mode 100644 index 00000000..240c4684 --- /dev/null +++ b/.env.scalingo @@ -0,0 +1,29 @@ +# Configuration de NPM +NODE_MODULES_CACHE="${NODE_MODULES_CACHE:-true}" +NPM_CONFIG_PRODUCTION="${NPM_CONFIG_PRODUCTION:-true}" + +# Configuration de Strapi +DATABASE_URL='$SCALINGO_POSTGRESQL_URL' +ADMIN_JWT_SECRET="${ADMIN_JWT_SECRET}" +API_TOKEN_SALT="${ADMIN_JWT_SECRET}" +APP_KEYS="${APP_KEYS}" +JWT_SECRET="${JWT_SECRET}" +STRAPI_TELEMETRY_DISABLED="${STRAPI_TELEMETRY_DISABLED:-true}" + +# Minio utilisé pour le stockage des médias +MINIO_ACCESS_KEY="${MINIO_ACCESS_KEY}" +MINIO_BUCKET="${MINIO_BUCKET}" +MINIO_ENDPOINT="${MINIO_ENDPOINT}" +MINIO_SECRET_KEY="${MINIO_SECRET_KEY}" + +# MeiliSearch +PLUGIN_MEILISEARCH_API_KEY="${PLUGIN_MEILISEARCH_API_KEY}" +PLUGIN_MEILISEARCH_URL="${PLUGIN_MEILISEARCH_URL}" +MEILISEARCH_BATCH_SIZE="${MEILISEARCH_BATCH_SIZE:-100}" + +# Sentry +SENTRY_DSN="${SENTRY_DSN}" +SENTRY_ENVIRONMENT="${SENTRY_ENVIRONMENT}" # "production", "recette" or "dev" + +# Variables auto-configurées par Scalingo : +# - SCALINGO_POSTGRESQL_URL diff --git a/.github/renovate.json b/.github/renovate.json index 4a0d2a05..f7ff3cbd 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,4 +1,7 @@ { "enabled": true, - "extends": ["github>SocialGouv/renovate-config"] + "extends": ["github>SocialGouv/renovate-config"], + "nvm": { + "enabled": true + } } diff --git a/.github/workflows/mise-en-production.yml b/.github/workflows/mise-en-production.yml new file mode 100644 index 00000000..967bf3b2 --- /dev/null +++ b/.github/workflows/mise-en-production.yml @@ -0,0 +1,68 @@ +name: Mise en production + +on: + workflow_dispatch: + inputs: + purge_cloudflare_cache: + description: 'Faut-il vider le cache Cloudflare après le déploiement ?' + type: boolean + default: false + +jobs: + backup: + name: Sauvegarder la base de données PostgreSQL + runs-on: ubuntu-latest + environment: + name: scalingo-production + url: https://www.1jeune1solution.gouv.fr + steps: + - name: Configurer la CLI Scalingo + uses: scalingo-community/setup-scalingo@v0.1.1 + with: + api_token: ${{ secrets.SCALINGO_API_TOKEN }} + region: ${{ vars.SCALINGO_REGION }} + app_name: ${{ secrets.TF_VAR_NOM_DE_L_APPLICATION }} + - name: Créer une sauvegarde de la base PostgreSQL Scalingo + run: | + POSTGRESQL_ADDON_ID=$(scalingo addons | grep -i postgresql | awk 'BEGIN{FS=" [|] "}{print $2}') + scalingo backups-create --addon $POSTGRESQL_ADDON_ID + + terraform: + uses: DNUM-SocialGouv/1j1s-front/.github/workflows/terraform-template.yml@main + secrets: inherit + with: + apply: true + environnement_name: scalingo-production + environnement_url: https://www.1jeune1solution.gouv.fr + concurrency: terraform-state-production # Evite les conflits sur le state Terraform + + deployment: + name: Déployer le code sur Scalingo + needs: [terraform, backup] + runs-on: ubuntu-latest + environment: + name: scalingo-production + url: https://www.1jeune1solution.gouv.fr + steps: + - name: Configurer la CLI Scalingo + uses: scalingo-community/setup-scalingo@v0.1.1 + with: + api_token: ${{ secrets.SCALINGO_API_TOKEN }} + region: ${{ vars.SCALINGO_REGION }} + app_name: ${{ secrets.TF_VAR_NOM_DE_L_APPLICATION }} + - name: Déployer le code sur Scalingo + run: | + scalingo integration-link-manual-deploy main + + cloudflare: + name: Purger le cache Cloudflare + needs: scalingo + runs-on: ubuntu-latest + if: ${{ inputs.purge_cloudflare_cache == true }} + + steps: + - name: Purger le cache Cloudflare + uses: nathanvaughn/actions-cloudflare-purge@v3.1.0 + with: + cf_zone: ${{ secrets.CLOUDFLARE_ZONE_ID }} + cf_auth: ${{ secrets.CLOUDFLARE_API_TOKEN }} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 04689ac9..cb5e3489 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -1,8 +1,14 @@ +name: release-please + on: push: branches: - main -name: release-please + +permissions: + contents: write + pull-requests: write + jobs: release-please: runs-on: ubuntu-latest @@ -11,3 +17,4 @@ jobs: with: release-type: node package-name: release-please-action + changelog-types: '[{"type":"feat","section":"✨ Nouvelles fonctionnalités","hidden":false},{"type":"fix","section":"🐛 Corrections de bogues","hidden":false},{"type":"chore","section":"👷 Autres changements","hidden":false},{"type":"ci","section":"👷 Autres changements","hidden":false},{"type":"refacto","section":"👷 Autres changements","hidden":false},{"type":"build","section":"👷 Autres changements","hidden":false},{"type":"docs","section":"📚 Documentation","hidden":false}]' diff --git a/.github/workflows/test-ci.yml b/.github/workflows/run-unit-tests.yml similarity index 51% rename from .github/workflows/test-ci.yml rename to .github/workflows/run-unit-tests.yml index bbe2cbbe..0cc5a6f7 100644 --- a/.github/workflows/test-ci.yml +++ b/.github/workflows/run-unit-tests.yml @@ -1,17 +1,14 @@ -name: Test +name: Tests unitaires on: [push] jobs: - Test: - if: "!contains(github.event.head_commit.message, 'WIP')" + tests-unitaires: + if: ${{ !contains(github.event.head_commit.message, 'WIP') }} runs-on: ubuntu-latest - strategy: - matrix: - node-version: [18.12.1] steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: ${{matrix.node-version}} + node-version-file: ".nvmrc" cache: 'npm' - run: npm ci - run: npm test diff --git a/.github/workflows/terraform-pr.yml b/.github/workflows/terraform-pr.yml new file mode 100644 index 00000000..a8829f0b --- /dev/null +++ b/.github/workflows/terraform-pr.yml @@ -0,0 +1,24 @@ +name: Simulation de déploiement Terraform + +# Exécute le plan uniquement quand des modifications sont apportées +# - aux fichiers Terraform +# - aux variables d'environnement +# dans une pull request +on: + pull_request: + branches: [ main ] + paths: + - 'terraform/**' + - '.github/workflows/terraform-*.yml' + - '.env.scalingo' + +jobs: + # Quand le job est exécuté sur une pull request le "plan" s'éxécute sur la recette + # sauf si la pull request est générée par release-please, auquel cas le "plan" s'éxécute sur la production + terraform_plan: + uses: DNUM-SocialGouv/1j1s-front/.github/workflows/terraform-template.yml@main + secrets: inherit + with: + plan: true + environnement_name: ${{ startsWith(github.head_ref, 'release-please--') && 'scalingo-production' || 'scalingo-recette' }} + environnement_url: ${{ startsWith(github.head_ref, 'release-please--') && 'https://www.1jeune1solution.gouv.fr' || 'https://recette.1jeune1solution.gouv.fr' }} diff --git a/.github/workflows/terraform-recette.yml b/.github/workflows/terraform-recette.yml new file mode 100644 index 00000000..fb3b6034 --- /dev/null +++ b/.github/workflows/terraform-recette.yml @@ -0,0 +1,19 @@ +name: Déploiement en Recette + +# Déploie le code Terraform lors de chaque commit/merge sur la branche "main" +# une fois que c'est réussi, normalement l'intégration Github<=>Scalingo automatique va déployer +# la branche main sur l'app 1j1s-front (qui correspond à la recette) +# c'est pour ça qu'on ne déploie pas Scalingo ici +on: + push: + branches: [ main ] + +jobs: + recette: + uses: DNUM-SocialGouv/1j1s-front/.github/workflows/terraform-template.yml@main + secrets: inherit + with: + apply: true + environnement_name: scalingo-recette + environnement_url: https://recette.1jeune1solution.gouv.fr + concurrency: terraform-state-recette # Evite les conflits sur le state Terraform diff --git a/.gitignore b/.gitignore index 462b878a..4d6395d1 100644 --- a/.gitignore +++ b/.gitignore @@ -107,6 +107,7 @@ coverage ############################ .env +.env.* license.txt exports *.cache @@ -119,3 +120,9 @@ build ############################ tmp .nyc_output + +############################ +# Terraform +############################ +.terraform +*.tfstate diff --git a/config/database.ts b/config/database.ts index 9a011401..b7f36540 100644 --- a/config/database.ts +++ b/config/database.ts @@ -1,13 +1,17 @@ -export default ({ env }) => ({ - connection: { - client: "postgres", +export default ({ env }) => { + const databaseURL = env("DATABASE_URL", "postgres://database-user:database-password@127.0.0.1:5432/cms-principal?sslmode=prefer"); + + return { connection: { - host: env("DATABASE_HOST", "127.0.0.1"), - port: env.int("DATABASE_PORT", 5432), - database: env("DATABASE_NAME", "cms-principal"), - user: env("DATABASE_USERNAME", "database-user"), - password: env("DATABASE_PASSWORD", "database-password"), - ssl: env.bool("DATABASE_SSL", false), + client: "postgres", + connection: { + host: databaseURL.hostname, + port: databaseURL.port, + database: databaseURL.pathname.substr(1), + user: databaseURL.username, + password: databaseURL.password, + ssl: env.bool("DATABASE_SSL", false), + }, }, - }, -}); + } +}; diff --git a/config/sentry/index.ts b/config/sentry/index.ts index 44d500cb..4ad254c9 100644 --- a/config/sentry/index.ts +++ b/config/sentry/index.ts @@ -4,7 +4,7 @@ export default (env) => ({ dsn: env("SENTRY_DSN"), init: { release: `${env("npm_package_name")}@${env("npm_package_version")}`, - environment: env("NODE_ENV") + environment: env("SENTRY_ENVIRONMENT", "dev") } }, }) diff --git a/package.json b/package.json index d640f283..53e0d124 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "1j1s-main-cms", "private": true, "version": "1.21.5", - "description": "1 jeune 1 solution main CMS ", + "description": "CMS agrégeant les données pour le site 1jeune1solution.gouv.fr", "scripts": { "docker:populate": "./populate-with-recette-data.sh", "docker:start": "docker-compose --env-file=.env.docker up --build -d && sleep 5 && open http://localhost:1337/admin", @@ -47,8 +47,7 @@ "uuid": "c8583f78-6df0-4091-8734-ede822e386b8" }, "engines": { - "node": "^16.20.0", - "npm": "^9.7.1" + "node": "^18.12.1" }, "license": "MIT" } diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl new file mode 100644 index 00000000..48cf1ee8 --- /dev/null +++ b/terraform/.terraform.lock.hcl @@ -0,0 +1,115 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/cloudflare/cloudflare" { + version = "4.15.0" + constraints = "~> 4.14" + hashes = [ + "h1:OrIIAhBWsPrLS2005mOZtLKyCUaIXqUR0z2H3Fn0xO0=", + "zh:12e7678cab172746b3acac66cd280a99a9b12a9af21c2a063242cf53c2c49f25", + "zh:13e7086f3c444fe58b8495ecfd3c6cef8a200e5d91e758b833c7991a4b782605", + "zh:22bf57720c93c4c6e5a052719977d34b4cfeb6930a05b0ccd8e13562c45c1acc", + "zh:371b5e5fc7f958f3698add96b45fd059b82c7412084113cac8e4ded27568959c", + "zh:376bc20158e4823b1ce28084167385f00d3e5e8419e499be2ddb1b9f0e2d677a", + "zh:6d3ffb50f54275926fe4fb82b56439b36eb9cac266a74f7c2eb46e13c0b9450a", + "zh:726ad74feb174d9f03433fc77e8ec8690371fbe891c4d980f9db6382e790145b", + "zh:7572aaf85d3687fbac623f7c28aa27f22e827a39ebbf8e482f712a43f49de054", + "zh:8494fdbbdec365b6d04b8dd23dcaaba1038030af5496f10df3f73efdad257a3d", + "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", + "zh:8972f77c222e43f81512382149786c229a68de1f428ad27c1f7052886e1faea7", + "zh:8eda83189beb5c6f220c97b49e683990447a020816aa71472077bbc1f48aab57", + "zh:ab2be9910ce3f9a8a7eeeb6ba89fe60f933a9303925cac7ee41e3de764803fe6", + "zh:bf8e782797ad63b6101a05707d976980c66cce846fac89d9017cba14fe0c14b2", + "zh:ef8352c6bff9845fd498be018a70c67a61f22e7c4cc7c1e1e5e880e0f2d9dfd7", + ] +} + +provider "registry.terraform.io/eppo/environment" { + version = "1.3.5" + constraints = "~> 1.3" + hashes = [ + "h1:y1ixJXr2B3Jw98keyxPqP3+FqGQW4wNrCv/7lVPrFcw=", + "zh:00e7a6bf7f0f09cc4871d7f4fee2c943ce61c05b9802365a97703d6c2e63e3dc", + "zh:018d92e621177d053ed5c32e8220efa8c019852c4d60cc7539683bac28470d9b", + "zh:12ca5162286b80b7f46bd013ae2007641132d201af12bc6adb872f9a0ff85b7a", + "zh:2991085432bd4dc718aadfb37b2cdb6201ef73a8a0e5661411f46d9ec782e678", + "zh:2a8f6801266f89b816ebfdb441411e53f4cf1e0278e853715fb561946ad5a575", + "zh:8783a8dc846d3e71b38ca470066f506dde8040f149402f0d348e5dca7f012909", + "zh:8bc8f61e496e96c81c46e1aa59bf2155b6acc80db1ea462f2ddd665748fcda7f", + "zh:95fb102fecceb3a5b44dbe9fbe262494a0abdb6805addf1286c5d92cd4b0f779", + "zh:a158837ec561c161d3c47068e30bca341e5e4c7abff7fa72b9522438b85af4ac", + "zh:a738a7b2e953ee8059f9e68d48ae954175d001a5480f29e22d717bee9fd93f7f", + "zh:bac4b3a38eed35c91269cd008ad88862f47be99474de85e9a2efcce6564e0c24", + "zh:cd56a12eef3515fa5a5845d550be2f67989c8e65563e8fa9f5060666c0728a7c", + "zh:e3e895bc8b557b36bfa03f251df429aa0fba068f4c7ef0ed6ac551b7cba9ff86", + "zh:e959a9e826e3c33242bf4492ee12e5f8be023cf2461702c43d1833c4a8516232", + "zh:f41d9d60b205e6d536881e4af7bb9fc85ae90858bfddf695f95fbd68e01e0ad3", + ] +} + +provider "registry.terraform.io/jrhouston/dotenv" { + version = "1.0.1" + constraints = "~> 1.0" + hashes = [ + "h1:z1Yp0bGzt/q3C3Gf3Xv+g2zczTZfIuMTTAzE0iYb6G0=", + "zh:14e0d4864866259cd8f660fc99fb62c4bbef0e88be426a547bcb8faf8cbc2753", + "zh:1dfe5ec2ca772ad94b0a49734c9f173a84ccf65f46ee0e97542de9e8ef9736fc", + "zh:315a570bf5f20017f16afec0be1a5c4939a7cca4798ce59aec0e97f481bebba3", + "zh:386155dc3791f177c04e5968ab79570b7373258d24a8a4e0265968f97cab1288", + "zh:3ad4617ad7aa209a237c71fe1eead73a56eab85c421d1aad937e0cc9682cec8e", + "zh:59c1a26e1a70b11811f6f0281edf673ef140c67655c7131e5495fda48d316d62", + "zh:657ac83e69064b89bfa7a4a692c1c0525b4a8e23b2cdb0685dff07e4479af081", + "zh:6c6f4acaf9c5ba1b63d77da3173d828add9c1d4059d93596f3842d7ca79efdae", + "zh:6de21bd8c3cbdb468d3c32c11df33e8e3c26b12758e0a76eeb345c7bfba212b8", + "zh:afecbb9b052079b2ea8cdca3001714c8ed2d023d397e7e5626cf6df70c471b7f", + "zh:ba487d781c66dd392f40588d1bf277997d7b7f8e8738e9048a0f48c536fb5fd8", + "zh:c9f63aefe4a8973e9f1f7d2280340713e1d2c65dfc672495526653d5207df349", + "zh:ddffbc4c5d1987834dd4899f5d794cbd6d5f09894666f4a9357bce2b0b4de8a8", + "zh:f631fc8519c3651fc8f5f21262aaf5b49640a04c1482ac33cac770f7a3a2cc99", + ] +} + +provider "registry.terraform.io/scalingo/scalingo" { + version = "2.2.0" + constraints = "~> 2.1, ~> 2.2" + hashes = [ + "h1:nibMvbUm9F5aSfEnvmR7QZdbW/iqvl57k2I00cR++54=", + "zh:06f1f07dc6d45d7c6e925c3dbefb3794c6f2e62ce68ca8cf61713672e6c58b6c", + "zh:122fc93bb62c5705f209e2f96aa7c372e1cb398ea4c033e8b80756029a64c0d6", + "zh:44116c87d69dec826fa604af20263a085e22b82d963daeefb75be655d5bcfc49", + "zh:5ac38fd77944799a818452246544c3cc562f30cc54c68bd268ea03cb3e3c8ac0", + "zh:75196df70c1cb12be2a50c49c1da95e7dc48d7d266e494b104008c18d6c08d1e", + "zh:8c3c296d73bb038746d4e87bcd7a6a32f5ef99357799edddc708b53ac733d221", + "zh:99c04205459593e7bed180238ae6e44598572b48ed0a067d71e0fa89cbab4250", + "zh:9e1b3904093f418dccc3ee446ae628b4815d1bbcf7210f104c37408487b7c138", + "zh:c22609a5c050a726e8bc691acee00b50bec6c6c0153ef6ff969dbf981f6606b7", + "zh:dc596c0bd011575a344b602f99186b11e807cc7fecb101306d588c23c72e80a5", + "zh:e2de27303ffdae9349ad0ff5bd01c61bf66aa149ba8bbf27c4b80e7effcc5639", + "zh:e77efcb0f64ee792a3276186b35158b0cccef0e601c3ab98acca4573e18f6833", + "zh:f5993e52a7d366c9f47db2f54349e14e87a179596dd59ae6dbe44e4db448c18a", + "zh:f7154b05670f245a54ffba914b21537ea243deff65943c8cc1279e806d319222", + ] +} + +provider "registry.terraform.io/statuscakedev/statuscake" { + version = "2.2.0" + constraints = "~> 2.1" + hashes = [ + "h1:7U7JdNVDCjfiLFvQmC1RyQ+RTV0xoJwACFkbvPKF9/I=", + "zh:0a2997ed0d2745cb5726c3165b187c33bbaeb4c0c7ad518533792d06616f1032", + "zh:1c3e89cf19118fc07d7b04257251fc9897e722c16e0a0df7b07fcd261f8c12e7", + "zh:1d146934e413d1923eb3317cb35acf3eaa11f19db8930a9cd9f1181dd34e448c", + "zh:1de63c00f38db03f8e2b2e89ec0056ec50688be9705786c1b7cbfbaab2c6ce7f", + "zh:24e6c137fffa4db170292eaf130cc7f60ebc4a73012afc2b24e4728b1f90f1f7", + "zh:41c06a30d38dab58bf0049bc3ecf460b46db69604594351d68df1c7139c44ee7", + "zh:5a28b914ba40c941700aab856e7b34361fd9f6ddd695a6cdbd5efc3f2df393c0", + "zh:716475004cc7b012d869d617a8a7b80184536edb7b849fa4a66bbe7e6ace7acc", + "zh:8084dff36e22f286fd23c5e2b94c777e5946c862bd34865db884c85fdba84448", + "zh:83231dc83307e769dc5e5bd853c1eda5683190dfaafabf249a640a989a0e5141", + "zh:8b431aceee8ea6b5ef0068b6e531d6c51f9eccc978e3b0a196079b97162bcb87", + "zh:b94b92d54b3b5660b4dfbbcce62ecb1835d91379c91d46ef7527401ac3e5eaa1", + "zh:b990a0d75445ad0c195eea97f4731526d924eefbb0dd05b19e388c0afd10d9d3", + "zh:c63beade9aa6bad92634f3a73312ea7c4f843907a0039d622ddff681e6daba73", + "zh:db391fd4de4be15601f0c36f35a6eb2b20e5d80a0e09bc7015eb376035300fd3", + ] +} diff --git a/terraform/app.tf b/terraform/app.tf new file mode 100644 index 00000000..6751afb3 --- /dev/null +++ b/terraform/app.tf @@ -0,0 +1,48 @@ +module "main_cms_app" { + # source = "scalingo-community/app/scalingo" + # version = "0.2.0" + source = "../../terraform-scalingo-app" + + stack = "scalingo-22" + + name = var.nom_de_l_application + + containers = { + web = { + size = terraform.workspace == "production" ? "L" : "M" + amount = terraform.workspace == "production" ? 2 : 1 + autoscaler = terraform.workspace == "production" ? { + min_containers = 2 + max_containers = 4 + metric = "cpu" + target = 0.8 + } : null + } + } + + github_integration = { + repo_url = "https://github.com/DNUM-SocialGouv/1j1s-main-cms" + branch = var.branche_git + auto_deploy_enabled = (terraform.workspace == "default") ? true : false + } + + environment = local.envs_du_fichier_env + + addons = [ + { + provider = "postgresql" + plan = terraform.workspace == "production" ? "postgresql-business-1024" : "postgresql-starter-1024" + database_features = [] + } + ] + + domain = var.nom_de_domaine + router_logs = true + + log_drains = (var.logstash_uri != null) ? [ + { + type = "elk" + url = sensitive(var.logstash_uri) + } + ] : null +} diff --git a/terraform/cdn.tf b/terraform/cdn.tf new file mode 100644 index 00000000..e51d2b20 --- /dev/null +++ b/terraform/cdn.tf @@ -0,0 +1,16 @@ +data "cloudflare_zone" "zone" { + account_id = "6150db30a41adef4af3b396df6c4b315" + name = "1jeune1solution.gouv.fr" +} + +resource "cloudflare_record" "domaine" { + for_each = toset(var.nom_de_domaine != null ? [var.nom_de_domaine] : []) + + zone_id = data.cloudflare_zone.zone.id + name = trimsuffix(var.nom_de_domaine, ".1jeune1solution.gouv.fr") + value = module.main_cms_app.origin_domain + type = "CNAME" + ttl = 1 + proxied = contains(["default", "production"], terraform.workspace) ? true : false + tags = ["managed-by:terraform", "app:main-cms", "env:${local.nom_environnement}"] +} diff --git a/terraform/locals.tf b/terraform/locals.tf new file mode 100644 index 00000000..ec94c3fa --- /dev/null +++ b/terraform/locals.tf @@ -0,0 +1,22 @@ +locals { + # Parse le fichier .env et retourne une map de clé/valeur de variables d'environnement + # Les valeurs sont automatiquement déclarées comme sensibles pour éviter de les afficher dans les logs + # Si le fichier n'existe pas, la map est vide + # + # Le fichier .env est un fichier multiligne au format "KEY=VALUE" ou "KEY='VALUE'" ou "KEY="VALUE"" + # Exemple de fichier .env : + # KEY1=VALUE1 + # KEY2='VALUE2' + # KEY3="VALUE3" + envs_du_fichier_env = data.dotenv.envs_du_fichier_env.env == null ? null : { + for key, value in data.dotenv.envs_du_fichier_env.env : + key => sensitive(value) if value != null && value != "" + } + + # Nom de l'environnement + nom_environnement = terraform.workspace == "default" ? "recette" : terraform.workspace +} + +data "dotenv" "envs_du_fichier_env" { + filename = var.fichier_env_secret +} diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 00000000..65ece5fe --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,33 @@ +# Peut aussi être défini avec TF_VAR_nom_de_l_application +variable "nom_de_l_application" { + description = "Nom de l'application Scalingo" + type = string +} + +# Peut aussi être défini avec TF_VAR_nom_de_domaine +variable "nom_de_domaine" { + description = "Nom de domaine principal" + type = string + default = null +} + +# Peut aussi être défini avec TF_VAR_fichier_env_secret +variable "fichier_env_secret" { + description = "Nom du fichier contenant des variables d'environment, par exemple \".env\". Sera fusionné avec les variables" + type = string + default = null +} + +# Peut aussi être défini avec TF_VAR_branche_git +variable "branche_git" { + description = "Nom de la branche à déployer" + type = string + default = "main" +} + +# Peut aussi être défini avec TF_VAR_logstash_uri +variable "logstash_uri" { + description = "URI du logstash, sous le format https://user:password@host:port" + type = string + sensitive = true +} diff --git a/terraform/versions.tf b/terraform/versions.tf new file mode 100644 index 00000000..401c2d35 --- /dev/null +++ b/terraform/versions.tf @@ -0,0 +1,74 @@ +terraform { + # Version minimale de Terraform CLI requise pour ce projet + required_version = "~> 1.5" + + backend "s3" { + # Pour la connexion au backend S3 Minio, il faut configurer en variables d'environnements : + # AWS_ACCESS_KEY_ID : le login de l'utilisateur Minio + # AWS_SECRET_ACCESS_KEY : le mot de passe de l'utilisateur Minio + # AWS_S3_ENDPOINT : l'URL de l'API Minio + + # Le chemin du fichier de state sera de la forme : "{workspace_key_prefix}/{TF_WORKSPACE}/{key}" + key = "state/main-cms.tfstate" + workspace_key_prefix = "workspaces" + + # Le bucket S3 doit déjà exister + bucket = "1j1s-terraform-remote-state-applications" + + # On est obligé de configurer une région bidon car on utilise Minio au lieu d'AWS + region = "lorem-ipsum" + + # Les options ci-dessous sont nécessaires pour utiliser le backend S3 Minio : + + # parce que la STS API n'existe pas avec Minio + skip_credentials_validation = true + # parce que l'AWS Metadata API n'existe pas avec Minio + skip_metadata_api_check = true + # parce que Minio n'utilise pas les même régions que AWS + skip_region_validation = true + # parce que Minio ne supporte pas le virtual-hosted-style + force_path_style = true + } + + required_providers { + scalingo = { + source = "Scalingo/scalingo" + version = "~> 2.2" + } + + statuscake = { + source = "StatusCakeDev/statuscake" + version = "~> 2.2" + } + + cloudflare = { + source = "cloudflare/cloudflare" + version = "~> 4.15" + } + + dotenv = { + source = "jrhouston/dotenv" + version = "~> 1.0" + } + } +} + +provider "scalingo" { + # Afin de ne pas stocker de token dans le code source, pour utiliser le provider Scalingo + # il faut configurer en variables d'environnements : + # SCALINGO_API_TOKEN : le token d'authentification de l'utilisateur Scalingo ("tk-us-...") + # SCALINGO_REGION : la région de l'API Scalingo ("osc-fr1" ou "osc-secnum-fr1") +} + +provider "statuscake" { + # Afin de ne pas stocker de token dans le code source, pour utiliser le provider StatusCake + # il faut configurer en variables d'environnements : + # STATUSCAKE_API_TOKEN : le token d'authentification de l'utilisateur StatusCake +} + +provider "cloudflare" { + # Afin de ne pas stocker de token dans le code source, pour utiliser le provider Cloudflare + # il faut configurer en variables d'environnements : + # CLOUDFLARE_API_TOKEN : le token d'authentification de l'utilisateur Cloudflare + # CLOUDFLARE_ZONE_ID : l'ID de la zone Cloudflare +}