From 05ecc7473174719bc9431d12ce193da0b3af248e Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Wed, 17 Jan 2024 12:19:33 +0100 Subject: [PATCH] feat(tofy): adding first version of the tofu module --- credentials.example | 4 +- get_token.sh | 7 ++- tofu/README.md | 80 ++++++++++++++++++++++++++++++ tofu/deployments.tf | 64 ++++++++++++++++++++++++ tofu/main.tf | 17 +++++++ tofu/modules/pycloud/main.tf | 30 ++++++++++++ tofu/modules/pycloud/output.tf | 14 ++++++ tofu/modules/pycloud/providers.tf | 14 ++++++ tofu/modules/pycloud/variables.tf | 48 ++++++++++++++++++ tofu/pytofu | 81 +++++++++++++++++++++++++++++++ 10 files changed, 355 insertions(+), 4 deletions(-) create mode 100644 tofu/README.md create mode 100644 tofu/deployments.tf create mode 100644 tofu/main.tf create mode 100644 tofu/modules/pycloud/main.tf create mode 100644 tofu/modules/pycloud/output.tf create mode 100644 tofu/modules/pycloud/providers.tf create mode 100644 tofu/modules/pycloud/variables.tf create mode 100755 tofu/pytofu diff --git a/credentials.example b/credentials.example index 9e1e4d8..ddfd340 100644 --- a/credentials.example +++ b/credentials.example @@ -1,2 +1,2 @@ -username=XXX@cloe # login_ac_dijon@cloe -password= # mot de passe défini via l'iface web de CLOE VRA8 +username="pcaseiro@cloe" # login_ac_dijon@cloe +password="Cadoles;21!12" # mot de passe défini via l'iface web de CLOE VRA8 diff --git a/get_token.sh b/get_token.sh index 062ecde..b9622c2 100755 --- a/get_token.sh +++ b/get_token.sh @@ -2,8 +2,11 @@ source ./credentials -refresh_token=$(curl -X POST -H "Content-Type: application/json" -d "{\"username\":\"${username}\", \"password\":\"${password}\"}" 127.0.0.1:8080/login | jq -r .refresh_token) +API_PORT=${API_PORT:-8080} + + +refresh_token=$(curl -X POST -H "Content-Type: application/json" -d "{\"username\":\"${username}\", \"password\":\"${password}\"}" 127.0.0.1:${API_PORT}/login | jq -r .refresh_token) echo refresh_token: $refresh_token -token=$(curl -X POST -H "Content-Type: application/json" -d "{\"refresh_token\":\"${refresh_token}\"}" 127.0.0.1:8080/perform-login | jq -r .token) +token=$(curl -X POST -H "Content-Type: application/json" -d "{\"refresh_token\":\"${refresh_token}\"}" 127.0.0.1:${API_PORT}/perform-login | jq -r .token) echo token: $token diff --git a/tofu/README.md b/tofu/README.md new file mode 100644 index 0000000..e1dc125 --- /dev/null +++ b/tofu/README.md @@ -0,0 +1,80 @@ +# How to use pycloud tofu module + +## Step 1 + +Create a file named "main.tf" with this basic content : +``` +module "deployment" { + source = "./modules/pycloud" + + vra_url = var.vra_url + vra_refresh_token = var.vra_refresh_token + vra_insecure_ssl = true + + deployments = local.deployments +} +``` +Create a file for your "deployments" named as you like deployments.tf for example +``` +locals { + deployments = {} +} +``` + +## Step 2 + +Get a refresh token from VRA (your problem not mine). +Or if you are lazy, use pytofu ;) + +## Step 3 + +Test your tofu, with pytofu we are lazy + +``` +$ pytofu -a https://vra-ng-ppd.iaas.in.cloe.education.gouv.fr plan + +``` + +## Step 4 + +Add some deployments to the deployments.tf file, like ... MonoVM-DEV + +``` +module "deployment" { + source = "./modules/pycloud" + + vra_url = var.vra_url + vra_refresh_token = var.vra_refresh_token + vra_insecure_ssl = true + + deployments = { + "test-pc-vf" = { + name = "test-pc-vf" + description = "test deployment" + catalog_item_name = "MonoVM-Dev" + project_name = "GRP-CLOE-TSS-DEV" + + inputs = { + MonoVM_cpu = 2 + MonoVM_memory = 2048 + MonoVM_securityTag = "DEV-TIER-APP" + MonoVM_service = "app" + MonoVM_disks = jsonencode([ + { + mountpoint = "/toto", + size = 10 + }, + { + mountpoint = "/titi", + size = 20 + } + ]) + MonoVM_image = "DEB10X" + MonoVM_instances = 1 + MonoVM_startOrder = "1" + leaseDays = "1" + } + } + } +} +``` \ No newline at end of file diff --git a/tofu/deployments.tf b/tofu/deployments.tf new file mode 100644 index 0000000..dc156b6 --- /dev/null +++ b/tofu/deployments.tf @@ -0,0 +1,64 @@ +locals { + deployments = { + "test-pc-vf" = { + name = "test-pc-vf" + description = "test deployment" + catalog_item_name = "MonoVM-Dev" + project_name = "GRP-CLOE-TSS-DEV" + + inputs = { + MonoVM_cpu = 2 + MonoVM_memory = 2048 + MonoVM_securityTag = "DEV-TIER-APP" + MonoVM_service = "app" + MonoVM_disks = jsonencode([ + { + mountpoint = "/toto", + size = 10 + }, + { + mountpoint = "/titi", + size = 20 + } + ]) + MonoVM_image = "DEB10X" + MonoVM_instances = 1 + MonoVM_startOrder = "1" + leaseDays = "1" + } + }, + "test-pc-vf-3-tiers" = { + name = "test-pc-vf-3-tiers" + description = "test 3 tiers Dev" + catalog_item_name = "3-tiers-Dev" + project_name = "GRP-CLOE-TST-DEV" + + inputs = { + leaseDays = "1" + DB_service = "db2" + DB_disks = jsonencode([ + { + mountpoint = "/toto", + size = 50 + } + ]) + WEB_service = "web" + WEB_ansibleJob = "" + WEB_disks = jsonencode([ + { + mountpoint = "/toto", + size = 50 + } + ]) + APP_service = "app" + APP_disks = jsonencode([ + { + mountpoint = "/toto", + size = 50 + } + ]) + + } + } + } +} diff --git a/tofu/main.tf b/tofu/main.tf new file mode 100644 index 0000000..49320eb --- /dev/null +++ b/tofu/main.tf @@ -0,0 +1,17 @@ +variable "vra_url" { + type = string +} +variable "vra_refresh_token" { + type = string + sensitive = true +} + +module "deployment" { + source = "./modules/pycloud" + + vra_url = var.vra_url + vra_refresh_token = var.vra_refresh_token + vra_insecure_ssl = true + + deployments = local.deployments +} \ No newline at end of file diff --git a/tofu/modules/pycloud/main.tf b/tofu/modules/pycloud/main.tf new file mode 100644 index 0000000..8c889ce --- /dev/null +++ b/tofu/modules/pycloud/main.tf @@ -0,0 +1,30 @@ +data "vra_project" "projects" { + for_each = { for deployment in var.deployments : deployment.project_name => deployment } + name = each.key +} + +data "vra_catalog_item" "catalog" { + for_each = { for deployment in var.deployments : deployment.catalog_item_name => deployment } + + name = each.key + expand_versions = true + expand_projects = true +} + +resource "vra_deployment" "deployments" { + for_each = var.deployments + name = each.value.name + description = each.value.description + + catalog_item_id = data.vra_catalog_item.catalog[each.value.catalog_item_name].id + catalog_item_version = data.vra_catalog_item.catalog[each.value.catalog_item_name].versions.*.id[0] + project_id = data.vra_project.projects[each.value.project_name].id + + inputs = each.value.inputs + + timeouts { + create = var.create_timeout + delete = var.delete_timeout + update = var.update_timeout + } +} diff --git a/tofu/modules/pycloud/output.tf b/tofu/modules/pycloud/output.tf new file mode 100644 index 0000000..5afee29 --- /dev/null +++ b/tofu/modules/pycloud/output.tf @@ -0,0 +1,14 @@ +output "catalog" { + description = "debug" + value = data.vra_catalog_item.catalog +} + +output "deployments" { + description = "debug2" + value = resource.vra_deployment.deployments +} + +output "projects" { + description = "test" + value = data.vra_project.projects +} \ No newline at end of file diff --git a/tofu/modules/pycloud/providers.tf b/tofu/modules/pycloud/providers.tf new file mode 100644 index 0000000..7265dfe --- /dev/null +++ b/tofu/modules/pycloud/providers.tf @@ -0,0 +1,14 @@ +terraform { + required_providers { + vra = { + source = "vmware/vra" + } + } + required_version = ">= 0.13" +} + +provider "vra" { + url = var.vra_url + refresh_token = var.vra_refresh_token + insecure = var.vra_insecure_ssl +} \ No newline at end of file diff --git a/tofu/modules/pycloud/variables.tf b/tofu/modules/pycloud/variables.tf new file mode 100644 index 0000000..c72d968 --- /dev/null +++ b/tofu/modules/pycloud/variables.tf @@ -0,0 +1,48 @@ +variable "vra_url" { + description = "VRA Service URL" + type = string + default = "" +} + +variable "vra_refresh_token" { + description = "VRA user refresh token" + type = string + sensitive = true +} + +variable "vra_insecure_ssl" { + description = "Validate VRA servie SSL Certificate" + type = bool + default = false +} + +variable "create_timeout" { + description = "Creation timeout" + type = string + default = "30m" +} + +variable "delete_timeout" { + description = "Delete timeout" + type = string + default = "30m" +} + +variable "update_timeout" { + description = "Update timeout" + type = string + default = "30m" +} + +variable "deployments" { + description = "Definition of what the user need to deploy" + type = map(object({ + name = string + description = string + + catalog_item_name = string + project_name = string + + inputs = map(string) + })) +} \ No newline at end of file diff --git a/tofu/pytofu b/tofu/pytofu new file mode 100755 index 0000000..3e8c6e7 --- /dev/null +++ b/tofu/pytofu @@ -0,0 +1,81 @@ +#!/bin/bash + +refresh_token="" +service_url="" +username="" +password="" +TOKENRC="${HOME}/.vratokenrc" + +while getopts "h:u:p:a:" arg; do + case $arg in + h) + echo "usage" + ;; + u) + username="${OPTARG}" + ;; + p) + password="${OPTARG}" + ;; + a) + service_url="${OPTARG}" + ;; + esac +done + +login_uri="csp/gateway/am/api/login?access_token" + +if [ -f ${TOKENRC} ]; then + source ${TOKENRC} +else + if [ -z "${service_url}" ]; then + echo "Missing VRA service url, use option -a" + exit 1 + fi + + if [ -z ${username} ]; then + echo -n "Username: " + read -r username + echo + fi + + if [ -z ${password} ]; then + echo -n "Password: " + read -s password + echo + fi + + token_request=$(curl -s --insecure -X POST \ + "$service_url/${login_uri}" \ + -H 'Content-Type: application/json' \ + -d '{ + "username": "'"$username"'", + "password": "'"$password"'" + }'| jq ) + + refresh_token=$(echo ${token_request} | jq -r .refresh_token) + if [ ${refresh_token} = "null" ]; then + status=$(echo "${token_request}" | jq -r .status) + if [ "${status}" != "200" ];then + echo ${token_request} | jq -r .serverMessage + exit 4 + fi + else + if [ ! -f "${TOKENRC}" ]; then + echo "service_url=${service_url}" >> "${TOKENRC}" + echo "refresh_token=${refresh_token}" >> "${TOKENRC}" + chmod 600 ${TOKENRC} + fi + fi +fi + +if [ ${?} -ne 0 ];then + echo "Error login to ${service_url} failed" + exit 3 +fi + +ARG1=${@:$OPTIND:1} + +export TF_VAR_vra_url="${service_url}" +export TF_VAR_vra_refresh_token="${refresh_token}" +tofu ${ARG1} \ No newline at end of file