If you already have ACI running and then want to move to a DevOps approach and bring that configuration into Terraform, how can that be performed?
The ACI Terraform provider supports importing configuration. All that is required is the resource
and name of that resource.
In the following example, I will use the Cisco ACI lab to import the tenant Heroes
.
To import into Terraform for ACI all that is required is the resource
and name.
Create New Terraform File
I have created an import.tf
file that contains the Heroes
tenant resource and the name
of it. If the name
argument is different to what has been configured in ACI it will be overwritten according to the Cisco docs.
0 1 2 3 4 |
resource "aci_tenant" "Heroes" { name = "Heroes" } |
Add Import Stage to CI File
I have added an import
stage to my .gitlab-ci.yml
file. This will add the tenant resource only.
If you were to add any new resources, then this will need to be updated. It is only here to serve as an example. This is a manual process to import everything.
Lastly, this stage will only run if there is a change detected to the import.tf
file.
0 1 2 3 4 5 6 7 8 9 10 11 |
#Test Stage to import tenant import: stage: import script: - gitlab-terraform init - gitlab-terraform import "aci_tenant.Heroes" "uni/tn-Heroes" resource_group: ${TF_STATE_NAME} rules: - changes: - import.tf |
Here is the complete .gitlab-ci.yml
file.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# To contribute improvements to CI/CD templates, please follow the Development guide at: # https://docs.gitlab.com/ee/development/cicd/templates.html # This specific template is located at: # https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml include: - template: Terraform/Base.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml - template: Jobs/SAST-IaC.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/SAST-IaC.gitlab-ci.yml variables: TF_VAR_ACI_PASS: $ACI_PASS TF_VAR_ACI_USER: $ACI_USER stages: - validate - test - import - build - deploy - cleanup fmt: extends: .terraform:fmt needs: [] validate: extends: .terraform:validate needs: [] #Test Stage to import tenant import: stage: import script: - gitlab-terraform init - gitlab-terraform import "aci_tenant.Heroes" "uni/tn-Heroes" resource_group: ${TF_STATE_NAME} rules: - changes: - import.tf build: extends: .terraform:build environment: name: $TF_STATE_NAME action: prepare deploy: extends: .terraform:deploy dependencies: - build environment: name: $TF_STATE_NAME action: start cleanup: extends: .terraform:destroy dependencies: - build - deploy environment: name: $TF_STATE_NAME action: start |
Running the Pipeline
When the pipeline runs, if there is a change detected to import.tf
then the stage will run and import.
Before the import
state is run, let’s look at the current terraform state file. This file is located under: Operate
>> Terraform States
Download the JSON file by clicking on the three dots under Actions
If you download the state, there won’t be a reference for the Heroes
tenant.
Run the pipeline to import the tenant.
Return to the terraform state file: Operate
>> Terraform States
Inside this file will be the new tenant Heroes
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{ "mode": "managed", "type": "aci_tenant", "name": "Heroes", "provider": "provider[\"registry.terraform.io/ciscodevnet/aci\"]", "instances": [ { "schema_version": 1, "attributes": { "annotation": "", "description": "", "id": "uni/tn-Heroes", "name": "Heroes", "name_alias": "", "relation_fv_rs_tenant_mon_pol": "uni/tn-common/monepg-default", "relation_fv_rs_tn_deny_rule": [] }, "sensitive_attributes": [], "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjEifQ==" } ] }, |
The Heroes
tenant has now been imported. It is not configuration, so running any destroy
will lose the configuration.
Add to Configuration
Even though the tenant has been imported to the Terraform state file, it is not part of the configuration file.
The configuration can be pulled out of the JSON download for the Terraform state file. Below is the output from the Terraform state file.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{ "mode": "managed", "type": "aci_tenant", "name": "Heroes", "provider": "provider[\"registry.terraform.io/ciscodevnet/aci\"]", "instances": [ { "schema_version": 1, "attributes": { "annotation": "", "description": "", "id": "uni/tn-Heroes", "name": "Heroes", "name_alias": "", "relation_fv_rs_tenant_mon_pol": "uni/tn-common/monepg-default", "relation_fv_rs_tn_deny_rule": [] }, "sensitive_attributes": [], "private": "eyJzY2hlbWFfdmVyc2lvbiI6IjEifQ==" } ] }, |
To get the configuration for the resource out of this, use the ACI Terraform provider docs. In the reference guide, all the arguments have been referenced, but only some populated.
I am going to add in the configuration to the main.tf
file.
0 1 2 3 4 5 6 7 8 |
######################### #Tenant# ######################### resource "aci_tenant" "Heroes" { name = "Heroes" relation_fv_rs_tenant_mon_pol = "uni/tn-common/monepg-default" } |
For this to work, the tenant resource in the import.tf
file must be removed. As this changes the file, the import
stage will run in the .gitlab-ci
file. I have modified this to be manual, so I can skip it.
0 1 2 3 4 5 6 7 8 9 10 11 12 |
#Test Stage to import tenant import: stage: import script: - gitlab-terraform init - gitlab-terraform import "aci_tenant.Heroes" "uni/tn-Heroes" resource_group: ${TF_STATE_NAME} rules: - changes: - import.tf when: manual |
Reviewing the build, the Heroe
s tenant is not going to be created as expected.
If I were to manually delete the Heroes
tenant and re-run the build, I would expect to see it.