Oracle Cloud Gen 2 (OCI) : (4) Utiliser Terraform

Voici le dernier article de la série sur la seconde génération du Cloud Oracle, maintenant nommé avec l’acronyme OCI, pour Oracle Cloud Infrastructure. La série se veut un parcours non exhaustif des fonctionnalités proposées en mettant l’accent :

Voici maintenant comment faire pour provisionner votre infrastructure à l’aide de Terraform.

L’exemple constitue en la création d’un système base de données (« DB System ») s’appuyant sur une machine virtuelle.
Pour pouvoir faire cette opération, il faut, au préalable, sur votre environnement Cloud :

  • Créer un VCN
  • Créer un sous-réseau
  • Créer une passerelle internet IGW.

Récupération du produit « Terraform » :

Rendez vous directement sur le site du produit et téléchargez la distribution qui convient à votre système.
J’ai pris l’option de continuer à l’utiliser sur mon laptop en Windows 10, la version en date de l’écriture de cet article était la 0.12  :  terraform_0.12.6_windows_amd64.zip

Le zip ne contient qu’un seul fichier :  terraform.exe.
Il suffit de l’extraire dans un répertoire inclus dans le PATH de la machine, ou inclure le répertoire d’installation dans le PATH.
J’ai, de mon coté, créé une arborescence particulière terraform et extrait l’exécutable dans le sous-répertoire « bin ».
Pour l’utiliser, on ouvre une fenêtre MS-DOS :

C:\Users\ericl>set PATH=C:\Users\ericl\terraform\bin;%PATH%
C:\Users\ericl>terraform version
Terraform v0.12.6

L’étape suivante est de créer une clé API de la même manière que ce que je vous ai déjà décrit ici dans le paragraphe « Clés API et utilisateur Cloud ».
A la fin des actions, vous aurez sous le répertoire « .oci » les fichiers de clés « oci_api_key.pem » et « oci_api_key_public.pem » et vous aurez inséré la clé API dans le profil de l’utilisateur de connexion tout en notant et conservant l’empreinte de la clé dans un bloc note.

Terraform s’appuie sur une série de fichiers de déclaration de paramètres avec les extensions « .tf » et « *tvars ».
L’ensemble est à créer dans un sous-répertoire dédié et c’est depuis ce répertoire que vous exécuterez les commandes terraform.

Le premier est le fichier terraform.tvars : vous devez l’enrichir pour positionner les valeurs utilisées ensuite par les fichiers de déploiement.

C:\Users\ericl>set PATH=C:\Users\ericl\terraform\bin;%PATH%
C:\Users\ericl>cd terraform\work
C:\Users\ericl\terraform\work>notepad terraform.tfvars
C:\Users\ericl\terraform\work>

Voici un exemple de contenu :

