The First Five Minutes: Run Stuff
A Compute Node
When working with VMs and TOSCA, the starting point will often be the tosca.nodes.Compute
node type.
This requests that a new “compute node” (for instance a VM) be provisioned.
You can deploy the following TOSCA “topology template” defining a compute node:
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_name: compute-example
template_version: 1.0.0-SNAPSHOT
topology_template:
node_templates:
a_server:
type: tosca.nodes.Compute
Try it, in the GUI, or copying to compute-example.yaml
and running br deploy compute-example.yaml
.
A Software Component Node
The next step is either to use a specific image and/or to have some software installed. If you’re interested in the former, or more details on configuring compute nodes, see Common Types. In this section, we’ll cover the latter.
First, we need to say which compute node our software is going to be hosted on.
We will use a tosca.nodes.SoftwareComponent
– which under the covers,
has a TOSCA “requirement” called host
that must point at a tosca.nodes.Compute
node.
In practice, this is straightforward to fulfill, we simply reference the compute node,
called a_server
here, in the host
requirement:
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_name: tosca-demo-0
template_version: 1.0.0-SNAPSHOT
topology_template:
node_templates:
a_server:
type: tosca.nodes.Compute
a_software:
type: tosca.nodes.SoftwareComponent
requirements:
- host: a_server
Again the above can be deployed in the GUI or with br deploy
.
A Software Component with custom behaviour
We will invoke some bash scripts as part of the deployment.
Create directories 1-hello
, 1-hello/scripts
and bash scripts 1-hello/scripts/configure.sh
,
1-hello/scripts/start.sh
, 1-hello/scripts/stop.sh
with content like the following:
echo configuring/starting/stopping my software # choose one operation per script
Create 1-hello/topology.yaml
with the following content:
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_name: tosca-demo-1
template_version: 1.0.0-SNAPSHOT
topology_template:
node_templates:
a_server:
type: tosca.nodes.Compute
interfaces:
Standard:
operations:
configure: classpath://scripts/configure.sh
a_software:
type: tosca.nodes.SoftwareComponent
requirements:
- host: a_server
interfaces:
Standard:
operations:
create: classpath://scripts/configure.sh
start: classpath://scripts/start.sh
stop: classpath://scripts/stop.sh
Create directory 1-hello/run
and runnable tosca blueprint 1-hello/run/run.yaml
with the following content:
tosca_definitions_version: tosca_simple_yaml_1_3
topology_template:
node_templates:
app:
type: tosca-demo-1
Add new type and its dependencies into AMP catalog, by running the following command:
br catalog add 1-hello
And then deploy new application, by running:
br deploy 1-hello/run/run.yaml
Behaviour that we added by customizing the operations for the Standard
interface, become part of application lifecycle,
and can be called manually in AMP Effectors, when needed.
More behaviour, input data or configurations, can be added to an operation using artifacts as shown in the example below:
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_name: tosca-demo-1
template_version: 1.0.0-SNAPSHOT
topology_template:
node_templates:
a_server:
type: tosca.nodes.Compute
a_software:
type: tosca.nodes.SoftwareComponent
requirements:
- host: a_server
interfaces:
Standard:
operations:
configure:
implementation:
primary: classpath://scripts/configure.sh
dependencies:
- config_file
artifacts:
config_file:
file: classpath://scripts/hello.sh
Create the 1-hello/scripts/hello.sh
with a simple command such as echo hello
, respectively.
Inputs and Properties
Inputs are set on topology_template
to allow custom values to be injected as arguments for node and relationship templates. The input values can be injected into properties or attributes, as shown in the following example:
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_name: testTemplateWithInputs
topology_template:
inputs:
input_num_cpus:
type: integer
description: Number of CPUs for the server.
default: 3
node_templates:
a-node:
type: tosca.nodes.Compute
properties:
custom_cpus_no: {get_input: input_num_cpus}
attributes:
num_cpus: {get_input: input_num_cpus}
Properties are declared on node types. they can have default values or their values can be injected with inout values, as shown in the following example:
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_name: testTemplateWithCustomPropertiesAndInputs
node_types:
tosca-custom-node:
derived_from: tosca.nodes.Compute
properties:
custom_cpus_no:
type: integer
required: true
app.port:
type: string
required: false
default: 8080
topology_template:
inputs:
input_num_cpus:
type: integer
description: Number of CPUs for the server.
default: 3
node_templates:
a-node:
type: tosca-custom-node
properties:
custom_cpus_no: {get_input: input_num_cpus}
app.port: 9090
Dependency Injection: A Three Tier Co-Lo Deployment
There are two ways to connect nodes in the same application: through relationships and through attributes. Using relationships results in rigid node connection.
The dependency between two nodes is declared in the node type and deploying a node template of one type without the other is not allowed. The following example shows the declaration of two node types and the relationship type used to link them.
An Apache Tomcat node is declared requiring a Database node, using a relationship type named io.cloudsoft.depends-on-db
.
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_name: io.cloudsoft.tosca-node-types
template_version: 0.1.0-SNAPSHOT
relationship_types:
io.cloudsoft.depends-on-db:
derived_from: tosca.relationships.DependsOn
interfaces:
Configure:
pre_configure_source:
inputs:
DB_URL: { get_attribute: [ TARGET, db_url ] }
DB_DRIVER: { get_attribute: [ TARGET, db_driver ] }
implementation: classpath://tomcat-scripts/tomcat-configure_db.sh
node_types:
tosca-tomcat8-node:
derived_from: tosca.nodes.WebServer
# configuration elements omitted for brevity
requirements:
- needs-db:
relationship: io.cloudsoft.depends-on-db
node: tosca.nodes.Database
tosca-postgresql12-node:
derived_from: tosca.nodes.Database
# configuration elements omitted for brevity
attributes:
db_url: { concat: [ "postgresql://", get_attribute: [ HOST, public_address ] , ":", get_property: [ SELF, app.port ] ] }
db_driver:
type: string
description: Driver to use to connect the DB
default: "org.postgresql.Driver"
Creating a topology template using these three types is quite straight forward.
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_name: io.cloudsoft.family-chat-postgresql
template_version: 0.1.0-SNAPSHOT
# some configurations were omitted for brevity
topology_template:
node_templates:
tomcat-host:
type: tosca.nodes.Compute
tomcat-instance:
type: tosca-tomcat8-node
requirements:
- host: tomcat-host
- needs-db: db-instance
db-host:
type: tosca.nodes.Compute
db-instance:
type: tosca-postgresql12-node
requirements:
- host: db-host
The other way to declare a dependency is by using attributes. Since a relationship is not enforced, those two node types can be used for node templates deployed independently.
This promotes reusability, since the node templates can be used separately in different topology templates. This is especially useful when clusters of nodes are required.
The following example shows an Apache Tomcat node type that does not declare a requirement (dependency) on a database node through a relationship, but through two properties that will be set with values
when the database node is deployed. The values of those properties are then used as inputs for the interface configure
operation. The database node require no changes.
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_name: io.cloudsoft.tosca-node-types
template_version: 0.1.0-SNAPSHOT
node_types:
smart-tomcat8-node:
derived_from: tosca-tomcat8-node
# configuration elements omitted for brevity
properties:
db_url:
type: string
required: false
description: URL of the database.
db_driver:
type: string
required: false
description: Driver of the database.
interfaces:
Standard:
configure:
inputs:
DB_URL: { get_property: [ SELF, db_url ] }
DB_DRIVER: { get_property: [ SELF, db_driver ] }
implementation:
primary: classpath://tomcat-scripts/tomcat-inject_db.sh
The following example shows how to use this node type in a simple topology template declaring a tomcat and a database node template.
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_name: io.cloudsoft.family-chat-postgresql
template_version: 0.1.0-SNAPSHOT
# some configurations were omitted for brevity
topology_template:
node_templates:
tomcat-host:
type: tosca.nodes.Compute
tomcat-instance:
type: smart-tomcat8-node
properties:
db_url: { get_attribute: [ db-instance, db_url ] }
db_driver: { get_attribute: [ db-instance, db_driver ] }
requirements:
- host: tomcat-host
db-host:
type: tosca.nodes.Compute
db-instance:
type: tosca-postgresql12-node
requirements:
- host: db-host
And since clusters where mentioned, the following example adds in a topology template encapsulating a tomcat host and node, that can be used as a cluster member.
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_author: Cloudsoft
template_name: io.cloudsoft.smart-tomcat9-node-member
template_version: 0.1.0-SNAPSHOT
# some configurations were omitted for brevity
topology_template:
inputs:
tomcat_db_url:
default: null
tomcat_db_driver:
default: null
node_templates:
tomcat-host:
type: tosca.nodes.Compute
tomcat-instance:
type: smart-tomcat9-node
properties:
db_url: { get_input: tomcat_db_url }
db_driver: { get_input: tomcat_db_driver }
requirements:
- host: tomcat-host
The following example shows how to use this node type in a topology template declaring a cluster of tomcat nodes and a database node template.
tosca_definitions_version: tosca_simple_yaml_1_3
metadata:
template_name: io.cloudsoft.cluster-with-postgresql
template_version: 0.1.0-SNAPSHOT
# some configurations were omitted for brevity
topology_template:
node_templates:
db-host:
type: tosca.nodes.Compute
db-instance:
type: tosca-postgresql12-node
requirements:
- host: db-host
tomcat-cluster:
type: tosca.entity.DynamicCluster
properties:
cluster.initial.size: 2
dynamiccluster.memberspec:
$brooklyn:entitySpec:
name: Apache Tomcat Member
type: io.cloudsoft.smart-tomcat9-node-member
brooklyn.config:
tomcat_db_url: { get_attribute: [ db-instance, db_instance_url ] }
tomcat_db_driver: { get_attribute: [ db-instance, db_instance_driver ] }