diff --git a/CHANGELOG.md b/CHANGELOG.md index 36804d2a1..e8ebcac2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,16 @@ # Release Notes +## Version 0.10.2 +**Release Date**: 27th August 2020 +### Bug Fixes +1. Resolve issue where deleting an artefact would cause an addition OKE cluster to be created if one exists on the canvas. In addition deleteing OKE caused it to be removed from the model but not the view. + + ## Version 0.10.1 **Release Date**: 27th August 2020 ### Bug Fixes -1. Querying occasionally hit a condition where the SVG rectangle does not exist before attempting to get the bounding client information (Issuse: #86) +1. Querying occasionally hit a condition where the SVG rectangle does not exist before attempting to get the bounding client information (Issue: #86) ## Version 0.10.0 diff --git a/README.md b/README.md index 336db2cc2..f5fe8b111 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# OCI Designer Toolkit [0.10.1](CHANGELOG.md#version-0.10.1) +# OCI Designer Toolkit [0.10.2](CHANGELOG.md#version-0.10.2) OCI designer toolKIT (OKIT) is a set of tools for enabling design, deploy and visualise OCI environments through a graphical web based interface. diff --git a/documentation/Installation.md b/documentation/Installation.md index 18893a037..714ff8b60 100644 --- a/documentation/Installation.md +++ b/documentation/Installation.md @@ -22,22 +22,22 @@ python modules are installed and in addition provide a simple flask server that ## Clone Repository Before the building either the Docker or Vagrant Images the project will nee to be cloned from the Git Repository (or downloaded) and it is recommended that the latest Stable Release be cloned. The latest stable version number if shown in the README -and the associated Release tag is in the format vX.Y.Z hence for the version 0.10.1 the Release tag will be -**v0.10.1**. The command shows how this can be cloned to the local machine. +and the associated Release tag is in the format vX.Y.Z hence for the version 0.10.2 the Release tag will be +**v0.10.2**. The command shows how this can be cloned to the local machine. ```bash -git clone -b v0.10.1 --depth 1 git@github.com:oracle/oci-designer-toolkit.git +git clone -b v0.10.2 --depth 1 git@github.com:oracle/oci-designer-toolkit.git ``` or ```bash -git clone -b v0.10.1 --depth 1 https://github.com/oracle/oci-designer-toolkit.git +git clone -b v0.10.2 --depth 1 https://github.com/oracle/oci-designer-toolkit.git ``` ### Download If you do not have git installed locally the current release of OKIT can be retrieved by downloading it as a zip file from -https://github.com/oracle/oci-designer-toolkit/archive/v0.10.1.zip +https://github.com/oracle/oci-designer-toolkit/archive/v0.10.2.zip ## OCI Config File diff --git a/okitweb/__init__.py b/okitweb/__init__.py index 7a0f92ee1..bc6e3a823 100644 --- a/okitweb/__init__.py +++ b/okitweb/__init__.py @@ -47,5 +47,7 @@ def favicon(): app.register_blueprint(okitPricing.bp) from . import okitOci app.register_blueprint(okitOci.bp) + from . import okitImport + app.register_blueprint(okitImport.bp) return app diff --git a/okitweb/okitImport.py b/okitweb/okitImport.py new file mode 100644 index 000000000..8a78b8f2e --- /dev/null +++ b/okitweb/okitImport.py @@ -0,0 +1,38 @@ +#!/usr/bin/python + +"""Provide Module Description +""" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +__author__ = ["Andrew Hopkinson (Oracle Cloud Solutions A-Team)"] +__version__ = "1.0.0.0" +__module__ = "okitImport" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +import os +from flask import Blueprint +from flask import request + +import json +from common.okitCommon import logJson +from common.okitLogging import getLogger +from parsers.okitHclJsonParser import OkitHclJsonParser + +# Configure logging +logger = getLogger() + +bp = Blueprint('parsers', __name__, url_prefix='/okit/import', static_folder='static/okit') + +debug_mode = bool(str(os.getenv('DEBUG_MODE', 'False')).title()) + +@bp.route('hcljson', methods=(['POST'])) +def importHclJson(): + logger.debug('JSON : {0:s}'.format(str(request.json))) + if request.method == 'POST': + logJson(request.json) + # Import HCL + parser = OkitHclJsonParser(request.json) + return json.dumps(parser.parse(), sort_keys=False, indent=2, separators=(',', ': ')) + else: + return '404' diff --git a/okitweb/static/okit/js/okit_console.js b/okitweb/static/okit/js/okit_console.js index 9ca4d9d25..7d963805a 100644 --- a/okitweb/static/okit/js/okit_console.js +++ b/okitweb/static/okit/js/okit_console.js @@ -4,7 +4,7 @@ */ console.info('Loaded Console Javascript'); -const okitVersion = '0.10.1'; +const okitVersion = '0.10.2'; const okitReleaseDate = '27th August 2020'; // Validation const validate_error_colour = "#ff4d4d"; diff --git a/okitweb/static/okit/json/release.json b/okitweb/static/okit/json/release.json index ed619cb62..ce76532a4 100644 --- a/okitweb/static/okit/json/release.json +++ b/okitweb/static/okit/json/release.json @@ -1,4 +1,4 @@ { - "release": "0.10.1", - "tag": "v0.10.1" + "release": "0.10.2", + "tag": "v0.10.2" } \ No newline at end of file diff --git a/okitweb/static/okit/model/js/okit_model.js b/okitweb/static/okit/model/js/okit_model.js index fcf5053b7..158fe2ae0 100644 --- a/okitweb/static/okit/model/js/okit_model.js +++ b/okitweb/static/okit/model/js/okit_model.js @@ -18,7 +18,6 @@ class OkitJson { this.compartments = []; this.autonomous_databases = []; this.block_storage_volumes = []; - this.oke_clusters = []; this.database_systems = []; this.dynamic_routing_gateways = []; this.fast_connects = []; @@ -31,6 +30,7 @@ class OkitJson { this.nat_gateways = []; this.network_security_groups = []; this.object_storage_buckets = []; + this.oke_clusters = []; this.remote_peering_gateways = []; this.route_tables = []; this.security_lists = []; diff --git a/okitweb/static/okit/palette/compute/Instance_Pool.svg b/okitweb/static/okit/palette/compute/Instance_Pool.svg new file mode 100755 index 000000000..e00ddde16 --- /dev/null +++ b/okitweb/static/okit/palette/compute/Instance_Pool.svg @@ -0,0 +1,13 @@ + + + + + + + diff --git a/okitweb/static/okit/view/designer/js/okit_designer_view.js b/okitweb/static/okit/view/designer/js/okit_designer_view.js index 40c4050ae..3e25782e7 100644 --- a/okitweb/static/okit/view/designer/js/okit_designer_view.js +++ b/okitweb/static/okit/view/designer/js/okit_designer_view.js @@ -109,10 +109,6 @@ class OkitDesignerJsonView extends OkitJsonView { for (let file_storage_system of this.file_storage_systems) { file_storage_system.draw(); } - // Containers - for (let container of this.containers) { - container.draw(); - } // Instances for (let instance of this.instances) { instance.draw(); diff --git a/okitweb/static/okit/view/js/okit_view.js b/okitweb/static/okit/view/js/okit_view.js index 68cfce7ae..1a02c66c9 100644 --- a/okitweb/static/okit/view/js/okit_view.js +++ b/okitweb/static/okit/view/js/okit_view.js @@ -71,7 +71,6 @@ class OkitJsonView { this.compartments = []; this.autonomous_databases = []; this.block_storage_volumes = []; - this.containers = []; this.database_systems = []; this.dynamic_routing_gateways = []; this.fast_connects = []; @@ -83,6 +82,7 @@ class OkitJsonView { this.nat_gateways = []; this.network_security_groups = []; this.object_storage_buckets = []; + this.oke_clusters = []; this.remote_peering_gateways = []; this.route_tables = []; this.security_lists = []; @@ -750,7 +750,7 @@ class OkitJsonView { } return undefined; } - deleteOkeCluster() { + deleteOkeCluster(id='') { this.okitjson.deleteOkeCluster(id); this.update(); } diff --git a/okitweb/static/okit/view/tree/css/okit_tree_view.css b/okitweb/static/okit/view/tree/css/okit_tree_view.css index 0ce91cd2a..41de95fa0 100644 --- a/okitweb/static/okit/view/tree/css/okit_tree_view.css +++ b/okitweb/static/okit/view/tree/css/okit_tree_view.css @@ -56,6 +56,18 @@ rect.okit-explorer-view-highlight { white-space: nowrap; } +.collapsible-view-element > div::before { + content: "-"; + color: #336600; + display: inline-block; +} + +.simple-view-element > div::before { + content: "├"; + color: #336600; + display: inline-block; +} + .autonomous-database-tree-view > div { background-image: url("/static/okit/palette/database/Autonomous_Database.svg"); } @@ -68,7 +80,7 @@ rect.okit-explorer-view-highlight { background-image: url("/static/okit/palette/containers/Compartment.svg"); } -.compartment-tree-view > div::before { +.compartment-tree-view1 > div::before { content: "-"; color: #336600; display: inline-block; @@ -134,7 +146,7 @@ rect.okit-explorer-view-highlight { background-image: url("/static/okit/palette/networking/Subnet.svg"); } -.subnet-tree-view > div::before { +.subnet-tree-view1 > div::before { content: "-"; color: #336600; display: inline-block; @@ -144,7 +156,7 @@ rect.okit-explorer-view-highlight { background-image: url("/static/okit/palette/networking/Virtual_Cloud_Network.svg"); } -.vcn-tree-view > div::before { +.vcn-tree-view1 > div::before { content: "-"; color: #336600; display: inline-block; diff --git a/okitweb/static/okit/view/tree/js/okit_tree_view.js b/okitweb/static/okit/view/tree/js/okit_tree_view.js index 8281c6454..fb0a5600d 100644 --- a/okitweb/static/okit/view/tree/js/okit_tree_view.js +++ b/okitweb/static/okit/view/tree/js/okit_tree_view.js @@ -47,26 +47,29 @@ class OkitJsonTreeView extends OkitJsonView { d3.select(d3Id(id + '_li')).append('ul') .attr('id', id + '_ul') .attr('class', ''); + $(jqId(id + '_li')).addClass('collapsible-view-element'); + } else { + $(jqId(id + '_li')).addClass('simple-view-element'); } } // Autonomous Database drawAutonomousDatabase(id, parent_id) { console.info('Drawing Autonomous Database ' + id); - this.addItemToTree(parent_id, id, 'autonomous-database-tree-okit_view', this.getOkitJson().getAutonomousDatabase(id).display_name, false); + this.addItemToTree(parent_id, id, 'autonomous-database-tree-view', this.getOkitJson().getAutonomousDatabase(id).display_name, false); } // Block Storage Volume drawBlockStorageVolume(id, parent_id) { console.info('Drawing Block Storage ' + id); - this.addItemToTree(parent_id, id, 'block-storage-tree-okit_view', this.getOkitJson().getBlockStorageVolume(id).display_name, false); + this.addItemToTree(parent_id, id, 'block-storage-tree-view', this.getOkitJson().getBlockStorageVolume(id).display_name, false); } // Compartments drawCompartment(id, parent_id) { console.info('Drawing Compartment ' + id); - this.addItemToTree(parent_id, id, 'compartment-tree-okit_view', this.getOkitJson().getCompartment(id).display_name, true); + this.addItemToTree(parent_id, id, 'compartment-tree-view', this.getOkitJson().getCompartment(id).display_name, true); this.drawCompartmentSubComponents(id); } @@ -106,91 +109,91 @@ class OkitJsonTreeView extends OkitJsonView { // Database Systems drawDatabaseSystem(id, parent_id) { console.info('Drawing Database System ' + id); - this.addItemToTree(parent_id, id, 'database-system-tree-okit_view', this.getOkitJson().getDatabaseSystem(id).display_name, false); + this.addItemToTree(parent_id, id, 'database-system-tree-view', this.getOkitJson().getDatabaseSystem(id).display_name, false); } // Dynamic Routing Gateway drawDynamicRoutingGateway(id, parent_id) { console.info('Drawing Dynamic Routing Gateway ' + id); - this.addItemToTree(parent_id, id, 'drg-tree-okit_view', this.getOkitJson().getDynamicRoutingGateway(id).display_name, false); + this.addItemToTree(parent_id, id, 'drg-tree-view', this.getOkitJson().getDynamicRoutingGateway(id).display_name, false); } // Fast Connect drawFastConnect(id, parent_id) { console.info('Drawing Fast Connect ' + id); - this.addItemToTree(parent_id, id, 'fast-connect-tree-okit_view', this.getOkitJson().getFastConnect(id).display_name, false); + this.addItemToTree(parent_id, id, 'fast-connect-tree-view', this.getOkitJson().getFastConnect(id).display_name, false); } // File Storage System drawFileStorageSystem(id, parent_id) { console.info('Drawing File Storage System ' + id); - this.addItemToTree(parent_id, id, 'file-storage-tree-okit_view', this.getOkitJson().getFileStorageSystem(id).display_name, false); + this.addItemToTree(parent_id, id, 'file-storage-tree-view', this.getOkitJson().getFileStorageSystem(id).display_name, false); } // Instance drawInstance(id, parent_id) { console.info('Drawing Instance ' + id); - this.addItemToTree(parent_id, id, 'instance-tree-okit_view', this.getOkitJson().getInstance(id).display_name, false); + this.addItemToTree(parent_id, id, 'instance-tree-view', this.getOkitJson().getInstance(id).display_name, false); } // InternetGateway drawInternetGateway(id, parent_id) { console.info('Drawing Internet gateway ' + id); - this.addItemToTree(parent_id, id, 'internet-gateway-tree-okit_view', this.getOkitJson().getInternetGateway(id).display_name, false); + this.addItemToTree(parent_id, id, 'internet-gateway-tree-view', this.getOkitJson().getInternetGateway(id).display_name, false); } // Load Balancers drawLoadBalancer(id, parent_id) { console.info('Drawing Load Balancer ' + id); - this.addItemToTree(parent_id, id, 'loadbalancer-tree-okit_view', this.getOkitJson().getLoadBalancer(id).display_name, false); + this.addItemToTree(parent_id, id, 'loadbalancer-tree-view', this.getOkitJson().getLoadBalancer(id).display_name, false); } // Local Peering Gateway drawLocalPeeringGateway(id, parent_id) { console.info('Drawing Local Peering Gateway ' + id); - this.addItemToTree(parent_id, id, 'lpg-tree-okit_view', this.getOkitJson().getLocalPeeringGateway(id).display_name, false); + this.addItemToTree(parent_id, id, 'lpg-tree-view', this.getOkitJson().getLocalPeeringGateway(id).display_name, false); } // NAT Gateway drawNATGateway(id, parent_id) { console.info('Drawing NAT Gateway ' + id); - this.addItemToTree(parent_id, id, 'nat-gateway-tree-okit_view', this.getOkitJson().getNATGateway(id).display_name, false); + this.addItemToTree(parent_id, id, 'nat-gateway-tree-view', this.getOkitJson().getNATGateway(id).display_name, false); } // Network Security Group drawNetworkSecurityGroup(id, parent_id) { console.info('Drawing Network Security Group ' + id); - this.addItemToTree(parent_id, id, 'network-security-group-tree-okit_view', this.getOkitJson().getNetworkSecurityGroup(id).display_name, false); + this.addItemToTree(parent_id, id, 'network-security-group-tree-view', this.getOkitJson().getNetworkSecurityGroup(id).display_name, false); } // Object Storage Bucket drawObjectStorageBucket(id, parent_id) { console.info('Drawing Object Storage Bucket ' + id); - this.addItemToTree(parent_id, id, 'object-storage-tree-okit_view', this.getOkitJson().getObjectStorageBucket(id).display_name, false); + this.addItemToTree(parent_id, id, 'object-storage-tree-view', this.getOkitJson().getObjectStorageBucket(id).display_name, false); } // Route Table drawRouteTable(id, parent_id) { console.info('Drawing Route Table ' + id); - this.addItemToTree(parent_id, id, 'route-table-tree-okit_view', this.getOkitJson().getRouteTable(id).display_name, false); + this.addItemToTree(parent_id, id, 'route-table-tree-view', this.getOkitJson().getRouteTable(id).display_name, false); } // Security List drawSecurityList(id, parent_id) { console.info('Drawing Security List ' + id); - this.addItemToTree(parent_id, id, 'security-list-tree-okit_view', this.getOkitJson().getSecurityList(id).display_name, false); + this.addItemToTree(parent_id, id, 'security-list-tree-view', this.getOkitJson().getSecurityList(id).display_name, false); } // Service Gateway drawServiceGateway(id, parent_id) { console.info('Drawing Service Gateway ' + id); - this.addItemToTree(parent_id, id, 'service-gateway-tree-okit_view', this.getOkitJson().getServiceGateway(id).display_name, false); + this.addItemToTree(parent_id, id, 'service-gateway-tree-view', this.getOkitJson().getServiceGateway(id).display_name, false); } // Subnets drawSubnet(id, parent_id) { console.info('Drawing Subnet ' + id); - this.addItemToTree(parent_id, id, 'subnet-tree-okit_view', this.getOkitJson().getSubnet(id).display_name, true); + this.addItemToTree(parent_id, id, 'subnet-tree-view', this.getOkitJson().getSubnet(id).display_name, true); this.drawSubnetSubComponents(id); } @@ -208,7 +211,7 @@ class OkitJsonTreeView extends OkitJsonView { } } // Load Balancers - for (let loadbalancer of this.getOkitJson().getloadBalancers()) { + for (let loadbalancer of this.getOkitJson().getLoadBalancers()) { if (loadbalancer.subnet_id === id) { this.drawLoadBalancer(loadbalancer.id, `${id}_ul`); } @@ -236,7 +239,7 @@ class OkitJsonTreeView extends OkitJsonView { // Virtual Cloud Networks drawVirtualCloudNetwork(id, parent_id) { console.info('Drawing Virtual Cloud Network ' + id); - this.addItemToTree(parent_id, id, 'vcn-tree-okit_view', this.getOkitJson().getVirtualCloudNetwork(id).display_name, true); + this.addItemToTree(parent_id, id, 'vcn-tree-view', this.getOkitJson().getVirtualCloudNetwork(id).display_name, true); this.drawVirtualCloudNetworkSubComponents(id); } diff --git a/okitweb/templates/okit/okit_designer.html b/okitweb/templates/okit/okit_designer.html index ca4cc2049..ecad0b3d2 100644 --- a/okitweb/templates/okit/okit_designer.html +++ b/okitweb/templates/okit/okit_designer.html @@ -151,6 +151,17 @@
  • Ansible
  • Resource Manager
  • + {% endblock %} diff --git a/visualiser/parsers/okitHclJsonParser.py b/visualiser/parsers/okitHclJsonParser.py new file mode 100644 index 000000000..d3f3b91b5 --- /dev/null +++ b/visualiser/parsers/okitHclJsonParser.py @@ -0,0 +1,112 @@ +#!/usr/bin/python + +"""Provide Module Description +""" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +__author__ = ["Andrew Hopkinson (Oracle Cloud Solutions A-Team)"] +__version__ = "1.0.0.0" +__module__ = "OkitHclJsonParser" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# + +import json +from common.okitLogging import getLogger + +# Configure logging +logger = getLogger() + + +class OkitHclJsonParser(object): + tf_map = { + "oci_core_vcn": "virtual_cloud_networks", + "oci_core_subnet": "subnets", + "oci_core_route_table": "route_tables", + "oci_core_default_security_list": "security_lists", + "oci_core_security_list": "security_lists", + "oci_core_internet_gateway": "internet_gateways", + "oci_core_network_security_group": "network_security_groups", + "oci_core_instance": "instances" + } + + def __init__(self, hcl_json=None): + self.hcl_json = hcl_json + self.okit_json = self.initialiseOkitJson() + if self.hcl_json is not None: + self.convert() + + + def initialiseOkitJson(self): + okitjson = { + "compartments": [ + { + "id": "var.compartment_id", + "name": "okit-root", + "compartment_id": None, + "parent_id": "canvas", + "display_name": "okit-root" + } + ], + "autonomous_databases": [], + "block_storage_volumes": [], + "database_systems": [], + "dynamic_routing_gateways": [], + "fast_connects": [], + "file_storage_systems": [], + "instances": [], + "instance_pools": [], + "internet_gateways": [], + "load_balancers": [], + "local_peering_gateways": [], + "nat_gateways": [], + "network_security_groups": [], + "object_storage_buckets": [], + "oke_clusters": [], + "remote_peering_gateways": [], + "route_tables": [], + "security_lists": [], + "service_gateways": [], + "subnets": [], + "virtual_cloud_networks": [], + "web_application_firewalls": [] + } + return okitjson + + + def processOddities(self, artefact): + # Instance + if "create_vnic_details" in artefact: + artefact["vnics"] = artefact["create_vnic_details"] + del artefact["create_vnic_details"] + + # Default Security List + if "manage_default_resource_id" in artefact: + id = artefact["manage_default_resource_id"].split(".") + id[-1] = id[-1][-3:] + artefact["vcn_id"] = ".".join(id) + del artefact["manage_default_resource_id"] + return artefact + + + def parse(self, hcl_json=None): + if hcl_json is not None: + self.hcl_json = hcl_json + + self.okit_json = self.initialiseOkitJson() + result_json = {"okit_json": {}, "warnings": {}} + + if self.hcl_json is not None: + # Loop through resource + for resource in self.hcl_json["resource"]: + for resource_key, resource_value in resource.items(): + for artefact in resource_value: + for artefact_key, artefact_value in artefact.items(): + for artefact_json in artefact_value: + artefact_json["id"] = "{0!s:s}.{1!s:s}.id".format(resource_key, artefact_key) + if resource_key in self.tf_map: + self.okit_json[self.tf_map[resource_key]].append(self.processOddities(artefact_json)) + else: + logger.warn("Unknown Resource {0!s:s}".format(resource_key)) + result_json["warnings"][resource_key] = "Unknown Resource {0!s:s}".format(resource_key) + result_json["okit_json"] = self.okit_json + return result_json