# -- PLEASE UPDATE LINES BELOW TO MATCH YOUR OCI TENANT, COMPARTEMENT AND REGION
tenancy_ocid     = "ocid1.tenancy.oc1..aaaaaaaaey5af3vkx2ywqd5xe2qficfv4t3wlf3ssnfh5zfwbymf7ixfskea"
user_ocid        = "ocid1.user.oc1..aaaaaaaadrvqb4fso6lr4bbbdmnmquk999xrvnhmou6kswvpyet2i2jt42a7a"
fingerprint      = "7c:ba:f2:a0:06:4b:76:29:21:5b:63:45:da:0d:63:b6"
compartment_ocid = "ocid1.compartment.oc1..aaaaaaaa63p4d7wercun999js3ntasqisvuxskc5sb6olxyekjtjl3w2eoka"
region           = "eu-frankfurt-1"
private_key_path = "apikey.pem"
# ---- availability domain (1, 2 or 3)
AD               = "1"
# ---- Network
cidr_vcn              = "172.27.16.0/24"
cidr_subnet1          = "172.27.16.0/25"
vcn_name              = "VCNELE"
internet_gateway_name = "IGW_ELE"
route_table_name      = "Default Route Table for VCNELE"
security_list_name    = "Default Security List for vcn20190826101012"
public_subnet1_name   = "SNFORMDEV"
SubnetDB_ocid	     = "ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaacrd4l55uldthfffffd7ccmeizffffc7dt6wcdrqsg5jtiq"
# ---- Authorized public IPs ingress
authorized_ips   = "0.0.0.0/0"
# ---- Compute instance
compute_instance_shape  = "VM.Standard1.1"
BootStrapFile_ol7       = "userdata_bootstrap_ol7.sh"
ssh_public_key_file_ol7 = "sshkey.pub"
ssh_private_key_file_ol7= "sshkey"
compute_instance_name   = "PROTO Oracle Linux 7"
vnic_name               = "PROTO vnic"
# ---- Database 
db_subnet_id         = ""
DBNodeShape          = "VM.Standard2.1"
CPUCoreCount         = "1"
DBEdition            = "ENTERPRISE_EDITION_HIGH_PERFORMANCE"
DBAdminPassword      = "easy_4U_7Bien"
DBName               = "PROTO04"
DBVersion            = "11.2.0.4"
DBDBHomeName         = "DBhome_11"
DBNodeDisplayName    = "PROTO01 Database"
DBNodeHostName       = "srvproto01db"
NCharacterSet        = "AL16UTF16"
CharacterSet         = "AL32UTF8"
DBWorkload           = "OLTP"
DataStorageSizeInGB  = "256"
LicenseModel         = "LICENSE_INCLUDED"
NodeCount            = "1"
PDBName              = "PDB1"

Section « Tenant Compartiment et region »
Cette section reprend les différents éléments de connexion
tenant_ocid
Identifiant de votre tenant dans le Cloud Oracle – OCIDInformation à récupérer depuis le Cloud, dans la section « Administration » / « Détails de location » : pour votre tenant, cliquer sur les liens « Afficher » ou « Copier » pour le mettre dans le presse-papier et le coller dans votre fichier.

user_ocid
Identifiant sur le Cloud de votre utilisateur – OCID – Information à récupérer depuis le Cloud, dans la section « Identité » / « Utilisateurs » : pour l’utilisateur, cliquer sur les liens « Afficher » ou « Coller » pour le mettre dans le presse-papier et le coller dans votre fichier.

fingerprint
Empreinte de la clé API que vous avez mis de coté plus haut et que vous pouvez maintenant mettre dans la configuration.

compartment_ocid
Identifiant du compartiment dans lequel vous voulez réaliser des déploiements.
Pour récupérer l’id de votre compartiment, il faut aller dans la section « Gouvernance et administration » / Identité / Compartiment / Détails du compartiment.
Dans la section « Informations sur le compartiment », copier l’information OCID dans le presse papier pour la coller dans votre fichier.
Si vous n’avez pas créé de compartiment et que vous désirez travailler dans le compartiment « racine » (ce qui est suffisant pour faire des tests), l’id du compartiment sera la même que celle du tenant.

region
Le datacenter abritant votre tenant, en général pour nous Français « eu-frankfurt-1 ».

private_key_path
Le chemin complet (ou relatif à l’endroit d’où vous exécuterez Terraform) de la localisation de votre clé API privée.

Section domaine de disponibilité
AD
Choix du domaine de disponibilité pour la création de votre déploiement, la notion de domaine de disponibilité étant intrinsèque à l’architecture du Cloud Oracle. Mettre la valeur « 1 » pour des tests.

Section réseau
Les informations proviennent de la configuration faite au préalable pour le réseau et le sous-réseau.

Section autorisation des adresses publics
authorized_ips

Pas de limitation pour cet environnement de test.

Section « Compute Instance »
compute_instance_shape
Modèle de déploiement pour la machine virtuelle, attention pendant votre essai, vous êtes limité et n’avez pas tous les choix. Pour un test, la plus petite VM est suffisante.

BootStrapFile_ol7
Fichier de commandes shell qui peuvent être exécutées après le déploiement de la VM : peut, par exemple, contenir les commandes pour télécharger les librairies d’un programme particulier, faire l’installation d’un agent, récupérer un portefeuille de clé de sécurité (pour les sauvegardes RMAN qui seraient dans le Cloud par exemple), etc.
Ce fichier doit se trouver dans l’arborescence de travail depuis laquelle vous lancerez les commandes « terraform ».

