Commits (5)
*/bin
**/.DS_Store
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>mwt-plugtests</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
<nature>org.etsi.mts.tdl.nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.pde.PluginNature</nature>
</natures>
</projectDescription>
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
org.eclipse.jdt.core.compiler.compliance=17
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=17
Manifest-Version: 1.0
Automatic-Module-Name: postman-mwt-plugtests
Bundle-ManifestVersion: 2
Bundle-Name: postman-mwt-plugtests
Bundle-Vendor: My Company
Bundle-Version: 1.0.0.qualifier
Bundle-SymbolicName: mwt-plugtests;singleton:=true
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-17
# mWT Plugtest Examples
This project contains prototypical exploration of converting examples from the mWT plugtests to TDL. The goal is to explore suitability and open questions and provide a guideline for future plugtests and similar definitions.
The examples are derived from the [ETSI Plugtests Test Plan V1.0 (2020-11)](https://portal.etsi.org/Portals/0/TBpages/CTI/Docs/mWT_Plugtests2-3_TestPlan_v1_0.pdf) and the [Postman implementations](https://forge.etsi.org/rep/sdn/mwt/plugtests-3).
TODO: Observations and notes to be added.
\ No newline at end of file
source.. = src/
bin.includes = META-INF/,\
.,\
plugin.xml
/*
* This is an example package
*/
Package Config {
Import all from Standard
Import all from HTTP
Import all from HTTP.MessageBased
Import all from generated_from_step3body_json
Import all from generated_from_step2body_json
//example type
Type float
//define additional elements here
Type message
Message Gate MPI accepts message, JSON_step2body_json, JSON, Response, Request, String
Component DomainController {
gate MPI mpi
}
Component Postman {
variable Response response
variable Integer i
timer t
gate MPI mpi
}
Component NE {
gate MPI mpi //?
}
Component OpticalPatchPanel {
gate MPI mpi //?
}
Component TrafficGeneratorAndAnalyser {
gate MPI mpi //?
}
Configuration GenericTestArchitecture {
Postman pm as Tester,
DomainController M1 as SUT,
DomainController M2 as SUT,
//...
connect M1::mpi to pm::mpi, //TODO: this should be fine
connect M2::mpi to pm::mpi
//...
}
Configuration TestLanArchitecture {
Postman pm as Tester,
DomainController X as SUT,
//...
connect X::mpi to pm::mpi
//...
}
//Lots and lots of configurations that need to be
//Or are some of those configuraitons that are setup to be tested virtually?
Configuration TREE_CFG {
//Postman pm as Tester,
TrafficGeneratorAndAnalyser traffic as Tester,
DomainController X as SUT,
//,,,
connect X::mpi to traffic::mpi
//...
}
}
/*
* This is an example model
*/
Package Data {
}
Package Descriptions {
Import all from Standard
Import all from Objectives
Import all from Config
Import all from generated_from_step3body_json
Import all from generated_from_step2body_json
Import all from HTTP.MessageBased
Annotation Failure
Type ^PICS extends Boolean
^PICS MW_8040
^PICS MW_8345
Boolean TD_SSP_01_Completed
String modules_state_uri
Use "pm.settings.json" as SETTINGS
Map modules_state_uri
to "{{TD_SDN_RESTCONF_PATH}}/data/ietf-yang-library:modules-state"
in SETTINGS
as modules_state_uri_MAPPING
//TODO:to be imported from protocol definition
Structure JSON_modules_state extends Body (
String modules_state,
Modules modules
)
JSON_modules_state JSON_instance_modules_state ()
Collection Modules of Module
Structure Module (
String name,
String revision,
String namespace
)
// ...
//TODO: clean up, align, document, and share
Test Description DomainControllerInitialisation uses TestLanArchitecture
Test Description DomainControllersInitialisation uses TestLanArchitecture
Test Description DevicesUpgrade uses TestLanArchitecture
Test Description BasicConfigurationsSetup uses TestLanArchitecture
Test Description L2DataServicesCreation uses TestLanArchitecture
Test Description ResetDomainControllers uses TestLanArchitecture
Test Description ResetMicrowaveUnits uses TestLanArchitecture
Objective ResponseContainsAllYanModules {
Description: "The response body of the request should contain a list of all YANG modules"
References: "Postman implementation"
}
Test Purpose Description TPD_MDD_01 {
Objective: TD_MDD_01
Configuration: TestLanArchitecture //TREE_CFG?
PICS: (MW_8040 or MW_8345) //etc.
Initial conditions
with {
//initial textual
perform action: "Postman has been correctly initialized earlier, by executing
TD_POSTMAN_INIT"
perform action: "All the Domain Controller instances up and running normally"
perform action: "All the devices are upgraded to correct versions"
perform action: "All basic configurations are completed (e.g., NE_id, OSPF, PCEP, etc.)"
//then gradually formalised, e.g.
execute DomainControllersInitialisation
execute DevicesUpgrade
execute BasicConfigurationsSetup
//!DONE: check constraints above -> fixed
//...
}
Expected behaviour
ensure that {
when {
//initial textual
perform action: "Send GET request via Postman to all domain controllers by
executing Collection TD_MDD_01"
//refine to first structure
//TODO: what happens to all the parentheses?!?! -> make filter optional (or remove?)
pm::mpi sends rGET() to X::mpi
//refine to specific uri inline
pm::mpi sends rGET(
uri = "{{TD_SDN_RESTCONF_PATH}}/data/ietf-yang-library:modules-state"
) to X::mpi
//...or define elsewhere
pm::mpi sends rGET(
uri = modules_state_uri
) to X::mpi
}
then {
//initial textual
perform action: "Check the response body of each request and confirm if all the
Restconf servers are serviceable."
perform action: "The response body of the request should contain a list of all
YANG modules and submodules used by the Restconf server along with
information about name and revision for each module."
perform action: "The response body of each query should contain the specified YANG
module along with its name and revision."
//refinements
// Test 1: Check the response body of the above request and confirm if the Restconf
// server is serviceable.
pm::mpi receives OK() from X::mpi
// Step 2: The response body of the request should contain a list of all YANG modules
//and submodules used by the Restconf server along with information about name and revision
//for each module.
//---
//asserts can be used but probably simpler to use a specification of the expected data
//optionally: explicit objective that can be checked
Objective: ResponseContainsAllYanModules
pm::mpi receives OK(
body = JSON_instance_modules_state(
modules_state = ?,
modules_state = ?,
//TODO: do we need a pattern ? / * for collections? Otherwise we need a loop instead
//TODO: as a side note, is checking for the presence of a property
// equivalent to that property having any value?
modules[*] = (name = ?, revision = ?, namespace = ?)
//...
)) from X::mpi
//asserts can provide fine granular diagnostics though, for individual problems
response = pm::mpi receives OK() from X::mpi
//optionally: explicit objective that can be checked
Objective: ResponseContainsAllYanModules
//optionally: annotations can be used for inline information
@Failure: "The response body of the request should contain a list of all YANG modules"
//TODO: property access for subclasses?
//TODO: do we have matching expressions in assertions as well
//TODO: do we have checking of types
assert ( pm::response.body == JSON_instance_modules_state(
modules_state = ?,
//TODO: do we need a pattern ? / * for collections? Otherwise we need a loop instead
//TODO: as a side note, is checking for the presence of a property
// equivalent to that property having any value?
modules[*] = (name = ?, revision = ?, namespace = ?)
//
))
on pm //may be skipped at first
with {
timeLabel=now
}
//alternatively with a loop
//TODO: do we need counters? integrated in loops? e.g. with state to address collections?
pm::i = 0
repeat 5 times on pm
//[MW_8040]
{
//DONE: fixed constraint with bounded loop behaviour, still not quite there
assert ( pm::response.body == JSON_instance_modules_state(
modules_state = ?,
//TODO: as a side note, is checking for the presence of a property
// equivalent to that property having any value?
modules[pm::i] = (name = ?, revision = ?, namespace = ?)
//
))
on pm //may be skipped at first
//DONE: handle undefined return types -> a bit of a hack, assuming they are the same
pm::i = ( pm::i + 1 )
}
}
}
}
Test Purpose Description TPD_MSP_01 {
Objective: TD_MSP_01
Configuration: TestLanArchitecture //TREE_CFG?
PICS: (MW_8040 or MW_8345) //etc.
Initial conditions
with {
//initial textual
perform action: "Postman has been correctly initialized earlier, by executing TD_POSTMAN_INIT"
perform action: "The Domain Controller instance is up and running normally"
perform action: "All the devices are upgraded to correct versions"
perform action: "All basic configurations are completed (e.g., NE_id, OSPF, PCEP, etc.)"
perform action: "All Restconf servers are serviceable."
perform action: "If TD_SSP_01 has been run before TD_ MSP_01, all Domain Controllers and
microwave units should be reset to the state they were before executing
TD_SSP_01"
//then gradually formalised, e.g.
execute DomainControllerInitialisation
execute DomainControllerInitialisation
execute DevicesUpgrade
execute BasicConfigurationsSetup
if [TD_SSP_01_Completed] {
execute ResetDomainControllers
execute ResetMicrowaveUnits
}
//!TODO: check constraints above
//...
}
Expected behaviour
ensure that {
when {
//initial textual
perform action: "Send POST request via Postman to all domain controllers
by executing Collection TD_ SSP_01"
// //refine to first structure
// pm::mpi sends rPOST() to X::mpi
// //refine to specific body (or define inline)
// pm::mpi sends rPOST(body = JSON_instance) to X::mpi
//
// //provide additional parameter overrides
// pm::mpi sends rPOST(
// body = JSON_instance (
// services[0].adminStatus = "up",
// //..
// //TODO: check constraints
// services[0].ports[1].accessNodeId = node1
// //..
// )
// )
// to X::mpi //....
}
then {
//initial textual
perform action: "Check the TGA if the data start flowing properly."
// pm::mpi receives OK() from X::mpi
// pm::mpi receives OK(body = JSON_instance) from X::mpi
// pm::mpi receives OK(
// body = JSON_instance(
// //..
// services[2] = omit,
// //...
// services[3].ports[1] = omit
// )
// )
// from X::mpi
// //first response definition, then refined, also with overrides
// //!TODO: Why are comments before receive message not OK?
// //... refine further
}
}
}
Test Purpose Description TPD_MSP_04 {
Objective: TD_MSP_04
Configuration: TestLanArchitecture //TREE_CFG?
PICS: (MW_8040 or MW_8345) //etc.
Initial conditions
with {
//initial textual
perform action: "Postman has been correctly initialized earlier, by executing TD_POSTMAN_INIT"
perform action: "All the Domain Controller instances are up and running normally"
perform action: "All the devices are upgraded to correct versions"
perform action: "All basic configurations are completed (e.g., NE_id, OSPF, PCEP, etc.)"
perform action: "All Restconf servers are serviceable."
perform action: "All L2 data services are successfully created."
//then gradually formalised, e.g.
execute DomainControllersInitialisation
execute DevicesUpgrade
execute BasicConfigurationsSetup
execute L2DataServicesCreation
//!TODO: check constraints above
//...
}
Expected behaviour
ensure that {
when {
//initial textual
perform action: "Send GET request via Postman to
all domain controllers by executing
Collection TD_MSP_04"
//refine to first structure
pm::mpi sends rGET() to X::mpi
//refine to specific body (or define inline)
pm::mpi sends rGET(body = JSON_instance) to X::mpi
//provide additional parameter overrides
pm::mpi sends rGET(
body = JSON_instance (
services[0].adminStatus = "up" {JSON_String},
//..
//DONE: check constraints
services[0].ports[1].accessNodeId = node1
//..
)
)
to X::mpi //....
}
then {
//initial textual
perform action: "The response body should no longer contain
information about the L2 service deleted in TD_MSP_03"
//!DONE: Why are comments before receive message not OK? -> fixed
//basic response definition
pm::mpi receives OK() from X::mpi
//refined with reference to body definition
pm::mpi receives OK(body = JSON_instance) from X::mpi
//refined with inline overrides
pm::mpi receives OK(
body = JSON_instance(
//..
//TODO: does an optional collection member imply entire collection is ommitted?
// or also individual items?
//TODO: does special value use conform to everything?
services[2] = omit,
//...
services[3].ports[1] = omit
)
)
from X::mpi
//... refine further
}
}
}
}
\ No newline at end of file
This diff is collapsed.
Package HTTP {
Package MessageBasedConfiguration {
Import all from MessageBased
Message Gate HTTPGate accepts Request,Response
Component API {
//Add variables and timers here or define new component types and configurations
gate HTTPGate http
}
Configuration BasicClientServer {
API client as Tester,
API server as SUT,
connect client::http to server::http
}
} Note : "Message based types and instances"
Package MessageBased {
Import all from Standard
//Generic Method type -> required for generation!!!
Enumerated Method {
Method GET,
Method POST,
Method PUT,
Method PATCH,
Method DELETE
}
//Generic Request type
Structure Request (
String uri,
optional Method method,
optional Headers headers,
optional Parameters parameters,
optional Body body
)
//Generic Request instances
Request rGET (method = GET)
Request rPOST (method = POST)
Request PUT (method = PUT)
Request PATCH (method = PATCH)
Request DELETE (method = DELETE)
//Generic Response type
Structure Response (
optional Integer status,
optional String statusMessage,
optional Headers headers,
optional Body body
)
//Generic Response instances, name = status code
Response r200 (statusMessage = "OK")
Response r201 (statusMessage = "Created")
Response r204 (statusMessage = "No Content")
Response r400 (statusMessage = "Bad Request")
Response r401 (statusMessage = "Not Found")
Response r403 (statusMessage = "Not Authorized")
Response r404 (statusMessage = "Forbidden")
//Generic Response instances, name = status message
Response OK (status = "200")
Response Created (status = "201")
Response NoContent (status = "204")
Response BadRequest (status = "400")
Response NotFound (status = "404")
Response NotAuthorized (status = "401")
Response Forbidden (status = "403")
//supporting types
Collection Parameters of Parameter
Structure Parameter (
Location location,
String ^name,
String ^value
)
Type Location
Location path
Location query
//may need a structure, not necessarily relevant in standardized testing
Location cookie
//separate headers -> not necessary
//Location header;
Collection Headers of Header
Structure Header (
String ^name,
String ^value
//not relevant in TDL?
//optional contentLength of type Integer,
//optional contentType of type String
)
//Base body for extension
Structure Body ( )
//Basic string body
Structure StringBody extends Body (
String text
)
//Basic wrapper for collection responses
Structure CollectionBody extends Body (
Bodies items
)
//Any body can be included
//If consistent type is needed, a custom subtype shall be defined and used
Collection Bodies of Body
//Custom collection data instances can be defined
// - inline in the responses
// - predefined as a separate data element
//Custom collection data instances can be defined
//to enforce type consistency specific for API
//Basic form body
Structure FormBody extends Body (
String field,
String content
)
}
}
\ No newline at end of file
Package Objectives {
Import all from Standard
Objective TD_MDD_01 {
Description: "Issue a request via Postman to all domain controllers,
to check the overall viability of the test network."
References: "ETSI Plugtests Test Plan V1.0 (2020-11), 8.3.2"
}
Objective TD_MDD_02 {
Description: "The microwave topology information are requested from
all DCs connected to the NBI LAN at the same time for
the same information as TD_SDD_02. This allows to check
that the connectivity to all DC is fully functional. A
comparison of the answers received may be performed to
check consistency and compliance."
References: "ETSI Plugtests Test Plan V1.0 (2020-11), 8.3.2"
}
Objective TD_MDD_03 {
Description: "The Ethernet topology information are requested
from all DCs connected to the NBI LAN at the same
time for the same information as TD_SDD_03. This
allows to check that the connectivity to all DC
is fully functional. A comparison of the answers
received may be performed to check consistency
and compliance."
References: "ETSI Plugtests Test Plan V1.0 (2020-11), 8.5.2"
}
Objective TD_MSP_01 {
Description: "Create the specified L2 data services over all
available domains. The TGA confirms that data
start flowing. The traffic on the inter-domain
links is classified based on S- VLAN only."
References: "ETSI Plugtests Test Plan V1.0 (2020-11), 8.5.2"
}
Objective TD_MSP_02 {
Description: "The Ethernet service information is requested from
all the DCs under test in TD_MSP_01. The received
information is checked to correctly list the newly
created services."
References: "ETSI Plugtests Test Plan V1.0 (2020-11), 8.5.2"
}
Objective TD_MSP_03 {
Description: "Delete the specified L2 data service over all available
domains. The TGA confirms that data stops flowing."
References: "ETSI Plugtests Test Plan V1.0 (2020-11), 8.5.2"
}
Objective TD_MSP_04 {
//TODO: remove formatting spaces?
Description: "The Ethernet service information is requested from all
the DCs under test in TD_MSP_03. The received
information is checked to correctly not list the newly
deleted services anymore."
References: "ETSI Plugtests Test Plan V1.0 (2020-11), 8.5.2"
}
}
\ No newline at end of file
Package Standard {
//TODO: extract to standard library
Constraint length
Constraint minLength
Constraint maxLength
Constraint range
Constraint format
Constraint union
Constraint uniontype
Type Boolean
Type Integer
Type String
Type Verdict
//TODO: these do not work at present -> literal values take precedence?
// Boolean true
// Boolean false
Boolean True
Boolean False
Verdict pass
Verdict fail
Verdict inconclusive
Time second
Annotation Master
Annotation MappingName
//standard annotations for STO
Annotation Initial conditions
Annotation Expected behaviour
Annotation Final conditions
Annotation Test Purpose Description
Annotation when
Annotation then
Predefined == returns Boolean
Predefined != returns Boolean
Predefined and returns Boolean
Predefined or returns Boolean
Predefined xor returns Boolean
Predefined not returns Boolean
Predefined < returns Boolean
Predefined > returns Boolean
Predefined <= returns Boolean
Predefined >= returns Boolean
Predefined +
Predefined -
Predefined *
Predefined /
Predefined mod
Predefined size returns Integer
}
\ No newline at end of file
{
"etht-svc-bandwidth-profiles": [
{
"bandwidth-profile-name": "bw_profile_{{TD_SDN_SERVICE_NAME}}",
"bandwidth-profile-type": "ietf-eth-tran-types:mef-10-bwp",
"CIR": "{{TD_SDN_CIR_VALUE}}",
"EIR": "{{TD_SDN_EIR_VALUE}}",
"color-aware": true,
"coupling-flag": true
}
]
}
\ No newline at end of file
Package generated_from_step2body_json {
Type String
Type TODO_RESOLVE_REFERENCED
Use "step2body.json" as SOURCE_MAPPING
Type JSON_String
Structure JSON_step2body_json (
JSON_etht_svc_bandwidth_profiles etht_svc_bandwidth_profiles
)
Collection JSON_etht_svc_bandwidth_profiles of JSON_etht_svc_bandwidth_profiles_item
Structure JSON_etht_svc_bandwidth_profiles_item (
JSON_String bandwidth_profile_name,
JSON_String bandwidth_profile_type,
JSON_String CIR,
JSON_String EIR,
JSON_String color_aware,
JSON_String coupling_flag
)
//Just use mappings? or replace with variables? (if dynamic)
JSON_step2body_json JSON_instance (
etht_svc_bandwidth_profiles = [
(
bandwidth_profile_name = "bw_profile_{{TD_SDN_SERVICE_NAME}}",
bandwidth_profile_type = "ietf-eth-tran-types:mef-10-bwp",
CIR = "{{TD_SDN_CIR_VALUE}}",
EIR = "{{TD_SDN_EIR_VALUE}}",
color_aware = "true",
coupling_flag = "true"
)
]
)
Map JSON_step2body_json to "JSON" in SOURCE_MAPPING as JSON_SOURCE_MAPPING {
etht_svc_bandwidth_profiles -> "etht-svc-bandwidth-profiles"
}
Map JSON_etht_svc_bandwidth_profiles_item to "JSON.etht-svc-bandwidth-profiles.item" in SOURCE_MAPPING as JSON_etht_svc_bandwidth_profiles_item_SOURCE_MAPPING {
bandwidth_profile_name -> "bandwidth-profile-name",
bandwidth_profile_type -> "bandwidth-profile-type",
CIR -> "CIR",
EIR -> "EIR",
color_aware -> "color-aware",
coupling_flag -> "coupling-flag"
}
}
\ No newline at end of file
(
services =
[
(
^name = 'S1-local',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '201'),
(accessNodeId = node2, accessLtpId = p3, tagType = 'c-vlan', vlanValue = '101', bwprofile = true)
]
),
(
^name = 'S2-local-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '202'),
(accessNodeId = node2, accessLtpId = p2, tagType = 's-vlan', vlanValue = '202')
]
),
(
^name = 'S3-local-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '203'),
(accessNodeId = node2, accessLtpId = p4, tagType = 's-vlan', vlanValue = '203')
]
),
(
^name = 'S1-inter-d-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '204'),
(accessNodeId = node2, accessLtpId = p2, tagType = 's-vlan', vlanValue = '204')
]
),
(
^name = 'S2-inter-d-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '205'),
(accessNodeId = node2, accessLtpId = p2, tagType = 's-vlan', vlanValue = '205')
]
),
(
^name = 'S3-inter-d-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '206'),
(accessNodeId = node2, accessLtpId = p4, tagType = 's-vlan', vlanValue = '206')
]
),
(
^name = 'S4-inter-d-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '207'),
(accessNodeId = node2, accessLtpId = p4, tagType = 's-vlan', vlanValue = '207')
]
),
(
^name = 'S1-leaf-2',
adminStatus = 'up',
ports = [
(accessNodeId = node2, accessLtpId = p2, tagType = 's-vlan', vlanValue = '208'),
(accessNodeId = node2, accessLtpId = p4, tagType = 's-vlan', vlanValue = '208')
]
),
(
^name = 'S2-leaf-2',
adminStatus = 'up',
ports = [
(accessNodeId = node2, accessLtpId = p2, tagType = 's-vlan', vlanValue = '209'),
(accessNodeId = node2, accessLtpId = p3, tagType = 'c-vlan', vlanValue = '103', bwprofile = true)
]
),
(
^name = 'S3-leaf-1',
adminStatus = 'up',
ports = [
(accessNodeId = node2, accessLtpId = p3, tagType = 'c-vlan', vlanValue = '104', bwprofile = true),
(accessNodeId = node2, accessLtpId = p4, tagType = 's-vlan', vlanValue = '210')
]
)
]
)
\ No newline at end of file
{
services:
[
{
name: 'S1-local',
adminStatus: 'up',
ports: [
{accessNodeId: node1, accessLtpId: p1, tagType: 's-vlan', vlanValue: '201'},
{accessNodeId: node2, accessLtpId: p3, tagType: 'c-vlan', vlanValue: '101', bwprofile: true},
]
},
{
name: 'S2-local-1',
adminStatus: 'up',
ports: [
{accessNodeId: node1, accessLtpId: p1, tagType: 's-vlan', vlanValue: '202'},
{accessNodeId: node2, accessLtpId: p2, tagType: 's-vlan', vlanValue: '202'},
]
},
{
name: 'S3-local-1',
adminStatus: 'up',
ports: [
{accessNodeId: node1, accessLtpId: p1, tagType: 's-vlan', vlanValue: '203'},
{accessNodeId: node2, accessLtpId: p4, tagType: 's-vlan', vlanValue: '203'},
]
},
{
name: 'S1-inter-d-1',
adminStatus: 'up',
ports: [
{accessNodeId: node1, accessLtpId: p1, tagType: 's-vlan', vlanValue: '204'},
{accessNodeId: node2, accessLtpId: p2, tagType: 's-vlan', vlanValue: '204'},
]
},
{
name: 'S2-inter-d-1',
adminStatus: 'up',
ports: [
{accessNodeId: node1, accessLtpId: p1, tagType: 's-vlan', vlanValue: '205'},
{accessNodeId: node2, accessLtpId: p2, tagType: 's-vlan', vlanValue: '205'},
]
},
{
name: 'S3-inter-d-1',
adminStatus: 'up',
ports: [
{accessNodeId: node1, accessLtpId: p1, tagType: 's-vlan', vlanValue: '206'},
{accessNodeId: node2, accessLtpId: p4, tagType: 's-vlan', vlanValue: '206'},
]
},
{
name: 'S4-inter-d-1',
adminStatus: 'up',
ports: [
{accessNodeId: node1, accessLtpId: p1, tagType: 's-vlan', vlanValue: '207'},
{accessNodeId: node2, accessLtpId: p4, tagType: 's-vlan', vlanValue: '207'},
]
},
{
name: 'S1-leaf-2',
adminStatus: 'up',
ports: [
{accessNodeId: node2, accessLtpId: p2, tagType: 's-vlan', vlanValue: '208'},
{accessNodeId: node2, accessLtpId: p4, tagType: 's-vlan', vlanValue: '208'},
]
},
{
name: 'S2-leaf-2',
adminStatus: 'up',
ports: [
{accessNodeId: node2, accessLtpId: p2, tagType: 's-vlan', vlanValue: '209'},
{accessNodeId: node2, accessLtpId: p3, tagType: 'c-vlan', vlanValue: '103', bwprofile: true},
]
},
{
name: 'S3-leaf-1',
adminStatus: 'up',
ports: [
{accessNodeId: node2, accessLtpId: p3, tagType: 'c-vlan', vlanValue: '104', bwprofile: true},
{accessNodeId: node2, accessLtpId: p4, tagType: 's-vlan', vlanValue: '210'},
]
}
]
}
\ No newline at end of file
Package generated_from_step3body_json {
Import all from HTTP.MessageBased
Type String
Type TODO_RESOLVE_REFERENCED
Use "step3body.json" as SOURCE_MAPPING
Type JSON_String
Structure JSON extends Body (
optional Services services
)
Collection Services of Service
Structure Service (
JSON_String ^name,
JSON_String adminStatus,
Ports ports
)
JSON_String p1
JSON_String p2
JSON_String p3
JSON_String p4
JSON_String node1
JSON_String node2
//Option 1: Map to concrete values that shall be substituted using data-mappings
//Import different mappings or resolve dynamically?
Use "companysettings" as Settings
Map p1 to "companySettings.svc['access-port1'][ 'a-link-aggr-id']" in Settings as P1_Map
Map p2 to "companySettings.svc['access-port2'][ 'i-d-link-W-id']" in Settings as P1_Map
//...
//Option 2: Use substitution inline with paths
//Option 3: Apply functions to transform / substitute some parts
//To which extent is that needed? is it dynamic or statically initialised at start?
//-> Defer to adaptation? expose only necessary parts?
Collection Ports of Port
Structure Port (
JSON_String accessNodeId,
JSON_String accessLtpId,
JSON_String tagType,
JSON_String vlanValue,
JSON_String bwprofile
)
//Just use mappings? or replace with variables? (if dynamic)
JSON JSON_instance (
services = [
(
^name = 'S1-local',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '201'),
(accessNodeId = node2, accessLtpId = p3, tagType = 'c-vlan', vlanValue = '101', bwprofile = true)
]
),
(
^name = 'S2-local-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '202'),
(accessNodeId = node2, accessLtpId = p2, tagType = 's-vlan', vlanValue = '202')
]
),
(
^name = 'S3-local-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '203'),
(accessNodeId = node2, accessLtpId = p4, tagType = 's-vlan', vlanValue = '203')
]
),
(
^name = 'S1-inter-d-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '204'),
(accessNodeId = node2, accessLtpId = p2, tagType = 's-vlan', vlanValue = '204')
]
),
(
^name = 'S2-inter-d-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '205'),
(accessNodeId = node2, accessLtpId = p2, tagType = 's-vlan', vlanValue = '205')
]
),
(
^name = 'S3-inter-d-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '206'),
(accessNodeId = node2, accessLtpId = p4, tagType = 's-vlan', vlanValue = '206')
]
),
(
^name = 'S4-inter-d-1',
adminStatus = 'up',
ports = [
(accessNodeId = node1, accessLtpId = p1, tagType = 's-vlan', vlanValue = '207'),
(accessNodeId = node2, accessLtpId = p4, tagType = 's-vlan', vlanValue = '207')
]
),
(
^name = 'S1-leaf-2',
adminStatus = 'up',
ports = [
(accessNodeId = node2, accessLtpId = p2, tagType = 's-vlan', vlanValue = '208'),
(accessNodeId = node2, accessLtpId = p4, tagType = 's-vlan', vlanValue = '208')
]
),
(
^name = 'S2-leaf-2',
adminStatus = 'up',
ports = [
(accessNodeId = node2, accessLtpId = p2, tagType = 's-vlan', vlanValue = '209'),
(accessNodeId = node2, accessLtpId = p3, tagType = 'c-vlan', vlanValue = '103', bwprofile = true)
]
),
(
^name = 'S3-leaf-1',
adminStatus = 'up',
ports = [
(accessNodeId = node2, accessLtpId = p3, tagType = 'c-vlan', vlanValue = '104', bwprofile = true),
(accessNodeId = node2, accessLtpId = p4, tagType = 's-vlan', vlanValue = '210')
]
)
]
)
}
\ No newline at end of file