summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--LICENSE201
-rw-r--r--mock-aai/Dockerfile11
-rw-r--r--mock-aai/README.md2
-rw-r--r--mock-aai/app.py154
-rw-r--r--mock-aai/requirements.txt1
-rw-r--r--mock-aai/resources/__init__.py16
-rw-r--r--mock-aai/resources/cloud_region.py193
-rw-r--r--mock-aai/resources/complex.py65
-rw-r--r--mock-aai/resources/customer.py325
-rw-r--r--mock-aai/resources/network.py61
-rw-r--r--mock-aai/resources/vnf.py108
-rw-r--r--mock-cds/Dockerfile17
-rw-r--r--mock-cds/Pipfile12
-rw-r--r--mock-cds/Pipfile.lock125
-rw-r--r--mock-cds/README.md2
-rw-r--r--mock-cds/app/app.py22
-rw-r--r--mock-cds/app/routes.py22
-rw-r--r--mock-cds/app/views.py51
-rw-r--r--mock-cds/cleanup-dev.sh6
-rw-r--r--mock-cds/run-dev.sh8
-rw-r--r--mock-clamp/.dockerignore13
-rw-r--r--mock-clamp/Dockerfile32
-rw-r--r--mock-clamp/README.md1
-rw-r--r--mock-clamp/clamp_handlers.go130
-rw-r--r--mock-clamp/generic_handlers.go32
-rw-r--r--mock-clamp/loop_handlers.go404
-rw-r--r--mock-clamp/mock-clamp.go44
-rw-r--r--mock-clamp/policies_handlers.go98
-rw-r--r--mock-dmaap/Dockerfile7
-rw-r--r--mock-dmaap/Makefile23
-rw-r--r--mock-dmaap/README.md23
-rw-r--r--mock-dmaap/app/app.py98
-rw-r--r--mock-dmaap/app/event_storage.py40
-rw-r--r--mock-dmaap/app/sdc.py38
-rw-r--r--mock-dmaap/app/ves.py46
-rw-r--r--mock-dmaap/requirements.txt6
-rw-r--r--mock-msb-k8s/Dockerfile11
-rw-r--r--mock-msb-k8s/README.md2
-rw-r--r--mock-msb-k8s/app/app.py284
-rw-r--r--mock-msb-k8s/requirements.txt2
-rw-r--r--mock-sdc/.dockerignore16
-rw-r--r--mock-sdc/Dockerfile33
-rw-r--r--mock-sdc/README.md2
-rw-r--r--mock-sdc/generic_handlers.go32
-rw-r--r--mock-sdc/mock-sdc.go71
-rw-r--r--mock-sdc/resource_handlers.go1379
-rw-r--r--mock-sdc/sdc_handlers.go210
-rw-r--r--mock-sdc/vendor_handlers.go185
-rw-r--r--mock-sdc/vsp_handlers.go418
-rw-r--r--mock-sdnc/Dockerfile11
-rw-r--r--mock-sdnc/README.md2
-rw-r--r--mock-sdnc/app.py35
-rw-r--r--mock-sdnc/requirements.txt1
-rw-r--r--mock-sdnc/resources/__init__.py16
-rw-r--r--mock-sdnc/resources/preload.py28
-rw-r--r--mock-so/Dockerfile11
-rw-r--r--mock-so/README.md2
-rw-r--r--mock-so/app.py126
-rw-r--r--mock-so/requirements.txt2
-rw-r--r--mock-so/resources/__init__.py16
-rw-r--r--mock-so/resources/orchestration_request.py93
-rw-r--r--mock-so/resources/service_instance.py344
-rw-r--r--mock-ves/Dockerfile17
-rw-r--r--mock-ves/README.md26
-rw-r--r--mock-ves/app/app.py84
-rw-r--r--mock-ves/cleanup-dev.sh7
-rw-r--r--mock-ves/requirements.txt2
-rw-r--r--mock-ves/run-dev.sh8
68 files changed, 5913 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..5b656e9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2019 Orange-OpenSource / lfn / onap
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/mock-aai/Dockerfile b/mock-aai/Dockerfile
new file mode 100644
index 0000000..d558a0d
--- /dev/null
+++ b/mock-aai/Dockerfile
@@ -0,0 +1,11 @@
+FROM python:3.8-alpine
+
+COPY . /app
+
+WORKDIR /app
+
+RUN pip install -r requirements.txt
+
+ENTRYPOINT ["python"]
+
+CMD ["app.py"]
diff --git a/mock-aai/README.md b/mock-aai/README.md
new file mode 100644
index 0000000..5217b76
--- /dev/null
+++ b/mock-aai/README.md
@@ -0,0 +1,2 @@
+# mock-aai
+
diff --git a/mock-aai/app.py b/mock-aai/app.py
new file mode 100644
index 0000000..408d3e4
--- /dev/null
+++ b/mock-aai/app.py
@@ -0,0 +1,154 @@
+"""A&AI mock application."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from flask import Flask
+from flask_restful import Resource, Api
+
+from resources.cloud_region import (
+ CloudRegion,
+ CloudRegionList,
+ CloudRegionRelationshipList,
+ CloudRegionRelationship,
+ Tenant,
+ TenantList,
+)
+from resources.complex import Complex, ComplexList
+from resources.customer import (
+ Customer,
+ CustomerList,
+ ServiceSubscription,
+ ServiceSubscriptionInstance,
+ ServiceSubscriptionList,
+ ServiceSubscriptionRelationship,
+ ServiceSubscriptionRelationshipList,
+ ServiceSubscriptionInstanceList,
+ ServiceSubscriptionInstanceRelationshipList,
+)
+from resources.network import Network
+from resources.vnf import Vnf, VfModule, VfModuleList
+
+app = Flask(__name__)
+api = Api(app)
+
+API_VERSIONS_SUPPORTED = ["v16", "v20", "v23", "v26"]
+
+def generate_urls_for_all_versions(endpoint_pattern: str) -> list:
+ """Helper function.
+
+ Generates list of endpoints by replacing <version> pattern for each supported API version.
+
+ Args:
+ endpoint_pattern (str): url pattern with <version> tag to be replaced
+
+ Returns:
+ list: List of string values reporesenting endpoints that are currently supported
+
+ """
+ return [endpoint_pattern.replace("<version>", api_version) for api_version in API_VERSIONS_SUPPORTED]
+
+@app.route("/reset")
+def reset() -> str:
+ """Reset endpoint.
+
+ Reset all resources.
+
+ Returns:
+ str: Empty string, it has to returns anything
+
+ """
+ CloudRegion.reset()
+ Complex.reset()
+ Customer.reset()
+ Network.reset()
+ Vnf.reset()
+ return ""
+
+
+# Cloud region resource
+api.add_resource(CloudRegionList, *generate_urls_for_all_versions("/aai/<version>/cloud-infrastructure/cloud-regions"))
+api.add_resource(
+ CloudRegion,
+ *generate_urls_for_all_versions("/aai/<version>/cloud-infrastructure/cloud-regions/cloud-region/<cloud_owner>/<cloud_region_id>"),
+)
+api.add_resource(
+ CloudRegionRelationshipList,
+ *generate_urls_for_all_versions("/aai/<version>/cloud-infrastructure/cloud-regions/cloud-region/<cloud_owner>/<cloud_region_id>/relationship-list"),
+)
+api.add_resource(
+ CloudRegionRelationship,
+ *generate_urls_for_all_versions("/aai/<version>/cloud-infrastructure/cloud-regions/cloud-region/<cloud_owner>/<cloud_region_id>/relationship-list/relationship"),
+)
+api.add_resource(
+ TenantList,
+ *generate_urls_for_all_versions("/aai/<version>/cloud-infrastructure/cloud-regions/cloud-region/<cloud_owner>/<cloud_region_id>/tenants"),
+)
+api.add_resource(
+ Tenant,
+ *generate_urls_for_all_versions("/aai/<version>/cloud-infrastructure/cloud-regions/cloud-region/<cloud_owner>/<cloud_region_id>/tenants/tenant/<tenant_id>"),
+)
+# Complex resource
+api.add_resource(ComplexList, *generate_urls_for_all_versions("/aai/<version>/cloud-infrastructure/complexes"))
+api.add_resource(
+ Complex, *generate_urls_for_all_versions("/aai/<version>/cloud-infrastructure/complexes/complex/<physical_location_id>")
+)
+# Customer resource
+api.add_resource(CustomerList, *generate_urls_for_all_versions("/aai/<version>/business/customers"))
+api.add_resource(Customer, *generate_urls_for_all_versions("/aai/<version>/business/customers/customer/<global_customer_id>"))
+api.add_resource(
+ ServiceSubscriptionList,
+ *generate_urls_for_all_versions("/aai/<version>/business/customers/customer/<global_customer_id>/service-subscriptions"),
+)
+api.add_resource(
+ ServiceSubscription,
+ *generate_urls_for_all_versions("/aai/<version>/business/customers/customer/<global_customer_id>/service-subscriptions/service-subscription/<service_type>"),
+)
+api.add_resource(
+ ServiceSubscriptionRelationshipList,
+ *generate_urls_for_all_versions("/aai/<version>/business/customers/customer/<global_customer_id>/service-subscriptions/service-subscription/<service_type>/relationship-list"),
+)
+api.add_resource(
+ ServiceSubscriptionRelationship,
+ *generate_urls_for_all_versions("/aai/<version>/business/customers/customer/<global_customer_id>/service-subscriptions/service-subscription/<service_type>/relationship-list/relationship"),
+)
+api.add_resource(
+ ServiceSubscriptionInstance,
+ *generate_urls_for_all_versions("/aai/<version>/business/customers/customer/<global_customer_id>/service-subscriptions/service-subscription/<service_type>/service-instances/service-instance/<service_instance_id>"),
+)
+api.add_resource(
+ ServiceSubscriptionInstanceList,
+ *generate_urls_for_all_versions("/aai/<version>/business/customers/customer/<global_customer_id>/service-subscriptions/service-subscription/<service_type>/service-instances"),
+)
+api.add_resource(
+ ServiceSubscriptionInstanceRelationshipList,
+ *generate_urls_for_all_versions("/aai/<version>/business/customers/customer/<global_customer_id>/service-subscriptions/service-subscription/<service_type>/service-instances/service-instance/<service_instance_id>/relationship-list"),
+)
+# VNF resource
+api.add_resource(Vnf, *generate_urls_for_all_versions("/aai/<version>/network/generic-vnfs/generic-vnf/<vnf_instance_id>"))
+api.add_resource(
+ VfModule,
+ *generate_urls_for_all_versions("/aai/<version>/network/generic-vnfs/generic-vnf/<vnf_instance_id>/vf-modules/<vf_module_instance_id>"),
+)
+api.add_resource(
+ VfModuleList,
+ *generate_urls_for_all_versions("/aai/<version>/network/generic-vnfs/generic-vnf/<vnf_instance_id>/vf-modules"),
+)
+api.add_resource(
+ Network, *generate_urls_for_all_versions("/aai/<version>/network/l3-networks/l3-network/<network_instance_id>")
+)
+
+
+if __name__ == "__main__":
+ app.run(host="0.0.0.0", debug=True)
diff --git a/mock-aai/requirements.txt b/mock-aai/requirements.txt
new file mode 100644
index 0000000..04f7256
--- /dev/null
+++ b/mock-aai/requirements.txt
@@ -0,0 +1 @@
+Flask-RESTful==0.3.9 \ No newline at end of file
diff --git a/mock-aai/resources/__init__.py b/mock-aai/resources/__init__.py
new file mode 100644
index 0000000..bbc4e6a
--- /dev/null
+++ b/mock-aai/resources/__init__.py
@@ -0,0 +1,16 @@
+"""A&AI mock resources package."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
diff --git a/mock-aai/resources/cloud_region.py b/mock-aai/resources/cloud_region.py
new file mode 100644
index 0000000..aa5098d
--- /dev/null
+++ b/mock-aai/resources/cloud_region.py
@@ -0,0 +1,193 @@
+"""A&AI CloudRegion mock module."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from typing import Dict, List, Tuple
+
+from flask_restful import Resource, request
+
+CLOUD_REGIONS = {}
+
+
+class CloudRegion(Resource):
+ """Cloud region resource."""
+
+ def get(self, cloud_owner: str, cloud_region_id: str) -> Dict[str, str]:
+ """Get cloud region.
+
+ Get cloud region from CLOUD_REGIONS dictionary.
+
+ Args:
+ cloud_owner (str): cloud owner key value
+ cloud_region_id (str): cloud region id key value
+
+ Returns:
+ Dict[str, str]: Cloud region dictionary
+
+ """
+ return CLOUD_REGIONS[cloud_owner][cloud_region_id]
+
+ def put(self, cloud_owner: str, cloud_region_id: str) -> Tuple[str, int]:
+ """Cloud region resource put method.
+
+ Add cloud region data into CLOUD_REGIONS dictionary.
+
+ Args:
+ cloud_owner (str): Cloud owner key value
+ cloud_region_id (str): Cloud region id key value
+
+ Returns:
+ Tuple[str, int]: Response tuple. First element is a response body,
+ the second one is HTTP response code.
+ """
+ CLOUD_REGIONS.update({cloud_owner: {cloud_region_id: request.get_json()}})
+ return "", 201
+
+ @staticmethod
+ def reset() -> None:
+ """Reset Cloud region resource.
+
+ Clean CLOUD_REGIONS dictionary
+
+ """
+ global CLOUD_REGIONS
+ CLOUD_REGIONS = {}
+
+
+class CloudRegionList(Resource):
+ """List of cloud regions resource."""
+
+ def get(self):
+ """Get the list of cloud regions.
+
+ Return data from CLOUD_REGIONS dictionary.
+
+ Returns:
+ Dict[str, List]: Cloud regions dictionary
+
+ """
+ return {
+ "cloud-region": [
+ data
+ for cloud_owner, cloud_owner_dict in CLOUD_REGIONS.items()
+ for cloud_owner, data in cloud_owner_dict.items()
+ ]
+ }
+
+
+class CloudRegionRelationship(Resource):
+ """Cloud region relationship resource."""
+
+ def put(self, cloud_owner: str, cloud_region_id: str):
+ """Cloud region relationship resource put method.
+
+ Add cloud region relationship data into CLOUD_REGIONS dictionary.
+
+ Args:
+ cloud_owner (str): Cloud owner key value
+ cloud_region_id (str): Cloud region id key value
+
+ """
+ try:
+ CLOUD_REGIONS[cloud_owner][cloud_region_id]["relationships"].apped(request.get_json())
+ except KeyError:
+ CLOUD_REGIONS[cloud_owner][cloud_region_id]["relationships"] = [request.get_json()]
+
+
+class CloudRegionRelationshipList(Resource):
+ """List of cloud region relationships resource."""
+
+ def get(self, cloud_owner: str, cloud_region_id: str) -> Dict[str, List]:
+ """Get the list of cloud region relationships.
+
+ Return data from CLOUD_REGIONS dictionary.
+
+ Args:
+ cloud_owner (str): Cloud owner key value
+ cloud_region_id (str): Cloud region id key value
+
+ Returns:
+ Dict[str, List]: Cloud region relationships dictionary
+
+ """
+ try:
+ return {"relationship": CLOUD_REGIONS[cloud_owner][cloud_region_id]["relationships"]}
+ except KeyError:
+ return {"relationship": []}
+
+
+class Tenant(Resource):
+ """Cloud region tenant resource."""
+
+ def put(self, cloud_owner: str, cloud_region_id: str, tenant_id: str) -> None:
+ """Cloud region tenant resource put method.
+
+ Add cloud region tenant data into CLOUD_REGIONS dictionary.
+
+ Args:
+ cloud_owner (str): Cloud owner key value
+ cloud_region_id (str): Cloud region id key value
+
+ """
+ try:
+ CLOUD_REGIONS[cloud_owner][cloud_region_id]["tenants"].update(
+ {tenant_id: request.get_json()}
+ )
+ except KeyError:
+ CLOUD_REGIONS[cloud_owner][cloud_region_id]["tenants"] = {tenant_id: request.get_json()}
+
+ def get(self, cloud_owner: str, cloud_region_id: str, tenant_id: str) -> Dict[str, str]:
+ """Get cloud region tenant.
+
+ Get cloud region tenant from CLOUD_REGIONS dictionary.
+
+ Args:
+ cloud_owner (str): cloud owner key value
+ cloud_region_id (str): cloud region id key value
+
+ Returns:
+ Dict[str, str]: Cloud region tenant dictionary
+
+ """
+ try:
+ return CLOUD_REGIONS[cloud_owner][cloud_region_id]["tenants"][tenant_id]
+ except KeyError:
+ return "", 404
+
+
+class TenantList(Resource):
+ """List of tenants resource."""
+
+ def get(self, cloud_owner: str, cloud_region_id: str) -> Dict[str, List]:
+ """Get the list of cloud region tenants.
+
+ Return data from CLOUD_REGIONS dictionary.
+
+ Args:
+ cloud_owner (str): Cloud owner key value
+ cloud_region_id (str): Cloud region id key value
+
+ Returns:
+ Dict[str, List]: Cloud region tenants dictionary
+
+ """
+ return {
+ "tenant": [
+ data
+ for tenant_id, data in CLOUD_REGIONS[cloud_owner][cloud_region_id]
+ .get("tenants", {})
+ .items()
+ ]
+ }
diff --git a/mock-aai/resources/complex.py b/mock-aai/resources/complex.py
new file mode 100644
index 0000000..9185221
--- /dev/null
+++ b/mock-aai/resources/complex.py
@@ -0,0 +1,65 @@
+"""A&AI Complex mock module."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from typing import Dict, List
+
+from flask_restful import reqparse, Resource, request
+
+COMPLEXES = {}
+
+parser = reqparse.RequestParser()
+
+
+class Complex(Resource):
+ """Complex resource class."""
+
+ def put(self, physical_location_id: str):
+ """Complex resource put method.
+
+ Add complex data sent in JSON to COMPLEXES dictionary.
+
+ Args:
+ physical_location_id (str): Complex physical location id
+
+ """
+ COMPLEXES.update({physical_location_id: request.get_json()})
+
+ @staticmethod
+ def reset():
+ """Reset Complex resource.
+
+ Clean COMPLEXES dictionary
+
+ """
+ global COMPLEXES
+ COMPLEXES = {}
+
+
+class ComplexList(Resource):
+ """List of complexes resource."""
+
+ def get(self) -> Dict[str, List]:
+ """Get the list of complexes.
+
+ Return data from COMPLEXES dictionary.
+
+ Returns:
+ Dict[str, List]: Complexes dictionary
+
+ """
+ return {
+ "complex": [complex_data for physical_location_id, complex_data in COMPLEXES.items()]
+ }
diff --git a/mock-aai/resources/customer.py b/mock-aai/resources/customer.py
new file mode 100644
index 0000000..d53eb0d
--- /dev/null
+++ b/mock-aai/resources/customer.py
@@ -0,0 +1,325 @@
+"""A&AI Customer mock module."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from typing import Dict, List
+from uuid import uuid4
+
+from flask_restful import reqparse, Resource, request
+
+
+CUSTOMERS = {}
+
+
+def random_resource_version() -> str:
+ """Generate random resource version string value.
+
+ Returns:
+ str: UUID value
+
+ """
+ return str(uuid4())
+
+
+class Customer(Resource):
+ """Customer resource."""
+
+ @staticmethod
+ def reset():
+ """Reset Cloud region resource.
+
+ Clean CUSTOMERS dictionary
+
+ """
+ global CUSTOMERS
+ CUSTOMERS = {}
+
+ def get(self, global_customer_id: str):
+ """Get customer.
+
+ Get customer from CUSTOMERS dictionary.
+
+ Args:
+ global_customer_id (str): global customer id key value
+
+ Returns:
+ Dict[str, str]: Customer dictionary
+
+ """
+ return CUSTOMERS[global_customer_id]
+
+ def put(self, global_customer_id: str):
+ """Resource put method.
+
+ Add customer data into CUSTOMERS dictionary.
+
+ Args:
+ global_customer_id (str): global customer id key value
+
+ Returns:
+ Tuple[str, int]: Response tuple. First element is a response body,
+ the second one is HTTP response code.
+
+ """
+ CUSTOMERS[global_customer_id] = request.get_json()
+ CUSTOMERS[global_customer_id]["resource-version"] = random_resource_version()
+ return "", 201
+
+
+class CustomerList(Resource):
+ """List of customers resource."""
+
+ def get(self) -> Dict[str, List]:
+ """Get the list of customers.
+
+ Return data from CUSTOMERS dictionary.
+
+ Returns:
+ Dict[str, List]: Customer dictionary
+
+ """
+ return {"customer": [data for global_customer_id, data in CUSTOMERS.items()]}
+
+
+class ServiceSubscription(Resource):
+ """Service subscription resource."""
+
+ def put(self, global_customer_id: str, service_type: str) -> None:
+ """Service subscription resource put method.
+
+ Add service subscription data into CUSTOMERS dictionary.
+
+ Args:
+ global_customer_id (str): Global customer id key value
+ service_type (str): Service type key value
+
+ """
+ try:
+ CUSTOMERS[global_customer_id]["service_subscriptions"][
+ service_type
+ ] = {"service-type": service_type}
+ except KeyError:
+ CUSTOMERS[global_customer_id]["service_subscriptions"] = {
+ service_type: {"service-type": service_type}
+ }
+ CUSTOMERS[global_customer_id]["service_subscriptions"][service_type].update(
+ {"service-type": service_type}
+ )
+
+
+class ServiceSubscriptionList(Resource):
+ """List of service subscriptions resource."""
+
+ def get(self, global_customer_id: str) -> Dict[str, List]:
+ """Get the list of service subscriptions.
+
+ Return data from CUSTOMERS dictionary.
+
+ Args:
+ global_customer_id (str): Global customer id key value
+
+ Returns:
+ Dict[str, List]: Service subscriptions dictionary
+
+ """
+ service_type: str = request.args.get("service-type")
+ if not service_type:
+ return {
+ "service-subscription": [
+ data
+ for service_type, data in CUSTOMERS[global_customer_id][
+ "service_subscriptions"
+ ].items()
+ ]
+ }
+ try:
+ return {
+ "service-subscription": [
+ CUSTOMERS[global_customer_id]["service_subscriptions"][service_type]
+ ]
+ }
+ except KeyError:
+ return "", 404
+
+
+class ServiceSubscriptionRelationship(Resource):
+ """Service subscription relationship resource."""
+
+ def put(self, global_customer_id: str, service_type: str) -> None:
+ """Service subscription relationship resource put method.
+
+ Add service subscription relationship data into CUSTOMERS dictionary.
+
+ Args:
+ global_customer_id (str): Global customer id key value
+ service_type (str): Service type key value
+
+ """
+ try:
+ CUSTOMERS[global_customer_id]["service_subscriptions"][service_type][
+ "relationships"
+ ].append(request.get_json())
+ except KeyError:
+ CUSTOMERS[global_customer_id]["service_subscriptions"][service_type][
+ "relationships"
+ ] = [request.get_json()]
+
+
+class ServiceSubscriptionRelationshipList(Resource):
+ """Service subscription relationships list resource."""
+
+ def get(self, global_customer_id: str, service_type: str) -> Dict[str, List]:
+ """Get the list of service subscription relationships.
+
+ Return data from CUSTOMERS dictionary.
+
+ Args:
+ global_customer_id (str): Global customer id key value
+ service_type (str): Service type key value
+
+ Returns:
+ Dict[str, List]: Service subscription relationships dictionary
+
+ """
+ return {
+ "relationship": CUSTOMERS[global_customer_id]["service_subscriptions"][
+ service_type
+ ].get("relationships", [])
+ }
+
+
+class ServiceSubscriptionInstance(Resource):
+ """Service subscription instance resource."""
+
+ def delete(self, global_customer_id: str, service_type: str, service_instance_id: str) -> None:
+ """Delete service subscription instance.
+
+ Removes data from CUSTOMERS dictionary.
+
+ Args:
+ global_customer_id (str): Global customer id key value
+ service_type (str): Service type key value
+ service_instance_id (str): Service instance id key value
+
+ """
+ del CUSTOMERS[global_customer_id]["service_subscriptions"][service_type][
+ "service_instances"
+ ][service_instance_id]
+
+
+class ServiceSubscriptionInstanceList(Resource):
+ """Service subscription instances list resource."""
+
+ def get(self, global_customer_id: str, service_type: str) -> Dict[str, List]:
+ """Get service subscription's service instances.
+
+ Returns data from CUSTOMERS dictionary
+
+ Args:
+ global_customer_id (str): Global customer id key value
+ service_type (str): Service type key value
+
+ Returns:
+ Dict[str, List]: Service instances dictionary
+ """
+ return {
+ "service-instance": [
+ data
+ for instance_id, data in CUSTOMERS[global_customer_id]["service_subscriptions"][
+ service_type
+ ]
+ .get("service_instances", dict())
+ .items()
+ ]
+ }
+
+ def post(self, global_customer_id: str, service_type: str) -> None:
+ """Add service instance to service subscription.
+
+ Add service instance data dictionary to service subscription's
+ service instances dictionary.
+
+ Args:
+ global_customer_id (str): Global customer id key value
+ service_type (str): Service type key value
+
+ """
+ request_data = request.get_json()
+ instance_id = request_data["service-instance-id"]
+ try:
+ CUSTOMERS[global_customer_id]["service_subscriptions"][service_type][
+ "service_instances"
+ ][instance_id] = request_data
+ except KeyError:
+ CUSTOMERS[global_customer_id]["service_subscriptions"][service_type][
+ "service_instances"
+ ] = {instance_id: request_data}
+
+
+class ServiceSubscriptionInstanceRelationshipList(Resource):
+ """Service subscription instance relationships list resource."""
+
+ def post(self, global_customer_id: str, service_type: str, service_instance_id) -> None:
+ """Add relationship into service instance relationships list.
+
+ Args:
+ global_customer_id (str): Global customer id key value
+ service_type (str): Service type key value
+ service_instance_id (str): Service instance id key value
+
+ """
+ try:
+ CUSTOMERS[global_customer_id]["service_subscriptions"][service_type][
+ "service_instances"
+ ][service_instance_id]["relationships"].append(request.get_json())
+ except KeyError:
+ CUSTOMERS[global_customer_id]["service_subscriptions"][service_type][
+ "service_instances"
+ ][service_instance_id]["relationships"] = [request.get_json()]
+
+ def get(
+ self, global_customer_id: str, service_type: str, service_instance_id: str
+ ) -> Dict[str, List]:
+ """Get the service instance relationships list.
+
+ Args:
+ global_customer_id (str): Global customer id key value
+ service_type (str): Service type key value
+ service_instance_id (str): Service instance id key value
+
+ Returns:
+ Dict[str, List]: Service instance relationships dictionary
+
+ """
+ return {
+ "relationship": CUSTOMERS[global_customer_id]["service_subscriptions"][service_type][
+ "service_instances"
+ ][service_instance_id].get("relationships", [])
+ }
+
+ def delete(self, global_customer_id: str, service_type: str, service_instance_id: str) -> None:
+ """Delete service subscription instance relationships.
+
+ Make relationships list clea.
+
+ Args:
+ global_customer_id (str): Global customer id key value
+ service_type (str): Service type key value
+ service_instance_id (str): Service instance id key value
+
+ """
+ CUSTOMERS[global_customer_id]["service_subscriptions"][service_type]["service_instances"][
+ service_instance_id
+ ]["relationships"] = []
diff --git a/mock-aai/resources/network.py b/mock-aai/resources/network.py
new file mode 100644
index 0000000..3fddd41
--- /dev/null
+++ b/mock-aai/resources/network.py
@@ -0,0 +1,61 @@
+"""Vnf resources module."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from typing import Dict, List
+from uuid import uuid4
+
+from flask_restful import Resource, request
+
+
+NETWORKS = {}
+
+
+class Network(Resource):
+ """Network resource."""
+
+ @staticmethod
+ def reset():
+ """Reset resource for tests.
+
+ Create new, empty NETWORKS dictionary
+
+ """
+ global NETWORKS
+ NETWORKS = {}
+
+ def get(self, network_instance_id: str) -> Dict[str, List]:
+ """Get network instance data.
+
+ Get data from NETWORKS dictionary
+
+ Args:
+ network_instance_id (str): Network instance id key value
+
+ Returns:
+ Dict[str, List]: Network instance data dictionary
+
+ """
+ try:
+ return NETWORKS[network_instance_id]
+ except KeyError:
+ NETWORKS[network_instance_id] = {
+ "network-id": network_instance_id,
+ "is-bound-to-vpn": False,
+ "is-provider-network": False,
+ "is-shared-network": False,
+ "is-external-network": False,
+ }
+ return NETWORKS[network_instance_id]
diff --git a/mock-aai/resources/vnf.py b/mock-aai/resources/vnf.py
new file mode 100644
index 0000000..3a49f01
--- /dev/null
+++ b/mock-aai/resources/vnf.py
@@ -0,0 +1,108 @@
+"""Vnf resources module."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from typing import Dict, List
+from uuid import uuid4
+
+from flask_restful import Resource, request
+
+
+VNFS = {}
+
+
+class Vnf(Resource):
+ """Vnf resource."""
+
+ @staticmethod
+ def reset():
+ """Reset resource for tests.
+
+ Create new, empty VNFS dictionary
+
+ """
+ global VNFS
+ VNFS = {}
+
+ def get(self, vnf_instance_id: str) -> Dict[str, List]:
+ """Get vnf instance data.
+
+ Get data from VNFS dictionary
+
+ Args:
+ vnf_instance_id (str): Vnf instance id key value
+
+ Returns:
+ Dict[str, List]: Vnf instance data dictionary
+
+ """
+ try:
+ return VNFS[vnf_instance_id]
+ except KeyError:
+ VNFS[vnf_instance_id] = {"vnf-id": vnf_instance_id, "model-version-id": str(uuid4())}
+ return VNFS[vnf_instance_id]
+
+
+class VfModule(Resource):
+ """Vf module resource."""
+
+ def delete(self, vnf_instance_id: str, vf_module_instance_id: str) -> None:
+ """Delete vf module.
+
+ Removes vf module data from VNFS dictionary.
+
+ Args:
+ vnf_instance_id (str): Vnf instance id key value
+ vf_module_instance_id (str): Vf module instance id key value
+
+ """
+ del VNFS[vnf_instance_id]["vf_modules"][vf_module_instance_id]
+
+
+class VfModuleList(Resource):
+ """Vf module list resource."""
+
+ def post(self, vnf_instance_id: str) -> None:
+ """Create vf module.
+
+ Add vf module data into VNFS dictionary.
+
+ Args:
+ vnf_instance_id (str): Vnf instance id key value
+
+ """
+ vf_module_data = request.get_json()
+ vf_module_dict = {vf_module_data["vf-module-id"]: vf_module_data}
+ try:
+ VNFS[vnf_instance_id]["vf_modules"].update(vf_module_dict)
+ except KeyError:
+ VNFS[vnf_instance_id]["vf_modules"] = vf_module_dict
+
+ def get(self, vnf_instance_id: str) -> Dict[str, List]:
+ """Get Vnf instance Vf modules list.
+
+ Get data from VNFS dictionary
+
+ Args:
+ vnf_instance_id (str): Vnf instance id key value
+
+ Returns:
+ Dict[str, List]: Vnf instance vf modules dictionary
+ """
+ return {
+ "vf-module": [
+ data for vf_module_id, data in VNFS[vnf_instance_id].get("vf_modules", {}).items()
+ ]
+ }
diff --git a/mock-cds/Dockerfile b/mock-cds/Dockerfile
new file mode 100644
index 0000000..4a396bb
--- /dev/null
+++ b/mock-cds/Dockerfile
@@ -0,0 +1,17 @@
+FROM python:3.7.8-alpine
+
+COPY . /app
+WORKDIR /app
+
+# GCC for Alpine Linux in Docker
+RUN apk add build-base
+
+
+# Dependencies
+RUN pip install pipenv && \
+ pipenv requirements > requirements.txt && \
+ pip install -r requirements.txt
+
+
+ENTRYPOINT ["python"]
+CMD ["app/app.py"] \ No newline at end of file
diff --git a/mock-cds/Pipfile b/mock-cds/Pipfile
new file mode 100644
index 0000000..857def1
--- /dev/null
+++ b/mock-cds/Pipfile
@@ -0,0 +1,12 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+
+[packages]
+aiohttp = "*"
+
+[requires]
+python_version = "3.7"
diff --git a/mock-cds/Pipfile.lock b/mock-cds/Pipfile.lock
new file mode 100644
index 0000000..9ac068c
--- /dev/null
+++ b/mock-cds/Pipfile.lock
@@ -0,0 +1,125 @@
+{
+ "_meta": {
+ "hash": {
+ "sha256": "2c5c75ab0fc628a232239706591e922fec111ed0bb34cc8c62d3352e2d21a02d"
+ },
+ "pipfile-spec": 6,
+ "requires": {
+ "python_version": "3.7"
+ },
+ "sources": [
+ {
+ "name": "pypi",
+ "url": "https://pypi.org/simple",
+ "verify_ssl": true
+ }
+ ]
+ },
+ "default": {
+ "aiohttp": {
+ "hashes": [
+ "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e",
+ "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326",
+ "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a",
+ "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654",
+ "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a",
+ "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4",
+ "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17",
+ "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec",
+ "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd",
+ "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48",
+ "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59",
+ "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965"
+ ],
+ "index": "pypi",
+ "version": "==3.6.2"
+ },
+ "async-timeout": {
+ "hashes": [
+ "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
+ "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"
+ ],
+ "markers": "python_full_version >= '3.5.3'",
+ "version": "==3.0.1"
+ },
+ "attrs": {
+ "hashes": [
+ "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c",
+ "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==19.3.0"
+ },
+ "chardet": {
+ "hashes": [
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
+ ],
+ "version": "==3.0.4"
+ },
+ "idna": {
+ "hashes": [
+ "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
+ "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==2.10"
+ },
+ "multidict": {
+ "hashes": [
+ "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a",
+ "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000",
+ "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2",
+ "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507",
+ "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5",
+ "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7",
+ "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d",
+ "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463",
+ "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19",
+ "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3",
+ "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b",
+ "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c",
+ "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87",
+ "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7",
+ "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430",
+ "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255",
+ "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==4.7.6"
+ },
+ "typing-extensions": {
+ "hashes": [
+ "sha256:6e95524d8a547a91e08f404ae485bbb71962de46967e1b71a0cb89af24e761c5",
+ "sha256:79ee589a3caca649a9bfd2a8de4709837400dfa00b6cc81962a1e6a1815969ae",
+ "sha256:f8d2bd89d25bc39dabe7d23df520442fa1d8969b82544370e03d88b5a591c392"
+ ],
+ "markers": "python_version < '3.8'",
+ "version": "==3.7.4.2"
+ },
+ "yarl": {
+ "hashes": [
+ "sha256:040b237f58ff7d800e6e0fd89c8439b841f777dd99b4a9cca04d6935564b9409",
+ "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593",
+ "sha256:3a584b28086bc93c888a6c2aa5c92ed1ae20932f078c46509a66dce9ea5533f2",
+ "sha256:4439be27e4eee76c7632c2427ca5e73703151b22cae23e64adb243a9c2f565d8",
+ "sha256:48e918b05850fffb070a496d2b5f97fc31d15d94ca33d3d08a4f86e26d4e7c5d",
+ "sha256:9102b59e8337f9874638fcfc9ac3734a0cfadb100e47d55c20d0dc6087fb4692",
+ "sha256:9b930776c0ae0c691776f4d2891ebc5362af86f152dd0da463a6614074cb1b02",
+ "sha256:b3b9ad80f8b68519cc3372a6ca85ae02cc5a8807723ac366b53c0f089db19e4a",
+ "sha256:bc2f976c0e918659f723401c4f834deb8a8e7798a71be4382e024bcc3f7e23a8",
+ "sha256:c22c75b5f394f3d47105045ea551e08a3e804dc7e01b37800ca35b58f856c3d6",
+ "sha256:c52ce2883dc193824989a9b97a76ca86ecd1fa7955b14f87bf367a61b6232511",
+ "sha256:ce584af5de8830d8701b8979b18fcf450cef9a382b1a3c8ef189bedc408faf1e",
+ "sha256:da456eeec17fa8aa4594d9a9f27c0b1060b6a75f2419fe0c00609587b2695f4a",
+ "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb",
+ "sha256:df89642981b94e7db5596818499c4b2219028f2a528c9c37cc1de45bf2fd3a3f",
+ "sha256:f18d68f2be6bf0e89f1521af2b1bb46e66ab0018faafa81d70f358153170a317",
+ "sha256:f379b7f83f23fe12823085cd6b906edc49df969eb99757f58ff382349a3303c6"
+ ],
+ "markers": "python_version >= '3.5'",
+ "version": "==1.5.1"
+ }
+ },
+ "develop": {}
+}
diff --git a/mock-cds/README.md b/mock-cds/README.md
new file mode 100644
index 0000000..d74d171
--- /dev/null
+++ b/mock-cds/README.md
@@ -0,0 +1,2 @@
+# mock-cds
+
diff --git a/mock-cds/app/app.py b/mock-cds/app/app.py
new file mode 100644
index 0000000..a15dbea
--- /dev/null
+++ b/mock-cds/app/app.py
@@ -0,0 +1,22 @@
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from aiohttp import web
+from routes import setup_routes
+
+app = web.Application()
+
+setup_routes(app)
+web.run_app(app) \ No newline at end of file
diff --git a/mock-cds/app/routes.py b/mock-cds/app/routes.py
new file mode 100644
index 0000000..10da668
--- /dev/null
+++ b/mock-cds/app/routes.py
@@ -0,0 +1,22 @@
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from views import blueprint_enrich, blueprint_publish, dictionary, dictionary_get
+
+def setup_routes(app):
+ app.router.add_post('/api/v1/blueprint-model/enrich', blueprint_enrich)
+ app.router.add_post('/api/v1/blueprint-model/publish', blueprint_publish)
+ app.router.add_post('/api/v1/dictionary', dictionary)
+ app.router.add_get('/api/v1/dictionary/{name}', dictionary_get) \ No newline at end of file
diff --git a/mock-cds/app/views.py b/mock-cds/app/views.py
new file mode 100644
index 0000000..b6d9f37
--- /dev/null
+++ b/mock-cds/app/views.py
@@ -0,0 +1,51 @@
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+import json
+
+from aiohttp import web
+
+BYTES = b'Response in bytes'
+DICTIONARY = {
+ "message": "Response in JSON",
+ "success": True
+ }
+DICTIONARIES = {}
+
+async def blueprint_enrich(request):
+ """ Blueprint enrichment """
+ return web.Response(body=BYTES, status=200)
+
+async def blueprint_publish(request):
+ """ Blueprint publishing """
+ return web.Response(body=BYTES, status=200)
+
+async def dictionary(request):
+ """ Data dictionary """
+ try:
+ body = await request.json()
+ DICTIONARIES[body["name"]] = body
+ except ValueError:
+ print("No JSON sent! Leave it because we used that endpoint during "
+ "the availability and we won't break the integration tests")
+ return web.json_response(data=DICTIONARY, status=200)
+
+async def dictionary_get(request):
+ """ Data dictionary get """
+ name = request.match_info["name"]
+ try:
+ return web.json_response(data=DICTIONARIES[name], status=200)
+ except KeyError:
+ return web.Response(status=404) \ No newline at end of file
diff --git a/mock-cds/cleanup-dev.sh b/mock-cds/cleanup-dev.sh
new file mode 100644
index 0000000..fb4a1bc
--- /dev/null
+++ b/mock-cds/cleanup-dev.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+export APP_NAME=mock-cds-app
+
+docker rm $(docker stop $(docker ps -a -q --filter ancestor="${APP_NAME}" --format="{{.ID}}"))
+docker rmi ${APP_NAME} \ No newline at end of file
diff --git a/mock-cds/run-dev.sh b/mock-cds/run-dev.sh
new file mode 100644
index 0000000..392bfaa
--- /dev/null
+++ b/mock-cds/run-dev.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+export APP_NAME=mock-cds-app
+export DOCKER_PORT=8080
+export APP_PORT=8080
+
+docker build -t $APP_NAME .
+docker run -d -p $DOCKER_PORT:$APP_PORT $APP_NAME \ No newline at end of file
diff --git a/mock-clamp/.dockerignore b/mock-clamp/.dockerignore
new file mode 100644
index 0000000..393fc3b
--- /dev/null
+++ b/mock-clamp/.dockerignore
@@ -0,0 +1,13 @@
+# Binaries for programs and plugins
+mock-clamp
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out \ No newline at end of file
diff --git a/mock-clamp/Dockerfile b/mock-clamp/Dockerfile
new file mode 100644
index 0000000..12a3a07
--- /dev/null
+++ b/mock-clamp/Dockerfile
@@ -0,0 +1,32 @@
+FROM golang:1.17-alpine AS builder
+
+# Add all the source code (except what's ignored
+# under `.dockerignore`) to the build context.
+ADD ./ /go/src/
+
+WORKDIR /go/src
+
+RUN apk add --no-cache git
+RUN go mod init onap.com/mock-clamp
+RUN go get github.com/satori/go.uuid
+RUN go get github.com/labstack/echo
+RUN go get github.com/dgrijalva/jwt-go
+
+RUN set -ex && \
+ CGO_ENABLED=0 GOOS=linux go build \
+ -tags netgo \
+ -installsuffix cgo \
+ -v -a \
+ -ldflags '-extldflags "-static"' \
+ -o mock-clamp .
+
+RUN ls -la
+
+FROM scratch
+
+# Retrieve the binary from the previous stage
+COPY --from=builder /go/src/mock-clamp /app/mock-clamp
+WORKDIR /app
+
+# Set the binary as the entrypoint of the container
+ENTRYPOINT [ "./mock-clamp" ]
diff --git a/mock-clamp/README.md b/mock-clamp/README.md
new file mode 100644
index 0000000..53540d1
--- /dev/null
+++ b/mock-clamp/README.md
@@ -0,0 +1 @@
+# mock-clamp \ No newline at end of file
diff --git a/mock-clamp/clamp_handlers.go b/mock-clamp/clamp_handlers.go
new file mode 100644
index 0000000..edccf22
--- /dev/null
+++ b/mock-clamp/clamp_handlers.go
@@ -0,0 +1,130 @@
+// Copyright 2023 Deutsche Telekom AG, Orange
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "net/http"
+
+ "github.com/labstack/echo"
+ "github.com/satori/go.uuid"
+)
+
+//describes loop template in Clamp database
+type LoopTemplate struct {
+ Name string `json:"name"`
+ DcaeBlueprintId string `json:"dcaeBlueprintId"`
+ ModelService struct {
+ ServiceDetails struct {
+ Name string `json:"name"`
+ } `json:"serviceDetails"`
+ } `json:"modelService"`
+}
+
+//describes policy in Clamp database
+type Policy struct {
+ PolicyModelType string `json:"policyModelType"`
+ Version string `json:"version"`
+ PolicyAcronym string `json:"policyAcronym"`
+ CreatedDate string `json:"createdDate"`
+ UpdatedDate string `json:"updatedDate"`
+ UpdatedBy string `json:"updatedBy"`
+ CreatedBy string `json:"createdBy"`
+}
+
+//ClampError is the way to return Error in CLAMP
+type ClampError struct {
+ Message string `json:"message"`
+ Error string `json:"error"`
+ Status string `json:"status"`
+}
+
+var templateList []LoopTemplate
+
+//must modify this function to generate template with service model name
+func generateInitialTemplateList() {
+ templateList = nil
+ u1 := uuid.NewV4().String()
+ loop1 := new(LoopTemplate)
+ loop1.Name = "template_service01"
+ loop1.DcaeBlueprintId = u1
+ loop1.ModelService.ServiceDetails.Name = "service01"
+ templateList = append(templateList, *loop1)
+ u2 := uuid.NewV4().String()
+ loop2 := new(LoopTemplate)
+ loop2.Name = "template_service02"
+ loop2.DcaeBlueprintId = u2
+ loop2.ModelService.ServiceDetails.Name = "service02"
+ templateList = append(templateList, *loop2)
+}
+
+var policyList []Policy
+
+func generateInitialPolicyList() {
+ policyList = nil
+ policyList = append(policyList, Policy{
+ PolicyModelType: "onap.policies.controlloop.MinMax",
+ Version: "1.0.0",
+ PolicyAcronym: "MinMax",
+ CreatedDate: "2020-04-30T09:03:30.362897Z",
+ UpdatedDate: "2020-04-30T09:03:30.362897Z",
+ UpdatedBy: "Not found",
+ CreatedBy: "Not found",
+ })
+ policyList = append(policyList, Policy{
+ PolicyModelType: "onap.policies.controlloop.Guard",
+ Version: "1.0.0",
+ PolicyAcronym: "Guard",
+ CreatedDate: "2020-04-30T09:03:30.362897Z",
+ UpdatedDate: "2020-04-30T09:03:30.362897Z",
+ UpdatedBy: "Not found",
+ CreatedBy: "Not found",
+ })
+ policyList = append(policyList, Policy{
+ PolicyModelType: "onap.policies.controlloop.guard.common.FrequencyLimiter",
+ Version: "1.0.0",
+ PolicyAcronym: "FrequencyLimiter",
+ CreatedDate: "2020-04-30T09:03:30.362897Z",
+ UpdatedDate: "2020-04-30T09:03:30.362897Z",
+ UpdatedBy: "Not found",
+ CreatedBy: "Not found",
+ })
+}
+
+func getTemplates(c echo.Context) error {
+ var templates []LoopTemplate
+ for _, t := range templateList {
+ //service must be distributed from sdc
+ if t.DcaeBlueprintId != "" {
+ templates = append(templates, t)
+ }
+ }
+ if len(templates) != 0 {
+ return c.JSON(http.StatusOK, templates)
+ }
+ return c.JSON(http.StatusNotFound, ClampError{
+ Message: "No Templates found",
+ Error: "Not Found",
+ Status: "404"})
+}
+
+func getPolicies(c echo.Context) error {
+ if len(policyList) != 0 {
+ return c.JSON(http.StatusOK, policyList)
+ }
+ return c.JSON(http.StatusNotFound, ClampError{
+ Message: "No Policies found",
+ Error: "Not Found",
+ Status: "404"})
+}
diff --git a/mock-clamp/generic_handlers.go b/mock-clamp/generic_handlers.go
new file mode 100644
index 0000000..a636ea1
--- /dev/null
+++ b/mock-clamp/generic_handlers.go
@@ -0,0 +1,32 @@
+// Copyright 2023 Deutsche Telekom AG, Orange
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "net/http"
+
+ "github.com/labstack/echo"
+)
+
+func index(c echo.Context) error {
+ return c.String(http.StatusOK, "Hello, World!")
+}
+
+func reset(c echo.Context) error {
+ generateInitialTemplateList()
+ generateInitialPolicyList()
+ generateInitialLoopInstances()
+ return c.String(http.StatusCreated, "reset done!")
+}
diff --git a/mock-clamp/loop_handlers.go b/mock-clamp/loop_handlers.go
new file mode 100644
index 0000000..ff8a552
--- /dev/null
+++ b/mock-clamp/loop_handlers.go
@@ -0,0 +1,404 @@
+// Copyright 2023 Deutsche Telekom AG, Orange
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "net/http"
+ "time"
+
+ "github.com/labstack/echo"
+ uuid "github.com/satori/go.uuid"
+)
+
+//describes the loop state in term of policy and DCAE
+type State struct {
+ ComponentState struct {
+ StateName string `json:"stateName"`
+ } `json:"componentState"`
+}
+
+//describes entity id in CLAMP got from SDC
+type Resource struct {
+ ResourceID struct {
+ VfModuleModelName string `json:"vfModuleModelName"`
+ VfModuleModelInvariantUUID string `json:"vfModuleModelInvariantUUID"`
+ VfModuleModelUUID string `json:"vfModuleModelUUID"`
+ VfModuleModelVersion string `json:"vfModuleModelVersion"`
+ VfModuleModelCustomizationUUID string `json:"vfModuleModelCustomizationUUID"`
+ } `json:"resourceID"`
+}
+
+//frequency limiter configuration
+type Frequency_payload struct {
+ ID string `json:"id"`
+ Actor string `json:"actor"`
+ Operation string `json:"operation"`
+ Limit int `json:"limit"`
+ TimeWindow int `json:"timeWindow"`
+ TimeUnits string `json:"timeUnits"`
+}
+
+/*
+//describes operational policy configuration in CLAMP
+type OperationalPolicy struct {
+ Name string `json:"name"`
+ PolicyModel Policy `json:"policyModel"`
+ ConfigurationsJson struct{ Frequency_payload } `json:"configurationsJson"` //depends on operational policy model
+}
+*/
+//describes TCA POLICY in CLAMP
+type Tca_policy struct {
+ Domain string `json:"Domain"`
+ MetricsPerEventName []struct {
+ PolicyScope string `json:"policyScope"`
+ Thresholds []struct {
+ Version string `json:"version"`
+ Severity string `json:"severity"`
+ ThresholdValue int `json:"thresholdValue"`
+ ClosedLoopEventStatus string `json:"closedLoopEventStatus"`
+ ClosedLoopControlName string `json:"closedLoopControlName"`
+ Direction string `json:"direction"`
+ FieldPath string `json:"fieldPath"`
+ } `json:"thresholds"`
+ EventName string `json:"eventName"`
+ PolicyVersion string `json:"policyVersion"`
+ ControlLoopSchemaType string `json:"controlLoopSchemaType"`
+ PolicyName string `json:"policyName"`
+ } `json:"metricsPerEventName"`
+}
+
+//describes TCA POLICY payload in CLAMP
+type Tca_policy_struct struct {
+ TcaPolicy Tca_policy `json:"tca.policy"`
+}
+
+//describes microservice policy configuration in CLAMP
+type MicroServicePolicy struct {
+ Name string `json:"name"`
+ ConfigurationsJson Tca_policy_struct `json:"configurationsJson"`
+ PdpGroup string `json:"pdpGroup"`
+ PdpSubgroup string `json:"pdpSubgroup"`
+}
+
+//LoopDetails describes loop innstance in CLAMP
+type LoopDetails struct {
+ Name string `json:"name"`
+ Template LoopTemplate `json:"loopTemplate"`
+ GlobalPropertiesJSON struct {
+ DcaeDeployParameters struct {
+ UniqueBlueprintParameters struct {
+ PolicyID string `json:"policy_id"`
+ } `json:"uniqueBlueprintParameters"`
+ } `json:"dcaeDeployParameters"`
+ } `json:"globalPropertiesJson"`
+ LoopElementModelsUsed []string `json:"loopElementModelsUsed"` //microservices from sdc
+ Components struct {
+ POLICY State `json:"POLICY"`
+ DCAE State `json:"DCAE"`
+ } `json:"components"`
+ ModelService struct {
+ ResourceDetails struct {
+ VFModule Resource `json:"VFModule"`
+ } `json:"resourceDetails"`
+ } `json:"modelService"`
+ OperationalPolicies []OperationalPolicy_payload `json:"operationalPolicies"`
+ MicroServicePolicies []MicroServicePolicy `json:"microServicePolicies"`
+}
+
+var loopInstanceList []LoopDetails
+
+func generateInitialLoopInstances() {
+ loopInstanceList = nil
+ loop1 := new(LoopDetails)
+ loop1.Template = templateList[0]
+ loop1.Name = "intance_template01"
+ loopInstanceList = append(loopInstanceList, *loop1)
+ loop2 := new(LoopDetails)
+ loop2.Name = "intance_template02"
+ loop2.Template = templateList[1]
+ loopInstanceList = append(loopInstanceList, *loop2)
+}
+
+func updateLoopDetails(c echo.Context) error {
+ loopID := c.Param("loopID")
+ for _, loop := range loopInstanceList {
+ if loop.Name == loopID {
+ return c.JSON(http.StatusOK, loop)
+ }
+ }
+ return c.JSON(http.StatusNotFound, ClampError{
+ Message: "No ClosedLoop found",
+ Error: "Not Found",
+ Status: "404"})
+}
+
+func createLoopInstance(c echo.Context) error {
+ loopID := c.Param("loopID")
+ templateName := c.QueryParam("templateName")
+ loop := new(LoopDetails)
+
+ //must add the constraint of limit number of instances for a template
+ for _, l := range loopInstanceList {
+ if l.Name == loopID &&
+ l.Template.Name == templateName {
+ //in reality it's overwritten
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "loop of same Name and for same template exists",
+ Error: "Exists",
+ Status: "500"})
+ }
+ }
+ loop.Name = loopID
+ loop.Template.Name = templateName
+ //For drools configuration
+ resource := new(Resource)
+ resource.ResourceID.VfModuleModelUUID = uuid.NewV4().String()
+ resource.ResourceID.VfModuleModelName = uuid.NewV4().String()
+ resource.ResourceID.VfModuleModelInvariantUUID = uuid.NewV4().String()
+ resource.ResourceID.VfModuleModelVersion = uuid.NewV4().String()
+ resource.ResourceID.VfModuleModelCustomizationUUID = uuid.NewV4().String()
+ loop.ModelService.ResourceDetails.VFModule = *resource
+ //must generate as much microservices as tca blueprints count
+ loop.LoopElementModelsUsed = append(loop.LoopElementModelsUsed, "microservice01")
+ nb_microservices := len(loop.LoopElementModelsUsed)
+ for i := 0; i < nb_microservices; i++ {
+ loop.MicroServicePolicies = append(loop.MicroServicePolicies, MicroServicePolicy{
+ Name: "Microservice" + uuid.NewV4().String(),
+ })
+ }
+ loop.GlobalPropertiesJSON.DcaeDeployParameters.UniqueBlueprintParameters.PolicyID = "Microservice" + uuid.NewV4().String()
+ state := new(State)
+ state.ComponentState.StateName = "NOT_SENT"
+ loop.Components.POLICY = *state
+ state.ComponentState.StateName = "BLUEPRINT_DEPLOYED"
+ loop.Components.DCAE = *state
+
+ loopInstanceList = append(loopInstanceList, *loop)
+ return c.JSON(http.StatusCreated, *loop)
+}
+
+func addOperationaPolicy(c echo.Context) error {
+ loopID := c.Param("loopID")
+ policyType := c.Param("policyType")
+ policyVersion := c.Param("policyVersion")
+ op_policy := new(struct {
+ PolicyModelType string `json:"policyModelType"`
+ Version string `json:"version"`
+ PolicyAcronym string `json:"policyAcronym"`
+ PolicyPdpGroup struct {
+ SupportedPdpGroups []struct {
+ DefaultGroup []string `json:"defaultGroup"`
+ } `json:"supportedPdpGroups"`
+ } `json:"policyPdpGroup"`
+ CreatedDate time.Time `json:"createdDate"`
+ UpdatedDate time.Time `json:"updatedDate"`
+ UpdatedBy string `json:"updatedBy"`
+ CreatedBy string `json:"createdBy"`
+ })
+ for _, p := range policyList {
+ if p.PolicyModelType == policyType &&
+ p.Version == policyVersion {
+ for j, l := range loopInstanceList {
+ if l.Name == loopID {
+ op_policy.PolicyAcronym = p.PolicyAcronym
+ loopInstanceList[j].OperationalPolicies = append(loopInstanceList[j].OperationalPolicies,
+ OperationalPolicy_payload{
+ Name: "OPERATIONAL" + uuid.NewV4().String(),
+ PolicyModel: *op_policy,
+ })
+ return c.JSON(http.StatusOK, loopInstanceList[j])
+ }
+ }
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "loop not found",
+ Error: "Not Found",
+ Status: "404"})
+ }
+ }
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "Policy not found",
+ Error: "Not Found",
+ Status: "404"})
+}
+
+//remove operation is not working in the real CLAMP
+func removeOperationaPolicy(c echo.Context) error {
+ loopID := c.Param("loopID")
+ policyType := c.Param("policyType")
+ policyVersion := c.Param("policyVersion")
+
+ for j, l := range loopInstanceList {
+ if l.Name == loopID {
+ for i, pp := range l.OperationalPolicies {
+ if pp.PolicyModel.PolicyModelType == policyType &&
+ pp.PolicyModel.Version == policyVersion {
+ loopInstanceList[j].OperationalPolicies = append(loopInstanceList[j].OperationalPolicies[:i],
+ loopInstanceList[j].OperationalPolicies[i+1:]...)
+ return c.JSON(http.StatusOK, l)
+ }
+ }
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "Policy not found",
+ Error: "Not Found",
+ Status: "404"})
+ }
+ }
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "loop not found",
+ Error: "Not Found",
+ Status: "404"})
+}
+
+//must review tca_policy struct
+func addTcaConfig(c echo.Context) error {
+ loopID := c.Param("loopID")
+ data := new(MicroServicePolicy)
+ if err := c.Bind(data); err != nil {
+ return err
+ }
+ for j, l := range loopInstanceList {
+ if l.Name == loopID {
+ if l.MicroServicePolicies != nil {
+ for i, _ := range l.MicroServicePolicies {
+ loopInstanceList[j].MicroServicePolicies[i] = *data
+ }
+ return c.JSON(http.StatusOK, loopInstanceList[j].MicroServicePolicies[0])
+ }
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "Microservice policy not found",
+ Error: "Not Found",
+ Status: "404"})
+ }
+ }
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "Loop not found",
+ Error: "Not Found",
+ Status: "404"})
+}
+
+func addOperationalPolicyConfig(c echo.Context) error {
+ loopID := c.Param("loopID")
+ for j, l := range loopInstanceList {
+ if l.Name == loopID {
+ /*
+ //cannot bind a list as said in labstack echo bind
+ data := new([]OperationalPolicy_payload)
+ if err := c.Bind(data); err != nil {
+ return err
+ }
+ */
+ if l.OperationalPolicies != nil {
+ //loopInstanceList[j].OperationalPolicies = *data
+ loopInstanceList[j].OperationalPolicies[len(l.OperationalPolicies)-1].ConfigurationsJSON.Actor = "Test"
+ return c.JSON(http.StatusOK, loopInstanceList[j])
+ }
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "Operational Policy not found",
+ Error: "Not Found",
+ Status: "404"})
+ }
+ }
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "Loop not found",
+ Error: "Not Found",
+ Status: "404"})
+}
+
+//util function
+func checkPoliciesConfiguration(l LoopDetails) bool {
+ var empty struct {
+ Actor string `json:"actor"`
+ Operation string `json:"operation"`
+ Limit int `json:"limit"`
+ TimeWindow int `json:"timeWindow"`
+ TimeUnits string `json:"timeUnits"`
+ }
+
+ for i, _ := range l.MicroServicePolicies {
+ if l.MicroServicePolicies[i].ConfigurationsJson.TcaPolicy.Domain == "" {
+ return false
+ }
+ }
+ for i, _ := range l.OperationalPolicies {
+ if l.OperationalPolicies[i].ConfigurationsJSON == empty {
+ return false
+ }
+ }
+ return true
+}
+
+func putLoopAction(c echo.Context) error {
+ action := c.Param("action")
+ loopID := c.Param("loopID")
+ state := new(State)
+ for j, l := range loopInstanceList {
+ if l.Name == loopID {
+ //POLICY actions
+ if action == "submit" {
+ if checkPoliciesConfiguration(loopInstanceList[j]) {
+ state.ComponentState.StateName = "SENT_AND_DEPLOYED"
+ loopInstanceList[j].Components.POLICY = *state
+ return c.JSON(http.StatusOK, loopInstanceList[j].Components.POLICY.ComponentState)
+ }
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "Policies are not well Configured",
+ Error: "Bad Action",
+ Status: "401"})
+ }
+ if action == "stop" {
+ if l.Components.POLICY.ComponentState.StateName == "NOT_SENT" {
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "Cannot perform this action",
+ Error: "Bad Action",
+ Status: "400"})
+ }
+ state.ComponentState.StateName = "SENT"
+ loopInstanceList[j].Components.POLICY = *state
+ return c.JSON(http.StatusOK, "{}")
+ }
+ if action == "restart" {
+ state.ComponentState.StateName = "SENT_AND_DEPLOYED"
+ loopInstanceList[j].Components.POLICY = *state
+ return c.JSON(http.StatusOK, "{}")
+ }
+ //DCAE actions
+ if action == "deploy" {
+ //must add deploy failure
+ state.ComponentState.StateName = "MICROSERVICE_INSTALLED_SUCCESSFULLY"
+ loopInstanceList[j].Components.DCAE = *state
+ return c.JSON(http.StatusOK, "{}")
+ }
+ if action == "undeploy" {
+ state.ComponentState.StateName = "MICROSERVICE_UNINSTALLED_SUCCESSFULLY"
+ loopInstanceList[j].Components.DCAE = *state
+ return c.JSON(http.StatusOK, "{}")
+ }
+ //LOOP action
+ if action == "delete" {
+ loopInstanceList = append(loopInstanceList[:j], loopInstanceList[j+1:]...)
+ return c.JSON(http.StatusOK, "{}")
+ }
+ //action failure
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "Cannot perform this action",
+ Error: "Bad Action",
+ Status: "400"})
+ }
+ }
+ return c.JSON(http.StatusBadRequest, ClampError{
+ Message: "Loop not found",
+ Error: "Not Found",
+ Status: "404"})
+}
diff --git a/mock-clamp/mock-clamp.go b/mock-clamp/mock-clamp.go
new file mode 100644
index 0000000..6e82d7f
--- /dev/null
+++ b/mock-clamp/mock-clamp.go
@@ -0,0 +1,44 @@
+// Copyright 2023 Deutsche Telekom AG, Orange
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+ "github.com/labstack/gommon/log"
+)
+
+func main() {
+ e := echo.New()
+ e.Use(middleware.Logger())
+ e.Logger.SetLevel(log.DEBUG)
+ e.GET("/", index)
+ e.GET("/restservices/clds/v2/templates/", getTemplates)
+ e.GET("/restservices/clds/v2/policyToscaModels/", getPolicies)
+
+ e.GET("/restservices/clds/v2/loop/:loopID", updateLoopDetails)
+ e.GET("/restservices/clds/v2/loop/getstatus/:loopID", updateLoopDetails) //refresh status
+ e.POST("/restservices/clds/v2/loop/create/:loopID", createLoopInstance)
+ e.PUT("/restservices/clds/v2/loop/addOperationaPolicy/:loopID/policyModel/:policyType/:policyVersion", addOperationaPolicy)
+ e.PUT("/restservices/clds/v2/loop/removeOperationaPolicy/:loopID/policyModel/:policyType/:policyVersion", removeOperationaPolicy)
+ e.POST("/restservices/clds/v2/loop/updateMicroservicePolicy/:loopID", addTcaConfig) //modify
+ e.POST("/restservices/clds/v2/loop/updateOperationalPolicies/:loopID", addOperationalPolicyConfig) //modify
+ e.PUT("/restservices/clds/v2/loop/:action/:loopID", putLoopAction)
+ e.POST("/reset", reset)
+ generateInitialTemplateList()
+ generateInitialPolicyList()
+ generateInitialLoopInstances()
+ e.Logger.Fatal(e.Start(":30258"))
+}
diff --git a/mock-clamp/policies_handlers.go b/mock-clamp/policies_handlers.go
new file mode 100644
index 0000000..52cc04a
--- /dev/null
+++ b/mock-clamp/policies_handlers.go
@@ -0,0 +1,98 @@
+// Copyright 2023 Deutsche Telekom AG, Orange
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import "time"
+
+//describes operational policy configuration in CLAMP
+type OperationalPolicy_payload struct {
+ Name string `json:"name"`
+ JSONRepresentation struct {
+ Title string `json:"title"`
+ Type string `json:"type"`
+ Description string `json:"description"`
+ Required []string `json:"required"`
+ Properties struct {
+ ID struct {
+ Type string `json:"type"`
+ Description string `json:"description"`
+ } `json:"id"`
+ Actor struct {
+ Type string `json:"type"`
+ Description string `json:"description"`
+ } `json:"actor"`
+ Operation struct {
+ Type string `json:"type"`
+ Description string `json:"description"`
+ } `json:"operation"`
+ TimeRange struct {
+ Title string `json:"title"`
+ Type string `json:"type"`
+ Required []string `json:"required"`
+ Properties struct {
+ StartTime struct {
+ Type string `json:"type"`
+ Format string `json:"format"`
+ } `json:"start_time"`
+ EndTime struct {
+ Type string `json:"type"`
+ Format string `json:"format"`
+ } `json:"end_time"`
+ } `json:"properties"`
+ } `json:"timeRange"`
+ Limit struct {
+ Type string `json:"type"`
+ Description string `json:"description"`
+ ExclusiveMinimum string `json:"exclusiveMinimum"`
+ } `json:"limit"`
+ TimeWindow struct {
+ Type string `json:"type"`
+ Description string `json:"description"`
+ } `json:"timeWindow"`
+ TimeUnits struct {
+ Type string `json:"type"`
+ Description string `json:"description"`
+ Enum []string `json:"enum"`
+ } `json:"timeUnits"`
+ } `json:"properties"`
+ } `json:"jsonRepresentation"`
+ ConfigurationsJSON struct {
+ Actor string `json:"actor"`
+ Operation string `json:"operation"`
+ Limit int `json:"limit"`
+ TimeWindow int `json:"timeWindow"`
+ TimeUnits string `json:"timeUnits"`
+ } `json:"configurationsJson"`
+ PolicyModel struct {
+ PolicyModelType string `json:"policyModelType"`
+ Version string `json:"version"`
+ PolicyAcronym string `json:"policyAcronym"`
+ PolicyPdpGroup struct {
+ SupportedPdpGroups []struct {
+ DefaultGroup []string `json:"defaultGroup"`
+ } `json:"supportedPdpGroups"`
+ } `json:"policyPdpGroup"`
+ CreatedDate time.Time `json:"createdDate"`
+ UpdatedDate time.Time `json:"updatedDate"`
+ UpdatedBy string `json:"updatedBy"`
+ CreatedBy string `json:"createdBy"`
+ } `json:"policyModel"`
+ CreatedDate time.Time `json:"createdDate"`
+ UpdatedDate time.Time `json:"updatedDate"`
+ UpdatedBy string `json:"updatedBy"`
+ CreatedBy string `json:"createdBy"`
+ PdpGroup string `json:"pdpGroup"`
+ PdpSubgroup string `json:"pdpSubgroup"`
+}
diff --git a/mock-dmaap/Dockerfile b/mock-dmaap/Dockerfile
new file mode 100644
index 0000000..d17e075
--- /dev/null
+++ b/mock-dmaap/Dockerfile
@@ -0,0 +1,7 @@
+FROM python:3
+COPY . /app
+WORKDIR /app
+COPY ./requirements.txt ./
+RUN pip install -r ./requirements.txt
+ENV FLASK_APP=app/app.py
+CMD ["python", "app/app.py"] \ No newline at end of file
diff --git a/mock-dmaap/Makefile b/mock-dmaap/Makefile
new file mode 100644
index 0000000..af8f162
--- /dev/null
+++ b/mock-dmaap/Makefile
@@ -0,0 +1,23 @@
+all: build
+
+.PHONY: build
+
+build:
+ @echo "##### Build dmaap simulator image #####"
+ docker build . -t dmaap-simulator
+ @echo "##### DONE #####"
+
+start:
+ @echo "##### Start dmaap simulator #####"
+ docker run -d -p 3904:3904 --name dmaap-simulator dmaap-simulator
+ @echo "##### DONE #####"
+
+stop:
+ @echo "##### Stop dmaap simulator #####"
+ docker rm -f dmaap-simulator
+ @echo "##### DONE #####"
+
+get-data:
+ @echo "##### Get data fetched by dmaap-simulator #####\n"
+ curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://localhost:3904/events
+ @echo "\n\n##### DONE #####"
diff --git a/mock-dmaap/README.md b/mock-dmaap/README.md
new file mode 100644
index 0000000..6759e79
--- /dev/null
+++ b/mock-dmaap/README.md
@@ -0,0 +1,23 @@
+DMaaP Mock
+---------------
+
+
+### Build an image
+```
+make build
+```
+
+### Start
+```
+make start
+```
+
+### Stop
+```
+make stop
+```
+
+### Get fetched events
+```
+make get-data
+```
diff --git a/mock-dmaap/app/app.py b/mock-dmaap/app/app.py
new file mode 100644
index 0000000..ffaaa63
--- /dev/null
+++ b/mock-dmaap/app/app.py
@@ -0,0 +1,98 @@
+"""
+ Copyright 2023 Deutsche Telekom AG, Nokia, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+
+import json
+import logging as sys_logging
+from event_storage import EventStorage
+from sdc import Sdc
+from ves import Ves
+
+from flask import Flask, request, logging, Response
+
+app = Flask(__name__)
+
+sys_logging.basicConfig(level=sys_logging.DEBUG)
+logger = logging.create_logger(app)
+apiKey = {"key": "test_key", "secret": "test_secret"}
+event_storage = EventStorage()
+sdc = Sdc(logger, event_storage)
+ves = Ves(logger, event_storage)
+
+
+@app.route("/apiKeys/create", methods=['POST'])
+def create_api_key():
+ resp = Response(json.dumps(apiKey))
+ return resp
+
+
+@app.route("/apiKeys/<path:key>", methods=['DELETE'])
+def delete_api_key(key):
+ if key == apiKey["key"]:
+ return {}, 200
+ return {"no such key"}, 404
+
+
+@app.route("/reset", methods=['GET'])
+def reset_events():
+ event_storage.clear()
+ return event_storage
+
+
+@app.route("/events", methods=['GET'])
+def get_events():
+ resp = Response(json.dumps(event_storage))
+ resp.headers['Content-Type'] = 'application/json'
+ return resp
+
+
+@app.route("/events/<path:topic>/<path:consumer_group>/<path:consumer_id>", methods=['GET'])
+def get_events_from_topic(topic, consumer_group, consumer_id):
+ events = event_storage.get_events_from_topic(topic)
+ resp = Response(json.dumps(events))
+ event_storage.delete_events(topic)
+ resp.headers['Content-Type'] = 'application/json'
+ return resp
+
+
+@app.route("/events/<path:topic>", methods=['POST'])
+def post_msg_to_topic(topic):
+ receive_msg = request.data.decode("utf-8")
+ if sdc.is_event_from_sdc(receive_msg):
+ return sdc.post_msg_to_topic(topic, receive_msg)
+ else:
+ return ves.handle_new_event(topic, receive_msg)
+
+
+@app.route("/events/<path:topic>/add", methods=['POST'])
+def add_msg_to_topic(topic):
+ receive_msg = request.data.decode("utf-8")
+ return sdc.add_msg_to_topic(topic, receive_msg)
+
+
+@app.route("/topics", methods=['GET'])
+def get_topics():
+ topics = {
+ 'topics': ['org.onap.dmaap.mr.PNF_REGISTRATION', 'SDC-DISTR-STATUS-TOPIC-AUTO', 'SDC-DISTR-NOTIF-TOPIC-AUTO',
+ 'org.onap.dmaap.mr.PNF_READY', 'POLICY-PDP-PAP', 'POLICY-NOTIFICATION',
+ 'unauthenticated.SEC_3GPP_FAULTSUPERVISION_OUTPUT', '__consumer_offsets',
+ 'org.onap.dmaap.mr.mirrormakeragent']}
+ resp = Response(json.dumps(topics))
+ resp.headers['Content-Type'] = 'application/json'
+ return resp
+
+
+if __name__ == "__main__":
+ app.run(host='0.0.0.0', port=3904)
diff --git a/mock-dmaap/app/event_storage.py b/mock-dmaap/app/event_storage.py
new file mode 100644
index 0000000..a520166
--- /dev/null
+++ b/mock-dmaap/app/event_storage.py
@@ -0,0 +1,40 @@
+"""
+ Copyright 2023 Deutsche Telekom AG, Nokia, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+
+class EventStorage:
+ __events = {}
+
+ def get_events(self):
+ return self.__events
+
+ def get_events_from_topic(self, topic):
+ if self.__events.__contains__(topic):
+ return self.__events[topic]
+ else:
+ return []
+
+ def add(self, topic, event):
+ if self.__events.__contains__(topic):
+ self.__events[topic].append(event)
+ else:
+ self.__events[topic] = [event]
+
+ def delete_events(self, topic):
+ if self.__events.__contains__(topic):
+ self.__events[topic].clear()
+
+ def clear(self):
+ self.__events.clear()
diff --git a/mock-dmaap/app/sdc.py b/mock-dmaap/app/sdc.py
new file mode 100644
index 0000000..5317ad2
--- /dev/null
+++ b/mock-dmaap/app/sdc.py
@@ -0,0 +1,38 @@
+"""
+ Copyright 2023 Deutsche Telekom AG, Nokia, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+
+class Sdc:
+ __jsonArtifact = {}
+
+ def __init__(self, logger, events):
+ self.__logger = logger
+ self.__events = events
+
+ def post_msg_to_topic(self, topic, receive_msg):
+ self.__logger.info("received events: " + str(receive_msg))
+ return self.__jsonArtifact
+
+ def add_msg_to_topic(self, topic, receive_msg):
+ self.__jsonArtifact = receive_msg
+ self.__events.add(topic, receive_msg)
+ self.__logger.info("received events: " + str(receive_msg))
+ return receive_msg
+
+ def is_event_from_sdc(self, event):
+ if event[:3] == '14.':
+ return True
+ else:
+ return False
diff --git a/mock-dmaap/app/ves.py b/mock-dmaap/app/ves.py
new file mode 100644
index 0000000..6c25730
--- /dev/null
+++ b/mock-dmaap/app/ves.py
@@ -0,0 +1,46 @@
+"""
+ Copyright 2023 Deutsche Telekom AG, Nokia, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+
+import json
+
+
+class Ves:
+
+ def __init__(self, logger, events):
+ self.__logger = logger
+ self.__events = events
+
+ def handle_new_event(self, topic, http_request):
+ receive_events = self.__decode_request_data(http_request)
+ for event in receive_events:
+ self.__events.add(topic, json.loads(event))
+ return {}, 200
+
+ def __decode_request_data(self, data):
+ receive_events = data.split("\n")
+ receive_events = receive_events[:-1]
+ self.__logger.info("received events: " + str(receive_events))
+ correct_events = []
+ for event in receive_events:
+ self.__logger.info("received event: " + str(event))
+ correct_events.append(self.__get_correct_json(event))
+ return correct_events
+
+ def __get_correct_json(self, incorrect_json):
+ json_start_position = incorrect_json.find("{")
+ correct_json = incorrect_json[json_start_position:]
+ correct_json = correct_json.replace("\r", "").replace("\t", "").replace(" ", "")
+ return correct_json
diff --git a/mock-dmaap/requirements.txt b/mock-dmaap/requirements.txt
new file mode 100644
index 0000000..a6d2d3a
--- /dev/null
+++ b/mock-dmaap/requirements.txt
@@ -0,0 +1,6 @@
+Click==7.0
+Flask==1.1.1
+itsdangerous==1.1.0
+Jinja2==2.10.3
+MarkupSafe==1.1.1
+Werkzeug==0.16.0
diff --git a/mock-msb-k8s/Dockerfile b/mock-msb-k8s/Dockerfile
new file mode 100644
index 0000000..65efac9
--- /dev/null
+++ b/mock-msb-k8s/Dockerfile
@@ -0,0 +1,11 @@
+FROM python:3.8-alpine
+
+COPY . .
+
+WORKDIR /app
+
+RUN pip3 install -r ../requirements.txt
+
+EXPOSE 5003
+
+CMD ["python","app.py"] \ No newline at end of file
diff --git a/mock-msb-k8s/README.md b/mock-msb-k8s/README.md
new file mode 100644
index 0000000..f446fa0
--- /dev/null
+++ b/mock-msb-k8s/README.md
@@ -0,0 +1,2 @@
+# mock-msb-k8s
+
diff --git a/mock-msb-k8s/app/app.py b/mock-msb-k8s/app/app.py
new file mode 100644
index 0000000..5da64d7
--- /dev/null
+++ b/mock-msb-k8s/app/app.py
@@ -0,0 +1,284 @@
+"""MSB k8s mock application"""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+
+import http
+import json
+import uuid
+
+from flask import Flask, request
+from flask_restful import Api
+
+app = Flask(__name__)
+api = Api(app)
+
+CONNECTIVITY_INFOS = []
+DEFINITIONS = []
+CONFIGURATIONS_TEMPLATES = []
+PROFILES = []
+INSTANCES = []
+INSTANCE_EXAMPLE = {
+ "id": "ID_GENERATED_BY_K8SPLUGIN",
+ "namespace": "NAMESPACE_WHERE_INSTANCE_HAS_BEEN_DEPLOYED_AS_DERIVED_FROM_PROFILE",
+ "release-name": "RELEASE_NAME_AS_COMPUTED_BASED_ON_INSTANTIATION_REQUEST_AND_PROFILE_DEFAULT",
+ "request": {
+ "rb-name": "test-rbdef",
+ "rb-version": "v1",
+ "profile-name": "p1",
+ "cloud-region": "krd",
+ "override-values": {
+ "optionalDictOfParameters": "andTheirValues, like",
+ "global.name": "dummy-name"
+ },
+ "labels": {
+ "optionalLabelForInternalK8spluginInstancesMetadata": "dummy-value"
+ },
+ },
+ "resources": [
+ {
+ "GVK": {
+ "Group": "",
+ "Kind": "ConfigMap",
+ "Version": "v1"
+ },
+ "Name": "test-cm"
+ },
+ {
+ "GVK": {
+ "Group": "",
+ "Kind": "Service",
+ "Version": "v1"
+ },
+ "Name": "test-svc"
+ },
+ {
+ "GVK": {
+ "Group": "apps",
+ "Kind": "Deployment",
+ "Version": "v1"
+ },
+ "Name": "test-dep"
+ }
+ ]
+}
+
+
+@app.route('/api/multicloud-k8s/v1/v1/connectivity-info/<string:region_id>', methods=['GET', 'DELETE'])
+def connectivity_info_get_delete(region_id):
+ if request.method == 'GET':
+ for conninfo in CONNECTIVITY_INFOS:
+ if conninfo["cloud-region"] == region_id:
+ return conninfo, http.HTTPStatus.OK
+ else:
+ return '', http.HTTPStatus.NOT_FOUND
+ if request.method == 'DELETE':
+ for conninfo in CONNECTIVITY_INFOS:
+ if conninfo["cloud-region"] == region_id:
+ CONNECTIVITY_INFOS.remove(conninfo)
+ return '', http.HTTPStatus.OK
+ else:
+ return '', http.HTTPStatus.NOT_FOUND
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/connectivity-info', methods=['POST'])
+def connectivity_info_create():
+ if request.method == 'POST':
+ kubeconfig = request.files['file']
+ metadata = json.loads(request.values['metadata'])
+ CONNECTIVITY_INFOS.append({
+ "cloud-region": metadata['cloud-region'],
+ "cloud-owner": metadata['cloud-region'],
+ "kubeconfig": kubeconfig.read().decode("utf-8")
+ })
+ return '', http.HTTPStatus.OK
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/rb/definition', methods=['POST'])
+def definition_create():
+ if request.method == 'POST':
+ data = json.loads(request.data)
+ DEFINITIONS.append({
+ "rb-name": data['rb-name'],
+ "rb-version": data['rb-version'],
+ "chart-name": data['chart-name'],
+ "description": data['description'],
+ "labels": data['labels']
+ })
+ return '', http.HTTPStatus.OK
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/rb/definition/<string:rb_name>/<string:rb_version>/content', methods=['POST'])
+def definition_upload_artifact(rb_name, rb_version):
+ if request.method == 'POST':
+ data = request.data
+ return '', http.HTTPStatus.OK
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/rb/definition/<string:rb_name>/<string:rb_version>', methods=['GET', 'DELETE'])
+def definition_get_delete(rb_name, rb_version):
+ if request.method == 'GET':
+ for rb in DEFINITIONS:
+ if rb['rb-name'] == rb_name and rb['rb-version'] == rb_version:
+ return rb, http.HTTPStatus.OK
+ else:
+ return '', http.HTTPStatus.NOT_FOUND
+ if request.method == 'DELETE':
+ for rb in DEFINITIONS:
+ if rb['rb-name'] == rb_name and rb['rb-version'] == rb_version:
+ DEFINITIONS.remove(rb)
+ return '', http.HTTPStatus.OK
+ else:
+ return '', http.HTTPStatus.NOT_FOUND
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/rb/definition', methods=['GET'])
+def definition_get_all():
+ if request.method == 'GET':
+ return json.dumps(DEFINITIONS), http.HTTPStatus.OK
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/rb/definition/<string:rb_name>/<string:rb_version>/profile', methods=['POST'])
+def profile_create(**kwargs):
+ if request.method == 'POST':
+ data = json.loads(request.data)
+ PROFILES.append({
+ "rb-name": data['rb-name'],
+ "rb-version": data['rb-version'],
+ "profile-name": data['profile-name'],
+ "release-name": data['release-name'],
+ "namespace": data['namespace'],
+ "kubernetes-version": data['kubernetes-version']
+ })
+ return '', http.HTTPStatus.OK
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route(
+ '/api/multicloud-k8s/v1/v1/rb/definition/<string:rb_name>/<string:rb_version>/profile/<string:profile_name>/content'
+ , methods=['POST'])
+def profile_upload_artifact(rb_name, rb_version, profile_name):
+ if request.method == 'POST':
+ data = request.data
+ return '', http.HTTPStatus.OK
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/rb/definition/<string:rb_name>/<string:rb_version>/profile/<string:profile_name>',
+ methods=['GET', 'DELETE'])
+def profile_get_delete(rb_name, rb_version, profile_name):
+ if request.method == 'GET':
+ for profile in PROFILES:
+ if profile['rb-name'] == rb_name and profile['rb-version'] == rb_version \
+ and profile["profile-name"] == profile_name:
+ return profile, http.HTTPStatus.OK
+ else:
+ return '', http.HTTPStatus.NOT_FOUND
+ if request.method == 'DELETE':
+ for profile in PROFILES:
+ if profile['rb-name'] == rb_name and profile['rb-version'] == rb_version \
+ and profile["profile-name"] == profile_name:
+ PROFILES.remove(profile)
+ return '', http.HTTPStatus.OK
+ else:
+ return '', http.HTTPStatus.NOT_FOUND
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/rb/definition/<string:rb_name>/<string:rb_version>/profile', methods=['GET'])
+def profile_get_all(rb_name, rb_version):
+ if request.method == 'GET':
+ profiles = []
+ for profile in PROFILES:
+ if profile['rb-name'] == rb_name and profile['rb-version'] == rb_version:
+ profiles.append(profile)
+ return json.dumps(PROFILES), http.HTTPStatus.OK
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+@app.route('/api/multicloud-k8s/v1/v1/instance', methods=['POST'])
+def instance_create():
+ if request.method == 'POST':
+ data = json.loads(request.data)
+ instance_details = INSTANCE_EXAMPLE
+ instance_details["id"] = str(uuid.uuid4())
+ instance_details["request"] = data
+ INSTANCES.append(instance_details)
+ return instance_details, http.HTTPStatus.OK
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+@app.route('/api/multicloud-k8s/v1/v1/instance/<string:instance_id>', methods=['GET', 'DELETE'])
+def instance_get_delete(instance_id):
+ if request.method == 'GET':
+ for instance in INSTANCES:
+ if instance['id'] == instance_id:
+ return instance, http.HTTPStatus.OK
+ else:
+ return '', http.HTTPStatus.NOT_FOUND
+ if request.method == 'DELETE':
+ for instance in INSTANCES:
+ if instance['id'] == instance_id:
+ INSTANCES.remove(instance)
+ return '', http.HTTPStatus.OK
+ else:
+ return '', http.HTTPStatus.NOT_FOUND
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/instance', methods=['GET'])
+def instance_get_all():
+ if request.method == 'GET':
+ return json.dumps(INSTANCES), http.HTTPStatus.OK
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/rb/definition/<string:rb_name>/<string:rb_version>/config-template',
+ methods=["POST"])
+def configuration_template_create(rb_name, rb_version):
+ if request.method == "POST":
+ data = json.loads(request.data)
+ configuration_template = data
+ CONFIGURATIONS_TEMPLATES.append(configuration_template)
+ return '', http.HTTPStatus.OK
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/rb/definition/<string:rb_name>/<string:rb_version>/config-template/<string:name>',
+ methods=["GET"])
+def configuration_template_get(rb_name, rb_version, name):
+ if request.method == "GET":
+ for template in CONFIGURATIONS_TEMPLATES:
+ if template['template-name'] == name:
+ return json.dumps(template), http.HTTPStatus.OK
+ else:
+ return '', http.HTTPStatus.NOT_FOUND
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+@app.route('/api/multicloud-k8s/v1/v1/rb/definition/<string:rb_name>/<string:rb_version>/config-template',
+ methods=["GET"])
+def configuration_template_get_all(rb_name, rb_version):
+ if request.method == 'GET':
+ return json.dumps(CONFIGURATIONS_TEMPLATES), http.HTTPStatus.OK
+ return '', http.HTTPStatus.METHOD_NOT_ALLOWED
+
+
+if __name__ == "__main__":
+ app.run(debug=True, host='0.0.0.0', port=5003)
diff --git a/mock-msb-k8s/requirements.txt b/mock-msb-k8s/requirements.txt
new file mode 100644
index 0000000..07e3f1f
--- /dev/null
+++ b/mock-msb-k8s/requirements.txt
@@ -0,0 +1,2 @@
+Flask==1.1.2
+Flask-RESTful==0.3.8
diff --git a/mock-sdc/.dockerignore b/mock-sdc/.dockerignore
new file mode 100644
index 0000000..53b2e85
--- /dev/null
+++ b/mock-sdc/.dockerignore
@@ -0,0 +1,16 @@
+# Binaries for programs and plugins
+mock-sdc
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+# vendor/
diff --git a/mock-sdc/Dockerfile b/mock-sdc/Dockerfile
new file mode 100644
index 0000000..524c178
--- /dev/null
+++ b/mock-sdc/Dockerfile
@@ -0,0 +1,33 @@
+FROM golang:alpine AS builder
+
+# Add all the source code (except what's ignored
+# under `.dockerignore`) to the build context.
+ADD ./ /go/src/
+
+WORKDIR /go/src
+
+RUN apk add --no-cache git
+RUN go env -w GO111MODULE=auto
+RUN go get github.com/satori/go.uuid
+RUN go get github.com/labstack/echo
+RUN go get github.com/golang-jwt/jwt
+RUN go get golang.org/x/time/rate
+
+RUN set -ex && \
+ CGO_ENABLED=0 GOOS=linux go build \
+ -tags netgo \
+ -installsuffix cgo \
+ -v -a \
+ -ldflags '-extldflags "-static"' \
+ -o mock-sdc .
+
+RUN ls -la
+
+FROM scratch
+
+# Retrieve the binary from the previous stage
+COPY --from=builder /go/src/mock-sdc /app/mock-sdc
+WORKDIR /app
+
+# Set the binary as the entrypoint of the container
+ENTRYPOINT [ "./mock-sdc" ]
diff --git a/mock-sdc/README.md b/mock-sdc/README.md
new file mode 100644
index 0000000..ae7ae66
--- /dev/null
+++ b/mock-sdc/README.md
@@ -0,0 +1,2 @@
+# mock-sdc
+
diff --git a/mock-sdc/generic_handlers.go b/mock-sdc/generic_handlers.go
new file mode 100644
index 0000000..a24cb45
--- /dev/null
+++ b/mock-sdc/generic_handlers.go
@@ -0,0 +1,32 @@
+// Copyright 2023 Deutsche Telekom AG, Orange
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "net/http"
+
+ "github.com/labstack/echo"
+)
+
+func index(c echo.Context) error {
+ return c.String(http.StatusOK, "Hello, World!")
+}
+
+func reset(c echo.Context) error {
+ generateInitialVendorList()
+ generateInitialVspList()
+ generateInitialResourceList()
+ return c.String(http.StatusCreated, "reset done!")
+}
diff --git a/mock-sdc/mock-sdc.go b/mock-sdc/mock-sdc.go
new file mode 100644
index 0000000..0b53afe
--- /dev/null
+++ b/mock-sdc/mock-sdc.go
@@ -0,0 +1,71 @@
+// Copyright 2023 Deutsche Telekom AG, Orange
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "github.com/labstack/echo"
+ "github.com/labstack/echo/middleware"
+ "github.com/labstack/gommon/log"
+)
+
+func main() {
+ e := echo.New()
+ e.Use(middleware.Logger())
+ e.Logger.SetLevel(log.DEBUG)
+ e.GET("/", index)
+ e.GET("/sdc1/feProxy/onboarding-api/v1.0/items/:itemID/versions", getItemVersions)
+ e.GET("/sdc1/feProxy/onboarding-api/v1.0/items/:itemID/versions/:versionID", getItemVersion)
+ e.PUT("/sdc1/feProxy/onboarding-api/v1.0/items/:itemID/versions/:versionID/actions", updateItemVersion)
+ e.GET("/sdc1/feProxy/onboarding-api/v1.0/vendor-license-models", getVendorServiceModels)
+ e.POST("/sdc1/feProxy/onboarding-api/v1.0/vendor-license-models", postVendorServiceModels)
+ e.PUT("/sdc1/feProxy/onboarding-api/v1.0/vendor-license-models/:vendorID/versions/:versionID/actions", updateVendorVersion)
+ e.GET("/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products", getVendorSoftwareProducts)
+ e.POST("/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products", postVendorSoftwareProducts)
+ e.GET("/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/:vspID/versions/:versionID", getVspVersion)
+ e.PUT("/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/:vspID/versions/:versionID/actions", updateVspVersion)
+ e.POST("/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/:vspID/versions/:versionID/orchestration-template-candidate", uploadArtifacts)
+ e.PUT("/sdc1/feProxy/onboarding-api/v1.0/vendor-software-products/:vspID/versions/:versionID/orchestration-template-candidate/process", validateArtifacts)
+ e.GET("/sdc1/feProxy/rest/v1/followed", getAllResources)
+ e.GET("/sdc1/feProxy/rest/v1/screen", getAllResources)
+ e.GET("/sdc/v1/catalog/resources", getResources)
+ e.GET("/sdc/v1/catalog/services", getServices)
+ e.GET("/sdc/v1/artifactTypes", getArtifactTypes)
+ e.GET("/sdc/v1/distributionKafkaData", distributionKafkaData)
+ e.POST("/sdc/v1/registerForDistribution", registerForDistribution)
+ e.POST("/sdc/v1/unRegisterForDistribution", unRegisterForDistribution)
+ e.POST("/sdc1/feProxy/rest/v1/catalog/resources", postResources)
+ e.POST("/sdc1/feProxy/rest/v1/catalog/resources/:resourceID/lifecycleState/:action", postResourceAction)
+ e.POST("/sdc1/feProxy/rest/v1/catalog/services", postResources)
+ e.POST("/sdc1/feProxy/rest/v1/catalog/services/:resourceID/resourceInstance", postAddResourceToService)
+ e.POST("/sdc1/feProxy/rest/v1/catalog/services/:resourceID/lifecycleState/:action", postResourceAction)
+ e.POST("/sdc1/feProxy/rest/v1/catalog/services/:resourceID/distribution-state/:action", postResourceAction)
+ e.POST("/sdc1/feProxy/rest/v1/catalog/services/:resourceID/distribution/PROD/:action", postResourceAction)
+ e.GET("/sdc1/feProxy/rest/v1/catalog/services/:resourceID/distribution", getDistribution)
+ e.GET("/sdc1/feProxy/rest/v1/catalog/services/distribution/:distributionID", getDistributionList)
+ e.GET("/sdc1/feProxy/rest/v1/catalog/services/:resourceID", getServiceUniqueIdentifier)
+ e.POST("/sdc1/feProxy/rest/v1/catalog/services/:resourceID/resourceInstance/:vfID/artifacts", uploadTcaArtifact)
+ e.POST("/sdc1/feProxy/rest/v1/catalog/services/:resourceID/properties", postResourceProperties)
+ e.POST("/sdc1/feProxy/rest/v1/catalog/services/:resourceID/create/inputs", postResourceInputs)
+ e.POST("/sdc1/feProxy/rest/v1/catalog/resources/:resourceID/create/inputs", postResourceInputs)
+ e.GET("/sdc1/feProxy/rest/v1/catalog/resources/:resourceID/filteredDataByParams", getResourcefilteredData)
+ e.GET("/sdc1/feProxy/rest/v1/catalog/services/:resourceID/filteredDataByParams", getResourcefilteredData)
+ e.GET("/sdc1/feProxy/rest/v1/setup/ui", getCategories)
+ e.POST("/reset", reset)
+ generateInitialVendorList()
+ generateInitialVspList()
+ generateInitialResourceList()
+ generateDistributionStatusList()
+ e.Logger.Fatal(e.Start(":30206"))
+}
diff --git a/mock-sdc/resource_handlers.go b/mock-sdc/resource_handlers.go
new file mode 100644
index 0000000..53aa98f
--- /dev/null
+++ b/mock-sdc/resource_handlers.go
@@ -0,0 +1,1379 @@
+// Copyright 2023 Deutsche Telekom AG, Orange
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "container/list"
+ "encoding/json"
+ "net/http"
+ "errors"
+ "io/ioutil"
+
+ "github.com/labstack/echo"
+ uuid "github.com/satori/go.uuid"
+)
+
+// ResourceLight describes license model in SDC
+type ResourceLight struct {
+ ID string `json:"uuid"`
+ InvariantID string `json:"invariantUUID"`
+ ResourceType string `json:"resourceType"`
+ Name string `json:"name"`
+ Category string `json:"category"`
+ SubCategory string `json:"subCategory"`
+ LastUpdaterUserID string `json:"lastUpdaterUserId"`
+ LifecycleState string `json:"lifecycleState"`
+ Version string `json:"version"`
+ ToscaModelURL string `json:"toscaModelURL"`
+ DistributionStatus string `json:"distributionStatus"`
+}
+
+// SubCategory describes SubCategory model in SDC
+type SubCategory struct {
+ Name string `json:"name"`
+ NormalizedName string `json:"normalizedName"`
+ UniqueID string `json:"uniqueId"`
+ Icons []string `json:"icons"`
+ Groupings string `json:"groupings"`
+ OwnerID string `json:"ownerId"`
+ Empty bool `json:"empty"`
+ Version string `json:"version"`
+ Type string `json:"type"`
+}
+
+// Category describes Category model in SDC
+type Category struct {
+ Name string `json:"name"`
+ NormalizedName string `json:"normalizedName"`
+ UniqueID string `json:"uniqueId"`
+ Icons []string `json:"icons"`
+ Subcategories []SubCategory `json:"subcategories"`
+ OwnerID string `json:"ownerId"`
+ Empty bool `json:"empty"`
+ Type string `json:"type"`
+ Version string `json:"version"`
+}
+
+//ArtifactAdd Describes ressource component Instances artifacts in SDC
+type ArtifactAdd struct {
+ ArtifactName string `json:"artifactName"`
+ ArtifactLabel string `json:"artifactLabel"`
+ ArtifactType string `json:"artifactType"`
+ Description string `json:"description"`
+}
+
+//ComponentInstance Describes ressource component Instances in SDC
+type ComponentInstance struct {
+ UniqueID string `json:"uniqueId"`
+ Name string `json:"name"`
+ ComponentName string `json:"componentName"`
+ OriginType string `json:"originType"`
+ ComponentVersion string `json:"componentVersion"`
+ DeploymentArtifacts []ArtifactAdd `json:"deploymentArtifacts"`
+}
+
+// Resource describes Resource model in SDC
+type Resource struct {
+ ID string `json:"uuid"`
+ InvariantID string `json:"invariantUUID"`
+ UniqueID string `json:"uniqueId"`
+ ResourceType string `json:"resourceType"`
+ Name string `json:"name"`
+ Category string `json:"category"`
+ SubCategory string `json:"subCategory"`
+ LastUpdaterUserID string `json:"lastUpdaterUserId"`
+ LifecycleState string `json:"lifecycleState"`
+ Version string `json:"version"`
+ ToscaModelURL string `json:"toscaModelURL"`
+ Artifacts struct{} `json:"artifacts"`
+ Attributes []string `json:"attributes"`
+ Capabilities struct{} `json:"capabilities"`
+ Categories []Category `json:"categories"`
+ ComponentInstances []ComponentInstance `json:"componentInstances"`
+ ComponentInstancesAttributes struct{} `json:"componentInstancesAttributes"`
+ ComponentInstancesProperties struct{} `json:"componentInstancesProperties"`
+ ComponentType string `json:"componentType"`
+ ContactID string `json:"contactId"`
+ CsarUUID string `json:"csarUUID"`
+ CsarVersion string `json:"csarVersion"`
+ DeploymentArtifacts struct{} `json:"deploymentArtifacts"`
+ Description string `json:"description"`
+ Icon string `json:"icon"`
+ Properties []Property `json:"properties"`
+ Requirements struct{} `json:"requirements"`
+ Tags []string `json:"tags"`
+ ToscaArtifacts struct{} `json:"toscaArtifacts"`
+ VendorName string `json:"vendorName"`
+ VendorRelease string `json:"vendorRelease"`
+ DistributionStatus string `json:"distributionStatus"`
+ DistributionID string `json:"distributionID"`
+ Inputs []Input
+}
+
+// ResourceList is the way to return Resources in SDC via DeepLoad
+type ResourceList struct {
+ Resources []Resource `json:"resources"`
+ Services []Resource `json:"services"`
+}
+
+// ActionBody yolo
+type ActionBody struct {
+ UserRemarks string `json:"userRemarks"`
+}
+
+// ResourceAdd to a Service
+type ResourceAdd struct {
+ Name string `json:"name"`
+ ComponentVersion string `json:"componentVersion"`
+ PosY int `json:"posY"`
+ PosX int `json:"posX"`
+ UniqueID string `json:"uniqueId"`
+ OriginType string `json:"originType"`
+ ComponentUID string `json:"componentUid"`
+ Icon string `json:"icon"`
+}
+
+// DistributionIDResult format
+type DistributionIDResult struct {
+ DistributionID string `json:"distributionID"`
+ UserID string `json:"userId"`
+ DeployementStatus string `json:"deployementStatus"`
+}
+
+// DistributionIDList format
+type DistributionIDList struct {
+ DistributionStatusOfServiceList []DistributionIDResult `json:"distributionStatusOfServiceList"`
+}
+
+//DistributionStatus format
+type DistributionStatus struct {
+ OmfComponentID string `json:"omfComponentID"`
+ Timestamp string `json:"timestamp"`
+ URL string `json:"url"`
+ Status string `json:"status"`
+ ErrorReason string `json:"errorReason"`
+}
+
+// DistributionStatusList format
+type DistributionStatusList struct {
+ DistributionStatusList []DistributionStatus `json:"distributionStatusList"`
+}
+
+// NewUploadResult format
+type NewUploadResult struct {
+ Description string `json:"description"`
+ ArtifactType string `json:"artifactType"`
+ ArtifactName string `json:"artifactName"`
+}
+
+//Property format
+type Property struct {
+ Name string `json:"name"`
+ Value string `json:"value"`
+ Type string `json:"type"`
+ UniqueID string `json:"uniqueId"`
+ ParentUniqueID string `json:"parentUniqueId"`
+}
+
+//Input format
+type Input struct {
+ Name string `json:"name"`
+ Value string `json:"value"`
+ Type string `json:"type"`
+ UniqueID string `json:"uniqueId"`
+}
+
+var resourceList []Resource
+var distributionList []DistributionStatus
+
+func generateInitialResourceList() {
+ resourceList = nil
+ resourceList = append(resourceList, Resource{
+ ID: "6c4952d2-0ecc-4697-a039-d9766565feae",
+ InvariantID: "803cbaf5-deea-4022-a731-709d285435d6",
+ UniqueID: "1e6e90ec-632a-492f-9511-f2787a2befaf",
+ ResourceType: "Configuration",
+ Name: "VLAN Network Receptor Configuration",
+ Category: "Configuration",
+ SubCategory: "Configuration",
+ LastUpdaterUserID: "jh0003",
+ LifecycleState: "CERTIFIED",
+ Version: "1.0",
+ ToscaModelURL: "/sdc/v1/catalog/resources/6c4952d2-0ecc-4697-a039-d9766565feae/toscaModel",
+ })
+ resourceList = append(resourceList, Resource{
+ ID: "85a9a912-b0ca-4cc9-9dc4-a480546ef93b",
+ InvariantID: "2df7615c-38f5-45e2-ac40-f9a8f97baec2",
+ UniqueID: "1e6e90ec-632a-492f-9511-f2787a2befaf",
+ ResourceType: "CP",
+ Name: "contrailV2VLANSubInterfaceV2",
+ Category: "Generic",
+ SubCategory: "Network Elements",
+ LastUpdaterUserID: "jh0003",
+ LifecycleState: "CERTIFIED",
+ Version: "1.0",
+ ToscaModelURL: "/sdc/v1/catalog/resources/85a9a912-b0ca-4cc9-9dc4-a480546ef93b/toscaModel",
+ })
+ resourceList = append(resourceList, Resource{
+ ID: "7c6b6644-590d-4e60-84d7-0dfba3ad4694",
+ InvariantID: "1e6e90ec-632a-492f-9511-f2787a2bef9f",
+ UniqueID: "1e6e90ec-632a-492f-9511-f2787a2befaf",
+ ResourceType: "VFC",
+ Name: "VDU Compute",
+ Category: "Generic",
+ SubCategory: "Infrastructure",
+ LastUpdaterUserID: "jh0003",
+ LifecycleState: "CERTIFIED",
+ Version: "1.0",
+ ToscaModelURL: "/sdc/v1/catalog/resources/7c6b6644-590d-4e60-84d7-0dfba3ad4694/toscaModel",
+ })
+ resourceList = append(resourceList, Resource{
+ ID: "9391354f-8f25-462d-b331-841e6cc5c851",
+ InvariantID: "85cd3f14-cb9c-4a28-811b-d076e9a48303",
+ UniqueID: "1e6e90ec-632a-492f-9511-f2787a2befaf",
+ ResourceType: "VFC",
+ Name: "Cp",
+ Category: "Generic",
+ SubCategory: "Infrastructure",
+ LastUpdaterUserID: "jh0003",
+ LifecycleState: "CERTIFIED",
+ Version: "1.0",
+ ToscaModelURL: "/sdc/v1/catalog/resources/9391354f-8f25-462d-b331-841e6cc5c851/toscaModel",
+ })
+}
+
+func getResources(c echo.Context) error {
+ resourceType := c.QueryParam("resourceType")
+ resources := []ResourceLight{}
+ for _, r := range resourceList {
+ if (r.ComponentType != "SERVICE") &&
+ ((resourceType == "") || (r.ResourceType == resourceType)) {
+ resources = append(resources, ResourceLight{
+ ID: r.ID,
+ InvariantID: r.InvariantID,
+ ResourceType: r.ResourceType,
+ Name: r.Name,
+ Category: r.Category,
+ SubCategory: r.SubCategory,
+ LastUpdaterUserID: r.LastUpdaterUserID,
+ LifecycleState: r.LifecycleState,
+ Version: r.Version,
+ ToscaModelURL: r.ToscaModelURL,
+ })
+ }
+ }
+ if len(resources) != 0 {
+ return c.JSON(http.StatusOK, resources)
+ }
+ return c.JSON(http.StatusNotFound, SdcError{
+ Message: "No Resources found",
+ ErrorCode: "SVC4642",
+ Status: "Not Found"})
+}
+
+func getServices(c echo.Context) error {
+ resources := []ResourceLight{}
+ for _, r := range resourceList {
+ if r.ComponentType == "SERVICE" {
+ resources = append(resources, ResourceLight{
+ ID: r.ID,
+ InvariantID: r.InvariantID,
+ ResourceType: r.ResourceType,
+ Name: r.Name,
+ Category: r.Category,
+ SubCategory: r.SubCategory,
+ LastUpdaterUserID: r.LastUpdaterUserID,
+ LifecycleState: r.LifecycleState,
+ Version: r.Version,
+ ToscaModelURL: r.ToscaModelURL,
+ DistributionStatus: r.DistributionStatus,
+ })
+ }
+ }
+ if len(resources) != 0 {
+ return c.JSON(http.StatusOK, resources)
+ }
+ return c.JSON(http.StatusNotFound, SdcError{
+ Message: "No Resources found",
+ ErrorCode: "SVC4642",
+ Status: "Not Found"})
+}
+
+func postResources(c echo.Context) error {
+ resource := new(Resource)
+ if err := c.Bind(resource); err != nil {
+ return err
+ }
+ for _, r := range resourceList {
+ if resource.Name == r.Name && r.ResourceType == resource.ResourceType {
+ return c.JSON(http.StatusBadRequest, SdcError{
+ Message: "Resource of same Name and ResourceType exists",
+ ErrorCode: "SVC3642",
+ Status: "Exists"})
+ }
+ }
+ resource.ID = uuid.Must(uuid.NewV4()).String()
+ resource.InvariantID = uuid.Must(uuid.NewV4()).String()
+ resource.UniqueID = uuid.Must(uuid.NewV4()).String()
+ resource.Version = "0.1"
+ resource.LifecycleState = "NOT_CERTIFIED_CHECKOUT"
+ resource.DistributionStatus = "DISTRIBUTION_NOT_APPROVED"
+
+ resourceList = append(resourceList, *resource)
+
+ return c.JSON(http.StatusCreated, resource)
+}
+
+func postResourceAction(c echo.Context) error {
+ resourceID := c.Param("resourceID")
+ action := c.Param("action")
+ actionBody := new(ActionBody)
+ if err := c.Bind(actionBody); err != nil {
+ return err
+ }
+ for i, r := range resourceList {
+ if r.UniqueID == resourceID {
+ if r.LifecycleState == "NOT_CERTIFIED_CHECKOUT" && action == "Certify" {
+ resourceList[i].Version = "1.0"
+ resourceList[i].LifecycleState = "CERTIFIED"
+ return c.JSON(http.StatusCreated, resourceList[i])
+ }
+ if r.LifecycleState == "NOT_CERTIFIED_CHECKOUT" && action == "checkin" {
+ resourceList[i].LifecycleState = "NOT_CERTIFIED_CHECKIN"
+ return c.JSON(http.StatusOK, resourceList[i])
+ }
+ if r.LifecycleState == "NOT_CERTIFIED_CHECKIN" && action == "Certify" {
+ resourceList[i].LifecycleState = "CERTIFIED"
+ resourceList[i].Version = "1.0"
+ resourceList[i].DistributionStatus = "DISTRIBUTION_APPROVED"
+ return c.JSON(http.StatusOK, resourceList[i])
+ }
+ if r.LifecycleState == "CERTIFIED" &&
+ r.DistributionStatus == "DISTRIBUTION_APPROVED" &&
+ action == "activate" {
+ resourceList[i].DistributionStatus = "DISTRIBUTED"
+ return c.JSON(http.StatusOK, resourceList[i])
+ }
+ return c.JSON(http.StatusBadRequest, SdcError{
+ Message: "Cannot perform this action",
+ ErrorCode: "SVC3642",
+ Status: "Bad Action"})
+ }
+ }
+ return c.JSON(http.StatusNotFound, SdcError{
+ Message: "Resource not found",
+ ErrorCode: "SVC4642",
+ Status: "Not Found"})
+}
+
+func postAddResourceToService(c echo.Context) error {
+ resourceID := c.Param("resourceID")
+ resourceAdd := new(ResourceAdd)
+ if err := c.Bind(resourceAdd); err != nil {
+ return err
+ }
+ for i, r := range resourceList {
+ if r.UniqueID == resourceID {
+ if r.LifecycleState == "NOT_CERTIFIED_CHECKOUT" {
+ for _, rr := range resourceList {
+ if rr.UniqueID == resourceAdd.UniqueID &&
+ rr.UniqueID == resourceAdd.ComponentUID &&
+ rr.Name == resourceAdd.Name &&
+ rr.Version == resourceAdd.ComponentVersion &&
+ rr.ResourceType == resourceAdd.OriginType {
+ if rr.ResourceType == "VF" {
+ ci := ComponentInstance{
+ UniqueID: uuid.Must(uuid.NewV4()).String(),
+ Name: resourceAdd.Name,
+ ComponentName: resourceAdd.Name,
+ OriginType: "VF",
+ ComponentVersion: "1.0",
+ }
+ resourceList[i].ComponentInstances = append(r.ComponentInstances, ci)
+ }
+ return c.JSON(http.StatusCreated, r)
+ }
+ }
+ }
+
+ return c.JSON(http.StatusBadRequest, SdcError{
+ Message: "Cannot perform this action",
+ ErrorCode: "SVC3642",
+ Status: "Bad Action"})
+ }
+ }
+
+ return c.JSON(http.StatusNotFound, SdcError{
+ Message: "Resource not found",
+ ErrorCode: "SVC4642",
+ Status: "Not Found"})
+}
+
+func getDistribution(c echo.Context) error {
+ resourceID := c.Param("resourceID")
+ for i, r := range resourceList {
+ if r.ID == resourceID {
+ distributionIDResult := new(DistributionIDResult)
+ if r.DistributionStatus == "DISTRIBUTED" {
+ if len(r.DistributionID) < 1 {
+ resourceList[i].DistributionID = uuid.Must(uuid.NewV4()).String()
+ }
+ distributionIDResult.DeployementStatus = "Distributed"
+ distributionIDResult.UserID = "Oper P(op0001)"
+ distributionIDResult.DistributionID = resourceList[i].DistributionID
+ }
+ distributionIDList := new(DistributionIDList)
+ distributionIDList.DistributionStatusOfServiceList = append(distributionIDList.DistributionStatusOfServiceList, *distributionIDResult)
+ return c.JSON(http.StatusOK, distributionIDList)
+ }
+ }
+ return c.JSON(http.StatusNotFound, SdcError{
+ Message: "Resource not found",
+ ErrorCode: "SVC4642",
+ Status: "Not Found"})
+}
+
+func getDistributionList(c echo.Context) error {
+ distributionID := c.Param("distributionID")
+ for _, r := range resourceList {
+ if r.DistributionID == distributionID {
+ d := new(DistributionStatusList)
+ d.DistributionStatusList = distributionList
+ return c.JSON(http.StatusOK, d)
+ }
+ }
+ return c.JSON(http.StatusNotFound, SdcError{
+ Message: "Resource not found",
+ ErrorCode: "SVC4642",
+ Status: "Not Found"})
+}
+
+func getAllResources(c echo.Context) error {
+
+ var listResources []Resource
+ var listServices []Resource
+
+ for _, r := range resourceList {
+ if r.ComponentType != "SERVICE" {
+ listResources = append(listResources, r)
+ } else {
+ listServices = append(listServices, r)
+ }
+ }
+ list := &ResourceList{listResources, listServices}
+ return c.JSON(http.StatusOK, list)
+}
+
+func getServiceUniqueIdentifier(c echo.Context) error {
+ resourceID := c.Param("resourceID")
+ for _, r := range resourceList {
+ if r.UniqueID == resourceID {
+ return c.JSON(http.StatusOK, r)
+ }
+ }
+
+ return c.JSON(http.StatusNotFound, SdcError{
+ Message: "Resource not found",
+ ErrorCode: "SVC4642",
+ Status: "Not Found"})
+}
+
+func uploadTcaArtifact(c echo.Context) error {
+ resourceID := c.Param("resourceID")
+ vfID := c.Param("vfID")
+ for _, r := range resourceList {
+ if r.UniqueID == resourceID {
+ if r.LifecycleState == "NOT_CERTIFIED_CHECKOUT" {
+ for _, cc := range r.ComponentInstances {
+ if cc.UniqueID == vfID {
+ newArtifact := new(ArtifactAdd)
+ if err := c.Bind(newArtifact); err != nil {
+ return err
+ }
+ cc.DeploymentArtifacts = append(cc.DeploymentArtifacts, *newArtifact)
+ NewUploadResult := NewUploadResult{
+ Description: newArtifact.Description,
+ ArtifactType: newArtifact.ArtifactType,
+ ArtifactName: newArtifact.ArtifactName,
+ }
+ return c.JSON(http.StatusCreated, NewUploadResult)
+ }
+ }
+ }
+ return c.JSON(http.StatusBadRequest, SdcError{
+ Message: "Cannot perform this action",
+ ErrorCode: "SVC3642",
+ Status: "Bad Action"})
+ }
+ }
+ return c.JSON(http.StatusNotFound, SdcError{
+ Message: "Resource not found",
+ ErrorCode: "SVC4642",
+ Status: "Not Found"})
+}
+
+func postResourceProperties(c echo.Context) error {
+ resourceID := c.Param("resourceID")
+ var bodyBytes []byte
+ if c.Request().Body != nil {
+ bodyBytes, _ = ioutil.ReadAll(c.Request().Body)
+ }
+ var dat map[string]interface{}
+ if err := json.Unmarshal(bodyBytes, &dat); err != nil {
+ return err
+ }
+ for i, r := range resourceList {
+ if r.UniqueID == resourceID {
+ for key := range dat {
+ propertyBody := new(Property)
+ propertyBody.Name = dat[key].(map[string]interface{})["name"].(string)
+ propertyBody.Type = dat[key].(map[string]interface{})["type"].(string)
+ resourceList[i].Properties = append(r.Properties, *propertyBody)
+ }
+ return c.JSON(http.StatusOK, "")
+ }
+ }
+ return c.JSON(http.StatusNotFound, "")
+}
+
+func getResourceProperties(c echo.Context) error {
+ resourceID := c.Param("resourceID")
+ for _, r := range resourceList {
+ if r.UniqueID == resourceID {
+ return c.JSON(http.StatusOK, map[string][]Property{
+ "properties": r.Properties,
+ })
+ }
+ }
+ return c.JSON(http.StatusNotFound, "")
+}
+
+func postResourceInputs(c echo.Context) error {
+ resourceID := c.Param("resourceID")
+ inputBody := new(Input)
+ if err := c.Bind(inputBody); err != nil {
+ return err
+ }
+ for i, r := range resourceList {
+ if r.UniqueID == resourceID {
+ resourceList[i].Inputs = append(r.Inputs, *inputBody)
+ return c.JSON(http.StatusOK, r.Inputs)
+ }
+ }
+ return c.JSON(http.StatusNotFound, "")
+}
+
+func getResourcefilteredData(c echo.Context) error {
+ paramType := c.QueryParam("include")
+ switch paramType {
+ case "inputs":
+ return getResourceInputs(c)
+ case "properties":
+ return getResourceProperties(c)
+ }
+ return errors.New("Invalid query param")
+}
+
+func getResourceInputs(c echo.Context) error {
+ resourceID := c.Param("resourceID")
+ for _, r := range resourceList {
+ if r.UniqueID == resourceID {
+ return c.JSON(http.StatusOK, map[string][]Input{
+ "inputs": r.Inputs,
+ })
+ }
+ }
+ return c.JSON(http.StatusNotFound, "")
+}
+
+func generateDistributionStatusList() {
+ distributionList = nil
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774740421",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vf-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "aai-ml",
+ Timestamp: "1574774737842",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vf-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774740421",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-template.yml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "cds",
+ Timestamp: "1574774726254",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774731805",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "sdc-COpenSource-Env11-sdnc-dockero",
+ Timestamp: "1574774720318",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "sdc-COpenSource-Env11-sdnc-dockero",
+ Timestamp: "1574774737396",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "DEPLOY_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "clamp",
+ Timestamp: "1574774737925",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vendor-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774750490",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "DEPLOY_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774736174",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774731805",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774740421",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "clamp",
+ Timestamp: "1574774737925",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vf-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "policy-id",
+ Timestamp: "1574774728667",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774737784",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "clamp",
+ Timestamp: "1574774737925",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-template.yml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774744883",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774731805",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774731805",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774740421",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774756945",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "DEPLOY_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774752508",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "cds",
+ Timestamp: "1574774726254",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774736174",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vendor-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "aai-ml",
+ Timestamp: "1574774745892",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "cds",
+ Timestamp: "1574774726254",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vf-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "aai-ml",
+ Timestamp: "1574774737842",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774757951",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "DEPLOY_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "aai-ml",
+ Timestamp: "1574774737842",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774737784",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vf-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "clamp",
+ Timestamp: "1574774737925",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "cds",
+ Timestamp: "1574774726254",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-template.yml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "dcae-sch",
+ Timestamp: "1574774724083",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vf-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774749381",
+ URL: "",
+ Status: "COMPONENT_DONE_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774736174",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vf-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774746542",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "policy-id",
+ Timestamp: "1574774728667",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-template.yml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774736174",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "cds",
+ Timestamp: "1574774726254",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "cds",
+ Timestamp: "1574774735595",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774737784",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774736174",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-template.yml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "dcae-sch",
+ Timestamp: "1574774724083",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774748752",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "cds",
+ Timestamp: "1574774736609",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "COMPONENT_DONE_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774969197",
+ URL: "",
+ Status: "DISTRIBUTION_COMPLETE_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "dcae-sch",
+ Timestamp: "1574774724083",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "aai-ml",
+ Timestamp: "1574774737842",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-template.yml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "aai-ml",
+ Timestamp: "1574774750517",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "DEPLOY_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774744623",
+ URL: "",
+ Status: "COMPONENT_DONE_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "dcae-sch",
+ Timestamp: "1574774724083",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "dcae-sch",
+ Timestamp: "1574774724083",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774731805",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-template.yml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774750947",
+ URL: "",
+ Status: "COMPONENT_DONE_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "sdc-COpenSource-Env11-sdnc-dockero",
+ Timestamp: "1574774735764",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774737784",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "cds",
+ Timestamp: "1574774726254",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vendor-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "clamp",
+ Timestamp: "1574774750026",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "ALREADY_DOWNLOADED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774753902",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774736174",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "policy-id",
+ Timestamp: "1574774728667",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "policy-id",
+ Timestamp: "1574774737376",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "policy-id",
+ Timestamp: "1574774728667",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "sdc-COpenSource-Env11-sdnc-dockero",
+ Timestamp: "1574774720318",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-template.yml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774754939",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "DEPLOY_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774731805",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vf-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "sdc-COpenSource-Env11-sdnc-dockero",
+ Timestamp: "1574774720318",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "sdc-COpenSource-Env11-sdnc-dockero",
+ Timestamp: "1574774720318",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774748190",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "policy-id",
+ Timestamp: "1574774728667",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vendor-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774742014",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "sdc-COpenSource-Env11-sdnc-dockero",
+ Timestamp: "1574774720318",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "policy-id",
+ Timestamp: "1574774728667",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774745715",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "DEPLOY_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774740421",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "dcae-sch",
+ Timestamp: "1574774724083",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vendor-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-k8s-id",
+ Timestamp: "1574774736174",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "sdc-COpenSource-Env11-sdnc-dockero",
+ Timestamp: "1574774738399",
+ URL: "",
+ Status: "COMPONENT_DONE_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774740487",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774731805",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vendor-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "policy-id",
+ Timestamp: "1574774740598",
+ URL: "",
+ Status: "COMPONENT_DONE_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "clamp",
+ Timestamp: "1574774737925",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "aai-ml",
+ Timestamp: "1574774737842",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "clamp",
+ Timestamp: "1574774737925",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774737784",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-template.yml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774749858",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774748343",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "aai-ml",
+ Timestamp: "1574774751522",
+ URL: "",
+ Status: "COMPONENT_DONE_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "cds",
+ Timestamp: "1574774726254",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "sdc-COpenSource-Env11-sdnc-dockero",
+ Timestamp: "1574774720318",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vendor-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774740421",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "policy-id",
+ Timestamp: "1574774739512",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "DEPLOY_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774737784",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vendor-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774746621",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "clamp",
+ Timestamp: "1574774751028",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-csar.csar",
+ Status: "ALREADY_DEPLOYED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774740421",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vendor-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774737784",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "sdc-COpenSource-Env11-sdnc-dockero",
+ Timestamp: "1574774720318",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vf-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "policy-id",
+ Timestamp: "1574774728667",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vf-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "aai-ml",
+ Timestamp: "1574774737842",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774751123",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "aai-ml",
+ Timestamp: "1574774737842",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vendor-license-model.xml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "dcae-sch",
+ Timestamp: "1574774724083",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/artifacts/service-Test12-template.yml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-starlingx-id",
+ Timestamp: "1574774752037",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/vsrx0_modules.json",
+ Status: "DEPLOY_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "SO-COpenSource-Env11",
+ Timestamp: "1574774755942",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "DEPLOY_OK",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "clamp",
+ Timestamp: "1574774737925",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.yaml",
+ Status: "NOT_NOTIFIED",
+ ErrorReason: "null",
+ })
+ distributionList = append(distributionList, DistributionStatus{
+ OmfComponentID: "multicloud-windriver-id",
+ Timestamp: "1574774743466",
+ URL: "/sdc/v1/catalog/services/Test12/1.0/resourceInstances/vsrx0/artifacts/base_ubuntu16.env",
+ Status: "DOWNLOAD_OK",
+ ErrorReason: "null",
+ })
+}
+
+func getArtifactTypes(c echo.Context) error {
+ list := []string{"HEAT"}
+ return c.JSON(http.StatusOK, list)
+}
+
+func registerForDistribution(c echo.Context) error {
+ distributionRegistration := map[string]string{
+ "distrNotificationTopicName":"testName",
+ "distrStatusTopicName":"testTopic",
+ }
+ return c.JSON(http.StatusOK, distributionRegistration)
+}
+
+func unRegisterForDistribution(c echo.Context) error {
+ return c.JSON(http.StatusOK, list.New())
+}
+
+func distributionKafkaData(c echo.Context) error {
+ kafkaData := map[string]string{
+ "kafkaBootStrapServer":"localhost:43219",
+ "distrNotificationTopicName":"SDC-DIST-NOTIF-TOPIC",
+ "distrStatusTopicName":"SDC-DIST-STATUS-TOPIC",
+ }
+ return c.JSON(http.StatusOK, kafkaData)
+}
+
diff --git a/mock-sdc/sdc_handlers.go b/mock-sdc/sdc_handlers.go
new file mode 100644
index 0000000..02f8a11
--- /dev/null
+++ b/mock-sdc/sdc_handlers.go
@@ -0,0 +1,210 @@
+// Copyright 2023 Deutsche Telekom AG, Orange
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "net/http"
+
+ "github.com/labstack/echo"
+)
+
+// VersionList describe the list return in SDC
+type VersionList struct {
+ ListCount int `json:"listCount"`
+ Results []VersionLight `json:"results"`
+}
+
+// Version describe version model in SDC
+type Version struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ BaseID string `json:"baseId"`
+ Status string `json:"status"`
+ RealStatus string
+ CreationTime int64 `json:"creationTime"`
+ ModificationTime int64 `json:"modificationTime"`
+ AdditionalInfo struct {
+ OptionalCreationMethods []string `json:"OptionalCreationMethods"`
+ } `json:"additionalInfo"`
+ State struct {
+ SynchronizationState string `json:"synchronizationState"`
+ Dirty bool `json:"dirty"`
+ } `json:"state"`
+}
+
+// VersionLight describe version model in SDC
+type VersionLight struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ BaseID string `json:"baseId"`
+ Status string `json:"status"`
+ CreationTime int64 `json:"creationTime"`
+ ModificationTime int64 `json:"modificationTime"`
+ AdditionalInfo struct {
+ OptionalCreationMethods []string `json:"OptionalCreationMethods"`
+ } `json:"additionalInfo"`
+}
+
+// VersionDetails show details of a version
+type VersionDetails struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Status string `json:"status"`
+ CreationTime int64 `json:"creationTime"`
+ ModificationTime int64 `json:"modificationTime"`
+ State struct {
+ SynchronizationState string `json:"synchronizationState"`
+ Dirty bool `json:"dirty"`
+ } `json:"state"`
+}
+
+// CreatedVersion of a CreatedVendor in SDC
+type CreatedVersion struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Status string `json:"status"`
+}
+
+// CreatedItem model in SDC
+type CreatedItem struct {
+ ItemID string `json:"itemId"`
+ Version CreatedVersion `json:"version"`
+}
+
+// Action describe the action on items in SDC
+type Action struct {
+ Action string `json:"action"`
+}
+
+// SdcError is the way to return Error in SDC
+type SdcError struct {
+ Status string `json:"status"`
+ ErrorCode string `json:"errorCode"`
+ Message string `json:"message"`
+}
+
+func getItemVersions(c echo.Context) error {
+ itemID := c.Param("itemID")
+ for _, v := range vendorList {
+ if v.ID == itemID {
+ versionList := generateVersionList(v.Versions)
+ list := &VersionList{len(versionList), versionList}
+ return c.JSON(http.StatusOK, list)
+ }
+ }
+ for _, v := range vspList {
+ if v.ID == itemID {
+ versionList := generateVersionList(v.Versions)
+ list := &VersionList{len(versionList), versionList}
+ return c.JSON(http.StatusOK, list)
+ }
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Item Not Found")
+}
+
+func generateVersionList(versions []Version) []VersionLight {
+ versionList := []VersionLight{}
+ for _, version := range versions {
+ versionList = append(versionList, VersionLight{
+ ID: version.ID,
+ Name: version.Name,
+ Description: version.Description,
+ BaseID: version.BaseID,
+ Status: version.Status,
+ CreationTime: version.CreationTime,
+ ModificationTime: version.ModificationTime,
+ AdditionalInfo: version.AdditionalInfo,
+ })
+
+ }
+ return versionList
+}
+
+func getItemVersion(c echo.Context) error {
+ itemID := c.Param("itemID")
+ versionID := c.Param("versionID")
+ for _, v := range vendorList {
+ if v.ID == itemID {
+ for _, version := range v.Versions {
+ if version.ID == versionID {
+ versionDetails := VersionDetails{
+ ID: version.ID,
+ Name: version.Name,
+ Description: version.Description,
+ Status: version.Status,
+ CreationTime: version.CreationTime,
+ ModificationTime: version.ModificationTime,
+ State: version.State,
+ }
+ return c.JSON(http.StatusOK, versionDetails)
+ }
+ }
+ }
+ }
+ for _, v := range vspList {
+ if v.ID == itemID {
+ for _, version := range v.Versions {
+ if version.ID == versionID {
+ versionDetails := VersionDetails{
+ ID: version.ID,
+ Name: version.Name,
+ Description: version.Description,
+ Status: version.Status,
+ CreationTime: version.CreationTime,
+ ModificationTime: version.ModificationTime,
+ State: version.State,
+ }
+ return c.JSON(http.StatusOK, versionDetails)
+ }
+ }
+ }
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Item Not Found")
+}
+
+func updateItemVersion(c echo.Context) error {
+ action := new(Action)
+ if err := c.Bind(action); err != nil {
+ return err
+ }
+ itemID := c.Param("itemID")
+ versionID := c.Param("versionID")
+ for i, v := range vspList {
+ if v.ID == itemID {
+ for j, version := range v.Versions {
+ if version.ID == versionID {
+ if action.Action == "Commit" {
+ if version.RealStatus == "Validated" {
+ vspList[i].Versions[j].RealStatus = "Commited"
+ vspList[i].Versions[j].State.Dirty = false
+ return c.String(http.StatusOK, "{}")
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Item not in good state")
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Unknown Action")
+ }
+ }
+ }
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Item Not Found")
+}
+
+func getCategories(c echo.Context) error {
+ return c.String(http.StatusOK, `{"categories":{"resourceCategories":[{"name":"Application L4+","normalizedName":"application l4+","uniqueId":"resourceNewCategory.application l4+","icons":null,"subcategories":[{"name":"Media Servers","normalizedName":"media servers","uniqueId":"resourceNewCategory.application l4+.media servers","icons":["applicationServer"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Database","normalizedName":"database","uniqueId":"resourceNewCategory.application l4+.database","icons":["database"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Border Element","normalizedName":"border element","uniqueId":"resourceNewCategory.application l4+.border element","icons":["borderElement"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Application Server","normalizedName":"application server","uniqueId":"resourceNewCategory.application l4+.application server","icons":["applicationServer"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Firewall","normalizedName":"firewall","uniqueId":"resourceNewCategory.application l4+.firewall","icons":["firewall"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Call Control","normalizedName":"call control","uniqueId":"resourceNewCategory.application l4+.call control","icons":["call_controll"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Web Server","normalizedName":"web server","uniqueId":"resourceNewCategory.application l4+.web server","icons":["applicationServer"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Load Balancer","normalizedName":"load balancer","uniqueId":"resourceNewCategory.application l4+.load balancer","icons":["loadBalancer"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null}],"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Network Connectivity","normalizedName":"network connectivity","uniqueId":"resourceNewCategory.network connectivity","icons":null,"subcategories":[{"name":"Connection Points","normalizedName":"connection points","uniqueId":"resourceNewCategory.network connectivity.connection points","icons":["cp"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Virtual Links","normalizedName":"virtual links","uniqueId":"resourceNewCategory.network connectivity.virtual links","icons":["vl"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null}],"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Allotted Resource","normalizedName":"allotted resource","uniqueId":"resourceNewCategory.allotted resource","icons":null,"subcategories":[{"name":"BRG","normalizedName":"brg","uniqueId":"resourceNewCategory.allotted resource.brg","icons":["brg"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"TunnelXConn","normalizedName":"tunnelxconn","uniqueId":"resourceNewCategory.allotted resource.tunnelxconn","icons":["tunnel_x_connect"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"IP Mux Demux","normalizedName":"ip mux demux","uniqueId":"resourceNewCategory.allotted resource.ip mux demux","icons":["ip_mux_demux"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Security Zone","normalizedName":"security zone","uniqueId":"resourceNewCategory.allotted resource.security zone","icons":["security_zone"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Service Admin","normalizedName":"service admin","uniqueId":"resourceNewCategory.allotted resource.service admin","icons":["service_admin"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Allotted Resource","normalizedName":"allotted resource","uniqueId":"resourceNewCategory.allotted resource.allotted resource","icons":["allotted_resource"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Contrail Route","normalizedName":"contrail route","uniqueId":"resourceNewCategory.allotted resource.contrail route","icons":["contrail_route"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null}],"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Configuration","normalizedName":"configuration","uniqueId":"resourceNewCategory.configuration","icons":null,"subcategories":[{"name":"Configuration","normalizedName":"configuration","uniqueId":"resourceNewCategory.configuration.configuration","icons":["pmc"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null}],"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Network L4+","normalizedName":"network l4+","uniqueId":"resourceNewCategory.network l4+","icons":null,"subcategories":[{"name":"Common Network Resources","normalizedName":"common network resources","uniqueId":"resourceNewCategory.network l4+.common network resources","icons":["network"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null}],"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Generic","normalizedName":"generic","uniqueId":"resourceNewCategory.generic","icons":null,"subcategories":[{"name":"Abstract","normalizedName":"abstract","uniqueId":"resourceNewCategory.generic.abstract","icons":["objectStorage","compute"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Network Service","normalizedName":"network service","uniqueId":"resourceNewCategory.generic.network service","icons":["network"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Rules","normalizedName":"rules","uniqueId":"resourceNewCategory.generic.rules","icons":["networkrules","securityrules"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Infrastructure","normalizedName":"infrastructure","uniqueId":"resourceNewCategory.generic.infrastructure","icons":["connector"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Network Elements","normalizedName":"network elements","uniqueId":"resourceNewCategory.generic.network elements","icons":["network","connector"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Database","normalizedName":"database","uniqueId":"resourceNewCategory.generic.database","icons":["database"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null}],"version":null,"ownerId":null,"empty":false,"type":null},{"name":"DCAE Component","normalizedName":"dcae component","uniqueId":"resourceNewCategory.dcae component","icons":null,"subcategories":[{"name":"Analytics","normalizedName":"analytics","uniqueId":"resourceNewCategory.dcae component.analytics","icons":["dcae_analytics"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Database","normalizedName":"database","uniqueId":"resourceNewCategory.dcae component.database","icons":["dcae_database"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Policy","normalizedName":"policy","uniqueId":"resourceNewCategory.dcae component.policy","icons":["dcae_policy"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Machine Learning","normalizedName":"machine learning","uniqueId":"resourceNewCategory.dcae component.machine learning","icons":["dcae_machineLearning"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Microservice","normalizedName":"microservice","uniqueId":"resourceNewCategory.dcae component.microservice","icons":["dcae_microservice"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Source","normalizedName":"source","uniqueId":"resourceNewCategory.dcae component.source","icons":["dcae_source"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Collector","normalizedName":"collector","uniqueId":"resourceNewCategory.dcae component.collector","icons":["dcae_collector"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Utility","normalizedName":"utility","uniqueId":"resourceNewCategory.dcae component.utility","icons":["dcae_utilty"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null}],"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Network L2-3","normalizedName":"network l2-3","uniqueId":"resourceNewCategory.network l2-3","icons":null,"subcategories":[{"name":"Gateway","normalizedName":"gateway","uniqueId":"resourceNewCategory.network l2-3.gateway","icons":["gateway"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"WAN Connectors","normalizedName":"wan connectors","uniqueId":"resourceNewCategory.network l2-3.wan connectors","icons":["network","connector","port"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Infrastructure","normalizedName":"infrastructure","uniqueId":"resourceNewCategory.network l2-3.infrastructure","icons":["ucpe"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Router","normalizedName":"router","uniqueId":"resourceNewCategory.network l2-3.router","icons":["router","vRouter"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"LAN Connectors","normalizedName":"lan connectors","uniqueId":"resourceNewCategory.network l2-3.lan connectors","icons":["network","connector","port"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null}],"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Template","normalizedName":"template","uniqueId":"resourceNewCategory.template","icons":null,"subcategories":[{"name":"Base Monitoring Template","normalizedName":"base monitoring template","uniqueId":"resourceNewCategory.template.base monitoring template","icons":["monitoring_template"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Monitoring Template","normalizedName":"monitoring template","uniqueId":"resourceNewCategory.template.monitoring template","icons":["monitoring_template"],"groupings":null,"version":null,"ownerId":null,"empty":false,"type":null}],"version":null,"ownerId":null,"empty":false,"type":null}],"serviceCategories":[{"name":"Mobility","normalizedName":"mobility","uniqueId":"serviceNewCategory.mobility","icons":["mobility"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Network L4+","normalizedName":"network l4+","uniqueId":"serviceNewCategory.network l4+","icons":["network_l_4"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"E2E Service","normalizedName":"e2e service","uniqueId":"serviceNewCategory.e2e service","icons":["network_l_1-3"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"VoIP Call Control","normalizedName":"voip call control","uniqueId":"serviceNewCategory.voip call control","icons":["call_controll"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Network Service","normalizedName":"network service","uniqueId":"serviceNewCategory.network service","icons":["network_l_1-3"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Network L1-3","normalizedName":"network l1-3","uniqueId":"serviceNewCategory.network l1-3","icons":["network_l_1-3"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null},{"name":"Partner Domain Service","normalizedName":"partner domain service","uniqueId":"serviceNewCategory.partner domain service","icons":["partner_domain_service"],"subcategories":null,"version":null,"ownerId":null,"empty":false,"type":null}],"productCategories":[]},"version":"1.6.7"}`)
+}
diff --git a/mock-sdc/vendor_handlers.go b/mock-sdc/vendor_handlers.go
new file mode 100644
index 0000000..2bdde87
--- /dev/null
+++ b/mock-sdc/vendor_handlers.go
@@ -0,0 +1,185 @@
+// Copyright 2023 Deutsche Telekom AG, Orange
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "net/http"
+ "time"
+
+ "github.com/labstack/echo"
+ uuid "github.com/satori/go.uuid"
+)
+
+// Vendor describes license model in SDC
+type Vendor struct {
+ ID string `json:"id"`
+ Type string `json:"type"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Owner string `json:"owner"`
+ Status string `json:"status"`
+ Properties struct {
+ } `json:"properties"`
+ Versions []Version `json:"-"`
+}
+
+// NewVendor describe the vendor creation model in SDC
+type NewVendor struct {
+ IconRef string `json:"iconRef"`
+ VendorName string `json:"vendorName"`
+ Description string `json:"description"`
+}
+
+// VendorList is the way to return Vendors in SDC
+type VendorList struct {
+ ListCount int `json:"listCount"`
+ Results []Vendor `json:"results"`
+}
+
+var vendorList []Vendor
+
+func generateInitialVendorList() {
+ vendorList = nil
+ var empty struct{}
+ version1 := Version{
+ ID: "61c134e128f54119934b3960c77a3f33",
+ Name: "1.0",
+ Description: "Initial version",
+ BaseID: "",
+ Status: "Certified",
+ RealStatus: "Certified",
+ CreationTime: 1559565688604,
+ ModificationTime: 1559565787436,
+ AdditionalInfo: struct {
+ OptionalCreationMethods []string `json:"OptionalCreationMethods"`
+ }{
+ OptionalCreationMethods: []string{"major"}},
+ }
+ version2 := Version{
+ ID: "2e3ba48c748d47e3bd4afdd8348bdfb9",
+ Name: "1.0",
+ Description: "Initial version",
+ BaseID: "",
+ Status: "Certified",
+ RealStatus: "Certified",
+ CreationTime: 1559562354868,
+ ModificationTime: 1559562421476,
+ AdditionalInfo: struct {
+ OptionalCreationMethods []string `json:"OptionalCreationMethods"`
+ }{
+ OptionalCreationMethods: []string{"major"}},
+ }
+ vendorList = append(vendorList,
+ Vendor{
+ ID: "212a52b2630749388a7693086ac1467e",
+ Type: "vlm",
+ Name: "wvfw",
+ Description: "wvfw",
+ Owner: "cs0008",
+ Status: "ACTIVE",
+ Properties: empty,
+ Versions: []Version{version1}})
+ vendorList = append(vendorList, Vendor{
+ ID: "e78eb0b1c73e43138f705cd92c0e4ace",
+ Type: "vlm",
+ Name: "vfw_test",
+ Description: "test vfw",
+ Owner: "cs0008",
+ Status: "ACTIVE",
+ Properties: empty,
+ Versions: []Version{version2}})
+}
+
+func getVendorServiceModels(c echo.Context) error {
+ list := &VendorList{len(vendorList), vendorList}
+ return c.JSON(http.StatusOK, list)
+}
+
+func postVendorServiceModels(c echo.Context) error {
+ newVendor := new(NewVendor)
+ if err := c.Bind(newVendor); err != nil {
+ return err
+ }
+
+ u1 := uuid.Must(uuid.NewV4()).String()
+ version := Version{
+ ID: u1,
+ Name: "1.0",
+ Description: "Initial version",
+ BaseID: "",
+ Status: "Draft",
+ RealStatus: "Draft",
+ CreationTime: (time.Now().UnixNano() / 1000000),
+ ModificationTime: (time.Now().UnixNano() / 1000000),
+ AdditionalInfo: struct {
+ OptionalCreationMethods []string `json:"OptionalCreationMethods"`
+ }{
+ OptionalCreationMethods: []string{"major"}},
+ State: struct {
+ SynchronizationState string `json:"synchronizationState"`
+ Dirty bool `json:"dirty"`
+ }{
+ SynchronizationState: "UpToDate",
+ Dirty: false,
+ },
+ }
+ u2 := uuid.Must(uuid.NewV4()).String()
+ var empty struct{}
+ vendorList = append(vendorList, Vendor{
+ ID: u2,
+ Type: "vlm",
+ Name: newVendor.VendorName,
+ Description: newVendor.Description,
+ Owner: "cs0008",
+ Status: "ACTIVE",
+ Properties: empty,
+ Versions: []Version{version}})
+
+ createdVendor := CreatedItem{
+ ItemID: u2,
+ Version: CreatedVersion{
+ ID: u1,
+ Name: "1.0",
+ Description: "Initial version",
+ Status: "Draft",
+ },
+ }
+ return c.JSON(http.StatusCreated, createdVendor)
+}
+
+func updateVendorVersion(c echo.Context) error {
+ action := new(Action)
+ if err := c.Bind(action); err != nil {
+ return err
+ }
+ if action.Action == "Submit" {
+ vendorID := c.Param("vendorID")
+ versionID := c.Param("versionID")
+ for i, vendor := range vendorList {
+ if vendor.ID == vendorID {
+ for j, version := range vendor.Versions {
+ if version.ID == versionID {
+ vendorList[i].Versions[j].Status = "Certified"
+ vendorList[i].Versions[j].RealStatus = "Certified"
+ }
+ return c.String(http.StatusOK, "{}")
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Version Not Found")
+ }
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Vendor Not Found")
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Unknown Action")
+}
diff --git a/mock-sdc/vsp_handlers.go b/mock-sdc/vsp_handlers.go
new file mode 100644
index 0000000..6b45774
--- /dev/null
+++ b/mock-sdc/vsp_handlers.go
@@ -0,0 +1,418 @@
+// Copyright 2023 Deutsche Telekom AG, Orange
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/labstack/echo"
+ uuid "github.com/satori/go.uuid"
+)
+
+// Vsp describes software product in SDC
+type Vsp struct {
+ ID string `json:"id"`
+ Icon string `json:"icon"`
+ OnboardingMethod string `json:"onboardingMethod"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Owner string `json:"owner"`
+ Status string `json:"status"`
+ VendorName string `json:"vendorName"`
+ VendorID string `json:"vendorId"`
+ Category string `json:"category"`
+ SubCategory string `json:"subCategory"`
+ CandidateOnboardingOrigin string `json:"candidateOnboardingOrigin"`
+ OnboardingOrigin string `json:"onboardingOrigin"`
+ NetworkPackageName string `json:"networkPackageName"`
+ ValidationData struct {
+ ImportStructure struct {
+ Heat string `json:"heat"`
+ } `json:"importStructure"`
+ } `json:"validationData"`
+ Versions []Version `json:"-"`
+}
+
+// VspLight describes software product in SDC lists
+type VspLight struct {
+ ID string `json:"id"`
+ OnboardingMethod string `json:"onboardingMethod"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Owner string `json:"owner"`
+ Status string `json:"status"`
+ VendorName string `json:"vendorName"`
+ VendorID string `json:"vendorId"`
+}
+
+// VspList is the way to return Vsps in SDC
+type VspList struct {
+ ListCount int `json:"listCount"`
+ Results []VspLight `json:"results"`
+}
+
+// VspDetailsDraft describes software product in SDC
+type VspDetailsDraft struct {
+ ID string `json:"id"`
+ Icon string `json:"icon"`
+ OnboardingMethod string `json:"onboardingMethod"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ VendorName string `json:"vendorName"`
+ VendorID string `json:"vendorId"`
+ Version string `json:"version"`
+ Category string `json:"category"`
+ SubCategory string `json:"subCategory"`
+}
+
+// VspDetailsUploaded describes software product in SDC
+type VspDetailsUploaded struct {
+ ID string `json:"id"`
+ Icon string `json:"icon"`
+ OnboardingMethod string `json:"onboardingMethod"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ VendorName string `json:"vendorName"`
+ VendorID string `json:"vendorId"`
+ Version string `json:"version"`
+ Category string `json:"category"`
+ SubCategory string `json:"subCategory"`
+ CandidateOnboardingOrigin string `json:"candidateOnboardingOrigin"`
+ NetworkPackageName string `json:"networkPackageName"`
+}
+
+// VspDetailsValidated describes software product in SDC
+type VspDetailsValidated struct {
+ ID string `json:"id"`
+ Icon string `json:"icon"`
+ OnboardingMethod string `json:"onboardingMethod"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ VendorName string `json:"vendorName"`
+ VendorID string `json:"vendorId"`
+ Version string `json:"version"`
+ Category string `json:"category"`
+ SubCategory string `json:"subCategory"`
+ OnboardingOrigin string `json:"onboardingOrigin"`
+ NetworkPackageName string `json:"networkPackageName"`
+ ValidationData struct {
+ ImportStructure struct {
+ Heat string `json:"heat"`
+ } `json:"importStructure"`
+ } `json:"validationData"`
+}
+
+// NewVsp describe the vsp creation model in SDC
+type NewVsp struct {
+ Icon string `json:"iconRef"`
+ Name string `json:"name"`
+ VendorName string `json:"vendorName"`
+ VendorID string `json:"vendorId"`
+ Description string `json:"description"`
+ Category string `json:"category"`
+ SubCategory string `json:"subCategory"`
+ LicensingData struct{} `json:"licensingData"`
+ OnboardingMethod string `json:"onboardingMethod"`
+}
+
+// ArtifactUploadResult bla
+type ArtifactUploadResult struct {
+ Errors struct{} `json:"errors"`
+ Status string `json:"status"`
+ OnboardingOrigin string `json:"onboardingOrigin"`
+ NetworkPackageName string `json:"networkPackageName"`
+}
+
+// ArtifactValidationResult bla
+type ArtifactValidationResult struct {
+ Errors struct{} `json:"errors"`
+ Status string `json:"status"`
+ FileNames []string `json:"fileNames"`
+}
+
+// CsarCreateResult bla
+type CsarCreateResult struct {
+ Description string `json:"description"`
+ VspName string `json:"vspName"`
+ Version string `json:"version"`
+ PackageID string `json:"packageId"`
+ Category string `json:"category"`
+ SubCategory string `json:"subCategory"`
+ VendorName string `json:"vendorName"`
+ VendorRelease string `json:"vendorRelease"`
+ PackageType string `json:"packageType"`
+ ResourceType string `json:"resourceType"`
+}
+
+var vspList []Vsp
+
+func generateInitialVspList() {
+ vspList = []Vsp{}
+}
+
+func getVendorSoftwareProducts(c echo.Context) error {
+ vspLights := []VspLight{}
+ for _, v := range vspList {
+ vspLights = append(vspLights, VspLight{
+ ID: v.ID,
+ OnboardingMethod: v.OnboardingMethod,
+ Name: v.Name,
+ Description: v.Description,
+ Owner: v.Owner,
+ Status: v.Status,
+ VendorName: v.VendorName,
+ VendorID: v.VendorID,
+ })
+ }
+ list := &VspList{len(vspLights), vspLights}
+ return c.JSON(http.StatusOK, list)
+}
+
+func postVendorSoftwareProducts(c echo.Context) error {
+ newVsp := new(NewVsp)
+ if err := c.Bind(newVsp); err != nil {
+ return err
+ }
+
+ u1 := uuid.Must(uuid.NewV4()).String()
+ version := Version{
+ ID: u1,
+ Name: "1.0",
+ Description: "Initial version",
+ BaseID: "",
+ Status: "Draft",
+ RealStatus: "Draft",
+ CreationTime: (time.Now().UnixNano() / 1000000),
+ ModificationTime: (time.Now().UnixNano() / 1000000),
+ AdditionalInfo: struct {
+ OptionalCreationMethods []string `json:"OptionalCreationMethods"`
+ }{
+ OptionalCreationMethods: []string{"major"}},
+ State: struct {
+ SynchronizationState string `json:"synchronizationState"`
+ Dirty bool `json:"dirty"`
+ }{
+ SynchronizationState: "UpToDate",
+ Dirty: false,
+ },
+ }
+ u2 := uuid.Must(uuid.NewV4()).String()
+ vspList = append(vspList, Vsp{
+ ID: u2,
+ OnboardingMethod: "NetworkPackage",
+ Name: newVsp.Name,
+ Description: newVsp.Description,
+ Owner: "cs0008",
+ Status: "ACTIVE",
+ VendorName: newVsp.VendorName,
+ VendorID: newVsp.VendorID,
+ Category: "resourceNewCategory.generic",
+ SubCategory: "resourceNewCategory.generic.abstract",
+ Icon: "icon",
+ Versions: []Version{version}})
+
+ createdVsp := CreatedItem{
+ ItemID: u2,
+ Version: CreatedVersion{
+ ID: u1,
+ Name: "1.0",
+ Description: "Initial version",
+ Status: "Draft",
+ },
+ }
+ return c.JSON(http.StatusCreated, createdVsp)
+}
+
+func uploadArtifacts(c echo.Context) error {
+ vspID := c.Param("vspID")
+ versionID := c.Param("versionID")
+ for i, v := range vspList {
+ if v.ID == vspID {
+ for j, version := range v.Versions {
+ if version.ID == versionID {
+ if version.RealStatus == "Draft" {
+ file, err := c.FormFile("upload")
+ if err != nil {
+ return err
+ }
+ fileName := strings.Split(file.Filename, ".")[0]
+ fileExtension := strings.Split(file.Filename, ".")[1]
+ vspList[i].NetworkPackageName = fileName
+ vspList[i].CandidateOnboardingOrigin = fileExtension
+ vspList[i].Versions[j].RealStatus = "Uploaded"
+ var empty struct{}
+ artifactUploadResult := ArtifactUploadResult{
+ Errors: empty,
+ Status: "Success",
+ OnboardingOrigin: fileExtension,
+ NetworkPackageName: fileName,
+ }
+ return c.JSON(http.StatusCreated, artifactUploadResult)
+ }
+ }
+ }
+ }
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Item Not Found")
+}
+
+func validateArtifacts(c echo.Context) error {
+ vspID := c.Param("vspID")
+ versionID := c.Param("versionID")
+ for i, v := range vspList {
+ if v.ID == vspID {
+ for j, version := range v.Versions {
+ if version.ID == versionID {
+ if version.RealStatus == "Uploaded" {
+ vspList[i].OnboardingOrigin = vspList[i].CandidateOnboardingOrigin
+ vspList[i].Versions[j].State.Dirty = true
+ vspList[i].ValidationData = struct {
+ ImportStructure struct {
+ Heat string `json:"heat"`
+ } `json:"importStructure"`
+ }{
+ ImportStructure: struct {
+ Heat string `json:"heat"`
+ }{
+ Heat: "Yes",
+ },
+ }
+ vspList[i].Versions[j].RealStatus = "Validated"
+ var empty struct{}
+ artifactValidationResult := ArtifactValidationResult{
+ Errors: empty,
+ FileNames: []string{
+ "base_ubuntu16.env",
+ "base_ubuntu16.yaml",
+ },
+ Status: "Success",
+ }
+ return c.JSON(http.StatusOK, artifactValidationResult)
+ }
+ }
+ }
+ }
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Item Not Found")
+}
+
+func updateVspVersion(c echo.Context) error {
+ action := new(Action)
+ if err := c.Bind(action); err != nil {
+ return err
+ }
+ vspID := c.Param("vspID")
+ versionID := c.Param("versionID")
+ for i, v := range vspList {
+ if v.ID == vspID {
+ for j, version := range v.Versions {
+ if version.ID == versionID {
+ if action.Action == "Submit" {
+ if version.RealStatus == "Commited" {
+ vspList[i].Versions[j].RealStatus = "Certified"
+ vspList[i].Versions[j].Status = "Certified"
+ return c.String(http.StatusOK, "{}")
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Item not in good state")
+ }
+ if action.Action == "Create_Package" {
+ if version.RealStatus == "Certified" {
+ csarCreateResult := CsarCreateResult{
+ Description: v.Description,
+ VspName: v.Name,
+ Version: version.Name,
+ PackageID: v.ID,
+ Category: v.Category,
+ SubCategory: v.SubCategory,
+ VendorName: v.VendorName,
+ VendorRelease: "1.0",
+ PackageType: "CSAR",
+ ResourceType: "VF",
+ }
+ return c.JSON(http.StatusOK, csarCreateResult)
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Item not in good state")
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Unknown Action")
+ }
+ }
+ }
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Item Not Found")
+}
+
+func getVspVersion(c echo.Context) error {
+ vspID := c.Param("vspID")
+ versionID := c.Param("versionID")
+ for _, v := range vspList {
+ if v.ID == vspID {
+ for _, version := range v.Versions {
+ if version.ID == versionID {
+ if version.RealStatus == "Draft" {
+ vspDetails := VspDetailsDraft{
+ ID: v.ID,
+ Icon: v.Icon,
+ OnboardingMethod: v.OnboardingMethod,
+ Name: v.Name,
+ Description: v.Description,
+ VendorName: v.VendorName,
+ VendorID: v.VendorID,
+ Version: version.ID,
+ Category: v.Category,
+ SubCategory: v.SubCategory,
+ }
+ return c.JSON(http.StatusOK, vspDetails)
+ }
+ if version.RealStatus == "Uploaded" {
+ vspDetails := VspDetailsUploaded{
+ ID: v.ID,
+ Icon: v.Icon,
+ OnboardingMethod: v.OnboardingMethod,
+ Name: v.Name,
+ Description: v.Description,
+ VendorName: v.VendorName,
+ VendorID: v.VendorID,
+ Version: version.ID,
+ Category: v.Category,
+ SubCategory: v.SubCategory,
+ CandidateOnboardingOrigin: v.CandidateOnboardingOrigin,
+ NetworkPackageName: v.NetworkPackageName,
+ }
+ return c.JSON(http.StatusOK, vspDetails)
+ }
+ vspDetails := VspDetailsValidated{
+ ID: v.ID,
+ Icon: v.Icon,
+ OnboardingMethod: v.OnboardingMethod,
+ Name: v.Name,
+ Description: v.Description,
+ VendorName: v.VendorName,
+ VendorID: v.VendorID,
+ Version: version.ID,
+ Category: v.Category,
+ SubCategory: v.SubCategory,
+ OnboardingOrigin: v.OnboardingOrigin,
+ NetworkPackageName: v.NetworkPackageName,
+ ValidationData: v.ValidationData,
+ }
+ return c.JSON(http.StatusOK, vspDetails)
+ }
+ }
+ }
+ }
+ return echo.NewHTTPError(http.StatusNotFound, "Item Not Found")
+}
diff --git a/mock-sdnc/Dockerfile b/mock-sdnc/Dockerfile
new file mode 100644
index 0000000..d558a0d
--- /dev/null
+++ b/mock-sdnc/Dockerfile
@@ -0,0 +1,11 @@
+FROM python:3.8-alpine
+
+COPY . /app
+
+WORKDIR /app
+
+RUN pip install -r requirements.txt
+
+ENTRYPOINT ["python"]
+
+CMD ["app.py"]
diff --git a/mock-sdnc/README.md b/mock-sdnc/README.md
new file mode 100644
index 0000000..a2e32f0
--- /dev/null
+++ b/mock-sdnc/README.md
@@ -0,0 +1,2 @@
+# mock-sdnc
+
diff --git a/mock-sdnc/app.py b/mock-sdnc/app.py
new file mode 100644
index 0000000..f5899e1
--- /dev/null
+++ b/mock-sdnc/app.py
@@ -0,0 +1,35 @@
+"""SDNC mock application."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from flask import Flask
+from flask_restful import Api
+
+from resources.preload import Preload
+
+
+app = Flask(__name__)
+api = Api(app)
+
+
+api.add_resource(
+ Preload,
+ "/restconf/operations/GENERIC-RESOURCE-API:preload-vf-module-topology-operation",
+ "/restconf/operations/GENERIC-RESOURCE-API:preload-network-topology-operation",
+)
+
+
+if __name__ == "__main__":
+ app.run(host="0.0.0.0", debug=True)
diff --git a/mock-sdnc/requirements.txt b/mock-sdnc/requirements.txt
new file mode 100644
index 0000000..8c695e4
--- /dev/null
+++ b/mock-sdnc/requirements.txt
@@ -0,0 +1 @@
+Flask-RESTful==0.3.8
diff --git a/mock-sdnc/resources/__init__.py b/mock-sdnc/resources/__init__.py
new file mode 100644
index 0000000..56a522c
--- /dev/null
+++ b/mock-sdnc/resources/__init__.py
@@ -0,0 +1,16 @@
+"""SDNC mock resources package."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
diff --git a/mock-sdnc/resources/preload.py b/mock-sdnc/resources/preload.py
new file mode 100644
index 0000000..9795e16
--- /dev/null
+++ b/mock-sdnc/resources/preload.py
@@ -0,0 +1,28 @@
+"""SDNC preload resource module."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from flask_restful import Resource
+
+
+class Preload(Resource):
+ """Preload resource class."""
+
+ def post(self) -> None:
+ """Preload resource mock method.
+
+ Do nothing.
+
+ """
diff --git a/mock-so/Dockerfile b/mock-so/Dockerfile
new file mode 100644
index 0000000..d558a0d
--- /dev/null
+++ b/mock-so/Dockerfile
@@ -0,0 +1,11 @@
+FROM python:3.8-alpine
+
+COPY . /app
+
+WORKDIR /app
+
+RUN pip install -r requirements.txt
+
+ENTRYPOINT ["python"]
+
+CMD ["app.py"]
diff --git a/mock-so/README.md b/mock-so/README.md
new file mode 100644
index 0000000..539b890
--- /dev/null
+++ b/mock-so/README.md
@@ -0,0 +1,2 @@
+# mock-so
+
diff --git a/mock-so/app.py b/mock-so/app.py
new file mode 100644
index 0000000..b1d6db2
--- /dev/null
+++ b/mock-so/app.py
@@ -0,0 +1,126 @@
+"""SO mock application."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+import json
+
+from flask import Flask, request
+from flask_restful import Api
+
+from resources.orchestration_request import OrchestrationRequest
+from resources.service_instance import (
+ NetworkInstance,
+ NetworkInstanceList,
+ ServiceInstance,
+ ServiceInstanceList,
+ VnfInstance,
+ VnfInstanceList,
+ VfModuleInstance,
+ VfModuleInstanceList,
+)
+
+
+app = Flask(__name__)
+api = Api(app)
+
+
+@app.route("/reset")
+def reset():
+ """Reset endpoint.
+
+ Reset all resources.
+
+ Returns:
+ str: Empty string, it has to returns anything
+
+ """
+ ServiceInstanceList.reset()
+ OrchestrationRequest.reset()
+ return ""
+
+
+@app.route("/set_aai_mock", methods=["POST"])
+def set_aai_mock():
+ """Set A&AI mock url address.
+
+ Set it for all resources which connects with A&AI mock.
+
+ Returns:
+ str: Empty string, it has to returns anything
+
+ """
+ aai_mock_url = json.loads(request.data)["AAI_MOCK"]
+ ServiceInstance.set_aai_mock(aai_mock_url)
+ ServiceInstanceList.set_aai_mock(aai_mock_url)
+ VnfInstance.set_aai_mock(aai_mock_url)
+ VfModuleInstance.set_aai_mock(aai_mock_url)
+ VnfInstanceList.set_aai_mock(aai_mock_url)
+ VfModuleInstanceList.set_aai_mock(aai_mock_url)
+ NetworkInstance.set_aai_mock(aai_mock_url)
+ NetworkInstanceList.set_aai_mock(aai_mock_url)
+ return ""
+
+
+api.add_resource(
+ ServiceInstance,
+ "/onap/so/infra/serviceInstantiation/v7/serviceInstances/<service_instance_id>",
+)
+api.add_resource(
+ ServiceInstanceList, "/onap/so/infra/serviceInstantiation/v7/serviceInstances"
+)
+api.add_resource(
+ VnfInstance,
+ (
+ "/onap/so/infra/serviceInstantiation/v7/serviceInstances/<service_instance_id>/"
+ "vnfs/<vnf_instance_id>"
+ ),
+)
+api.add_resource(
+ VnfInstanceList,
+ "/onap/so/infra/serviceInstantiation/v7/serviceInstances/<service_instance_id>/vnfs",
+)
+api.add_resource(
+ VfModuleInstance,
+ (
+ "/onap/so/infra/serviceInstantiation/v7/serviceInstances/<service_instance_id>/vnfs/"
+ "<vnf_instance_id>/vfModules/<vf_module_instance_id>"
+ ),
+)
+api.add_resource(
+ VfModuleInstanceList,
+ (
+ "/onap/so/infra/serviceInstantiation/v7/serviceInstances/<service_instance_id>/vnfs/"
+ "<vnf_instance_id>/vfModules"
+ ),
+)
+api.add_resource(
+ OrchestrationRequest,
+ "/onap/so/infra/orchestrationRequests/v7/<orchestration_request_id>",
+)
+api.add_resource(
+ NetworkInstanceList,
+ "/onap/so/infra/serviceInstantiation/v7/serviceInstances/<service_instance_id>/networks",
+)
+api.add_resource(
+ NetworkInstance,
+ (
+ "/onap/so/infra/serviceInstantiation/v7/serviceInstances/<service_instance_id>/"
+ "networks/<network_instance_id>"
+ ),
+)
+
+
+if __name__ == "__main__":
+ app.run(host="0.0.0.0", debug=True)
diff --git a/mock-so/requirements.txt b/mock-so/requirements.txt
new file mode 100644
index 0000000..f733aba
--- /dev/null
+++ b/mock-so/requirements.txt
@@ -0,0 +1,2 @@
+Flask-RESTful==0.3.8
+requests==2.23.0 \ No newline at end of file
diff --git a/mock-so/resources/__init__.py b/mock-so/resources/__init__.py
new file mode 100644
index 0000000..e189131
--- /dev/null
+++ b/mock-so/resources/__init__.py
@@ -0,0 +1,16 @@
+"""SO mock resources."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
diff --git a/mock-so/resources/orchestration_request.py b/mock-so/resources/orchestration_request.py
new file mode 100644
index 0000000..e7df8e9
--- /dev/null
+++ b/mock-so/resources/orchestration_request.py
@@ -0,0 +1,93 @@
+"""Mock SO orchestration request resource."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from dataclasses import dataclass, field
+from datetime import datetime
+from typing import Dict
+
+from flask_restful import Resource
+
+
+@dataclass
+class OrchestrationRequestData:
+ """Orchestration request dataclass."""
+
+ request_id: str
+ created_at: datetime = field(default_factory=datetime.now)
+
+
+ORCHESTRATION_REQUESTS = {}
+
+
+def time_diff(dt: datetime, diff: int = 1) -> bool:
+ """Check if given datetime has older (in seconds) than current datetime.
+
+ Args:
+ dt (datetime): Datetime to check
+ diff (int, optional): Number of seconds to check. Defaults to 1.
+
+ Returns:
+ bool: True if datetime is older, False otherwise
+
+ """
+ return (datetime.now() - dt).seconds > diff
+
+
+class OrchestrationRequest(Resource):
+ """Orchestration request resource."""
+
+ @staticmethod
+ def reset() -> None:
+ """Reset orchestration request resource.
+
+ Clean ORCHESTRATION_REQUESTS dictionary
+
+ """
+ global ORCHESTRATION_REQUESTS
+ ORCHESTRATION_REQUESTS = {}
+
+ def get(self, orchestration_request_id: str) -> Dict[str, Dict[str, str]]:
+ """Get orchestration request data.
+
+ Return orchestration request data from ORCHESTRATION_REQUESTS dictionary.
+ If it doesn't exist it creates that.
+
+ Args:
+ orchestration_request_id (str): Orchestration request id key value
+
+ Returns:
+ Dict[str, Dict[str, str]]: Orchestration request data
+ """
+ try:
+ orchestration_request_data = ORCHESTRATION_REQUESTS[
+ orchestration_request_id
+ ]
+ except KeyError:
+ orchestration_request_data = OrchestrationRequestData(
+ request_id=orchestration_request_id
+ )
+ ORCHESTRATION_REQUESTS[
+ orchestration_request_id
+ ] = orchestration_request_data
+ return {
+ "request": {
+ "requestStatus": {
+ "requestState": "COMPLETE"
+ if time_diff(orchestration_request_data.created_at)
+ else "IN_PROGRESS"
+ }
+ }
+ }
diff --git a/mock-so/resources/service_instance.py b/mock-so/resources/service_instance.py
new file mode 100644
index 0000000..60880c2
--- /dev/null
+++ b/mock-so/resources/service_instance.py
@@ -0,0 +1,344 @@
+"""SO mock instance resources."""
+"""
+ Copyright 2023 Deutsche Telekom AG, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+from typing import Callable, Dict, List
+from uuid import uuid4
+
+import requests
+from flask_restful import Resource, request
+
+
+SERVICE_INSTANCES = {}
+
+
+class SoResource(Resource):
+ """Base SO resource class."""
+
+ AAI_MOCK_URL = ""
+
+ @classmethod
+ def set_aai_mock(cls, aai_mock_url: str) -> None:
+ """Set A&AI mock address.
+
+ Instance resources needs to communicate with A&AI mock
+ to update it's state.
+
+ Args:
+ aai_mock_url (str): A&AI mock url
+
+ """
+ cls.AAI_MOCK_URL = aai_mock_url
+
+ @classmethod
+ def reset(cls) -> None:
+ """Reset SO resource.
+
+ Clean SERVICE_INSTANCES dictionary
+ and A&AI mock url address.
+
+ """
+ global SERVICE_INSTANCES
+ SERVICE_INSTANCES = {}
+ cls.AAI_MOCK_URL = ""
+
+ def check_aai_mock_address(method: Callable) -> Callable:
+ """Decorate method to check if A&AI address is set.
+
+ If A&AI mock address is not set it returns 500 HTTP
+ response for resource's method
+
+ Args:
+ method (Callable): method to decorate
+
+ """
+
+ def decorator(self, *args, **kwargs):
+ if not self.AAI_MOCK_URL:
+ return "A&AI mock address not set", 500
+ return method(self, *args, **kwargs)
+
+ return decorator
+
+
+class ServiceInstance(SoResource):
+ """Service instance resource class."""
+
+ def delete(self, service_instance_id: str) -> Dict[str, Dict[str, str]]:
+ """Delete service instance.
+
+ Remove service instance data from SERVICE_INSTANCES
+ dictionary.
+
+ Args:
+ service_instance_id (str): Service instance id key value
+
+ Returns:
+ Dict[str, Dict[str, str]]: Deletion request dictionary
+
+ """
+ service_instance = SERVICE_INSTANCES[service_instance_id]
+ requests.delete(
+ (
+ f"{self.AAI_MOCK_URL}/aai/v16/business/customers/customer/"
+ f"{service_instance['customerId']}/service-subscriptions/service-subscription/"
+ f"{service_instance['serviceSubscriptionId']}/service-instances/service-instance/"
+ f"{service_instance_id}"
+ )
+ )
+ del SERVICE_INSTANCES[service_instance_id]
+ return {"requestReferences": {"requestId": str(uuid4())}}
+
+
+class ServiceInstanceList(SoResource):
+ """Service instances list resource."""
+
+ @SoResource.check_aai_mock_address
+ def post(self) -> Dict[str, Dict[str, str]]:
+ """Create service instance.
+
+ Create service instance data dictionary.
+ Call request to A&AI mock to create service instance there.
+
+ Returns:
+ Dict[str, Dict[str, str]]: Creation request dictionary
+
+ """
+ instance_id = str(uuid4())
+ request_data = request.get_json()
+ customer_id = request_data["requestDetails"]["subscriberInfo"][
+ "globalSubscriberId"
+ ]
+ service_subscription_id = request_data["requestDetails"]["requestParameters"][
+ "subscriptionServiceType"
+ ]
+ instance_name = request_data["requestDetails"]["requestInfo"]["instanceName"]
+ service_instance = {
+ "requestId": str(uuid4()),
+ "instanceId": instance_id,
+ "customerId": customer_id,
+ "serviceSubscriptionId": service_subscription_id,
+ "instanceName": instance_name,
+ }
+ requests.post(
+ (
+ f"{self.AAI_MOCK_URL}/aai/v16/business/customers/customer/{customer_id}/"
+ f"service-subscriptions/service-subscription/{service_subscription_id}/"
+ "service-instances"
+ ),
+ json={
+ "service-instance-name": instance_name,
+ "service-instance-id": instance_id,
+ },
+ )
+ SERVICE_INSTANCES[service_instance["instanceId"]] = service_instance
+ return {"requestReferences": service_instance}
+
+
+class VnfInstance(SoResource):
+ """Vnf instance resource."""
+
+ @SoResource.check_aai_mock_address
+ def delete(
+ self, service_instance_id: str, vnf_instance_id: str
+ ) -> Dict[str, Dict[str, str]]:
+ """Delete vnf instance.
+
+ Remove vnf instanca data from SERVICE_INSTANCES dictionary.
+ Call DELETE request to A&AI mock.
+
+ Args:
+ service_instance_id (str): Service instance id key value
+ vnf_instance_id (str): Vnf instance id key value
+
+ Returns:
+ Dict[str, Dict[str, str]]: Deletion request dictionary.
+
+ """
+ related_service = SERVICE_INSTANCES[service_instance_id]
+ requests.delete(
+ (
+ f"{self.AAI_MOCK_URL}/aai/v16/business/customers/customer/"
+ f"{related_service['customerId']}/service-subscriptions/service-subscription/"
+ f"{related_service['serviceSubscriptionId']}/service-instances/service-instance/"
+ f"{service_instance_id}/relationship-list"
+ )
+ )
+ return {"requestReferences": {"requestId": str(uuid4())}}
+
+
+class VnfInstanceList(SoResource):
+ """Vnf instances list resource."""
+
+ @SoResource.check_aai_mock_address
+ def post(self, service_instance_id: str) -> Dict[str, Dict[str, str]]:
+ """Create vnf instance.
+
+ Create vnf instance data dictionary.
+ Call request to A&AI mock to create vnf instance there.
+
+ Returns:
+ Dict[str, Dict[str, str]]: Creation request dictionary
+
+ """
+ instance_id = str(uuid4())
+ request_data = request.get_json()
+ related_instance_id = request_data["requestDetails"]["relatedInstanceList"][0][
+ "relatedInstance"
+ ]["instanceId"]
+ related_service = SERVICE_INSTANCES[related_instance_id]
+ requests.post(
+ (
+ f"{self.AAI_MOCK_URL}/aai/v16/business/customers/customer/{related_service['customerId']}/"
+ f"service-subscriptions/service-subscription/{related_service['serviceSubscriptionId']}/"
+ f"service-instances/service-instance/{related_instance_id}/relationship-list"
+ ),
+ json={
+ "related-to": "generic-vnf",
+ "related-link": f"/aai/v16/network/generic-vnfs/generic-vnf/{instance_id}",
+ },
+ )
+ return {
+ "requestReferences": {"requestId": str(uuid4()), "instanceId": instance_id}
+ }
+
+
+class VfModuleInstance(SoResource):
+ """Vf module instance resource class."""
+
+ @SoResource.check_aai_mock_address
+ def delete(
+ self, service_instance_id: str, vnf_instance_id: str, vf_module_instance_id: str
+ ) -> Dict[str, Dict[str, str]]:
+ """Delete vf module instance.
+
+ Call DELETE request to A&AI mock to delete vf module instance.
+
+ Args:
+ service_instance_id (str): Service instance id key value.
+ vnf_instance_id (str): Vnf instance id key value.
+ vf_module_instance_id (str): Vf module instance id key value.
+
+ Returns:
+ Dict[str, Dict[str, str]]: Deletion request dictionary
+
+ """
+ requests.delete(
+ (
+ f"{self.AAI_MOCK_URL}/aai/v16/network/generic-vnfs/generic-vnf/"
+ f"{vnf_instance_id}/vf-modules/{vf_module_instance_id}"
+ )
+ )
+ return {"requestReferences": {"requestId": str(uuid4())}}
+
+
+class VfModuleInstanceList(SoResource):
+ """Vf module instances list resource."""
+
+ @SoResource.check_aai_mock_address
+ def post(
+ self, service_instance_id: str, vnf_instance_id: str
+ ) -> Dict[str, Dict[str, str]]:
+ """Create vf module instance.
+
+ Call POST request to A&AI mock to create vf module instance.
+
+ Args:
+ service_instance_id (str): Service instance id key value
+ vnf_instance_id (str): Vnf instance id key value
+
+ Returns:
+ Dict[str, Dict[str, str]]: Creation request dictionary
+
+ """
+ instance_id = str(uuid4())
+ requests.post(
+ (
+ f"{self.AAI_MOCK_URL}/aai/v16/network/generic-vnfs/generic-vnf/"
+ f"{vnf_instance_id}/vf-modules"
+ ),
+ json={"vf-module-id": instance_id},
+ )
+ return {
+ "requestReferences": {"requestId": str(uuid4()), "instanceId": instance_id}
+ }
+
+
+class NetworkInstance(SoResource):
+ """Network instance resource."""
+
+ @SoResource.check_aai_mock_address
+ def delete(
+ self, service_instance_id: str, network_instance_id: str
+ ) -> Dict[str, Dict[str, str]]:
+ """Delete network instance.
+
+ Remove network instanca data from SERVICE_INSTANCES dictionary.
+ Call DELETE request to A&AI mock.
+
+ Args:
+ service_instance_id (str): Service instance id key value
+ network_instance_id (str): Network instance id key value
+
+ Returns:
+ Dict[str, Dict[str, str]]: Deletion request dictionary.
+
+ """
+ related_service = SERVICE_INSTANCES[service_instance_id]
+ requests.delete(
+ (
+ f"{self.AAI_MOCK_URL}/aai/v16/business/customers/customer/"
+ f"{related_service['customerId']}/service-subscriptions/service-subscription/"
+ f"{related_service['serviceSubscriptionId']}/service-instances/service-instance/"
+ f"{service_instance_id}/relationship-list"
+ )
+ )
+ return {"requestReferences": {"requestId": str(uuid4())}}
+
+
+class NetworkInstanceList(SoResource):
+ """Network instances list resource."""
+
+ @SoResource.check_aai_mock_address
+ def post(self, service_instance_id: str) -> Dict[str, Dict[str, str]]:
+ """Create network instance.
+
+ Create network instance data dictionary.
+ Call request to A&AI mock to create network instance there.
+
+ Returns:
+ Dict[str, Dict[str, str]]: Creation request dictionary
+
+ """
+ instance_id = str(uuid4())
+ request_data = request.get_json()
+ related_instance_id = request_data["requestDetails"]["relatedInstanceList"][0][
+ "relatedInstance"
+ ]["instanceId"]
+ related_service = SERVICE_INSTANCES[related_instance_id]
+ requests.post(
+ (
+ f"{self.AAI_MOCK_URL}/aai/v16/business/customers/customer/{related_service['customerId']}/"
+ f"service-subscriptions/service-subscription/{related_service['serviceSubscriptionId']}/"
+ f"service-instances/service-instance/{related_instance_id}/relationship-list"
+ ),
+ json={
+ "related-to": "l3-network",
+ "related-link": f"/aai/v16/network/l3-networks/l3-network/{instance_id}",
+ },
+ )
+ return {
+ "requestReferences": {"requestId": str(uuid4()), "instanceId": instance_id}
+ }
diff --git a/mock-ves/Dockerfile b/mock-ves/Dockerfile
new file mode 100644
index 0000000..32c530a
--- /dev/null
+++ b/mock-ves/Dockerfile
@@ -0,0 +1,17 @@
+FROM python:3.8-alpine
+
+COPY . /app
+WORKDIR /app
+
+# GCC for Alpine Linux in Docker
+RUN apk add build-base
+
+
+# Dependencies
+RUN pip install -r requirements.txt
+
+EXPOSE 30417
+
+ENTRYPOINT ["python"]
+
+CMD ["app/app.py"] \ No newline at end of file
diff --git a/mock-ves/README.md b/mock-ves/README.md
new file mode 100644
index 0000000..b75ea97
--- /dev/null
+++ b/mock-ves/README.md
@@ -0,0 +1,26 @@
+# mock-ves
+This is a simple ves mock created for ONAP integration tests.
+
+Build image
+===========
+To build ves-mock image you can simply run command:
+
+ ```
+docker build . -t mock-ves
+```
+
+Run image
+=========
+
+To run ves-mock image use below command:
+```
+docker run -d --net=host --name mock-ves mock-ves
+```
+
+Stop container
+==============
+To stop the container use:
+```
+docker rm -f mock-ves
+```
+
diff --git a/mock-ves/app/app.py b/mock-ves/app/app.py
new file mode 100644
index 0000000..acf1caa
--- /dev/null
+++ b/mock-ves/app/app.py
@@ -0,0 +1,84 @@
+"""
+ Copyright 2023 Deutsche Telekom AG, Nokia, Orange
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+"""
+import json
+import requests
+import logging as sys_logging
+from flask import Flask, logging, request
+
+FAULT_TOPIC = "fault"
+dmaap_url = ""
+
+app = Flask(__name__)
+sys_logging.basicConfig(level=sys_logging.DEBUG)
+logger = logging.create_logger(app)
+
+
+@app.route("/set_dmaap_address", methods=['POST'])
+def set_dmaap_address():
+ logger.debug(request.json)
+ global dmaap_url
+ dmaap_url = get_dmaap_mock_url()
+ return {}, 202
+
+
+@app.route("/eventListener/<version>", methods=['POST'])
+def event_sec_fault_output(version):
+ logger.debug(request.json)
+ event = json.dumps(request.json["event"]) \
+ .replace('\n', ' ') \
+ .__add__("\n")
+ send_event_to_dmaap(dmaap_url, event, FAULT_TOPIC)
+ return handle_new_event(version)
+
+
+@app.route("/eventListener/<version>/eventBatch", methods=['POST'])
+def event_sec_fault_output_batch(version):
+ logger.debug(request.json)
+ dmaap_mock_url = dmaap_url
+ event = prepare_event_list_for_dmaap()
+ send_event_to_dmaap(dmaap_mock_url, event, FAULT_TOPIC)
+ return handle_new_event(version)
+
+
+def send_event_to_dmaap(dmaap_mock_url, event, topic):
+ byte_event = change_from_str_to_byte_array(event)
+ requests.post("{}/events/{}".format(dmaap_mock_url, topic), data=byte_event)
+
+
+def handle_new_event(version):
+ return {}, 202
+
+
+def change_from_str_to_byte_array(event):
+ b = bytearray()
+ b.extend(event.encode())
+ return b
+
+
+def prepare_event_list_for_dmaap():
+ event_list = []
+ for event in request.json["eventList"]:
+ event_list.append(json.dumps(event).replace('\n', ' '))
+ event = "\n".join(event_list).__add__("\n")
+ return event
+
+
+def get_dmaap_mock_url():
+ return request.json["DMAAP_MOCK"]
+
+
+if __name__ == "__main__":
+ app.run(host='0.0.0.0', port=30417, debug=True)
diff --git a/mock-ves/cleanup-dev.sh b/mock-ves/cleanup-dev.sh
new file mode 100644
index 0000000..0cf27b3
--- /dev/null
+++ b/mock-ves/cleanup-dev.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+export APP_NAME=mock-ves
+
+docker rm -f ${APP_NAME}
+docker rmi ${APP_NAME}
+
diff --git a/mock-ves/requirements.txt b/mock-ves/requirements.txt
new file mode 100644
index 0000000..07da031
--- /dev/null
+++ b/mock-ves/requirements.txt
@@ -0,0 +1,2 @@
+Flask-RESTful==0.3.8
+requests[socks]==2.24.0 \ No newline at end of file
diff --git a/mock-ves/run-dev.sh b/mock-ves/run-dev.sh
new file mode 100644
index 0000000..5b50d95
--- /dev/null
+++ b/mock-ves/run-dev.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+export APP_NAME=mock-ves
+export DOCKER_PORT=30417
+export APP_PORT=30417
+
+docker build . -t $APP_NAME
+docker run -p $DOCKER_PORT:$APP_PORT --name $APP_NAME $APP_NAME