ssh_public_key_file_ol7 , ssh_private_key_file_ol7
Ensemble des fichiers clés publiques/privées généré pour l’authentification à la VM par ssh.
Les fichiers doivent se trouver dans l’arborescence de travail depuis laquelle vous lancerez les commandes « terraform ».
compute_instance_name =  »  »
Nom de votre instance de machine virtuelle pour la référence.

Section « Database »
L’ensemble des éléments pour créer le système de base de données : pour le détail de tous les paramètres, se reporter à la documentation de création des DBSystem.

 

Ensuite, il vous faut des fichiers d’extension « .tf ».
Fichiers qui seront traités dans l’ordre de leur suffixe par l’exécution des commandes terraform, par exemple :

  • 01_auth.tf : Va définir les informations de connexion et d’identification pour les différents services utilisés dans le déploiement, ainsi que l’appel au provider Oracle pour la récupération des API correspondantes.
  • 02_vcn.tf : Utilisé pour la définition et le déploiement des composants du réseau, dans mon exemple où le réseau est déjà créé, j’ai tout commenté sauf la récupération de l’information de l’OCID du compartiment en cours.
  • 03_createdb.tf : Définition de tous les éléments pour la création du système base de données.
  • 04_get_info.tf : Récupération des informations après la création du système (optionnel).
  • 05_remote_exec.tf : Définition des actions à réaliser après le déploiement du système (comme installer le module Cloud pour RMAN – optionnel).

Voici ce que j’ai utilisé, il vous faut l’adapter en fonction de ce que vous souhaitez faire.
Attention, ces fichiers sont les pilotes des actions qui vont être déroulées par Terraform, il est important qu’ils soient cohérents et qu’il n’y ait pas d’erreur incluse.

01_auth.tf
Association des variables avec leur valeur (celle qui est définie dans le fichier .tfvars).
Et appel au plugin oracle (provider oci).

# ---- use variables defined in terraform.tfvars file
variable "tenancy_ocid" {}

variable "user_ocid" {}
variable "fingerprint" {}
variable "private_key_path" {}
variable "compartment_ocid" {}
variable "region" {}
variable "AD" {}
variable "authorized_ips" {}
variable "compute_instance_shape" {}
variable "BootStrapFile_ol7" {}
variable "ssh_public_key_file_ol7" {}
variable "ssh_private_key_file_ol7" {}

# ---- Network
variable "cidr_vcn" {}
variable "cidr_subnet1" {}
variable "vcn_name" {}
variable "internet_gateway_name" {}
variable "route_table_name" {}
variable "security_list_name" {}
variable "public_subnet1_name" {}

# Compute instance
variable "compute_instance_name" {}
variable "vnic_name" {}

# Database
variable "db_subnet_id"         {}
variable "compartment_display_name" {default = "PrivDBCompartment"}
variable "DBNodeShape"          {}
variable "CPUCoreCount"         {}
variable "DBEdition"            {}
variable "DBAdminPassword"      {}
variable "DBName"               {}
variable "DBVersion"            {}
variable "DBDBHomeName"         {}
variable "DBNodeDisplayName"    {}
variable "DBNodeHostName"       {}
variable "NCharacterSet"        {}
variable "CharacterSet"         {}
variable "DBWorkload"           {}
variable "PDBName"              {}
variable "DataStorageSizeInGB"  {}
variable "LicenseModel"         {}
variable "NodeCount"            {}

# ---- provider
provider "oci" {
  region           = "${var.region}"
  tenancy_ocid     = "${var.tenancy_ocid}"
  user_ocid        = "${var.user_ocid}"
  fingerprint      = "${var.fingerprint}"
  private_key_path = "${var.private_key_path}"
}

 

02_vcn.tf
Définition du réseau à déployer (ici rien à faire qu’à récupérer l’identifiant existant).

# -------- get the list of available ADs
data "oci_identity_availability_domains" "ADs" {
  compartment_id = "${var.tenancy_ocid}"
}

 

