tosca_definitions_version: tosca_simple_yaml_1_3 topology_template: node_templates: web: type: Application requirements: - host: node_filter: # Our target provider will be selected using a node filter. In this case we have only # one node template that has "can_provision" as true. properties: can_provision: - equal: true relationship: # Our target hosts will be selected during deployment via an allocation engine. # We will use the "selector" property to configure both the the allocation algorithm. # In this case we will allow any ARM hosts but for x86 we will avoid the ACME vendor, # and we also require hosts that have at least 6 cores. properties: host_count: 5 # we want to install on 5 hosts provision: true # provision new hosts if there are less than 5 hosts matching our selector selector: and: - or: - equal: { attribute: [ host, architecture ], string: arm } - and: - equal: { attribute: [ host, architecture ], string: x86 } - not: equal: { attribute: [ host, vendor ], string: ACME } - greater_or_equal: { attribute: [ host, core_count ], integer: 6 } # Our target node template will be a substituted virtual provider, which provides hosts as # virtual machines using the OpenStack API. We will assume that the provider may maintain a pool # of "ready to use" virtual machines, in addition to being able to provision new ones on demand. openstack-cluster: type: VirtualMachineProvider properties: platform: OpenStack directives: - substitutable # We could, instead, choose this cluster of managed physical machines by filtering on # "can_provision" equals false. baremetal: type: PhysicalCluster properties: can_provision: false node_types: Application: description: >- A software package that can be installed zero or more times on hosts. Runtime model: An "instance" represents a single running deployment of the software package. Each deployment will have its own unique attributes. requirements: - host: capability: Host # Both VirtualProvider and PhysicalCluster have this capability relationship: Installations HostProvider: description: >- Provides hosts. It is expected that a provider has an allocation engine that supports our SimpleSelector DSL. Optionally, it may also have a provisioning engine. Runtime model: The provider is a singleton, meaning there is only ever one "instance" of the provider. Node attributes thus refer to the particular singleton provider. However, each provider can have zero or more hosts, which would be considered the "instances" (factory pattern). The attributes of the "host" capability thus map to individual host instances. properties: can_provision: description: >- Whether or not this provider has a provisioning engine. type: boolean capabilities: host: Host VirtualMachineProvider: derived_from: HostProvider properties: can_provision: type: boolean default: true platform: type: string PhysicalCluster: description: >- A physical cluster might have "stand by" machines which it can provision for us as hosts by installing an operating system on them, allocating VLANs, etc. Thus, some clusters may set "has_provision" to true. derived_from: HostProvider properties: can_provision: type: boolean default: false attributes: machine_count: type: integer capability_types: Host: attributes: architecture: type: string vendor: type: string core_count: type: integer virtual: type: boolean relationship_types: Installations: description: >- Describes the requirements for zero or more software installations on hosts. valid_target_types: [ Host ] properties: selector: description: >- This standardized expression will be fed to a runtime allocation engine. The number of hosts to be selected is determined by "host_count". type: SimpleSelector required: false host_count: description: >- By default a single host will be selected (according to the "selector"), but this value can be increased, in which case more hosts will be selected, and there will be a one-to-many runtime relationship between the source and the target hosts. If the number of hosts that match the "selector" is greater than "host_count", then arbitrary hosts will be selected from within that group. (Unfortunately, secondary or fallback selection criteria cannot be easily expressed via this simplistic algorithm.) If the number of selected hosts is smaller than "host_count", then the outcome will depend on the "provision" property. If "provision" is true, then new hosts will be provisioned to meet the "host_count" number. Otherwise, allocation will fail with an error. Set this property to 0 to disable installation without error (in which case the relationship will remain as a purely design-time construct and there will be no runtime instances of it). type: integer default: 1 constraints: - greater_or_equal: 0 provision: description: >- Whether to allow provisioning of new hosts in case the number of selected nodes is smaller than "host_count". It is assumed that the allocation engine can delegate this work to a provisioning engine. Note that the provisioned nodes would obviously have to match the "selector". However, there is no way to specify preferences using this simplistic algorithm. type: boolean default: false installations_per_host: description: >- The number of installations (relationship instances) per target host. Note that the actual number of installations (relationship instances) would be "host_count" * "installations_per_host". type: integer default: 1 constraints: - greater_or_equal: 1 data_types: SimpleSelector: description: >- Generic, simple DSL for runtime node instance selection via an algorithm based on standardized expressions and node instance attribute or property values. This DSL is likely insufficient for many real world situations. On the one hand, the allocation engine is likely already provided and cannot be modified to support this DSL. In such a case the actual allocation engine can be modeled using its own specific TOSCA data types. On the other hand, this simple DSL might be too simple, in which case it can be expanded. That said, TOSCA data types may very well be insufficient for modeling a complex DSL, in which case you can either provide the source code for your DSL as a string value or attach it as an artifact. Note: One *and only one* of the properties must be set. (There is currently no way to express this kind of requirement in TOSCA.) properties: equal: type: CompareValue required: false greater_than: type: CompareValue required: false greater_or_equal: type: CompareValue required: false less_than: type: CompareValue required: false less_or_equal: type: CompareValue required: false not: type: SimpleSelector required: false and: type: list entry_schema: SimpleSelector required: false or: type: list entry_schema: SimpleSelector required: false CompareValue: description: >- Compares an attribute or property value to a literal value. Unfortunately, TOSCA does not have an "any" type, so we must specify individual properties per type. Note: One *and only one* of "attribute" or "property" must be set. Also, one *and only one* of "string", "integer", "float", or "boolean" must be set. (There is currently no way to express this kind of requirement in TOSCA.) properties: attribute: description: >- Path to the attribute. Uses the syntax for the "get_property" function. type: list entry_schema: string required: false property: description: >- Path to the property. Uses the syntax for the "get_property" function. type: list entry_schema: string required: false string: type: string required: false integer: type: integer required: false float: type: float required: false boolean: type: boolean required: false