.. This work is licensed under a Creative Commons Attribution 4.0 International License.
.. http://creativecommons.org/licenses/by/4.0
-.. Copyright 2018 AT&T Intellectual Property. All rights reserved.
+.. Copyright 2019 AT&T Intellectual Property. All rights reserved.
Manual Heat Template Validation
===============================
If the assert statement fails, the failure is collected by ``pytest``, and the
associated requirements and error_message are included in the final report.
-Optional: Pytest Markers and Validation Profiles
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Optional: Pytest Markers and Validation Categories
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The VVP test suite has the concept of a ``base`` test. These are used as
sanity tests and are executed before the other tests, and if they fail the
@validates("R-123456")
def test_my_new_requirement():
-The VVP test suite also has the concept of a ``validation profile`` to
-define what set of tests to execute. The way it works is by using ``pytest``
-markers.
+The VVP test suite also has the concept of a ``category`` to
+define what additional set of optional tests to execute. The way it works
+is by using ``categories`` decorator.
-By default, all ``base`` tests and non-marked tests are executed. If you want
-an additional profile to run, pass the command line argument:
+By default, all ``base`` tests and tests with no category are executed.
+If you want an additional category to run, pass the command line argument:
-``--validation-profile=<my_validation_profile>``
+``--category=<category>``
This will execute all ``base`` tests, non-marked tests,
and tests marked like the following:
import pytest
- @pytest.mark.<my_validation_profile> # this is an additional pytest marker
+ @categories("<category>") # substitue <category> with the category name
@validates("R-123456")
def test_my_new_requirement():
This should be used sparingly, and in practice consider reviewing a requirement
-with the VNF Requirements team before adding a test to a validation profile.
+with the VNF Requirements team before adding a test to a category.
Self-Test Suite
~~~~~~~~~~~~~~~
# -*- coding: utf8 -*-
-# ============LICENSE_START=======================================================
+# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
----
-parameters:
- out: 2
- res: 3
- indexed: 4
- indx: 1
\ No newline at end of file
# -*- coding: utf8 -*-
-# ============LICENSE_START=======================================================
+# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
----
-parameters:
- out:
- type: string
- description: test for output
- res:
- type: string
- description: test for resources
- indexed:
- type: comma_delimited_list
- description: test for indexed param
- indx:
- type: number
- description: Index of the current instance
-resources:
- test:
- type: abc
- properties:
- test_res: {get_param: res}
- test_ind_param: { get_param: [ indexed, { get_param: indx } ] }
+from threading import Thread
-outputs:
- test_out:
- description: test getting output param
- value: {get_param: out}
\ No newline at end of file
+from vvp import ValidatorApp, VERSION
+
+
+def test_app_starts():
+ app = ValidatorApp()
+ assert "VNF Validation Tool" in app.title
+ assert VERSION in app.title
+ app_thread = Thread(target=app.start, args=())
+ app_thread.daemon = True
+ app.config.command_queue.put("SHUTDOWN")
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START====================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+from io import StringIO
+
+import pytest
+import yaml
+
+import vvp
+
+DEFAULT_CONFIG = """
+ui:
+ app-name: VNF Validation Tool
+categories:
+ - name: Environment File Compliance. (Required to Onboard)
+ category: environment_file
+ description:
+ Checks certain parameters are excluded from the .env file, per HOT Requirements.
+ Required for ASDC onboarding, not needed for manual Openstack testing.
+settings:
+ polling-freqency: 1000
+ default-verbosity: Standard
+"""
+
+
+# noinspection PyShadowingNames
+@pytest.fixture(scope="module")
+def config():
+ return vvp.Config(yaml.load(StringIO(DEFAULT_CONFIG)))
+
+
+def test_app_name(config):
+ assert "VNF Validation Tool" in config.app_name
+ assert vvp.VERSION in config.app_name
+
+
+def test_categories_names_length(config):
+ names = config.category_names
+ assert len(names) == 1
+ assert names[0] == "Environment File Compliance. (Required to Onboard)"
+
+
+def test_polling_frequency(config):
+ assert config.polling_frequency == 1000
+
+
+def test_get_category_when_other(config):
+ assert (
+ config.get_category("Environment File Compliance. (Required to Onboard)")
+ == "environment_file"
+ )
+
+
+def test_default_verbosity(config):
+ assert config.default_verbosity(vvp.ValidatorApp.VERBOSITY_LEVELS) == "More (-vv)"
+
+
+def test_queues(config):
+ assert config.log_queue.empty(), "Log should start empty"
+ config.log_file.write("Test")
+ assert config.log_queue.get() == "Test"
+
+ assert config.status_queue.empty(), "status should start empty"
+ config.status_queue.put((True, None))
+ assert config.status_queue.get() == (True, None)
+
+
+MISSING_CATEGORY_FIELD = """
+ui:
+ app-name: VNF Validation Tool
+categories:
+ - description: |
+ Runs all default validations that apply to all VNF packages
+ regardless of deployment environment
+settings:
+ polling-freqency: 1000
+"""
+
+
+def test_missing_category_fields():
+ settings = yaml.load(StringIO(MISSING_CATEGORY_FIELD))
+ with pytest.raises(RuntimeError) as e:
+ vvp.Config(settings)
+ assert "Missing: name" in str(e)
+
+
+def test_default_output_format(config):
+ assert config.default_report_format == "HTML"
+
+
+def test_output_formats(config):
+ for format in ["CSV", "HTML", "Excel"]:
+ assert format in config.report_formats
+
+
+def test_category_names(config):
+ assert "Environment File Compliance. (Required to Onboard)" in config.category_names
+
+
+def test_default_input_format(config):
+ assert "Directory (Uncompressed)" == config.default_input_format
+
+
+def test_input_formats(config):
+ assert "Directory (Uncompressed)" in config.input_formats
+ assert "ZIP File" in config.input_formats
# -*- coding: utf8 -*-
-# ============LICENSE_START=======================================================
+# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
----
-parameters:
- out:
- type: string
- description: test for output
- res:
- type: string
- description: test for resources
- indexed:
- type: comma_delimited_list
- description: test for indexed param
- indx:
- type: number
- description: Index of the current instance
- unused_yaml:
- type: number
- description: unused param in yaml file
-resources:
- test:
- type: abc
- properties:
- test_res: {get_param: res}
- test_ind_param: { get_param: [ indexed, { get_param: indx } ] }
-outputs:
- test_out:
- description: test getting output param
- value: {get_param: out}
\ No newline at end of file
+ui:
+ app-name: VNF Validation Tool
+categories:
+ - name: Environment File Compliance. (Required to Onboard)
+ category: environment_file
+ description:
+ Checks certain parameters are excluded from the .env file, per HOT Requirements.
+ Required for ASDC onboarding, not needed for manual Openstack testing.
+settings:
+ polling-freqency: 1000
+ default-verbosity: Standard
{
- "created": "2018-12-19T19:29:53.158345",
+ "created": "2019-01-25T23:15:47.976656",
"current_version": "dublin",
"project": "",
"versions": {
"needs_amount": 789
},
"dublin": {
- "created": "2018-12-19T19:29:53.158326",
+ "created": "2019-01-25T23:15:47.976584",
"needs": {
"R-00011": {
"description": "A VNF's Heat Orchestration Template's parameter defined\nin a nested YAML file\n**SHOULD NOT** have a parameter constraint defined.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-05257": {
"description": "A VNF's Heat Orchestration Template's **MUST NOT**\ncontain the Resource ``OS::Neutron::FloatingIP``.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-11200": {
"description": "A VNF's Cinder Volume Module, when it exists, **MUST** be 1:1\nwith a Base module or Incremental module.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-21511": {
"description": "A VNF's Heat Orchestration Template's use of ``{network-role}``\nin all Resource IDs **MUST** be the same case.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-21558": {
"description": "The VNF **SHOULD** use intelligent routing by having knowledge\nof multiple downstream/upstream endpoints that are exposed to it, to\nensure there is no dependency on external services (such as load balancers)\nto switch to alternate endpoints.",
"type_name": "Requirement",
"updated": "",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-43740": {
"description": "VNF's Heat Orchestration Template's Resource **MAY** declare the\nattribute ``deletion_policy:``.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-45719": {
"description": "The VNF **MUST**, if not integrated with the Operator's Identity and Access\nManagement system, or enforce a configurable \"terminate idle sessions\"\npolicy by terminating the session after a configurable period of inactivity.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-465236": {
"description": "The VNF **SHOULD** provide the capability of maintaining the integrity of\nits static files using a cryptographic method.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-48917": {
"description": "The VNF **MUST** monitor for and alert on (both sender and\nreceiver) errant, running longer than expected and missing file transfers,\nso as to minimize the impact due to file transfer errors.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-49036": {
"description": "The xNF **SHOULD** conform its YANG model to RFC 7277,\n\"A YANG Data Model for IP Management\".",
"introduced": "",
"is_need": true,
"is_part": false,
- "keyword": "MAY",
+ "keyword": "MUST",
"links": [],
"notes": "",
"parts": {},
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-52499": {
"description": "The VNF **MUST** meet their own resiliency goals and not rely\non the Network Cloud.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-54520": {
"description": "The VNF **MUST** log successful and unsuccessful authentication\nattempts, e.g., authentication associated with a transaction,\nauthentication to create a session, authentication to assume elevated\nprivilege.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-56385": {
"description": "The xNF **MUST** support APPC ``Audit`` command.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-57617": {
"description": "The VNF **MUST** include the field \"success/failure\" in the\nSecurity alarms (where applicable and technically feasible).",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-58670": {
"description": "The VNF's Heat Orchestration Template's Resource ``OS::Nova::Server``\nproperty\n``image`` parameter name **MUST** follow the naming convention\n``{vm-type}_image_name``.",
"type_name": "Requirement",
"updated": "",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-59568": {
"description": "The VNF's Heat Orchestration Template's Resource ``OS::Nova::Server``\nproperty\n``availability_zone`` parameter **MUST NOT** be enumerated in the Heat\nOrchestration\nTemplate's Environment File.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-61354": {
"description": "The VNF **MUST** provide a mechanism (e.g., access control list) to\npermit and/or restrict access to services on the VNF by source,\ndestination, protocol, and/or port.",
"introduced": "casablanca",
"is_need": true,
"is_part": false,
- "keyword": "MUST",
+ "keyword": "MAY",
"links": [],
"notes": "",
"parts": {},
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-67895": {
"description": "The VNFD provided by VNF vendor may use the below described TOSCA\ncapabilities. An on-boarding entity (ONAP SDC) **MUST** support them.\n\n **tosca.capabilities.nfv.VirtualBindable**\n\n A node type that includes the VirtualBindable capability indicates\n that it can be pointed by **tosca.relationships.nfv.VirtualBindsTo**\n relationship type.\n\n **tosca.capabilities.nfv.VirtualLinkable**\n\n A node type that includes the VirtualLinkable capability indicates\n that it can be pointed by **tosca.relationships.nfv.VirtualLinksTo**\n relationship.\n\n **tosca.capabilities.nfv.ExtVirtualLinkable**\n\n A node type that includes the ExtVirtualLinkable capability\n indicates that it can be pointed by\n **tosca.relationships.nfv.VirtualLinksTo** relationship.\n\n **Note**: This capability type is used in Casablanca how it does\n not exist in the last SOL001 draft\n\n **tosca.capabilities.nfv.VirtualCompute** and\n **tosca.capabilities.nfv.VirtualStorage** includes flavours of VDU",
"introduced": "",
"is_need": true,
"is_part": false,
- "keyword": "SHOULD",
+ "keyword": "MUST",
"links": [],
"notes": "",
"parts": {},
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-69431": {
"description": "The VNF's Heat Orchestration Template's Resource ``OS::Nova::Server``\nproperty\n``flavor`` parameter **MUST** be enumerated in the Heat Orchestration\nTemplate's Environment File and a value **MUST** be assigned.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-69610": {
"description": "The VNF **MUST** provide the capability of using X.509 certificates\nissued by an external Certificate Authority.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-71152": {
"description": "The VNF's Heat Orchestration Template's Resource ``OS::Nova::Server``\nproperty\n``image`` parameter **MUST** be declared as type: ``string``.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-82134": {
"description": "A VNF's Heat Orchestration Template's ``OS::Nova::Server`` resource property\n``metadata`` key/value pair ``vf_module_id`` parameter **MUST**\nbe declared as ``vf_module_id`` and the parameter **MUST**\nbe defined as type: ``string``.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-82732": {
"description": "A VNF Heat Orchestration Template's Cinder Volume Module **MUST**\nbe named identical to the base or incremental module it is supporting with\n``_volume`` appended.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-83790": {
"description": "The xNF **MUST** implement the ``:validate`` capability.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-84366": {
"description": "The xNF Package **MUST** include documentation describing\nxNF Functional APIs that are utilized to build network and\napplication services. This document describes the externally exposed\nfunctional inputs and outputs for the xNF, including interface\nformat and protocols supported.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-88536": {
"description": "A VNF's Heat Orchestration Template's OS::Nova::Server\nResource **SHOULD** contain the metadata map value parameter\n'environment_context'.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-96554": {
"description": "The xNF **MUST** implement the protocol operation:\n``unlock(target)`` - Unlock the configuration data store target.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-97102": {
"description": "The VNF Package **MUST** include VM requirements via a Heat\ntemplate that provides the necessary data for VM specifications\nfor all VNF components - for hypervisor, CPU, memory, storage.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-978752": {
"description": "The xNF providers **MUST** provide the Service Provider the following\nartifacts to support the delivery of high-volume xNF telemetry to\nDCAE via GPB over TLS/TCP:\n\n * A valid VES Event .proto definition file, to be used validate and\n decode an event\n * A valid high volume measurement .proto definition file, to be used for\n processing high volume events\n * A supporting PM content metadata file to be used by analytics\n applications to process high volume measurement events",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-981585": {
"description": "The pnfRegistration VES event periodicity **MUST** be configurable.\n\nNote: The PNF uses the service configuration request as a semaphore to\nstop sending the pnfRegistration sent. See the requirement PNP-5360\nrequirement.",
"type_name": "Requirement",
"updated": "casablanca",
"validated_by": "",
- "validation_mode": "static"
+ "validation_mode": "none"
},
"R-99798": {
"description": "A VNF's Heat Orchestration Template's Virtual Machine\n(i.e., ``OS::Nova::Server`` resource) **MAY** boot from an image or\n**MAY** boot from a Cinder Volume.",
--- /dev/null
+pyinstaller --onedir vvp.spec
\ No newline at end of file
import xlsxwriter
from six import string_types
+import version
+
__path__ = [os.path.dirname(os.path.abspath(__file__))]
DEFAULT_OUTPUT_DIR = "{}/../output".format(__path__[0])
msg = "!!Base Test Failure!! Halting test suite execution...\n{}".format(
result.error_message
)
- pytest.exit(
- "{}\n{}\n{}".format(msg, result.files, result.test_case)
- )
+ pytest.exit("{}\n{}\n{}".format(msg, result.files, result.test_case))
def make_timestamp():
"""
if not session.config.option.template_dir:
return
- template_path = os.path.abspath(session.config.option.template_dir[0])
- profile_name = session.config.option.validation_profile_name or ""
+
+ if session.config.option.template_source:
+ template_source = session.config.option.template_source[0]
+ else:
+ template_source = os.path.abspath(session.config.option.template_dir[0])
+
+ categories_selected = session.config.option.test_categories or ""
generate_report(
get_output_dir(session.config),
- template_path,
- profile_name,
+ template_source,
+ categories_selected,
session.config.option.report_format,
)
# noinspection PyUnusedLocal
def pytest_collection_modifyitems(session, config, items):
"""
- Selects tests based on the validation profile requested. Tests without
- pytest markers will always be executed.
+ Selects tests based on the categories requested. Tests without
+ categories will always be executed.
"""
- allowed_marks = ["xfail", "base"]
- profile = config.option.validation_profile
-
- for item in items:
- markers = set(m.name for m in item.iter_markers())
- if not profile and markers and set(markers).isdisjoint(allowed_marks):
- item.add_marker(
- pytest.mark.skip(
- reason="No validation profile selected. "
- "Skipping tests with marks."
- )
- )
- if (
- profile
- and markers
- and profile not in markers
- and set(markers).isdisjoint(allowed_marks)
- ):
- item.add_marker(
- pytest.mark.skip(reason="Doesn't match selection " "validation profile")
- )
-
+ config.traceability_items = list(items) # save all items for traceability
+ if not config.option.self_test:
+ for item in items:
+ # checking if test belongs to a category
+ if hasattr(item.function, "categories"):
+ if config.option.test_categories:
+ test_categories = getattr(item.function, "categories")
+ passed_categories = config.option.test_categories
+ if not all(
+ category in passed_categories for category in test_categories
+ ):
+ item.add_marker(
+ pytest.mark.skip(
+ reason="Test categories do not match all the passed categories"
+ )
+ )
+ else:
+ item.add_marker(
+ pytest.mark.skip(
+ reason="Test belongs to a category but no categories were passed"
+ )
+ )
items.sort(
- key=lambda i: 0 if "base" in set(m.name for m in i.iter_markers()) else 1
+ key=lambda item: 0 if "base" in set(m.name for m in item.iter_markers()) else 1
)
return json.loads(f.read())
-def generate_report(outpath, template_path, profile_name, output_format="html"):
+def generate_report(outpath, template_path, categories, output_format="html"):
"""
Generates the various output reports.
:param outpath: destination directory for all reports
:param template_path: directory containing the Heat templates validated
- :param profile_name: Optional validation profile selected
+ :param categories: Optional categories selected
:param output_format: One of "html", "excel", or "csv". Default is "html"
:raises: ValueError if requested output format is unknown
"""
generate_failure_file(outpath)
output_format = output_format.lower().strip() if output_format else "html"
if output_format == "html":
- generate_html_report(outpath, profile_name, template_path, failures)
+ generate_html_report(outpath, categories, template_path, failures)
elif output_format == "excel":
- generate_excel_report(outpath, profile_name, template_path, failures)
+ generate_excel_report(outpath, categories, template_path, failures)
elif output_format == "json":
- generate_json(outpath, template_path, profile_name)
+ generate_json(outpath, template_path, categories)
elif output_format == "csv":
- generate_csv_report(outpath, profile_name, template_path, failures)
+ generate_csv_report(outpath, categories, template_path, failures)
else:
raise ValueError("Unsupported output format: " + output_format)
write_json(data, failure_path)
-def generate_csv_report(output_dir, profile_name, template_path, failures):
+def generate_csv_report(output_dir, categories, template_path, failures):
rows = [["Validation Failures"]]
headers = [
- ("Profile Selected:", profile_name),
+ ("Categories Selected:", categories),
+ ("Tool Version:", version.VERSION),
("Report Generated At:", make_timestamp()),
("Directory Validated:", template_path),
("Checksum:", hash_directory(template_path)),
writer.writerow(row)
-def generate_excel_report(output_dir, profile_name, template_path, failures):
+def generate_excel_report(output_dir, categories, template_path, failures):
output_path = os.path.join(output_dir, "report.xlsx")
workbook = xlsxwriter.Workbook(output_path)
bold = workbook.add_format({"bold": True})
worksheet.write(0, 0, "Validation Failures", heading)
headers = [
- ("Profile Selected:", profile_name),
+ ("Categories Selected:", ",".join(categories)),
+ ("Tool Version:", version.VERSION),
("Report Generated At:", make_timestamp()),
("Directory Validated:", template_path),
("Checksum:", hash_directory(template_path)),
else:
pytest.warns(
"Unexpected error aggregating outcomes ({}) for requirement {}".format(
- outcomes, r_id)
+ outcomes, r_id
+ )
)
return "ERROR"
r_id is None, then it collects all errors that occur on failures and
results that are not mapped to requirements
"""
+
def selector(item):
if r_id:
return r_id in req_ids(item)
else:
return not req_ids(item)
- errors = (error(x) for x in chain(collection_failures, test_result)
- if selector(x))
+ errors = (error(x) for x in chain(collection_failures, test_result) if selector(x))
return [e for e in errors if e]
-def generate_json(outpath, template_path, profile_name):
+def generate_json(outpath, template_path, categories):
"""
Creates a JSON summary of the entire test run.
"""
"template_directory": template_path,
"timestamp": make_iso_timestamp(),
"checksum": hash_directory(template_path),
- "profile": profile_name,
+ "categories": categories,
"outcome": aggregate_run_results(COLLECTION_FAILURES, ALL_RESULTS),
"tests": [],
"requirements": [],
"text": r_data["description"],
"keyword": r_data["keyword"],
"result": result,
- "errors": collect_errors(r_id, COLLECTION_FAILURES, ALL_RESULTS)
+ "errors": collect_errors(r_id, COLLECTION_FAILURES, ALL_RESULTS),
}
)
# If there are tests that aren't mapped to a requirement, then we'll
"id": "Unmapped",
"text": "Tests not mapped to requirements (see tests)",
"result": aggregate_results(has_errors, unmapped_outcomes),
- "errors": collect_errors(None, COLLECTION_FAILURES, ALL_RESULTS)
+ "errors": collect_errors(None, COLLECTION_FAILURES, ALL_RESULTS),
}
)
write_json(data, report_path)
-def generate_html_report(outpath, profile_name, template_path, failures):
+def generate_html_report(outpath, categories, template_path, failures):
reqs = load_current_requirements()
resolutions = load_resolutions_file()
fail_data = []
with open(j2_template_path, "r") as f:
report_template = jinja2.Template(f.read())
contents = report_template.render(
+ version=version.VERSION,
num_failures=len(failures) + len(COLLECTION_FAILURES),
- profile_name=profile_name,
+ categories=categories,
template_dir=make_href(template_path),
checksum=hash_directory(template_path),
timestamp=make_timestamp(),
help="Directory which holds the templates for validation",
)
+ parser.addoption(
+ "--template-source",
+ dest="template_source",
+ action="append",
+ help="Source Directory which holds the templates for validation",
+ )
+
parser.addoption(
"--self-test",
dest="self_test",
help="Test the unit tests against their fixtured data",
)
- parser.addoption(
- "--validation-profile",
- dest="validation_profile",
- action="store",
- help="Runs all unmarked tests plus test with a matching marker",
- )
-
- parser.addoption(
- "--validation-profile-name",
- dest="validation_profile_name",
- action="store",
- help="Friendly name of the validation profile used in reports",
- )
-
parser.addoption(
"--report-format",
dest="report_format",
dest="output_dir",
action="store",
default=None,
- help="Alternate "
+ help="Alternate ",
+ )
+
+ parser.addoption(
+ "--category",
+ dest="test_categories",
+ action="append",
+ help="optional category of test to execute",
)
writer.writerow(row)
+def parse_heat_requirements(reqs):
+ """Takes requirements and returns list of only Heat requirements"""
+ data = json.loads(reqs)
+ for key, values in list(data.items()):
+ if "Heat" in (values["docname"]):
+ if "MUST" not in (values["keyword"]):
+ del data[key]
+ else:
+ if "none" in (values["validation_mode"]):
+ del data[key]
+ else:
+ del data[key]
+ return data
+
+
# noinspection PyUnusedLocal
def pytest_report_collectionfinish(config, startdir, items):
"""Generates a simple traceability report to output/traceability.csv"""
output_dir = os.path.split(traceability_path)[0]
if not os.path.exists(output_dir):
os.makedirs(output_dir)
- requirements = load_current_requirements()
+ reqs = load_current_requirements()
+ reqs = json.dumps(reqs)
+ requirements = parse_heat_requirements(reqs)
unmapped, mapped = partition(
lambda i: hasattr(i.function, "requirement_ids"), items
)
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2015-04-30
description: fdsafsfsa
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2015-04-30
description: fdsafsfsa
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
parameters:
test123: nsdafjk
bad: ndfaskl
\ No newline at end of file
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
parameters:
test123:
type: string
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
parameters:
test123: nsdafjk
\ No newline at end of file
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
parameters:
test123:
type: string
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2015-04-30
description: fdsafsfsa
parameters:
+ my_nested_parameter:
+ type: number
+ description: sdfnklafd
+ STARKDB_image_name:
+ type: number
+ description: sdfnklafd
+ STARKDB_name:
+ type: number
+ description: sdfnklafd
my_nested_parameter:
type: number
description: sdfnklafd
resources:
+ STARKDB_server_2:
+ type: OS::Nova::Server
+ properties:
+ image: { get_param: STARKDB_image_name }
+ flavor: { get_param: STARKDB_flavor_dvdfg }
+ name: { get_param: STARKDB_name }
+ availability_zone: { get_param: availability_zone_0 }
+
my_nested_resource2:
type: test
properties:
- my_nested_parameter: {get_param: my_nested_parameter}
+ name: { get_param: asfasf }
+
+ STARKDB_2_crazy_port_2:
+ type: OS::Neutron::Port
+ properties:
+ network: { get_param: crazy_net_id }
+ fixed_ips:
+ - subnet: { get_param: crazy_subnet_id }
+ - ip_address: { get_param: STARKDB_crazy_ip_0 }
+ allowed_address_pairs: [ { "ip_address": {get_param:
+ STARKDB_crazy_floating_ip}}]
+
+ int_private_net_id:
+ type: OS::Neutron::Net
+ properties:
+ name: { get_param: int_priv_net_id }
+
+ STARKDB_0_int_priv_port_0:
+ type: OS::Neutron::Port
+ properties:
+ network: { get_resource: int_private_net_id }
+ fixed_ips:
+ - subnet: { get_resource: int_priv_subnet }
+ - ip_address: { get_param: STARKDB_int_private_v6_ips }
+
+ myrouteprefix:
+ type: OS::ContrailV2::InterfaceRouteTable
+ properties:
+ name:
+ str_replace:
+ template: VNF_NAME_interface_route_table
+ params:
+ VNF_NAME: { get_param: vnf_name }
+ interface_route_table_routes:
+ interface_route_table_routes_route: { get_param: fw_oam_route_prefixes }
+ test: safd
+
+ stark_rg:
+ type: OS::Heat::ResourceGroup
+ properties:
+ count: { get_param: stark_rg_count }
+ resource_def:
+ type: STARKDB-nested.yaml
+ properties:
+ my_nested_parameter: 4
outputs:
test_value:
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
parameters:
fw_oam_route_prefixes: nsaflj
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2015-04-30
description: fdsafsfsa
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2015-04-30
description: fdsafsfsa
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
parameters:
#fw_oam_route_prefixes: nsaflj
#TESTDB_name: bghbhjb
- TESTDB_avail_hosts: test
+ #TESTDB_avail_hosts: test
TESTDB_image_name: sadfadf
param_X: sadnfklsadnfl
- priv_net_id: 123214
+ #priv_net_id: 123214
#priv_sub2net_id: 123123
#STARKDB_crazy_floating_ip: safd
- crazy_net_id: safd
+ #crazy_net_id: safd
#crazy_subnet_id: asfd
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2015-04-30
description: fdsafsfsa
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START====================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+# VERSION = '1.0.0'
+
+---
+resources:
+ testvm_server_0:
+ type: OS::Nova::Server
+ properties:
+ name: { get_param: testvm_name_0 }
+ flavor: { get_param: testvm_flavor_name}
+ image: { get_param: testvm_image_name}
+
+ nested_resource:
+ type: testvm.yaml
+ properties:
+ param1: abc
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
---
resources:
- testvm_server_0:
+ testvm_server_1:
type: OS::Nova::Server
properties:
name: { get_param: testvm_name_0 }
flavor: { get_param: testvm_flavor_name}
- image: { get_param: testvm_image_name}
-
+ image: { get_param: testvm_image_name}
\ No newline at end of file
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
server_0:
type: nested_template_1.yaml
properties:
- name: { get_param: server_name_0 }
+ name: { get_param: name }
my_resource_group_1:
type: OS::Heat::ResourceGroup
properties:
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2015-04-30
description: fdsafsfsa
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2015-04-30
description: fdsafsfsa
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
echo "test"
\ No newline at end of file
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2015-04-30
description: fdsafsfsa
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
echo "test"
\ No newline at end of file
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2015-04-30
description: fdsafsfsa
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
test=one
\ No newline at end of file
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
vm_typeX_0_bialy_port_2:
type: OS::Neutron::Port
properties:
- name: mynameistrouble
+ name:
+ str_replace:
+ template: mynameisstilltrouble
+ param:
+ still: safnlk
network: { get_param: int_intranet_net_name }
fixed_ips:
- ip_address: { get_param: lb_1_int_intranet_floating_ip }
type: OS::Neutron::Port
properties:
name:
- str_replace: mynameisstilltrouble
+ str_replace:
+ template: mynameisstilltrouble
+ param:
+ still: safnlk
network: { get_param: int_intranet_net_id }
fixed_ips:
- ip_address: { get_param: lb_2_int_intranet_floating_v6_ip }
vm_typeX_2_bialy_port_2:
type: OS::Neutron::Port
properties:
+ name: ansdjlf
network: { get_param: extnet_net_name }
fixed_ips:
- ip_address: { get_param: lb_1_extnet_floating_ip }
+++ /dev/null
-# -*- coding: utf8 -*-
-# ============LICENSE_START====================================================
-# org.onap.vvp/validation-scripts
-# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
-# ===================================================================
-#
-# Unless otherwise specified, all software contained herein is licensed
-# under the Apache License, Version 2.0 (the "License");
-# you may not use this software 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.
-#
-#
-#
-# Unless otherwise specified, all documentation contained herein is licensed
-# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
-# you may not use this documentation except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://creativecommons.org/licenses/by/4.0/
-#
-# Unless required by applicable law or agreed to in writing, documentation
-# 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.
-#
-# ============LICENSE_END============================================
-#
-# ECOMP is a trademark and service mark of AT&T Intellectual Property.
-#
-# VERSION: '1.0.0'
-
----
-parameters:
-
- vm_typeX_bialy_vlan_filter:
- type: comma_delimited_list
- vm_typeX_bialy_public_vlans:
- type: comma_delimited_list
- vm_typeX_bialy_private_vlans:
- type: comma_delimited_list
- vm_typeX_bialy_guest_vlans:
- type: comma_delimited_list
-
-resources:
-
- vm_typeX_0_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- name:
- str_replace:
- template:
- params: mynameisstilltrouble
- network: { get_param: int_intranet_net_name }
- fixed_ips:
- - ip_address: { get_param: lb_1_int_intranet_floating_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: SR-IOV_Trunk
-
- vm_typeX_1_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- name:
- str_replace: {}
- network: { get_param: int_intranet_net_id }
- fixed_ips:
- - ip_address: { get_param: lb_2_int_intranet_floating_v6_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: SR-IOV_Non_Trunk
-
- vm_typeX_2_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- network: { get_param: extnet_net_name }
- fixed_ips:
- - ip_address: { get_param: lb_1_extnet_floating_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: OVS
-
- vm_typeX_3_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- network: { get_param: extnet_net_id }
- fixed_ips:
- - ip_address: { get_param: lb_2_extnet_floating_v6_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: SR-IOV_Mirrored_Trunk
-
+++ /dev/null
-# -*- coding: utf8 -*-
-# ============LICENSE_START====================================================
-# org.onap.vvp/validation-scripts
-# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
-# ===================================================================
-#
-# Unless otherwise specified, all software contained herein is licensed
-# under the Apache License, Version 2.0 (the "License");
-# you may not use this software 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.
-#
-#
-#
-# Unless otherwise specified, all documentation contained herein is licensed
-# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
-# you may not use this documentation except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://creativecommons.org/licenses/by/4.0/
-#
-# Unless required by applicable law or agreed to in writing, documentation
-# 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.
-#
-# ============LICENSE_END============================================
-#
-# ECOMP is a trademark and service mark of AT&T Intellectual Property.
-#
-# VERSION: '1.0.0'
-
----
-parameters:
-
- vm_typeX_bialy_vlan_filter:
- type: comma_delimited_list
- vm_typeX_bialy_public_vlans:
- type: comma_delimited_list
- vm_typeX_bialy_private_vlans:
- type: comma_delimited_list
- vm_typeX_bialy_guest_vlans:
- type: comma_delimited_list
-
-resources:
-
- vm_typeX_0_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- name:
- str_replace:
- template:
- params:
- mynameisstillbad: foozle
- network: { get_param: int_intranet_net_name }
- fixed_ips:
- - ip_address: { get_param: lb_1_int_intranet_floating_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: SR-IOV_Trunk
-
- vm_typeX_1_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- name:
- str_replace:
- template:
- params:
- mynameisstilltrouble:
- network: { get_param: int_intranet_net_id }
- fixed_ips:
- - ip_address: { get_param: lb_2_int_intranet_floating_v6_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: SR-IOV_Non_Trunk
-
- vm_typeX_2_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- network: { get_param: extnet_net_name }
- fixed_ips:
- - ip_address: { get_param: lb_1_extnet_floating_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: OVS
-
- vm_typeX_3_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- network: { get_param: extnet_net_id }
- fixed_ips:
- - ip_address: { get_param: lb_2_extnet_floating_v6_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: SR-IOV_Mirrored_Trunk
-
+++ /dev/null
-# -*- coding: utf8 -*-
-# ============LICENSE_START====================================================
-# org.onap.vvp/validation-scripts
-# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
-# ===================================================================
-#
-# Unless otherwise specified, all software contained herein is licensed
-# under the Apache License, Version 2.0 (the "License");
-# you may not use this software 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.
-#
-#
-#
-# Unless otherwise specified, all documentation contained herein is licensed
-# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
-# you may not use this documentation except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://creativecommons.org/licenses/by/4.0/
-#
-# Unless required by applicable law or agreed to in writing, documentation
-# 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.
-#
-# ============LICENSE_END============================================
-#
-# ECOMP is a trademark and service mark of AT&T Intellectual Property.
-#
-# VERSION: '1.0.0'
-
----
-parameters:
-
- vm_typeX_bialy_vlan_filter:
- type: comma_delimited_list
- vm_typeX_bialy_public_vlans:
- type: comma_delimited_list
- vm_typeX_bialy_private_vlans:
- type: comma_delimited_list
- vm_typeX_bialy_guest_vlans:
- type: comma_delimited_list
-
-resources:
-
- vm_typeX_0_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- name:
- str_replace:
- template:
- params:
- mynameisstillbad:
- get_param: foozle
- network: { get_param: int_intranet_net_name }
- fixed_ips:
- - ip_address: { get_param: lb_1_int_intranet_floating_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: SR-IOV_Trunk
-
- vm_typeX_1_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- name:
- str_replace:
- template:
- params:
- mynameisstilltrouble:
- get_param:
- network: { get_param: int_intranet_net_id }
- fixed_ips:
- - ip_address: { get_param: lb_2_int_intranet_floating_v6_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: SR-IOV_Non_Trunk
-
- vm_typeX_2_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- network: { get_param: extnet_net_name }
- fixed_ips:
- - ip_address: { get_param: lb_1_extnet_floating_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: OVS
-
- vm_typeX_3_bialy_port_2:
- type: OS::Neutron::Port
- properties:
- network: { get_param: extnet_net_id }
- fixed_ips:
- - ip_address: { get_param: lb_2_extnet_floating_v6_ip }
- binding:vnic_type: direct
- value_specs:
- vlan_filter: {get_param: vm_typeX_bialy_vlan_filter}
- public_vlans: {get_param: vm_typeX_bialy_public_vlans}
- private_vlans: {get_param: vm_typeX_bialy_private_vlans}
- guest_vlans: {get_param: vm_typeX_bialy_guest_vlans}
- vlan_mirror:
- ATT_FABRIC_CONFIGURATION_REQUIRED: true
- metadata:
- port_type: SR-IOV_Mirrored_Trunk
-
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
-# VERSION: '1.0.0'
+# VERSION: '1.2.0'
---
parameters:
properties:
name:
str_replace:
- template: mynameisok_port2
+ template: mynameisok_myindex
params:
mynameisok:
get_param: vnf_name
+ myindex:
+ get_param: 0
network: { get_param: int_intranet_net_name }
fixed_ips:
- ip_address: { get_param: lb_1_int_intranet_floating_ip }
properties:
name:
str_replace:
- template: mynameisok_port2
+ template: mynameisok_myindex
params:
mynameisok:
get_param: vnf_name
+ myindex:
+ get_param: 1
network: { get_param: int_intranet_net_id }
fixed_ips:
- ip_address: { get_param: lb_2_int_intranet_floating_v6_ip }
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+outputs:
+ oam_management_v6_address:
+ description: OAM management address
+ value: {get_param: oam_address}
+
+ oam_management_v4_address:
+ description: OAM management address
+ value: {get_param: oam_address}
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+outputs:
+ oam_management_v4_address:
+ description: OAM management address
+ value: {get_param: oam_address}
+
+ oam_management_v6_address:
+ description: OAM management address
+ value: {get_param: oam_address}
\ No newline at end of file
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+outputs:
+ oam_management_v6_address:
+ description: OAM management address
+ value: {get_param: oam_address}
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+outputs:
+ oam_management_v4_address:
+ description: OAM management address
+ value: {get_param: oam_address}
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2014-10-16
resources:
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
heat_template_version: 2014-10-16
resources:
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START====================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+
+resources:
+ sf_server_0:
+ type: OS::Nova::Server
+ properties:
+ networks:
+ - port: {get_resource: sf_1_int_di_port_2}
+ - port: {get_resource: sf_2_int_icsr_port_0}
+ - port: {get_resource: sf_3_gn_vmi_port_0}
+ - port: {get_resource: sf_4_cor_vmi_port_1}
+ - port: {get_resource: sf_5_rad_vmi_port_2}
+ - port: {get_resource: sf_6_calea_vmi_3}
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START====================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+
+resources:
+ sf_server_0:
+ type: OS::Nova::Server
+ properties:
+ networks:
+ - port: {get_resource: sf_0_int_di_port_2}
+ - port: {get_resource: sf_0_int_icsr_port_0}
+ - port: {get_resource: sf_0_gn_vmi_0}
+ - port: {get_resource: sf_0_cor_vmi_1}
+ - port: {get_resource: sf_0_rad_vmi_2}
+ - port: {get_resource: sf_0_calea_vmi_3}
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+parameters:
+ vm_role:
+ type: string
+
+resources:
+ dns_server_0:
+ type: OS::Nova::Server
+ properties:
+ metadata:
+ vm_role: {get_param: vm_role}
+ networks:
+ - port: { get_resource: dns_0_oam_port_0 }
+
+ dns_server_1:
+ type: OS::Nova::Server
+ properties:
+ metadata:
+ vm_role: {get_param: vm_role}
+ networks:
+ - port: { get_resource: dns_1_oam_port_0 }
+
+ dns_0_oam_port_0:
+ type: OS::Neutron::Port
+
+ dns_1_oam_port_0:
+ type: OS::Neutron::Port
+
+ cinder_attach_0:
+ type: OS::Cinder::VolumeAttachment
+ properties:
+ volume_id: 1234
+ instance_uuid: { get_resource: dns_server_0 }
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+parameters:
+ vm_role:
+ type: string
+
+resources:
+ dns_server_0:
+ type: OS::Nova::Server
+ properties:
+ metadata:
+ vm_role: {get_param: vm_role}
+ networks:
+ - port: { get_resource: dns_0_oam_port_0 }
+
+ dns_server_1:
+ type: OS::Nova::Server
+ properties:
+ metadata:
+ vm_role: {get_param: vm_role}
+ networks:
+ - port: { get_resource: dns_1_oam_port_0 }
+
+ dns_0_oam_port_0:
+ type: OS::Neutron::Port
+
+ dns_1_oam_port_0:
+ type: OS::Neutron::Port
+
+ cinder_attach_0:
+ type: OS::Cinder::VolumeAttachment
+ properties:
+ volume_id: 1234
+ instance_uuid: { get_resource: dns_server_0 }
+
+ cinder_attach_1:
+ type: OS::Cinder::VolumeAttachment
+ properties:
+ volume_id: 1234
+ instance_uuid: { get_resource: dns_server_1 }
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+parameters:
+ vm_role: dns$1
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+parameters:
+ vm_role:
+ type: string
+
+resources:
+ dns_server_0:
+ type: OS::Nova::Server
+ properties:
+ metadata:
+ vm_role: dns$1
+
+ dns_server_1:
+ type: OS::Nova::Server
+ properties:
+ metadata:
+ vm_role: {get_param: vm_role}
\ No newline at end of file
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+resources:
+ dns_server_0:
+ type: OS::Nova::Server
+ properties:
+ metadata:
+ vm_role: dns
\ No newline at end of file
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+parameters:
+ vm_role: dns
\ No newline at end of file
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+
+parameters:
+ vm_role:
+ type: string
+
+resources:
+ dns_server_0:
+ type: OS::Nova::Server
+ properties:
+ metadata:
+ vm_role: {get_param: vm_role}
\ No newline at end of file
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
return decorator
+def categories(*categories):
+ def decorator(func):
+ @funcutils.wraps(func)
+ def wrapper(*args, **kw):
+ return func(*args, **kw)
+
+ wrapper.categories = categories
+ return wrapper
+
+ decorator.categories = categories
+ return decorator
+
+
def get_environment_pair(heat_template):
"""Returns a yaml/env pair given a yaml file"""
base_dir, filename = os.path.split(heat_template)
return None
+def find_environment_file(yaml_files):
+ """
+ Pass file and recursively step backwards until environment file is found
+
+ :param yaml_files: list or string, start at size 1 and grows recursively
+ :return: corresponding environment file for a file, or None
+ """
+ # sanitize
+ if isinstance(yaml_files, str):
+ yaml_files = [yaml_files]
+
+ yaml_file = yaml_files[-1]
+ filepath, filename = os.path.split(yaml_file)
+
+ environment_pair = get_environment_pair(yaml_file)
+ if environment_pair:
+ return environment_pair
+
+ for file in os.listdir(filepath):
+ fq_name = "{}/{}".format(filepath, file)
+ if fq_name.endswith("yaml") or fq_name.endswith("yml"):
+ if fq_name not in yaml_files:
+ with open(fq_name) as f:
+ yml = yaml.load(f)
+ resources = yml.get("resources", {})
+ for resource_id, resource in resources.items():
+ resource_type = resource.get("type", "")
+ if resource_type == "OS::Heat::ResourceGroup":
+ resource_type = (
+ resource.get("properties", {})
+ .get("resource_def", {})
+ .get("type", "")
+ )
+ # found called nested file
+ if resource_type == filename:
+ yaml_files.append(fq_name)
+ environment_pair = find_environment_file(yaml_files)
+
+ return environment_pair
+
+
def load_yaml(yaml_file):
"""
Load the YAML file at the given path. If the file has previously been
{## ============LICENSE_START=======================================================#}
{## org.onap.vvp/validation-scripts#}
{## ===================================================================#}
-{## Copyright © 2018 AT&T Intellectual Property. All rights reserved.#}
+{## Copyright © 2019 AT&T Intellectual Property. All rights reserved.#}
{## ===================================================================#}
{###}
{## Unless otherwise specified, all software contained herein is licensed#}
<div class="callout {{ "alert" if failures or collection_failures else "success" }}">
<h1>Validation Report</h1>
<ul>
- <li><b>Profile:</b> {{ profile_name }}</li>
+ <li><b>Categories:</b> {{ categories }}</li>
<li><b>Tool Version:</b> {{ version }}</li>
<li><b>Directory Validated:</b> {{ template_dir }}</li>
<li><b>Checksum:</b> {{ checksum }}</li>
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ============LICENSE_END============================================
#
-
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
"""structures
"""
-import sys
-
-
import collections
import inspect
import os
import re
+import sys
from tests import cached_yaml as yaml
from tests.helpers import load_yaml
-
from .utils import nested_dict
-VERSION = "3.5.0"
+VERSION = "4.2.0"
# key = pattern, value = regex compiled from pattern
_REGEX_CACHE = {}
return regex
-class HeatObject(object):
- """base class for xxxx::xxxx::xxxx objects
+class Hashabledict(dict):
+ """A hashable dict.
+ dicts with the same keys and whose keys have the same values
+ are assigned the same hash.
"""
- resource_type = None
+ def __hash__(self):
+ return hash((frozenset(self), frozenset(self.values())))
+
+
+class HeatProcessor(object):
+ """base class for xxxx::xxxx::xxxx processors
+ """
- def __init__(self):
- self.re_rids = self.get_re_rids()
+ resource_type = None # string 'xxxx::xxxx::xxxx'
+ re_rids = collections.OrderedDict() # OrderedDict of name: regex
+ # name is a string to name the regex.
+ # regex parses the proper resource id format.
@staticmethod
- def get_re_rids():
- """Return OrderedDict of name: regex
- Each regex parses the proper format for a given rid
- (resource id).
+ def get_param_value(value):
+ """Return get_param value of `value`
"""
- return collections.OrderedDict()
+ if isinstance(value, dict) and len(value) == 1:
+ v = value.get("get_param")
+ if isinstance(v, list) and v:
+ v = v[0]
+ else:
+ v = None
+ return v
- def get_rid_match_tuple(self, rid):
+ @classmethod
+ def get_resource_or_param_value(cls, value):
+ """Return the get_resource or get_param value of `value`
+ """
+ if isinstance(value, dict) and len(value) == 1:
+ v = value.get("get_resource") or cls.get_param_value(value)
+ else:
+ v = None
+ return v
+
+ @classmethod
+ def get_rid_match_tuple(cls, rid):
"""find the first regex matching `rid` and return the tuple
(name, match object) or ('', None) if no match.
"""
- for name, regex in self.re_rids.items():
+ rid = "" if rid is None else rid
+ for name, regex in cls.re_rids.items():
match = regex.match(rid)
if match:
return name, match
return "", None
- def get_rid_patterns(self):
+ @classmethod
+ def get_rid_patterns(cls):
"""Return OrderedDict of name: friendly regex.pattern
"friendly" means the group notation is replaced with
braces, and the trailing "$" is removed.
"""
friendly_pattern = _get_regex(r"\(\?P<(.*?)>.*?\)")
rid_patterns = collections.OrderedDict()
- for name, regex in self.re_rids.items():
+ for name, regex in cls.re_rids.items():
rid_patterns[name] = friendly_pattern.sub(
r"{\1}", regex.pattern # replace groups with braces
)[
] # remove trailing $
return rid_patterns
+ @classmethod
+ def get_str_replace_name(cls, resource_dict):
+ """Return the name modified by str_replace of `resource_dict`,
+ a resource (i.e. a value in some template's resources).
+ Return None, if there is no name, str_replace, its template,
+ or any missing parameters.
+ """
+ str_replace = Heat.nested_get(
+ resource_dict, "properties", "name", "str_replace"
+ )
+ if not str_replace:
+ return None
+ template = Heat.nested_get(str_replace, "template")
+ if not isinstance(template, str):
+ return None
+ params = Heat.nested_get(str_replace, "params", default={})
+ if not isinstance(params, dict):
+ return None
+ # WARNING
+ # The user must choose non-overlapping keys for params since they
+ # are replaced in the template in arbitrary order.
+ name = template
+ for key, value in params.items():
+ param = cls.get_param_value(value)
+ if param is None:
+ return None
+ name = name.replace(key, str(param))
+ return name
+
+
+class CinderVolumeAttachmentProcessor(HeatProcessor):
+ """ Cinder VolumeAttachment
+ """
-class ContrailV2NetworkHeatObject(HeatObject):
+ resource_type = "OS::Cinder::VolumeAttachment"
+
+ @classmethod
+ def get_config(cls, resources):
+ """Return a tuple (va_config, va_count)
+ va_config - Hashabledict of Cinder Volume Attachment config
+ indexed by rid.
+ va_count - dict of attachment counts indexed by rid.
+ """
+ va_count = collections.defaultdict(int)
+ va_config = Hashabledict()
+ for resource in resources.values():
+ resource_type = nested_dict.get(resource, "type")
+ if resource_type == cls.resource_type:
+ config, rids = cls.get_volume_attachment_config(resource)
+ for rid in rids:
+ va_config[rid] = config
+ va_count[rid] += 1
+ return va_config, va_count
+
+ @classmethod
+ def get_volume_attachment_config(cls, resource):
+ """Returns the cinder volume attachment configuration
+ of `resource` as a tuple (config, rids)
+ where:
+ - config is a Hashabledict whose keys are the keys of the
+ properties of resource, and whose values are the
+ corresponding property values (nova server resource ids)
+ replaced with the vm-type they reference.
+ - rids is the set of nova server resource ids referenced by
+ the property values.
+ """
+ config = Hashabledict()
+ rids = set()
+ for key, value in (resource.get("properties") or {}).items():
+ rid = cls.get_resource_or_param_value(value)
+ if rid:
+ name, match = NovaServerProcessor.get_rid_match_tuple(rid)
+ if name == "server":
+ vm_type = match.groupdict()["vm_type"]
+ config[key] = vm_type
+ rids.add(rid)
+ return config, rids
+
+
+class ContrailV2NetworkFlavorBaseProcessor(HeatProcessor):
"""ContrailV2 objects which have network_flavor
"""
network_flavor_internal = "internal"
network_flavor_subint = "subint"
- def get_network_flavor(self, resource):
+ @classmethod
+ def get_network_flavor(cls, resource):
"""Return the network flavor of resource, one of
"internal" - get_resource, or get_param contains _int_
"subint" - get_param contains _subint_
param = network_refs[0]
if isinstance(param, dict):
if "get_resource" in param:
- network_flavor = self.network_flavor_internal
+ network_flavor = cls.network_flavor_internal
else:
p = param.get("get_param")
if isinstance(p, str):
if "_int_" in p or p.startswith("int_"):
- network_flavor = self.network_flavor_internal
+ network_flavor = cls.network_flavor_internal
elif "_subint_" in p:
- network_flavor = self.network_flavor_subint
+ network_flavor = cls.network_flavor_subint
else:
- network_flavor = self.network_flavor_external
+ network_flavor = cls.network_flavor_external
return network_flavor
-class ContrailV2InstanceIp(ContrailV2NetworkHeatObject):
+class ContrailV2InstanceIpProcessor(ContrailV2NetworkFlavorBaseProcessor):
""" ContrailV2 InstanceIp
"""
resource_type = "OS::ContrailV2::InstanceIp"
-
- def get_re_rids(self):
- """Return OrderedDict of name: regex
- """
- return collections.OrderedDict(
- [
- (
- "int_ip",
- _get_regex(
- r"(?P<vm_type>.+)"
- r"_(?P<vm_type_index>\d+)"
- r"_int"
- r"_(?P<network_role>.+)"
- r"_vmi"
- r"_(?P<vmi_index>\d+)"
- r"_IP"
- r"_(?P<index>\d+)"
- r"$"
- ),
+ re_rids = collections.OrderedDict(
+ [
+ (
+ "int_ip",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_int"
+ r"_(?P<network_role>.+)"
+ r"_vmi"
+ r"_(?P<vmi_index>\d+)"
+ r"_IP"
+ r"_(?P<index>\d+)"
+ r"$"
),
- (
- "int_v6_ip",
- _get_regex(
- r"(?P<vm_type>.+)"
- r"_(?P<vm_type_index>\d+)"
- r"_int"
- r"_(?P<network_role>.+)"
- r"_vmi"
- r"_(?P<vmi_index>\d+)"
- r"_v6_IP"
- r"_(?P<index>\d+)"
- r"$"
- ),
+ ),
+ (
+ "int_v6_ip",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_int"
+ r"_(?P<network_role>.+)"
+ r"_vmi"
+ r"_(?P<vmi_index>\d+)"
+ r"_v6_IP"
+ r"_(?P<index>\d+)"
+ r"$"
),
- (
- "subint_ip",
- _get_regex(
- r"(?P<vm_type>.+)"
- r"_(?P<vm_type_index>\d+)"
- r"_subint"
- r"_(?P<network_role>.+)"
- r"_vmi"
- r"_(?P<vmi_index>\d+)"
- r"_IP"
- r"_(?P<index>\d+)"
- r"$"
- ),
+ ),
+ (
+ "subint_ip",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_subint"
+ r"_(?P<network_role>.+)"
+ r"_vmi"
+ r"_(?P<vmi_index>\d+)"
+ r"_IP"
+ r"_(?P<index>\d+)"
+ r"$"
),
- (
- "subint_v6_ip",
- _get_regex(
- r"(?P<vm_type>.+)"
- r"_(?P<vm_type_index>\d+)"
- r"_subint"
- r"_(?P<network_role>.+)"
- r"_vmi"
- r"_(?P<vmi_index>\d+)"
- r"_v6_IP"
- r"_(?P<index>\d+)"
- r"$"
- ),
+ ),
+ (
+ "subint_v6_ip",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_subint"
+ r"_(?P<network_role>.+)"
+ r"_vmi"
+ r"_(?P<vmi_index>\d+)"
+ r"_v6_IP"
+ r"_(?P<index>\d+)"
+ r"$"
),
- (
- "ip",
- _get_regex(
- r"(?P<vm_type>.+)"
- r"_(?P<vm_type_index>\d+)"
- r"_(?P<network_role>.+)"
- r"_vmi"
- r"_(?P<vmi_index>\d+)"
- r"_IP"
- r"_(?P<index>\d+)"
- r"$"
- ),
+ ),
+ (
+ "ip",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_(?P<network_role>.+)"
+ r"_vmi"
+ r"_(?P<vmi_index>\d+)"
+ r"_IP"
+ r"_(?P<index>\d+)"
+ r"$"
),
- (
- "v6_ip",
- _get_regex(
- r"(?P<vm_type>.+)"
- r"_(?P<vm_type_index>\d+)"
- r"_(?P<network_role>.+)"
- r"_vmi"
- r"_(?P<vmi_index>\d+)"
- r"_v6_IP"
- r"_(?P<index>\d+)"
- r"$"
- ),
+ ),
+ (
+ "v6_ip",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_(?P<network_role>.+)"
+ r"_vmi"
+ r"_(?P<vmi_index>\d+)"
+ r"_v6_IP"
+ r"_(?P<index>\d+)"
+ r"$"
),
- ]
- )
+ ),
+ ]
+ )
-class ContrailV2InterfaceRouteTable(HeatObject):
+class ContrailV2InterfaceRouteTableProcessor(HeatProcessor):
""" ContrailV2 InterfaceRouteTable
"""
resource_type = "OS::ContrailV2::InterfaceRouteTable"
-class ContrailV2NetworkIpam(HeatObject):
+class ContrailV2NetworkIpamProcessor(HeatProcessor):
""" ContrailV2 NetworkIpam
"""
resource_type = "OS::ContrailV2::NetworkIpam"
-class ContrailV2PortTuple(HeatObject):
+class ContrailV2PortTupleProcessor(HeatProcessor):
""" ContrailV2 PortTuple
"""
resource_type = "OS::ContrailV2::PortTuple"
-class ContrailV2ServiceHealthCheck(HeatObject):
+class ContrailV2ServiceHealthCheckProcessor(HeatProcessor):
""" ContrailV2 ServiceHealthCheck
"""
resource_type = "OS::ContrailV2::ServiceHealthCheck"
-class ContrailV2ServiceInstance(HeatObject):
+class ContrailV2ServiceInstanceProcessor(HeatProcessor):
""" ContrailV2 ServiceInstance
"""
resource_type = "OS::ContrailV2::ServiceInstance"
-class ContrailV2ServiceInstanceIp(HeatObject):
+class ContrailV2ServiceInstanceIpProcessor(HeatProcessor):
""" ContrailV2 ServiceInstanceIp
"""
resource_type = "OS::ContrailV2::ServiceInstanceIp"
-class ContrailV2ServiceTemplate(HeatObject):
+class ContrailV2ServiceTemplateProcessor(HeatProcessor):
""" ContrailV2 ServiceTemplate
"""
resource_type = "OS::ContrailV2::ServiceTemplate"
-class ContrailV2VirtualMachineInterface(ContrailV2NetworkHeatObject):
+class ContrailV2VirtualMachineInterfaceProcessor(ContrailV2NetworkFlavorBaseProcessor):
""" ContrailV2 Virtual Machine Interface resource
"""
resource_type = "OS::ContrailV2::VirtualMachineInterface"
-
- def get_re_rids(self):
- """Return OrderedDict of name: regex
- """
- return collections.OrderedDict(
- [
- (
- "vmi_internal",
- _get_regex(
- r"(?P<vm_type>.+)"
- r"_(?P<vm_type_index>\d+)"
- r"_int"
- r"_(?P<network_role>.+)"
- r"_vmi"
- r"_(?P<vmi_index>\d+)"
- r"$"
- ),
+ re_rids = collections.OrderedDict(
+ [
+ (
+ "vmi_internal",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_int"
+ r"_(?P<network_role>.+)"
+ r"_vmi"
+ r"_(?P<vmi_index>\d+)"
+ r"$"
),
- (
- "vmi_subint",
- _get_regex(
- r"(?P<vm_type>.+)"
- r"_(?P<vm_type_index>\d+)"
- r"_subint"
- r"_(?P<network_role>.+)"
- r"_vmi"
- r"_(?P<vmi_index>\d+)"
- r"$"
- ),
+ ),
+ (
+ "vmi_subint",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_subint"
+ r"_(?P<network_role>.+)"
+ r"_vmi"
+ r"_(?P<vmi_index>\d+)"
+ r"$"
),
- (
- "vmi_external",
- _get_regex(
- r"(?P<vm_type>.+)"
- r"_(?P<vm_type_index>\d+)"
- r"_(?P<network_role>.+)"
- r"_vmi"
- r"_(?P<vmi_index>\d+)"
- r"$"
- ),
+ ),
+ (
+ "vmi_external",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_(?P<network_role>.+)"
+ r"_vmi"
+ r"_(?P<vmi_index>\d+)"
+ r"$"
),
- ]
- )
+ ),
+ ]
+ )
-class ContrailV2VirtualNetwork(HeatObject):
+class ContrailV2VirtualNetworkProcessor(HeatProcessor):
""" ContrailV2 VirtualNetwork
"""
resource_type = "OS::ContrailV2::VirtualNetwork"
+ re_rids = collections.OrderedDict(
+ [
+ ("network", _get_regex(r"int" r"_(?P<network_role>.+)" r"_network" r"$")),
+ ("rvn", _get_regex(r"int" r"_(?P<network_role>.+)" r"_RVN" r"$")),
+ ]
+ )
- def get_re_rids(self):
- """Return OrderedDict of name: regex
- """
- return collections.OrderedDict(
- [
- (
- "network",
- _get_regex(r"int" r"_(?P<network_role>.+)" r"_network" r"$"),
+
+class HeatResourceGroupProcessor(HeatProcessor):
+ """ Heat ResourceGroup
+ """
+
+ resource_type = "OS::Heat::ResourceGroup"
+ re_rids = collections.OrderedDict(
+ [
+ (
+ "subint",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_subint"
+ r"_(?P<network_role>.+)"
+ r"_port_(?P<port_index>\d+)"
+ r"_subinterfaces"
+ r"$"
),
- ("rvn", _get_regex(r"int" r"_(?P<network_role>.+)" r"_RVN" r"$")),
- ]
- )
+ )
+ ]
+ )
-class NeutronNet(HeatObject):
+class NeutronNetProcessor(HeatProcessor):
""" Neutron Net resource
"""
resource_type = "OS::Neutron::Net"
+ re_rids = collections.OrderedDict(
+ [("network", _get_regex(r"int" r"_(?P<network_role>.+)" r"_network" r"$"))]
+ )
- def get_re_rids(self):
- """Return OrderedDict of name: regex
- """
- return collections.OrderedDict(
- [("network", _get_regex(r"int" r"_(?P<network_role>.+)" r"_network" r"$"))]
- )
-
-class NeutronPort(HeatObject):
+class NeutronPortProcessor(HeatProcessor):
""" Neutron Port resource
"""
resource_type = "OS::Neutron::Port"
-
- def get_re_rids(self):
- """Return OrderedDict of name: regex
- """
- return collections.OrderedDict(
- [
- (
- "internal_port",
- _get_regex(
- r"(?P<vm_type>.+)"
- r"_(?P<vm_type_index>\d+)"
- r"_int"
- r"_(?P<network_role>.+)"
- r"_port_(?P<port_index>\d+)"
- r"$"
- ),
+ re_rids = collections.OrderedDict(
+ [
+ (
+ "internal_port",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_int"
+ r"_(?P<network_role>.+)"
+ r"_port_(?P<port_index>\d+)"
+ r"$"
),
- (
- "port",
- _get_regex(
- r"(?P<vm_type>.+)"
- r"_(?P<vm_type_index>\d+)"
- r"_(?P<network_role>.+)"
- r"_port_(?P<port_index>\d+)"
- r"$"
- ),
+ ),
+ (
+ "port",
+ _get_regex(
+ r"(?P<vm_type>.+)"
+ r"_(?P<vm_type_index>\d+)"
+ r"_(?P<network_role>.+)"
+ r"_port_(?P<port_index>\d+)"
+ r"$"
),
- (
- "floating_ip",
- _get_regex(
- r"reserve_port"
- r"_(?P<vm_type>.+)"
- r"_(?P<network_role>.+)"
- r"_floating_ip_(?P<index>\d+)"
- r"$"
- ),
+ ),
+ (
+ "floating_ip",
+ _get_regex(
+ r"reserve_port"
+ r"_(?P<vm_type>.+)"
+ r"_(?P<network_role>.+)"
+ r"_floating_ip_(?P<index>\d+)"
+ r"$"
),
- (
- "floating_v6_ip",
- _get_regex(
- r"reserve_port"
- r"_(?P<vm_type>.+)"
- r"_(?P<network_role>.+)"
- r"_floating_v6_ip_(?P<index>\d+)"
- r"$"
- ),
+ ),
+ (
+ "floating_v6_ip",
+ _get_regex(
+ r"reserve_port"
+ r"_(?P<vm_type>.+)"
+ r"_(?P<network_role>.+)"
+ r"_floating_v6_ip_(?P<index>\d+)"
+ r"$"
),
- ]
+ ),
+ ]
+ )
+
+ @classmethod
+ def uses_sr_iov(cls, resource):
+ """Returns True/False as `resource` is/not
+ An OS::Nova:Port with the property binding:vnic_type
+ """
+ return nested_dict.get(
+ resource, "type"
+ ) == cls.resource_type and "binding:vnic_type" in nested_dict.get(
+ resource, "properties", default={}
)
-class NovaServer(HeatObject):
+class NovaServerProcessor(HeatProcessor):
""" Nova Server resource
"""
resource_type = "OS::Nova::Server"
+ re_rids = collections.OrderedDict(
+ [
+ (
+ "server",
+ _get_regex(r"(?P<vm_type>.+)" r"_server_(?P<vm_type_index>\d+)" r"$"),
+ )
+ ]
+ )
- def get_re_rids(self):
- """Return OrderedDict of name: regex
- """
- return collections.OrderedDict(
- [
- (
- "server",
- _get_regex(
- r"(?P<vm_type>.+)" r"_server_(?P<vm_type_index>\d+)" r"$"
- ),
- )
- ]
- )
+ @classmethod
+ def get_flavor(cls, resource):
+ """Return the flavor property of `resource`
+ """
+ return cls.get_param_value(nested_dict.get(resource, "properties", "flavor"))
+
+ @classmethod
+ def get_image(cls, resource):
+ """Return the image property of `resource`
+ """
+ return cls.get_param_value(nested_dict.get(resource, "properties", "image"))
+
+ @classmethod
+ def get_network(cls, resource):
+ """Return the network configuration of `resource` as a
+ frozenset of network-roles.
+ """
+ network = set()
+ networks = nested_dict.get(resource, "properties", "networks")
+ if isinstance(networks, list):
+ for port in networks:
+ value = cls.get_resource_or_param_value(nested_dict.get(port, "port"))
+ name, match = NeutronPortProcessor.get_rid_match_tuple(value)
+ if name:
+ network_role = match.groupdict().get("network_role")
+ if network_role:
+ network.add(network_role)
+ return frozenset(network)
+
+ @classmethod
+ def get_vm_class(cls, resource):
+ """Return the vm_class of `resource`, a Hashabledict (of
+ hashable values) whose keys are only the required keys.
+ Return empty Hashabledict if `resource` is not a NovaServer.
+ """
+ vm_class = Hashabledict()
+ resource_type = nested_dict.get(resource, "type")
+ if resource_type == cls.resource_type:
+ d = dict(
+ flavor=cls.get_flavor(resource),
+ image=cls.get_image(resource),
+ networks=cls.get_network(resource),
+ )
+ if all(d.values()):
+ vm_class.update(d)
+ return vm_class
class Heat(object):
envpath - absolute path to environmnt file.
"""
+ type_bool = "boolean"
+ type_boolean = "boolean"
type_cdl = "comma_delimited_list"
+ type_comma_delimited_list = "comma_delimited_list"
+ type_json = "json"
type_num = "number"
+ type_number = "number"
type_str = "string"
+ type_string = "string"
def __init__(self, filepath=None, envpath=None):
self.filepath = None
self.env = None
if envpath:
self.load_env(envpath)
- self.heat_objects = self.get_heat_objects()
+ self.heat_processors = self.get_heat_processors()
@property
def contrail_resources(self):
"""This attribute is a dict of Contrail resources.
"""
return self.get_resource_by_type(
- resource_type=ContrailV2VirtualMachineInterface.resource_type
+ resource_type=ContrailV2VirtualMachineInterfaceProcessor.resource_type
)
+ def get_all_resources(self, base_dir):
+ """
+ Like ``resources``,
+ but this returns all the resources definitions
+ defined in the template, resource groups, and nested YAML files.
+ """
+ resources = {}
+ for r_id, r_data in self.resources.items():
+ resources[r_id] = r_data
+ resource = Resource(r_id, r_data)
+ if resource.is_nested():
+ nested = Heat(os.path.join(base_dir, resource.get_nested_filename()))
+ resources.update(nested.get_all_resources(base_dir))
+ return resources
+
@staticmethod
- def get_heat_objects():
+ def get_heat_processors():
"""Return a dict, key is resource_type, value is the
- HeatObject subclass whose resource_type is the key.
+ HeatProcessor subclass whose resource_type is the key.
"""
- return _HEAT_OBJECTS
+ return _HEAT_PROCESSORS
def get_resource_by_type(self, resource_type):
"""Return dict of resources whose type is `resource_type`.
"""return get_rid_match_tuple(rid) called on the class
corresponding to the given resource_type.
"""
- hoc = self.heat_objects.get(resource_type, HeatObject)
- return hoc().get_rid_match_tuple(rid)
+ processor = self.heat_processors.get(resource_type, HeatProcessor)
+ return processor.get_rid_match_tuple(rid)
def get_vm_type(self, rid, resource=None):
"""return the vm_type
self.yml = yaml.load(fi)
self.heat_template_version = self.yml.get("heat_template_version", None)
self.description = self.yml.get("description", "")
- self.parameter_groups = self.yml.get("parameter_groups", {})
+ self.parameter_groups = self.yml.get("parameter_groups") or {}
self.parameters = self.yml.get("parameters") or {}
- self.resources = self.yml.get("resources", {})
- self.outputs = self.yml.get("outputs", {})
- self.conditions = self.yml.get("conditions", {})
-
- def get_all_resources(self, base_dir):
- """
- Like ``resources``, but this returns all the resources definitions
- defined in the template, resource groups, and nested YAML files.
- """
- resources = {}
- for r_id, r_data in self.resources.items():
- resources[r_id] = r_data
- resource = Resource(r_id, r_data)
- if resource.is_nested():
- nested = Heat(os.path.join(base_dir, resource.get_nested_filename()))
- resources.update(nested.get_all_resources(base_dir))
- return resources
+ self.resources = self.yml.get("resources") or {}
+ self.outputs = self.yml.get("outputs") or {}
+ self.conditions = self.yml.get("conditions") or {}
def load_env(self, envpath):
- """
- Load the Environment template given a envpath.
+ """Load the Environment template given a envpath.
"""
self.env = Env(filepath=envpath)
def neutron_port_resources(self):
"""This attribute is a dict of Neutron Ports
"""
- return self.get_resource_by_type(resource_type=NeutronPort.resource_type)
+ return self.get_resource_by_type(
+ resource_type=NeutronPortProcessor.resource_type
+ )
@property
def nova_server_resources(self):
"""This attribute is a dict of Nova Servers
"""
- return self.get_resource_by_type(resource_type=NovaServer.resource_type)
+ return self.get_resource_by_type(
+ resource_type=NovaServerProcessor.resource_type
+ )
@staticmethod
def part_is_in_name(part, name):
self.resource_id = resource_id or ""
self.resource = resource or {}
self.properties = self.resource.get("properties", {})
- self.resource_type = resource.get("type", "")
+ self.resource_type = self.resource.get("type", "")
@staticmethod
def get_index_var(resource):
return {}
-def _get_heat_objects():
+def get_all_resources(yaml_files):
+ """Return a dict, resource id: resource
+ of the union of resources across all files.
"""
- Introspect this module and return a dict of all HeatObject sub-classes with
- a (True) resource_type. Key is the resource_type, value is the
- corresponding class.
+ resources = {}
+ for heat_template in yaml_files:
+ heat = Heat(filepath=heat_template)
+ dirname = os.path.dirname(heat_template)
+ resources.update(heat.get_all_resources(dirname))
+ return resources
+
+
+def _get_heat_processors():
+ """Introspect this module and return a
+ dict of all HeatProcessor sub-classes with a (True) resource_type.
+ Key is the resource_type, value is the corrresponding class.
"""
mod_classes = inspect.getmembers(sys.modules[__name__], inspect.isclass)
- heat_objects = {
+ heat_processors = {
c.resource_type: c
for _, c in mod_classes
- if issubclass(c, HeatObject) and c.resource_type
+ if issubclass(c, HeatProcessor) and c.resource_type
}
- return heat_objects
+ return heat_processors
-_HEAT_OBJECTS = _get_heat_objects()
+_HEAT_PROCESSORS = _get_heat_processors()
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ============LICENSE_END============================================
#
-# ECOMP is a trademark and service mark of AT&T Intellectual Property.
-#
-
-import pytest
-from tests import cached_yaml as yaml
-
-from .helpers import validates
-from .utils.nested_iterables import find_all_get_param_in_yml
+import re
-VERSION = "1.0.0"
+from tests.helpers import validates, load_yaml
+from tests.utils.nested_iterables import find_all_get_param_in_yml
-# pylint: disable=invalid-name
+AVAILABILITY_ZONE = re.compile(r"availability_zone_?\d*")
@validates("R-90279")
def test_all_parameters_used_in_template(yaml_file):
-
- invalid_params = []
- get_params = []
- skip_params = ["availability_zone"]
-
- with open(yaml_file, "r") as f:
- yml = yaml.load(f)
-
- template_parameters = yml.get("parameters")
- if not template_parameters:
- pytest.skip("no parameters found in template")
-
- get_params = find_all_get_param_in_yml(yml)
- if not get_params:
- pytest.skip("no get_params found in template")
-
- template_parameters = list(template_parameters.keys())
- for param in template_parameters:
- for sparam in skip_params:
- if param.find(sparam) != -1:
- template_parameters.remove(param)
-
- invalid_params = set(template_parameters) - set(get_params)
-
- assert not invalid_params, "Unused parameters detected in template {}".format(
- invalid_params
- )
+ yml = load_yaml(yaml_file)
+ params = (yml.get("parameters") or {}).keys()
+ expected_params = {p for p in params if not AVAILABILITY_ZONE.match(p)}
+ used_params = set(find_all_get_param_in_yml(yml))
+ unused_params = expected_params.difference(used_params)
+
+ msg = "Unused parameters detected in template {}".format(unused_params)
+ assert not unused_params, msg
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
-
"""
resources:
{vm-type}_server_{vm-type_index}
import pytest
from .structures import Heat
-from .structures import ContrailV2InstanceIp
+from .structures import ContrailV2InstanceIpProcessor
from .helpers import validates
-VERSION = "1.1.0"
+VERSION = "2.0.0"
def run_test(heat_template, regex_names, network_flavor):
"""run test
"""
heat = Heat(filepath=heat_template)
- heat_object_class = ContrailV2InstanceIp
- resource_type = heat_object_class.resource_type
+ processor = ContrailV2InstanceIpProcessor
+ resource_type = processor.resource_type
resources = heat.get_resource_by_type(resource_type=resource_type)
if not resources:
pytest.skip("No %s resources found" % resource_type)
bad = []
- heat_object = heat_object_class()
- rid_patterns = heat_object.get_rid_patterns()
+ rid_patterns = processor.get_rid_patterns()
for rid, resource in resources.items():
- flavor = heat_object.get_network_flavor(resource)
+ flavor = processor.get_network_flavor(resource)
if flavor != network_flavor:
continue
- regex_name = heat_object.get_rid_match_tuple(rid)[0]
+ regex_name = processor.get_rid_match_tuple(rid)[0]
if regex_name in regex_names:
continue
bad.append(rid)
run_test(
heat_template,
regex_names=("ip", "v6_ip"),
- network_flavor=ContrailV2InstanceIp.network_flavor_external,
+ network_flavor=ContrailV2InstanceIpProcessor.network_flavor_external,
)
run_test(
heat_template,
regex_names=("int_ip", "int_v6_ip"),
- network_flavor=ContrailV2InstanceIp.network_flavor_internal,
+ network_flavor=ContrailV2InstanceIpProcessor.network_flavor_internal,
)
run_test(
heat_template,
regex_names=("subint_ip", "subint_v6_ip"),
- network_flavor=ContrailV2InstanceIp.network_flavor_subint,
+ network_flavor=ContrailV2InstanceIpProcessor.network_flavor_subint,
)
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
"""
import pytest
-from .structures import ContrailV2InterfaceRouteTable
-from .structures import ContrailV2NetworkIpam
-from .structures import ContrailV2PortTuple
-from .structures import ContrailV2ServiceHealthCheck
-from .structures import ContrailV2ServiceTemplate
+from .structures import ContrailV2InterfaceRouteTableProcessor
+from .structures import ContrailV2NetworkIpamProcessor
+from .structures import ContrailV2PortTupleProcessor
+from .structures import ContrailV2ServiceHealthCheckProcessor
+from .structures import ContrailV2ServiceTemplateProcessor
from .utils.network_roles import get_network_roles
from .utils.vm_types import get_vm_types
from .structures import Heat
from .helpers import validates
-VERSION = "1.0.1"
+VERSION = "2.0.0"
def run_test(heat_template, contrail_class, get_parts, part_name):
contain the ``{network-role}``.
"""
run_test(
- heat_template, ContrailV2InterfaceRouteTable, get_network_roles, "network_role"
+ heat_template,
+ ContrailV2InterfaceRouteTableProcessor,
+ get_network_roles,
+ "network_role",
)
**MUST**
contain the ``{network-role}``.
"""
- run_test(heat_template, ContrailV2NetworkIpam, get_network_roles, "network_role")
+ run_test(
+ heat_template, ContrailV2NetworkIpamProcessor, get_network_roles, "network_role"
+ )
@validates("R-20065")
**MUST**
contain the ``{vm-type}``.
"""
- run_test(heat_template, ContrailV2PortTuple, get_vm_types, "vm_type")
+ run_test(heat_template, ContrailV2PortTupleProcessor, get_vm_types, "vm_type")
@validates("R-76014")
**MUST**
contain the ``{vm-type}``.
"""
- run_test(heat_template, ContrailV2ServiceHealthCheck, get_vm_types, "vm_type")
+ run_test(
+ heat_template, ContrailV2ServiceHealthCheckProcessor, get_vm_types, "vm_type"
+ )
@validates("R-16437")
**MUST**
contain the ``{vm-type}``.
"""
- run_test(heat_template, ContrailV2ServiceTemplate, get_vm_types, "vm_type")
+ run_test(heat_template, ContrailV2ServiceTemplateProcessor, get_vm_types, "vm_type")
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
-import pytest
-
-from .structures import Heat
-from .structures import ContrailV2VirtualMachineInterface
-from .helpers import validates
"""
resources:
{vm-type}_server_{vm-type_index}
"""
+import pytest
+
+from .structures import Heat
+from .structures import ContrailV2VirtualMachineInterfaceProcessor
+from .helpers import validates
-VERSION = "1.0.0"
+VERSION = "2.0.0"
def run_test(heat_template, regex_name, network_flavor):
"""run test
"""
heat = Heat(filepath=heat_template)
- heat_object_class = ContrailV2VirtualMachineInterface
+ heat_object_class = ContrailV2VirtualMachineInterfaceProcessor
resource_type = heat_object_class.resource_type
resources = heat.get_resource_by_type(resource_type=resource_type)
if not resources:
run_test(
heat_template,
regex_name="vmi_external",
- network_flavor=ContrailV2VirtualMachineInterface.network_flavor_external,
+ network_flavor=ContrailV2VirtualMachineInterfaceProcessor.network_flavor_external,
)
run_test(
heat_template,
regex_name="vmi_internal",
- network_flavor=ContrailV2VirtualMachineInterface.network_flavor_internal,
+ network_flavor=ContrailV2VirtualMachineInterfaceProcessor.network_flavor_internal,
)
run_test(
heat_template,
regex_name="vmi_subint",
- network_flavor=ContrailV2VirtualMachineInterface.network_flavor_subint,
+ network_flavor=ContrailV2VirtualMachineInterfaceProcessor.network_flavor_subint,
)
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
from .helpers import validates
from .structures import Heat
-from .structures import ContrailV2VirtualNetwork
+from .structures import ContrailV2VirtualNetworkProcessor
-VERSION = "1.0.0"
+VERSION = "2.0.0"
# pylint: disable=invalid-name
2) int_{network-role}_RVN`` where RVN represents Resource Virtual
"""
heat = Heat(filepath=heat_template)
- heat_object_class = ContrailV2VirtualNetwork
+ heat_object_class = ContrailV2VirtualNetworkProcessor
resource_type = heat_object_class.resource_type
resources = heat.get_resource_by_type(resource_type)
if not resources:
# ============LICENSE_START=======================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
@validates("R-599443")
-def test_env_params_are_defined_in_template(heat_template):
+def test_env_params_are_defined_in_template(yaml_file):
"""Test that each paraemter defined in an environment file
is also defined in the paired heat template"""
bad = []
- template_pair = get_environment_pair(heat_template)
+ template_pair = get_environment_pair(yaml_file)
if not template_pair:
pytest.skip("No yaml/env pair could be determined")
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
-
""" environment file structure
"""
+import os
+from .helpers import validates, categories, get_environment_pair, find_environment_file
import re
import pytest
-
-from .helpers import validates, get_environment_pair
-
+from tests import cached_yaml as yaml
VERSION = "1.0.0"
- nested_prop_1: { get_param: [parameter_2, {index}] }
prop2: # this is a dict of dicts
nested_prop_0: { get_param: parameter_1 }
+ prop3: { get_param: [parameter_3, 0]}
"""
exclude_resource="",
exclude_parameter="",
):
-
if not environment_pair:
pytest.skip("No heat/env pair could be identified")
pytest.skip("No parameters specified in the environment file")
invalid_parameters = []
-
if template_file:
for resource, resource_prop in template_file.get("resources", {}).items():
if not resource_parameter:
continue
-
if isinstance(resource_parameter, list) and nested_prop:
for param in resource_parameter:
-
nested_param = param.get(nested_prop)
if not nested_param:
continue
invalid_parameters.append(pattern)
elif isinstance(resource_parameter, dict):
-
if nested_prop and nested_prop in resource_parameter:
resource_parameter = resource_parameter.get(nested_prop)
if not pattern:
continue
+ if isinstance(pattern, list):
+ pattern = pattern[0]
+
if check_param_in_env_file(
environment_pair,
pattern,
return set(invalid_parameters)
-@validates("R-91125")
-def test_nova_server_image_parameter_exists_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
+def run_check_resource_parameter(
+ yaml_file, prop, DESIRED, resource_type, check_resource=True, **kwargs
+):
- prop = "image"
- DESIRED = True
- resource_type = "OS::Nova::Server"
+ filepath, filename = os.path.split(yaml_file)
+ environment_pair = get_environment_pair(yaml_file)
- invalid_parameters = check_resource_parameter(
- environment_pair, prop, DESIRED, resource_type
- )
-
- assert not invalid_parameters, (
- "OS::Nova::Server {} parameters not"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
+ if not environment_pair:
+ # this is a nested file
+
+ if not check_resource:
+ # dont check env for nested files
+ # This will be tested separately for parent template
+ pytest.skip("This test doesn't apply to nested files")
+
+ environment_pair = find_environment_file(yaml_file)
+ if environment_pair:
+ with open(yaml_file, "r") as f:
+ yml = yaml.load(f)
+ environment_pair["yyml"] = yml
+ else:
+ pytest.skip("unable to determine environment file for nested yaml file")
+
+ if check_resource:
+ invalid_parameters = check_resource_parameter(
+ environment_pair, prop, DESIRED, resource_type, **kwargs
)
- )
-
-
-@validates("R-69431")
-def test_nova_server_flavor_parameter_exists_in_environment_file(heat_template):
+ else:
+ invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "flavor"
- DESIRED = True
- resource_type = "OS::Nova::Server"
-
- invalid_parameters = check_resource_parameter(
- environment_pair, prop, DESIRED, resource_type
- )
+ if kwargs.get("resource_type_inverse"):
+ resource_type = "non-{}".format(resource_type)
assert not invalid_parameters, (
- "OS::Nova::Server {} parameters not"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
+ "{} {} parameters in template {}{}"
+ " found in {} environment file: {}".format(
+ resource_type,
+ prop,
+ filename,
+ " not" if DESIRED else "",
+ environment_pair.get("name"),
+ invalid_parameters,
)
)
-@validates("R-22838")
-def test_nova_server_name_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
+@validates("R-91125")
+def test_nova_server_image_parameter_exists_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "image", True, "OS::Nova::Server")
- environment_pair = get_environment_pair(heat_template)
- prop = "name"
- DESIRED = False
- resource_type = "OS::Nova::Server"
+@validates("R-69431")
+def test_nova_server_flavor_parameter_exists_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "flavor", True, "OS::Nova::Server")
- invalid_parameters = check_resource_parameter(
- environment_pair, prop, DESIRED, resource_type
- )
- assert not invalid_parameters, (
- "OS::Nova::Server {} parameters"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
- )
- )
+@categories("environment_file")
+@validates("R-22838")
+def test_nova_server_name_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "name", False, "OS::Nova::Server")
+@categories("environment_file")
@validates("R-59568")
-def test_nova_server_az_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "availability_zone"
- DESIRED = False
- resource_type = "OS::Nova::Server"
-
- invalid_parameters = check_resource_parameter(
- environment_pair, prop, DESIRED, resource_type
- )
-
- assert not invalid_parameters, (
- "OS::Nova::Server {} parameters"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
- )
+def test_nova_server_az_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file, "availability_zone", False, "OS::Nova::Server"
)
+@categories("environment_file")
@validates("R-20856")
-def test_nova_server_vnf_id_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "vnf_id"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
-
- assert not invalid_parameters, (
- "{} parameters"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
- )
- )
+def test_nova_server_vnf_id_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "vnf_id", False, "", check_resource=False)
+@categories("environment_file")
@validates("R-72871")
-def test_nova_server_vf_module_id_parameter_doesnt_exist_in_environment_file(
- heat_template
-):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "vf_module_id"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
-
- assert not invalid_parameters, (
- "{} parameters"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
- )
+def test_nova_server_vf_module_id_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file, "vf_module_id", False, "", check_resource=False
)
+@categories("environment_file")
@validates("R-37039")
def test_nova_server_vf_module_index_parameter_doesnt_exist_in_environment_file(
- heat_template
+ yaml_file
):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "vf_module_index"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
-
- assert not invalid_parameters, (
- "{} parameters"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
- )
+ run_check_resource_parameter(
+ yaml_file, "vf_module_index", False, "", check_resource=False
)
+@categories("environment_file")
@validates("R-36542")
-def test_nova_server_vnf_name_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "vnf_name"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
-
- assert not invalid_parameters, (
- "{} parameters"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
- )
- )
+def test_nova_server_vnf_name_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "vnf_name", False, "", check_resource=False)
+@categories("environment_file")
@validates("R-80374")
def test_nova_server_vf_module_name_parameter_doesnt_exist_in_environment_file(
- heat_template
+ yaml_file
):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "vf_module_name"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
-
- assert not invalid_parameters, (
- "{} parameters"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
- )
+ run_check_resource_parameter(
+ yaml_file, "vf_module_name", False, "", check_resource=False
)
+@categories("environment_file")
@validates("R-02691")
def test_nova_server_workload_context_parameter_doesnt_exist_in_environment_file(
- heat_template
+ yaml_file
):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "workload_context"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
-
- assert not invalid_parameters, (
- "{} parameters"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
- )
+ run_check_resource_parameter(
+ yaml_file, "workload_context", False, "", check_resource=False
)
+@categories("environment_file")
@validates("R-13194")
def test_nova_server_environment_context_parameter_doesnt_exist_in_environment_file(
- heat_template
+ yaml_file
):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "environment_context"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
-
- assert not invalid_parameters, (
- "{} parameters"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
- )
+ run_check_resource_parameter(
+ yaml_file, "environment_context", False, "", check_resource=False
)
+@categories("environment_file")
@validates("R-29872")
-def test_nova_server_network_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "networks"
- nested_prop = "network"
- DESIRED = False
- resource_type = "OS::Nova::Server"
-
- invalid_parameters = check_resource_parameter(
- environment_pair, prop, DESIRED, resource_type, nested_prop=nested_prop
- )
-
- assert not invalid_parameters, (
- "{} {} parameters"
- " found in {} environment file {}".format(
- resource_type, nested_prop, environment_pair.get("name"), invalid_parameters
- )
- )
+def test_neutron_port_network_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "network", False, "OS::Neutron::Port")
+@categories("environment_file")
@validates("R-39841", "R-87123", "R-62590", "R-98905", "R-93030", "R-62590")
def test_neutron_port_external_fixedips_ipaddress_parameter_doesnt_exist_in_environment_file(
- heat_template
+ yaml_file
):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "fixed_ips"
- nested_prop = "ip_address"
- DESIRED = False
- resource_type = "OS::Neutron::Port"
- exclude_parameter = re.compile(r"^(.+?)_int_(.+?)$")
-
- invalid_parameters = check_resource_parameter(
- environment_pair,
- prop,
- DESIRED,
- resource_type,
- nested_prop=nested_prop,
- exclude_parameter=exclude_parameter,
- )
-
- assert not invalid_parameters, (
- "{} {} external parameters"
- " found in {} environment file {}".format(
- resource_type, nested_prop, environment_pair.get("name"), invalid_parameters
- )
+ run_check_resource_parameter(
+ yaml_file,
+ "fixed_ips",
+ False,
+ "OS::Neutron::Port",
+ nested_prop="ip_address",
+ exclude_parameter=re.compile(r"^(.+?)_int_(.+?)$"),
)
@validates("R-28795", "R-97201", "R-93496", "R-90206", "R-98569", "R-93496")
def test_neutron_port_internal_fixedips_ipaddress_parameter_exists_in_environment_file(
- heat_template
+ yaml_file
):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "fixed_ips"
- nested_prop = "ip_address"
- DESIRED = True
- resource_type = "OS::Neutron::Port"
- exclude_parameter = re.compile(r"^((?!_int_).)*$")
-
- invalid_parameters = check_resource_parameter(
- environment_pair,
- prop,
- DESIRED,
- resource_type,
- nested_prop=nested_prop,
- exclude_parameter=exclude_parameter,
- )
-
- assert not invalid_parameters, (
- "{} {} internal parameters"
- " not found in {} environment file {}".format(
- resource_type, nested_prop, environment_pair.get("name"), invalid_parameters
- )
+ run_check_resource_parameter(
+ yaml_file,
+ "fixed_ips",
+ True,
+ "OS::Neutron::Port",
+ nested_prop="ip_address",
+ exclude_parameter=re.compile(r"^((?!_int_).)*$"),
)
+@categories("environment_file")
@validates("R-83677", "R-80829", "R-69634", "R-22288")
def test_neutron_port_fixedips_subnet_parameter_doesnt_exist_in_environment_file(
- heat_template
+ yaml_file
):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "fixed_ips"
- nested_prop = "subnet"
- DESIRED = False
- resource_type = "OS::Neutron::Port"
-
- invalid_parameters = check_resource_parameter(
- environment_pair, prop, DESIRED, resource_type, nested_prop=nested_prop
- )
-
- assert not invalid_parameters, (
- "{} {} parameters"
- " found in {} environment file {}".format(
- resource_type, nested_prop, environment_pair.get("name"), invalid_parameters
- )
+ run_check_resource_parameter(
+ yaml_file, "fixed_ips", False, "OS::Neutron::Port", nested_prop="subnet"
)
+@categories("environment_file")
@validates("R-83412", "R-83418")
-def test_neutron_port_aap_ip_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "allowed_address_pairs"
- nested_prop = "ip_address"
- DESIRED = False
- resource_type = "OS::Neutron::Port"
-
- invalid_parameters = check_resource_parameter(
- environment_pair, prop, DESIRED, resource_type, nested_prop=nested_prop
- )
-
- assert not invalid_parameters, (
- "{} {} parameters"
- " found in {} environment file {}".format(
- resource_type, nested_prop, environment_pair.get("name"), invalid_parameters
- )
+def test_neutron_port_aap_ip_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file,
+ "allowed_address_pairs",
+ False,
+ "OS::Neutron::Port",
+ nested_prop="ip_address",
)
+@categories("environment_file")
@validates("R-99812")
-def test_non_nova_server_name_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "name"
- DESIRED = False
- resource_type = "OS::Nova::Server"
-
- invalid_parameters = check_resource_parameter(
- environment_pair, prop, DESIRED, resource_type, resource_type_inverse=True
- )
-
- assert not invalid_parameters, (
- "non-{} {} parameters"
- " found in {} environment file {}".format(
- resource_type, prop, environment_pair.get("name"), invalid_parameters
- )
+def test_non_nova_server_name_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file, "name", False, "OS::Nova::Server", resource_type_inverse=True
)
+@categories("environment_file")
@validates("R-92193")
-def test_network_fqdn_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = r"^(.+?)_net_fqdn$"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
-
- assert not invalid_parameters, (
- "{} parameters"
- " found in {} environment file {}".format(
- prop, environment_pair.get("name"), invalid_parameters
- )
+def test_network_fqdn_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file, r"^(.+?)_net_fqdn$", False, "", check_resource=False
)
+@categories("environment_file")
@validates("R-76682")
-def test_contrail_route_prefixes_parameter_doesnt_exist_in_environment_file(
- heat_template
-):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "interface_route_table_routes"
- nested_prop = "interface_route_table_routes_route"
- DESIRED = False
- resource_type = "OS::ContrailV2::InterfaceRouteTable"
-
- invalid_parameters = check_resource_parameter(
- environment_pair, prop, DESIRED, resource_type, nested_prop=nested_prop
- )
-
- assert not invalid_parameters, (
- "{} {} parameters"
- " found in {} environment file {}".format(
- resource_type, nested_prop, environment_pair.get("name"), invalid_parameters
- )
+def test_contrail_route_prefixes_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file,
+ "interface_route_table_routes",
+ False,
+ "OS::ContrailV2::InterfaceRouteTable",
+ nested_prop="interface_route_table_routes_route",
)
@validates("R-50011")
-def test_heat_rg_count_parameter_exists_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "count"
- DESIRED = True
- resource_type = "OS::Heat::ResourceGroup"
- exclude_resource = re.compile(r"^(.+?)_subint_(.+?)_port_(.+?)_subinterfaces$")
-
- invalid_parameters = check_resource_parameter(
- environment_pair,
- prop,
- DESIRED,
- resource_type,
- exclude_resource=exclude_resource,
- )
-
- assert not invalid_parameters, (
- "{} {} parameters not"
- " found in {} environment file {}".format(
- resource_type, prop, environment_pair.get("name"), invalid_parameters
- )
+def test_heat_rg_count_parameter_exists_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file,
+ "count",
+ True,
+ "OS::Heat::ResourceGroup",
+ exclude_resource=re.compile(r"^(.+?)_subint_(.+?)_port_(.+?)_subinterfaces$"),
)
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
# ============LICENSE_END============================================
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
-
import os
-from tests import cached_yaml as yaml
-
from .helpers import validates
-from .utils.vm_types import get_vm_types
+from .utils.vm_types import get_all_vm_types
+from .parametrizers import get_nested_files
VERSION = "1.0.0"
vm_types = []
invalid_files = []
+ nested_files = []
- for yaml_file in yaml_files:
- with open(yaml_file, "r") as f:
- yml = yaml.load(f)
-
- if "resources" not in yml:
- continue
+ nested_files.extend(
+ os.path.splitext(os.path.basename(filename))[0]
+ for filename in get_nested_files(yaml_files)
+ )
- vm_types.extend(get_vm_types(yml["resources"]))
+ vm_types = get_all_vm_types(yaml_files)
- for yaml_file in yaml_files:
- basename, filename = os.path.split(yaml_file)
- file, ext = os.path.splitext(os.path.basename(filename))
- for vt in vm_types:
- if vt == file:
- invalid_files.append({"vm_type": vt, "file": yaml_file})
+ invalid_files.extend(vm_type for vm_type in vm_types if vm_type in nested_files)
- assert not invalid_files, "filenames must not be in format vm_type.yaml: {}".format(
- invalid_files
- )
+ assert (
+ not invalid_files
+ ), "Nested filenames must not be in format vm_type.yaml: {}".format(invalid_files)
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
"""heat parameters
"""
-
import pytest
from tests import cached_yaml as yaml
from tests.structures import Resource
-
from .helpers import validates
VERSION = "1.0.0"
-def check_nested_parameter_doesnt_change(yaml_file, parameter):
+def check_nested_parameter_doesnt_change(yaml_file):
with open(yaml_file) as fh:
yml = yaml.load(fh)
invalid_parameters = []
"""
- checking if property: { get_param: <parameter> }, then property == <parameter>
+ checking if property: { get_param: parameter }, then property == parameter
resource_id:
type: nested.yaml
properties:
- property: { get_param: <parameter> }
+ property: { get_param: parameter }
resource_id:
type: OS::Heat::ResourceGroup
properties:
resource_def:
properties:
- property: { get_param: <parameter> }
+ property: { get_param: parameter }
"""
for resource_id, resource in yml.get("resources", {}).items():
- r = Resource(resource_id=resource_id, resource=resource)
- properties = r.get_nested_properties()
- for k1, v1 in properties.items():
- if (
- isinstance(v1, dict)
- and "get_param" in v1
- and parameter == v1.get("get_param")
- ):
- if k1 != parameter:
- invalid_parameters.append(
- {
- "resource": r.resource_id,
- "nested parameter": k1,
- "parameter": parameter,
- }
- )
+ resource_type = resource.get("type")
+ if resource_type and (
+ resource_type.endswith("yaml")
+ or resource_type.endswith("yml")
+ or resource_type == "OS::Heat::ResourceGroup"
+ ):
+ # workaround for subinterfaces
+ metadata = resource.get("metadata")
+ if metadata:
+ subinterface_type = metadata.get("subinterface_type")
+ if subinterface_type and subinterface_type == "network_collection":
+ continue
+
+ r = Resource(resource_id=resource_id, resource=resource)
+ properties = r.get_nested_properties()
+ for k1, v1 in properties.items():
+ if isinstance(v1, dict) and "get_param" in v1:
+ parameter = v1.get("get_param")
+ if isinstance(parameter, list):
+ parameter = parameter[0]
+
+ if k1 != parameter:
+ invalid_parameters.append(
+ {
+ "resource": r.resource_id,
+ "nested parameter": k1,
+ "parameter": parameter,
+ "file": yaml_file,
+ }
+ )
assert (
not invalid_parameters
)
-@validates("R-70757")
-def test_vm_role_doesnt_change_in_nested_template(yaml_file):
- check_nested_parameter_doesnt_change(yaml_file, "vm_role")
-
-
-@validates("R-44491")
-def test_vnf_id_doesnt_change_in_nested_template(yaml_file):
- check_nested_parameter_doesnt_change(yaml_file, "vnf_id")
-
-
-@validates("R-86237")
-def test_vf_module_id_doesnt_change_in_nested_template(yaml_file):
- check_nested_parameter_doesnt_change(yaml_file, "vf_module_id")
-
-
-@validates("R-16576")
-def test_vnf_name_doesnt_change_in_nested_template(yaml_file):
- check_nested_parameter_doesnt_change(yaml_file, "vnf_name")
-
-
-@validates("R-49177")
-def test_vf_module_name_doesnt_change_in_nested_template(yaml_file):
- check_nested_parameter_doesnt_change(yaml_file, "vf_module_name")
-
-
-@validates("R-22441")
-def test_vf_module_index_name_doesnt_change_in_nested_template(yaml_file):
- check_nested_parameter_doesnt_change(yaml_file, "vf_module_index")
-
-
-@validates("R-62954")
-def test_environment_context_name_doesnt_change_in_nested_template(yaml_file):
- check_nested_parameter_doesnt_change(yaml_file, "environment_context")
-
-
-@validates("R-75202")
-def test_workload_context_name_doesnt_change_in_nested_template(yaml_file):
- check_nested_parameter_doesnt_change(yaml_file, "workload_context")
+@validates("R-708564")
+def test_parameter_name_doesnt_change_in_nested_template(yaml_file):
+ check_nested_parameter_doesnt_change(yaml_file)
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
from .helpers import validates
from .structures import Heat
-from .structures import NeutronNet
+from .structures import NeutronNetProcessor
-VERSION = "1.1.0"
+VERSION = "2.0.0"
# pylint: disable=invalid-name
* int_{network-role}_network
"""
heat = Heat(filepath=heat_template)
- neutron_nets = heat.get_resource_by_type(NeutronNet.resource_type)
+ neutron_nets = heat.get_resource_by_type(NeutronNetProcessor.resource_type)
if not neutron_nets:
pytest.skip("No neutron nets found")
- neutron_net = NeutronNet()
bad = []
for rid in neutron_nets:
- if not neutron_net.get_rid_match_tuple(rid)[0]:
+ if not NeutronNetProcessor.get_rid_match_tuple(rid)[0]:
bad.append("Neutron Net %s does not match any known format" % rid)
assert not bad, "; ".join(bad)
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ============LICENSE_END============================================
#
-# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
"""
param = heat.nested_get(aa_pair, field, "get_param")
if param is None:
continue
+ else:
+ param = param[0] if isinstance(param, list) else param
port_addresses[field][param][basename].add(rid)
return port_addresses
break
else:
# if v6 and testing v6, or inverse
+ param = param[0] if isinstance(param, list) else param
if v6 == is_v6_ip(param):
ports.add(param)
if error is None and len(ports) > 1:
@validates("R-91810")
def test_neutron_port_external_ipaddress(heat_template):
"""
- If a VNF requires ECOMP to assign a Virtual IP (VIP) Address to
+ If a VNF requires ONAP to assign a Virtual IP (VIP) Address to
ports connected an external network, the port
**MUST NOT** have more than one IPv4 VIP address.
"""
@validates("R-41956")
def test_neutron_port_external_ipaddress_v6(heat_template):
"""
- If a VNF requires ECOMP to assign a Virtual IP (VIP) Address to
+ If a VNF requires ONAP to assign a Virtual IP (VIP) Address to
ports connected an external network, the port
**MUST NOT** have more than one IPv6 VIP address.
"""
"""
If a VNF has two or more ports that
attach to an external network that require a Virtual IP Address (VIP),
- and the VNF requires ECOMP automation to assign the IP address,
+ and the VNF requires ONAP automation to assign the IP address,
all the Virtual Machines using the VIP address **MUST**
be instantiated in the same Base Module Heat Orchestration Template
or in the same Incremental Module Heat Orchestration Template.
for field, params in fields.items():
for param, files in params.items():
if len(files) > 1:
- bad.append(
- '"%s" "%s" in multiple templates: %s'
- % (
- field,
- param,
- ", ".join("%s: %s" % (k, list(v)) for k, v in files.items()),
+ error = ["{} {} assigned in multiple templates: ".format(field, param)]
+ for file_name, r_ids in files.items():
+ error.append(
+ "In {} it's assigned to {}. ".format(
+ file_name, ", ".join(r_ids)
+ )
)
- )
+ bad.append("".join(error))
assert not bad, "; ".join(bad)
"""
When the VNF's Heat Orchestration Template's
resource ``OS::Neutron::Port`` is attaching
- to an external network (per the ECOMP definition, see
- Requirement R-57424),
+ to an external network,
and an IPv4 address is being cloud assigned by OpenStack's DHCP Service
and the external network IPv4 subnet is to be specified
using the property ``fixed_ips``
* the VNF's Heat Orchestration Template's
resource ``OS::Neutron::Port`` in an Incremental Module is attaching
- to an internal network (per the ECOMP definition, see
- Requirements R-52425 and R-46461)
+ to an internal network
that is created in the Base Module, AND
* an IPv4 address is being cloud assigned by OpenStack's DHCP Service AND
* the internal network IPv4 subnet is to be specified
def test_neutron_port_internal_network(yaml_files):
"""
When the VNF's Heat Orchestration Template's Resource
- ``OS::Neutron::Port`` is attaching to an internal network (per the
- ECOMP definition, see Requirements R-52425 and R-46461),
+ ``OS::Neutron::Port`` is attaching to an internal network,
and the internal network is created in a
different Heat Orchestration Template than the ``OS::Neutron::Port``,
the ``network`` parameter name **MUST**
+++ /dev/null
-# -*- coding: utf8 -*-
-# ============LICENSE_START=======================================================
-# org.onap.vvp/validation-scripts
-# ===================================================================
-# Copyright © 2018 AT&T Intellectual Property. All rights reserved.
-# ===================================================================
-#
-# Unless otherwise specified, all software contained herein is licensed
-# under the Apache License, Version 2.0 (the "License");
-# you may not use this software 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.
-#
-#
-#
-# Unless otherwise specified, all documentation contained herein is licensed
-# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
-# you may not use this documentation except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://creativecommons.org/licenses/by/4.0/
-#
-# Unless required by applicable law or agreed to in writing, documentation
-# 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.
-#
-# ============LICENSE_END============================================
-#
-import os
-import pytest
-
-from .helpers import validates, get_environment_pair
-
-
-def get_keys(template, key):
- """
- Gets the set of keys from an expected dict from the ``template`` mapped to
- the ``key``. If the key is not found, or is not a dict, then an empty
- set is returned
- """
- value = template.get(key)
- if not value or not hasattr(value, "keys"):
- return set()
- else:
- return set(value.keys())
-
-
-@pytest.mark.heat_only
-@validates("R-01896", "R-26124")
-def test_no_unused_parameters_between_env_and_templates(heat_template):
- """
- Check all defined parameters are used in the appropriate Heat template.
- """
- environment_pair = get_environment_pair(heat_template)
- if not environment_pair:
- pytest.skip("No heat/env pair could be identified")
-
- env_parameters = get_keys(environment_pair["eyml"], "parameters")
- template_parameters = get_keys(environment_pair["yyml"], "parameters")
-
- extra_in_template = template_parameters.difference(env_parameters)
- extra_in_env = env_parameters.difference(template_parameters)
-
- msg = (
- "Mismatched parameters detected for the template and environment pair "
- "({basename}). Ensure the parameters exist in both "
- "templates indented under their respective parameters sections. "
- )
- if extra_in_env:
- msg += (
- "The following parameters exist in the env file, but not the "
- "template: {extra_in_env}. "
- )
- if extra_in_template:
- msg += (
- "The following parameters exist in the template file, but not the "
- "environment file: {extra_in_template}"
- )
-
- assert not (extra_in_template or extra_in_env), msg.format(
- basename=os.path.split(environment_pair["name"])[-1],
- extra_in_env=", ".join(extra_in_env),
- extra_in_template=", ".join(extra_in_template),
- )
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
resource property name
"""
+import collections
+
import pytest
from .structures import Heat
+from .structures import HeatProcessor
from .helpers import validates
-VERSION = "1.1.0"
+VERSION = "1.2.0"
def get_non_servers(heat):
"""
If a VNF's Heat Orchestration Template contains the property ``name``
for a non ``OS::Nova::Server`` resource, the intrinsic function
- ``str_replace`` **MUST** be used in conjunction with the ECOMP
+ ``str_replace`` **MUST** be used in conjunction with the ONAP
supplied metadata parameter ``vnf_name`` to generate a unique value.
"""
+ "template ({})"
).format(rid, vnf_name_param, template)
)
- msg = "Improper name property for non-OS::Nova::Server resources. " + ". ".join(bad)
+ msg = (
+ "Improper name property for" " non-OS::Nova::Server resources. "
+ ) + ". ".join(bad)
assert not bad, msg
+
+
+@validates("R-85734")
+def test_non_server_name_unique(yaml_files):
+ """Test name has unique value
+ """
+ non_servers = {}
+ for yaml_file in yaml_files:
+ h = Heat(filepath=yaml_file)
+ non_servers.update(get_non_servers(h))
+ names = collections.defaultdict(set)
+ for rid, resource in non_servers.items():
+ name = HeatProcessor.get_str_replace_name(resource)
+ if name:
+ names[name].add(rid)
+ bad = {key: value for key, value in names.items() if len(value) > 1}
+ delim = "\n" + 4 * " "
+ assert not bad, "Names must be unique," " not shared across resource ids.%s%s" % (
+ delim,
+ delim.join("%s: %s" % (name, list(value)) for name, value in bad.items()),
+ )
# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
-
"""
resources:
{vm-type}_server_{vm-type_index}
"""
import pytest
-
from .structures import Heat
-from .structures import NovaServer
+from .structures import NovaServerProcessor
from .helpers import validates
-VERSION = "1.0.0"
+VERSION = "2.0.0"
# pylint: disable=invalid-name
resources = heat.nova_server_resources
if not resources:
pytest.skip("No Nova Server resources found")
- nova_server = NovaServer()
bad = []
for rid in resources:
- if not nova_server.get_rid_match_tuple(rid)[0]:
+ if not NovaServerProcessor.get_rid_match_tuple(rid)[0]:
bad.append(rid)
assert not bad, "Resource ids %s must match %s" % (
bad,
- nova_server.get_rid_patterns(),
+ NovaServerProcessor.get_rid_patterns(),
)
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
-
import pytest
from tests import cached_yaml as yaml
-
from .helpers import validates
from .utils.vm_types import get_vm_type_for_nova_server
)
assert not invalid_nova_servers, (
- "Invalid OS::Nova::Server resource ids detected {}\n"
+ "Invalid OS::Nova::Server resource ids detected {}. "
"OS::Nova::Server resource ids must be in the form "
- "<vm_type>_server_<vm_type_index> \n"
- "<vm_type> is derived from flavor, image and name properties "
+ "{{vm_type}}_server_{{vm_type_index}} where "
+ "{{vm_type}} is derived from flavor, image and name properties."
"".format(invalid_nova_servers)
)
# ============LICENSE_START=======================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
@validates("R-50436", "R-45188", "R-40499")
def test_nova_server_flavor_parameter(yaml_file):
-
- prop = "flavor"
- check_nova_parameter_format(prop, yaml_file)
+ check_nova_parameter_format("flavor", yaml_file)
@validates("R-51430", "R-54171", "R-87817")
def test_nova_server_name_parameter(yaml_file):
-
- prop = "name"
- check_nova_parameter_format(prop, yaml_file)
+ check_nova_parameter_format("name", yaml_file)
@validates("R-71152", "R-57282", "R-58670")
def test_nova_server_image_parameter(yaml_file):
-
- prop = "image"
- check_nova_parameter_format(prop, yaml_file)
+ check_nova_parameter_format("image", yaml_file)
def check_nova_parameter_format(prop, yaml_file):
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+import os
+
+from tests.helpers import validates
+from tests.structures import Heat
+
+MSG = (
+ "OAM management address can be declared as output in at most 1 template. "
+ + "Output parameter {} found in multiple templates: {}"
+)
+
+
+def find_output_param(param, templates):
+ templates = (t for t in templates if param in Heat(t).outputs)
+ return [os.path.basename(t) for t in templates]
+
+
+@validates("R-18683")
+def test_oam_address_v4_zero_or_one(heat_templates):
+ param = "oam_management_v4_address"
+ templates = find_output_param(param, heat_templates)
+ assert len(templates) <= 1, MSG.format(param, ", ".join(templates))
+
+
+@validates("R-94669")
+def test_oam_address_v6_zero_or_one(heat_templates):
+ param = "oam_management_v6_address"
+ templates = find_output_param(param, heat_templates)
+ assert len(templates) <= 1, MSG.format(param, ", ".join(templates))
# ============LICENSE_START=======================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
from .utils.vm_types import get_vm_type_for_nova_server
-@validates("R-20453", "R-26351", "R-26506" "R-681859")
+@validates("R-20453", "R-26351", "R-26506", "R-681859")
def test_port_resource_ids(heat_template):
"""
Check that all resource ids for ports follow the right
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+import re
+
+from tests.helpers import validates
+from tests.structures import Heat
+from tests.utils import nested_dict
+
+SERVER_ID_PATTERN = re.compile(r"\w+_server_(\d+)")
+PORT_ID_PATTERN = re.compile(r"\w+_(\d+)_\w+\d+")
+
+
+def get_ports(server):
+ props = server.get("properties") or {}
+ networks = props.get("networks") or []
+ for network in networks:
+ r_id = nested_dict.get(network, "port", "get_resource")
+ if r_id:
+ yield r_id
+
+
+@validates("R-304011")
+def test_server_and_port_vmtype_indices_match(yaml_file):
+ # NOTE: This test is only going to validate that the index values
+ # match between the between the ports and server names. Other
+ # tests already cover the other aspects of this requirement
+
+ heat = Heat(filepath=yaml_file)
+ servers = heat.get_resource_by_type("OS::Nova::Server")
+ errors = []
+ for r_id, server in servers.items():
+ match = SERVER_ID_PATTERN.match(r_id)
+ if not match:
+ continue # other tests cover valid server ID format
+ server_index = match.group(1)
+ ports = get_ports(server)
+ for port in ports:
+ port_match = PORT_ID_PATTERN.match(port)
+ if port_match:
+ port_vm_index = port_match.group(1)
+ if port_vm_index != server_index:
+ errors.append(
+ (
+ "{{vm-type_index}} ({}) in port ID ({}) "
+ + "does not match the {{index}} ({}) in the "
+ + "servers resource ID ({})"
+ ).format(port_vm_index, port, server_index, r_id)
+ )
+ assert not errors, ". ".join(errors)
# ============LICENSE_START=======================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ============LICENSE_END============================================
#
-# ECOMP is a trademark and service mark of AT&T Intellectual Property.
-#
import pytest
from tests import cached_yaml as yaml
def test_servers_have_required_metadata(yaml_file):
"""
Check all defined nova server instances have the required metadata:
- vnf_id and vf_module_id
+ vnf_id, vf_module_id, and vnf_name
"""
with open(yaml_file) as fh:
yml = yaml.load(fh)
- # Check if the param vm_role is defined
if "resources" not in yml:
pytest.skip("No resources specified in the heat template")
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START====================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+"""heat parameters
+"""
+
+import collections
+
+import pytest
+
+from .structures import CinderVolumeAttachmentProcessor
+from .structures import NovaServerProcessor
+from .structures import get_all_resources
+from .helpers import validates
+
+VERSION = "2.0.0"
+
+
+class VmClassValidator(object):
+ """validate VM class has unique type
+ """
+
+ def __init__(self):
+ self.vm_counts = None
+ self.vm_classes = None
+ self.vm_rids = None
+ self.vm_types = None
+ self.va_count = None
+
+ def __call__(self, resources):
+ """return (possibly empty) list of error message strings
+ """
+ if not resources:
+ pytest.skip("No resources found")
+ self.vm_counts = collections.defaultdict(set)
+ self.vm_classes = collections.defaultdict(set)
+ self.vm_rids = collections.defaultdict(set)
+ self.vm_types = collections.defaultdict(set)
+ va_config, self.va_count = CinderVolumeAttachmentProcessor.get_config(resources)
+ if not va_config:
+ pytest.skip("No Cinder Volume Attachment configurations found")
+ for rid, resource in resources.items():
+ vm_class = NovaServerProcessor.get_vm_class(resource)
+ if vm_class:
+ vm_class["cinder_volume_attachment"] = va_config.get(rid)
+ match = NovaServerProcessor.get_rid_match_tuple(rid)[1]
+ if match:
+ vm_type = match.groupdict().get("vm_type")
+ if vm_type:
+ self.vm_classes[vm_class].add(rid)
+ self.vm_types[vm_type].add(vm_class)
+ self.vm_counts[vm_type].add(self.va_count.get(rid))
+ self.vm_rids[vm_type].add(rid)
+ if not self.vm_classes:
+ pytest.skip("No vm_classes found")
+ return self.get_errors()
+
+ def get_errors(self):
+ """return (possibly empty) list of error message strings
+ """
+ errors = []
+ for k, v in self.vm_types.items():
+ if len(v) > 1:
+ errors.append(
+ "vm-type %s has class conflict %s"
+ % (k, ", ".join(str(list(self.vm_classes[c])) for c in v))
+ )
+ classes = list(v)
+ errors.append(
+ "Differences %s"
+ % ", ".join([str(key_diff(classes[0], c)) for c in classes[1:]])
+ )
+ for k, v in self.vm_counts.items():
+ if len(v) > 1:
+ errors.append(
+ "Attachment count conflict %s"
+ % ({rid: self.va_count.get(rid) for rid in self.vm_rids[k]})
+ )
+ return errors
+
+
+def key_diff(d1, d2, prefix=""):
+ """Return list of keys which differ between d1 and d2 (dicts)
+ """
+ diff = [prefix + k for k in d1 if k not in d2]
+ diff.extend(prefix + k for k in d2 if k not in d1)
+ if isinstance(d1, dict) and isinstance(d2, dict):
+ for k, v1 in d1.items():
+ if k in d2 and v1 != d2[k]:
+ v2 = d2[k]
+ if isinstance(v1, type(v2)) and isinstance(v1, (dict, frozenset)):
+ diff.extend(key_diff(v1, v2, prefix=prefix + k + "."))
+ else:
+ diff.append(prefix + k)
+ return diff
+
+
+@validates("R-01455")
+def test_vm_class_has_unique_type(yaml_files):
+ """
+ When a VNF’s Heat Orchestration Template creates a Virtual
+ Machine (i.e., OS::Nova::Server), each “class” of VMs MUST be
+ assigned a VNF unique vm-type; where “class” defines VMs that
+ MUST have the following identical characteristics:
+
+ 1. OS::Nova::Server resource property flavor value
+ 2. OS::Nova::Server resource property image value
+ 3. Cinder Volume attachments
+ Each VM in the “class” MUST have the identical Cinder
+ Volume configuration
+ 4. Network attachments and IP address requirements
+ Each VM in the “class” MUST have the the identical number of
+ ports connecting to the identical networks and requiring the
+ identical IP address configuration
+ """
+ resources = get_all_resources(yaml_files)
+ errors = VmClassValidator()(resources)
+ assert not errors, "\n".join(errors)
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START=======================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+import re
+
+import pytest
+from six import string_types
+
+from tests.helpers import validates, get_environment_pair
+from tests.structures import Heat
+
+
+@validates("R-86476")
+def test_vm_role_hardcoded(yaml_file):
+ """
+ Validate vm_role value when hardcoded in the template
+ """
+ heat = Heat(filepath=yaml_file)
+ servers = heat.get_resource_by_type("OS::Nova::Server")
+ errors = []
+ for r_id, server in servers.items():
+ props = server.get("properties") or {}
+ metadata = props.get("metadata") or {}
+ if "vm_role" not in metadata:
+ continue
+ vm_role_value = metadata["vm_role"]
+ if isinstance(vm_role_value, dict):
+ continue # Likely using get_param - validate separately
+ if not re.match(r"^\w+$", vm_role_value):
+ errors.append(
+ "OS::Nova::Server {} vm_role = {}".format(r_id, vm_role_value)
+ )
+
+ msg = (
+ "vm_role's value must only contain alphanumerics and underscores. "
+ + "Invalid vm_role's detected: "
+ + ". ".join(errors)
+ )
+ assert not errors, msg
+
+
+@validates("R-86476")
+def test_vm_role_from_env_file(heat_template):
+ """
+ Validate vm_role when using parameters and env file
+ """
+ pair = get_environment_pair(heat_template)
+ if not pair:
+ pytest.skip("Unable to resolve environment pair")
+ template_params = pair["yyml"].get("parameters") or {}
+ env_params = pair["eyml"].get("parameters") or {}
+
+ if "vm_role" not in template_params:
+ pytest.skip("vm_role not in parameters")
+
+ if "vm_role" not in env_params:
+ pytest.skip("vm_role not in environment file. Error checked elsewhere")
+
+ vm_role = env_params.get("vm_role", "")
+ if not isinstance(vm_role, string_types):
+ vm_role = str(vm_role)
+ msg = "vm_role {} contains non-alphanumeric or non-underscore characters".format(
+ vm_role
+ )
+ assert re.match(r"^\w+$", vm_role), msg
# ============LICENSE_START=======================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2018 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
# ============LICENSE_END============================================
import os
+from tests.helpers import validates
from tests.parametrizers import get_nested_files
from tests.structures import Heat, Resource
return set(filenames).difference(set(nested_files))
-# No requirement ID yet available
+@validates("R-589037")
def test_detected_volume_module_follows_naming_convention(template_dir):
all_files = [os.path.join(template_dir, f) for f in os.listdir(template_dir)]
yaml_files = [f for f in all_files if f.endswith(".yaml") or f.endswith(".yml")]
# ============LICENSE_START=======================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
-
import re
-
import pytest
from tests import cached_yaml as yaml
-
from .utils.vm_types import get_vm_type_for_nova_server
# ============LICENSE_START=======================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
import re
+from tests import cached_yaml as yaml
def get_vm_types_for_resource(resource):
vm_types.extend(list(get_vm_types_for_resource(v)))
return set(vm_types)
+
+
+def get_all_vm_types(yaml_files):
+ """
+ Get all vm_types for a list of yaml files
+ """
+ vm_types = []
+ for yaml_file in yaml_files:
+ with open(yaml_file, "r") as f:
+ yml = yaml.load(f)
+
+ if "resources" not in yml:
+ continue
+
+ vm_types.extend(get_vm_types(yml["resources"]))
+
+ return set(vm_types)
# -*- coding: utf8 -*-
-# ============LICENSE_START=======================================================
+# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
----
-parameters:
- out: 2
- res: 3
- indexed: 4
- unused_env: 4
- indx: 1
\ No newline at end of file
+
+VERSION = "1.0.0"
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START====================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+ui:
+ app-name: VNF Validation Tool
+categories:
+ - name: Environment File Compliance. (Required to Onboard)
+ category: environment_file
+ description:
+ Checks certain parameters are excluded from the .env file, per HOT Requirements.
+ Required for ASDC onboarding, not needed for manual Openstack testing.
+settings:
+ polling-freqency: 1000
+ default-verbosity: Standard
--- /dev/null
+# -*- coding: utf8 -*-
+# ============LICENSE_START====================================================
+# org.onap.vvp/validation-scripts
+# ===================================================================
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the "License");
+# you may not use this software 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.
+#
+#
+#
+# Unless otherwise specified, all documentation contained herein is licensed
+# under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+# you may not use this documentation except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://creativecommons.org/licenses/by/4.0/
+#
+# Unless required by applicable law or agreed to in writing, documentation
+# 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.
+#
+# ============LICENSE_END============================================
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+#
+
+"""
+A GUI that wraps the pytest validations scripts.
+
+To make an executable for windows execute the ``make_exe.bat`` to generate the
+.exe and its associated files. The the necessary files will be written to the
+``dist/vvp/`` directory. This entire directory must be copied to the target machine.
+
+NOTE: This script does require Python 3.6+
+"""
+import appdirs
+import os
+import pytest
+import sys
+import version
+import yaml
+import contextlib
+import multiprocessing
+import queue
+import tempfile
+import webbrowser
+import zipfile
+
+from collections import MutableMapping
+from configparser import ConfigParser
+from multiprocessing import Queue
+from pathlib import Path
+from shutil import rmtree
+from tkinter import (
+ filedialog,
+ font,
+ messagebox,
+ Tk,
+ PanedWindow,
+ BOTH,
+ HORIZONTAL,
+ RAISED,
+ Frame,
+ Label,
+ W,
+ StringVar,
+ OptionMenu,
+ LabelFrame,
+ E,
+ BooleanVar,
+ Entry,
+ Button,
+ WORD,
+ END,
+ Checkbutton,
+ IntVar,
+ Toplevel,
+)
+from tkinter.scrolledtext import ScrolledText
+from typing import Optional, List, Dict, TextIO, Callable, Iterator
+
+VERSION = version.VERSION
+PATH = os.path.dirname(os.path.realpath(__file__))
+OUT_DIR = "output"
+
+
+class ToolTip(object):
+ """
+ create a tooltip for a given widget
+ """
+
+ def __init__(self, widget, text="widget info"):
+ self.waittime = 750 # miliseconds
+ self.wraplength = 180 # pixels
+ self.widget = widget
+ self.text = text
+ self.widget.bind("<Enter>", self.enter)
+ self.widget.bind("<Leave>", self.leave)
+ self.widget.bind("<ButtonPress>", self.leave)
+ self.id = None
+ self.tw = None
+
+ def enter(self, event=None):
+ self.schedule()
+
+ def leave(self, event=None):
+ self.unschedule()
+ self.hidetip()
+
+ def schedule(self):
+ self.unschedule()
+ self.id = self.widget.after(self.waittime, self.showtip)
+
+ def unschedule(self):
+ id = self.id
+ self.id = None
+ if id:
+ self.widget.after_cancel(id)
+
+ def showtip(self, event=None):
+ x = y = 0
+ x, y, cx, cy = self.widget.bbox("insert")
+ x += self.widget.winfo_rootx() + 25
+ y += self.widget.winfo_rooty() + 20
+ # creates a toplevel window
+ self.tw = Toplevel(self.widget)
+ # Leaves only the label and removes the app window
+ self.tw.wm_overrideredirect(True)
+ self.tw.wm_geometry("+%d+%d" % (x, y))
+ label = Label(
+ self.tw,
+ text=self.text,
+ justify="left",
+ background="#ffffff",
+ relief="solid",
+ borderwidth=1,
+ wraplength=self.wraplength,
+ )
+ label.pack(ipadx=1)
+
+ def hidetip(self):
+ tw = self.tw
+ self.tw = None
+ if tw:
+ tw.destroy()
+
+
+class QueueWriter:
+ """``stdout`` and ``stderr`` will be written to this queue by pytest, and
+ pulled into the main GUI application"""
+
+ def __init__(self, log_queue: queue.Queue):
+ """Writes data to the provided queue.
+
+ :param log_queue: the queue instance to write to.
+ """
+ self.queue = log_queue
+
+ def write(self, data: str):
+ """Writes ``data`` to the queue """
+ self.queue.put(data)
+
+ # noinspection PyMethodMayBeStatic
+ def isatty(self) -> bool:
+ """Always returns ``False``"""
+ return False
+
+ def flush(self):
+ """No operation method to satisfy file-like behavior"""
+ pass
+
+
+def get_plugins() -> Optional[List]:
+ """When running in a frozen bundle, plugins need to be registered
+ explicitly. This method will return the required plugins to register
+ based on the run mode"""
+ if hasattr(sys, "frozen"):
+ import pytest_tap.plugin
+
+ return [pytest_tap.plugin]
+ else:
+ return None
+
+
+def run_pytest(
+ template_dir: str,
+ log: TextIO,
+ result_queue: Queue,
+ categories: Optional[list],
+ verbosity: str,
+ report_format: str,
+ halt_on_failure: bool,
+ template_source: str,
+):
+ """Runs pytest using the given ``profile`` in a background process. All
+ ``stdout`` and ``stderr`` are redirected to ``log``. The result of the job
+ will be put on the ``completion_queue``
+
+ :param template_dir: The directory containing the files to be validated.
+ :param log: ` `stderr`` and ``stdout`` of the pytest job will be
+ directed here
+ :param result_queue: Completion status posted here. See :class:`Config`
+ for more information.
+ :param categories: list of optional categories. When provided, pytest
+ will collect and execute all tests that are
+ decorated with any of the passed categories, as
+ well as tests not decorated with a category.
+ :param verbosity: Flag to be passed to pytest to control verbosity.
+ Options are '' (empty string), '-v' (verbose),
+ '-vv' (more verbose).
+ :param report_format: Determines the style of report written. Options are
+ csv, html, or excel
+ :param halt_on_failure: Determines if validation will halt when basic failures
+ are encountered in the input files. This can help
+ prevent a large number of errors from flooding the
+ report.
+ """
+ out_path = "{}/{}".format(PATH, OUT_DIR)
+ if os.path.exists(out_path):
+ rmtree(out_path, ignore_errors=True)
+ with contextlib.redirect_stderr(log), contextlib.redirect_stdout(log):
+ try:
+ args = [
+ "--ignore=app_tests",
+ "--capture=sys",
+ verbosity,
+ "--template-directory={}".format(template_dir),
+ "--report-format={}".format(report_format),
+ "--template-source={}".format(template_source),
+ ]
+ if categories:
+ for category in categories:
+ args.extend(("--category", category))
+ if not halt_on_failure:
+ args.append("--continue-on-failure")
+ pytest.main(args=args, plugins=get_plugins())
+ result_queue.put((True, None))
+ except Exception as e:
+ result_queue.put((False, e))
+
+
+class UserSettings(MutableMapping):
+ FILE_NAME = "UserSettings.ini"
+
+ def __init__(self):
+ user_config_dir = appdirs.AppDirs("org.onap.vvp", "ONAP").user_config_dir
+ if not os.path.exists(user_config_dir):
+ os.makedirs(user_config_dir, exist_ok=True)
+ self._settings_path = os.path.join(user_config_dir, self.FILE_NAME)
+ self._config = ConfigParser()
+ self._config.read(self._settings_path)
+
+ def __getitem__(self, k):
+ return self._config["DEFAULT"][k]
+
+ def __setitem__(self, k, v) -> None:
+ self._config["DEFAULT"][k] = v
+
+ def __delitem__(self, v) -> None:
+ del self._config["DEFAULT"][v]
+
+ def __len__(self) -> int:
+ return len(self._config["DEFAULT"])
+
+ def __iter__(self) -> Iterator:
+ return iter(self._config["DEFAULT"])
+
+ def save(self):
+ with open(self._settings_path, "w") as f:
+ self._config.write(f)
+
+
+class Config:
+ """
+ Configuration for the Validation GUI Application
+
+ Attributes
+ ----------
+ ``log_queue`` Queue for the ``stdout`` and ``stderr` of
+ the background job
+ ``log_file`` File-like object (write only!) that writes to
+ the ``log_queue``
+ ``status_queue`` Job completion status of the background job is
+ posted here as a tuple of (bool, Exception).
+ The first parameter is True if the job completed
+ successfully, and False otherwise. If the job
+ failed, then an Exception will be provided as the
+ second element.
+ ``command_queue`` Used to send commands to the GUI. Currently only
+ used to send shutdown commands in tests.
+ """
+
+ DEFAULT_FILENAME = "vvp-config.yaml"
+ DEFAULT_POLLING_FREQUENCY = "1000"
+
+ def __init__(self, config: dict = None):
+ """Creates instance of application configuration.
+
+ :param config: override default configuration if provided."""
+ if config:
+ self._config = config
+ else:
+ with open(self.DEFAULT_FILENAME, "r") as f:
+ self._config = yaml.load(f)
+ self._user_settings = UserSettings()
+ self._watched_variables = []
+ self._validate()
+ self._manager = multiprocessing.Manager()
+ self.log_queue = self._manager.Queue()
+ self.status_queue = self._manager.Queue()
+ self.log_file = QueueWriter(self.log_queue)
+ self.command_queue = self._manager.Queue()
+
+ def watch(self, *variables):
+ """Traces the variables and saves their settings for the user. The
+ last settings will be used where available"""
+ self._watched_variables = variables
+ for var in self._watched_variables:
+ var.trace_add("write", self.save_settings)
+
+ def save_settings(self, *args):
+ """Save the value of all watched variables to user settings"""
+ for var in self._watched_variables:
+ self._user_settings[var._name] = str(var.get())
+ self._user_settings.save()
+
+ @property
+ def app_name(self) -> str:
+ """Name of the application (displayed in title bar)"""
+ app_name = self._config["ui"].get("app-name", "VNF Validation Tool")
+ return "{} - {}".format(app_name, VERSION)
+
+ @property
+ def category_names(self) -> List[str]:
+ """List of validation profile names for display in the UI"""
+ return [category["name"] for category in self._config["categories"]]
+
+ @property
+ def polling_frequency(self) -> int:
+ """Returns the frequency (in ms) the UI polls the queue communicating
+ with any background job"""
+ return int(
+ self._config["settings"].get(
+ "polling-frequency", self.DEFAULT_POLLING_FREQUENCY
+ )
+ )
+
+ def default_verbosity(self, levels: Dict[str, str]) -> str:
+ requested_level = self._user_settings.get("verbosity") or self._config[
+ "settings"
+ ].get("default-verbosity", "Standard")
+ keys = [key for key in levels]
+ for key in levels:
+ if key.lower().startswith(requested_level.lower()):
+ return key
+ raise RuntimeError(
+ "Invalid default-verbosity level {}. Valid"
+ "values are {}".format(requested_level, ", ".join(keys))
+ )
+
+ def get_description(self, category_name: str) -> str:
+ """Returns the description associated with the category name"""
+ return self._get_category(category_name)["description"]
+
+ def get_category(self, category_name: str) -> str:
+ """Returns the category associated with the category name"""
+ return self._get_category(category_name).get("category", "")
+
+ def get_category_value(self, category_name: str) -> str:
+ """Returns the saved value for a category name"""
+ return self._user_settings.get(category_name, 0)
+
+ def _get_category(self, category_name: str) -> Dict[str, str]:
+ """Returns the profile definition"""
+ for category in self._config["categories"]:
+ if category["name"] == category_name:
+ return category
+ raise RuntimeError(
+ "Unexpected error: No category found in vvp-config.yaml "
+ "with a name of " + category_name
+ )
+
+ @property
+ def default_report_format(self):
+ return self._user_settings.get("report_format", "HTML")
+
+ @property
+ def report_formats(self):
+ return ["CSV", "Excel", "HTML"]
+
+ @property
+ def default_input_format(self):
+ requested_default = self._user_settings.get("input_format") or self._config[
+ "settings"
+ ].get("default-input-format")
+ if requested_default in self.input_formats:
+ return requested_default
+ else:
+ return self.input_formats[0]
+
+ @property
+ def input_formats(self):
+ return ["Directory (Uncompressed)", "ZIP File"]
+
+ @property
+ def default_halt_on_failure(self):
+ setting = self._user_settings.get("halt_on_failure", "True")
+ return setting.lower() == "true"
+
+ def _validate(self):
+ """Ensures the config file is properly formatted"""
+ categories = self._config["categories"]
+
+ # All profiles have required keys
+ expected_keys = {"name", "description"}
+ for category in categories:
+ actual_keys = set(category.keys())
+ missing_keys = expected_keys.difference(actual_keys)
+ if missing_keys:
+ raise RuntimeError(
+ "Error in vvp-config.yaml file: "
+ "Required field missing in category. "
+ "Missing: {} "
+ "Categories: {}".format(",".join(missing_keys), category)
+ )
+
+
+class ValidatorApp:
+ VERBOSITY_LEVELS = {"Less": "", "Standard (-v)": "-v", "More (-vv)": "-vv"}
+
+ def __init__(self, config: Config = None):
+ """Constructs the GUI element of the Validation Tool"""
+ self.task = None
+ self.config = config or Config()
+
+ self._root = Tk()
+ self._root.title(self.config.app_name)
+ self._root.protocol("WM_DELETE_WINDOW", self.shutdown)
+
+ main_window = PanedWindow(self._root)
+ main_window.pack(fill=BOTH, expand=1)
+
+ control_panel = PanedWindow(
+ main_window, orient=HORIZONTAL, sashpad=4, sashrelief=RAISED
+ )
+ actions = Frame(control_panel)
+ control_panel.add(actions)
+ control_panel.paneconfigure(actions, minsize=250)
+
+ # profile start
+ number_of_categories = len(self.config.category_names)
+ category_frame = LabelFrame(actions, text="Additional Validation Categories:")
+ category_frame.grid(row=1, column=1, columnspan=3, pady=5, sticky="we")
+
+ self.categories = []
+
+ for x in range(0, number_of_categories):
+ category_name = self.config.category_names[x]
+ category_value = IntVar(value=0)
+ category_value._name = "category_{}".format(category_name.replace(" ", "_"))
+ category_value.set(self.config.get_category_value(category_value._name))
+ self.categories.append(category_value)
+ category_checkbox = Checkbutton(
+ category_frame, text=category_name, variable=self.categories[x]
+ )
+ ToolTip(category_checkbox, self.config.get_description(category_name))
+ category_checkbox.grid(row=x + 1, column=1, columnspan=2, sticky="w")
+
+ settings_frame = LabelFrame(actions, text="Settings")
+ settings_frame.grid(row=3, column=1, columnspan=3, pady=10, sticky="we")
+ verbosity_label = Label(settings_frame, text="Verbosity:")
+ verbosity_label.grid(row=1, column=1, sticky=W)
+ self.verbosity = StringVar(self._root, name="verbosity")
+ self.verbosity.set(self.config.default_verbosity(self.VERBOSITY_LEVELS))
+ verbosity_menu = OptionMenu(
+ settings_frame, self.verbosity, *tuple(self.VERBOSITY_LEVELS.keys())
+ )
+ verbosity_menu.config(width=25)
+ verbosity_menu.grid(row=1, column=2, columnspan=3, sticky=E, pady=5)
+
+ report_format_label = Label(settings_frame, text="Report Format:")
+ report_format_label.grid(row=2, column=1, sticky=W)
+ self.report_format = StringVar(self._root, name="report_format")
+ self.report_format.set(self.config.default_report_format)
+ report_format_menu = OptionMenu(
+ settings_frame, self.report_format, *self.config.report_formats
+ )
+ report_format_menu.config(width=25)
+ report_format_menu.grid(row=2, column=2, columnspan=3, sticky=E, pady=5)
+
+ input_format_label = Label(settings_frame, text="Input Format:")
+ input_format_label.grid(row=3, column=1, sticky=W)
+ self.input_format = StringVar(self._root, name="input_format")
+ self.input_format.set(self.config.default_input_format)
+ input_format_menu = OptionMenu(
+ settings_frame, self.input_format, *self.config.input_formats
+ )
+ input_format_menu.config(width=25)
+ input_format_menu.grid(row=3, column=2, columnspan=3, sticky=E, pady=5)
+
+ self.halt_on_failure = BooleanVar(self._root, name="halt_on_failure")
+ self.halt_on_failure.set(self.config.default_halt_on_failure)
+ halt_on_failure_label = Label(settings_frame, text="Halt on Basic Failures:")
+ halt_on_failure_label.grid(row=4, column=1, sticky=E, pady=5)
+ halt_checkbox = Checkbutton(
+ settings_frame, offvalue=False, onvalue=True, variable=self.halt_on_failure
+ )
+ halt_checkbox.grid(row=4, column=2, columnspan=2, sticky=W, pady=5)
+
+ directory_label = Label(actions, text="Template Location:")
+ directory_label.grid(row=4, column=1, pady=5, sticky=W)
+ self.template_source = StringVar(self._root, name="template_source")
+ directory_entry = Entry(actions, width=40, textvariable=self.template_source)
+ directory_entry.grid(row=4, column=2, pady=5, sticky=W)
+ directory_browse = Button(actions, text="...", command=self.ask_template_source)
+ directory_browse.grid(row=4, column=3, pady=5, sticky=W)
+
+ validate = Button(actions, text="Validate Templates", command=self.validate)
+ validate.grid(row=5, column=1, columnspan=2, pady=5)
+
+ self.result_panel = Frame(actions)
+ # We'll add these labels now, and then make them visible when the run completes
+ self.completion_label = Label(self.result_panel, text="Validation Complete!")
+ self.result_label = Label(
+ self.result_panel, text="View Report", fg="blue", cursor="hand2"
+ )
+ self.underline(self.result_label)
+ self.result_label.bind("<Button-1>", self.open_report)
+ self.result_panel.grid(row=6, column=1, columnspan=2)
+ control_panel.pack(fill=BOTH, expand=1)
+
+ main_window.add(control_panel)
+
+ self.log_panel = ScrolledText(main_window, wrap=WORD, width=120, height=20)
+ self.log_panel.configure(font=font.Font(family="Courier New", size="11"))
+ self.log_panel.pack(fill=BOTH, expand=1)
+
+ main_window.add(self.log_panel)
+
+ # Briefly add the completion and result labels so the window size includes
+ # room for them
+ self.completion_label.pack()
+ self.result_label.pack() # Show report link
+ self._root.after_idle(
+ lambda: (
+ self.completion_label.pack_forget(),
+ self.result_label.pack_forget(),
+ )
+ )
+
+ self.config.watch(
+ *self.categories,
+ self.verbosity,
+ self.input_format,
+ self.report_format,
+ self.halt_on_failure,
+ )
+ self.schedule(self.execute_pollers)
+
+ def ask_template_source(self):
+ if self.input_format.get() == "ZIP File":
+ template_source = filedialog.askopenfilename(
+ title="Select Archive",
+ filetypes=(("ZIP Files", "*.zip"), ("All Files", "*")),
+ )
+ else:
+ template_source = filedialog.askdirectory()
+ self.template_source.set(template_source)
+
+ def validate(self):
+ """Run the pytest validations in a background process"""
+ if not self.delete_prior_report():
+ return
+
+ if not self.template_source.get():
+ self.ask_template_source()
+
+ template_dir = self.resolve_template_dir()
+
+ if template_dir:
+ self.kill_background_task()
+ self.clear_log()
+ self.completion_label.pack_forget()
+ self.result_label.pack_forget()
+ self.task = multiprocessing.Process(
+ target=run_pytest,
+ args=(
+ template_dir,
+ self.config.log_file,
+ self.config.status_queue,
+ self.categories_list(),
+ self.VERBOSITY_LEVELS[self.verbosity.get()],
+ self.report_format.get().lower(),
+ self.halt_on_failure.get(),
+ self.template_source.get(),
+ ),
+ )
+ self.task.daemon = True
+ self.task.start()
+
+ @property
+ def title(self):
+ """Returns the text displayed in the title bar of the application"""
+ return self._root.title()
+
+ def execute_pollers(self):
+ """Call all methods that require periodic execution, and re-schedule
+ their execution for the next polling interval"""
+ try:
+ self.poll_log_file()
+ self.poll_status_queue()
+ self.poll_command_queue()
+ finally:
+ self.schedule(self.execute_pollers)
+
+ @staticmethod
+ def _drain_queue(q):
+ """Yields values from the queue until empty"""
+ while True:
+ try:
+ yield q.get(block=False)
+ except queue.Empty:
+ break
+
+ def poll_command_queue(self):
+ """Picks up command strings from the commmand queue, and
+ dispatches it for execution. Only SHUTDOWN is supported
+ currently"""
+ for command in self._drain_queue(self.config.command_queue):
+ if command == "SHUTDOWN":
+ self.shutdown()
+
+ def poll_status_queue(self):
+ """Checks for completion of the job, and then displays the View Report link
+ if it was successful or writes the exception to the ``log_panel`` if
+ it fails."""
+ for is_success, e in self._drain_queue(self.config.status_queue):
+ if is_success:
+ self.completion_label.pack()
+ self.result_label.pack() # Show report link
+ else:
+ self.log_panel.insert(END, str(e))
+
+ def poll_log_file(self):
+ """Reads captured stdout and stderr from the log queue and writes it to the
+ log panel."""
+ for line in self._drain_queue(self.config.log_queue):
+ self.log_panel.insert(END, line)
+ self.log_panel.see(END)
+
+ def schedule(self, func: Callable):
+ """Schedule the callable ``func`` to be executed according to
+ the polling_frequency"""
+ self._root.after(self.config.polling_frequency, func)
+
+ def clear_log(self):
+ """Removes all log entries from teh log panel"""
+ self.log_panel.delete("1.0", END)
+
+ def delete_prior_report(self) -> bool:
+ """Attempts to delete the current report, and pops up a warning message
+ to the user if it can't be deleted. This will force the user to
+ close the report before re-running the validation. Returns True if
+ the file was deleted or did not exist, or False otherwise"""
+ if not os.path.exists(self.report_file_path):
+ return True
+
+ try:
+ os.remove(self.report_file_path)
+ return True
+ except OSError as e:
+ messagebox.showerror(
+ "Error",
+ "Please close or rename the open report file before re-validating",
+ )
+ return False
+
+ @property
+ def report_file_path(self):
+ ext_mapping = {"csv": "csv", "html": "html", "excel": "xlsx"}
+ ext = ext_mapping.get(self.report_format.get().lower())
+ return os.path.join(PATH, OUT_DIR, "report.{}".format(ext))
+
+ def open_report(self, event):
+ """Open the report in the user's default browser"""
+ webbrowser.open_new("file://{}".format(self.report_file_path))
+
+ def start(self):
+ """Start the event loop of the application. This method does not return"""
+ self._root.mainloop()
+
+ @staticmethod
+ def underline(label):
+ """Apply underline format to an existing label"""
+ f = font.Font(label, label.cget("font"))
+ f.configure(underline=True)
+ label.configure(font=f)
+
+ def kill_background_task(self):
+ if self.task and self.task.is_alive():
+ self.task.terminate()
+ for _ in self._drain_queue(self.config.log_queue):
+ pass
+
+ def shutdown(self):
+ """Shutdown the application"""
+ self.kill_background_task()
+ self._root.destroy()
+
+ def check_template_source_is_valid(self):
+ """Verifies the value of template source exists and of valid type based
+ on input setting"""
+ if not self.template_source.get():
+ return False
+ template_path = Path(self.template_source.get())
+
+ if not template_path.exists():
+ messagebox.showerror(
+ "Error",
+ "Input does not exist. Please provide a valid file or directory.",
+ )
+ return False
+
+ if self.input_format.get() == "ZIP File":
+ if zipfile.is_zipfile(template_path):
+ return True
+ else:
+ messagebox.showerror(
+ "Error", "Expected ZIP file, but input is not a valid ZIP file"
+ )
+ return False
+ else:
+ if template_path.is_dir():
+ return True
+ else:
+ messagebox.showerror(
+ "Error", "Expected directory, but input is not a directory"
+ )
+ return False
+
+ def resolve_template_dir(self) -> str:
+ """Extracts the zip file to a temporary directory if needed, otherwise
+ returns the directory supplied to template source. Returns empty string
+ if the template source isn't valid"""
+ if not self.check_template_source_is_valid():
+ return ""
+ if self.input_format.get() == "ZIP File":
+ temp_dir = tempfile.mkdtemp()
+ archive = zipfile.ZipFile(self.template_source.get())
+ archive.extractall(path=temp_dir)
+ return temp_dir
+ else:
+ return self.template_source.get()
+
+ def categories_list(self) -> list:
+ categories = []
+ selected_categories = self.categories
+ for x in range(0, len(selected_categories)):
+ if selected_categories[x].get():
+ category = self.config.category_names[x]
+ categories.append(self.config.get_category(category))
+ return categories
+
+
+if __name__ == "__main__":
+ multiprocessing.freeze_support() # needed for PyInstaller to work
+ ValidatorApp().start()
# ============LICENSE_START=======================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
jinja2==2.10
yamllint==1.12.1
six==1.12.0
+pyinstaller
[tox]
skipsdist=True
-envlist = py3,style
+envlist = py36,style
[testenv]
distribute = False
+basepython = python3.6
commands =
{envpython} --version
pytest --version
coverage run --module pytest ice_validator/tests --self-test -rxXs
coverage xml
-deps = -rrequirements.txt
+deps = --no-use-pep517
+ -rrequirements.txt
flake8==3.4.1
coverage==4.5.1
[testenv:style]
commands = flake8 ice_validator
-[testenv:py3]
+[testenv:py36]
basepython=python3.6
[flake8]