03_createdb.tf
Pour la création du système base de données, noter que le subnet_id est écrit dans le fichier, il devrait pouvoir être en variable :

# ------ Create a DB System
resource "oci_database_db_system" "PROTO04-Database" {
  availability_domain   = "${lookup(data.oci_identity_availability_domains.ADs.availability_domains[var.AD - 1],"name")}"
  compartment_id        = "${var.compartment_ocid}"
  cpu_core_count        = "${var.CPUCoreCount}"
  database_edition      = "${var.DBEdition}"
  db_home {
    database {
      "admin_password"  = "${var.DBAdminPassword}"
      "db_name"         = "${var.DBName}"
      "character_set"   = "${var.CharacterSet}"
      "ncharacter_set"  = "${var.NCharacterSet}"
      "db_workload"     = "${var.DBWorkload}"
    }
    db_version          = "${var.DBVersion}"
    display_name        = "${var.DBDBHomeName}"
  }
  shape                = "${var.DBNodeShape}"
  subnet_id            = "ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaacrd4l55uldthlvpbjuqdfffffff4hzhsdcffffwcdrqsg5jtiq"
  #
  # if trimspace is not used, then further calls to terraform will trigger a destroy/create new resource
  #
  ssh_public_keys         = ["${trimspace(file(var.ssh_public_key_file_ol7))}"]
  display_name            = "${var.DBNodeDisplayName}"
  hostname                = "${var.DBNodeHostName}"
  data_storage_percentage = "40"
  data_storage_size_in_gb = "${var.DataStorageSizeInGB}"
  license_model           = "${var.LicenseModel}"
  node_count              = "${var.NodeCount}"
 }

 

04_get_info.tf
Récupération des informations nécessaire pour la suite des opérations (optionnel) :

# Get DB node list
data "oci_database_db_nodes" "DBNodeList" {
  compartment_id = "${var.compartment_ocid}"
  db_system_id = "${oci_database_db_system.PROTO01-Database.id}"
}

# Get DB node details
data "oci_database_db_node" "DBNodeDetails" {
  db_node_id = "${lookup(data.oci_database_db_nodes.DBNodeList.db_nodes[0], "id")}"
}

# Gets the OCID of the first (default) vNIC
data "oci_core_vnic" "DBNodeVnic" {
  vnic_id = "${data.oci_database_db_node.DBNodeDetails.vnic_id}"
}

 

05_remote_exec.tf (optionnel)
Envoi du fichier jar d’installation pour le module cloud RMAN.
Envoi d’un shell pour la réalisation de l’installation.
Exécution du shell :

resource "null_resource" "remote-exec" {
    depends_on = ["oci_database_db_system.PROTO01-Database"]

     provisioner "file" {
               connection {
                        agent = false
                        timeout = "10m"
                        host = "${data.oci_core_vnic.DBNodeVnic.public_ip_address}"
                        user = "opc"
                        private_key = "${file(var.ssh_private_key_file_ol7)}"
                }
        source = "${path.module}/opc_install.jar"
        destination = "/tmp/opc_install.jar"
}

     provisioner "file" {
               connection {
                        agent = false
                        timeout = "5m"
                        host = "${data.oci_core_vnic.DBNodeVnic.public_ip_address}"
                        user = "opc"
                        private_key = "${file(var.ssh_private_key_file_ol7)}"
                }
        source = "${path.module}/bootstrap_rman.sh"
        destination = "/tmp/bootstrap_rman.sh"
}


    provisioner "remote-exec" {
      connection {
        agent = false
        host = "${data.oci_core_vnic.DBNodeVnic.public_ip_address}"
        user = "opc"
        private_key = "${file(var.ssh_private_key_file_ol7)}"
    }
  inline = [
      "sudo echo ERIC >/tmp/eric",
      "sudo chown oracle /tmp/opc_install.jar",
      "sudo chown oracle /tmp/bootstrap_rman.sh",
      "sudo chmod +x /tmp/bootstrap_rman.sh",
      "sudo -u oracle /tmp/bootstrap_rman.sh ${var.DBName}"
    ]
  }

}

 

