From 5e7cd8f009fa78b39cf3114f62f0697405364bdc Mon Sep 17 00:00:00 2001
From: Debora Benedetto <debora.benedetto@hpe.com>
Date: Thu, 14 Jul 2022 11:40:55 +0200
Subject: [PATCH] add automation for terraform config file generation

---
 controller/Orchestrator.py                    |  6 +++---
 icgparser/DomlParserUtilities.py              |  3 +++
 icgparser/ModelParser.py                      | 21 +++++++++++++++++++
 input_file_generated/ir.json                  | 15 +++++++++++++
 plugin/PluginUtility.py                       |  8 +++++++
 plugin/TemplateUtils.py                       |  4 ++--
 plugin/TerraformPlugin.py                     |  8 +++++--
 template-location.properties                  |  1 +
 templates/terraform/open_stack/config.tpl     | 14 +++++++++++++
 .../open_stack/virtual_machine_out.tpl        |  2 +-
 10 files changed, 74 insertions(+), 8 deletions(-)
 create mode 100644 plugin/PluginUtility.py
 create mode 100644 templates/terraform/open_stack/config.tpl

diff --git a/controller/Orchestrator.py b/controller/Orchestrator.py
index 29af7c8..62897d6 100644
--- a/controller/Orchestrator.py
+++ b/controller/Orchestrator.py
@@ -30,9 +30,9 @@ def choose_plugin(parameters, template_generated_folder):
     for step in parameters["steps"]:
         if step["programming_language"] == "ansible":
             logging.info("Ansible Plugin chosen")
-            metadata_root_folder["iac"].append("ansible")
-            input_data = step["data"]
-            AnsiblePlugin.create_files(input_data, template_generated_folder)
+        #     metadata_root_folder["iac"].append("ansible")
+        #     input_data = step["data"]
+        #     AnsiblePlugin.create_files(input_data, template_generated_folder)
         elif step["programming_language"] == "terraform":
             logging.info("Terraform Plugin chosen")
             metadata_root_folder["iac"].append("terraform")
diff --git a/icgparser/DomlParserUtilities.py b/icgparser/DomlParserUtilities.py
index 0f1b76f..0125b8b 100644
--- a/icgparser/DomlParserUtilities.py
+++ b/icgparser/DomlParserUtilities.py
@@ -85,6 +85,9 @@ def save_references_info(from_object, to_object):  ## TODO refactoring
             update_missing_parsed_resources(reference_object, reference=ref, is_to_be_parsed=True)
     return to_object
 
+def get_references(from_object):
+    refs = from_object.eClass.eAllReferences()
+    return list(refs)
 
 def save_inner_components(from_object, to_object):
     inner_components = from_object.eAllContents()
diff --git a/icgparser/ModelParser.py b/icgparser/ModelParser.py
index 7666d79..1dd5daa 100644
--- a/icgparser/ModelParser.py
+++ b/icgparser/ModelParser.py
@@ -76,13 +76,34 @@ def parse_infrastructural_objects(doml_model):
         infra_object_step = include_missing_objects_from_infrastructure_layer(infra_object_step)
     return infra_object_step
 
+def parse_application_layer(doml_model):
+    logging.info("DOML parsing: getting active configuration")
+    application_object_step = {"programming_language": "ansible", "data": {}}
+    active_configuration = doml_model.activeConfiguration
+    logging.info(f"Found active configuration '{active_configuration.name}'")
+    for deployment in list(active_configuration.deployments):
+        deployment_component_name = deployment.component.name
+        logging.info(f'Parsing deployment for component {deployment_component_name}')
+        refs = DomlParserUtilities.get_references(deployment)
+        object_list_representation = []
+        for ref in refs:
+            object_representation = {}
+            obj = deployment.eGet(ref.name)
+            object_representation = DomlParserUtilities.save_annotations(obj, object_representation)
+            object_representation = DomlParserUtilities.save_attributes(obj, object_representation)
+            object_list_representation.append(object_representation)
+
+        application_object_step["data"][deployment.component.name] = object_list_representation
+    return application_object_step
 
 def create_intermediate_representation(model_loaded):
     model_name = model_loaded.name
     output_path = OUTPUT_BASE_DIR_PATH + model_name + "/"
     intermediate_representation_steps = []
     infra_object_step = parse_infrastructural_objects(model_loaded)
+    application_step = parse_application_layer(model_loaded)
     intermediate_representation_steps.append(infra_object_step)
+    intermediate_representation_steps.append(application_step)
     intermediate_representation = {
         "output_path": output_path,
         "steps": intermediate_representation_steps
diff --git a/input_file_generated/ir.json b/input_file_generated/ir.json
index 3a81c9d..5dc101a 100644
--- a/input_file_generated/ir.json
+++ b/input_file_generated/ir.json
@@ -94,6 +94,21 @@
         ]
       },
       "programming_language": "terraform"
+    },
+    {
+      "data": {
+        "nginx": [
+          {
+            "name": "vm1",
+            "os": "ubuntu-20.04.3"
+          },
+          {
+            "name": "nginx",
+            "source_code": "/usr/share/nginx/html/index.html"
+          }
+        ]
+      },
+      "programming_language": "ansible"
     }
   ]
 }
