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.
, ,

Custom Resources and Resource Actions in VCF Automation: Day-2 Operations That Stay Honest (VCF Automation 9 Series, Part 23)

How to model external objects as custom resources in VCF Automation 9 and wire day-2 resource actions through VCF Operations Orchestrator, including the read-workflow trap that makes deployments lie about their own state.

VCF Automation 9 Series · Part 23 of 41
TL;DR · Key Takeaways
  • 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.
Who this is for: platform and cloud admins, automation engineers and architects who run VCF Automation and want catalog items that provision more than VMs.
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.

Custom resource lifecycleCreate and Destroy are obvious. Read and Day-2 are where designs fail.1Createworkflow buildsthe object2Readperiodic reconcilerefreshes state3Destroyworkflow removesthe object+Day-2optional actionson the resourceCreate + Destroy alone gives you a resource that provisions and de-provisions but never tells the truth between those two events.Read closes the loop. Day-2 actions let consumers change the object without re-deploying.
The four operations behind every custom resource. Skipping Read is the most common regression.

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.

ApproachOrg typeBackingRead behaviorWhen I pick it
New schemaAll Apps (external vRO)Create / Read / Destroy workflowsPeriodic read workflow you buildVCF 9 greenfield on All Apps
Dynamic typesVM AppsOrchestrator dynamic types pluginInventory refresh from the typeMigrated vRA / Aria 8.x content
ABX-backedEitherABX actions (function as a service)Action returns current stateLight glue, no vRO dependency
In practice: during brownfield migrations I leave existing dynamic-types resources alone in VM Apps rather than rebuilding them on the new schema. The new schema is cleaner, but a rebuild means re-testing every CRUD path and every day-2 action. I only move a resource when I am redesigning it anyway, or when the tenant is born on All Apps.

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.

  1. Build the create, read and destroy workflows in Orchestrator first. Test them standalone before VCF Automation ever sees them.
  2. In VCF Automation go to Build & Deploy > Blueprint Design > Custom Resources and create a new resource.
  3. 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.
  4. Attach the create workflow, then the read and destroy workflows, and map their inputs and outputs to the resource properties.
  5. 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.

From definition to deploymentThe custom resource becomes a normal blueprint component once defined.Customresource defBlueprintcomponentCatalog itemin BrokerDeploymentwith day-2Backing workflows live in VCF Operations Orchestrator. The blueprint only references the resource type.
Once defined, a custom resource flows through the same path as a VM: blueprint, catalog, deployment.

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.

Gotcha
A custom resource with create and destroy but no read will provision, show whatever create returned, and then never change. It looks finished. It passes a demo. In production it silently drifts. Always build read, and document the reconcile interval so operators do not chase phantom mismatches.

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.

Day-2 action request flowThe action only appears if a day-2 policy permits it.ConsumerService BrokerDay-2 policygate + tagsOrchestratoraction workflowExternalsystemRead workflow refreshdeployment property updated on next cyclethenBindings inject deployment id, resource id and project into the workflow so the consumer form stays short.
A day-2 action passes through the policy gate, runs a workflow, and the read cycle reflects the change.

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.

ControlWhere it livesQuestion it answers
Day-2 action policyOrg policies (All Apps)Who may run which action
Action condition / tagCustom resource definitionWhere the action appears
BindingAction / request formWhat context the workflow gets
Worked example
One tenant, three projects, a DBaaS custom resource. The create workflow provisions a database on Data Services Manager; the read workflow reconciles size and status every 10 minutes; destroy tears it down. You expose two day-2 actions: resize and delete. The day-2 action policy lets project admins in all three projects run resize, but limits delete to the platform team. A tag condition hides delete on any deployment tagged 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.

Which backing do I pick?Stateful CRUD?Orchestratorplug-ins, scheduling, read loopABX actionstateless glue, quick API callyesno
A blunt decision: state and a read loop push you to Orchestrator; thin glue belongs in ABX.
Disclaimer
Custom resources change real objects in real systems. Build and test every workflow in a non-production org first, confirm destroy removes exactly one object, and rehearse the failure paths before you publish the catalog item. A broken destroy workflow leaves orphans that someone has to clean up by hand.

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.

VCF Automation 9 Series · Part 23 of 41
« Previous: Part 22  |  VCF Automation Guide  |  Next: Part 24 »

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