summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/Chapter4/Modularity.rst20
-rw-r--r--docs/Chapter4/Resiliency.rst2
-rw-r--r--docs/Chapter5/Heat/ONAP Heat Cinder Volumes.rst2
-rw-r--r--docs/Chapter5/Heat/ONAP Heat Orchestration Template Format.rst19
-rw-r--r--docs/Chapter5/Heat/ONAP Heat Orchestration Templates Overview.rst14
-rw-r--r--docs/Chapter5/Heat/ONAP Heat Resource ID and Parameter Naming Convention/Nova Parameters.rst8
-rw-r--r--docs/Chapter5/Tosca.rst2
-rwxr-xr-xdocs/Chapter7/Monitoring-And-Management.rst8
-rwxr-xr-xdocs/Chapter7/VNF-On-boarding-and-package-management.rst1
-rw-r--r--docs/Chapter8/Ansible-JSON-Key-Value-Description.rst6
-rw-r--r--docs/Chapter8/Ansible-Playbook-Examples.rst10
-rw-r--r--docs/Chapter8/Chef-JSON-Key-Value-Description.rst44
-rw-r--r--etc/requirements.txt1
-rw-r--r--fix_invalid_metadata.py306
-rw-r--r--gen_requirement_changes.py9
15 files changed, 402 insertions, 50 deletions
diff --git a/docs/Chapter4/Modularity.rst b/docs/Chapter4/Modularity.rst
index 6372342..157dccb 100644
--- a/docs/Chapter4/Modularity.rst
+++ b/docs/Chapter4/Modularity.rst
@@ -27,8 +27,8 @@ ONAP VNF Modularity Overview
With VNF Modularity, a single VNF may be composed from one or more Heat
Orchestration Templates, each of which represents a subset of the
-overall VNF. These component parts are referred to as “\ *VNF
-Modules*\ ”. During orchestration, these modules are deployed
+overall VNF. These component parts are referred to as "\ *VNF
+Modules*\ ". During orchestration, these modules are deployed
incrementally to create the complete VNF.
A modular Heat Orchestration Template can be either one of the following
@@ -82,7 +82,7 @@ ONAP supports a modular Heat Orchestration Template design pattern,
referred to as *VNF Modularity.* With this approach, a single VNF may be
composed from one or more Heat Orchestration Templates, each of which
represents a subset of the overall VNF. These component parts are
-referred to as “\ *VNF Modules*\ ”. During orchestration, these modules
+referred to as "\ *VNF Modules*\ ". During orchestration, these modules
are deployed incrementally to create the complete VNF.
A modular Heat Orchestration Template can be either one of the following
@@ -94,8 +94,8 @@ types:
3. Cinder Volume Module
-A VNF must be composed of one “base” module and may be composed of zero
-to many “incremental” modules. The base module must be deployed first,
+A VNF must be composed of one "base" module and may be composed of zero
+to many "incremental" modules. The base module must be deployed first,
prior to the incremental modules.
ONAP also supports the concept of an optional, independently deployed
@@ -174,8 +174,8 @@ b. Incremental modules for incremental scaling units
ii. May be separated by VM type for multi-dimensional scaling
-With no growth units, Option 2 is equivalent to the “One Heat Template
-per VNF” model.
+With no growth units, Option 2 is equivalent to the "One Heat Template
+per VNF" model.
Note that modularization of VNFs is not required. A single Heat
Orchestration Template (a base module) may still define a complete VNF,
@@ -193,13 +193,13 @@ There are some rules to follow when building modular VNF templates:
a. Must include all shared resources (e.g., private networks, server
groups, security groups)
- b. Must expose all shared resources (by UUID) as “outputs” in its
+ b. Must expose all shared resources (by UUID) as "outputs" in its
associated Heat template (i.e., ONAP Base Module Output
Parameters)
c. May include initial set of VMs
- d. May be operational as a stand-alone “minimum” configuration of the
+ d. May be operational as a stand-alone "minimum" configuration of the
VNF
2. VNFs may have one or more incremental modules which:
@@ -221,7 +221,7 @@ There are some rules to follow when building modular VNF templates:
ii. must not be dependent on other Add-On VNF Modules
e. Multiple instances of an incremental Module may be added to the
- same VNF (e.g., incrementally grow a VNF by a fixed “add-on”
+ same VNF (e.g., incrementally grow a VNF by a fixed "add-on"
growth units)
3. Each VNF Module (base or incremental) may have (optional) an
diff --git a/docs/Chapter4/Resiliency.rst b/docs/Chapter4/Resiliency.rst
index ab188d6..a61bd01 100644
--- a/docs/Chapter4/Resiliency.rst
+++ b/docs/Chapter4/Resiliency.rst
@@ -128,7 +128,7 @@ Avoid performance-sapping data center-to-data center replication delay
by applying techniques such as caching and persistent transaction paths
- Eliminate replication delay impact between data centers by using a
concept of stickiness (i.e., once a client is routed to data center "A",
-the client will stay with Data center “A” until the entire session is
+the client will stay with Data center "A" until the entire session is
completed).
Minimize Cross Data-Center Traffic Requirements
diff --git a/docs/Chapter5/Heat/ONAP Heat Cinder Volumes.rst b/docs/Chapter5/Heat/ONAP Heat Cinder Volumes.rst
index 6ce2cad..4f2861f 100644
--- a/docs/Chapter5/Heat/ONAP Heat Cinder Volumes.rst
+++ b/docs/Chapter5/Heat/ONAP Heat Cinder Volumes.rst
@@ -66,7 +66,7 @@ Parameters.
:target: VNF
:keyword: MUST
:validation_mode: static
- :updated: casablanca
+ :introduced: casablanca
A VNF's Heat Orchestration Template's Cinder Volume Template **MUST**
contain either
diff --git a/docs/Chapter5/Heat/ONAP Heat Orchestration Template Format.rst b/docs/Chapter5/Heat/ONAP Heat Orchestration Template Format.rst
index bf810b7..edc3b34 100644
--- a/docs/Chapter5/Heat/ONAP Heat Orchestration Template Format.rst
+++ b/docs/Chapter5/Heat/ONAP Heat Orchestration Template Format.rst
@@ -12,6 +12,7 @@ As stated above, Heat Orchestration templates must be defined in YAML.
:id: R-92635
:keyword: MUST
:validation_mode: static
+ :introduced: casablanca
A VNF's Heat Orchestration Template **MUST** be compliant with the
OpenStack Template Guide.
@@ -130,6 +131,7 @@ attributes (e.g., type, label) defined as nested elements.
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF Heat Orchestration's template's parameter **MUST** be used
in a resource with the exception of the parameters for the
@@ -139,6 +141,7 @@ attributes (e.g., type, label) defined as nested elements.
:id: R-91273
:target: VNF
:keyword: MAY NOT
+ :updated: casablanca
A VNF Heat Orchestration's template's parameter for the
``OS::Nova::Server`` resource property ``availability_zone``
@@ -181,6 +184,7 @@ type
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF's Heat Orchestration Template's parameter type **MUST** be one of
the following values:
@@ -238,6 +242,7 @@ default
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
If a VNF Heat Orchestration Template parameter has a default value,
it **MUST** be enumerated in the environment file.
@@ -275,6 +280,7 @@ that defines a list of constraints to apply to the parameter.
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF's Heat Orchestration Template's parameter defined
in a non-nested YAML file as type
@@ -285,6 +291,7 @@ that defines a list of constraints to apply to the parameter.
:id: R-40518
:target: VNF
:keyword: MAY
+ :updated: casablanca
A VNF's Heat Orchestration Template's parameter defined
in a non-nested YAML file as type
@@ -294,6 +301,7 @@ that defines a list of constraints to apply to the parameter.
:id: R-96227
:target: VNF
:keyword: MAY
+ :updated: casablanca
A VNF's Heat Orchestration Template's parameter defined
in a non-nested YAML file as type
@@ -303,6 +311,7 @@ that defines a list of constraints to apply to the parameter.
:id: R-79817
:target: VNF
:keyword: MAY
+ :updated: casablanca
A VNF's Heat Orchestration Template's parameter defined
in a non-nested YAML file as
@@ -312,6 +321,7 @@ that defines a list of constraints to apply to the parameter.
:id: R-06613
:target: VNF
:keyword: MAY
+ :updated: casablanca
A VNF's Heat Orchestration Template's parameter defined
in a non-nested YAML file as type
@@ -322,6 +332,7 @@ that defines a list of constraints to apply to the parameter.
:target: VNF
:keyword: MUST NOT
:validation_mode: static
+ :updated: casablanca
A VNF's Heat Orchestration Template's parameter defined
in a nested YAML file
@@ -448,6 +459,7 @@ resources
:id: R-40551
:target: VNF
:keyword: MAY
+ :updated: casablanca
A VNF's Heat Orchestration Template's Nested YAML files **MAY**
(or **MAY NOT**) contain the section ``resources:``.
@@ -554,6 +566,7 @@ be provided in place, or via a function
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
If a VNF's Heat Orchestration Template resource attribute
``property:`` uses a nested ``get_param``, the nested
@@ -569,6 +582,7 @@ The resource attribute ``metadata`` is an OpenStack optional attribute.
:target: VNF
:keyword: MUST
:validation_mode: static
+ :introduced: casablanca
A VNF's Heat Orchestration Template's Resource **MAY** declare the
attribute ``metadata``.
@@ -607,6 +621,7 @@ deletion_policy
:id: R-43740
:target: VNF
:keyword: MAY
+ :updated: casablanca
VNF's Heat Orchestration Template's Resource **MAY** declare the
attribute ``deletion_policy:``.
@@ -627,6 +642,7 @@ external_id
:id: R-78569
:target: VNF
:keyword: MAY
+ :updated: casablanca
VNF's Heat Orchestration Template's Resource **MAY** declare the
attribute ``external_id:``.
@@ -675,6 +691,7 @@ A VNF's Heat Orchestration Template's environment file is a yaml text file.
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF's Heat Orchestration template **MUST** have a
corresponding environment file.
@@ -690,6 +707,7 @@ the mandatory parameter section.
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF's Heat Orchestration template's Environment File **MUST**
contain the ``parameters:`` section.
@@ -698,6 +716,7 @@ the mandatory parameter section.
:id: R-68198
:target: VNF
:keyword: MAY
+ :updated: casablanca
A VNF's Heat Orchestration template's Environment File's
``parameters:`` section **MAY** (or **MAY NOT**) enumerate parameters.
diff --git a/docs/Chapter5/Heat/ONAP Heat Orchestration Templates Overview.rst b/docs/Chapter5/Heat/ONAP Heat Orchestration Templates Overview.rst
index 2d59cb2..acc9ef3 100644
--- a/docs/Chapter5/Heat/ONAP Heat Orchestration Templates Overview.rst
+++ b/docs/Chapter5/Heat/ONAP Heat Orchestration Templates Overview.rst
@@ -34,6 +34,7 @@ deployed incrementally to create the complete VNF.
:id: R-33132
:target: VNF
:keyword: MAY
+ :updated: casablanca
A VNF's Heat Orchestration Template **MAY** be
1.) Base Module Heat Orchestration Template (also referred to as a
@@ -47,6 +48,7 @@ deployed incrementally to create the complete VNF.
:id: R-37028
:target: VNF
:keyword: MUST
+ :updated: casablanca
A VNF **MUST** be composed of one Base Module
@@ -61,6 +63,7 @@ deployed incrementally to create the complete VNF.
:id: R-20974
:target: VNF
:keyword: MUST
+ :updated: casablanca
At orchestration time, the VNF's Base Module **MUST**
be deployed first, prior to any incremental modules.
@@ -134,6 +137,7 @@ on another instance (e.g., during a failover activity).
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF's Cinder Volume Module, when it exists, **MUST** be 1:1
with a Base module or Incremental module.
@@ -146,6 +150,7 @@ Module.
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF's Base Module **MUST** have a corresponding Environment File.
@@ -154,6 +159,7 @@ Module.
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF's Incremental Module **MUST** have a corresponding Environment File
@@ -162,6 +168,7 @@ Module.
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF's Cinder Volume Module **MUST** have a corresponding environment file
@@ -262,6 +269,7 @@ Base Modules
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF Heat Orchestration Template's Base Module file name **MUST** include
case insensitive 'base' in the filename and
@@ -298,6 +306,7 @@ Incremental Modules
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
VNF Heat Orchestration Template's Incremental Module file name
**MUST** contain only alphanumeric characters and underscores
@@ -333,6 +342,7 @@ Cinder Volume Modules
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF Heat Orchestration Template's Cinder Volume Module **MUST**
be named identical to the base or incremental module it is supporting with
@@ -343,6 +353,7 @@ Cinder Volume Modules
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
VNF Heat Orchestration Template's Cinder Volume Module's Environment File
**MUST** be named identical to the VNF Heat Orchestration Template's
@@ -357,6 +368,7 @@ Nested Heat file
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
VNF Heat Orchestration Template's Nested YAML file name **MUST** contain
only alphanumeric characters and underscores '_' and
@@ -455,6 +467,7 @@ ONAP Volume Module Output Parameters
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF's Heat Orchestration Template's Cinder Volume Module Output
Parameter(s)
@@ -472,6 +485,7 @@ template is associated with.
:target: VNF
:keyword: MUST
:validation_mode: static
+ :updated: casablanca
A VNF's Heat Orchestration Templates' Cinder Volume Module Output
Parameter's name and type **MUST** match the input parameter name and type
diff --git a/docs/Chapter5/Heat/ONAP Heat Resource ID and Parameter Naming Convention/Nova Parameters.rst b/docs/Chapter5/Heat/ONAP Heat Resource ID and Parameter Naming Convention/Nova Parameters.rst
index 5f16802..b5501fd 100644
--- a/docs/Chapter5/Heat/ONAP Heat Resource ID and Parameter Naming Convention/Nova Parameters.rst
+++ b/docs/Chapter5/Heat/ONAP Heat Resource ID and Parameter Naming Convention/Nova Parameters.rst
@@ -31,7 +31,7 @@ Requirement R-82481 defines how the ``{vm-type}`` is used.
:target: VNF
:keyword: MUST
:validation_mode: static
- :updated: casablanca
+ :introduced: casablanca
A VNF's Heat Orchestration Template's ``OS::Nova::Server`` resource's
@@ -70,7 +70,7 @@ Property: image
:target: VNF
:keyword: MUST
:validation_mode: static
- :updated: casablanca
+ :introduced: casablanca
The VNF's Heat Orchestration Template's Resource ``OS::Nova::Server``
property ``image`` value **MUST** be be obtained via a ``get_param``.
@@ -141,7 +141,7 @@ Property: flavor
:target: VNF
:keyword: MUST
:validation_mode: static
- :updated: casablanca
+ :introduced: casablanca
The VNF's Heat Orchestration Template's Resource ``OS::Nova::Server``
property ``flavor`` value **MUST** be be obtained via a ``get_param``.
@@ -209,7 +209,7 @@ Property: Name
:target: VNF
:keyword: MUST
:validation_mode: static
- :updated: casablanca
+ :introduced: casablanca
The VNF's Heat Orchestration Template's Resource ``OS::Nova::Server``
property ``name`` value **MUST** be be obtained via a ``get_param``.
diff --git a/docs/Chapter5/Tosca.rst b/docs/Chapter5/Tosca.rst
index 9970dbc..93436a8 100644
--- a/docs/Chapter5/Tosca.rst
+++ b/docs/Chapter5/Tosca.rst
@@ -945,7 +945,7 @@ model as described in YAML 1.1. Pending on Shitao proposal (see
NFVIFA(17)000110 discussion paper)
**[editor note]** new relationship type as suggested in Matt
-presentation. Slide 8. With specific rules of “valid\_target\_type”
+presentation. Slide 8. With specific rules of "valid\_target\_type"
+---------------------------+--------------------------------------+
| **Shorthand Name** | VirtualStorage |
diff --git a/docs/Chapter7/Monitoring-And-Management.rst b/docs/Chapter7/Monitoring-And-Management.rst
index 8ff1eb3..38295ab 100755
--- a/docs/Chapter7/Monitoring-And-Management.rst
+++ b/docs/Chapter7/Monitoring-And-Management.rst
@@ -382,7 +382,7 @@ minimizing changes to data delivery.
:keyword: SHOULD
:impacts: dcae
:validation_mode: in_service
- :introduced: casblanca
+ :introduced: casablanca
The xNF **SHOULD** deliver event records that fall into the event domains
supported by VES.
@@ -393,7 +393,7 @@ minimizing changes to data delivery.
:keyword: MUST
:impacts: dcae
:validation_mode: in_service
- :introduced: casblanca
+ :introduced: casablanca
The xNF **MUST** deliver event records to ONAP using the common transport
mechanisms and protocols defined in this document.
@@ -418,7 +418,7 @@ data sets.
:keyword: MUST
:impacts: dcae
:validation_mode: none
- :introduced: casblanca
+ :introduced: casablanca
The xNF provider **MUST** reach agreement with the Service Provider on
the selected methods for encoding, serialization and data delivery
@@ -529,6 +529,7 @@ JSON
:id: R-19624
:target: XNF
:keyword: MUST
+ :updated: casablanca
The xNF, when leveraging JSON for events, **MUST** encode and serialize
content delivered to ONAP using JSON (RFC 7159) plain text format.
@@ -810,6 +811,7 @@ Asynchronous and Synchronous Data Delivery
:keyword: SHOULD
:impacts: dcae
:validation_mode: in_service
+ :introduced: casablanca
The xNF **SHOULD** deliver all syslog messages to the VES Collector per the
specifications in Monitoring and Management chapter.
diff --git a/docs/Chapter7/VNF-On-boarding-and-package-management.rst b/docs/Chapter7/VNF-On-boarding-and-package-management.rst
index bd49838..f68b129 100755
--- a/docs/Chapter7/VNF-On-boarding-and-package-management.rst
+++ b/docs/Chapter7/VNF-On-boarding-and-package-management.rst
@@ -481,6 +481,7 @@ Testing
:id: R-43958
:target: XNF
:keyword: MUST
+ :updated: casablanca
The xNF Package **MUST** include documentation describing
the tests that were conducted by the xNF provider and the test results.
diff --git a/docs/Chapter8/Ansible-JSON-Key-Value-Description.rst b/docs/Chapter8/Ansible-JSON-Key-Value-Description.rst
index 4913823..5179518 100644
--- a/docs/Chapter8/Ansible-JSON-Key-Value-Description.rst
+++ b/docs/Chapter8/Ansible-JSON-Key-Value-Description.rst
@@ -44,11 +44,11 @@ Table B1. Ansible JSON File key value description
| | value pairs to be | |Attribute names (variable |
| | passed to the Ansible| |names) passed to Ansible |
| | playbook. These | |shall follow Ansible valid |
-| | values would | |variable names: “Variable |
+| | values would | |variable names: "Variable |
| | correspond to | |names should be letters, |
| | instance specific | |numbers, and underscores. |
| | parameters that a | |Variables should always |
-| | playbook may need to | |start with a letter.” |
+| | playbook may need to | |start with a letter." |
| | execute an action. | | |
+---------------+----------------------+---------+----------------------------+
| NodeList |Ansible inventory | Optional|If not provided, pre-loaded |
@@ -110,7 +110,7 @@ Ansible JSON file example:
In the above example, the Ansible Server will:
-a. Process the “FileParameters” dictionary and generate a file named
+a. Process the "FileParameters" dictionary and generate a file named
‘config.txt’ with contents set to the value of the ‘config.txt’ key.
b. Execute the playbook named ‘<VNFCode>/<Version>/ansible/configure/site.yml’
diff --git a/docs/Chapter8/Ansible-Playbook-Examples.rst b/docs/Chapter8/Ansible-Playbook-Examples.rst
index 9875963..5c3d5cd 100644
--- a/docs/Chapter8/Ansible-Playbook-Examples.rst
+++ b/docs/Chapter8/Ansible-Playbook-Examples.rst
@@ -447,7 +447,7 @@ Optional:
<VNF type>/<Version>/ansible/inventory/group_vars/<VNF instance name>
NOTE: Default groups will be created based on VNFC type, 3 characters,
-on VNFC name. Example: “oam”, “rdb”, “dbs”, “man”, “iox”, “app”,…
+on VNFC name. Example: "oam", "rdb", "dbs", "man", "iox", "app",…
Ansible Directories for other artifacts – VNF (special) other files –
Optional – Example – License file:
@@ -520,7 +520,7 @@ Ansible Server.
a. Includes VNF type using VNF function code 4 characters under
/storage.
- b. Includes VNF “Version” directory as part of the path to store
+ b. Includes VNF "Version" directory as part of the path to store
playbooks for this VNF version.
c. Include generic ansible root directory. Creating full directory
@@ -603,10 +603,10 @@ example:
vm\_config\_rdb4\_hostname: vfdb9904vm006
vm\_config\_rdb4\_provider\_ip\_address: 1xx.2yy.zzz.yyy
-NOTE: Please note names in this file shall use underscore “\_” not dots
-“.” or dashes “-“.
+NOTE: Please note names in this file shall use underscore "\_" not dots
+"." or dashes "-".
-7. Perform some basic playbook validation running with “--check” option,
+7. Perform some basic playbook validation running with "--check" option,
running dummy playbooks or other.
NOTE: Each Ansible Server or cluster of Ansible Server will have its own
diff --git a/docs/Chapter8/Chef-JSON-Key-Value-Description.rst b/docs/Chapter8/Chef-JSON-Key-Value-Description.rst
index ae8972f..4beeefe 100644
--- a/docs/Chapter8/Chef-JSON-Key-Value-Description.rst
+++ b/docs/Chapter8/Chef-JSON-Key-Value-Description.rst
@@ -63,7 +63,7 @@ Table A1. Chef JSON File key value description
| | as part of the desired | | |
| | VNF action. | | |
+----------------+--------------------------+---------+----------------------+
-| PushJobFlag | This field indicates |Mandatory| If set to “True”, |
+| PushJobFlag | This field indicates |Mandatory| If set to "True", |
| | whether the VNF action | | ONAP will request a |
| | requires a push Job. Push| | push job. Ignored |
| | job object will be | | otherwise. |
@@ -73,7 +73,7 @@ Table A1. Chef JSON File key value description
| CallbackCapable| This field indicates if | Optional| If Chef cookbook is |
| | the chef-client run | | callback capable, VNF|
| | invoked by push job | | owner is required to |
-| | corresponding to the VNF | | set it to “True”. |
+| | corresponding to the VNF | | set it to "True". |
| | action is capable of | | Ignored otherwise. |
| | posting results on a | | |
| | callback URL. | | |
@@ -83,7 +83,7 @@ Table A1. Chef JSON File key value description
| | retrieve output generated| | NodeObject attributes|
| | in a chef-client run from| | [‘PushJobOutput’] for|
| | Node object attribute | | all nodes in NodeList|
-| | node[‘PushJobOutput’] for| | if set to “True”. |
+| | node[‘PushJobOutput’] for| | if set to "True". |
| | this VNF action (e.g., in| | Ignored otherwise. |
| | Audit). | | |
+----------------+--------------------------+---------+----------------------+
@@ -92,39 +92,39 @@ Chef Template example:
.. code-block:: erb
- “Environment”:{
+ "Environment":{
"name": "HAR",
"description": "VNF Chef environment for HAR",
"json\_class": "Chef::Environment",
"chef\_type": "environment",
"default\_attributes": { },
"override\_attributes": {
- “Retry\_Time”:”50”,
- “MemCache”: “1024”,
- “Database\_IP”:”10.10.1.5”
+ "Retry\_Time":"50",
+ "MemCache": "1024",
+ "Database\_IP":"10.10.1.5"
},
}
}
- “Node”: {
- “name” : “signal.network.com “
+ "Node": {
+ "name" : "signal.network.com "
"chef\_type": "node",
"json\_class": "Chef::Node",
"attributes": {
- “IPAddress1”: “192.168.1.2”,
- “IPAddress2”:”135.16.162.5”,
- “MyRole”:”BE”
+ "IPAddress1": "192.168.1.2",
+ "IPAddress2":"135.16.162.5",
+ "MyRole":"BE"
},
"override": {},
"default": {},
- “normal”:{},
- “automatic”:{},
- “chef\_environment” : “\_default”
+ "normal":{},
+ "automatic":{},
+ "chef\_environment" : "\_default"
"run\_list": [ "configure\_signal" ]
},
- “NodeList”:[“node1.vnf\_a.onap.com”, “node2.vnf\_a.onap.com”],
- “PushJobFlag”: “True”
- “CallbackCapable”:True
- “GetOutputFlag” : “False”
+ "NodeList":["node1.vnf\_a.onap.com", "node2.vnf\_a.onap.com"],
+ "PushJobFlag": "True"
+ "CallbackCapable":True
+ "GetOutputFlag" : "False"
}
The example JSON file provided by the VNF provider for each VNF action will be
@@ -136,8 +136,8 @@ Some points worth noting regarding the JSON fields:
a. The JSON file must be created for each action for each VNF.
b. If a VNF action involves multiple endpoints (VMs) of a VNF, ONAP will
- replicate the “Node” JSON dictionary in the template and post it to
- each FQDN (i.e., endpoint) in the NodeList after setting the “name”
+ replicate the "Node" JSON dictionary in the template and post it to
+ each FQDN (i.e., endpoint) in the NodeList after setting the "name"
field in the Node object to be the respective FQDN [#8.1.1]_. Hence, it
is required that all end points (VMs) of a VNF involved in a VNF
action support the same set of Node Object attributes.
@@ -185,5 +185,5 @@ Table A2. JSON Dictionary to Post in Callback
+--------------+----------------------------+---------+-----------------------+
.. [#8.1.1]
- The “name” field is a mandatory field in a valid Chef Node Object
+ The "name" field is a mandatory field in a valid Chef Node Object
JSON dictionary.
diff --git a/etc/requirements.txt b/etc/requirements.txt
index db5c4ac..21bd7e0 100644
--- a/etc/requirements.txt
+++ b/etc/requirements.txt
@@ -32,3 +32,4 @@ sphinxcontrib-swaggerdoc
sphinxcontrib-plantuml
xlwt==1.3.0
PyYAML>=3.10,<4
+pytest
diff --git a/fix_invalid_metadata.py b/fix_invalid_metadata.py
new file mode 100644
index 0000000..dbff72c
--- /dev/null
+++ b/fix_invalid_metadata.py
@@ -0,0 +1,306 @@
+# -*- coding: utf8 -*-
+# org.onap.vnfrqts/requirements
+# ============LICENSE_START====================================================
+# 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============================================
+
+"""
+This script will consume the `invalid_metadata.csv` file produced by
+`gen_requirement_changes.py`, then add/update any `:introduced:` or `:updated:`
+attributes that may be missing from req directives.
+"""
+import csv
+import os
+import re
+from collections import OrderedDict
+
+import pytest
+
+INPUT_FILE = "invalid_metadata.csv"
+
+
+def load_invalid_reqs(fileobj):
+ """Load the invalid requirements from the input file into a dict"""
+ reader = csv.reader(fileobj)
+ next(reader) # skip header
+ return {row[0]: (row[1].strip(), row[2].strip()) for row in reader}
+
+
+def check(predicate, msg):
+ """Raises a RuntimeError with the given msg if the predicate is false"""
+ if not predicate:
+ raise RuntimeError(msg)
+
+
+class MetadataFixer:
+ """Takes a dict of requirement ID to expected metadata value. The
+ NeedsVisitor will pass the requirement attributes as a a dict
+ to `__call__`. If the requirement is one that needs to be fixed, then
+ it will add or update the attributes as needed and return it to the
+ visitor, otherwise it will return the attributes unchanged."""
+
+ def __init__(self, reqs_to_fix):
+ """Initialize the fixer with a dict of requirement ID to tuple of
+ (attr name, attr value)."""
+ self.reqs_to_fix = reqs_to_fix
+
+ def __call__(self, metadata):
+ """If metadata is for a requirement that needs to be fixed, then
+ adds or updates the attribute as needed and returns it, otherwise
+ it returns metadata unchanged."""
+ r_id = metadata[":id:"]
+ if r_id in self.reqs_to_fix:
+ attr, value = self.reqs_to_fix[r_id]
+ metadata[attr] = value
+ return metadata
+
+
+class NeedsVisitor:
+ """Walks a directory for reStructuredText files and detects needs
+ directives as defined by sphinxcontrib-needs. When a directive is
+ found, then attributes are passed to a callback for processing if the
+ callback returns a dict of attributes, then the revised dict is used
+ instead of the attributes that were passed"""
+
+ def __init__(self, func):
+ self.directives = re.compile("\.\.\s+req::.*")
+ self.func = func
+
+ def process(self, root_dir):
+ """Walks the `root_dir` looking for rst to files to parse"""
+ for dir_path, sub_dirs, filenames in os.walk(root_dir):
+ for filename in filenames:
+ if filename.lower().endswith(".rst"):
+ self.handle_rst_file(os.path.join(dir_path, filename))
+
+ @staticmethod
+ def read(path):
+ """Read file at `path` and return lines as list"""
+ with open(path, "r") as f:
+ print("path=", path)
+ return list(f)
+
+ @staticmethod
+ def write(path, content):
+ """Write a content to the given path"""
+ with open(path, "w") as f:
+ for line in content:
+ f.write(line)
+
+ def handle_rst_file(self, path):
+ lines = (line for line in self.read(path))
+ new_contents = []
+ for line in lines:
+ if self.is_needs_directive(line):
+ metadata_lines = self.handle_need(lines)
+ new_contents.append(line)
+ new_contents.extend(metadata_lines)
+ else:
+ new_contents.append(line)
+ self.write(path, new_contents)
+
+ def is_needs_directive(self, line):
+ """Returns True if the line denotes the start of a needs directive"""
+ return bool(self.directives.match(line))
+
+ def handle_need(self, lines):
+ """Called when a needs directive is encountered. The lines
+ will be positioned on the line after the directive. The attributes
+ will be read, and then passed to the visitor for processing"""
+ attributes = OrderedDict()
+ indent = 4
+ for line in lines:
+ if line.strip().startswith(":"):
+ indent = self.calc_indent(line)
+ attr, value = self.parse_attribute(line)
+ attributes[attr] = value
+ else:
+ if attributes:
+ new_attributes = self.func(attributes)
+ attr_lines = self.format_attributes(new_attributes, indent)
+ return attr_lines + [line]
+ else:
+ return [line]
+
+ @staticmethod
+ def format_attributes(attrs, indent):
+ """Converts a dict back to properly indented lines"""
+ spaces = " " * indent
+ return ["{}{} {}\n".format(spaces, k, v) for k, v in attrs.items()]
+
+ @staticmethod
+ def parse_attribute(line):
+ return re.split("\s+", line.strip(), maxsplit=1)
+
+ @staticmethod
+ def calc_indent(line):
+ return len(line) - len(line.lstrip())
+
+
+if __name__ == '__main__':
+ with open(INPUT_FILE, "r") as f:
+ invalid_reqs = load_invalid_reqs(f)
+ metadata_fixer = MetadataFixer(invalid_reqs)
+ visitor = NeedsVisitor(metadata_fixer)
+ visitor.process("docs")
+
+
+# Tests
+@pytest.fixture
+def metadata_fixer():
+ fixes = {
+ "R-1234": (":introduced:", "casablanca"),
+ "R-5678": (":updated:", "casablanca"),
+ }
+ return MetadataFixer(fixes)
+
+
+def test_check_raises_when_false():
+ with pytest.raises(RuntimeError):
+ check(False, "error")
+
+
+def test_check_does_not_raise_when_true():
+ check(True, "error")
+
+
+def test_load_invalid_req():
+ contents = [
+ "reqt_id, attribute, value",
+ "R-1234,:introduced:, casablanca",
+ "R-5678,:updated:, casablanca",
+ ]
+ result = load_invalid_reqs(contents)
+ assert len(result) == 2
+ assert result["R-1234"][0] == ":introduced:"
+ assert result["R-1234"][1] == "casablanca"
+
+
+def test_metadata_fixer_adds_when_missing(metadata_fixer):
+ attributes = {":id:": "R-5678", ":introduced:": "beijing"}
+ result = metadata_fixer(attributes)
+ assert ":updated:" in result
+ assert result[":updated:"] == "casablanca"
+
+
+def test_metadata_fixer_updates_when_incorrect(metadata_fixer):
+ attributes = {":id:": "R-5678", ":updated:": "beijing"}
+ result = metadata_fixer(attributes)
+ assert ":updated:" in result
+ assert result[":updated:"] == "casablanca"
+ assert ":introduced:" not in result
+
+
+def test_needs_visitor_process(monkeypatch):
+ v = NeedsVisitor(lambda x: x)
+ paths = []
+
+ def mock_handle_rst(path):
+ paths.append(path)
+
+ monkeypatch.setattr(v, "handle_rst_file", mock_handle_rst)
+ v.process("docs")
+
+ assert len(paths) > 1
+ assert all(path.endswith(".rst") for path in paths)
+
+
+def test_needs_visitor_is_needs_directive():
+ v = NeedsVisitor(lambda x: x)
+ assert v.is_needs_directive(".. req::")
+ assert not v.is_needs_directive("test")
+ assert not v.is_needs_directive(".. code::")
+
+
+def test_needs_visitor_format_attributes():
+ v = NeedsVisitor(lambda x: x)
+ attr = OrderedDict()
+ attr[":id:"] = "R-12345"
+ attr[":updated:"] = "casablanca"
+ lines = v.format_attributes(attr, 4)
+ assert len(lines) == 2
+ assert lines[0] == " :id: R-12345"
+ assert lines[1] == " :updated: casablanca"
+
+
+def test_needs_visitor_parse_attributes():
+ v = NeedsVisitor(lambda x: x)
+ assert v.parse_attribute(" :id: R-12345") == [":id:", "R-12345"]
+ assert v.parse_attribute(" :key: one two") == [":key:", "one two"]
+
+
+def test_needs_visitor_calc_indent():
+ v = NeedsVisitor(lambda x: x)
+ assert v.calc_indent(" test") == 4
+ assert v.calc_indent(" test") == 3
+ assert v.calc_indent("test") == 0
+
+
+def test_needs_visitor_no_change(monkeypatch):
+ v = NeedsVisitor(lambda x: x)
+ lines = """.. req::
+ :id: R-12345
+ :updated: casablanca
+
+ Here's my requirement"""
+ monkeypatch.setattr(v, "read", lambda path: lines.split("\n"))
+ result = []
+ monkeypatch.setattr(v, "write", lambda _, content: result.extend(content))
+
+ v.handle_rst_file("dummy_path")
+ assert len(result) == 5
+ assert "\n".join(result) == lines
+
+
+def test_needs_visitor_with_fix(monkeypatch):
+ fixer = MetadataFixer({"R-12345": (":introduced:", "casablanca")})
+ v = NeedsVisitor(fixer)
+ lines = """.. req::
+ :id: R-12345
+
+ Here's my requirement"""
+ monkeypatch.setattr(v, "read", lambda path: lines.split("\n"))
+ result = []
+ monkeypatch.setattr(v, "write", lambda _, content: result.extend(content))
+
+ v.handle_rst_file("dummy_path")
+ assert len(result) == 5
+ assert ":introduced: casablanca" in "\n".join(result)
+
+
+def test_load_invalid_reqs():
+ input_file = [
+ "r_id,attr,value",
+ "R-12345,:updated:,casablanca"
+ ]
+ result = load_invalid_reqs(input_file)
+ assert "R-12345" in result
+ assert result["R-12345"][0] == ":updated:"
+ assert result["R-12345"][1] == "casablanca"
diff --git a/gen_requirement_changes.py b/gen_requirement_changes.py
index 2661c59..c04ff2a 100644
--- a/gen_requirement_changes.py
+++ b/gen_requirement_changes.py
@@ -36,6 +36,7 @@ This script will generate an summary of the requirements changes between
two version's of requirements by analyzing the needs.json file. The template
can be customized by updating release-requirement-changes.rst.jinja2.
"""
+import csv
from itertools import groupby, chain
import json
import os
@@ -279,15 +280,21 @@ def print_invalid_metadata_report(difference_finder, current_version):
print()
print("Requirements Added, but Missing :introduced: Attribute")
print("----------------------------------------------------")
+ errors = [["reqt_id", "attribute", "value"]]
for req in difference_finder.new_requirements.values():
if "introduced" not in req or req["introduced"] != current_version:
+ errors.append([req["id"], ":introduced:", current_version])
print(req["id"])
print()
print("Requirements Changed, but Missing :updated: Attribute")
print("-----------------------------------------------------")
for req in difference_finder.changed_requirements.values():
if "updated" not in req or req["updated"] != current_version:
+ errors.append([req["id"], ":updated:", current_version])
print(req["id"])
+ with open("invalid_metadata.csv", "w", newline="") as error_report:
+ error_report = csv.writer(error_report)
+ error_report.writerows(errors)
if __name__ == "__main__":
@@ -310,3 +317,5 @@ if __name__ == "__main__":
num_removed=len(differ.removed_requirements),
num_changed=len(differ.changed_requirements),
)
+
+