Tuono Concepts Overview – Blueprints, Versioning, and Variables

Blueprints: Blue… What Now?

Tuono Blueprints are YAML files that contain the abstract definitions for the infrastructure objects that comprise an application. You can think of Blueprints as the “what”. These infrastructure objects encompass all of the infrastructure that you need to instantiate your application. These objects include:

  • Simple Objects
    • A network definition
    • A security group definition
    • A virtual machine definition
    • etc.
  • Complex Objects
    • A complete virtual machine and image definition
    • A complete load-balancer definition
    • etc.
  • Logical Objects
    • A datacenter location definition
    • A folder structure definition

You can encompass all objects in a single Blueprint, or you can take a more modular approach, creating several more focused Blueprints that should be used in combination. However you design your Blueprints, the focus should be on reusability. With good design principles, it becomes possible to reuse the same Blueprint for a variety of applications. Blueprints can be thought of in the same way as you might think of a template.

Versioning

Blueprints in Tuono support versioning. If for any reason you need to return to an older version of a Blueprint, the Blueprint history is retained in the portal and you can revert back to an older version, as needed. This reverted version can either be used directly, or it can be a base for further changes which you can subsequently save.

Again, this saved version is given a discrete version number and it becomes its own independent version. When manipulating blueprints, it is also possible to compare the current version of the blueprint, with any other version. When you compare two blueprints, you are presented with a side by side diff, so that you can quickly see any differences between the versions.

Tuono Blueprints Versioning

Whether you are editing the current version, or reverting to an older version, the existing Environments that use this blueprint are not automatically updated. This allows each Environment to be managed independently. It also allows for separation of control so that one person could have access to edit and test a Blueprint, but someone else might have the right to manage and update the Environment.

Variables

With reusability in mind, Tuono supports the use of variables in Blueprints. Any value can be variablised, and this can dramatically increase the reusability of Blueprints. Variables may be something simple like the number of cores or amount of memory. Alternatively, they could be something organizational, for example, a string that is used as part of the naming scheme and leveraged throughout the blueprint. The four basic types are:

  • Integer values
  • String values
  • Arithmetic expressions
  • Secrets

NOTE: If you use multiple Blueprints, the variables must be defined in the same Blueprint that they are referenced in.

Integer Values

Integer values are typically used when defining the number of something, be that the number of cores, quantity of memory, number of instances, etc. A description is not a required field, but it is recommended. This can be displayed in the portal to help the end-user understand what is being requested. Optionally, variables can include a default value. If a value is not explicitly supplied, the default is used.

variables:
  ...
  cpu_core_count:
    description: The core count for the virtual machine.
    type: integer
    default: 1
  memory_in_gb:
    description: The memory size for the virtual machine.
    type: integer    
    default: 2
  number_of_vms
    description: The number of required VMs.
    type: integer
  ...

These in turn can be instantiated like this:

compute:
  vm:
    example:
      count: (( number_of_vms ))
      cores: (( cpu_core_count ))
      memory: ((  memory_in_gb )) GB
      ...

String Values

String values can be used to define any alphanumeric value that may need to be referenced in the blueprint. This may be an arbitrary value used as, for example, an identifier, or it may be something more prescribed, such as an SSH public key. Within the definition, it is possible to define acceptable characters, where this is required, for example, only lowercase alpha characters (“a-z”) or upper and lowercase alphanumeric characters (“a-zA-Z0-9”). As with integer values, these can optionally include a description and a default.

variables:
  ...
  naming_scheme
    description: The naming scheme to be used in the Blueprint
    type: string
    regex: "a-z"
  admin_username:
    description: The username for the administrative user.
    type: string
    default: adminuser
  admin_public_key:
    description: The OpenSSH Public Key to use for administrative access.
    type: string
  ...

There are instantiated like this:

compute:
  vm:
      ...
      configure:
        admin:
          username: (( admin_username ))
          public_key: (( admin_public_key ))
      ...
      disks:
        data:
          size: 128 GB
          tags:
            my_custom_tag: (( naming_scheme ))

Arithmetic Expressions

As mentioned above, using variables it is also possible to define algorithmic expressions within Blueprints. These variables, rather than being defined from the outset, are instantiated directly within the Blueprint. These are similar to lambda functions in a programming language like Python. If this does not make sense, don’t worry about it at all! It’s not important in the understanding of how to use arithmetic expressions!

storage:
  disk:
    records:
      count: 3
      ...
      zone: (( ((count - 1) % 3) + 1 ))

Arithmetic expressions support all standard modifiers:

  • Add (+)
  • Subtract (-)
  • Multiply (*)
  • Divide (/)
  • Modulus (%)

What follows is a quick explanation of this. A detailed understanding is not critical, and learning this by rote is an entirely acceptable answer here!

  • ((1 – 1) % 3) + 1 = 1
  • ((2 – 1) % 3) + 1 = 2
  • ((3 – 1) % 3) + 1 = 3

And for counts > 3 (not represented in the example)

  • ((4 – 1) % 3) + 1 = 1
  • ((5 – 1) % 3) + 1 = 2
  • ((6 – 1) % 3) + 1 = 3

Modulus (%) refers to what is left of the 1st number after being divided by the modulus (3 in this case). NOTE: 0 (zero) is a valid division, so 2 divided by 3 = 0, with 2 remaining, for example. The -1/+1 is a device to make sure that we start counting at 1, not 0 when doing this operations, as that is how zones are defined within the venue(s).

TL;DR: Through a quirk of modulus, as it iterates over the count, the leading 1, 2 and 3 refer exactly to the end result where it equates to less than count and as it equates to greater than count, that pattern repeats. For example:

  • 5 – 1 = 4
  • 4 / 3 = 1, with a remainder of 1
  • 1 + 1 = 2

Are you are interested in having a play around with Blueprints yourself? Sign up for our free Community Edition and give it a try!

Deploy your first environment