- A custom resource brings an object VCF Automation does not natively manage (DNS record, IPAM lease, database, config item) under the same deployment, catalog and day-2 model as a VM.
- VCF Automation 9 adds a new schema for custom resources in All Apps organizations. It needs three workflows: create, read and destroy. VM Apps still uses Orchestrator dynamic types.
- The read workflow is the part teams skip. Without it the deployment shows stale state and there is no event-driven update, only a periodic reconcile.
- A resource action is a day-2 operation a consumer runs on a provisioned resource. It calls an Orchestrator workflow, uses bindings to pass deployment context, and only appears if a day-2 action policy permits it.
- My rule: use Orchestrator for stateful CRUD, ABX for stateless glue, and build the read workflow before you ship the create.
Prerequisites: a working VCF Automation 9.x instance, a reachable VCF Operations Orchestrator (embedded for VM Apps, external for All Apps), provider or org admin rights, and comfort with VMware Cloud Templates and Orchestrator workflows.
A custom resource that provisions cleanly and then quietly lies to you is worse than one that fails. You build a Custom.linkmanager type, drop it on a blueprint, deploy it, and the deployment goes green. Someone changes the backing object outside VCF Automation. The deployment keeps reporting the old value for the better part of twenty minutes, because there is no read workflow behind the resource. That gap is the whole story of custom resources in VCF Automation 9. The platform will let you model almost anything. It only stays honest if you build all the operations, not just the two that feel obvious.
What a custom resource actually is
VCF Automation provisions VMs, networks, load balancers and storage out of the box. Everything else is a custom resource. It is the mechanism that takes an object the platform does not understand, binds it to a set of Orchestrator workflows (or ABX actions), and from then on treats it like a first-class component: it appears in the blueprint designer, it lives inside a deployment, it carries properties, and it can expose day-2 actions. DNS records, IPAM leases, databases on Data Services Manager, ServiceNow tickets, entitlements in some external API. If you can drive it from a workflow, you can model it.
Three terms people mix up
The custom resource is the definition that maps a resource type to its create, read and destroy workflows. The resource type is the internal name, always starting with custom., that you reference as type in the blueprint YAML. The resource action is the day-2 operation a consumer runs against an already-provisioned resource, like change, resize or restart. One definition, one type, zero or many actions. Keep them separate in your head or the policy model later will confuse you.
New schema (All Apps) vs dynamic types (VM Apps)
This is the first decision and it is dictated by your organization type. VCF Automation 9 introduced a new schema for custom resources that drops the dependency on the Orchestrator dynamic types plugin. You define the resource directly, point it at three workflows, and you are done. No type hierarchy, no inventory plumbing. The catch: the new schema is only available in an All Apps organization, and it requires an external Orchestrator. A VM Apps organization, which is the closer cousin of Aria Automation 8.x, still uses the dynamic types approach you may remember from vRA.
The practical difference is the read path. Dynamic types had an inventory model that the platform refreshed from the type itself. The new schema has no automated external process that updates the resource, so you must supply a read workflow that runs on a schedule and pulls current state back into the deployment. More on that trap below.
| Approach | Org type | Backing | Read behavior | When I pick it |
|---|---|---|---|---|
| New schema | All Apps (external vRO) | Create / Read / Destroy workflows | Periodic read workflow you build | VCF 9 greenfield on All Apps |
| Dynamic types | VM Apps | Orchestrator dynamic types plugin | Inventory refresh from the type | Migrated vRA / Aria 8.x content |
| ABX-backed | Either | ABX actions (function as a service) | Action returns current state | Light glue, no vRO dependency |
Building a custom resource, step by step
The walkthrough below uses a simple link-management resource that stores name and URL pairs in an Orchestrator configuration element. It is deliberately trivial so the mechanics are visible. Swap the workflows for IPAM or DBaaS calls and the shape is identical.
- Build the create, read and destroy workflows in Orchestrator first. Test them standalone before VCF Automation ever sees them.
- In VCF Automation go to Build & Deploy > Blueprint Design > Custom Resources and create a new resource.
- Set a Name (how it shows in the designer), a Resource Type starting with
custom., enable Make custom resource available in blueprints, and select Create new schema. - Attach the create workflow, then the read and destroy workflows, and map their inputs and outputs to the resource properties.
- Add any additional actions (day-2) and reference their workflows. Save.
One mapping detail that bites people: the destroy and read workflows need to know which object they are acting on. Map the input to the property that uniquely identifies the resource, for example the link name, not an arbitrary property that may not be set. Get this wrong and destroy either fails or, worse, removes the wrong object.
The blueprint references the type and feeds it inputs. This is the same VMware Cloud Template YAML covered in Part 12, just pointing at a custom type:
formatVersion: 1
inputs:
link-name:
type: string
title: Link Name
link-url:
type: string
title: Link URL
resources:
Custom_linkmanager_1:
type: Custom.linkmanager
properties:
LinkName: ${input.link-name}
LinkUrl: ${input.link-url}
The create workflow is a normal Orchestrator action. It does the real work and returns the object the read and destroy workflows will key on. A minimal version:
// VCF Operations Orchestrator action: createLink
// inputs: linkName (string), linkUrl (string)
var cfg = Server.getConfigurationElementWithPath(
'Links Management', 'CustomResources');
cfg.setAttributeWithKey(linkName, linkUrl);
// the object VCF Automation stores as the resource state
return {
id: linkName,
LinkName: linkName,
CurrentUrl: linkUrl
};
Expected result: the deployment shows a resource with CurrentUrl set. Failure mode: if the action throws or returns no id, the deployment fails the resource and you get an orphaned object in the backing system. Make create idempotent or clean up on failure.
The read workflow trap
Here is the part the docs underplay. With the new schema there is no event-driven update of resource state. If the backing object changes outside VCF Automation, the deployment does not know until the read workflow runs again, and the read workflow runs on a periodic cycle, not on demand. In my own testing of a link resource the refresh took roughly eighteen minutes to land after I changed the value manually. That is not a bug. It is the design. The read workflow is your only reconciliation path, so treat it as a first-class deliverable, not an afterthought.
The implication for operations is concrete. If a consumer changes the object through a path that bypasses VCF Automation, the deployment view is wrong for the length of the reconcile interval. For a cosmetic property nobody cares. For something a downstream automation reads, like an IP address or a connection string, a stale value can drive a bad decision. Decide up front whether the property must be authoritative in real time. If it must, a custom resource with a slow read may be the wrong model, and a direct API call at consumption time may serve better.
Resource actions: wiring a day-2 operation
A resource action is an extra operation you let a consumer run against a provisioned resource. Change a value, resize a database, rotate a credential, vMotion a VM. In the custom resource definition you add an additional action and point it at an Orchestrator workflow. Optionally you attach a condition so the action only shows in certain situations. Broadcom ships a worked example of building a resource action to vMotion a virtual machine, which is the canonical pattern for a custom day-2 on a native resource.
The piece that makes a day-2 action usable is bindings. A binding maps deployment and resource context, the deployment id, the resource id, the project, into the workflow inputs so the system supplies them and the consumer does not retype them. VCF Automation supports several binding types for day-2 actions so the request form stays short and the workflow still gets everything it needs.
You can also drive a day-2 action from the VCF Automation API, which is how you script bulk changes. The request posts an action id against a resource inside a deployment:
curl -k -X POST
https://vcfa.corp.local/deployment/api/deployments/$DEP/resources/$RES/requests
-H 'Authorization: Bearer '$TOKEN
-H 'Content-Type: application/json'
-d '{
"actionId": "Custom.linkmanager.changeLink",
"inputs": { "LinkUrl": "https://new.example.com" }
}'
Expected result: HTTP 202 with a request object you can poll. Failure mode: a 403 means the day-2 action policy does not permit that action for the token user, and a 400 usually means the action id is wrong or a required input is missing. The action id is not the friendly name in the UI, so pull it from a GET on the resource first.
The object-reference gotcha
In the simple build, the change action makes the consumer type the link name again because nothing tells the workflow which entry to touch. That is a poor experience and an error source. The fix is to customize the request form and bind the identifying input to an external source, for example an Orchestrator action that returns the object reference from the deployment context. Spend the time on this. A day-2 action that asks the user to re-supply the key of the thing they are already looking at will get used wrong.
Governing day-2 actions
Defining an action does not make it available. Day-2 action policies decide what each user can run, and an action a policy does not list will not appear in Service Broker. This is the same governance surface covered in Part 16, applied to your custom actions. The point of the policy is to keep consumers away from destructive or costly operations: you publish an allow-list, scope it to the right users and projects, and everything else stays hidden.
For finer control, attach a condition to the action itself so it only shows on resources that carry a given tag. Tag-based visibility is how you expose a risky action, say a force-delete, only on non-production deployments while hiding it everywhere else. Combine the two: the policy says who may act, the tag condition says where the action even appears.
| Control | Where it lives | Question it answers |
|---|---|---|
| Day-2 action policy | Org policies (All Apps) | Who may run which action |
| Action condition / tag | Custom resource definition | Where the action appears |
| Binding | Action / request form | What context the workflow gets |
env:prod. Net effect: a developer can grow their database, a project admin can resize, and nobody but the platform team can drop a production database, even by accident. Lease stays 30 days so abandoned dev databases reclaim themselves.ABX or Orchestrator for the CRUD?
Both can back a custom resource. ABX is lightweight, serverless, good for a few lines of Python or Node that hit an API and return. Orchestrator is heavier but gives you the plug-in ecosystem, the configuration elements, scheduling, error handling and the dynamic-types history. Neither is universally correct.
What I’d Do
Treat a custom resource as a contract, not a script. The contract has four clauses, create, read, destroy and any day-2 action, and the one teams break is read. Build read first or at least alongside create, and write down the reconcile interval so operators trust the deployment view. Use Orchestrator when the resource has state and needs a real read loop; use ABX for thin, stateless glue where an action returns the answer directly. Gate every day-2 action with a policy and, where the action is risky, a tag condition, so consumers see only what they should. The one place I would do it differently from a quick demo: never let a day-2 action ask the consumer to re-type the key of the resource they are acting on. Bind it. Skip the read workflow and the symptom is always the same: a day-2 action runs against a value that looks current but is stale, and the downstream automation quietly does the wrong thing. Wiring the read is what keeps the resource honest.
Building a custom resource this week? Start with the read workflow and the destroy mapping, not the create. Those are the two that decide whether the resource is honest and safe.
References
- vrealize.it – VCF Automation 9 custom resource with the new schema
- Broadcom TechDocs – Create a VCF Automation resource action to vMotion a VM
- Broadcom TechDocs – Configure Day 2 action policies in VCF Automation
- vrealize.it – Custom day-2 action visibility based on tags



