Dr. Pranay Jha

VMware • Cloud • AI • Enterprise Architecture

FORMERLY
VMware Insight & Cloud Pathshala
What began over a decade ago as a passion for sharing knowledge has evolved into a unified platform for Enterprise AI, VMware, Cloud Architecture, Research, and Modern Infrastructure.
, ,

Writing VMware Cloud Templates in VCF Automation: Inputs, Resources and the YAML (VCF Automation 9 Series, Part 12)

A VMware Cloud Template is a few dozen lines of YAML that become a running, networked, governed deployment. The structure, inputs that build the form, resources, and the canvas-plus-code workflow.

VCF Automation 9 Series · Part 12 of 41

TL;DR · Key Takeaways

  • A VMware Cloud Template is a YAML blueprint with three core sections: formatVersion, inputs, and resources.
  • Inputs build the request form a user sees, and they are your first line of governance. Constrain them with enums and ranges.
  • Resources declare the machines, networks, and storage to build, referencing the flavor, image, and network names from Part 11.
  • You author two ways at once: a visual design canvas and a code editor, kept in sync, so you can drag or type.
  • Templates are infrastructure as code. Version them in Git, then publish to the catalog. The YAML is the source of truth.
Who this is for: template authors and platform engineers building deployable blueprints.  Prerequisites: mappings and profiles from Part 11, because templates reference their names.

Everything in this series so far has been scaffolding for one file. A VMware Cloud Template is where it pays off: a few dozen lines of YAML that become a running, networked, governed deployment. The provider, the tenants, the projects, the zones, the mappings, all of it exists so that this file can be short. Learn to write one well and the platform finally does what it promised, which is to turn a request into infrastructure without a ticket in sight.

The anatomy of a template

A cloud template has three sections that matter. The top declares formatVersion and a name, the boilerplate that identifies the template. The inputs section defines what the user is asked when they request it, which becomes the form in the catalog. The resources section declares what gets built, referencing the flavor, image, and network names you set up as mappings and profiles. That is the whole shape: identify, ask, build.

SectionWhat it doesBecomes
formatVersion + nameIdentifies and versions the templateThe blueprint’s identity
inputsDeclares what to ask the requesterThe catalog request form
resourcesDeclares the machines, networks, storageThe deployment
Three sections, one file formatVersion + nameidentity inputswhat to ask resourceswhat to build Catalog formthe user fills it Deploymentreal machines
Inputs become the form a user fills; resources become the machines that get built. The YAML holds both.

A real template, top to bottom

Here is a complete, small template that asks for a size and an environment, then builds a machine on an on-demand network. Notice how little is hard-coded: the flavor and image are names that the region’s mappings resolve, and the inputs carry constraints so the form cannot be used to request something silly.

formatVersion: 1
name: linux-app-server
inputs:
  size:
    type: string
    title: Machine size
    enum: [small, medium, large]     # constrains the form
    default: small
  hostname:
    type: string
    title: Hostname
    pattern: '^[a-z][a-z0-9-]{2,30}$' # validation, not trust
resources:
  app_net:
    type: Cloud.Network
    properties:
      networkType: outbound          # on-demand, built by the network profile
  app_vm:
    type: Cloud.vSphere.Machine
    properties:
      flavor:  '${input.size}'       # resolved by the flavor mapping
      image:   ubuntu                # resolved by the image mapping
      name:    '${input.hostname}'
      networks:
        - network: '${resource.app_net.id}'

Two things are doing quiet work here. The ${input.x} and ${resource.x.id} bindings wire the form to the build and the resources to each other, so the machine attaches to the very network this template created. And the enum and pattern on the inputs are governance: a user cannot request a size you did not bless or a hostname that breaks your naming, because the form will not let them. Constraints in the template beat policy documents nobody reads.

Inputs are your first governance

It is worth dwelling on inputs, because authors underuse them. Every input is both a question and a guardrail. An enum restricts choice to known-good values. A pattern validates format. A default makes the common case one click. Inputs can also be conditional, shown or required only when another input has a certain value, so the form stays simple until complexity is actually needed. The more intent you push into well-constrained inputs, the less you rely on approvals and clean-up later. A loose input is a support ticket waiting to happen.

inputs:
  environment:
    type: string
    enum: [dev, prod]
    default: dev
  data_disk_gb:
    type: integer
    title: Data disk size (GB)
    minimum: 10
    maximum: 500          # a hard ceiling on what anyone can request
    default: 50
# An input with a min, a max and a default is a guardrail and a convenience
# at the same time. Most governance problems are an unconstrained input.

Canvas and code, the same template

You do not have to choose between clicking and coding. VCF Automation gives you a visual design canvas and a code editor for the same template, kept in sync: drag a machine onto the canvas and the YAML appears; edit the YAML and the canvas updates. The canvas is good for sketching a shape and for people newer to the syntax; the code editor is where you do the precise work, the bindings, the constraints, the conditionals. Treat the YAML as the source of truth, because it is what you version and review, and use the canvas as a fast way to see and shape it.

Two views, one source Design canvasdrag and drop, see the shape kept in sync Code editor (YAML)source of truth, version it
Canvas to sketch, code to finish. The YAML is what you commit to Git and publish to the catalog.
In practice: templates are infrastructure as code, so treat them like code. Keep them in Git, on GitHub, GitLab, or Bitbucket, review changes in pull requests, and publish to the catalog from a known version. A template edited live in the UI with no version history is a production change with no undo.