Une fois tous les fichiers présents sous votre arborescence de travail :

C:\Users\ericl\terraform\work>dir /B
01_auth.tf
02_vcn.tf
03_createdb.tf
04_getinfo.tf
05_remote_exec.tf
apikey.pem
apikey_public.pem
bootstrap_rman.sh
sshkey
sshkey.pub
terraform.tfvars

Valider la synthase par la commande « terraform validate ».
En cas d’erreur le fichier, la ligne et la raison de l’erreur vous serons renvoyés :

C:\Users\ericl>set PATH=C:\Users\ericl\terraform\bin;%PATH%
C:\Users\ericl\terraform\work>terraform validate

Error: Invalid argument name

  on 03_createdb.tf line 10, in resource "oci_database_db_system" "PROTO04-Database":
  10:       "admin_password"  = "${var.DBAdminPassword}"

Argument names must not be quoted.

Après les corrections réalisées (ici suppression des quotes devant les arguments dans le fichier « 03_dbcreatedb.tf ») vous devez obtenir la validation :

C:\Users\ericl>set PATH=C:\Users\ericl\terraform\bin;%PATH%
C:\Users\ericl\terraform\work>terraform validate
Success! The configuration is valid.

Attention, la vérification de la synthaxe est faite seulement sur les fichiers *.tf.
La vérification pour le fichier terraform.tfvars n’a pas lieu à ce moment-là (mais seulement pendant l’étape « plan » ou « apply »).

Vous pouvez déclencher l’étape d’initialisation, qui va, entre autres, vérifier que les plugins utilisés (mot clé « provider ») sont accessibles et compatibles avec votre installation de Terraform :

C:\Users\ericl>set PATH=C:\Users\ericl\terraform\bin;%PATH%
C:\Users\ericl\terraform\work>terraform init
Initializing the backend...
Initializing provider plugins...
The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.oci: version = "~> 3.39"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

La commande d’initialisation génère un sous-répertoire caché de type « .terraform » qui va contenir des fichiers de configuration et d’état.

Pour anticiper et voir les actions qui vont être réalisées, vous pouvez lancer la commande « terraform plan ».
Le resultat est verbeux mais il peut être sauvegardé dans un fichier :

C:\Users\ericl>set PATH=C:\Users\ericl\terraform\bin;%PATH%
C:\Users\ericl\terraform\work>terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

data.oci_identity_availability_domains.ADs: Refreshing state...

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
 <= read (data resources)

