Introduction
Starting your journey on vRA 8.x can be a little challenging. Out of numerous demanding areas, one of them is creating blueprints or do i say, cloud templates in Cloud Assembly. Converting your existing vRA 7.x blueprints to vRA 8.x cloud templates requires some clarity on YAML development. Even though, a good deal of things are already provided out of the box, considering YAML as a Code which can single-handedly establish all your cloud deployments, getting the desired state out of it can be a trickster. Hence, I would like to share some quick bits on what we can do in vRA provided YAML editor to get the job done faster.
Samples
We will start with the basics and then will move to more advanced template options.
A blank template
name: templateName
formatVersion: 1
inputs: {}
resources: {}
YAMLLiterals
The following literals are supported:
- Boolean (true or false)
- Integer
- Floating point
- StringBackslash escapes double quote, single quote, and backslash itself:
"
is escaped as\"
'
is escaped as\'
\
is escaped as\\
Quotes only need to be escaped inside a string enclosed with the same type of quote, as shown in the following example."I am a \"double quoted\" string inside \"double quotes\"."
- Null
Environment variables
Environment names:
- orgId
- projectId
- projectName
- deploymentId
- deploymentName
- blueprintId
- blueprintVersion
- blueprintName
- requestedBy (user)
- requestedAt (time)
${env.blueprintId}
Resource variables
Resource variables let you bind to resource properties from other resources
format: resource.RESOURCE_NAME.PROPERTY_NAME
${resource.db.id}
${resource.db.networks[0].address}
${resource.app.id} (Return the string for non-clustered resources, where count isn't specified. Return the array for clustered resources.)
${resource.app[0].id} (Return the first entry for clustered resources.)
Resource self variables
Resource self variables are allowed only for resources supporting the allocation phase. Resource self variables are only available (or only have a value set) after the allocation phase is complete.
${self.address}
(Return the address assigned during the allocation phase.)
Note that for a resource named resource_x
, self.property_name
and resource.resource_x.property_name
are the same and are both considered self-references.
Cluster count index
${count.index == 0 ? "primary" : "secondary"}
(Return the node type for clustered resources.)
Limitations:
Use of count.index
for resource allocation is not supported. For example, the following capacity expression fails when it references the position within an array of disks created at input time.
inputs:
disks:
type: array
minItems: 0
maxItems: 12
items:
type: object
properties:
size:
type: integer
title: Size (GB)
minSize: 1
maxSize: 2048
resources:
Cloud_vSphere_Disk_1:
type: Cloud.vSphere.Disk
properties:
<kbd>capacityGb: '${input.disks[count.index].size}'</kbd>
count: '${length(input.disks)}'
YAMLConditions
- Equality operators are
==
and!=
. - Relational operators are
<
>
<=
and>=
. - Logical operators are
&&
||
and!
. - Conditionals use the pattern:condition-expression
?
true-expression:
false-expression
${input.count < 5 && input.size == 'small'}
${input.count < 2 ? "small" : "large"}
Arithmetic operators
Operators are +
–
/
*
and %
.
${(input.count + 5) * 2}
String concatenation
${'ABC' + 'DEF'}
Operators [ ] and .
The expression follows ECMAScript in unifying the treatment of the [ ] and . operators.
So, expr.identifier
is equivalent to expr["identifier"]
. The identifier is used to construct a literal whose value is the identifier, and then the [ ] operator is used with that value.
${resource.app.networks[0].address}
In addition, when a property includes a space, delimit with square brackets and double quotes instead of using dot notation.
Incorrect:
input.operating system
Correct:
input["operating system"]
Construction of map
${{'key1':'value1', 'key2':input.key2}}
Construction of array
${['key1','key2']}
Functions
${function(arguments...)}
${to_lower(resource.app.name)}
List of supported functions
Function | Description |
---|---|
abs(number) | Absolute number value |
avg(array) | Return average of all values from array of numbers |
base64_decode(string) | Return decoded base64 value |
base64_encode(string) | Return base64 encoded value |
ceil(number) | Returns the smallest (closest to negative infinity) value that is greater than or equal to the argument and is equal to a mathematical integer |
contains(array, value) | Check if array contains a value |
contains(string, value) | Check if string contains a value |
digest(value, type) | Return digest of value using supported type (md5, sha1, sha256, sha384, sha512) |
ends_with(subject, suffix) | Check if subject string ends with suffix string |
filter_by(array, filter) | Return only the array entries that pass the filter operationfilter_by([1,2,3,4], x => x >= 2 && x <= 3) returns [2, 3] filter_by({'key1':1, 'key2':2}, (k,v) => v != 1) returns [{"key2": 2}] |
floor(number) | Returns the largest (closest to positive infinity) value that is less than or equal to the argument and is equal to a mathematical integer |
format(format, values…) | Return a formatted string using Java Class Formatter format and values. |
from_json(string) | Parse json string |
join(array, delim) | Join array of strings with a delimiter and return a string |
json_path(value, path) | Evaluate path against value using XPath for JSON. |
keys(map) | Return keys of map |
length(array) | Return array length |
length(string) | Return string length |
map_by(array, operation) | Return each array entry with an operation applied to itmap_by([1,2], x => x * 10) returns [10, 20] map_by([1,2], x => to_string(x)) returns ["1", "2"] map_by({'key1':1, 'key2':2}, (k,v) => {k:v*10}) returns [{"key1":10},{"key2":20}] |
map_to_object(array, keyname) | Return an array of key:value pairs of the specified key name paired with values from another arraymap_to_object(resource.Disk[*].id, "source") returns an array of key:value pairs that has a key field called source paired with disk ID stringsNote thatmap_by(resource.Disk[*].id, id => {'source':id}) returns the same result |
matches(string, regex) | Check if string matches a regex expression |
max(array) | Return maximum value from array of numbers |
merge(map, map) | Return a merged map |
min(array) | Return minimum value from array of numbers |
not_null(array) | Return the first entry which is not null |
now() | Return current time in ISO-8601 format |
range(start, stop) | Return a series of numbers in increments of 1 that begins with the start number and ends just before the stop number |
replace(string, target, replacement) | Replace string containing target string with target string |
reverse(array) | Reverse entries of array |
slice(array, begin, end) | Return slice of array from begin index to end index |
split(string, delim) | Split string with a delimiter and return array of strings |
starts_with(subject, prefix) | Check if subject string starts with prefix string |
substring(string, begin, end) | Return substring of string from begin index until end index |
sum(array) | Return sum of all values from array of numbers |
to_json(value) | Serialize value as json string |
to_lower(str) | Convert string to lower case |
to_number(string) | Parse string as number |
to_string(value) | Return string representation of the value |
to_upper(str) | Convert string to upper case |
trim(string) | Remove leading and trailing spaces |
url_encode(string) | Encode string using url encoding specification |
uuid() | Return randomly generated UUID |
values(map) | Return values of map |
Referencing input parameters
In the resources
section, you can reference an input parameter using ${input.property-name}
syntax. If a property name includes a space, delimit with square brackets and double quotes instead of using dot notation: ${input["property name"]}
.
inputs:
sshKey:
type: string
maxLength: 500
resources:
frontend:
type: Cloud.Machine
properties:
remoteAccess:
authentication: publicPrivateKey
sshKey: <mark style="background-color:#ffffff" class="has-inline-color has-black-color">'${input.sshKey}'</mark>
YAMLImportant In cloud template code, you cannot use the word input
except to indicate an input parameter.
Optional Inputs
Inputs are usually required and marked with an asterisk. To make an input optional, set an empty default value as shown.
owner:
type: string
minLength: 0
maxLength: 30
title: Owner Name
description: Account Owner
<mark style="background-color:#ffffff" class="has-inline-color has-black-color">default: ''</mark>
YAMLList of available input properties
Property | Description |
---|---|
const | Used with oneOf. The real value associated with the friendly title. |
default | Prepopulated value for the input.The default must be of the correct type. Do not enter a word as the default for an integer. |
description | User help text for the input. |
encrypted | Whether to encrypt the input that the user enters, true or false.Passwords are usually encrypted.You can also create encrypted properties that are reusable across multiple cloud templates. See Secret Cloud Assembly properties. |
enum | A drop-down menu of allowed values.Use the following example as a format guide.enum: – value 1 – value 2 |
format | Sets the expected format for the input. For example, (25/04/19) supports date-time.Allows the use of the date picker in Service Broker custom forms. |
items | Declares items within an array. Supports number, integer, string, Boolean, or object. |
maxItems | Maximum number of selectable items within an array. |
maxLength | Maximum number of characters allowed for a string.For example, to limit a field to 25 characters, enter maxLength: 25 . |
maximum | Largest allowed value for a number or integer. |
minItems | Minimum number of selectable items within an array. |
minLength | Minimum number of characters allowed for a string. |
minimum | Smallest allowed value for a number or integer. |
oneOf | Allows the user input form to display a friendly name (title) for a less friendly value (const). If setting a default value, set the const, not the title.Valid for use with types string, integer, and number. |
pattern | Allowable characters for string inputs, in regular expression syntax.For example, '[a-z]+' or '[a-z0-9A-Z@#$]+' |
properties | Declares the key:value properties block for objects. |
readOnly | Used to provide a form label only. |
title | Used with oneOf. The friendly name for a const value. The title appears on the user input form at deployment time. |
type | Data type of number, integer, string, Boolean, or object.Important:A Boolean type adds a blank checkbox to the request form. Leaving the box untouched does not make the input False.To set the input to False, users must check and then clear the box. |
writeOnly | Hides keystrokes behind asterisks in the form. Cannot be used with enum. Appears as a password field in Service Broker custom forms. |
Explicit dependencies
Sometimes, a resource needs another to be deployed first. For example, a database server might need to exist first, before an application server can be created and configured to access it.
An explicit dependency sets the build order at deployment time, or for scale in or scale out actions. You can add an explicit dependency using the graphical design canvas or the code editor.
- Design canvas option—draw a connection starting at the dependent resource and ending at the resource to be deployed first.
- Code editor option—add a
dependsOn
property to the dependent resource, and identify the resource to be deployed first.An explicit dependency creates a solid arrow in the canvas.

Property bindings
Sometimes, a resource property needs a value found in a property of another resource. For example, a backup server might need the operating system image of the database server that is being backed up, so the database server must exist first.
Also called an implicit dependency, a property binding controls build order by waiting until the needed property is available before deploying the dependent resource. You add a property binding using the code editor.
- Edit the dependent resource, adding a property that identifies the resource and property that must exist first.A property binding creates a dashed arrow in the canvas.

Encrypt access credentials
resources:
apitier:
type: Cloud.Machine
properties:
cloudConfig: |
#cloud-config
runcmd:
- export apikey=${base64_encode(input.username:input.password)}
- curl -i -H 'Accept:application/json' -H 'Authorization:Basic :$apikey' http://example.com
YAMLPassing inputs to ABXs
resources:
db-tier:
type: Cloud.Machine
properties:
# Command to execute
abxRunScript_script: mkdir bp-dir
# Time delay in seconds before the script is run
abxRunScript_delay: 120
# Type of the script: shell (Linux) or powershell (Windows)
abxRunScript_shellType: linux
# Could be aws, azure, etc.
abxRunScript_endpointType: '${self.endpointType}'
YAMLFetching value from Property Groups
appSize: '${propgroup.propGroup_name.const_size}'
YAMLAdding a secret property
type: Cloud.Machine
properties:
name: ourvm
image: mint20
flavor: small
remoteAccess:
authentication: publicPrivateKey
sshKey: '${secret.ourPublicKey}'
username: root
YAMLEnum & oneOf (Dropdowns in Input form)
enum and oneOf both are used to provide a set of default values in the input form. However, the only difference in them is that oneOf allows for a friendly title.
inputs:
osversion:
type: string
title: Select OS Version
default: SLES12
enum:
- SLES12
- SLES15
- RHEL7
inputs:
platform:
type: string
title: Deploy to
oneOf:
# Title is what the user sees, const is the tag for the endpoints.
- title: AWS
const: aws
- title: Azure
const: azure
- title: vSphere
const: vsphere
default: vsphere
YAMLDynamic Enums (binding with vRO action)
input1:
type: string
title: Environment
default: ''
$dynamicEnum: '/data/vro-actions/com.org.utils/getEnvironment?environment={{vmenvironment}}'
.
.
.
.
input1:
type: string
title: podId
$dynamicEnum: /data/vro-actions/com.org.helpers/getPod
YAMLThis is calling a vRO action getEnvironments
inside a action module com.org.utils
with 1 input environment
. Actions with no inputs can be called with without using quotes.
vRO Custom DataTypes
inputs:
accountName:
type: string
title: Account name
encrypted: true
displayName:
type: string
title: Display name
password:
type: string
title: Password
encrypted: true
confirmPassword:
type: string
title: Password
encrypted: true
ouContainer:
type: object
title: AD OU container
$data: 'vro/data/inventory/AD:OrganizationalUnit'
properties:
id:
type: string
type:
type: string
YAMLResource Flags
Cloud Assembly includes several cloud template settings that adjust how a resource is handled at request time. Resource flag settings aren’t part of the resource object properties schema. For a given resource, you add the flag settings outside of the properties section as shown.
resources:
Cloud_Machine_1:
type: Cloud.Machine
preventDelete: true
properties:
image: coreos
flavor: small
attachedDisks:
- source: '${resource.Cloud_Volume_1.id}'
Cloud_Volume_1:
type: Cloud.Volume
properties:
capacityGb: 1
YAMLAvailable resource flags
Resource Flag | Description |
---|---|
allocatePerInstance | When set to true, resource allocation can be customized for each machine in a cluster.The default is false, which allocates resources equally across the cluster, resulting in the same configuration for each machine. In addition, day 2 actions might not be separately possible for individual resources.Per instance allocation allows count.index to correctly apply the configuration for individual machines. For code examples, see Machine and disk clusters in Cloud Assembly. |
createBeforeDelete | Some update actions require that the existing resource be removed and a new one be created. By default, removal is first, which can lead to conditions where the old resource is gone but the new one wasn’t created successfully for some reason.Set this flag to true if you need to make sure that the new resource is successfully created before deleting the previous one. |
createTimeout | The Cloud Assembly default timeout for resource allocate, create, and plan requests is 2 hours (2h). In addition, a project administrator can set a custom default timeout for these requests, applicable throughout the project.This flag lets you override any defaults and set the individual timeout for a specific resource operation. See also updateTimeout and deleteTimeout. |
deleteTimeout | The Cloud Assembly default timeout for delete requests is 2 hours (2h). In addition, a project administrator can set a different default timeout for delete requests, applicable throughout the project.This flag lets you override any defaults and set the individual timeout for a specific resource delete operation. See also updateTimeout and createTimeout. |
dependsOn | This flag identifies an explicit dependency between resources, where one resource must exist before creating the next one. For more information, see Creating bindings and dependencies between resources in Cloud Assembly. |
dependsOnPreviousInstances | When set to true, create cluster resources sequentially. The default is false, which simultaneously creates all resources in a cluster.For example, sequential creation is useful for database clusters where primary and secondary nodes must be created, but secondary node creation needs configuration settings that connect the node to an existing, primary node. |
forceRecreate | Not all update actions require that the existing resource be removed and a new one be created. If you want an update to remove the old resource and create a new one, independent of whether the update would have done so by default, set this flag to true. |
ignoreChanges | Users of a resource might reconfigure it, changing the resource from its deployed state.If you want to perform a deployment update but not overwrite the changed resource with the configuration from the cloud template, set this flag to true. |
ignorePropertiesOnUpdate | Users of a resource might customize certain properties, and those properties might be reset to their original cloud template state during an update action.To prevent any properties from being reset by an update action, set this flag to true. |
preventDelete | If you need to protect a created resource from accidental deletion during updates, set this flag to true. If a user deletes the deployment, however, the resource is deleted. |
recreatePropertiesOnUpdate | Users of a resource might reconfigure properties, changing the resource from its deployed state. During an update, a resource might or might not be recreated. Resources that aren’t recreated might remain with properties in changed states.If you want a resource and its properties to be recreated, independent of whether the update would have done so by default, set this flag to true. |
updateTimeout | The Cloud Assembly default timeout for update requests is 2 hours (2h). In addition, a project administrator can set a different default timeout for update requests, applicable throughout the project.This flag lets you override any defaults and set the individual timeout for a specific resource update operation. See also deleteTimeout and createTimeout. |
cloudConfig (cloud-init & Cloudbase-Init)
You can add a cloudConfig section to Cloud Assembly template code, in which you add machine initialization commands that run at deployment time. cloudConfig command formats are:
- Linux—initialization commands follow the open cloud-init standard.
- Windows—initialization commands use Cloudbase-init.
Linux cloud-init and Windows Cloudbase-init don’t share the same syntax. A cloudConfig section for one operating system won’t work in a machine image of the other operating system.
To ensure correct interpretation of commands, always include the pipe character cloudConfig: |
as shown. Learn more about cloud-config here.
cloudConfig: |
#cloud-config
repo_update: true
repo_upgrade: all
packages:
- apache2
- php
- php-mysql
- libapache2-mod-php
- php-mcrypt
- mysql-client
runcmd:
- mkdir -p /var/www/html/mywordpresssite && cd /var/www/html && wget https://wordpress.org/latest.tar.gz && tar -xzf /var/www/html/latest.tar.gz -C /var/www/html/mywordpresssite --strip-components 1
- i=0; while [ $i -le 5 ]; do mysql --connect-timeout=3 -h ${DBTier.networks[0].address} -u root -pmysqlpassword -e "SHOW STATUS;" && break || sleep 15; i=$((i+1)); done
- mysql -u root -pmysqlpassword -h ${DBTier.networks[0].address} -e "create database wordpress_blog;"
- mv /var/www/html/mywordpresssite/wp-config-sample.php /var/www/html/mywordpresssite/wp-config.php
- sed -i -e s/"define( 'DB_NAME', 'database_name_here' );"/"define( 'DB_NAME', 'wordpress_blog' );"/ /var/www/html/mywordpresssite/wp-config.php && sed -i -e s/"define( 'DB_USER', 'username_here' );"/"define( 'DB_USER', 'root' );"/ /var/www/html/mywordpresssite/wp-config.php && sed -i -e s/"define( 'DB_PASSWORD', 'password_here' );"/"define( 'DB_PASSWORD', 'mysqlpassword' );"/ /var/www/html/mywordpresssite/wp-config.php && sed -i -e s/"define( 'DB_HOST', 'localhost' );"/"define( 'DB_HOST', '${DBTier.networks[0].address}' );"/ /var/www/html/mywordpresssite/wp-config.php
- service apache2 reload
YAMLIf a cloud-init script behaves unexpectedly, check the captured console output in /var/log/cloud-init-output.log
when troubleshooting. For more about cloud-init, see the cloud-init documentation.
Examples of vSphere resources
vSphere virtual machine with CPU, memory, and operating system
resources:
demo-machine:
type: Cloud.vSphere.Machine
properties:
name: demo-machine
cpuCount: 1
totalMemoryMB: 1024
image: ubuntu
YAMLvSphere machine with a datastore resource
resources:
demo-vsphere-disk-001:
type: Cloud.vSphere.Disk
properties:
name: DISK_001
type: 'HDD'
capacityGb: 10
dataStore: 'datastore-01'
provisioningType: thick
YAMLvSphere machine with an attached disk
resources:
demo-vsphere-disk-001:
type: Cloud.vSphere.Disk
properties:
name: DISK_001
type: HDD
capacityGb: 10
dataStore: 'datastore-01'
provisioningType: thin
demo-machine:
type: Cloud.vSphere.Machine
properties:
name: demo-machine
cpuCount: 2
totalMemoryMB: 2048
imageRef: >-
https://packages.vmware.com/photon/4.0/Rev1/ova/photon-ova-4.0-ca7c9e9330.ova
attachedDisks:
- source: '${demo-vsphere-disk-001.id}'
YAMLvSphere machine with a dynamic number of disks
inputs:
disks:
type: array
title: disks
items:
title: disks
type: integer
maxItems: 15
resources:
Cloud_Machine_1:
type: Cloud.vSphere.Machine
properties:
image: Centos
flavor: small
attachedDisks: '${map_to_object(resource.Cloud_Volume_1[*].id, "source")}'
Cloud_Volume_1:
type: Cloud.Volume
allocatePerInstance: true
properties:
capacityGb: '${input.disks[count.index]}'
count: '${length(input.disks)}'
YAMLvSphere machine from a snapshot image. Append a forward slash and the snapshot name. The snapshot image can be a linked clone.
resources:
demo-machine:
type: Cloud.vSphere.Machine
properties:
imageRef: 'demo-machine/snapshot-01'
cpuCount: 1
totalMemoryMB: 1024
YAMLvSphere machine in a specific folder in vCenter
resources:
demo-machine:
type: Cloud.vSphere.Machine
properties:
name: demo-machine
cpuCount: 2
totalMemoryMB: 1024
imageRef: ubuntu
resourceGroupName: 'myFolder'
YAMLvSphere machine with multiple NICs
resources:
demo-machine:
type: Cloud.vSphere.Machine
properties:
image: ubuntu
flavor: small
networks:
- network: '${network-01.name}'
deviceIndex: 0
- network: '${network-02.name}'
deviceIndex: 1
network-01:
type: Cloud.vSphere.Network
properties:
name: network-01
network-02:
type: Cloud.vSphere.Network
properties:
name: network-02
YAMLvSphere machine with an attached tag in vCenter
resources:
demo-machine:
type: Cloud.vSphere.Machine
properties:
flavor: small
image: ubuntu
tags:
- key: env
value: demo
YAMLvSphere machine with a customization spec
resources:
demo-machine:
type: Cloud.vSphere.Machine
properties:
name: demo-machine
image: ubuntu
flavor: small
customizationSpec: Linux
YAMLvSphere machine with remote access
inputs:
username:
type: string
title: Username
description: Username
default: testUser
password:
type: string
title: Password
default: VMware@123
encrypted: true
description: Password for the given username
resources:
demo-machine:
type: Cloud.vSphere.Machine
properties:
flavor: small
imageRef: >-
https://cloud-images.ubuntu.com/releases/16.04/release-20170307/ubuntu-16.04-server-cloudimg-amd64.ova
cloudConfig: |
ssh_pwauth: yes
chpasswd:
list: |
${input.username}:${input.password}
expire: false
users:
- default
- name: ${input.username}
lock_passwd: false
sudo: ['ALL=(ALL) NOPASSWD:ALL']
groups: [wheel, sudo, admin]
shell: '/bin/bash'
runcmd:
- echo "Defaults:${input.username} !requiretty" >> /etc/sudoers.d/${input.username}
YAMLMarket Place
The Marketplace provides VMware Solution Exchange cloud templates and images that help you build your template library and access supporting OVA or OVFs.

Other ways to create Cloud Assembly templates
Cloud template cloning
To clone a template, go to Design, select a source, and click Clone. You clone a cloud template to create a copy based on the source, then assign the clone to a new project or use it as starter code for a new application.
Uploading and downloading
You can upload, download, and share cloud template YAML code in any way that makes sense for your site. You can even modify template code using external editors and development environments.
Note A good way to validate shared template code is to inspect it in the Cloud Assembly code editor on the design page.
Integrating Cloud Assembly with a repository
An integrated git source control repository can make cloud templates available to qualified users as the basis for a new deployment. See How do I use Git integration in Cloud Assembly.
References
- Samples by Oleg Burdaev: https://gitlab.com/vra8/bp
- More Samples by Cody De Arkland: https://gitlab.com/codydearkland/cas-blueprints
Leave a Reply