Worked example

A single linux-app-server template with three inputs, size, hostname, and environment, can serve a whole organization. The size enum caps what anyone provisions, the hostname pattern enforces naming, and the environment input drives a constraint that lands dev requests on dev capacity and prod on prod. One file, maybe forty lines, replaces a request form, a provisioning runbook, and a naming policy, and because it references mapping names rather than real resources, the same forty lines deploy in every region you support. That is the leverage this layer gives you: the more correct the template, the less everything downstream has to do.

Composing bigger systems

One machine is the hello-world of cloud templates. Real systems are several resources that depend on each other, and the same file describes them all. A template can declare a web tier, an app tier, a database, and the network that joins them, and deploy the whole thing as one unit. The bindings you already saw, where a machine references a network’s id, are also how you express dependencies: because the app VM references the database’s address, the platform knows to build the database first. You rarely write explicit ordering. You write the references, and the dependency graph falls out of them.

One template, many resources web app database app references db, so db builds first shared on-demand network One deploymentbuilt and destroyed together
Resources reference each other, and the platform orders the build from those references. No manual sequencing.

The judgment call is how much to put in one template. Keep a tightly coupled system, an app and its private network, in one template so it deploys and tears down as a unit. Split things that have independent lifecycles, a shared database that outlives the apps using it, into their own template or an existing resource, so destroying one app does not take the database with it. The mistake is the mega-template that builds an entire environment in one file: it is impressive in a demo and miserable to change, because every edit risks everything. Small templates that compose beat one template that does everything, and they are far easier to review.

Gotcha

Bindings that point two resources at each other create a circular dependency the platform cannot order, and the deploy fails before it starts. If a template will not deploy and the error mentions dependencies, look for two resources that each reference the other, and break the loop by giving one of them a static value or an input instead of a reference. Most ordering failures are a cycle you can see once you go looking for it.

Iteration is where versioning earns its keep. A template in Git with a version is one you can change safely: edit, review, publish a new version, and roll back if it misbehaves, all without disturbing the deployments already running on the old version. A template edited live in the UI has none of that safety. Treat each published version as a release, and the catalog as something that consumes releases rather than works in progress. That discipline is what lets you improve a template that hundreds of deployments depend on without holding your breath each time.

Versioning and testing templates like code

Release discipline

A cloud template you are still editing is invisible to the catalog, because only released versions are published. That is a feature, not a nuisance: it means the version a tenant deploys is a deliberate, frozen artifact. The discipline that follows is to treat each release like a code release, with a version string that means something and a note on what changed, so that when a deployment behaves oddly you can tell which released version produced it. Editing in place and forgetting to release is the reason a fixed template keeps deploying the old, broken build.

Test before you publish

Validation in the editor proves the template parses, not that it deploys. Run an actual deployment of a new version in a non-production project before you release it to tenants, ideally in every region it claims to support, because the failures that matter, a missing image, an unmatched profile, a bad input default, only appear at provision time. A template that validates and fails to deploy is worse than one that fails to validate, because it fails in front of a user.

Inputs are guardrails, not just fields

Every input is a chance to constrain what a user can ask for. Replace free-form fields with enumerations, set sane defaults, and bound numeric ranges, so the template itself prevents the absurd request rather than relying on a policy to catch it later. An input that offers three sensible sizes is governance; an input that accepts any number is a support ticket waiting to happen.

Worked example · A safe input design

A workstation template exposes size as an enumeration of small, medium and large with small as the default, region as a constrained choice, and disk as a bounded range rather than an open field. A user cannot request a 40-terabyte volume or an unknown size, because the template does not let them. The same item with free-form inputs would lean entirely on downstream policy and human review. Push the guardrails into the inputs and most bad requests become impossible rather than merely discouraged.


My Take

The template is the smallest, highest-leverage artifact in the whole platform, so invest in writing it well. My recommendation: keep templates small and composable rather than building one giant blueprint that does everything; push governance into constrained inputs instead of trusting requesters; reference mapping and profile names, never real resources, so a template stays portable across regions; and treat the YAML as code, versioned in Git and reviewed, with the canvas as a sketchpad rather than the system of record. Do that and a template becomes a durable asset that outlives the person who wrote it. The reward for getting these forty lines right is that the next thousand deployments need no attention at all.

Next we take this template and put it in front of users: tags and tag-based placement, then the Service Broker catalog. For the names this template resolves, revisit Part 11 on mappings and profiles. How big do your templates get before you split them? Tell me in the comments.

VCF Automation 9 Series · Part 12 of 41
« Previous: Part 11  |  VCF Automation Guide  |  Next: Part 13 »

References

About The Author


Discover more from Dr. Pranay Jha

Subscribe to get the latest posts sent to your email.

Leave a Reply

Your email address will not be published. Required fields are marked *

Architect’s Toolkit

About the Author

Dr. Pranay Jha is a Cloud and AI Consultant with 18+ years of experience in hybrid cloud, virtualization, and enterprise infrastructure transformation. He specializes in VMware technologies, multi-cloud strategy, and Generative AI solutions. He holds a PhD in Computer Applications with research focused on Cloud and AI, has published multiple research papers, and has been a VMware vExpert since 2016 and a VMUG Community Leader.

VCF Automation 9 Series

Discover more from Dr. Pranay Jha

Subscribe now to keep reading and get access to the full archive.

Continue reading