\ No newline at end of file
diff --git a/plugin/PluginUtility.py b/plugin/PluginUtility.py
new file mode 100644
index 0000000..1b4326e
--- /dev/null
+++ b/plugin/PluginUtility.py
@@ -0,0 +1,8 @@
+from plugin import TemplateUtils
+
+
+def createExecutionFileInstructions(iac_language, key, data):
+    template_for_config_path = TemplateUtils.find_template_path(iac_language, key, "config")
+    template_for_config = TemplateUtils.read_template(template_for_config_path)
+    template_for_config_path_edited = TemplateUtils.edit_template(template_for_config, data)
+    return template_for_config_path_edited
diff --git a/plugin/TemplateUtils.py b/plugin/TemplateUtils.py
index 6eeb561..c74d427 100644
--- a/plugin/TemplateUtils.py
+++ b/plugin/TemplateUtils.py
@@ -23,7 +23,7 @@ def find_template_path(iac_language, key, resource_name):
 
 
 def edit_template(template, parameters: dict):
-    logging.info("Starting editing template")
+    logging.info(f"Starting editing template '{template}'")
     template.globals['context'] = get_context
     template.globals['callable'] = callable
     render = template.render(parameters)
@@ -47,4 +47,4 @@ def write_template(template, output_path_file):
     file = open(output_path_file, "w+")
     file.write(template)
     logging.info("Writing file at: '%s'", output_path_file)
-    file.close()
+    file.close()
\ No newline at end of file
diff --git a/plugin/TerraformPlugin.py b/plugin/TerraformPlugin.py
index 6b7facf..ef165ce 100644
--- a/plugin/TerraformPlugin.py
+++ b/plugin/TerraformPlugin.py
@@ -1,10 +1,13 @@
 import logging
-from plugin import TemplateUtils
+from plugin import TemplateUtils, PluginUtility
 
 
 def create_files(parameters, output_path):
     language = "terraform"
     provider = parameters["provider"]
+
+    config_file = PluginUtility.createExecutionFileInstructions(language, provider, parameters)
+
     resources = parameters.keys()
     terraform_main_file = create_init_file(language, provider)
     terraform_out_file = ""
@@ -27,11 +30,12 @@ def create_files(parameters, output_path):
                 # resource = parameters[resource_name]
                 template_out_filled = TemplateUtils.edit_template(template_out, resource_params)
                 terraform_out_file = terraform_out_file + template_out_filled + "\n"
-
     main_file_stored_path = output_path + "/main.tf"
     TemplateUtils.write_template(terraform_main_file, main_file_stored_path)
     output_file_stored_path = output_path + "/output.tf"
     TemplateUtils.write_template(terraform_out_file, output_file_stored_path)
+    config_file_stored_path = output_path + "/config.yaml"
+    TemplateUtils.write_template(config_file, config_file_stored_path)
     logging.info("Terraform main file available at: {}".format(main_file_stored_path))
     logging.info(f"Terraform output file available at {output_file_stored_path}")
 
diff --git a/template-location.properties b/template-location.properties
index 2a462fc..f6a4c4a 100644
--- a/template-location.properties
+++ b/template-location.properties
@@ -1,5 +1,6 @@
 [terraform.openstack]
 init = templates/terraform/open_stack/init.tpl
+config = templates/terraform/open_stack/config.tpl
 vms = templates/terraform/open_stack/virtual_machine.tpl
 vms_out = templates/terraform/open_stack/virtual_machine_out.tpl
 networks = templates/terraform/open_stack/network.tpl
diff --git a/templates/terraform/open_stack/config.tpl b/templates/terraform/open_stack/config.tpl
new file mode 100644
index 0000000..83b68b7
--- /dev/null
+++ b/templates/terraform/open_stack/config.tpl
@@ -0,0 +1,14 @@
+---
+engine: terraform
+input:
+  - OS_USERNAME
+  - OS_PASSWORD
+  - OS_AUTH_URL
+  - OS_PROJECT_NAME
+output:
+{% for vm in vms %}
+  - instance_server_public_key_{{ vm.vm_key_name }}
+  - instance_server_private_key_{{ vm.vm_key_name }}
+  - instance_ip_{{ vm.vm_name }}
+{% endfor %}
+...
diff --git a/templates/terraform/open_stack/virtual_machine_out.tpl b/templates/terraform/open_stack/virtual_machine_out.tpl
index 95fa933..e39fa9f 100644
--- a/templates/terraform/open_stack/virtual_machine_out.tpl
+++ b/templates/terraform/open_stack/virtual_machine_out.tpl
@@ -6,6 +6,6 @@ output "instance_server_private_key_{{ vm_key_name }}" {
   value = openstack_compute_keypair_v2.{{ vm_key_name }}.private_key
 }
 
-output "instance_ip" {
+output "instance_ip_{{ vm_name }}" {
   value = openstack_compute_floatingip_associate_v2.{{ infra_element_name ~ "_floating_ip_association" }}.floating_ip
 }
\ No newline at end of file
-- 
GitLab