Assembly descriptors
Assembly descriptors are YAML files that describe the building blocks of applications that are managed by the orchestration component of IBM® Cloud Pak for Network Automation.
The basic building blocks are described in resource descriptors. Resource descriptors are then composed into assembly descriptors to describe a complete application or service that the orchestration component can manage.
Assembly descriptors include descriptions of relationships between components, which allow the orchestration component to provision the component instances that it manages. If you want to manage the configuration of those instances after they are provisioned, you must use a tool other than IBM Cloud Pak for Network Automation. Assemblies can also reference other assemblies and existing infrastructure items, such as external network instances.
The following table summarizes the sections in assembly descriptors:
Section | Required | Description |
---|---|---|
name |
Y | The type, name, and version of this descriptor. |
description |
N | A meaningful description of the contents of this descriptor. |
properties |
Y | The properties and values for the assembly instance that is created by using this descriptor. |
operations |
N | The operations that can be called when this assembly is involved in a relationship in a higher-level descriptor. |
composition |
Y | The components that make up the assembly and are instantiated when the assembly is installed. |
references |
N | The existing assemblies or externally managed systems that this assembly can refer to. |
relationships |
N | The details of relationships between assembly components, such as the capabilities that one component requires from another. |
data-types |
N | The customized data types that you might want to use for properties. |
capabilities |
N | The functions that the assembly provides. |
requirements |
N | The capabilities that the assembly requires to work successfully. |
name
section
name
section. When you deploy the package to an orchestration environment, if no
descriptor name is specified, a default name is created automatically. For more information, see
Naming rules.In the name
section, you specify a name and a version number for the descriptor.
The name section comprises the following components, which are separated by a double colon
(::
):
- Descriptor Type
- Specifies the type of descriptor:
assembly
orresource
. - Name
- Specifies a name for the descriptor. The name must be unique for the descriptor type. To make
sure that the name is unique, use a convention such as
companyname.resourcename
when you name the descriptor. The name must conform to the following rules:- Starts with a letter (uppercase or lowercase).
- Ends with either a letter (uppercase or lowercase) or a number.
- Can include letters, digits, and non-consecutive underscores and hyphens.
- No spaces.
- Maximum length of 50 characters.
- Version
- Specifies one or more number values that are separated by a single period character
(
.
). Alphabetic characters are not allowed. Therefore, the following values are valid:1.0
and1.0.0
. The following value is not valid:v1.0
name: assembly::Example_company2.neutron_network::1.0.0
description
section
In the description
section, you provide a meaningful description of the
descriptor. The following example shows the name
and description
sections of a resource descriptor:
name: resource::c_streamer::1.0
description: Component package for c_streamer
properties
section
In the higher level properties
section of an assembly descriptor, you define the
properties of an assembly instance, that is, the set of properties that are required to orchestrate
an assembly through to the Active
state. These properties can be understood as the
context for the management of the assembly during its lifecycle.
Assembly descriptors can also contain other, low-level properties
sections. For
example, assembly components, which are described in the composition
section,
include their own sets of properties. For all properties
sections in an assembly
descriptor, the same rules, attributes, and structure apply.
The properties in this section are assembly-wide properties, that is, they can be referred to in
low-level properties
sections anywhere in the assembly descriptor.
Each property is identified by a name and a number of attributes.
Attribute | Description | Required | Type | Restrictions |
---|---|---|---|---|
<property_name> |
The property name, which must be unique within its property section or scope. To specify the deployment location properties for this assembly instance, set this attribute to
To specify the resource manager properties for this assembly instance, set this attribute to
For more information, see |
Y | String |
|
type |
The data type of the property. For more information about the For more information about customized data types,
see |
Y | The following options are available:
|
|
required |
Indicates that a value for this property must be provided when the assembly is instantiated. | N | Boolean | |
description |
A textual description of the purpose of the property. | N | String | |
default |
A default value that is provided to the assembly if an override is not provided at instantiation time. | N | String | |
read-only |
Indicates that a value cannot be provided at instantiation time and that the assembly might provide an updated value when instantiated. A default value or a mapped property might be provided. | N | Boolean | |
volatile |
Identifies that changes to this property do not trigger a re-installation of the assembly. For more information, see Volatile properties. | N | Boolean | |
value |
A static value for the property, which cannot be overridden at instantiation time. You can identify a value that is mapped from one or more properties of the parent assembly or from the properties of any peer component. To identify a mapped property, use the following syntax:
|
N | String or reference | You must include a space between the value: string and the value itself, for
example, value: 123 . |
- Example of a
properties
section -
properties: deploymentLocation: type: string required: true description: The name of the openstack project (tenant) to install this assembly in. resourceManager: value: '${resourceManager}' numOfStreamers: # the name of the property type: string description: the number of streamers that should be created at install time default: 2 tenant_key_name: type: string required: true description: The SSH key for the current tenant flavor: value: m1.small cluster_public_ip_address: type: string description: the public IP address for this cluster read-only: true value: '${balancer.publicIp}'
- Properties and required or optional status
-
Properties are optional unless they are explicitly defined as required by using a
required: true
attribute. The required status affects a higher-level assembly only and means that a value must be present (that is, not null) for a property.If a value is required, it's a good idea to include it when you define the property. The inclusion of the value helps designers of other assembly descriptors to ensure that the value is represented in assemblies when the property is mapped or promoted. You can check the value in the
value
attribute, thedefault
value, or in the value that is passed in from the intent request.
- Read-only properties
-
Properties that are marked as
read-only: true
are not overridden by values that are mapped in from an enclosing assembly or from the intent request. Theread-only
attribute is typically used for properties that are calculated from, or returned by, the assembly instance itself.
- Property values
-
You can assign a default value or a specific value to a property. To set a property value to the value of another property in the higher level
properties
section of the descriptor, use the following syntax:value: '${<sourceProperty>}'
To set a higher level property value to the value of a property in a low-levelproperties
section, include the name of the object that the low-level property belongs to. For example, if your descriptor contains a component that is calledbalancer
, use the following syntax to set a higher level property to the value of thepublicIp
property for this component:value: ‘${balancer.publicIp}’
The orchestration component assigns an internal name and identifier to each resource instance that it creates. It also supplies the index number of a resource in a cluster. These values can be useful when you define properties because they indicate the unique resource instance names. To access these values, you can set property values to references such as
${instance.name}
,${instance.id}
, or${instance.index}
. The orchestration component then replaces the references with the appropriate values.
deploymentLocation
andresourceManager
properties-
The
deploymentLocation
andresourceManager
properties appear only in assembly descriptors.In the
deploymentLocation
property, you specify the virtual infrastructure location where you want the resources that are created for this assembly instance to be deployed. For example, you might set the value of this property to the name of a Kubernetes namespace or an OpenStack tenant.In the
resourceManager
property, you specify the name of the resource manager that manages the resources that are created for this assembly instance. This property must be set toBrent
.
Property data types
Properties can have the following scalar types:
string
boolean
integer
float
timestamp
This example shows how you can assign scalar types to properties and set default and hard-coded values for each type:
msg:
type: string
default: "hello world"
test_integer:
description: This is the test integer description from the parent
type: integer
value: 100
test_boolean:
type: boolean
default: true
readOnly: true
test_float:
type: float
value: 3.141592654
test_timestamp:
type: timestamp
value: 2019-09-07T15:50-04:00
volatile: true
Structured properties
In addition to using scalar types, you can define properties that use a structured type, which
must be either list
or map
.
Use the list
type to define a list of values that can each be accessed by using
the value's position in the array. Use the map
type to define a set of key-value
pairs, where each value can be accessed by using its corresponding key.
Lists and maps can be nested. For example, each value in a list might be another list.
- Brackets. For example, you might describe a list of three elements in this format:
[0, 1, 2]
- A hyphenated format that shows each listed item on a separate line. For example, you might
describe a list of three lists in this
format:
- [0,1,2] - [3,4,5] - [6,7,8]
- Braces. For example, you might describe a map of three elements like this:
{a: 100, b: 101, c: 102}
- A list that shows each mapped item on a separate line. For example, you might describe a map of
three items in this format:
a: 100 b: 101 c: 102
Use the entry-schema
property to define the data type of each value in a list or
map. In addition to scalar and structured data types, you can use customized data types that are
defined in the data-types
section.
- A list of three integers that is called
test_list
and is described by using brackets. - A map that is called
test_map
and contains three floating-point values and their corresponding keys,floatkey1
,floatkey2
, andfloatkey3
. - A list of maps that is called
test_data
and is described by using a hyphenated format that shows each listed item on a separate line. This list contains the following complex nested structure:- In each higher level map in the list, the value of the
nested-property
list element is another map that contains two elements, which are identified by the keysfirst-level
anddouble-nested
. - The
double-nested
element is another map that contains two elements, which are identified by the keyssecond-level
anddeeply-nested
. - The
deeply-nested
element is another map that contains one element, which is identified by the keythird-level
.
- In each higher level map in the list, the value of the
test_list:
type: list
entry-schema:
type: integer
default: [-2147483648, 0, 2147483647]
test_map:
type: map
entry-schema:
type: float
description: This the the test map inner description from the parent
default:
floatkey1: -3.141592654
floatkey2: 0.123456789
floatkey3: 3.141592654
test_data:
default:
- { id: 'internal1', name: 'public1', nested-property: {first-level: '11', double-nested: {second-level: '12', deeply-nested: {third-level: '13'}}}}
- { id: 'internal2', name: 'public2', nested-property: {first-level: '21', double-nested: {second-level: '22', deeply-nested: {third-level: '23'}}}}
- { id: 'internal3', name: 'public3', nested-property: {first-level: '31', double-nested: {second-level: '32', deeply-nested: {third-level: '33'}}}}
type: list
entry_schema:
type: map
description: Array of structured data to be passed to the 'D' group
Structured property mapping
After you define maps and lists that contain data, you can access the data and map it into other descriptor properties. You can map both scalar and structured data.
test_map
and contains the following complex
nested structure:- In each higher level map in the list, the value of the
list-property
list element is another list that contains three string elements. - In each higher level map in the list, the value of the
nested-property
list element is another map that contains three elements, which are identified by the keysfirst-level
,nested-list
, anddouble-nested
. - The
nested-list
element is another list that contains three string elements. - The
double-nested
element is another map that contains two elements, which are identified by the keyssecond-level
anddeeply-nested
. - The
deeply-nested
element is another map that contains one element, which is identified by the keythird-level
.
In this example, string values from the structured list are mapped to component properties by
setting the value
attribute for each component property to a list value. The list
value that each component property is mapped to is indicated by a comment, that is,
//
.
properties:
test_map:
type: map
default: { id: 'internal1',
name: 'public1',
list-property: ['entry1', 'entry2', 'entry3'],
nested-property:
{first-level: '11',
nested-list: ['entry12', 'entry22', 'entry32'],
double-nested: {second-level: '12',
deeply-nested: {third-level: '13'}}}}
...
composition:
...
component1:
properties:
data-nested1-value:
value: ${test_map.nested-property.first-level} // value = '11'
data-nested2-value:
value: ${test_map.nested-property.double-nested.second-level} // value = '12'
data-nested3-value:
value: ${test_map.nested-property.double-nested.deeply-nested.third-level} // value = '13'
data-list-first-value:
value: ${test_map.list-property[0]} // value = 'entry1'
data-nested-list-second-value:
value: ${test_map.nested-property.nested-list[1]} // will be set to value 'entry22'
See Defining component groups for property mapping in the context of a group.
operations
section
In the operations
section, you specify the component operations that you want to
make available to higher-level assembly descriptors that include this assembly in relationships.
- Operations and relationships
-
Relationships between assembly components are created and ceased through the calling of operations. Each component can be a resource or another assembly.
Operations are described in resource descriptors. After you describe a resource's operations, you can define relationships that call these operations in the
relationships
section of the containing assembly descriptor. When you define a relationship that involves a resource, you can specify which of the resource's operations are called when the relationship is created or ceased.Similarly, when you define a relationship that involves another assembly, you might want the relationship to call operations for that other assembly. In this case, you must first ensure that these operations are exposed in that other assembly’s descriptor by including them in its
operations
section. This process is known as publishing operations.
- Publishing operations
-
In an assembly descriptor, you publish operations so that they can be called from higher-level descriptors that contain the assembly and use it in relationships.
When you publish an operation by including it in theoperations
section, use the following format: <assembly_operation_name>: source-operation: <component_name>.<component_operation_name>
- <assembly_operation_name> is the name that you want to use to publish this operation in this assembly. This name must be used by higher-level descriptors that call this operation.
- <component_name> is the name of the component that contains the operation that you want to publish.
- <component_operation_name> is the defined name of the operation in the component’s descriptor.
- Example
-
This sample scenario shows how you can publish operations to enable the setup of relationships that involve assemblies:
- Operations R_op1 and R_op2 are described in the resource descriptor for resource_R.
- The assembly descriptor for assembly_B contains resource_R.
- The assembly descriptor for assembly_A contains assembly_B and resource_S.
- In the descriptor for assembly_A, you decide to define a relationship between assembly_B and resource_S that calls operations R_op1 and R_op2.
- To allow this relationship to be defined, you publish the two operations in the descriptor for
assembly_B by adding them to its
operations
section. - In the descriptor for assembly_A, you can now define a relationship between resource_S and assembly_B that calls the two operations.
In the descriptor for assembly_B, when you include resource_R and publish its operations, you might specify these attributes:name: assembly::assembly_B::1.0 ... composition: res_R: type: resource::resource_R::1.0 quantity: 1 properties: deploymentLocation: value: '${deploymentLocation}' resourceManager: value: '${resourceManager}' ... ... ... operations: Operation_1: source-operation: res_R.R_op1 Operation_2: source-operation: res_R.R_op2 ...
By specifying these attributes, you publish resource_R’s operations, that is, R_op1 and R_op2, by using the names Operation_1 and Operation_2 respectively.
In the descriptor for assembly_A, you might then define this relationship between assembly_B and resource_S, which calls the operations when the relationship is created and ceased:name: assembly::assembly_A::1.0 ... composition: assm_B: type: assembly::assembly_B::1.0 properties: ... res_S: type: 'resource::resource_S::1.0' properties: ... ... ... relationships: balanceStreamer: source-capabilities: - assm_B.VideoStream target-requirements: - res_S.HttpServer source-state: Active target-state: Active properties: max_connections: value: '${max_connections}' server_ip: value: '${source.privateIp}' server_port: value: '8080' lifecycle: Create: - assm_B.Operation_1 Cease: - assm_B.Operation_2
- Customizing operations on multiple component instances
-
Depending on your requirements, you might need to create an assembly descriptor that contains multiple instances of a component. In the assembly descriptor, you can describe multiple component instances by taking any of the following actions:
- In the
composition
section, you include a component that has one of these attributes:- A quantity value that is greater than 1.
- An
items
value that is based on a list or a map. - A cluster section where the
initial-quantity
value is greater than 1.Note: A cluster that has an initial quantity of 0 or 1 might later contain multiple instances if the cluster's component is scaled out.
- In the
composition
section, you include an assembly that contains multiple component instances. - In the
references
section, you refer to an existing assembly instance that contains multiple component instances.
By default, component operations that are called by relationships are called for every instance of the component. You can adjust this behavior by setting themultiple-instances
attribute. The following table lists the settings for this attribute and describes the associated behavior:Setting System behavior Usage notes/recommendations Sample use case every
The operation is called for every component instance. This setting is used by default for the operation if the multiple-instances
attribute is not set.The instance operations are not called in sequence, and therefore might run in parallel.
You want to configure distributed units (DUs) in a gNodeB base station, where each DU instance is distinct and must be configured separately. any
The operation is called for any one component instance. Use this setting when the effect of the operation on all component instances is the same regardless of which instance the operation is called for. You want to update Kafka configuration, where the configuration can be applied to any Kafka node. Kafka then ensures that the configuration is consistent across its cluster. first
The operation is called for the first component instance in a group. Use this setting when the operation is effective only if it is called on the first component instance in the group. Restriction: If the component is part of a group that is based on a map, you cannot use this setting.You want to update PostgreSQL database configuration, where a single PostgreSQL node distributes the updated configuration among the other nodes. For the sample use case that involves configuring DUs in a gNodeB, you might create an assembly descriptor for the gNodeB that includes these attributes:... composition: DU: items: ${DU-map} type: resource::dist_unit::2.1 properties: deploymentLocation: type: string value: test resourceManager: value: brent ... ... ... operations: ConfigureDUforSlice: source-operation: DU.Create-3gpp multiple-instances: every ...
In a higher-level descriptor, you might then define a relationship that involves the gNodeB assembly and calls the
ConfigureDUforSlice
operation. Because themultiple-instances
attribute is set to every, this operation is called for every DU instance. For example, when a new gNodeB assembly is created through an intent request, this operation is called for every DU instance that is created for the gNodeB. - In the
composition
section
In the composition
section, you describe the components, that is, the resources
or assemblies, that make up the assembly. The components are instantiated when a new instance of the
assembly is requested.
A dependency exists between this section and the references
section. If the
orchestration component cannot uniquely identify all of the referenced instances in the
references
section, the components in the composition
section, and
the assembly itself, cannot be instantiated.
Attribute | Description | Required | Type | Restrictions |
---|---|---|---|---|
<component_name> |
A name of your choosing that identifies the component. When the component is instantiated, this name becomes part of the instance name. |
Y | String |
|
type |
The type, name, and version number of the assembly or resource descriptor that the component instance is based on. | Y | String | |
dynamicType |
A Jinja expression, which is evaluated when an intent request is submitted, that determines which descriptor type to use for the component instance. This expression can use variables, |
N | Only properties that are defined in this component can be used in the expression. | |
quantity |
The number of instances of the component that are created. The default value is 1. |
N | Integer |
This value is used only in nonclustered environments. In clustered environments, the value of the |
properties |
The full set of properties that are required to orchestrate the component through to the
Active state.For information about how to create properties, see properties section. |
Y | ||
upgrade-dependencies |
The components that must be upgraded or reconfigured before this component can be upgraded or reconfigured. | N |
Only components that exist in this assembly descriptor can be specified. Specified resources must include the Circular dependencies are not allowed, regardless of whether the dependency is direct or
indirect. For example, if
resource_1 is an upgrade dependency of
resource_2 , you cannot perform these actions:
|
|
cluster |
A set of attributes that specify the number of component instances that can be created in, added to, or removed from a cluster. | N | ||
initial-quantity |
The initial number of component instances that are created in the cluster. If this value is not set, the value of |
N | Integer |
Must contain a value that is between the values of This value is used only in clustered environments. In nonclustered environments, the value of the
|
minimum-nodes |
The minimum number of instances that can exist in the cluster. You can set this value to 0 if no instances are required at instantiation time. The default value is 1. |
N | Integer | Cannot be greater than the value of maximum-nodes . |
maximum-nodes |
The maximum number of instances that can exist in the cluster. | N | Integer | Cannot be less than the value of minimum-nodes . |
scaling-increment |
The number of instances that are added to, or removed from, the cluster during scaling. The default value is 1. |
N | Integer | |
items |
The list or map that this component is instantiated from. This list or map is defined in the higher level
|
N | Must match the name of a list or map that is defined in the higher level
properties section for the assembly. |
- Examples
-
In this example, three components are shown with their properties omitted. The quantity of the
streamer
component is inherited from thenumOfStreamers
property, which is an assembly-wide property that is defined in the higher levelproperties
section of the descriptor.The
upgrade-dependencies
attribute specifies that, if a planned Reconfigure or Upgrade lifecycle transition is to be run on thenet_video
component, the transition must be run on thestreamer
component first.composition: streamer: # The component name type: resource::c_streamer::1.0 quantity: ${numOfStreamers} properties: ... balancer: type: resource::c_balancer::1.0 quantity: 1 properties: ... net_video: type: resource::net_video::1.0 quantity: 1 properties: ... upgrade-dependencies: - streamer
This example shows one component with seven properties. The values for some of the properties, such as
deploymentLocation
andresourceManager
, are inherited from assembly-wide properties that are defined in the higher levelproperties
section.composition: streamer: type: resource::c_streamer::1.0 cluster: ... properties: deploymentLocation: value: '${deploymentLocation}' resourceManager: value: '${resourceManager}' flavor: value: m1.small server_name: value: ${instance.name} referenced-video-network: value: ${net_video.network-id} availability_zone: value: DMZ mgmtIp: type: string description: MGMT IpAddress of server read-only: true
This example shows how a cluster of instances can be defined for a component. This cluster can contain a minimum of one instance and a maximum of four, and only one instance can be added or removed through scaling. The initial number of instances that are created when an intent request is submitted is inherited from the assembly-wide
numOfServers
property.composition: streamer: type: resource::c_streamer::1.0 cluster: initial-quantity: ${numOfServers} minimum-nodes: 1 maximum-nodes: 4 scaling-increment: 1 properties: data: value: ${data} ip_address: read-only: true
Defining component groups
You can specify that component instances are created from lists or maps that are defined in the
higher level properties
section of the descriptor.
Components that are instantiated from a list are named based on the index of the list. You can
copy data from list items into component instances by using the item
keyword.
Components that are instantiated from a map are named based on the keys of the map. You can copy
data from the map items into component instances by combining the item
keyword and
the map keys.
- Defining component instance groups by using lists
-
This example shows how the
streamer
component is defined from a list of three items, which is calledstreamers
and is defined as a higher level assembly property.properties: streamers: type: list entry_schema: type: string default: ['192.0.2.1', '192.0.2.2', '192.0.2.3'] ... composition: streamer: type: resource::c_streamer::1.0 items: ${streamers} properties: data: value: ${item}
When an intent request is submitted, an instance of the
c_streamer
resource is created for each item in the list. In each instance, the value of thedata
property is set to the value of the list item. For example, in the first component instance, the value of thedata
property is set to192.0.2.1
.Component instances that are created from a list are named based on their index in the list. In the case of the previous example, the component instances are named as follows:
{Assembly Name}__streamer__1 {Assembly Name}__streamer__2 {Assembly Name}__streamer__3
This naming strategy applies to fixed-size and cluster component groups.
Tip: The sequencing of component list items can affect how topology differences are calculated after subsequent intent requests are submitted. If the list is reordered, or if elements are removed, the topology might appear differently, because the list index forms part of the component instance name. Other unexpected changes might also occur. If items in a list of components might be reordered or removed, consider using a map to define the component group instead.
- Defining component instance groups by using maps
-
This example shows how the
streamer
component is defined from a map that is calledstreamers
, which is defined as a higher level assembly property. This map contains three maps, each of which contains anip_addr
key-value pair.properties: streamers: type: map entry_schema: type: map default: - {first: {ip-addr: '192.0.2.1'}} - {second: {ip-addr: '192.0.2.2'}} - {third: {ip-addr: '192.0.2.3'}} ... composition: streamer: type: resource::c_streamer::1.0 items: ${streamers} properties: data: value: ${item.ip_addr}
When an intent request is submitted, an instance of the
c_streamer
resource is created for each item in the map. Each instance is named based on the assembly name, the component name, and the key of the map item. As a result, the instances have the following names:{Assembly Name}__streamer__first {Assembly Name}__streamer__second {Assembly Name}__streamer__third
In each instance, the value of the
data
property is set to the value of theip_addr
key in each map item. For example, in the{Assembly Name}__streamer__first
instance, the value of thedata
property is set to192.0.2.1
.
Dynamic type evaluation
You can define components so that their descriptor type is evaluated dynamically at runtime, based on information in the assembly descriptor or on properties that belong to the component instance.
Use the dynamicType
attribute to specify a Jinja expression that is evaluated at
runtime to determine which type is used for each instance.
In this example, the dynamic type expression uses the value of each component instance's
manufacturer
property to determine which descriptor to use for the instance.
properties:
streamers:
type: list
entry_schema:
type: map
...
composition:
streamer:
type: resource::c_streamer::1.0
dynamicType: >-
{% if manufacturer == 'Netflix' %}
{{ 'resource::netflix_streamer::1.0' }}
{% else %}
{{ 'resource::basic_streamer::1.0' }}
{% endif %}
items: ${streamers}
properties:
manufacturer:
value: ${item.mfr}
ip_addr:
value: ${item.ip_addr}
For components that are instantiated from lists and maps, dynamic type expressions can enable different instances within the same group to have different types. However, for fixed-size groups and clusters, all instances have the same type.
type
attribute must still be specified. You can use type
to specify a common descriptor that is suitable in all use cases, then specify a dynamic type
expression when you want to use different descriptors in particular use cases.- Resolving descriptor versions dynamically
-
You can also resolve the version of a descriptor based on the available descriptors in the system. To resolve the descriptor version, use a
resolveVersion
filter in the dynamic type expression.In this example, if the value of the component instance's
serverType
property isDell
, theresolveVersion
filter determines that any version of thet_simple
descriptor from 1.0 onwards can be used.composition: A: type: resource::not_found::1.0 dynamicType: >- {% if serverType == 'Dell' %} {{ 'resource::t_simple::[1.0,)'|resolveVersion }} {% elif serverType == 'Supermicro' %} {{ 'resource::t_simple_indexed::1.0' }} {% else %} {{ 'resource::t_simple::1.0' }} {% endif %} items: ${data}
To determine the version, the
resolveVersion
filter is run on the text in quotes that precedes the pipe symbol (|
) , that is,'resource::t_simple::[1.0,)'
. The filter resolves the version range, that is,[1.0,)
. This range indicates that the earliest version that can be used is 1.0, and any later version can be used. The filter then queries the Apollo descriptor catalog to identify the descriptor to use.The version range must be specified by using the Maven version range syntax. You must provide at least a minimum version or a maximum version. For more information about acceptable Maven version ranges, see Version Range References in the Oracle documentation.
Restriction: ThedynamicType
expression is evaluated when an intent request is submitted. If a new descriptor version that matches the expression is added since the last update for an assembly, the descriptor version that is used for the component might change. This change might cause resources to be reconfigured or reinstalled.
references
section
references
section, you describe existing assembly or resource instances
that you want to refer to elsewhere in the descriptor. You can describe two types of referenced instance:- Assembly instances that the orchestration component created.
- Externally-managed resource instances.
You can refer to these instances when you specify component properties or create relationships.
composition
section can be instantiated. If
any referenced instance cannot be identified, the assembly is not instantiated.Install
and
Uninstall
lifecycle transitions.For each referenced instance, you must define the following attributes:
Attribute | Description | Required | Type | Restrictions |
---|---|---|---|---|
<referenced_instance_name> |
A name of your choosing that is used to refer to the instance in this descriptor. |
Y | String |
|
type |
The type, name, and version number of the referenced instance's descriptor. You can use semantic versioning to specify the version number. |
Y | String | |
properties |
The properties that the orchestration component uses to uniquely identify the instance. If the orchestration component created the instance, you can refer to any of the properties in the instance's descriptor. You must include the For more information about the properties that you can specify, see properties section. |
Y |
- Examples
-
In this example, two referenced instances are described. For the
storage
instance, the following information is provided to help the orchestration component to uniquely identify the instance:- The type, name, and version of the instance's assembly descriptor. The exact version is not specified, but semantic versioning is used to restrict the range to versions between 1.0 and 1.9.
- Three property values, that is,
deploymentLocation
,resourceManager
, andstorage-name
, that are defined in the higher levelproperties
section of this assembly.
For the
ucd_network
instance, the following information is provided:- The type, name, and version number of the referenced instance's resource descriptor.
- Three higher level assembly properties, that is,
deploymentLocation
,resourceManager
, andmanagement-network-name
.
references: storage: # reference to an existing assembly instance type: assembly::storage_cluster::^1.0 properties: deploymentLocation: value: '${deploymentLocation}' resourceManager: value: '${resourceManager}' name: value: '${storage-name}' management-network: # reference to a neutron network that was not created by the orchestration component type: resource::ucd_network::1.0 properties: deploymentLocation: value: '${deploymentLocation}' resourceManager: value: '${resourceManager}' name: value: ${management-network-name}
After the orchestration component identifies these instances, their properties can be accessed by using this syntax:
${<referenced-item-name>.<property-name>}
For example, when you describe a component that is calledbalancer
, you might specify these attributes to access theid
property from a referenced instance that is calledmanagement-network
:composition: balancer: type: 'resource::c_balancer::1.0' quantity: '1' properties: … referenced-management-network: value: '${management-network.id}'
relationships
section
relationships
section, you define the relationships that you want to
create between source and target components. For each relationship, you provide the following
information: - The capabilities that the source component provides.
- The capabilities that the target component requires.
- The state that each component must reach for the relationship to be created.
- The operations that are run when the relationship is created and when it is ceased.
Attribute | Description | Required | Type | Restrictions |
---|---|---|---|---|
<relationship_name> | A name of your choosing that identifies the relationship. | Y | String |
|
source-capabilities |
A list of capabilities that the source component provides. You use this attribute to identify the source component in the relationship. If the source component is an assembly component that is described in the
If the source component is a referenced instance that is described in the
|
Y | String |
For assembly components, these restrictions apply:
For referenced instances, the instance name must match the name that is used in the
|
target-requirements |
A list of capabilities that the target component requires. You use this attribute to identify the target component in the relationship. Specify each requirement in this format:
|
Y | String |
|
source-state |
The state that the source component must reach for the relationship to be created. By default, the relationship is created after the source component reaches this state. You can
change this order of events by using the The relationship is always ceased before the source component leaves this state. |
Y | String |
Must be one of these values:
|
source-state-modifier |
A value that determines whether the relationship is created before or after the source component
reaches the state that is specified in To create the relationship before the source state is reached, set this attribute to
If this attribute is not specified, the relationship is created after the source state is reached. |
N |
Must be one of these values:
|
|
target-state |
The state that the target component must reach for the relationship to be created. By default, the relationship is created before the target component reaches this state. You can
change this order of events by using the The relationship is always ceased before the target component leaves this state. |
Y | String |
Must be one of these values:
|
target-state-modifier |
A value that determines whether the relationship is created before or after the target component
reaches the state that is specified in To create the relationship after the target state is reached, set this attribute to
If this attribute is not specified, the relationship is created before the target state is reached. |
N |
Must be one of these values:
|
|
properties |
The properties that apply to this relationship. These properties can be used by the operations that you specify in the
You can inherit the values of source or target component properties by using the syntax
For more information about the properties that you can specify, see properties section. |
Y | ||
lifecycle |
The lifecycle transitions that this relationship supports, and the operations that are run for each transition. Only the |
Y | ||
Create |
The operations that are called when the relationship is created. These operations are called one at a time in the specified order. Specify source operations in the format |
Y | String |
Each operation name must match the name of a defined operation in the |
Cease |
The operations that are called when the relationship is ceased. These operations are called one at a time in the specified order. Specify source operations in the format |
Y | String |
Each operation name must match the name of a defined operation in the |
multiple-instances
attribute in the operations
section. For more
information, see Customizing operations on multiple component instances.- Example
-
This example shows how you might configure a relationship between two components.
- The source component, that is,
storage
, provides theNFSMountpoint
capability. The target component, that is,streamer
, requires theRemoteNFSMountPoint
capability. - The relationship is created after the
storage
component reaches theActive
state and before thestreamer
component reaches theInactive
state. - When the relationship is created, the
MountStorage
operation, which is defined in the descriptor that thestorage
component is based on, is called. - The relationship contains several properties, including r
emote_nfs_server_ip
, which inherits the value of theprivateIp
property that is defined for thestorage
component. These properties can be used by theMountStorage
andUnmountStorage
operations. - The relationship is ceased before the
storage
component leaves theActive
state and before thestreamer
component leaves theInactive
state. - When the relationship is ceased, the
UnmountStorage
operation, which is defined in the descriptor that thestorage
component is based on, is called.
relationships: nfs_mount: source-capabilities: - storage.NFSMountpoint target-requirements: - streamer.RemoteNFSMountPoint source-state: Active target-state: Inactive properties: remote_nfs_port: value: '2049' remote_nfs_server_ip: value: '${source.privateIp}' remote_mount_point: value: '/' local_mount_point: value: '/mnt' lifecycle: Create: - source.MountStorage Cease: - source.UnmountStorage
- The source component, that is,
data-types
section
In the data-types
section, you define customized data types that you can use in
descriptor properties. You can define data types for sub-properties within a property, or specify
that a property derives a data type from another property.
Derived data types are specified in a derived-from
attribute. A data type that
derives properties from another data type derives all of the other data type's properties. In
addition, data types can reuse other data types in their properties. In this way, you can build up a
complex data type hierarchy.
Attribute | Description | Required | Type | Restrictions |
---|---|---|---|---|
<data_type_name> | A name of your choosing that describes the customized data type. | Y | String |
|
derived-from |
The name of another customized data type that this data type is derived from. All of the other data type's properties are inherited by this data type. |
N | Customized data type | Must match the name of another data type that is defined in this section. |
properties |
The properties of this customized data type. These properties can include other customized data types. For information about how to create assembly descriptor properties, see properties section. For information about how to create resource descriptor properties, see properties and private-properties sections. |
Y |
This example defines a customized data type, tag
,
which has one property, that is, name
. In the server
component
properties, in the tags
list, the entry-schema
property is used to
specify tag
as the data type of each value in the
list.
server:
properties:
tags:
type: list
entry-schema:
type: tag
tag:
properties:
name:
type: string
server
component
might contain data that is similar to this sample
data:"server": [
"tags": [
{
"name": "clustered"
}
{
"name": "non-clustered"
}
]
- Five standard data types,
base-type
,vnf-cpd
,ns-cpd
,pnf-cpd
, andvirtual-link-desc
, which include properties that have a type ofstring
. - Two data types
associated-cpd-id
andcpd-or-vl
, which reuse some of the five standard data types. For example,associated-cpd-id
reuses thevnf-cpd
,pnf-cpd
, andns-cpd
data types. - The
sap-type
data type, which derives properties from the data typebase-type
.- Because
base-type
contains a single property,source
,sap-type
inherits this property. - In the properties for the
sap
map, theentry-schema
property is used to specifysap-type
as the data type of each value in the map.
- Because
properties:
sap:
type: map
entry-schema: sap-type
default:
id: "ident1"
address-segment: "segment"
cpd-or-virtual-link:
...
...
data-types:
base-type:
properties:
source:
type: string
description: details about the source of an object
vnf-cpd:
properties:
vnfd-id:
type: string
ext-cpd-id:
type: string
ns-cpd:
properties:
ns-id:
type: string
ext-cpd-id:
type: string
pnf-cpd:
properties:
pnf-id:
type: string
ext-cpd-id:
type: string
virtual-link-desc:
properties:
virtual-link-desc:
type: string
associated-cpd-id:
properties:
vnf:
type: vnf-cpd
pnf:
type: pnf-cpd
ns:
type: ns-cpd
cpd-or-vl:
properties:
virtual-link-desc:
type: virtual-link-desc
associated-cpd-id:
type: associated-cpd-id
sap-type:
derived-from: base-type
properties:
id:
type string
address-assignment:
type: string
cpd-or-virtual-link:
type: cpd-or-vl
capabilities
and requirements
sections
In the capabilities
section of a component's descriptor, where a component is a
resource or an assembly, you define the functions that the component instance provides. In the
requirements
section, you define the capabilities that the component instance
requires to work successfully.
For example, a capabilities
section might state that a component instance
provides incoming HTTP requests. A requirements
section might state that networks
of various types are required for a component instance to work.
Attribute | Description | Required | Type | Restrictions |
---|---|---|---|---|
<capb_or_req_name> | A name of your choosing that describes the capability or requirement. | Y | String |
|
type |
For capabilities, a term of your choosing that indicates the function that this component instance provides. For requirements, the defined If possible, use common industry terms. |
Y | String |
- An HTTP response output stream, which is identified by the name
VideoStream
. - An API to the OpenStack Networking service, which allows network objects to be created within
OpenStack, and which is identified by the name
Network
.
capabilities:
VideoStream:
type: httpStreamOutput
Network:
type: neutronNetwork
- The requirement for a HTTP response output stream is identified by the name
HttpOutputStream
. - Requirements for API access to the OpenStack Networking service are identified by the names
VideoNetwork
andManagementNetwork
.
requirements:
HttpOutputStream:
type: httpStreamOutput
VideoNetwork:
type: neutronNetwork
ManagementNetwork:
type: neutronNetwork