diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..3775b6c2eda7128581a767ffde794bbfa2aa05c8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM python:3.10.1-alpine + +WORKDIR /opt +COPY . /opt/ + +RUN pip install -r requirements.txt + +CMD [ "python3", "/opt/app.py"] \ No newline at end of file diff --git a/ICG.py b/ICG.py index bc5b23b97228b006b0d8f45dee1188340a82783b..5cc58a84121074e0944cee5f7fa8debb75d41aef 100644 --- a/ICG.py +++ b/ICG.py @@ -1,22 +1,26 @@ from ansibleBuilder import * from terraformBuilder import * -import json -import sys - -arg_len = len(sys.argv) -if arg_len > 1: - file_name = sys.argv[1] -else: - print("Add parameters file name") - sys.exit() +import json, sys, os -input_file = open(file_name, "r") -parameters = json.load(input_file) -for step in parameters["steps"]: - if step["programming_language"] == "ansible": - input_data = InputData(app_type=step["type"], code_path=step["output_path"], template_type=step["info"]["name"], template_path=step["info"]["template_path"], template_data=step["data"]) - icg = AnsibleICG() - icg.generate_code(input_data) - elif step["programming_language"] == "terraform": - input_data = step["data"] - TerraformICG(input_data) \ No newline at end of file +def ICG_call(parameters): + os.system('rm -f /opt/Output-code/*') + for step in parameters["steps"]: + if step["programming_language"] == "ansible": + input_data = InputData(app_type=step["type"], code_path=step["output_path"], template_type=step["info"]["name"], template_path=step["info"]["template_path"], template_data=step["data"]) + icg = AnsibleICG() + icg.generate_code(input_data) + elif step["programming_language"] == "terraform": + input_data = step["data"] + TerraformICG(input_data) + +if __name__ == '__main__': + arg_len = len(sys.argv) + if arg_len > 1: + file_name = sys.argv[1] + else: + print("Add parameters file name") + sys.exit() + + input_file = open(file_name, "r") + parameters = json.load(input_file) + ICG_call(parameters) \ No newline at end of file diff --git a/README.md b/README.md index fe67bc3abe93838c5a2f208e77e1d33f09bb5c54..022a7ac1ae81b3a862cc6a842e2a5d4b0e0e7c03 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,20 @@ # ICG Controller +This repository contains all the required code and templates to run the ICG component, it also contains a Dockerfile that builds the complete image of the ICG with a provided REST API + +Installation +------------- + +To have a functional ICG application the following steps can be used. + - Download the full content of this repository + - Build the doxker image launching inside the downloaded folder the command: docker build . + - Create a volume for the container: docker volume create ICG-volume + - Run the container: docker run --mount source=ICG-volume,target=/opt -p 5000:5000 <image_name> + +User manual +------------ + +To use the now running ICG docker container we can call the available REST API. + +The API is available in loccalhost at port 5000, the application path "/". (ex: http://localhost:5000/) +Sending a post request at this endpoint with the indicated json body (see parameters.json as an example body) it will respond with a .tar.gz file containing all the required IaC files. \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000000000000000000000000000000000000..a500035cb562be6623a0e9c744d8ab4d58950696 --- /dev/null +++ b/app.py @@ -0,0 +1,26 @@ +from ICG import * +from flask import Flask, request, send_file +import tarfile +import os.path + +def create_app(test_config=None): + app = Flask(__name__) + + app.config["CLIENT_IMAGES"] = "/opt" + + @app.post("/") + def ICG(): + if request.is_json: + parameters = request.get_json() + ICG_call(parameters) + with tarfile.open("/opt/outputIaC.tar.gz", "w:gz") as tar: + tar.add("/opt/Output-code", arcname=os.path.basename("/opt/Output-code")) + file_name = "/opt/outputIaC.tar.gz" + return send_file(file_name, attachment_filename='outputIaC.tar.gz'), 201 + return {"error": "Request must be JSON"}, 415 + return app + +APP = create_app() + +if __name__ == '__main__': + APP.run(host='0.0.0.0', port=5000, debug=True) \ No newline at end of file diff --git a/parameters.json b/parameters.json index cb5f45ba6667dbaa97efa65622fcf204a147f26f..7d49fa8a2f41e897a97cc064a4896aa1eeb4971a 100644 --- a/parameters.json +++ b/parameters.json @@ -1,87 +1,91 @@ { - "steps" : [{ - "programming_language": "terraform", - "output_path": "Output-code/", - "data":{ - "provider": "aws", - "network": [ - { - "id": 1, - "subnetname": "piacere_subnet", - "subnet_cidrblock": "10.0.1.0/24", - "vpcname": "piacere_vpc", - "vpc_cidr": "10.0.0.0/16" - } - ], - "vm": [ - { - "id": 1, - "os": "ubuntu", - "ram": 1, - "cpu": 1, - "name": "firstvm" - }, - { - "id": 2, - "os": "ubuntu", - "ram": 1, - "cpu": 1, - "name": "secondvm" - } - ], - "db": [ - { - "id": 1, - "name": "Danilo", - "group_name": "Molteni", - "server_name": "DaniloMolteni", - "email": "molteni@hpe.com" - } - ] - } - },{ - "programming_language": "ansible", - "type":"database", - "output_path": "Output-code/", - "info" : { - "name" : "mysql", - "template_path" : "Databases-templates/" + "steps": [ + { + "programming_language": "terraform", + "output_path": "/opt/Output-code/", + "data": { + "provider": "aws", + "network": [ + { + "id": 1, + "subnetname": "piacere_subnet", + "subnet_cidrblock": "10.0.1.0/24", + "vpcname": "piacere_vpc", + "vpc_cidr": "10.0.0.0/16" + } + ], + "vm": [ + { + "id": 1, + "os": "ubuntu", + "ram": 1, + "cpu": 1, + "name": "firstvm" + }, + { + "id": 2, + "os": "ubuntu", + "ram": 1, + "cpu": 1, + "name": "secondvm" + } + ], + "db": [ + { + "id": 1, + "name": "Danilo", + "group_name": "Molteni", + "server_name": "DaniloMolteni", + "email": "molteni@hpe.com" + } + ] + } }, - "data":{ - "vars":{ - "DB_USER": "app1user", - "DB_PASSWORD": "app1user", - "DB_NAME": "app1" + { + "programming_language": "ansible", + "type": "database", + "output_path": "/opt/Output-code/", + "info": { + "name": "mysql", + "template_path": "/opt/Databases-templates/" }, - "play":{ - "OS": "debian", - "HOST": 1, - "ADMIN_USER": "A", - "ADMIN_PASSWORD": "A" + "data": { + "vars": { + "DB_USER": "app1user", + "DB_PASSWORD": "app1user", + "DB_NAME": "app1" + }, + "play": { + "OS": "debian", + "HOST": 1, + "ADMIN_USER": "A", + "ADMIN_PASSWORD": "A" + } } - } - },{ - "programming_language": "ansible", - "type":"docker-service", - "output_path": "Output-code/", - "info" : { - "name" : "wordpress", - "template_path" : "Docker-services-templates/" }, - "data":{ - "vars": { - "WORDPRESS_DB_HOST": "10.10.10.10", - "WORDPRESS_DB_USER": "app1user", - "WORDPRESS_DB_PASSWORD": "app1user", - "WORDPRESS_DB_NAME": "app1", - "WORDPRESS_TABLE_PREFIX": "wp" + { + "programming_language": "ansible", + "type": "docker-service", + "output_path": "Output-code/", + "info": { + "name": "wordpress", + "template_path": "/opt/Docker-services-templates/" }, - "play":{ - "OS": "debian", - "HOST": 2, - "ADMIN_USER": "B", - "ADMIN_PASSWORD": "B" + "data": { + "vars": { + "WORDPRESS_DB_HOST": "10.10.10.10", + "WORDPRESS_DB_USER": "app1user", + "WORDPRESS_DB_PASSWORD": "app1user", + "WORDPRESS_DB_NAME": "app1", + "WORDPRESS_TABLE_PREFIX": "wp" + }, + "play": { + "OS": "debian", + "HOST": 2, + "ADMIN_USER": "B", + "ADMIN_PASSWORD": "B" + } } } - }] + ] } \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..24019da8be99b95f5956e27c981f972e57ed0dd9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +Jinja2==3.0.3 +flask==2.0.2 +PyYAML==6.0 \ No newline at end of file diff --git a/terraformUtils.py b/terraformUtils.py index 0420f110af2eda1b8d9dd31359cba6132df0e98b..c81dae67798a9a93380c449852e7bc6e672aa7c3 100644 --- a/terraformUtils.py +++ b/terraformUtils.py @@ -4,7 +4,7 @@ from aws import * def awsvm(parametri): finalString = "" - jinjaTemplate = Template(open("VM-templates/AWStemplateVM.tpl", "r").read()) + jinjaTemplate = Template(open("/opt/VM-templates/AWStemplateVM.tpl", "r").read()) for parameter in parametri: my_dict = {'vm':'aws_ami', 'id': '1', @@ -61,7 +61,7 @@ def awsvm(parametri): def gcpvm(parametri): finalString = "" - jinjaTemplate = Template(open("VM-templates/GCPtemplateVM.tpl", "r").read()) + jinjaTemplate = Template(open("/opt/VM-templates/GCPtemplateVM.tpl", "r").read()) for parameter in parametri: my_dict = {'default': 'default', 'name': 'test', 'machine_type': 'e2-medium', 'zone': 'us-central1-a'} if 'default' in parameter: @@ -82,7 +82,7 @@ def gcpvm(parametri): def azurevm(parametri): finalString = "" - jinjaTemplate = Template(open("VM-templates/AZUREtemplateVM.tpl", "r").read()) + jinjaTemplate = Template(open("/opt/VM-templates/AZUREtemplateVM.tpl", "r").read()) for parameter in parametri: my_dict = {'source': "hashicorp/azurerm", 'version': "~>2.0", 'name': "<resource_group_name>", 'location': "<location>"} if 'source' in parameter: @@ -103,7 +103,7 @@ def azurevm(parametri): def networkaws(parametri): finalString = "" - jinjaTemplate = Template(open("Network-templates/AWStemplateNetwork.tpl", "r").read()) + jinjaTemplate = Template(open("/opt/Network-templates/AWStemplateNetwork.tpl", "r").read()) for parameter in parametri: my_dict = {'subname':'subname', 'vpcname': 'vpcname', 'subnet_cidrblock':'subnet_cidrblock', 'vpc_cidr': 'vpc_cidr'} if 'subnet_cidrblock' in parameter: @@ -124,7 +124,7 @@ def networkaws(parametri): def networkg(parametri): finalString = "" - jinjaTemplate = Template(open("Network-templates/GCPtemplateNetwork.tpl", "r").read()) + jinjaTemplate = Template(open("/opt/Network-templates/GCPtemplateNetwork.tpl", "r").read()) for parameter in parametri: my_dict = {'network':'terraform-network', 'subnetwork': 'terraform-subnetwork'} if 'network' in parameter: @@ -141,7 +141,7 @@ def networkg(parametri): def networkaz(parametri): finalString = "" - jinjaTemplate = Template(open("Network-templates/AZUREtemplateNetwork.tpl", "r").read()) + jinjaTemplate = Template(open("/opt/Network-templates/AZUREtemplateNetwork.tpl", "r").read()) for parameter in parametri: my_dict = {'name':'my-resources', 'subnet_names': ["subnet1", "subnet2", "subnet3"]} if 'name' in parameter: @@ -167,7 +167,7 @@ def networkaz(parametri): def awsdb(parametri): finalString = "" - jinjaTemplate = Template(open("DB-templates/AWStemplateDB.tpl", "r").read()) + jinjaTemplate = Template(open("/opt/DB-templates/AWStemplateDB.tpl", "r").read()) for parameter in parametri: my_dict = {'identifier':'education', 'instance':'db.t3.micro', 'storage':'5', 'engine':'postgres', 'version':'13.1', 'username': 'edu', 'password':'var.db_password', 'subnet': 'aws_db_subnet_group.education.name', 'security': '[aws_security_group.rds.id]', 'parameter': 'aws_db_parameter_group.education.name', 'accessible': 'true', 'skip': 'true'} if 'identifier' in parameter: @@ -204,7 +204,7 @@ def awsdb(parametri): def azuredb(parametri): finalString = "" - jinjaTemplate = Template(open("DB-templates/AZUREtemplateDB.tpl", "r").read()) + jinjaTemplate = Template(open("/opt/DB-templates/AZUREtemplateDB.tpl", "r").read()) for parameter in parametri: my_dict = {'name':'sqldbtf01', 'group_name':'${azurerm_resource_group.test2.name}', 'location':'North Central US', 'server_name':'${azurerm_sql_server.test2.name}', 'state':'Enabled', 'email':'["dbgrl93@gmail.com"]', 'days':'30', 'access_key':'${azurerm_storage_account.test2sa.primary_access_key}', 'endpoint':'${azurerm_storage_account.test2sa.primary_blob_endpoint}', 'default':'Enabled'} if 'name' in parameter: @@ -239,7 +239,7 @@ def azuredb(parametri): def googlesql(parametri): finalString = "" - jinjaTemplate = Template(open("DB-templates/GCPtemplateDB.tpl", "r").read()) + jinjaTemplate = Template(open("/opt/DB-templates/GCPtemplateDB.tpl", "r").read()) for parameter in parametri: my_dict = {'name':'my-database', 'instance':'google_sql_database_instance.instance.name', 'instance_name':'my-database-instance','region':'us-central1', 'tier':'db-f1-micro', 'deletion_protection':'true'} if 'name' in parameter: @@ -263,7 +263,7 @@ def googlesql(parametri): create_file.close() def postgresql(parametri): - jinjaTemplate = Template(open("DB-templates/AWStemplateDB.tpl", "r").read()) + jinjaTemplate = Template(open("/opt/DB-templates/AWStemplateDB.tpl", "r").read()) my_dict = {'name': 'my_db', 'owner': 'my_role', 'template': 'template0', 'lc_collate':'C', 'connection_limit':-1, 'allow_connections': 'true'} if 'name' in parametri: my_dict['name'] = parametri['name']