Terraform will perform the following actions:

  # data.oci_core_vnic.DBNodeVnic will be read during apply
  # (config refers to values not yet known)
 <= data "oci_core_vnic" "DBNodeVnic"  {
      + availability_domain    = (known after apply)
      + compartment_id         = (known after apply)
      + defined_tags           = (known after apply)
      + display_name           = (known after apply)
      + freeform_tags          = (known after apply)
      + hostname_label         = (known after apply)
      + id                     = (known after apply)
      + is_primary             = (known after apply)
      + mac_address            = (known after apply)
      + nsg_ids                = (known after apply)
      + private_ip_address     = (known after apply)
      + public_ip_address      = (known after apply)
      + skip_source_dest_check = (known after apply)
      + state                  = (known after apply)
      + subnet_id              = (known after apply)
      + time_created           = (known after apply)
      + vnic_id                = (known after apply)
    }

  # data.oci_database_db_node.DBNodeDetails will be read during apply
  # (config refers to values not yet known)
 <= data "oci_database_db_node" "DBNodeDetails"  {
      + backup_vnic_id              = (known after apply)
      + db_node_id                  = (known after apply)
      + db_system_id                = (known after apply)
      + fault_domain                = (known after apply)
      + hostname                    = (known after apply)
      + id                          = (known after apply)
      + software_storage_size_in_gb = (known after apply)
      + state                       = (known after apply)
      + time_created                = (known after apply)
      + vnic_id                     = (known after apply)
    }

  # data.oci_database_db_nodes.DBNodeList will be read during apply
  # (config refers to values not yet known)
 <= data "oci_database_db_nodes" "DBNodeList"  {
      + compartment_id = "ocid1.tenancy.oc1..aaaaaaaapro3o5widuiwbgix52f6xi3jseikok6tfgsp6pobdrg64lcvhrla"
      + db_nodes       = (known after apply)
      + db_system_id   = (known after apply)
      + id             = (known after apply)
    }

  # oci_database_db_system.PROTO01-Database will be created
  + resource "oci_database_db_system" "PROTO01-Database" {
      + availability_domain         = "wMde:EU-FRANKFURT-1-AD-1"
      + backup_subnet_id            = (known after apply)
      + cluster_name                = (known after apply)
      + compartment_id              = "ocid1.tenancy.oc1..aaaaaaaapro3o5widuiwbgix52f6xi3jseikok6tfgsp6pobdrg64lcvhrla"
      + cpu_core_count              = 1
      + data_storage_percentage     = 40
      + data_storage_size_in_gb     = 256
      + database_edition            = "ENTERPRISE_EDITION_HIGH_PERFORMANCE"
      + defined_tags                = (known after apply)
      + disk_redundancy             = (known after apply)
      + display_name                = "PROTO01 Database"
      + domain                      = (known after apply)
      + fault_domains               = (known after apply)
      + freeform_tags               = (known after apply)
      + hostname                    = "srvproto01db"
      + id                          = (known after apply)
      + iorm_config_cache           = (known after apply)
      + last_patch_history_entry_id = (known after apply)
      + license_model               = "LICENSE_INCLUDED"
      + lifecycle_details           = (known after apply)
      + listener_port               = (known after apply)
      + node_count                  = 1
      + reco_storage_size_in_gb     = (known after apply)
      + scan_dns_record_id          = (known after apply)
      + scan_ip_ids                 = (known after apply)
      + shape                       = "VM.Standard2.1"
      + source                      = (known after apply)
      + sparse_diskgroup            = (known after apply)
      + ssh_public_keys             = [
          + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxxBH4Tq9jhrbbLbDQjVCodN3J9tyA6yZIoKxh/FxMPyrseryYxZ03oB+Uh+r/rt80Pq/Ti9aHlKgXTGpEWe8uPsVjNDtICMMYunnMLG0SP/S1fnQsUxUSGN1LaRv6oh/sOMMPiupjLegMfCWrNIlGDe425R2nb9aOxvCOUMtc2Kc4Ll+AtB2MKePQPJc+EKuYGR9EnQx6FpsCteTNx9wLUUm3tNDPmszmcK5xaAVeN8WUaRnL3fV6WPe4CBqDVj6IHNsrz2//F3SAiyag90O2e2p1PfwFDt3N9OtHtwD2L/XbrOY9wnzEDwHrAnj7XaOCZSML04h4rogeoGb+jxRX oracle@vbgeneric",
        ]
      + state                       = (known after apply)
      + subnet_id                   = "ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaa3rglfwws6zexvus3l2pzbe3rkofzyorfdhmmlwxovyflra5ptxuq"
      + time_created                = (known after apply)
      + time_zone                   = (known after apply)
      + version                     = (known after apply)
      + vip_ids                     = (known after apply)

      + db_home {
          + db_version                  = "11.2.0.4"
          + display_name                = "DBhome_11"
          + id                          = (known after apply)
          + last_patch_history_entry_id = (known after apply)
          + state                       = (known after apply)
          + time_created                = (known after apply)

          + database {
              + admin_password      = (sensitive value)
              + backup_id           = (known after apply)
              + backup_tde_password = (sensitive value)
              + character_set       = "AL32UTF8"
              + connection_strings  = (known after apply)
              + db_name             = "PROTO01"
              + db_unique_name      = (known after apply)
              + db_workload         = "OLTP"
              + defined_tags        = (known after apply)
              + freeform_tags       = (known after apply)
              + id                  = (known after apply)
              + lifecycle_details   = (known after apply)
              + ncharacter_set      = "AL16UTF16"
              + pdb_name            = (known after apply)
              + state               = (known after apply)
              + time_created        = (known after apply)

              + db_backup_config {
                  + auto_backup_enabled     = (known after apply)
                  + recovery_window_in_days = (known after apply)
                }
            }
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Warning: Value for undeclared variable

  on terraform.tfvars line 20:
  20: SubnetDB_ocid        = "ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaa3rglfwws6zexvus3l2pzbe3rkofzyorfdhmmlwxovyflra5ptxuq"

The root module does not declare a variable named "SubnetDB_ocid". To use this
value, add a "variable" block to the configuration.

Using a variables file to set an undeclared variable is deprecated and will
become an error in a future release. If you wish to provide certain "global"
settings to all configurations in your organization, use TF_VAR_...
environment variables to set these instead.


------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Il montre ici clairement un ajout (le « DB System ») et rien d’autre.

Il manque une déclaration pour la variable SubnetDB_ocid dans le fichier 01_auth.tf, après ajout de la variable, le message d’attention disparait.

Dernière étape, l’application du plan, qui va réllement faire les actions sur votre tenant dans le Cloud Oracle :

C:\Users\ericl>set PATH=C:\Users\ericl\terraform\bin;%PATH%
C:\Users\ericl\terraform\work>terraform apply
data.oci_identity_availability_domains.ADs: Refreshing state...

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create
 <= read (data resources)

Terraform will perform the following actions:

  # data.oci_core_vnic.DBNodeVnic will be read during apply
  # (config refers to values not yet known)
 <= data "oci_core_vnic" "DBNodeVnic"  {
      + availability_domain    = (known after apply)
      + compartment_id         = (known after apply)
      + defined_tags           = (known after apply)
      + display_name           = (known after apply)
.../...

Après un nouvel affichage du plan, par défaut, il y a une demande de confirmation :

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:yes

Puis l’affichage d’une ligne toutes les 10s, le temps de la création qui est d’environ 30 mn :

oci_database_db_system.PROTO01-Database: Creating...
oci_database_db_system.PROTO01-Database: Still creating... [10s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [20s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [30s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [40s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [50s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1m0s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1m10s elapsed]
.../...

Après environ 1h10 (les essais d’il y a deux mois duraient plutot 1h30), le résultat est là :

oci_database_db_system.PROTO01-Database: Still creating... [1h7m11s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1h7m21s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1h7m31s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1h7m41s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1h7m51s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1h8m1s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1h8m11s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1h8m21s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1h8m31s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1h8m41s elapsed]
oci_database_db_system.PROTO01-Database: Still creating... [1h8m51s elapsed]
oci_database_db_system.PROTO01-Database: Creation complete after 1h9m31s [id=ocid1.dbsystem.oc1.eu-frankfurt-1.abtheljslgkwqazc575tx7hnrbvxmazus633uzcgbh5ynyqloagq6qqbml5a]
data.oci_database_db_nodes.DBNodeList: Refreshing state...
data.oci_database_db_node.DBNodeDetails: Refreshing state...
data.oci_core_vnic.DBNodeVnic: Refreshing state...

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

C’est bien entendu vérifiable depuis l’interface graphique :

  • Pour le DBSystem :

  • Et la base de données associée :

 

L’intérêt de cet outil est bien de pouvoir enchainer des actions de déploiement pour plusieurs services en respectant les dépendances.
Comme tout processus déclaratif, la construction des fichiers de déploiement (« *.tf ») est une tâche complexe, fastidieuse et intrensigeante concernant sa syntaxe.
Oracle a beaucoup travaillé avec et possède des modèles pour déployer rapidement l’ensemble des serveurs nécessaires à leurs applications Middleware, particulièrement PeopleSoft ou JD Edwards.
Cela facilite la mise en oeuvre et fait gagner du temps, c’est ensuite agréable de laisser la procédure se dérouler seule.

Nous sommes à la fin de cette série, il reste énormément de choses à dire et à faire sur l’infrastrucutre OCI, d’autant plus que les évolutions sont constantes.
Même si Oracle est parti en retard, les efforts réalisés commencent à se voir et il n’y a plus à rougir face aux géants du moment.
Faites-vous votre propre idée, c’est gratuit pendant 30 jours avec 250€ de Credit Cloud.

Références :