<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Vm-Service on The Nested Lab</title>
    <link>https://thenestedlab.com/tags/vm-service/</link>
    <description>Recent content in Vm-Service on The Nested Lab</description>
    <generator>Hugo</generator>
    <language>en-gb</language>
    <lastBuildDate>Thu, 01 Oct 2026 00:00:00 +0100</lastBuildDate>
    <atom:link href="https://thenestedlab.com/tags/vm-service/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Every resource in the VCF Automation 9.1 blueprint designer: the complete guide</title>
      <link>https://thenestedlab.com/posts/vcfa-blueprint-resource-reference/</link>
      <pubDate>Thu, 01 Oct 2026 00:00:00 +0100</pubDate>
      <guid>https://thenestedlab.com/posts/vcfa-blueprint-resource-reference/</guid>
      <description>A complete guide to the VCF Automation 9.1 blueprint designer: every palette item, the YAML behind it, every field the platform accepts, recipes and traps. Every snippet validated, dry-run or deployed.</description>
      <content:encoded><![CDATA[<p>The blueprint designer in a VCF Automation 9.1 All Apps organization offers
sixteen items in three groups. Drag one onto the canvas and you get a few
lines of YAML. What you may write underneath them is spread across the VM
Service, VKS, NSX VPC and Automation guides. For some items, it&rsquo;s written
down nowhere at all.</p>
<p>This guide puts it in one place. For each item, you get:</p>
<ul>
<li>what it creates, and the YAML behind it;</li>
<li>every field the platform accepts;</li>
<li>a minimal snippet, and recipes for the common jobs;</li>
<li>the status fields worth reading;</li>
<li>the traps we hit.</li>
</ul>
<p>Three things make it more than a list from memory, which, given my memory,
is just as well:</p>
<ul>
<li><strong>The field lists come from the platform.</strong> VCF Automation publishes the
schema of every blueprint resource type through its API. The designer
carries the schema of every palette item. The Supervisor publishes the
definition of every Kubernetes kind it serves, and VCF Automation&rsquo;s VPC API
publishes its own. Where they disagree (and they do), the tables follow
what the platform enforces.</li>
<li><strong>Every snippet was checked.</strong> Each one went through VCF Automation&rsquo;s
validation API, and every Kubernetes manifest through a server-side dry
run on the Supervisor. Five test blueprints (all of them in the downloads)
deployed every item for real. The remaining recipes are ones our lab
catalog deploys every day.</li>
<li><strong>The traps are real.</strong> Several of the most useful lines in this guide come
from things that went wrong while testing: a NAT rule that ignored its
port, a firewall rule that grew an &ldquo;Any&rdquo;, a request that waits for an
address that can never come.</li>
</ul>
<p>We checked it on our lab platform, f06:</p>
<ul>
<li>VCF Automation 9.1.0;</li>
<li>a Supervisor on Kubernetes 1.32.9, with the VM Operator API at <code>v1alpha5</code>;</li>
<li>VKS with ClusterClasses up to <code>builtin-generic-v3.6.0</code>, and Kubernetes
releases up to 1.35.5;</li>
<li>NSX VPCs.</li>
</ul>
<p>Names in the examples (<code>f06</code>, <code>nested-pod</code>, <code>vpc-student05</code>,
<code>vsan-default-storage-policy</code>) are ours; use yours.</p>
<p>In the field tables, <strong>Values</strong> gives a field&rsquo;s choices and default. Where the
schema has neither, it gives an example, marked <em>e.g.</em>: the value from our
tested blueprints wherever one of them set the field, otherwise a typical one.
For an object or a list, the example is a short YAML flow value built from its
fields (<code>...</code> marks the ones left out). And <code>&lt;...&gt;</code> stands for a name of yours.</p>
<h2 id="the-shape-of-a-blueprint">The shape of a blueprint</h2>
<p>An All Apps blueprint is YAML with <code>formatVersion: 2</code>, its inputs, its
resources and its outputs:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">formatVersion</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">inputs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">vmName</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">VM name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">default</span><span class="p">:</span><span class="w"> </span><span class="l">web-01</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">pattern</span><span class="p">:</span><span class="w"> </span><span class="s1">&#39;^[a-z0-9]([-a-z0-9]*[a-z0-9])?$&#39;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">size</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="l">Size</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">default</span><span class="p">:</span><span class="w"> </span><span class="l">small</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">oneOf</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- {<span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="nt">Small, const</span><span class="p">:</span><span class="w"> </span><span class="l">small}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- {<span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="nt">Medium, const</span><span class="p">:</span><span class="w"> </span><span class="l">medium}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Namespace</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">team-a-dev</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">existing</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">vm1</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Resource</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">context</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.namespace.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">manifest</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">vmoperator.vmware.com/v1alpha5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">VirtualMachine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">${input.vmName}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">className</span><span class="p">:</span><span class="w"> </span><span class="l">${&#39;best-effort-&#39; + input.size}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">imageName</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-24.04-server-cloudimg-amd64</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">storageClass</span><span class="p">:</span><span class="w"> </span><span class="l">vsan-default-storage-policy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">outputs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">vmName</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.vm1.object.metadata.name}</span><span class="w">
</span></span></span></code></pre></div><p>What the expressions can read:</p>
<table>
	<thead>
			<tr>
					<th>Expression</th>
					<th>Value</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>${input.&lt;name&gt;}</code></td>
					<td>A request input. An input group from a property group is <code>${input.&lt;group&gt;.&lt;property&gt;}</code>.</td>
			</tr>
			<tr>
					<td><code>${resource.&lt;name&gt;.&lt;property&gt;}</code></td>
					<td>Another resource&rsquo;s property; this also orders the two. <code>object</code> holds the live Kubernetes object of a Supervisor Resource.</td>
			</tr>
			<tr>
					<td><code>${propgroup.&lt;group&gt;.&lt;property&gt;}</code></td>
					<td>A constant property group&rsquo;s value.</td>
			</tr>
			<tr>
					<td><code>${secret.&lt;name&gt;}</code></td>
					<td>A VCF Automation secret, from the organization or the project.</td>
			</tr>
			<tr>
					<td><code>${env.deploymentName}</code>, <code>${count.index}</code></td>
					<td>The deployment&rsquo;s name; the instance number in a counted resource.</td>
			</tr>
			<tr>
					<td><code>${to_k8s_name(env.deploymentName, 63)}</code></td>
					<td>A string made safe for a Kubernetes name, as Broadcom&rsquo;s own samples use for <code>generateName</code>.</td>
			</tr>
	</tbody>
</table>
<p>Besides <code>type</code> and <code>properties</code>, each resource has <code>dependsOn</code> (an explicit
order) and <code>allocatePerInstance</code> (see <code>count</code> below). <code>formatVersion: 2</code> also
allows <code>metadata</code>, <code>variables</code>, and an output named <code>__deploymentOverview</code>,
whose Markdown value becomes the deployment&rsquo;s overview page.</p>
<h2 id="how-the-palette-maps-to-yaml">How the palette maps to YAML</h2>
<p>Behind the sixteen items there are only five resource types, and one of them
isn&rsquo;t in the palette. Most items are a type with part of its YAML already
filled in. For the workload items, that&rsquo;s a Kubernetes <code>apiVersion</code> and
<code>kind</code>; for the VPC items, it&rsquo;s a VPC configuration <code>kind</code>.</p>
<table>
	<thead>
			<tr>
					<th>Palette item</th>
					<th>YAML <code>type</code></th>
					<th>Pre-filled</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Supervisor Namespace</td>
					<td><code>CCI.Supervisor.Namespace</code></td>
					<td></td>
			</tr>
			<tr>
					<td><strong>VPC group</strong></td>
					<td></td>
					<td></td>
			</tr>
			<tr>
					<td>VPC</td>
					<td><code>CCI.VPC</code></td>
					<td></td>
			</tr>
			<tr>
					<td>VPC Configuration</td>
					<td><code>CCI.VPC.Configuration</code></td>
					<td>nothing: you set <code>kind</code></td>
			</tr>
			<tr>
					<td>Attachment</td>
					<td><code>CCI.VPC.Configuration</code></td>
					<td><code>kind: VPCAttachment</code></td>
			</tr>
			<tr>
					<td>IP Address Allocation</td>
					<td><code>CCI.VPC.Configuration</code></td>
					<td><code>kind: VPCIPAddressAllocation</code></td>
			</tr>
			<tr>
					<td>NAT Rule</td>
					<td><code>CCI.VPC.Configuration</code></td>
					<td><code>kind: VPCNATRule</code></td>
			</tr>
			<tr>
					<td>Group</td>
					<td><code>CCI.VPC.Configuration</code></td>
					<td><code>kind: VPCNetworkSecurityGroup</code></td>
			</tr>
			<tr>
					<td>Gateway Firewall Policy</td>
					<td><code>CCI.VPC.Configuration</code></td>
					<td><code>kind: VPCGatewayFirewallPolicy</code></td>
			</tr>
			<tr>
					<td><strong>Workload group</strong></td>
					<td></td>
					<td></td>
			</tr>
			<tr>
					<td>Supervisor Resource</td>
					<td><code>CCI.Supervisor.Resource</code></td>
					<td>nothing: any manifest</td>
			</tr>
			<tr>
					<td>Virtual Machine</td>
					<td><code>CCI.Supervisor.Resource</code></td>
					<td><code>vmoperator.vmware.com/v1alpha5</code> <code>VirtualMachine</code></td>
			</tr>
			<tr>
					<td>Virtual Machine Group</td>
					<td><code>CCI.Supervisor.Resource</code></td>
					<td><code>vmoperator.vmware.com/v1alpha5</code> <code>VirtualMachineGroup</code></td>
			</tr>
			<tr>
					<td>Virtual Machine Service</td>
					<td><code>CCI.Supervisor.Resource</code></td>
					<td><code>vmoperator.vmware.com/v1alpha3</code> <code>VirtualMachineService</code></td>
			</tr>
			<tr>
					<td>Subnet</td>
					<td><code>CCI.Supervisor.Resource</code></td>
					<td><code>crd.nsx.vmware.com/v1alpha1</code> <code>Subnet</code></td>
			</tr>
			<tr>
					<td>Persistent Volume Claim</td>
					<td><code>CCI.Supervisor.Resource</code></td>
					<td><code>v1</code> <code>PersistentVolumeClaim</code></td>
			</tr>
			<tr>
					<td>Secret</td>
					<td><code>CCI.Supervisor.Resource</code></td>
					<td><code>v1</code> <code>Secret</code></td>
			</tr>
			<tr>
					<td>Kubernetes Cluster</td>
					<td><code>CCI.Supervisor.Resource</code></td>
					<td><code>cluster.x-k8s.io/v1beta1</code> <code>Cluster</code></td>
			</tr>
			<tr>
					<td><em>(not in the palette)</em></td>
					<td><code>Util.PasswordEntry</code></td>
					<td></td>
			</tr>
	</tbody>
</table>
<p>Four consequences, worth knowing before any of the detail:</p>
<ul>
<li><strong>Anything the Supervisor understands can go in a blueprint.</strong> The workload
items are shortcuts. The generic Supervisor Resource takes any manifest the
namespace accepts. Our lab blueprints rely on a kind the palette doesn&rsquo;t
offer, <code>SubnetConnectionBindingMap</code>, to carry VLANs.</li>
<li><strong>The VPC items are a closed list.</strong> <code>CCI.VPC.Configuration</code> takes exactly
the five kinds above. A VPC&rsquo;s load balancer is a sixth kind in VCF
Automation&rsquo;s VPC API, and a blueprint can&rsquo;t make one (see
<a href="#vpc">VPC</a>).</li>
<li><strong>VCF Automation validates the outside, the platform the inside.</strong> The
validation API checks the resource type&rsquo;s own properties: required fields,
patterns, the namespace&rsquo;s two shapes. It doesn&rsquo;t look inside a <code>manifest</code>
or a <code>configs[].spec</code>: in our test, <code>powerState: Sideways</code> passed
validation. Those are checked when the request runs.</li>
<li><strong>The designer&rsquo;s schemas are not the platform&rsquo;s.</strong> The palette&rsquo;s forms
come from schemas bundled with VCF Automation, while the Supervisor and
the VPC API check against their own. They disagree in a handful of
places, listed next.</li>
</ul>
<h2 id="where-the-designer-and-the-platform-disagree">Where the designer and the platform disagree</h2>
<p>We compared each palette item&rsquo;s schema with the platform&rsquo;s definition of the
same <code>apiVersion</code> and <code>kind</code>. We went field by field (every bit as gripping
as it sounds) and tested every difference:</p>
<table>
	<thead>
			<tr>
					<th>Item</th>
					<th>The designer offers</th>
					<th>What the platform does</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Virtual Machine</td>
					<td><code>affinity.zoneAffinity</code>, <code>affinity.zoneAntiAffinity</code>, and VM affinity terms named <code>...IgnoredDuringExecution</code></td>
					<td>Rejects them as unknown fields. VM affinity and anti-affinity take <code>requiredDuringSchedulingPreferredDuringExecution</code> and <code>preferredDuringSchedulingPreferredDuringExecution</code>.</td>
			</tr>
			<tr>
					<td>Virtual Machine</td>
					<td>no <code>linuxPrep.password</code>, <code>linuxPrep.scriptText</code>, <code>crypto.vTPMMode</code>, <code>currentSnapshotName</code>, or disk options at volume level</td>
					<td>Accepts all of them.</td>
			</tr>
			<tr>
					<td>Virtual Machine</td>
					<td><code>bootOptions.firmware</code> as <code>BIOS</code> or <code>EFI</code>, and <code>bootOptions.enterBootSetup</code></td>
					<td><code>spec.bootOptions.firmware: Unsupported value: &quot;BIOS&quot;: supported values: &quot;bios&quot;, &quot;efi&quot;</code>, and <code>strict decoding error: unknown field &quot;spec.bootOptions.enterBootSetup&quot;</code>.</td>
			</tr>
			<tr>
					<td>Virtual Machine <code>v1alpha4</code>, <code>v1alpha3</code></td>
					<td><code>network.nameServers</code></td>
					<td>The field is <code>nameservers</code>, lower case.</td>
			</tr>
			<tr>
					<td>Subnet</td>
					<td><code>regionName</code>, <code>ipBlockNames</code>, <code>description</code></td>
					<td>Rejects them. Accepts <code>vlanConnectionName</code>, which the designer doesn&rsquo;t show.</td>
			</tr>
			<tr>
					<td>Persistent Volume Claim</td>
					<td><code>accessMode</code></td>
					<td><code>strict decoding error: unknown field &quot;spec.accessMode&quot;</code>. The field is <code>accessModes</code>.</td>
			</tr>
			<tr>
					<td>Kubernetes Cluster</td>
					<td><code>cluster.x-k8s.io/v1beta1</code></td>
					<td>Serves it, with <code>cluster.x-k8s.io/v1beta1 Cluster is deprecated; use cluster.x-k8s.io/v1beta2 Cluster</code>.</td>
			</tr>
			<tr>
					<td>Group</td>
					<td><code>vmSelectors[].selector</code>, <code>podSelectors[].selector</code></td>
					<td><code>spec.vmSelectors[0]: Required value: must specify at least one selector</code>. The field is <code>labelSelector</code>; the API also offers <code>propertySelector</code>.</td>
			</tr>
			<tr>
					<td>Gateway Firewall Policy</td>
					<td><code>ruleCount</code></td>
					<td>Computed by the API; not accepted. A rule&rsquo;s <code>from</code> is required, though the schema says empty means any.</td>
			</tr>
	</tbody>
</table>
<p>None of this stops the designer from saving a blueprint. It surfaces when the
request runs.</p>
<h2 id="what-every-resource-shares">What every resource shares</h2>
<h3 id="properties-on-every-type">Properties on every type</h3>
<table>
	<thead>
			<tr>
					<th>Property</th>
					<th>On</th>
					<th>What it does</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>count</code></td>
					<td>all</td>
					<td>How many instances to create. Default 1.</td>
			</tr>
			<tr>
					<td><code>allocatePerInstance</code></td>
					<td>all (beside <code>type</code>)</td>
					<td>Required for <code>${count.index}</code>: without it the validator refuses the blueprint with <code>should have allocatePerInstance property set to True</code>.</td>
			</tr>
			<tr>
					<td><code>dependsOn</code></td>
					<td>all (beside <code>type</code>)</td>
					<td>Explicit order. A reference to another resource orders the two already.</td>
			</tr>
			<tr>
					<td><code>context</code></td>
					<td>Supervisor Resource items</td>
					<td><strong>Required.</strong> The namespace the manifest goes into: <code>${resource.&lt;namespace&gt;.id}</code>.</td>
			</tr>
			<tr>
					<td><code>existing</code></td>
					<td>Namespace, Supervisor Resource items</td>
					<td><code>true</code> adopts what already exists instead of creating it.</td>
			</tr>
			<tr>
					<td><code>wait</code></td>
					<td>Supervisor Resource items, VPC Configuration</td>
					<td>When the resource counts as done.</td>
			</tr>
	</tbody>
</table>
<p>Recipe, two Secrets from one resource:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">sec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Resource</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">allocatePerInstance</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">count</span><span class="p">:</span><span class="w"> </span><span class="m">2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">context</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.ns.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">manifest</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Secret</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">${&#39;ref-s-&#39; + count.index}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">Opaque</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">stringData</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">note</span><span class="p">:</span><span class="w"> </span><span class="l">created by instance ${count.index}</span><span class="w">
</span></span></span></code></pre></div><p>The deployment then holds <code>sec[0]</code> and <code>sec[1]</code>, and the namespace
<code>ref-s-0</code> and <code>ref-s-1</code>.</p>
<h3 id="wait-when-a-resource-is-finished"><code>wait</code>: when a resource is finished</h3>
<p>Without a <code>wait</code>, a Supervisor Resource is finished as soon as the Supervisor
accepts the manifest. That&rsquo;s fine for a Secret, and wrong for a VM whose
address an output needs. <code>wait</code> takes conditions, fields, or both:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">      </span><span class="nt">wait</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">conditions</span><span class="p">:</span><span class="w">                      </span><span class="c"># status.conditions[] of the object</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">Ready</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">status</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;True&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">Ready</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">status</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;False&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">reason</span><span class="p">:</span><span class="w"> </span><span class="l">Failed</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">indicatesFailure</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">       </span><span class="c"># this one fails the resource instead of finishing it</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">fields</span><span class="p">:</span><span class="w">                          </span><span class="c"># any field of the object, by path</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">status.powerState</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l">PoweredOn</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">skipWaitOnDelete</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">          </span><span class="c"># true: deletion does not wait for the object to be gone</span><span class="w">
</span></span></span></code></pre></div><p>A Supervisor Resource can also watch log output with <code>executionLogs</code>:
<code>progressMessagePattern</code> while a matching message appears, and
<code>failureMessagePattern</code> to fail the resource.</p>
<p>The designer pre-fills a <code>wait</code> for some items:</p>
<table>
	<thead>
			<tr>
					<th>Item</th>
					<th>Designer&rsquo;s default <code>wait</code></th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>Virtual Machine</td>
					<td>condition <code>VirtualMachineCreated</code> = <code>True</code></td>
			</tr>
			<tr>
					<td>Virtual Machine Group</td>
					<td>condition <code>Ready</code> = <code>True</code></td>
			</tr>
			<tr>
					<td>NAT Rule, Group</td>
					<td>condition <code>Realized</code> = <code>True</code></td>
			</tr>
			<tr>
					<td>everything else</td>
					<td>none</td>
			</tr>
	</tbody>
</table>
<p>The VM&rsquo;s default came from a 9.0 problem: VM status could come back empty,
and Broadcom&rsquo;s KB 435137 gave this <code>wait</code> as the workaround. That condition
is true before the VM is even on, let alone has an address.</p>
<p>VCF Automation also waits by itself in one place: <strong>a Virtual Machine Service
of type <code>LoadBalancer</code> is not finished until it has an external address</strong>,
with or without a <code>wait</code>. In a VPC without a load balancer, that address
never comes, and the request stays in progress until it times out. Ours was
still <code>PARTIAL</code> after ten minutes, with the service <code>&lt;pending&gt;</code> on the
Supervisor.</p>
<h3 id="reading-a-resources-live-state">Reading a resource&rsquo;s live state</h3>
<p>Every Supervisor Resource exposes the object as the Supervisor sees it under
<code>object</code>, and a VPC Configuration exposes its objects under <code>configs</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">outputs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">vmIp</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.vm1.object.status.network.primaryIP4}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">vmHost</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.vm1.object.status.nodeName}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">lbIp</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.webLb.object.status.loadBalancer.ingress[0].ip}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">publicIp</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.publicIp.configs[0].spec.allocationIPs}</span><span class="w">
</span></span></span></code></pre></div><p><strong>Outputs are computed once, when the request finishes</strong>, and not refreshed
afterwards. A VM that waited only for <code>PoweredOn</code> finished before its guest
reported an address, and its IP output stayed empty for good. Waiting on the
condition that marks the guest&rsquo;s network as configured fixes it. This one
gave the output <code>172.30.0.2</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">      </span><span class="nt">wait</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">VirtualMachineGuestNetworkConfigSynced</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">status</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;True&#34;</span><span class="w">
</span></span></span></code></pre></div><h3 id="checking-a-manifest-before-you-deploy-it">Checking a manifest before you deploy it</h3>
<p>The fastest check we found is a server-side dry run with strict field
validation, against the namespace the blueprint will use:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">kubectl apply --dry-run=server --validate=strict -n &lt;namespace&gt; -f vm.yaml
</span></span></code></pre></div><p>It runs the Supervisor&rsquo;s schema checks and admission webhooks, flags unknown
fields, and creates nothing. It works for every workload kind. It does <strong>not</strong>
work for the VPC kinds: VCF Automation&rsquo;s VPC API ignores <code>dryRun</code> and creates
the object, as one of our probes found.</p>
<h2 id="supervisor-namespace">Supervisor Namespace</h2>
<p><code>type: CCI.Supervisor.Namespace</code>. Creates a vSphere Namespace through VCF
Automation, inside the project&rsquo;s allocation, or adopts one that exists.
Everything in the Workload group needs one: their <code>context</code> points at it.</p>
<p>The schema has two shapes, and the validator enforces them: an existing
namespace takes <code>name</code> and <code>existing: true</code> and nothing else; a new one needs
<code>generateName</code>, <code>className</code>, <code>regionName</code> and <code>vpcName</code>.</p>
<table>
	<thead>
			<tr>
					<th>Property</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>generateName</code></td>
					<td><strong>New namespace.</strong> Prefix; VCF Automation adds <code>-</code> and five random characters (<code>ns-ref-bstk7</code>). Must match <code>^[a-z0-9]([-a-z0-9]*[a-z0-9])?$</code>, so it cannot end in a hyphen.</td>
			</tr>
			<tr>
					<td><code>className</code></td>
					<td><strong>New namespace.</strong> The namespace class: limits, VM classes, storage classes and content libraries.</td>
			</tr>
			<tr>
					<td><code>regionName</code></td>
					<td><strong>New namespace.</strong> The region.</td>
			</tr>
			<tr>
					<td><code>vpcName</code></td>
					<td><strong>New namespace.</strong> The VPC its workloads use: an existing VPC&rsquo;s name, or <code>${resource.&lt;vpc&gt;.name}</code>.</td>
			</tr>
			<tr>
					<td><code>name</code> + <code>existing: true</code></td>
					<td><strong>Existing namespace.</strong> <code>name</code> alone matches neither shape.</td>
			</tr>
			<tr>
					<td><code>zones[]</code></td>
					<td>Per vSphere Zone: <code>name</code>, <code>cpuLimit</code>, <code>cpuReservation</code>, <code>memoryLimit</code>, <code>memoryReservation</code>, all five required.</td>
			</tr>
			<tr>
					<td><code>storageClasses[]</code></td>
					<td><code>name</code> (the storage policy as the namespace names it) and <code>limit</code>.</td>
			</tr>
			<tr>
					<td><code>vmClasses[]</code>, <code>contentSources[]</code></td>
					<td>VM classes and image sources beyond the class&rsquo;s own.</td>
			</tr>
			<tr>
					<td><code>sharedSubnetNames[]</code>, <code>infraPolicyNames[]</code>, <code>segName</code>, <code>description</code></td>
					<td>Shared subnets, extra infrastructure policies, an Avi Service Engine Group, a description.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (25)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>name</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>team-a-dev</code></td>
					<td>Supervisor namespace name</td>
			</tr>
			<tr>
					<td><code>count</code></td>
					<td>integer</td>
					<td></td>
					<td>default <code>1</code></td>
					<td>The number of resource instances to be created.</td>
			</tr>
			<tr>
					<td><code>zones</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: domain-c9, cpuLimit: 4000M}]</code></td>
					<td>Zone overrides for the namespace</td>
			</tr>
			<tr>
					<td><code>zones[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>domain-c9</code></td>
					<td>Name of the zone</td>
			</tr>
			<tr>
					<td><code>zones[].cpuLimit</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>4000M</code></td>
					<td>CPU limit in M or G</td>
			</tr>
			<tr>
					<td><code>zones[].memoryLimit</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>8192Mi</code></td>
					<td>Memory limit in Mi, Gi, or Ti</td>
			</tr>
			<tr>
					<td><code>zones[].cpuReservation</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>0M</code></td>
					<td>CPU reservation in M or G</td>
			</tr>
			<tr>
					<td><code>zones[].memoryReservation</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>0Mi</code></td>
					<td>Memory reservation in Mi, Gi, or Ti</td>
			</tr>
			<tr>
					<td><code>segName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>Default-Group</code></td>
					<td>Name of the Service Engine Group</td>
			</tr>
			<tr>
					<td><code>vpcName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>vpc-student05</code></td>
					<td>Name of the vpc</td>
			</tr>
			<tr>
					<td><code>existing</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Use existing supervisor namespace</td>
			</tr>
			<tr>
					<td><code>className</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>nested-pod</code></td>
					<td>Name of the supervisor namespace class</td>
			</tr>
			<tr>
					<td><code>vmClasses</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: best-effort-small}]</code></td>
					<td>VM Class overrides for the namespace</td>
			</tr>
			<tr>
					<td><code>vmClasses[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>best-effort-small</code></td>
					<td>Name of the vm class</td>
			</tr>
			<tr>
					<td><code>regionName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>f06</code></td>
					<td>Name of the region</td>
			</tr>
			<tr>
					<td><code>description</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>Team sandbox</code></td>
					<td>Description of the supervisor namespace</td>
			</tr>
			<tr>
					<td><code>generateName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>ns-demo</code></td>
					<td>Supervisor namespace generateName</td>
			</tr>
			<tr>
					<td><code>contentSources</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: my-library, type: ContentLibrary}]</code></td>
					<td>Content Source overrides for the namespace</td>
			</tr>
			<tr>
					<td><code>contentSources[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>my-library</code></td>
					<td>Name of the content source</td>
			</tr>
			<tr>
					<td><code>contentSources[].type</code></td>
					<td>string</td>
					<td>yes</td>
					<td>default <code>ContentLibrary</code></td>
					<td>Type of the content source</td>
			</tr>
			<tr>
					<td><code>storageClasses</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: vSAN Default Storage Policy, limit: 100Gi}]</code></td>
					<td>Storage Class overrides for the namespace</td>
			</tr>
			<tr>
					<td><code>storageClasses[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>vSAN Default Storage Policy</code></td>
					<td>Name of the storage class</td>
			</tr>
			<tr>
					<td><code>storageClasses[].limit</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>100Gi</code></td>
					<td>Storage Class limit in Mi, Gi, or Ti</td>
			</tr>
			<tr>
					<td><code>infraPolicyNames</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[&lt;infrastructure policy&gt;]</code></td>
					<td>Non-mandatory Infra Policy names</td>
			</tr>
			<tr>
					<td><code>sharedSubnetNames</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[&lt;shared subnet&gt;]</code></td>
					<td>Name of subnets</td>
			</tr>
	</tbody>
</table>

</details></p>

<p>Minimal, a new namespace with the zone and storage our class doesn&rsquo;t set:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">namespace</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Namespace</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">generateName</span><span class="p">:</span><span class="w"> </span><span class="l">ns-demo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">className</span><span class="p">:</span><span class="w"> </span><span class="l">nested-pod</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">regionName</span><span class="p">:</span><span class="w"> </span><span class="l">f06</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">vpcName</span><span class="p">:</span><span class="w"> </span><span class="l">vpc-student05</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">storageClasses</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">vSAN Default Storage Policy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">limit</span><span class="p">:</span><span class="w"> </span><span class="l">100Gi</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">zones</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">domain-c9</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">cpuLimit</span><span class="p">:</span><span class="w"> </span><span class="l">4000M</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">cpuReservation</span><span class="p">:</span><span class="w"> </span><span class="l">0M</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">memoryLimit</span><span class="p">:</span><span class="w"> </span><span class="l">8192Mi</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">memoryReservation</span><span class="p">:</span><span class="w"> </span><span class="l">0Mi</span><span class="w">
</span></span></span></code></pre></div><p><strong>Recipes</strong></p>
<ul>
<li>
<p><em>A quota sized from the request</em>, so a namespace never outgrows what was
asked for. Our lab blueprints compute the limits from the requested sizes:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storageClasses</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">vSAN Default Storage Policy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">limit</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;${input.hosts * 200 + &#39;Gi&#39;}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">zones</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">domain-c9</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">cpuLimit</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;${input.hosts * 8000 + &#39;M&#39;}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">cpuReservation</span><span class="p">:</span><span class="w"> </span><span class="l">0M</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">memoryLimit</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;${input.hosts * 32768 + &#39;Mi&#39;}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">memoryReservation</span><span class="p">:</span><span class="w"> </span><span class="l">0Mi</span><span class="w">
</span></span></span></code></pre></div></li>
<li>
<p><em>Deploy into a namespace that already exists</em>, for example one an
administrator prepared:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">namespace</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Namespace</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">team-a-dev</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">existing</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span></code></pre></div></li>
</ul>
<p><strong>Status worth reading:</strong> <code>${resource.&lt;ns&gt;.id}</code> is
<code>cci:&lt;project&gt;:&lt;namespace&gt;</code>, which <code>context</code> takes.</p>
<p><strong>Gotchas</strong></p>
<ul>
<li>Whether <code>zones</code> and <code>storageClasses</code> are optional depends on the namespace
class. Ours sets neither, and VCF Automation refused the minimal shape in
turn: <code>Zone should be specified in Namespace or in Namespace class</code>, then
<code>Storage Class should be specified in Namespace or in Namespace class</code>.</li>
<li>The zone <code>name</code> is the vSphere Zone. A Supervisor without zones still has
one, named after its cluster (<code>domain-c9</code> on f06).</li>
<li>A VM can only use a VM class the namespace allows and an image from its
content sources. The validator cannot know either; the request finds out.</li>
</ul>
<h2 id="vpc">VPC</h2>
<p><code>type: CCI.VPC</code>. Creates an NSX VPC in a region. Most blueprints use an
existing VPC, through the namespace&rsquo;s <code>vpcName</code>. This item is for a
blueprint that brings its own network.</p>
<table>
	<thead>
			<tr>
					<th>Property</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>generateName</code></td>
					<td><strong>Required.</strong> VCF Automation names the VPC <code>&lt;generateName&gt;-&lt;project&gt;-&lt;5 characters&gt;</code>: <code>vpc-ref-default-project-y3698</code>.</td>
			</tr>
			<tr>
					<td><code>regionName</code></td>
					<td><strong>Required.</strong> The region.</td>
			</tr>
			<tr>
					<td><code>privateIPs[]</code></td>
					<td>The VPC&rsquo;s private CIDRs. Empty uses the project&rsquo;s default.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (4)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>count</code></td>
					<td>integer</td>
					<td></td>
					<td>default <code>1</code></td>
					<td>The number of resource instances to be created.</td>
			</tr>
			<tr>
					<td><code>privateIPs</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[10.200.0.0/20]</code></td>
					<td>List of private IPs to be used in the VPC</td>
			</tr>
			<tr>
					<td><code>regionName</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>f06</code></td>
					<td>Region name for the VPC</td>
			</tr>
			<tr>
					<td><code>generateName</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>vpc-app</code></td>
					<td>Prefix for the generated name of the VPC</td>
			</tr>
	</tbody>
</table>

</details></p>

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">vpc</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.VPC</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">generateName</span><span class="p">:</span><span class="w"> </span><span class="l">vpc-app</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">regionName</span><span class="p">:</span><span class="w"> </span><span class="l">f06</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">privateIPs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="m">10.200.0.0</span><span class="l">/20</span><span class="w">
</span></span></span></code></pre></div><p><strong>Status worth reading:</strong> <code>id</code> (<code>cci:vpc:&lt;project&gt;:&lt;name&gt;</code>), which every VPC
Configuration takes as <code>vpc</code>, and <code>name</code>, which a namespace takes as
<code>vpcName</code>.</p>
<p><strong>Gotchas</strong></p>
<ul>
<li>A new VPC reaches nothing outside itself until it has an
<a href="#attachment">Attachment</a> to a VPC connectivity profile; give the namespace
<code>dependsOn</code> on the attachment.</li>
<li><code>privateIPs</code> must not overlap the connectivity profile&rsquo;s Private Transit
Gateway blocks, and the error only comes at attachment time: <code>private IP CIDR 172.31.64.0/20 overlaps with private TGW IP block CIDR 172.31.0.0/16</code>.</li>
<li><strong>A blueprint cannot give its VPC a load balancer.</strong> In VCF Automation&rsquo;s
VPC API the load balancer is its own kind, <code>LoadBalancer</code>, and
<code>CCI.VPC.Configuration</code> refuses it: <code>Failed to match exactly one schema (matched 0 out of 5)</code>. Without one, a LoadBalancer service never gets an
address (and its request never finishes, see <a href="#wait-when-a-resource-is-finished"><code>wait</code></a>),
and Broadcom&rsquo;s VPC page warns that a VPC without load balancing cannot run
VKS. For either, use a VPC made in the UI with <strong>Enable load balancing</strong>
on, and name it in the namespace&rsquo;s <code>vpcName</code>.</li>
</ul>
<h2 id="vpc-configuration">VPC Configuration</h2>
<p><code>type: CCI.VPC.Configuration</code>. One item for every object that lives inside a
VPC, and <code>kind</code> chooses which. The five palette entries below are this item
with <code>kind</code> filled in. Each <code>configs[]</code> entry becomes one object, so one
resource can create several rules or groups of the same kind.</p>
<table>
	<thead>
			<tr>
					<th>Property</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>vpc</code></td>
					<td><strong>Required.</strong> The VPC&rsquo;s id: <code>${resource.vpc.id}</code>, or an existing VPC&rsquo;s <code>cci:vpc:&lt;project&gt;:&lt;name&gt;</code>.</td>
			</tr>
			<tr>
					<td><code>kind</code></td>
					<td><strong>Required.</strong> <code>VPCAttachment</code>, <code>VPCIPAddressAllocation</code>, <code>VPCNATRule</code>, <code>VPCNetworkSecurityGroup</code> or <code>VPCGatewayFirewallPolicy</code>, and nothing else.</td>
			</tr>
			<tr>
					<td><code>apiVersion</code></td>
					<td><code>vpc.nsx.vmware.com/v1alpha1</code>.</td>
			</tr>
			<tr>
					<td><code>configs[]</code></td>
					<td><strong>Required.</strong> Per object: <code>generateName</code> (<strong>required</strong>), <code>spec</code>, <code>labels</code>, <code>annotations</code>.</td>
			</tr>
			<tr>
					<td><code>wait</code></td>
					<td>Applies to every object in <code>configs</code>.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (20)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>vpc</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>${resource.vpc.id}</code></td>
					<td>ID of the parent VPC this resource is associated with.</td>
			</tr>
			<tr>
					<td><code>kind</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>VPCNATRule</code></td>
					<td>The kind of the resource (e.g., VPCNetworkSecurityGroup, VPCIPAddressAllocation, VPCNATRule, VPCAttachment).</td>
			</tr>
			<tr>
					<td><code>wait</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{fields: [{path: status.conditions[0].status, value: True}], ...}</code></td>
					<td>Wait conditions applied to all config resources. All resources must satisfy these conditions before the operation is considered complete.</td>
			</tr>
			<tr>
					<td><code>wait.fields</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{path: status.conditions[0].status, value: True}]</code></td>
					<td>List of field conditions to wait for.</td>
			</tr>
			<tr>
					<td><code>wait.fields[].path</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>status.conditions[0].status</code></td>
					<td>JSONPath to the field to check (e.g., status.phase).</td>
			</tr>
			<tr>
					<td><code>wait.fields[].value</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>True</code></td>
					<td>The expected value of the field. Use &lsquo;*&rsquo; for any non-null value.</td>
			</tr>
			<tr>
					<td><code>wait.fields[].indicatesFailure</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Whether this field condition indicates a failure state.</td>
			</tr>
			<tr>
					<td><code>wait.conditions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{type: Realized, reason: &lt;condition reason&gt;}]</code></td>
					<td>List of status conditions to wait for.</td>
			</tr>
			<tr>
					<td><code>wait.conditions[].type</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>Realized</code></td>
					<td>The type of the condition (e.g., Ready, Realized).</td>
			</tr>
			<tr>
					<td><code>wait.conditions[].reason</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;condition reason&gt;</code></td>
					<td>Optional reason for the condition.</td>
			</tr>
			<tr>
					<td><code>wait.conditions[].status</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>True</code></td>
					<td>The expected status of the condition (e.g., True, False).</td>
			</tr>
			<tr>
					<td><code>wait.conditions[].indicatesFailure</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Whether this condition indicates a failure state.</td>
			</tr>
			<tr>
					<td><code>wait.skipWaitOnDelete</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Whether to skip waiting for conditions during delete operations.</td>
			</tr>
			<tr>
					<td><code>count</code></td>
					<td>integer</td>
					<td></td>
					<td>default <code>1</code></td>
					<td>The number of resource instances to be created.</td>
			</tr>
			<tr>
					<td><code>configs</code></td>
					<td>array of object</td>
					<td>yes</td>
					<td>e.g. <code>[{generateName: dnat-web, spec: {action: DNAT, translatedNetwork: 10.200.0.10}}]</code></td>
					<td>List of resources associated with the VPC.</td>
			</tr>
			<tr>
					<td><code>configs[].spec</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{action: DNAT, translatedNetwork: 10.200.0.10}</code></td>
					<td>The specification of the associated resource.</td>
			</tr>
			<tr>
					<td><code>configs[].labels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{app: web}</code></td>
					<td>Labels for categorizing the resource.</td>
			</tr>
			<tr>
					<td><code>configs[].annotations</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{owner: team-a}</code></td>
					<td>Annotations for additional metadata about the resource.</td>
			</tr>
			<tr>
					<td><code>configs[].generateName</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>dnat-web</code></td>
					<td>A prefix for generating a unique name for the resource.</td>
			</tr>
			<tr>
					<td><code>apiVersion</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>vpc.nsx.vmware.com/v1alpha1</code></td>
					<td>The API version of the resource.</td>
			</tr>
	</tbody>
</table>

</details></p>

<p>Three things hold for all five kinds:</p>
<ul>
<li><strong><code>generateName</code> is the name, not a prefix.</strong> VCF Automation names the
object <code>&lt;vpc&gt;:&lt;generateName&gt;</code>, as written: our group was
<code>vpc-ref-default-project-y3698:web</code>. Keep it unique per kind in the VPC.</li>
<li><strong>VCF Automation fills in <code>spec.vpcName</code> and <code>spec.regionName</code></strong> from the
<code>vpc</code> property; leave them out.</li>
<li><strong>Another resource reads an object as <code>configs[n]</code></strong>:
<code>${resource.webGroup.configs[0].name}</code> is the full name a firewall rule
needs, and <code>${resource.publicIp.configs[0].spec.allocationIPs}</code> is the
address an allocation got.</li>
</ul>
<p>The shape, for every kind:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">natRules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.VPC.Configuration</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">vpc</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.vpc.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">vpc.nsx.vmware.com/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">VPCNATRule</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">configs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">generateName</span><span class="p">:</span><span class="w"> </span><span class="l">dnat-web</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">spec</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="l">... }</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">generateName</span><span class="p">:</span><span class="w"> </span><span class="l">dnat-ssh</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">spec</span><span class="p">:</span><span class="w"> </span>{<span class="w"> </span><span class="l">... }</span><span class="w">
</span></span></span></code></pre></div><h3 id="attachment">Attachment</h3>
<p><code>kind: VPCAttachment</code>. Attaches the VPC to a VPC connectivity profile, which
decides its transit gateway, its external IP blocks and whether it gets a
default outbound NAT.</p>
<table>
	<thead>
			<tr>
					<th><code>spec</code> field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>vpcConnectivityProfileName</code></td>
					<td><strong>Required.</strong> The profile, as NSX names it (f06&rsquo;s is <code>default--f06</code>).</td>
			</tr>
			<tr>
					<td><code>preferredDefaultSNATIP</code></td>
					<td>The address for the VPC&rsquo;s automatic SNAT. It must be free in the external block; empty lets NSX choose.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (2)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>spec.preferredDefaultSNATIP</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>192.168.144.30</code></td>
					<td>PreferredDefaultSNATIP specifies the translated IP for VPC auto SNAT rules. The specified IP must be available.</td>
			</tr>
			<tr>
					<td><code>spec.vpcConnectivityProfileName</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>default--f06</code></td>
					<td>VPCConnectivityProfileName specifies the name of the VPC Connectivity Profile associated with the VPC.</td>
			</tr>
	</tbody>
</table>

</details></p>

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">attach</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.VPC.Configuration</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">vpc</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.vpc.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">vpc.nsx.vmware.com/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">VPCAttachment</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">configs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">generateName</span><span class="p">:</span><span class="w"> </span><span class="l">attach</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">vpcConnectivityProfileName</span><span class="p">:</span><span class="w"> </span><span class="l">default--f06</span><span class="w">
</span></span></span></code></pre></div><p>With the attachment realized, NSX adds the VPC&rsquo;s default SNAT rule and its
address by itself (ours: <code>10.200.0.0/20</code> to <code>192.168.144.14</code>).</p>
<h3 id="ip-address-allocation">IP Address Allocation</h3>
<p><code>kind: VPCIPAddressAllocation</code>. Reserves addresses from one of the VPC&rsquo;s IP
blocks, typically an external address for a NAT rule.</p>
<table>
	<thead>
			<tr>
					<th><code>spec</code> field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>ipAddressBlockVisibility</code></td>
					<td><code>Private</code> (default), <code>PrivateTGW</code> or <code>External</code>. The NSX API&rsquo;s own default is <code>External</code>.</td>
			</tr>
			<tr>
					<td><code>allocationSize</code></td>
					<td>How many addresses, a power of 2. Either this or <code>allocationIPs</code>.</td>
			</tr>
			<tr>
					<td><code>allocationIPs</code></td>
					<td>Specific addresses, as a CIDR (<code>192.168.0.1/32</code>).</td>
			</tr>
			<tr>
					<td><code>ipBlockName</code></td>
					<td>A particular block, when the visibility has more than one.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (4)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>spec.allocationIPs</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>192.168.144.18</code></td>
					<td>The specific IP addresses from IPBlock that needs to be requested. If specified, it should be passed like 192.168.0.0/24 or 192.168.0.1/32.</td>
			</tr>
			<tr>
					<td><code>spec.allocationSize</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>1</code></td>
					<td>Allocation IP address size for auto allocating IPs from IPBlock. The IP addresses will be auto allocated from unused IP addresses based on allocation size.</td>
			</tr>
			<tr>
					<td><code>spec.ipAddressBlockVisibility</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>External</code></td>
					<td>Visibility of IP address block. Must be External, Private or PrivateTGW. Note: the default Private Visibility is different from NSX API&rsquo;s default External Visibility.</td>
			</tr>
			<tr>
					<td><code>spec.ipBlockName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>:f06-vpc-ext02</code></td>
					<td>IPBlock name for allocating IP address.</td>
			</tr>
	</tbody>
</table>

</details></p>

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">publicIp</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.VPC.Configuration</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">dependsOn</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">attach]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">vpc</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.vpc.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">vpc.nsx.vmware.com/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">VPCIPAddressAllocation</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">configs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">generateName</span><span class="p">:</span><span class="w"> </span><span class="l">web-ip</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">ipAddressBlockVisibility</span><span class="p">:</span><span class="w"> </span><span class="l">External</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">allocationSize</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span></code></pre></div><p>The allocated address appears in the object&rsquo;s own spec:
<code>${resource.publicIp.configs[0].spec.allocationIPs}</code> gave <code>192.168.144.18</code>.
An external allocation needs the attachment first, hence the <code>dependsOn</code>.</p>
<h3 id="nat-rule">NAT Rule</h3>
<p><code>kind: VPCNATRule</code>. A NAT rule on the VPC&rsquo;s gateway. The designer&rsquo;s default
<code>wait</code> is <code>Realized</code>.</p>
<table>
	<thead>
			<tr>
					<th><code>spec</code> field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>action</code></td>
					<td><strong>Required.</strong> <code>SNAT</code>, <code>DNAT</code>, <code>Reflexive</code>, <code>NoSNAT</code> or <code>NoDNAT</code>.</td>
			</tr>
			<tr>
					<td><code>translatedNetwork</code></td>
					<td><strong>Required.</strong> For SNAT, one address from the VPC&rsquo;s external block.</td>
			</tr>
			<tr>
					<td><code>sourceNetwork</code></td>
					<td>One address, a comma-separated list, or a CIDR. Mandatory for SNAT.</td>
			</tr>
			<tr>
					<td><code>destinationNetwork</code></td>
					<td>One address; empty means any.</td>
			</tr>
			<tr>
					<td><code>serviceEntry</code></td>
					<td><code>protocol</code> (<code>TCP</code>, <code>UDP</code>, <code>ICMP</code>), <code>sourcePorts</code>, <code>destinationPorts</code>, <code>translatedPorts</code>. See the warning.</td>
			</tr>
			<tr>
					<td><code>sequenceNumber</code></td>
					<td>Priority, default 0.</td>
			</tr>
			<tr>
					<td><code>firewallMatch</code></td>
					<td><code>MatchInternalAddress</code> (default), <code>MatchExternalAddress</code> or <code>ByPass</code>.</td>
			</tr>
			<tr>
					<td><code>enabled</code>, <code>logging</code></td>
					<td>Defaults <code>true</code> and <code>false</code>.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (13)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>spec.action</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>DNAT</code></td>
					<td>Action represents action of NAT Rule. Valid values: SNAT, DNAT, Reflexive, NoSNAT and NoDNAT.</td>
			</tr>
			<tr>
					<td><code>spec.destinationNetwork</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>192.168.144.18</code></td>
					<td>DestinationNetwork represents the destination network. The value can be a single IPv4 address or CIDR, or a comma separated list of IPv4 addresses.</td>
			</tr>
			<tr>
					<td><code>spec.enabled</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>NAT Rule enabled flag Enabled indicates whether the NAT rule is enabled or disabled. The default is True.</td>
			</tr>
			<tr>
					<td><code>spec.firewallMatch</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>MATCH_INTERNAL_ADDRESS</code></td>
					<td>FirewallMatch indicates how the firewall matches the address after NATing if firewall stage is not skipped.</td>
			</tr>
			<tr>
					<td><code>spec.logging</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>NAT Rule logging flag Logging indicates whether the logging of NAT rule is enabled or disabled. The default is False.</td>
			</tr>
			<tr>
					<td><code>spec.sequenceNumber</code></td>
					<td>integer</td>
					<td></td>
					<td>default <code>0</code></td>
					<td>SequenceNumber decides the priority of a NAT rule. Valid range is [0, 2147481599]. Default is 0.</td>
			</tr>
			<tr>
					<td><code>spec.serviceEntry</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{destinationPorts: &quot;22&quot;, protocol: TCP}</code></td>
					<td></td>
			</tr>
			<tr>
					<td><code>spec.serviceEntry.destinationPorts</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&quot;22&quot;</code></td>
					<td>The destination ports to match. If specified, it must be either a single port (e.g. &ldquo;8080&rdquo;) or a port range (e.g. &ldquo;8090-8095&rdquo;).</td>
			</tr>
			<tr>
					<td><code>spec.serviceEntry.protocol</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>TCP</code></td>
					<td>Protocol supports TCP, UDP and ICMP v4.</td>
			</tr>
			<tr>
					<td><code>spec.serviceEntry.sourcePorts</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>1024-65535</code></td>
					<td>The source ports to match. If specified, it must be either a single port (e.g. &ldquo;8080&rdquo;) or a port range (e.g. &ldquo;8090-8095&rdquo;).</td>
			</tr>
			<tr>
					<td><code>spec.serviceEntry.translatedPorts</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&quot;2222&quot;</code></td>
					<td>The translated ports. If specified, it must be either a single port (e.g. &ldquo;8080&rdquo;) or a port range (e.g. &ldquo;8090-8095&rdquo;).</td>
			</tr>
			<tr>
					<td><code>spec.sourceNetwork</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10.200.0.0/28</code></td>
					<td>SourceNetwork represents the source network address. The value can be a single IPv4 address or CIDR, or a comma separated list of IPv4 addresses.</td>
			</tr>
			<tr>
					<td><code>spec.translatedNetwork</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>10.200.0.10</code></td>
					<td>TranslatedNetwork represents the translated network address. The field is required and must contain a single IPv4 address for SNAT, DNAT and Reflexive.</td>
			</tr>
	</tbody>
</table>

</details></p>

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">dnatSsh</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.VPC.Configuration</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">vpc</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.vpc.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">vpc.nsx.vmware.com/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">VPCNATRule</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">configs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">generateName</span><span class="p">:</span><span class="w"> </span><span class="l">dnat-ssh</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">DNAT</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">destinationNetwork</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.publicIp.configs[0].spec.allocationIPs}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">translatedNetwork</span><span class="p">:</span><span class="w"> </span><span class="m">10.200.0.10</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">serviceEntry</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l">TCP</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">destinationPorts</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;22&#34;</span><span class="w">
</span></span></span></code></pre></div><p><strong>Warning: the port did not reach NSX.</strong> VCF Automation&rsquo;s API kept the
<code>serviceEntry</code> (TCP 22), but the rule NSX realized had <code>service: null</code>: a
DNAT of every port on <code>192.168.144.18</code> to the private address. Treat a NAT
rule as a whole-address mapping. To publish one port, use a
<a href="#virtual-machine-service">Virtual Machine Service</a> of type <code>LoadBalancer</code>,
which forwards only its ports and follows the VM&rsquo;s address.</p>
<h3 id="group">Group</h3>
<p><code>kind: VPCNetworkSecurityGroup</code>. A group of addresses, VMs or pods that
firewall rules can name. Default <code>wait</code>: <code>Realized</code>.</p>
<table>
	<thead>
			<tr>
					<th><code>spec</code> field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>ipAddresses[]</code></td>
					<td>Addresses, ranges or CIDRs.</td>
			</tr>
			<tr>
					<td><code>vmSelectors[]</code></td>
					<td><code>labelSelector</code> (VMs by label, so new VMs with the label join), <code>namespaceSelector</code>, and <code>propertySelector</code> (VMs by <code>Name</code>, <code>OSName</code> or <code>ComputerName</code>, with <code>Equals</code>, <code>Contains</code>, <code>StartsWith</code>, <code>EndsWith</code>, <code>NotEquals</code>).</td>
			</tr>
			<tr>
					<td><code>podSelectors[]</code></td>
					<td><code>labelSelector</code> and <code>namespaceSelector</code> for pods.</td>
			</tr>
			<tr>
					<td><code>vms[]</code></td>
					<td>Specific VMs, by <code>instanceUUID</code>.</td>
			</tr>
			<tr>
					<td><code>vpcNetworkSecurityGroupNames[]</code></td>
					<td>Other groups, nested.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (35)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>spec.ipAddresses</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[10.200.0.0/28]</code></td>
					<td>List of IPs or CIDRs to be included in this VPCNetworkSecurityGroup. Each entry can be a single IP address, an IP range, or a subnet in CIDR notation.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{labelSelector: {matchLabels: {app: web}}, ...}]</code></td>
					<td>List of Pod label selectors that will dynamically select Pods to include in this VPCNetworkSecurityGroup.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].labelSelector</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{matchLabels: {app: web}}</code></td>
					<td>A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].labelSelector.matchExpressions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: app, operator: In}]</code></td>
					<td>matchExpressions is a list of label selector requirements. The requirements are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].labelSelector.matchExpressions[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>app</code></td>
					<td>key is the label key that the selector applies to.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].labelSelector.matchExpressions[].operator</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>In</code></td>
					<td>operator represents a key&rsquo;s relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].labelSelector.matchExpressions[].values</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[web]</code></td>
					<td>values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].labelSelector.matchLabels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{app: web}</code></td>
					<td>matchLabels is a map of {key,value} pairs.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].namespaceSelector</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{matchExpressions: [{key: app, operator: In}], matchLabels: {app: web}}</code></td>
					<td>A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].namespaceSelector.matchExpressions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: app, operator: In}]</code></td>
					<td>matchExpressions is a list of label selector requirements. The requirements are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].namespaceSelector.matchExpressions[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>app</code></td>
					<td>key is the label key that the selector applies to.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].namespaceSelector.matchExpressions[].operator</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>In</code></td>
					<td>operator represents a key&rsquo;s relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].namespaceSelector.matchExpressions[].values</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[web]</code></td>
					<td>values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.</td>
			</tr>
			<tr>
					<td><code>spec.podSelectors[].namespaceSelector.matchLabels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{app: web}</code></td>
					<td>matchLabels is a map of {key,value} pairs.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{labelSelector: {matchLabels: {app: web}}, ...}]</code></td>
					<td>List of Virtual Machine label selectors that will dynamically select VMs to include in this VPCNetworkSecurityGroup.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].labelSelector</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{matchLabels: {app: web}}</code></td>
					<td>A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].labelSelector.matchExpressions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: app, operator: In}]</code></td>
					<td>matchExpressions is a list of label selector requirements. The requirements are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].labelSelector.matchExpressions[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>app</code></td>
					<td>key is the label key that the selector applies to.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].labelSelector.matchExpressions[].operator</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>In</code></td>
					<td>operator represents a key&rsquo;s relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].labelSelector.matchExpressions[].values</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[web]</code></td>
					<td>values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].labelSelector.matchLabels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{app: web}</code></td>
					<td>matchLabels is a map of {key,value} pairs.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].namespaceSelector</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{matchExpressions: [{key: app, operator: In}], matchLabels: {app: web}}</code></td>
					<td>A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].namespaceSelector.matchExpressions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: app, operator: In}]</code></td>
					<td>matchExpressions is a list of label selector requirements. The requirements are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].namespaceSelector.matchExpressions[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>app</code></td>
					<td>key is the label key that the selector applies to.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].namespaceSelector.matchExpressions[].operator</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>In</code></td>
					<td>operator represents a key&rsquo;s relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].namespaceSelector.matchExpressions[].values</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[web]</code></td>
					<td>values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].namespaceSelector.matchLabels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{app: web}</code></td>
					<td>matchLabels is a map of {key,value} pairs.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].propertySelector</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{matchExpressions: [{key: Name, operator: StartsWith}]}</code></td>
					<td>PropertySelector represents a set of conditions on VM properties. All MatchExpressions are ANDed; a VM must satisfy all expressions to match.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].propertySelector.matchExpressions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: Name, operator: StartsWith}]</code></td>
					<td>MatchExpressions is a list of property selector requirements. Each requirement consists of a key, operator, and value.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].propertySelector.matchExpressions[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>Name</code></td>
					<td>Key is the VM property to match. Valid keys are Name, OSName and ComputerName.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].propertySelector.matchExpressions[].operator</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>StartsWith</code></td>
					<td>Operator defines how the Key is compared against Value. Valid operators are Equals, Contains, StartsWith, EndsWith and NotEquals.</td>
			</tr>
			<tr>
					<td><code>spec.vmSelectors[].propertySelector.matchExpressions[].value</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>web-</code></td>
					<td>Value is the target value to match against the VM property.</td>
			</tr>
			<tr>
					<td><code>spec.vms</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{instanceUUID: 5010c9b4-1f2e-4d3c-8b7a-6e5f4d3c2b1a}]</code></td>
					<td>List of Virtual Machine references that will be included in this VPCNetworkSecurityGroup.</td>
			</tr>
			<tr>
					<td><code>spec.vms[].instanceUUID</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>5010c9b4-1f2e-4d3c-8b7a-6e5f4d3c2b1a</code></td>
					<td>InstanceUUID of the VM being referenced.</td>
			</tr>
			<tr>
					<td><code>spec.vpcNetworkSecurityGroupNames</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[db-servers]</code></td>
					<td>List of VPCNetworkSecurityGroup names that will be included in this VPCNetworkSecurityGroup.</td>
			</tr>
	</tbody>
</table>

</details></p>

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">webGroup</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.VPC.Configuration</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">vpc</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.vpc.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">vpc.nsx.vmware.com/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">VPCNetworkSecurityGroup</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">configs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">generateName</span><span class="p">:</span><span class="w"> </span><span class="l">web</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">vmSelectors</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span>- <span class="nt">labelSelector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w"> </span>{<span class="nt">tier</span><span class="p">:</span><span class="w"> </span><span class="l">web}</span><span class="w">
</span></span></span></code></pre></div><p>Every VPC also has a group named <code>default</code>, made by NSX.</p>
<h3 id="gateway-firewall-policy">Gateway Firewall Policy</h3>
<p><code>kind: VPCGatewayFirewallPolicy</code>. Rules on the VPC&rsquo;s gateway, for traffic
entering and leaving the VPC. The distributed firewall inside the VPC is a
separate thing.</p>
<table>
	<thead>
			<tr>
					<th><code>spec</code> field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>rules[]</code></td>
					<td>Per rule: <code>name</code> (unique in the policy), <code>action</code> (<code>Allow</code> default, <code>Drop</code>, <code>Reject</code>, <code>JumpToApplication</code>), <code>direction</code> (<code>InOut</code> default, <code>In</code>, <code>Out</code>), <code>from[]</code> and <code>to[]</code> (each entry <code>groupName</code> or <code>ipAddress</code>), <code>services[]</code> (<code>networkServiceName</code>, or <code>l4PortSet</code> with <code>l4Protocol</code>, <code>destinationPorts</code>, <code>sourcePorts</code>), <code>ipProtocol</code>, <code>log</code>, <code>disabled</code>, <code>notes</code>, <code>tag</code>, <code>sourcesExcluded</code>, <code>destinationsExcluded</code>, <code>appliedTo</code>.</td>
			</tr>
			<tr>
					<td><code>category</code></td>
					<td><code>LocalGatewayRules</code> (default) or <code>Default</code>.</td>
			</tr>
			<tr>
					<td><code>priority</code></td>
					<td>Order against other policies, default 0.</td>
			</tr>
			<tr>
					<td><code>stateful</code>, <code>tcpStrict</code></td>
					<td>Stateful inspection; a full TCP handshake before data.</td>
			</tr>
			<tr>
					<td><code>description</code>, <code>locked</code></td>
					<td></td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (35)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>spec.category</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>LocalGatewayRules</code></td>
					<td>Pre-defined categories for classifying a VPC Gateway Firewall policy.There are two pre-defined categories. They are &ldquo;LocalGatewayRules&rdquo; and &ldquo;Default&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.description</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>Inbound HTTPS</code></td>
					<td>Description for the firewall policy.</td>
			</tr>
			<tr>
					<td><code>spec.isDefault</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>A flag to indicate whether rule is a default rule</td>
			</tr>
			<tr>
					<td><code>spec.locked</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Locked indicates whether a security policy should be locked</td>
			</tr>
			<tr>
					<td><code>spec.priority</code></td>
					<td>integer</td>
					<td></td>
					<td>default <code>0</code></td>
					<td>This field is used to resolve conflicts between multiple Rules under Security or Gateway Policy for a Domain. If no priority is specified in the payload, a value of 0 is assigned by default.</td>
			</tr>
			<tr>
					<td><code>spec.rules</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{action: Allow, name: https-in}]</code></td>
					<td>Rules that are a part of this FirewallPolicy</td>
			</tr>
			<tr>
					<td><code>spec.rules[].action</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>Allow</code></td>
					<td>Action to be applied to all the services</td>
			</tr>
			<tr>
					<td><code>spec.rules[].appliedTo</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{gatewayAttachmentNames: [&lt;transit gateway attachment&gt;], ...}</code></td>
					<td></td>
			</tr>
			<tr>
					<td><code>spec.rules[].appliedTo.gatewayAttachmentNames</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[&lt;transit gateway attachment&gt;]</code></td>
					<td>This field is only applicable when the rule is defined for Transit Gateway Firewall policy</td>
			</tr>
			<tr>
					<td><code>spec.rules[].appliedTo.gatewayNames</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[&lt;transit gateway&gt;]</code></td>
					<td>This field is only applicable when the rule is defined for Transit Gateway Firewall policy</td>
			</tr>
			<tr>
					<td><code>spec.rules[].appliedTo.groupNames</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[&lt;group&gt;]</code></td>
					<td>This field is only applicable when the rule is defined for Distributed Firewall policy</td>
			</tr>
			<tr>
					<td><code>spec.rules[].destinationsExcluded</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>DestinationsExcluded indicates that the rule applies to all destinations <em>except</em> those specified in the &lsquo;To&rsquo; field.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].direction</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>In</code></td>
					<td>Direction defines direction of traffic.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].disabled</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Disabled indicates if the rule is enabled/disabled.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].from</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{ipAddress: 0.0.0.0/0, groupName: admin-hosts}]</code></td>
					<td>From defines the source of the traffic. If empty, it defaults to &ldquo;Any&rdquo;, matching all sources.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].from[].groupName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>admin-hosts</code></td>
					<td></td>
			</tr>
			<tr>
					<td><code>spec.rules[].from[].ipAddress</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>0.0.0.0/0</code></td>
					<td></td>
			</tr>
			<tr>
					<td><code>spec.rules[].ipProtocol</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>IPV4</code></td>
					<td>IpProtocol indicates type of IP packet that should be matched while enforcing the rule. Only IPV_4 protocol is supported for new rules, IPV4_IPV6 is only allowed for default rules.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].isDefault</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>IsDefault is a flag to indicate whether rule is a default rule.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].log</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>Log indicates if traffic matching this rule should be logged.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>https-in</code></td>
					<td>Name for the rule. Must be unique within the policy.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].notes</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>HTTPS from anywhere</code></td>
					<td>Notes for the rule.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].services</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{l4PortSet: {destinationPorts: [443], l4Protocol: TCP}, networkServiceName: :HTTPS}]</code></td>
					<td>Services specifies the network services (protocols and ports) to which this rule applies. If empty or null ,it defaults to &ldquo;Any&rdquo; , then this rule applies to all services.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].services[].l4PortSet</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{destinationPorts: [443], l4Protocol: TCP}</code></td>
					<td>L4PortSetServiceEntry is a ServiceEntry that represents TCP or UDP protocol.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].services[].l4PortSet.destinationPorts</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[443]</code></td>
					<td>DestinationPorts defines the destination port or port range to match. For example: [&ldquo;443&rdquo;], [&ldquo;8080-8090&rdquo;]. If empty, matches any destination port.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].services[].l4PortSet.l4Protocol</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>TCP</code></td>
					<td>L4Protocol specifies the Layer 4 protocol (TCP or UDP).</td>
			</tr>
			<tr>
					<td><code>spec.rules[].services[].l4PortSet.sourcePorts</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[1000-2000]</code></td>
					<td>SourcePorts defines the source port or port range to match. For example: [&ldquo;80&rdquo;], [&ldquo;1000-2000&rdquo;]. If empty, matches any source port.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].services[].networkServiceName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>:HTTPS</code></td>
					<td></td>
			</tr>
			<tr>
					<td><code>spec.rules[].sourcesExcluded</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>SourcesExcluded indicates that the rule applies to all sources <em>except</em> those specified in the &lsquo;From&rsquo; field. When true, the &lsquo;From&rsquo; field acts as an exclusion list.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].tag</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>web</code></td>
					<td>Tag applied on the rule.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].to</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{groupName: ${resource.webGroup.configs[0].name}, ipAddress: 10.200.0.10}]</code></td>
					<td>To defines the destination of the traffic. If empty, it defaults to &ldquo;Any&rdquo;, matching all destinations.</td>
			</tr>
			<tr>
					<td><code>spec.rules[].to[].groupName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>${resource.webGroup.configs[0].name}</code></td>
					<td></td>
			</tr>
			<tr>
					<td><code>spec.rules[].to[].ipAddress</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10.200.0.10</code></td>
					<td></td>
			</tr>
			<tr>
					<td><code>spec.stateful</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Stateful or Stateless nature of security policy is enforced on all rules in this security policy.</td>
			</tr>
			<tr>
					<td><code>spec.tcpStrict</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Ensures that a 3 way TCP handshake is done before the data packets are sent. tcp_strict=true is supported only for stateful security policies.</td>
			</tr>
	</tbody>
</table>

</details></p>

<p>Recipe, HTTPS from anywhere to the web group:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">gwPolicy</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.VPC.Configuration</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">dependsOn</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">attach]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">vpc</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.vpc.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">vpc.nsx.vmware.com/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">VPCGatewayFirewallPolicy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">configs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>- <span class="nt">generateName</span><span class="p">:</span><span class="w"> </span><span class="l">web-in</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">stateful</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">https-in</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">action</span><span class="p">:</span><span class="w"> </span><span class="l">Allow</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">direction</span><span class="p">:</span><span class="w"> </span><span class="l">In</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">from</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span>- <span class="nt">ipAddress</span><span class="p">:</span><span class="w"> </span><span class="m">0.0.0.0</span><span class="l">/0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">to</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span>- <span class="nt">groupName</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.webGroup.configs[0].name}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">services</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span>- <span class="nt">networkServiceName</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;:HTTPS&#34;</span><span class="w">
</span></span></span></code></pre></div><p><strong>Gotchas</strong></p>
<ul>
<li><strong><code>from</code> is required</strong>, whatever the field&rsquo;s description says: without it,
<code>spec.rules[0].from: Required value</code>. Write <code>0.0.0.0/0</code> for any source.</li>
<li><strong>Name a service rather than a port set.</strong> A rule that lists only an
<code>l4PortSet</code> gets <code>networkServiceName: Any</code> added by the API, and NSX
realizes it as services <code>ANY</code> beside the raw TCP 443 entry. With
<code>networkServiceName: &quot;:HTTPS&quot;</code> NSX holds exactly <code>/infra/services/HTTPS</code>.
The API lists 415 services, all with a leading colon (<code>:DNS</code>, <code>:HTTPS</code>,
<code>:SSH</code>); without the colon it refuses: <code>Network service name must start with a colon (:), such as :HTTP</code>.</li>
<li><code>groupName</code> takes the group&rsquo;s full name, <code>&lt;vpc&gt;:&lt;generateName&gt;</code>, which
<code>configs[0].name</code> supplies.</li>
<li>The gateway firewall has to be active in the VPC&rsquo;s security profile for any
of this to be enforced.</li>
</ul>
<h2 id="supervisor-resource">Supervisor Resource</h2>
<p><code>type: CCI.Supervisor.Resource</code>. Any Kubernetes object in the namespace,
described by <code>manifest</code>. Every workload item that follows is this type with
<code>apiVersion</code> and <code>kind</code> filled in, so everything here applies to them.</p>
<table>
	<thead>
			<tr>
					<th>Property</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>context</code></td>
					<td><strong>Required.</strong> <code>${resource.&lt;namespace&gt;.id}</code>.</td>
			</tr>
			<tr>
					<td><code>manifest</code></td>
					<td><strong>Required.</strong> The object: <code>apiVersion</code>, <code>kind</code>, <code>metadata</code>, <code>spec</code>. A change to <code>manifest</code> or <code>context</code> recreates the object.</td>
			</tr>
			<tr>
					<td><code>wait</code></td>
					<td>As above.</td>
			</tr>
			<tr>
					<td><code>existing</code></td>
					<td><code>true</code> adopts an object that already exists.</td>
			</tr>
			<tr>
					<td><code>object</code></td>
					<td>Computed: the live object.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (18)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>wait</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{fields: [{path: status.powerState, value: PoweredOn}], ...}</code></td>
					<td>resource yaml</td>
			</tr>
			<tr>
					<td><code>wait.fields</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{path: status.powerState, value: PoweredOn}]</code></td>
					<td>List of fields for whose value needs to be waited for resource to be finished</td>
			</tr>
			<tr>
					<td><code>wait.fields[].path</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>status.powerState</code></td>
					<td>The path of the field within the Kubernetes resource</td>
			</tr>
			<tr>
					<td><code>wait.fields[].value</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>PoweredOn</code></td>
					<td>The value that needs to be met for the wait to be finished.</td>
			</tr>
			<tr>
					<td><code>wait.fields[].indicatesFailure</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>When the condition is met, indicates failure if set to true</td>
			</tr>
			<tr>
					<td><code>wait.conditions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{type: VirtualMachineGuestNetworkConfigSynced, status: True}]</code></td>
					<td>List of conditions that indicate success/failure of resource</td>
			</tr>
			<tr>
					<td><code>wait.conditions[].type</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>VirtualMachineGuestNetworkConfigSynced</code></td>
					<td>The condition type for which to wait</td>
			</tr>
			<tr>
					<td><code>wait.conditions[].reason</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;condition reason&gt;</code></td>
					<td>The condition reason for which to wait</td>
			</tr>
			<tr>
					<td><code>wait.conditions[].status</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>True</code></td>
					<td>The value of the condition that needs to be met</td>
			</tr>
			<tr>
					<td><code>wait.conditions[].indicatesFailure</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>When the condition is met, indicates failure if set to true</td>
			</tr>
			<tr>
					<td><code>wait.executionLogs</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{failureMessagePattern: (?i)error, progressMessagePattern: (?i)creating}</code></td>
					<td>The message to fetch from the logs while the resource is being created. This is only supported for Kubernetes Jobs.</td>
			</tr>
			<tr>
					<td><code>wait.executionLogs.failureMessagePattern</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>(?i)error</code></td>
					<td>The message pattern to check for to fail the resource creation. If the message is found in the logs, the resource creation will be marked as failed.</td>
			</tr>
			<tr>
					<td><code>wait.executionLogs.progressMessagePattern</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>(?i)creating</code></td>
					<td>The message pattern to check for to indicate that the resource creation is in progress. If the message is found in the logs, it will be shown as part of the deployment.</td>
			</tr>
			<tr>
					<td><code>wait.skipWaitOnDelete</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>If false, do not wait for resources to be gone before completing</td>
			</tr>
			<tr>
					<td><code>count</code></td>
					<td>integer</td>
					<td></td>
					<td>default <code>1</code></td>
					<td>The number of resource instances to be created.</td>
			</tr>
			<tr>
					<td><code>context</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>${resource.namespace.id}</code></td>
					<td>The CCI.Supervisor.Namespace resource id</td>
			</tr>
			<tr>
					<td><code>existing</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Use existing supervisor namespace</td>
			</tr>
			<tr>
					<td><code>manifest</code></td>
					<td>object</td>
					<td>yes</td>
					<td>e.g. <code>{apiVersion: vmoperator.vmware.com/v1alpha5, kind: VirtualMachine, spec: ...}</code></td>
					<td>The yaml representation of the Kubernetes resource</td>
			</tr>
	</tbody>
</table>

</details></p>

<p>Recipe, a kind the palette doesn&rsquo;t have. Our labs carry three VLANs over one
trunk subnet with binding maps:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">bmMgmt</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Resource</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">context</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.namespace.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">manifest</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">crd.nsx.vmware.com/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">SubnetConnectionBindingMap</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">bm-mgmt}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">spec</span><span class="p">:</span><span class="w"> </span>{<span class="nt">subnetName</span><span class="p">:</span><span class="w"> </span><span class="nt">sn-mgmt, targetSubnetName</span><span class="p">:</span><span class="w"> </span><span class="nt">sn-trunk, vlanTrafficTag</span><span class="p">:</span><span class="w"> </span><span class="m">1610</span>}<span class="w">
</span></span></span></code></pre></div><p>On the 9.1 Supervisor the namespace&rsquo;s API also offers, among others,
<code>VirtualMachineReplicaSet</code>, <code>VirtualMachineSnapshot</code>, <code>VirtualMachineImage</code>,
<code>SubnetSet</code>, <code>ConfigMap</code> and, with Avi, the Gateway API kinds.</p>
<p><strong>Gotchas</strong></p>
<ul>
<li><code>manifest</code> can be a string as well as a map. Our generator writes one per
host as a string, because a VM with optional sections is easier to build as
text: <code>manifest: &quot;${...}&quot;</code> works as long as the expression returns valid
YAML.</li>
<li>Broadcom&rsquo;s day-2 page warns that bindings don&rsquo;t work for Supervisor
Resources in day-2 operations; a day-2 action has to take the resource as
an input.</li>
</ul>
<h2 id="virtual-machine">Virtual Machine</h2>
<p><code>CCI.Supervisor.Resource</code> with <code>apiVersion: vmoperator.vmware.com/v1alpha5</code>,
<code>kind: VirtualMachine</code>. A VM Service VM: built from a VM class (CPU, memory,
devices) and an image, and configured on first boot by cloud-init, Sysprep,
LinuxPrep or vApp properties.</p>
<p>The most used fields; the complete list of 266 follows.</p>
<table>
	<thead>
			<tr>
					<th><code>spec</code> field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>className</code></td>
					<td>The VM class. Changing it later resizes the VM.</td>
			</tr>
			<tr>
					<td><code>imageName</code></td>
					<td>The image: its resource name (<code>vmi-0f0136a489b21d06c</code>) or its display name (<code>ubuntu-24.04-server-cloudimg-amd64</code>), if that is unique among the namespace&rsquo;s and the cluster&rsquo;s images.</td>
			</tr>
			<tr>
					<td><code>storageClass</code></td>
					<td>The storage class for the VM&rsquo;s disks.</td>
			</tr>
			<tr>
					<td><code>powerState</code></td>
					<td><code>PoweredOn</code> (default), <code>PoweredOff</code>, <code>Suspended</code>.</td>
			</tr>
			<tr>
					<td><code>guestID</code></td>
					<td>The guest OS identifier. <strong>Required when the VM has a CD-ROM.</strong> Immutable while powered on.</td>
			</tr>
			<tr>
					<td><code>network</code></td>
					<td><code>hostName</code>, <code>domainName</code>, <code>nameservers</code>, <code>searchDomains</code>, <code>disabled</code>, and <code>interfaces[]</code>: <code>name</code> (required), <code>network</code> (a Subnet or SubnetSet), <code>addresses[]</code>, <code>gateway4</code>, <code>dhcp4</code>, <code>mtu</code>, <code>routes[]</code>, <code>nameservers[]</code>, <code>searchDomains[]</code>, <code>guestDeviceName</code>, <code>macAddr</code>. Without <code>interfaces</code>, the VM joins the namespace&rsquo;s default network.</td>
			</tr>
			<tr>
					<td><code>bootstrap</code></td>
					<td>One of <code>cloudInit</code> (inline <code>cloudConfig</code>, <code>rawCloudConfig</code> from a Secret, <code>sshAuthorizedKeys</code>), <code>sysprep</code> (inline or <code>rawSysprep</code> from a Secret), <code>linuxPrep</code> (<code>timeZone</code>, <code>hardwareClockIsUTC</code>, <code>password</code>, <code>scriptText</code>), <code>vAppConfig</code> (<code>properties</code>, <code>rawProperties</code>).</td>
			</tr>
			<tr>
					<td><code>volumes[]</code></td>
					<td>Extra disks from Persistent Volume Claims: <code>name</code>, <code>persistentVolumeClaim.claimName</code>, and per volume <code>controllerType</code> (<code>SCSI</code> default, <code>NVME</code>, <code>SATA</code>, <code>IDE</code>), <code>controllerBusNumber</code>, <code>unitNumber</code>, <code>diskMode</code>, <code>sharingMode</code>, <code>applicationType</code>, <code>removable</code>.</td>
			</tr>
			<tr>
					<td><code>hardware</code></td>
					<td><code>cdrom[]</code> (an ISO image, <code>connected</code>, <code>allowGuestControl</code>) and the controllers: <code>scsiControllers[]</code>, <code>nvmeControllers[]</code>, <code>sataControllers[]</code>, <code>ideControllers[]</code>.</td>
			</tr>
			<tr>
					<td><code>advanced</code></td>
					<td><code>bootDiskCapacity</code>, <code>defaultVolumeProvisioningMode</code> (<code>Thin</code>, <code>Thick</code>, <code>ThickEagerZero</code>), <code>changeBlockTracking</code>.</td>
			</tr>
			<tr>
					<td><code>promoteDisksMode</code></td>
					<td><code>Online</code> (default), <code>Offline</code>, <code>Disabled</code>. See the gotchas.</td>
			</tr>
			<tr>
					<td><code>bootOptions</code></td>
					<td><code>firmware</code> (<code>bios</code>, <code>efi</code>: lower case, whatever the designer suggests), <code>efiSecureBoot</code>, <code>bootOrder</code>, <code>bootDelay</code>, <code>bootRetry</code>, <code>bootRetryDelay</code>, <code>networkBootProtocol</code>.</td>
			</tr>
			<tr>
					<td><code>readinessProbe</code></td>
					<td><code>tcpSocket.port</code>, <code>guestHeartbeat.thresholdStatus</code>, or <code>guestInfo[]</code>, with <code>periodSeconds</code> and <code>timeoutSeconds</code>.</td>
			</tr>
			<tr>
					<td><code>affinity</code></td>
					<td><code>vmAffinity</code> and <code>vmAntiAffinity</code>, each <code>requiredDuringSchedulingPreferredDuringExecution</code> (must hold) or <code>preferredDuringSchedulingPreferredDuringExecution</code> (best effort): a <code>labelSelector</code> and a <code>topologyKey</code>. Needs <code>groupName</code>.</td>
			</tr>
			<tr>
					<td><code>groupName</code></td>
					<td>The Virtual Machine Group the VM belongs to; the group then places it.</td>
			</tr>
			<tr>
					<td><code>crypto</code></td>
					<td><code>encryptionClassName</code>, <code>useDefaultKeyProvider</code> (default <code>true</code>), <code>vTPMMode</code>.</td>
			</tr>
			<tr>
					<td><code>minHardwareVersion</code></td>
					<td>A floor for the virtual hardware version: NVMe needs 14 or later.</td>
			</tr>
			<tr>
					<td><code>nextRestartTime</code></td>
					<td>Set to <code>now</code> to restart the VM, per <code>restartMode</code>.</td>
			</tr>
			<tr>
					<td><code>powerOffMode</code>, <code>suspendMode</code>, <code>restartMode</code></td>
					<td><code>TrySoft</code> (default), <code>Soft</code>, <code>Hard</code>.</td>
			</tr>
			<tr>
					<td><code>currentSnapshotName</code>, <code>policies[]</code>, <code>biosUUID</code>, <code>instanceUUID</code></td>
					<td>Revert to a snapshot, attach policies, pin identifiers.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (266)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>spec.advanced</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{bootDiskCapacity: 40Gi, defaultVolumeProvisioningMode: Thin}</code></td>
					<td>Advanced describes a set of optional, advanced VM configuration options.</td>
			</tr>
			<tr>
					<td><code>spec.advanced.bootDiskCapacity</code></td>
					<td>int or string</td>
					<td></td>
					<td>e.g. <code>40Gi</code></td>
					<td>BootDiskCapacity is the capacity of the VM&rsquo;s boot disk &ndash; the first disk from the VirtualMachineImage from which the VM was deployed.</td>
			</tr>
			<tr>
					<td><code>spec.advanced.changeBlockTracking</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>ChangeBlockTracking is a flag that enables incremental backup support for this VM, a feature utilized by external backup systems such as VMware Data Recovery.</td>
			</tr>
			<tr>
					<td><code>spec.advanced.defaultVolumeProvisioningMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>Thin</code>, <code>Thick</code>, <code>ThickEagerZero</code></td>
					<td>DefaultVolumeProvisioningMode specifies the default provisioning mode for persistent volumes managed by this VM.</td>
			</tr>
			<tr>
					<td><code>spec.affinity</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{vmAntiAffinity: {preferredDuringSchedulingPreferredDuringExecution: [{topologyKey: , ...}]}}</code></td>
					<td>Affinity describes the VM&rsquo;s scheduling constraints.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{preferredDuringSchedulingPreferredDuringExecution: [{labelSelector: {matchLabels: {, ...}}}]}</code></td>
					<td>VMAffinity describes affinity scheduling rules related to other VMs.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.preferredDuringSchedulingPreferredDuringExecution</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{labelSelector: {matchLabels: {app: web}}, topologyKey: kubernetes.io/hostname}]</code></td>
					<td>PreferredDuringSchedulingPreferredDuringExecution describes affinity requirements that should be met, but the VM can still be scheduled if the requirement cannot be satisfied.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{matchLabels: {app: web}}</code></td>
					<td>LabelSelector is a label query over a set of VMs. When omitted, this term matches with no VMs.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: app, operator: In}]</code></td>
					<td>matchExpressions is a list of label selector requirements. The requirements are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>app</code></td>
					<td>key is the label key that the selector applies to.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].operator</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>In</code></td>
					<td>operator represents a key&rsquo;s relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].values</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[web]</code></td>
					<td>values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector.matchLabels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{app: web}</code></td>
					<td>matchLabels is a map of {key,value} pairs.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.preferredDuringSchedulingPreferredDuringExecution[].topologyKey</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>kubernetes.io/hostname</code></td>
					<td>TopologyKey describes where this VM should be co-located (affinity) or not co-located (anti-affinity).</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.requiredDuringSchedulingPreferredDuringExecution</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{labelSelector: {matchLabels: {app: web}}, topologyKey: kubernetes.io/hostname}]</code></td>
					<td>RequiredDuringSchedulingPreferredDuringExecution describes affinity requirements that must be met or the VM will not be scheduled.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{matchLabels: {app: web}}</code></td>
					<td>LabelSelector is a label query over a set of VMs. When omitted, this term matches with no VMs.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: app, operator: In}]</code></td>
					<td>matchExpressions is a list of label selector requirements. The requirements are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>app</code></td>
					<td>key is the label key that the selector applies to.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].operator</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>In</code></td>
					<td>operator represents a key&rsquo;s relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].values</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[web]</code></td>
					<td>values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector.matchLabels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{app: web}</code></td>
					<td>matchLabels is a map of {key,value} pairs.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAffinity.requiredDuringSchedulingPreferredDuringExecution[].topologyKey</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>kubernetes.io/hostname</code></td>
					<td>TopologyKey describes where this VM should be co-located (affinity) or not co-located (anti-affinity).</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{preferredDuringSchedulingPreferredDuringExecution: [{topologyKey: kubernetes.io/hos, ...}]}</code></td>
					<td>VMAntiAffinity describes anti-affinity scheduling rules related to other VMs.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.preferredDuringSchedulingPreferredDuringExecution</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{topologyKey: kubernetes.io/hostname, labelSelector: {matchLabels: {app: web}}}]</code></td>
					<td>PreferredDuringSchedulingPreferredDuringExecution describes anti-affinity requirements that should be met, but the VM can still be scheduled if the requirement cannot be satisfied.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{matchLabels: {app: web}}</code></td>
					<td>LabelSelector is a label query over a set of VMs. When omitted, this term matches with no VMs.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: app, operator: In}]</code></td>
					<td>matchExpressions is a list of label selector requirements. The requirements are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>app</code></td>
					<td>key is the label key that the selector applies to.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].operator</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>In</code></td>
					<td>operator represents a key&rsquo;s relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].values</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[web]</code></td>
					<td>values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.preferredDuringSchedulingPreferredDuringExecution[].labelSelector.matchLabels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{app: web}</code></td>
					<td>matchLabels is a map of {key,value} pairs.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.preferredDuringSchedulingPreferredDuringExecution[].topologyKey</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>kubernetes.io/hostname</code></td>
					<td>TopologyKey describes where this VM should be co-located (affinity) or not co-located (anti-affinity).</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.requiredDuringSchedulingPreferredDuringExecution</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{labelSelector: {matchLabels: {app: web}}, topologyKey: kubernetes.io/hostname}]</code></td>
					<td>RequiredDuringSchedulingPreferredDuringExecution describes anti-affinity requirements that must be met or the VM will not be scheduled.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{matchLabels: {app: web}}</code></td>
					<td>LabelSelector is a label query over a set of VMs. When omitted, this term matches with no VMs.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: app, operator: In}]</code></td>
					<td>matchExpressions is a list of label selector requirements. The requirements are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>app</code></td>
					<td>key is the label key that the selector applies to.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].operator</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>In</code></td>
					<td>operator represents a key&rsquo;s relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector.matchExpressions[].values</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[web]</code></td>
					<td>values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.requiredDuringSchedulingPreferredDuringExecution[].labelSelector.matchLabels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{app: web}</code></td>
					<td>matchLabels is a map of {key,value} pairs.</td>
			</tr>
			<tr>
					<td><code>spec.affinity.vmAntiAffinity.requiredDuringSchedulingPreferredDuringExecution[].topologyKey</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>kubernetes.io/hostname</code></td>
					<td>TopologyKey describes where this VM should be co-located (affinity) or not co-located (anti-affinity).</td>
			</tr>
			<tr>
					<td><code>spec.biosUUID</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>4210d2a5-6d0e-4f6e-9c3a-0b1f2e3d4c5b</code></td>
					<td>BiosUUID describes the desired BIOS UUID for a VM. If omitted, this field defaults to a random UUID.</td>
			</tr>
			<tr>
					<td><code>spec.bootOptions</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{bootDelay: 5s, bootOrder: [{name: &lt;device name&gt;, type: Disk}]}</code></td>
					<td>BootOptions describes the settings that control the boot behavior of the virtual machine. These settings take effect during the next power-on of the virtual machine.</td>
			</tr>
			<tr>
					<td><code>spec.bootOptions.bootDelay</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>5s</code></td>
					<td>BootDelay is the delay before starting the boot sequence. The boot delay specifies a time interval between virtual machine power on or restart and the beginning of the boot sequence.</td>
			</tr>
			<tr>
					<td><code>spec.bootOptions.bootOrder</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: &lt;device name&gt;, type: Disk}]</code></td>
					<td>BootOrder represents the boot order of the virtual machine. After list is exhausted, default BIOS boot device algorithm is used for booting.</td>
			</tr>
			<tr>
					<td><code>spec.bootOptions.bootOrder[].name</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;device name&gt;</code></td>
					<td>Name represents the name of the bootable device. It is required for Disk and Network device types, while ignored for CDRom device types.</td>
			</tr>
			<tr>
					<td><code>spec.bootOptions.bootOrder[].type</code></td>
					<td>string</td>
					<td>yes</td>
					<td><code>Disk</code>, <code>Network</code>, <code>CDRom</code></td>
					<td>Type represents the type of bootable device. The available device types are: - Disk - Network - CDRom</td>
			</tr>
			<tr>
					<td><code>spec.bootOptions.bootRetry</code></td>
					<td>string</td>
					<td></td>
					<td>default <code>Disabled</code></td>
					<td>BootRetry specifies whether a virtual machine that fails to boot will try again.</td>
			</tr>
			<tr>
					<td><code>spec.bootOptions.bootRetryDelay</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10s</code></td>
					<td>BootRetryDelay specifies a time interval between virtual machine boot failure and the subsequent attempt to boot again.</td>
			</tr>
			<tr>
					<td><code>spec.bootOptions.efiSecureBoot</code></td>
					<td>string</td>
					<td></td>
					<td><code>Enabled</code>, <code>Disabled</code>; default <code>Disabled</code></td>
					<td>EFISecureBoot specifies whether the virtual machine&rsquo;s firmware will perform signature checks of any EFI images loaded during startup.</td>
			</tr>
			<tr>
					<td><code>spec.bootOptions.firmware</code></td>
					<td>string</td>
					<td></td>
					<td><code>bios</code>, <code>efi</code></td>
					<td>Firmware represents the firmware for the virtual machine to use. Any update to this value after the virtual machine has already been created will be ignored.</td>
			</tr>
			<tr>
					<td><code>spec.bootOptions.networkBootProtocol</code></td>
					<td>string</td>
					<td></td>
					<td><code>IP4</code>, <code>IP6</code>; default <code>IP4</code></td>
					<td>NetworkBootProtocol is the protocol to attempt during PXE network boot or NetBoot. The available protocols are: - IP4 &ndash; PXE (or Apple NetBoot) over IPv4.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{cloudInit: {cloudConfig: {timezone: Europe/London, users: [{name: ops, ...}]}}}</code></td>
					<td>Bootstrap describes the desired state of the guest&rsquo;s bootstrap configuration. If omitted, a default bootstrap method may be selected based on the guest OS identifier.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{cloudConfig: {timezone: Europe/London, users: [{name: ops, ...}]}}</code></td>
					<td>CloudInit may be used to bootstrap Linux guests with Cloud-Init or Windows guests that support Cloudbase-Init.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{timezone: Europe/London, users: [{name: ops, hashed_passwd: {key: ops-passwd, ...}}]}</code></td>
					<td>CloudConfig describes a subset of a Cloud-Init CloudConfig, used to bootstrap the VM.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.defaultUserEnabled</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>DefaultUserEnabled may be set to true to ensure even if the Users field is not empty, the default user is still created on systems that have one defined.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.runcmd</code></td>
					<td>any</td>
					<td></td>
					<td>e.g. <code>[systemctl enable --now nginx]</code></td>
					<td>RunCmd allows running one or more commands on the guest. The entries in this list can adhere to two, different formats: Format 1 &ndash; a string that contains the command and its arguments, ex.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.ssh_pwauth</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>SSHPwdAuth sets whether or not to accept password authentication. In order for this config to be applied, SSH may need to be restarted.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.timezone</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>Europe/London</code></td>
					<td>Timezone describes the timezone represented in /usr/share/zoneinfo.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: ops, hashed_passwd: {key: ops-passwd, name: web-pw}}]</code></td>
					<td>Users allows adding/configuring one or more users on the guest.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].create_groups</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>CreateGroups is a flag that may be set to false to disable creation of specified user groups. Defaults to true when Name is not &ldquo;default&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].expiredate</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>2027-01-01</code></td>
					<td>ExpireData is the date on which the user&rsquo;s account will be disabled.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].gecos</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>Operations user</code></td>
					<td>Gecos is an optional comment about the user, usually a comma-separated string of the user&rsquo;s real name and contact information.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].groups</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[sudo]</code></td>
					<td>Groups is an optional list of groups to add to the user.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].hashed_passwd</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{key: ops-passwd, name: web-pw}</code></td>
					<td>HashedPasswd is a hash of the user&rsquo;s password that will be applied even if the specified user already exists.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].hashed_passwd.key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>ops-passwd</code></td>
					<td>Key is the key in the secret that specifies the requested data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].hashed_passwd.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>web-pw</code></td>
					<td>Name is the name of the secret.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].homedir</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>/home/ops</code></td>
					<td>Homedir is the optional home directory for the user. Defaults to &ldquo;/home/<!-- raw HTML omitted -->&rdquo; when Name is not &ldquo;default&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].inactive</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>30</code></td>
					<td>Inactive optionally represents the number of days until the user is disabled.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].lock_passwd</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>false</code></td>
					<td>LockPasswd disables password login. Defaults to true when Name is not &ldquo;default&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>ops</code></td>
					<td>Name is the user&rsquo;s login name. When set to &ldquo;default&rdquo;, all other fields from this User must be nil.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].no_create_home</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>NoCreateHome prevents the creation of the home directory. Defaults to false when Name is not &ldquo;default&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].no_log_init</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>NoLogInit prevents the initialization of lastlog and faillog for the user. Defaults to false when Name is not &ldquo;default&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].no_user_group</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>NoUserGroup prevents the creation of the group named after the user. Defaults to false when Name is not &ldquo;default&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].passwd</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{key: &lt;key in the Secret&gt;, name: &lt;Secret name&gt;}</code></td>
					<td>Passwd is a hash of the user&rsquo;s password that will be applied only to a newly created user. To apply a new, hashed password to an existing user please use HashedPasswd instead.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].passwd.key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;key in the Secret&gt;</code></td>
					<td>Key is the key in the secret that specifies the requested data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].passwd.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret name&gt;</code></td>
					<td>Name is the name of the secret.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].primary_group</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>ops</code></td>
					<td>PrimaryGroup is the primary group for the user. Defaults to the value of the Name field when it is not &ldquo;default&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].selinux_user</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>staff_u</code></td>
					<td>SELinuxUser is the SELinux user for the user&rsquo;s login.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].shell</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>/bin/bash</code></td>
					<td>Shell is the path to the user&rsquo;s login shell.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].snapuser</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>ops@example.com</code></td>
					<td>SnapUser specifies an e-mail address to create the user as a Snappy user through &ldquo;snap create-user&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].ssh_authorized_keys</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOkJfr8Q3cNq ops@example]</code></td>
					<td>SSHAuthorizedKeys is a list of SSH keys to add to the user&rsquo;s authorized keys file.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].ssh_import_id</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[gh:octocat]</code></td>
					<td>SSHImportID is a list of SSH IDs to import for the user.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].ssh_redirect_user</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>SSHRedirectUser may be set to true to disable SSH logins for this user. Any SSH login as this user will timeout with a message to login instead as the default user.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].sudo</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>ALL=(ALL) NOPASSWD:ALL</code></td>
					<td>Sudo is a sudo rule to apply to the user. When omitted, no sudo rules will be applied to the user.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].system</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>System is an optional flag that indicates the user should be created as a system user with no home directory. Defaults to false when Name is not &ldquo;default&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.users[].uid</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>1001</code></td>
					<td>UID is the user&rsquo;s ID. When omitted the guest will default to the next available number.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.write_files</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{path: /etc/nginx/conf.d/lab.conf, content: server_tokens off;}]</code></td>
					<td>WriteFiles allows adding files to the guest file system.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.write_files[].append</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>Append specifies whether or not to append the content to an existing file if the file specified by Path already exists.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.write_files[].content</code></td>
					<td>any</td>
					<td></td>
					<td>e.g. <code>server_tokens off;</code></td>
					<td>Content is the optional content to write to the provided Path. When omitted an empty file will be created or existing file will be modified.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.write_files[].defer</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>Defer indicates to defer writing the file until Cloud-Init&rsquo;s &ldquo;final&rdquo; stage, after users are created and packages are installed.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.write_files[].encoding</code></td>
					<td>string</td>
					<td></td>
					<td><code>b64</code>, <code>base64</code>, <code>gz</code>, <code>gzip</code>, <code>gz+b64</code>, <code>gz+base64</code>, <code>gzip+b64</code>, <code>gzip+base64</code>, <code>text/plain</code>; default <code>text/plain</code></td>
					<td>Encoding is an optional encoding type of the content.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.write_files[].owner</code></td>
					<td>string</td>
					<td></td>
					<td>default <code>root:root</code></td>
					<td>Owner is an optional &ldquo;owner:group&rdquo; to chown the file.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.write_files[].path</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>/etc/nginx/conf.d/lab.conf</code></td>
					<td>Path is the path of the file to which the content is decoded and written.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.cloudConfig.write_files[].permissions</code></td>
					<td>string</td>
					<td></td>
					<td>default <code>0644</code></td>
					<td>Permissions an optional set of file permissions to set. &ldquo;0###&rdquo;. When omitted the guest will default this value to &ldquo;0644&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.instanceID</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>web-01-v2</code></td>
					<td>InstanceID is the cloud-init metadata instance ID. If omitted, this field defaults to the VM&rsquo;s BiosUUID.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.rawCloudConfig</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{key: user-data, name: jump-bootstrap}</code></td>
					<td>RawCloudConfig describes a key in a Secret resource that contains the CloudConfig data used to bootstrap the VM.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.rawCloudConfig.key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>user-data</code></td>
					<td>Key is the key in the secret that specifies the requested data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.rawCloudConfig.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>jump-bootstrap</code></td>
					<td>Name is the name of the secret.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.sshAuthorizedKeys</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[ssh-ed25519 AAAA... ops@admin]</code></td>
					<td>SSHAuthorizedKeys is a list of public keys that CloudInit will apply to the guest&rsquo;s default user.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.useGlobalNameserversAsDefault</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>UseGlobalNameserversAsDefault will use the global nameservers specified in the NetworkSpec as the per-interface nameservers when the per-interface nameservers is not provided.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.useGlobalSearchDomainsAsDefault</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>UseGlobalSearchDomainsAsDefault will use the global search domains specified in the NetworkSpec as the per-interface search domains when the per-interface search domains is not provided.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.waitOnNetwork4</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>WaitOnNetwork4 indicates whether the cloud-init datasource should wait for an IPv4 address to be available before writing the instance-data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.cloudInit.waitOnNetwork6</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>WaitOnNetwork6 indicates whether the cloud-init datasource should wait for an IPv6 address to be available before writing the instance-data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{password: {name: &lt;Secret name&gt;, key: password}, ...}</code></td>
					<td>LinuxPrep may be used to bootstrap Linux guests. The guest&rsquo;s networking stack is configured by Guest OS Customization (GOSC).</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.customizeAtNextPowerOn</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>CustomizeAtNextPowerOn describes when customization is performed on the VM. When set to false, the VM will not be customized at the next power on.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.expirePasswordAfterNextLogin</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>ExpirePasswordAfterNextLogin indicates whether or not the root account is required to change their password after the next login.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.hardwareClockIsUTC</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>HardwareClockIsUTC specifies whether the hardware clock is in UTC or local time.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.password</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{name: &lt;Secret name&gt;, key: password}</code></td>
					<td>Password is the new root password for the machine. When not explicitly specified, the Key field for the selector defaults to <code>password</code>.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.password.key</code></td>
					<td>string</td>
					<td></td>
					<td>default <code>password</code></td>
					<td>Key is the key in the secret that specifies the requested data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.password.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret name&gt;</code></td>
					<td>Name is the name of the secret.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.scriptText</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{from: {key: &lt;key in the Secret&gt;, name: &lt;Secret name&gt;}, value: '#!/bin/sh ...'}</code></td>
					<td>ScriptText is the script to run before and after customization. Please see <a href="https://knowledge.broadcom.com/external/article?legacyId=1026614">https://knowledge.broadcom.com/external/article?legacyId=1026614</a> for script examples.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.scriptText.from</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{key: &lt;key in the Secret&gt;, name: &lt;Secret name&gt;}</code></td>
					<td>From is specified to reference a value from a Secret resource.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.scriptText.from.key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;key in the Secret&gt;</code></td>
					<td>Key is the key in the secret that specifies the requested data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.scriptText.from.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret name&gt;</code></td>
					<td>Name is the name of the secret.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.scriptText.value</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>'#!/bin/sh ...'</code></td>
					<td>Value is used to directly specify a value.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.linuxPrep.timeZone</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>Europe/London</code></td>
					<td>TimeZone is a case-sensitive timezone, such as Europe/Sofia. Valid values are based on the tz (timezone) database used by Linux and other Unix systems.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{rawSysprep: {key: &lt;key in the Secret&gt;, name: &lt;Secret name&gt;}, ...}</code></td>
					<td>Sysprep may be used to bootstrap Windows guests. The guest&rsquo;s networking stack is configured by Guest OS Customization (GOSC).</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.customizeAtNextPowerOn</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>CustomizeAtNextPowerOn describes when customization is performed on the VM. When set to false, the VM will not be customized at the next power on.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.rawSysprep</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{key: &lt;key in the Secret&gt;, name: &lt;Secret name&gt;}</code></td>
					<td>RawSysprep describes a key in a Secret resource that contains an XML string of the Sysprep text used to bootstrap the VM.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.rawSysprep.key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;key in the Secret&gt;</code></td>
					<td>Key is the key in the secret that specifies the requested data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.rawSysprep.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret name&gt;</code></td>
					<td>Name is the name of the secret.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{guiRunOnce: {commands: [powershell -File C:\setup.ps1]}, ...}</code></td>
					<td>Sysprep is an object representation of a Windows sysprep.xml answer file. This field encloses all the individual keys listed in a sysprep.xml file.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.expirePasswordAfterNextLogin</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>ExpirePasswordAfterNextLogin indicates whether or not the local Administrators group accounts are required to change their password after the next login.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.guiRunOnce</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{commands: [powershell -File C:\setup.ps1]}</code></td>
					<td>GUIRunOnce is a representation of the Sysprep GuiRunOnce key.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.guiRunOnce.commands</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[powershell -File C:\setup.ps1]</code></td>
					<td>Commands is a list of commands to run at first user logon, after guest customization.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.guiUnattended</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{autoLogonCount: 1, password: {name: &lt;Secret name&gt;, key: password}}</code></td>
					<td>GUIUnattended is a representation of the Sysprep GUIUnattended key.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.guiUnattended.autoLogon</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>AutoLogon determine whether the machine automatically logs on as Administrator.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.guiUnattended.autoLogonCount</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>1</code></td>
					<td>AutoLogonCount specifies the number of times the machine should automatically log on as Administrator.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.guiUnattended.password</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{name: &lt;Secret name&gt;, key: password}</code></td>
					<td>Password is the new administrator password for the machine. To specify that the password should be set to blank (that is, no password), set the password value to NULL.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.guiUnattended.password.key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>default <code>password</code></td>
					<td>Key is the key in the secret that specifies the requested data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.guiUnattended.password.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret name&gt;</code></td>
					<td>Name is the name of the secret.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.guiUnattended.timeZone</code></td>
					<td>integer</td>
					<td></td>
					<td>default <code>85</code></td>
					<td>TimeZone is the time zone index for the virtual machine.ly/3Rzv8oL. Defaults to UTC.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.identification</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{domainAdmin: svc-join@example.local, domainAdminPassword: {name: &lt;Secret name&gt;, ...}}</code></td>
					<td>Identification is a representation of the Sysprep Identification key.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.identification.domainAdmin</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>svc-join@example.local</code></td>
					<td>DomainAdmin is the domain user account used for authentication if the virtual machine is joining a domain.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.identification.domainAdminPassword</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{name: &lt;Secret name&gt;, key: domain_admin_password}</code></td>
					<td>DomainAdminPassword is the password for the domain user account used for authentication if the virtual machine is joining a domain.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.identification.domainAdminPassword.key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>default <code>domain_admin_password</code></td>
					<td>Key is the key in the secret that specifies the requested data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.identification.domainAdminPassword.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret name&gt;</code></td>
					<td>Name is the name of the secret.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.identification.domainOU</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>OU=Servers,DC=example,DC=local</code></td>
					<td>DomainOU is the MachineObjectOU which specifies the full LDAP path name of the OU to which the computer belongs.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.identification.joinWorkgroup</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>WORKGROUP</code></td>
					<td>JoinWorkgroup is the workgroup that the virtual machine should join.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.licenseFilePrintData</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{autoUsers: 5, autoMode: perSeat}</code></td>
					<td>LicenseFilePrintData is a representation of the Sysprep LicenseFilePrintData key.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.licenseFilePrintData.autoMode</code></td>
					<td>string</td>
					<td>yes</td>
					<td><code>perSeat</code>, <code>perServer</code></td>
					<td>AutoMode specifies the server licensing mode.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.licenseFilePrintData.autoUsers</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>5</code></td>
					<td>AutoUsers indicates the number of client licenses purchased for the VirtualCenter server being installed.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.scriptText</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{from: {key: &lt;key in the Secret&gt;, name: &lt;Secret name&gt;}, ...}</code></td>
					<td>ScriptText describes the script to run before and after customization. The script must be a Windows batch file.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.scriptText.from</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{key: &lt;key in the Secret&gt;, name: &lt;Secret name&gt;}</code></td>
					<td>From is specified to reference a value from a Secret resource.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.scriptText.from.key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;key in the Secret&gt;</code></td>
					<td>Key is the key in the secret that specifies the requested data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.scriptText.from.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret name&gt;</code></td>
					<td>Name is the name of the secret.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.scriptText.value</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>powershell -File C:\setup.ps1</code></td>
					<td>Value is used to directly specify a value.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.userData</code></td>
					<td>object</td>
					<td>yes</td>
					<td>e.g. <code>{fullName: Lab Admin, orgName: Example Ltd}</code></td>
					<td>UserData is a representation of the Sysprep UserData key.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.userData.fullName</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>Lab Admin</code></td>
					<td>FullName is the user&rsquo;s full name.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.userData.orgName</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>Example Ltd</code></td>
					<td>OrgName is the name of the user&rsquo;s organization.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.userData.productID</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{name: &lt;Secret name&gt;, key: product_id}</code></td>
					<td>ProductID is a valid serial number. When not explicitly specified, the Key field for the selector defaults to <code>domain_admin_password</code>.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.userData.productID.key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>default <code>product_id</code></td>
					<td>Key is the key in the secret that specifies the requested data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.sysprep.sysprep.userData.productID.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret name&gt;</code></td>
					<td>Name is the name of the secret.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.vAppConfig</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{properties: [{key: guestinfo.hostname, value: {from: {key: &lt;key in the Secret&gt;, ...}}}]}</code></td>
					<td>VAppConfig may be used to bootstrap guests that rely on vApp properties (how VMware surfaces OVF properties on guests) to transport data into the guest.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.vAppConfig.properties</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: guestinfo.hostname, value: {from: {key: &lt;key in the Secret&gt;, ...}}}]</code></td>
					<td>Properties is a list of vApp/OVF property key/value pairs.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.vAppConfig.properties[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>guestinfo.hostname</code></td>
					<td>Key is the key part of the key/value pair.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.vAppConfig.properties[].value</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{from: {key: &lt;key in the Secret&gt;, name: &lt;Secret name&gt;}, value: web-01}</code></td>
					<td>Value is the optional value part of the key/value pair.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.vAppConfig.properties[].value.from</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{key: &lt;key in the Secret&gt;, name: &lt;Secret name&gt;}</code></td>
					<td>From is specified to reference a value from a Secret resource.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.vAppConfig.properties[].value.from.key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;key in the Secret&gt;</code></td>
					<td>Key is the key in the secret that specifies the requested data.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.vAppConfig.properties[].value.from.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret name&gt;</code></td>
					<td>Name is the name of the secret.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.vAppConfig.properties[].value.value</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>web-01</code></td>
					<td>Value is used to directly specify a value.</td>
			</tr>
			<tr>
					<td><code>spec.bootstrap.vAppConfig.rawProperties</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;ConfigMap with the OVF properties&gt;</code></td>
					<td>RawProperties is the name of a Secret resource in the same Namespace as this VM where each key/value pair from the Secret is used as a vApp key/value pair.</td>
			</tr>
			<tr>
					<td><code>spec.class</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{kind: VirtualMachineClass, name: best-effort-small}</code></td>
					<td>Class describes the VirtualMachineClassInstance resource that is referenced by this virtual machine.</td>
			</tr>
			<tr>
					<td><code>spec.class.apiVersion</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>vmoperator.vmware.com/v1alpha5</code></td>
					<td>APIVersion defines the versioned schema of this representation of an object.</td>
			</tr>
			<tr>
					<td><code>spec.class.kind</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>VirtualMachineClass</code></td>
					<td>Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to.</td>
			</tr>
			<tr>
					<td><code>spec.class.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>best-effort-small</code></td>
					<td>Name refers to a unique resource in the current namespace.</td>
			</tr>
			<tr>
					<td><code>spec.className</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>best-effort-small</code></td>
					<td>ClassName describes the name of the VirtualMachineClass resource used to deploy this VM.</td>
			</tr>
			<tr>
					<td><code>spec.crypto</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{encryptionClassName: &lt;encryption class&gt;, useDefaultKeyProvider: true}</code></td>
					<td>Crypto describes the desired encryption state of the VirtualMachine.</td>
			</tr>
			<tr>
					<td><code>spec.crypto.encryptionClassName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;encryption class&gt;</code></td>
					<td>EncryptionClassName describes the name of the EncryptionClass resource used to encrypt this VM.</td>
			</tr>
			<tr>
					<td><code>spec.crypto.useDefaultKeyProvider</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>true</code></td>
					<td>UseDefaultKeyProvider describes the desired behavior for when an explicit EncryptionClass is not provided.</td>
			</tr>
			<tr>
					<td><code>spec.crypto.vTPMMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>Clone</code>, <code>New</code>; default <code>New</code></td>
					<td>VTPMMode describes the desired behavior when deploying a VirtualMachine using a VirtualMachine-backed image which created from an encrypted VirtualMachine with a vTPM.</td>
			</tr>
			<tr>
					<td><code>spec.currentSnapshotName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>before-upgrade</code></td>
					<td>CurrentSnapshotName represents the desired snapshot that the VM should point to. This field can be specified to revert the VM to a given snapshot.</td>
			</tr>
			<tr>
					<td><code>spec.groupName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>web</code></td>
					<td>GroupName indicates the name of the VirtualMachineGroup to which this VM belongs. VMs that belong to a group do not drive their own placement, rather that is handled by the group.</td>
			</tr>
			<tr>
					<td><code>spec.guestID</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>vmkernel9Guest</code></td>
					<td>GuestID describes the desired guest operating system identifier for a VM. The logic that determines the guest ID is as follows: If this field is set, then its value is used.</td>
			</tr>
			<tr>
					<td><code>spec.hardware</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{cdrom: [{name: cdrom0, image: {kind: VirtualMachineImage, ...}}]}</code></td>
					<td>Hardware describes the VM&rsquo;s desired hardware.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.cdrom</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: cdrom0, image: {kind: VirtualMachineImage, name: vmi-e400a813bbd5d52a5}}]</code></td>
					<td>Cdrom describes the desired state of the VM&rsquo;s CD-ROM devices. Each CD-ROM device requires a reference to an ISO-type VirtualMachineImage or ClusterVirtualMachineImage resource as backing.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.cdrom[].allowGuestControl</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>true</code></td>
					<td>AllowGuestControl describes whether or not a web console connection may be used to connect/disconnect the CD-ROM device.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.cdrom[].connected</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>true</code></td>
					<td>Connected describes the desired connection state of the CD-ROM device. When true, the CD-ROM device is added and connected to the VM.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.cdrom[].controllerBusNumber</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>0</code></td>
					<td>ControllerBusNumber describes the bus number of the controller to which this CD-ROM should be attached.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.cdrom[].controllerType</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>SATA</code></td>
					<td>ControllerType describes the type of the controller to which this CD-ROM should be attached.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.cdrom[].image</code></td>
					<td>object</td>
					<td>yes</td>
					<td>e.g. <code>{kind: VirtualMachineImage, name: vmi-e400a813bbd5d52a5}</code></td>
					<td>Image describes the reference to an ISO type VirtualMachineImage or ClusterVirtualMachineImage resource used as the backing for the CD-ROM.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.cdrom[].image.kind</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>VirtualMachineImage</code></td>
					<td>Kind describes the type of image, either a namespace-scoped VirtualMachineImage or cluster-scoped ClusterVirtualMachineImage.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.cdrom[].image.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>vmi-e400a813bbd5d52a5</code></td>
					<td>Name refers to the name of a VirtualMachineImage resource in the same namespace as this VM or a cluster-scoped ClusterVirtualMachineImage.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.cdrom[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>cdrom0</code></td>
					<td>Name consists of at least two lowercase letters or digits of this CD-ROM. It must be unique among all CD-ROM devices attached to the VM.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.cdrom[].unitNumber</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>1</code></td>
					<td>UnitNumber describes the desired unit number for attaching the CD-ROM to a storage controller. When omitted, the next available unit number of the selected controller is used.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.ideControllers</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{busNumber: 0}]</code></td>
					<td>IDEControllers describes the desired list of IDE controllers for the VM. Defaults to two IDE controllers, with bus 0 and bus 1.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.ideControllers[].busNumber</code></td>
					<td>integer</td>
					<td>yes</td>
					<td>e.g. <code>0</code></td>
					<td>BusNumber describes the desired bus number of the controller.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.nvmeControllers</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{busNumber: 0, sharingMode: None}]</code></td>
					<td>NVMEControllers describes the desired list of NVME controllers for the VM.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.nvmeControllers[].busNumber</code></td>
					<td>integer</td>
					<td>yes</td>
					<td>e.g. <code>0</code></td>
					<td>BusNumber describes the desired bus number of the controller.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.nvmeControllers[].sharingMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>None</code>, <code>Physical</code>; default <code>None</code></td>
					<td>SharingMode describes the sharing mode for the controller. Defaults to None.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.sataControllers</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{busNumber: 0}]</code></td>
					<td>SATAControllers describes the desired list of SATA controllers for the VM.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.sataControllers[].busNumber</code></td>
					<td>integer</td>
					<td>yes</td>
					<td>e.g. <code>0</code></td>
					<td>BusNumber describes the desired bus number of the controller.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.scsiControllers</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{busNumber: 0, type: ParaVirtual}]</code></td>
					<td>SCSIControllers describes the desired list of SCSI controllers for the VM.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.scsiControllers[].busNumber</code></td>
					<td>integer</td>
					<td>yes</td>
					<td>e.g. <code>0</code></td>
					<td>BusNumber describes the desired bus number of the controller.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.scsiControllers[].sharingMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>None</code>, <code>Physical</code>, <code>Virtual</code>; default <code>None</code></td>
					<td>SharingMode describes the sharing mode for the controller. Defaults to None.</td>
			</tr>
			<tr>
					<td><code>spec.hardware.scsiControllers[].type</code></td>
					<td>string</td>
					<td></td>
					<td><code>ParaVirtual</code>, <code>BusLogic</code>, <code>LsiLogic</code>, <code>LsiLogicSAS</code>; default <code>ParaVirtual</code></td>
					<td>Type describes the desired type of SCSI controller. Defaults to ParaVirtual.</td>
			</tr>
			<tr>
					<td><code>spec.image</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{kind: VirtualMachineImage, name: vmi-0123456789abcdef0}</code></td>
					<td>Image describes the reference to the VirtualMachineImage or ClusterVirtualMachineImage resource used to deploy this VM.imageName, the value of spec.image.name MUST be a Kubernetes object &hellip;</td>
			</tr>
			<tr>
					<td><code>spec.image.kind</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>VirtualMachineImage</code></td>
					<td>Kind describes the type of image, either a namespace-scoped VirtualMachineImage or cluster-scoped ClusterVirtualMachineImage.</td>
			</tr>
			<tr>
					<td><code>spec.image.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>vmi-0123456789abcdef0</code></td>
					<td>Name refers to the name of a VirtualMachineImage resource in the same namespace as this VM or a cluster-scoped ClusterVirtualMachineImage.</td>
			</tr>
			<tr>
					<td><code>spec.imageName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>ubuntu-24.04-server-cloudimg-amd64</code></td>
					<td>ImageName describes the name of the image resource used to deploy this VM. This field may be used to specify the name of a VirtualMachineImage or ClusterVirtualMachineImage resource.</td>
			</tr>
			<tr>
					<td><code>spec.instanceUUID</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>5010c9b4-1f2e-4d3c-8b7a-6e5f4d3c2b1a</code></td>
					<td>InstanceUUID describes the desired Instance UUID for a VM. If omitted, this field defaults to a random UUID. This value is only used for the VM Instance UUID, it is not used within cloudInit.</td>
			</tr>
			<tr>
					<td><code>spec.minHardwareVersion</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>21</code></td>
					<td>MinHardwareVersion describes the desired, minimum hardware version. The logic that determines the hardware version is as follows: 1.</td>
			</tr>
			<tr>
					<td><code>spec.network</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{hostName: dc01, interfaces: [{name: eth0, addresses: [172.30.0.34/27]}]}</code></td>
					<td>Network describes the desired network configuration for the VM.</td>
			</tr>
			<tr>
					<td><code>spec.network.disabled</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>Disabled is a flag that indicates whether or not to disable networking for this VM.</td>
			</tr>
			<tr>
					<td><code>spec.network.domainName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>lab.local</code></td>
					<td>DomainName describes the value the guest uses as its domain name.</td>
			</tr>
			<tr>
					<td><code>spec.network.hostName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>dc01</code></td>
					<td>HostName describes the value the guest uses as its host name. If omitted, the name of the VM will be used.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: eth0, addresses: [172.30.0.34/27]}]</code></td>
					<td>Interfaces is the list of network interfaces used by this VM. If the Interfaces field is empty and the Disabled field is false, then a default interface with the name eth0 will be created.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].addresses</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[172.30.0.34/27]</code></td>
					<td>Addresses is an optional list of IP4 or IP6 addresses to assign to this interface. 192.168.0.10/24 or 2001:db8:101::a/64.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].dhcp4</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>DHCP4 indicates whether or not this interface uses DHCP for IP4 networking.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].dhcp6</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>DHCP6 indicates whether or not this interface uses DHCP for IP6 networking.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].gateway4</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>172.30.0.33</code></td>
					<td>Gateway4 is the default, IP4 gateway for this interface. If unset, the gateway from the network provider will be used.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].gateway6</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>fd00::1</code></td>
					<td>Gateway6 is the primary IP6 gateway for this interface. If unset, the gateway from the network provider will be used.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].guestDeviceName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>eth0</code></td>
					<td>GuestDeviceName is used to rename the device inside the guest when the bootstrap provider is Cloud-Init. dvd, cdrom, sda, etc.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].macAddr</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>00:50:56:00:00:10</code></td>
					<td>MACAddr is the optional MAC address of this interface. If no MAC address is provided, one will be generated by either the network provider or vCenter.nsx.vmware.com.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].mtu</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>1500</code></td>
					<td>MTU is the Maximum Transmission Unit size in bytes.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>eth0</code></td>
					<td>Name describes the unique name of this network interface, used to distinguish it from other network interfaces attached to this VM.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].nameservers</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[172.30.0.34]</code></td>
					<td>Nameservers is a list of IP4 and/or IP6 addresses used as DNS nameservers.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].network</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{kind: Subnet, name: sn-mgmt}</code></td>
					<td>Network is the name of the network resource to which this interface is connected. If no network is provided, then this interface will be connected to the Namespace&rsquo;s default network.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].network.apiVersion</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>crd.nsx.vmware.com/v1alpha1</code></td>
					<td>APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].network.kind</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>Subnet</code></td>
					<td>Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].network.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>sn-mgmt</code></td>
					<td>Name refers to a unique resource in the current namespace.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].routes</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{to: 172.16.0.0/16, via: 10.200.0.1}]</code></td>
					<td>Routes is a list of optional, static routes.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].routes[].metric</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>100</code></td>
					<td>Metric is the weight/priority of the route.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].routes[].to</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>172.16.0.0/16</code></td>
					<td>To is either &ldquo;default&rdquo;, or an IP4 or IP6 address.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].routes[].via</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>10.200.0.1</code></td>
					<td>Via is an IP4 or IP6 address.</td>
			</tr>
			<tr>
					<td><code>spec.network.interfaces[].searchDomains</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[lab.local]</code></td>
					<td>SearchDomains is a list of search domains used when resolving IP addresses with DNS.</td>
			</tr>
			<tr>
					<td><code>spec.network.nameservers</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[10.200.0.2]</code></td>
					<td>Nameservers is a list of IP4 and/or IP6 addresses used as DNS nameservers. These are applied globally. The Cloud-Init bootstrap provider supports per-interface nameservers.</td>
			</tr>
			<tr>
					<td><code>spec.network.searchDomains</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[lab.local]</code></td>
					<td>SearchDomains is a list of search domains used when resolving IP addresses with DNS. These are applied globally. The Cloud-Init bootstrap provider supports per-interface search domains.</td>
			</tr>
			<tr>
					<td><code>spec.nextRestartTime</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>now</code></td>
					<td>NextRestartTime may be used to restart the VM, in accordance with RestartMode, by setting the value of this field to &ldquo;now&rdquo; (case-insensitive).</td>
			</tr>
			<tr>
					<td><code>spec.policies</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{kind: ComputePolicy, name: &lt;compute policy&gt;}]</code></td>
					<td>Policies describes a list of policies that should be explicitly applied to this VM. Please consult a policy to determine if it may be applied directly.</td>
			</tr>
			<tr>
					<td><code>spec.policies[].apiVersion</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>vsphere.policy.vmware.com/v1alpha1</code></td>
					<td>APIVersion defines the versioned schema of this representation of an object.</td>
			</tr>
			<tr>
					<td><code>spec.policies[].kind</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>ComputePolicy</code></td>
					<td>Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to.</td>
			</tr>
			<tr>
					<td><code>spec.policies[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;compute policy&gt;</code></td>
					<td>Name refers to a unique resource in the current namespace.</td>
			</tr>
			<tr>
					<td><code>spec.powerOffMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>Hard</code>, <code>Soft</code>, <code>TrySoft</code>; default <code>TrySoft</code></td>
					<td>PowerOffMode describes the desired behavior when powering off a VM. There are three, supported power off modes: Hard, Soft, and TrySoft.</td>
			</tr>
			<tr>
					<td><code>spec.powerState</code></td>
					<td>string</td>
					<td></td>
					<td><code>PoweredOff</code>, <code>PoweredOn</code>, <code>Suspended</code></td>
					<td>PowerState describes the desired power state of a VirtualMachine.&quot; However, once the field is set to a non-empty value, it may no longer be set to an empty value.</td>
			</tr>
			<tr>
					<td><code>spec.promoteDisksMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>Online</code>, <code>Offline</code>, <code>Disabled</code>; default <code>Online</code></td>
					<td>PromoteDisksMode describes the mode used to promote a VM&rsquo;s delta disks to full disks. The available modes are: - Disabled &ndash; Do not promote disks.</td>
			</tr>
			<tr>
					<td><code>spec.readinessProbe</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{guestInfo: [{key: guestinfo.ready, value: &quot;true&quot;}], tcpSocket: {host: 10.200.0.10, ...}}</code></td>
					<td>ReadinessProbe describes a probe used to determine the VM&rsquo;s ready state.</td>
			</tr>
			<tr>
					<td><code>spec.readinessProbe.guestHeartbeat</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{thresholdStatus: green}</code></td>
					<td>GuestHeartbeat specifies an action involving the guest heartbeat status.</td>
			</tr>
			<tr>
					<td><code>spec.readinessProbe.guestHeartbeat.thresholdStatus</code></td>
					<td>string</td>
					<td></td>
					<td><code>yellow</code>, <code>green</code>; default <code>green</code></td>
					<td>ThresholdStatus is the value that the guest heartbeat status must be at or above to be considered successful.</td>
			</tr>
			<tr>
					<td><code>spec.readinessProbe.guestInfo</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: guestinfo.ready, value: &quot;true&quot;}]</code></td>
					<td>GuestInfo specifies an action involving key/value pairs from GuestInfo.</td>
			</tr>
			<tr>
					<td><code>spec.readinessProbe.guestInfo[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>guestinfo.ready</code></td>
					<td>Key is the name of the GuestInfo key. The key is automatically prefixed with &ldquo;guestinfo.&rdquo; before being evaluated.</td>
			</tr>
			<tr>
					<td><code>spec.readinessProbe.guestInfo[].value</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&quot;true&quot;</code></td>
					<td>Value is a regular expression that is matched against the value of the specified key. An empty value is the equivalent of &ldquo;match any&rdquo; or &ldquo;.*&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.readinessProbe.periodSeconds</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>10</code></td>
					<td>PeriodSeconds specifics how often (in seconds) to perform the probe. Defaults to 10 seconds. Minimum value is 1.</td>
			</tr>
			<tr>
					<td><code>spec.readinessProbe.tcpSocket</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{host: 10.200.0.10, port: 22}</code></td>
					<td>TCPSocket specifies an action involving a TCP port. Deprecated: The TCPSocket action requires network connectivity that is not supported in all environments.</td>
			</tr>
			<tr>
					<td><code>spec.readinessProbe.tcpSocket.host</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10.200.0.10</code></td>
					<td>Host is an optional host name to connect to. Host defaults to the VM IP.</td>
			</tr>
			<tr>
					<td><code>spec.readinessProbe.tcpSocket.port</code></td>
					<td>int or string</td>
					<td>yes</td>
					<td>e.g. <code>22</code></td>
					<td>Port specifies a number or name of the port to access on the VM. If the format of port is a number, it must be in the range 1 to 65535.</td>
			</tr>
			<tr>
					<td><code>spec.readinessProbe.timeoutSeconds</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>10</code></td>
					<td>TimeoutSeconds specifies a number of seconds after which the probe times out. Defaults to 10 seconds. Minimum value is 1.</td>
			</tr>
			<tr>
					<td><code>spec.reserved</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{resourcePolicyName: &lt;resource policy&gt;}</code></td>
					<td>Reserved describes a set of VM configuration options reserved for system use.</td>
			</tr>
			<tr>
					<td><code>spec.reserved.resourcePolicyName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;resource policy&gt;</code></td>
					<td></td>
			</tr>
			<tr>
					<td><code>spec.restartMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>Hard</code>, <code>Soft</code>, <code>TrySoft</code>; default <code>TrySoft</code></td>
					<td>RestartMode describes the desired behavior for restarting a VM when spec.nextRestartTime is set to &ldquo;now&rdquo; (case-insensitive).</td>
			</tr>
			<tr>
					<td><code>spec.storageClass</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>vsan-default-storage-policy</code></td>
					<td>StorageClass describes the name of a Kubernetes StorageClass resource used to configure this VM&rsquo;s storage-related attributes.</td>
			</tr>
			<tr>
					<td><code>spec.suspendMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>Hard</code>, <code>Soft</code>, <code>TrySoft</code>; default <code>TrySoft</code></td>
					<td>SuspendMode describes the desired behavior when suspending a VM. There are three, supported suspend modes: Hard, Soft, and TrySoft.</td>
			</tr>
			<tr>
					<td><code>spec.volumes</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: data, persistentVolumeClaim: {claimName: web-01-data, ...}}]</code></td>
					<td>Volumes describes a list of volumes that can be mounted to the VM.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].applicationType</code></td>
					<td>string</td>
					<td></td>
					<td><code>OracleRAC</code>, <code>MicrosoftWSFC</code></td>
					<td>ApplicationType describes the type of application for which this volume is intended to be used.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].controllerBusNumber</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>0</code></td>
					<td>ControllerBusNumber describes the bus number of the controller to which this volume should be attached.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].controllerType</code></td>
					<td>string</td>
					<td></td>
					<td><code>IDE</code>, <code>NVME</code>, <code>SCSI</code>, <code>SATA</code></td>
					<td>ControllerType describes the type of the controller to which this volume should be attached.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].diskMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>IndependentNonPersistent</code>, <code>IndependentPersistent</code>, <code>NonPersistent</code>, <code>Persistent</code></td>
					<td>DiskMode describes the desired mode to use when attaching the volume.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>data</code></td>
					<td>Name represents the volume&rsquo;s name. Must be a DNS_LABEL and unique within the VM.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].persistentVolumeClaim</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{claimName: web-01-data, instanceVolumeClaim: {size: 50Gi, ...}}</code></td>
					<td>PersistentVolumeClaim represents a reference to a PersistentVolumeClaim in the same namespace.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].persistentVolumeClaim.claimName</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>web-01-data</code></td>
					<td>claimName is the name of a PersistentVolumeClaim in the same namespace as the pod using this volume.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].persistentVolumeClaim.instanceVolumeClaim</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{size: 50Gi, storageClass: vsan-default-storage-policy}</code></td>
					<td>InstanceVolumeClaim is set if the PVC is backed by instance storage.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].persistentVolumeClaim.instanceVolumeClaim.size</code></td>
					<td>int or string</td>
					<td>yes</td>
					<td>e.g. <code>50Gi</code></td>
					<td>Size is the size of the requested instance storage volume.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].persistentVolumeClaim.instanceVolumeClaim.storageClass</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>vsan-default-storage-policy</code></td>
					<td>StorageClass is the name of the Kubernetes StorageClass that provides the backing storage for this instance storage volume.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].persistentVolumeClaim.readOnly</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>readOnly Will force the ReadOnly setting in VolumeMounts. Default false.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].removable</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>true</code></td>
					<td>Removable describes whether or not this volume may be removed from spec.volumes.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].sharingMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>MultiWriter</code>, <code>None</code></td>
					<td>SharingMode describes the volume&rsquo;s desired sharing mode. When applicationType=OracleRAC, this field defaults to MultiWriter.</td>
			</tr>
			<tr>
					<td><code>spec.volumes[].unitNumber</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>1</code></td>
					<td>UnitNumber describes the desired unit number for attaching the volume to a storage controller. When omitted, the next available unit number of the selected controller is used.</td>
			</tr>
	</tbody>
</table>

</details></p>

<p>Minimal:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">vm1</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Resource</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">context</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.namespace.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">manifest</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">vmoperator.vmware.com/v1alpha5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">VirtualMachine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">web-01</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">labels</span><span class="p">:</span><span class="w"> </span>{<span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">web}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">className</span><span class="p">:</span><span class="w"> </span><span class="l">best-effort-small</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">imageName</span><span class="p">:</span><span class="w"> </span><span class="l">ubuntu-24.04-server-cloudimg-amd64</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">storageClass</span><span class="p">:</span><span class="w"> </span><span class="l">vsan-default-storage-policy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">wait</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">VirtualMachineGuestNetworkConfigSynced</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">status</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;True&#34;</span><span class="w">
</span></span></span></code></pre></div><p><strong>Recipes</strong></p>
<ul>
<li>
<p><em>A Linux user with an SSH key and a password</em>, inline cloud-init. The
password is <strong>not</strong> a string here: <code>passwd</code> and <code>hashed_passwd</code> reference
a key in a Secret, and a plain string fails with <code>cannot restore struct from: string</code>. The hash can come from <a href="#utilpasswordentry">Util.PasswordEntry</a>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">        </span><span class="nt">bootstrap</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">cloudInit</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">cloudConfig</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">users</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">ops</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span><span class="nt">sudo</span><span class="p">:</span><span class="w"> </span><span class="l">ALL=(ALL) NOPASSWD:ALL</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span><span class="nt">lock_passwd</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span><span class="nt">hashed_passwd</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">web-pw         </span><span class="w"> </span><span class="c"># a Secret in the namespace</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">ops-passwd      </span><span class="w"> </span><span class="c"># holding ${resource.pw.sha512crypt}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span><span class="nt">ssh_authorized_keys</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span>- <span class="l">ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOkJfr8Q3cNq ops@example</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">runcmd</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span>- <span class="p">[</span><span class="l">systemctl, enable, --now, ssh]</span><span class="w">
</span></span></span></code></pre></div><p>We logged in through a load balancer as <code>ops</code> with that key; <code>sudo</code> needed
no password and the shadow entry held the <code>$6$</code> hash.</p>
</li>
<li>
<p><em>Windows, or a long first-boot script:</em> keep the whole cloud-config in a
Secret and point <code>rawCloudConfig</code> at it. Our jump hosts run cloudbase-init
this way:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">        </span><span class="nt">bootstrap</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">cloudInit</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">rawCloudConfig</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">jump-bootstrap    </span><span class="w"> </span><span class="c"># the Secret</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">key</span><span class="p">:</span><span class="w"> </span><span class="l">user-data          </span><span class="w"> </span><span class="c"># the key inside it</span><span class="w">
</span></span></span></code></pre></div></li>
<li>
<p><em>A static address on a VPC subnet.</em> With cloud-init the DNS servers go on
the interface:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">        </span><span class="nt">network</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">hostName</span><span class="p">:</span><span class="w"> </span><span class="l">dc01</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">interfaces</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">eth0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">network</span><span class="p">:</span><span class="w"> </span>{<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="nt">crd.nsx.vmware.com/v1alpha1, kind</span><span class="p">:</span><span class="w"> </span><span class="nt">Subnet, name</span><span class="p">:</span><span class="w"> </span><span class="l">sn-mgmt}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">addresses</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;172.30.0.34/27&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">gateway4</span><span class="p">:</span><span class="w"> </span><span class="m">172.30.0.33</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">nameservers</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="m">172.30.0.34</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">bootstrap</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">cloudInit</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">rawCloudConfig</span><span class="p">:</span><span class="w"> </span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="nt">dc-bootstrap, key</span><span class="p">:</span><span class="w"> </span><span class="l">user-data}</span><span class="w">
</span></span></span></code></pre></div></li>
<li>
<p><em>An address on a subnet without choosing it:</em> name the subnet and leave
<code>addresses</code> out. VM Operator takes one from the subnet and configures the
guest; ours got <code>172.30.0.2</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">        </span><span class="nt">network</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">interfaces</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">eth0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">network</span><span class="p">:</span><span class="w"> </span>{<span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="nt">crd.nsx.vmware.com/v1alpha1, kind</span><span class="p">:</span><span class="w"> </span><span class="nt">Subnet, name</span><span class="p">:</span><span class="w"> </span><span class="l">sn-app}</span><span class="w">
</span></span></span></code></pre></div></li>
<li>
<p><em>An extra data disk:</em> a Persistent Volume Claim in the same blueprint, then
the VM below. It arrived in the guest as <code>sdb</code>, 5 GiB, beside the image&rsquo;s
10 GiB <code>sda</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">        </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">data</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">persistentVolumeClaim</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">claimName</span><span class="p">:</span><span class="w"> </span><span class="l">web-01-data</span><span class="w">
</span></span></span></code></pre></div></li>
<li>
<p><em>An ISO in the CD-ROM</em>, for an installer (our nested hosts boot the ESXi
installer this way). <code>guestID</code> becomes mandatory:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">        </span><span class="nt">guestID</span><span class="p">:</span><span class="w"> </span><span class="l">vmkernel9Guest</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">hardware</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">cdrom</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">cdrom0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span>{<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="nt">VirtualMachineImage, name</span><span class="p">:</span><span class="w"> </span><span class="l">vmi-e400a813bbd5d52a5}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">connected</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">allowGuestControl</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span></code></pre></div></li>
<li>
<p><em>A bigger boot disk than the image&rsquo;s:</em> <code>advanced.bootDiskCapacity: 80Gi</code>.
The guest still has to grow its partition.</p>
</li>
<li>
<p><em>Keep VMs apart.</em> Affinity rules only work for members of a
<a href="#virtual-machine-group">Virtual Machine Group</a>; on a VM without
<code>groupName</code> the Supervisor refuses them (<code>spec.groupName: Required value: when setting affinity</code>). Our two web VMs with this rule landed on
different hosts:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">        </span><span class="nt">groupName</span><span class="p">:</span><span class="w"> </span><span class="l">web</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">affinity</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">vmAntiAffinity</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">preferredDuringSchedulingPreferredDuringExecution</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span>- <span class="nt">labelSelector</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span><span class="nt">matchLabels</span><span class="p">:</span><span class="w"> </span>{<span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">web}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">topologyKey</span><span class="p">:</span><span class="w"> </span><span class="l">kubernetes.io/hostname</span><span class="w">
</span></span></span></code></pre></div></li>
</ul>
<p><strong>Status worth reading:</strong> <code>status.network.primaryIP4</code> (after the wait above),
<code>status.powerState</code>, <code>status.nodeName</code> (the ESXi host), <code>status.zone</code>,
<code>status.instanceUUID</code>, <code>status.biosUUID</code>, <code>status.hardwareVersion</code>, and
<code>status.volumes[]</code> with <code>attached</code> per disk.</p>
<p><strong>Gotchas</strong></p>
<ul>
<li>DNS settings depend on the bootstrap provider: <code>spec.network.nameservers</code>
works only with LinuxPrep and Sysprep, the per-interface <code>nameservers</code> only
with CloudInit and Sysprep, and a VM with no bootstrap can have neither.
The Supervisor says which: <code>nameservers is available only with the following bootstrap providers: ...</code>.</li>
<li><code>promoteDisksMode</code> defaults to <code>Online</code>: after a fast deploy from a linked
clone, VM Operator copies the disks into full disks while the VM runs. For
a large image that is real I/O; <code>Disabled</code> keeps the linked clone and
deploys faster. Our Windows jump host was ready in 15.1 minutes with
<code>Disabled</code> against 17.6 with the default. VMs with snapshots cannot
promote online.</li>
<li>The first deployment of a new image into a VPC can fail with an NSX
<code>503638</code> error while the image is still being cached; a retry succeeds.</li>
<li>Changing <code>className</code> resizes the VM; changing <code>manifest</code> in a new blueprint
version recreates it.</li>
</ul>
<h2 id="virtual-machine-group">Virtual Machine Group</h2>
<p><code>CCI.Supervisor.Resource</code> with <code>apiVersion: vmoperator.vmware.com/v1alpha5</code>,
<code>kind: VirtualMachineGroup</code>. A set of VMs placed and powered as one: a boot
order with delays between steps, and one power state for all of them.</p>
<table>
	<thead>
			<tr>
					<th><code>spec</code> field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>bootOrder[]</code></td>
					<td>Steps, in order. Each has <code>members[]</code> (<code>kind</code>: <code>VirtualMachine</code> default or <code>VirtualMachineGroup</code>; <code>name</code>) and <code>powerOnDelay</code> before the step.</td>
			</tr>
			<tr>
					<td><code>powerState</code></td>
					<td><code>PoweredOn</code> (default), <code>PoweredOff</code>, <code>Suspended</code>, applied to every member.</td>
			</tr>
			<tr>
					<td><code>powerOffMode</code>, <code>suspendMode</code></td>
					<td><code>TrySoft</code> (default), <code>Soft</code>, <code>Hard</code>.</td>
			</tr>
			<tr>
					<td><code>groupName</code></td>
					<td>A parent group, to nest groups.</td>
			</tr>
			<tr>
					<td><code>nextForcePowerStateSyncTime</code></td>
					<td><code>now</code> pushes the group&rsquo;s power state to every member again.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (10)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>spec.bootOrder</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{members: [{name: web-01, kind: VirtualMachine}], powerOnDelay: 30s}]</code></td>
					<td>BootOrder describes the boot sequence for this group members. Each boot order contains a set of members that will be powered on simultaneously, with an optional delay before powering on.</td>
			</tr>
			<tr>
					<td><code>spec.bootOrder[].members</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: web-01, kind: VirtualMachine}]</code></td>
					<td>Members describes the names of VirtualMachine or VirtualMachineGroup objects that are members of this boot order group.</td>
			</tr>
			<tr>
					<td><code>spec.bootOrder[].members[].kind</code></td>
					<td>string</td>
					<td></td>
					<td><code>VirtualMachine</code>, <code>VirtualMachineGroup</code>; default <code>VirtualMachine</code></td>
					<td>Kind is the kind of member of this group, which can be either VirtualMachine or VirtualMachineGroup. If omitted, it defaults to VirtualMachine.</td>
			</tr>
			<tr>
					<td><code>spec.bootOrder[].members[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>web-01</code></td>
					<td>Name is the name of member of this group.</td>
			</tr>
			<tr>
					<td><code>spec.bootOrder[].powerOnDelay</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>30s</code></td>
					<td>PowerOnDelay is the amount of time to wait before powering on all the members of this boot order group.</td>
			</tr>
			<tr>
					<td><code>spec.groupName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;parent group&gt;</code></td>
					<td>GroupName describes the name of the group that this group belongs to.</td>
			</tr>
			<tr>
					<td><code>spec.nextForcePowerStateSyncTime</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>now</code></td>
					<td>NextForcePowerStateSyncTime may be used to force sync the power state of the group to all of its members, by setting the value of this field to &ldquo;now&rdquo; (case-insensitive).</td>
			</tr>
			<tr>
					<td><code>spec.powerOffMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>Hard</code>, <code>Soft</code>, <code>TrySoft</code></td>
					<td>PowerOffMode describes the desired behavior when powering off a VM Group. Refer to the VirtualMachine.PowerOffMode field for more details.</td>
			</tr>
			<tr>
					<td><code>spec.powerState</code></td>
					<td>string</td>
					<td></td>
					<td><code>PoweredOff</code>, <code>PoweredOn</code>, <code>Suspended</code></td>
					<td>PowerState describes the desired power state of a VirtualMachineGroup.</td>
			</tr>
			<tr>
					<td><code>spec.suspendMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>Hard</code>, <code>Soft</code>, <code>TrySoft</code></td>
					<td>SuspendMode describes the desired behavior when suspending a VM Group. Refer to the VirtualMachine.SuspendMode field for more details.</td>
			</tr>
	</tbody>
</table>

</details></p>

<p>Recipe, one VM before the next, thirty seconds apart:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">appGroup</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Resource</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">context</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.namespace.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">manifest</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">vmoperator.vmware.com/v1alpha5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">VirtualMachineGroup</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">app}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">bootOrder</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">members</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">web-01}]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- <span class="nt">members</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">web-02}]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">powerOnDelay</span><span class="p">:</span><span class="w"> </span><span class="l">30s</span><span class="w">
</span></span></span></code></pre></div><p>Each member names the group in <code>spec.groupName: app</code> and depends on the group
resource (<code>dependsOn: [appGroup]</code>), because the group is referenced only by
name.</p>
<p><strong>Status worth reading:</strong> <code>status.members[]</code> (each member&rsquo;s power state and
placement), <code>status.conditions</code>.</p>
<p><strong>Gotchas</strong></p>
<ul>
<li>A member of a later step stays off until every member of the earlier steps
is on. When our first test&rsquo;s <code>web-01</code> failed to create, <code>web-02</code> sat
powered off for good.</li>
<li>A VM in a group doesn&rsquo;t place itself; the group places its members.</li>
</ul>
<h2 id="virtual-machine-service">Virtual Machine Service</h2>
<p><code>CCI.Supervisor.Resource</code> with <code>apiVersion: vmoperator.vmware.com/v1alpha5</code>,
<code>kind: VirtualMachineService</code>. A Kubernetes-style service in front of VMs,
selected by label. With <code>type: LoadBalancer</code>, the VPC&rsquo;s load balancer gives
it an external address. That&rsquo;s how a VM on a private subnet is reached from
outside.</p>
<table>
	<thead>
			<tr>
					<th><code>spec</code> field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>type</code></td>
					<td><strong>Required.</strong> <code>LoadBalancer</code> or <code>ClusterIP</code>. The API lists <code>ExternalName</code> too; the VM Operator documentation says it isn&rsquo;t supported.</td>
			</tr>
			<tr>
					<td><code>selector</code></td>
					<td>Labels of the VMs behind it.</td>
			</tr>
			<tr>
					<td><code>ports[]</code></td>
					<td><code>name</code>, <code>port</code>, <code>targetPort</code>, <code>protocol</code> (<code>TCP</code>, <code>UDP</code>, <code>SCTP</code>).</td>
			</tr>
			<tr>
					<td><code>loadBalancerSourceRanges[]</code></td>
					<td>Source CIDRs allowed to reach a <code>LoadBalancer</code> service.</td>
			</tr>
			<tr>
					<td><code>loadBalancerIP</code>, <code>clusterIp</code>, <code>externalName</code></td>
					<td>A requested address, a fixed cluster IP, a DNS name.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (11)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>spec.clusterIp</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10.96.0.20</code></td>
					<td>ClusterIP is the IP address of the service and is usually assigned randomly by the master.</td>
			</tr>
			<tr>
					<td><code>spec.externalName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>web.example.com</code></td>
					<td>ExternalName is the external reference that kubedns or equivalent will return as a CNAME record for this service. No proxying will be involved.</td>
			</tr>
			<tr>
					<td><code>spec.loadBalancerIP</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>192.168.144.20</code></td>
					<td>LoadBalancer will get created with the IP specified in this field.</td>
			</tr>
			<tr>
					<td><code>spec.loadBalancerSourceRanges</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[10.0.0.0/8]</code></td>
					<td>LoadBalancerSourceRanges is an array of IP addresses in the format of CIDRs, for example: 103.21.244.0/22 and 10.0.0.0/24.</td>
			</tr>
			<tr>
					<td><code>spec.ports</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: rdp, port: 3389}]</code></td>
					<td>Ports specifies a list of VirtualMachineServicePort to expose with this VirtualMachineService. Each of these ports will be an accessible network entry point to access this service by.</td>
			</tr>
			<tr>
					<td><code>spec.ports[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>rdp</code></td>
					<td>Name describes the name to be used to identify this VirtualMachineServicePort.</td>
			</tr>
			<tr>
					<td><code>spec.ports[].port</code></td>
					<td>integer</td>
					<td>yes</td>
					<td>e.g. <code>3389</code></td>
					<td>Port describes the external port that will be exposed by the service.</td>
			</tr>
			<tr>
					<td><code>spec.ports[].protocol</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>TCP</code></td>
					<td>Protocol describes the Layer 4 transport protocol for this port. Supports &ldquo;TCP&rdquo;, &ldquo;UDP&rdquo;, and &ldquo;SCTP&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.ports[].targetPort</code></td>
					<td>integer</td>
					<td>yes</td>
					<td>e.g. <code>3389</code></td>
					<td>TargetPort describes the internal port open on a VirtualMachine that should be mapped to the external Port.</td>
			</tr>
			<tr>
					<td><code>spec.selector</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{app: web}</code></td>
					<td>Selector specifies a map of key-value pairs, also known as a Label Selector, that is used to match this VirtualMachineService with the set of VirtualMachines that should back this VirtualMachineService.</td>
			</tr>
			<tr>
					<td><code>spec.type</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>LoadBalancer</code></td>
					<td>Type specifies a desired VirtualMachineServiceType for this VirtualMachineService. Supported types are ClusterIP, LoadBalancer, ExternalName.</td>
			</tr>
	</tbody>
</table>

</details></p>

<p>Recipe, RDP to a jump host, the only way into our labs:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">jumpAccess</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Resource</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">context</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.namespace.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">manifest</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">vmoperator.vmware.com/v1alpha5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">VirtualMachineService</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">jump-access}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">LoadBalancer</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">selector</span><span class="p">:</span><span class="w"> </span>{<span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l">jump}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">ports</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span>- {<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="nt">rdp, port</span><span class="p">:</span><span class="w"> </span><span class="nt">3389, targetPort</span><span class="p">:</span><span class="w"> </span><span class="nt">3389, protocol</span><span class="p">:</span><span class="w"> </span><span class="l">TCP}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">loadBalancerSourceRanges</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="m">10.0.0.0</span><span class="l">/8]</span><span class="w">
</span></span></span></code></pre></div><p><strong>Status worth reading:</strong> <code>status.loadBalancer.ingress[0].ip</code>, the external
address.</p>
<p><strong>Gotchas</strong></p>
<ul>
<li><code>LoadBalancer</code> needs the VPC&rsquo;s load balancer. VCF Automation waits for the
address by itself, so in a VPC without one the request stays in progress
until it times out. A VPC made by a blueprint never has one; see <a href="#vpc">VPC</a>.</li>
<li>A service with several VMs behind it spreads connections across them: our
SSH sessions alternated between the two web VMs.</li>
<li>The palette writes <code>v1alpha3</code>; we use <code>v1alpha5</code>, the Supervisor&rsquo;s stored
version. Both are served.</li>
</ul>
<h2 id="subnet">Subnet</h2>
<p><code>CCI.Supervisor.Resource</code> with <code>apiVersion: crd.nsx.vmware.com/v1alpha1</code>,
<code>kind: Subnet</code>. A subnet of the namespace&rsquo;s VPC: a layer-2 segment with its
own address range, for VMs that need a network of their own.</p>
<table>
	<thead>
			<tr>
					<th><code>spec</code> field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>accessMode</code></td>
					<td><code>Private</code> (default): routed inside the VPC only. <code>PrivateTGW</code>: reachable from other VPCs through the transit gateway. <code>Public</code>: from the external network.</td>
			</tr>
			<tr>
					<td><code>ipv4SubnetSize</code></td>
					<td>Addresses in the subnet, default 64.</td>
			</tr>
			<tr>
					<td><code>ipAddresses[]</code></td>
					<td>Specific CIDRs instead of a size.</td>
			</tr>
			<tr>
					<td><code>subnetDHCPConfig.mode</code></td>
					<td><code>DHCPDeactivated</code> (default), <code>DHCPServer</code>, <code>DHCPRelay</code>; <code>dhcpServerAdditionalConfig.reservedIPRanges</code> keeps ranges out of the pool.</td>
			</tr>
			<tr>
					<td><code>advancedConfig</code></td>
					<td><code>staticIPAllocation.enabled</code>, <code>connectivityState</code> (<code>Connected</code> default, <code>Disconnected</code>), <code>gatewayAddresses</code>, <code>dhcpServerAddresses</code>.</td>
			</tr>
			<tr>
					<td><code>vpcName</code></td>
					<td>The VPC, when it isn&rsquo;t the namespace&rsquo;s own.</td>
			</tr>
			<tr>
					<td><code>vlanConnectionName</code></td>
					<td>A subnet backed by a distributed VLAN connection; not in the designer&rsquo;s form.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (15)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>spec.accessMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>Private</code>, <code>Public</code>, <code>PrivateTGW</code>, <code>L2Only</code></td>
					<td>Access mode of Subnet, accessible only from within VPC or from outside VPC.</td>
			</tr>
			<tr>
					<td><code>spec.advancedConfig</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{dhcpServerAddresses: [10.200.0.2/28], gatewayAddresses: [10.200.0.1/28]}</code></td>
					<td>VPC Subnet advanced configuration.</td>
			</tr>
			<tr>
					<td><code>spec.advancedConfig.connectivityState</code></td>
					<td>string</td>
					<td></td>
					<td><code>Connected</code>, <code>Disconnected</code>; default <code>Connected</code></td>
					<td>Connectivity status of the Subnet from other Subnets of the VPC. The default value is &ldquo;Connected&rdquo;.</td>
			</tr>
			<tr>
					<td><code>spec.advancedConfig.dhcpServerAddresses</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[10.200.0.2/28]</code></td>
					<td>DHCPServerAddresses specifies custom DHCP server IP addresses for the Subnet.</td>
			</tr>
			<tr>
					<td><code>spec.advancedConfig.gatewayAddresses</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[10.200.0.1/28]</code></td>
					<td>GatewayAddresses specifies custom gateway IP addresses for the Subnet.</td>
			</tr>
			<tr>
					<td><code>spec.advancedConfig.staticIPAllocation</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{enabled: true}</code></td>
					<td>Static IP allocation for VPC Subnet Ports.</td>
			</tr>
			<tr>
					<td><code>spec.advancedConfig.staticIPAllocation.enabled</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>Activate or deactivate static IP allocation for VPC Subnet Ports. If the DHCP mode is DHCPDeactivated or not set, its default value is true.</td>
			</tr>
			<tr>
					<td><code>spec.ipAddresses</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[10.200.0.0/28]</code></td>
					<td>Subnet CIDRS.</td>
			</tr>
			<tr>
					<td><code>spec.ipv4SubnetSize</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>32</code></td>
					<td>Size of Subnet based upon estimated workload count.</td>
			</tr>
			<tr>
					<td><code>spec.subnetDHCPConfig</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{dhcpServerAdditionalConfig: {reservedIPRanges: [10.200.0.10-10.200.0.15]}, ...}</code></td>
					<td>DHCP configuration for Subnet.</td>
			</tr>
			<tr>
					<td><code>spec.subnetDHCPConfig.dhcpServerAdditionalConfig</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{reservedIPRanges: [10.200.0.10-10.200.0.15]}</code></td>
					<td>Additional DHCP server config for a VPC Subnet.</td>
			</tr>
			<tr>
					<td><code>spec.subnetDHCPConfig.dhcpServerAdditionalConfig.reservedIPRanges</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[10.200.0.10-10.200.0.15]</code></td>
					<td>Reserved IP ranges. Supported formats include: [&ldquo;192.168.1.1&rdquo;, &ldquo;192.168.1.3-192.168.1.100&rdquo;]</td>
			</tr>
			<tr>
					<td><code>spec.subnetDHCPConfig.mode</code></td>
					<td>string</td>
					<td></td>
					<td><code>DHCPServer</code>, <code>DHCPRelay</code>, <code>DHCPDeactivated</code></td>
					<td>DHCP Mode. DHCPDeactivated will be used if it is not defined. It cannot switch from DHCPDeactivated to DHCPServer or DHCPRelay.</td>
			</tr>
			<tr>
					<td><code>spec.vlanConnectionName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;distributed VLAN connection&gt;</code></td>
					<td>Distributed VLAN Connection name.</td>
			</tr>
			<tr>
					<td><code>spec.vpcName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>${resource.vpc.name}</code></td>
					<td>VPC name of the Subnet.</td>
			</tr>
	</tbody>
</table>

</details></p>

<p>Minimal, our lab&rsquo;s management subnet:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">snMgmt</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Resource</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">context</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.namespace.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">manifest</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">crd.nsx.vmware.com/v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Subnet</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">sn-mgmt}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">spec</span><span class="p">:</span><span class="w"> </span>{<span class="nt">accessMode</span><span class="p">:</span><span class="w"> </span><span class="nt">Private, ipv4SubnetSize</span><span class="p">:</span><span class="w"> </span><span class="m">32</span>}<span class="w">
</span></span></span></code></pre></div><p>A VM joins it by name, in an interface:
<code>network: {apiVersion: crd.nsx.vmware.com/v1alpha1, kind: Subnet, name: sn-mgmt}</code>.</p>
<p><strong>Status worth reading:</strong> <code>status.networkAddresses</code>, <code>status.gatewayAddresses</code>,
<code>status.conditions</code> (<code>Realized</code>).</p>
<p><strong>Gotchas</strong></p>
<ul>
<li>DHCP is off by default. VMs still get addresses: VM Operator takes one
from the subnet and hands it to the guest through the bootstrap provider.</li>
<li>Subnets are NSX objects of the VPC. After a deployment is deleted they can
outlive it for a few minutes; wait until the VPC lists none before reusing
the addresses.</li>
</ul>
<h2 id="persistent-volume-claim">Persistent Volume Claim</h2>
<p><code>CCI.Supervisor.Resource</code> with <code>apiVersion: v1</code>,
<code>kind: PersistentVolumeClaim</code>. A disk from a storage class, for a VM&rsquo;s
<code>volumes</code> or a pod.</p>
<table>
	<thead>
			<tr>
					<th><code>spec</code> field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>storageClassName</code></td>
					<td>A storage class the namespace has.</td>
			</tr>
			<tr>
					<td><code>resources.requests.storage</code></td>
					<td>The size: <code>100Gi</code>.</td>
			</tr>
			<tr>
					<td><code>accessModes[]</code></td>
					<td><code>ReadWriteOnce</code> for a VM disk; <code>ReadWriteMany</code> where the storage supports it.</td>
			</tr>
			<tr>
					<td><code>volumeMode</code></td>
					<td><code>Filesystem</code> or <code>Block</code>.</td>
			</tr>
			<tr>
					<td><code>dataSource</code>, <code>dataSourceRef</code></td>
					<td>Restore from a snapshot or clone another claim.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (23)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>spec.accessModes</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[ReadWriteOnce]</code></td>
					<td>accessModes contains the desired access modes the volume should have.</td>
			</tr>
			<tr>
					<td><code>spec.dataSource</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{apiGroup: snapshot.storage.k8s.io, kind: &lt;kind&gt;}</code></td>
					<td>TypedLocalObjectReference contains enough information to let you locate the typed referenced object inside the same namespace.</td>
			</tr>
			<tr>
					<td><code>spec.dataSource.apiGroup</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>snapshot.storage.k8s.io</code></td>
					<td>APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group.</td>
			</tr>
			<tr>
					<td><code>spec.dataSource.kind</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;kind&gt;</code></td>
					<td>Kind is the type of resource being referenced</td>
			</tr>
			<tr>
					<td><code>spec.dataSource.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;name&gt;</code></td>
					<td>Name is the name of resource being referenced</td>
			</tr>
			<tr>
					<td><code>spec.dataSourceRef</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{apiGroup: snapshot.storage.k8s.io, namespace: ns-source}</code></td>
					<td>TypedObjectReference contains enough information to let you locate the typed referenced object</td>
			</tr>
			<tr>
					<td><code>spec.dataSourceRef.apiGroup</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>snapshot.storage.k8s.io</code></td>
					<td>APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group.</td>
			</tr>
			<tr>
					<td><code>spec.dataSourceRef.kind</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;kind&gt;</code></td>
					<td>Kind is the type of resource being referenced</td>
			</tr>
			<tr>
					<td><code>spec.dataSourceRef.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;name&gt;</code></td>
					<td>Name is the name of resource being referenced</td>
			</tr>
			<tr>
					<td><code>spec.dataSourceRef.namespace</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>ns-source</code></td>
					<td>Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to &hellip;</td>
			</tr>
			<tr>
					<td><code>spec.resources</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{limits: {storage: 20Gi}, requests: {storage: 20Gi}}</code></td>
					<td>VolumeResourceRequirements describes the storage resource requirements for a volume.</td>
			</tr>
			<tr>
					<td><code>spec.resources.limits</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{storage: 20Gi}</code></td>
					<td>Limits describes the maximum amount of compute resources allowed.</td>
			</tr>
			<tr>
					<td><code>spec.resources.requests</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{storage: 20Gi}</code></td>
					<td>Requests describes the minimum amount of compute resources required.</td>
			</tr>
			<tr>
					<td><code>spec.selector</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{matchExpressions: [{key: app, operator: In}], matchLabels: {tier: fast}}</code></td>
					<td>A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.selector.matchExpressions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: app, operator: In}]</code></td>
					<td>matchExpressions is a list of label selector requirements. The requirements are ANDed.</td>
			</tr>
			<tr>
					<td><code>spec.selector.matchExpressions[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>app</code></td>
					<td>key is the label key that the selector applies to.</td>
			</tr>
			<tr>
					<td><code>spec.selector.matchExpressions[].operator</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>In</code></td>
					<td>operator represents a key&rsquo;s relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist.</td>
			</tr>
			<tr>
					<td><code>spec.selector.matchExpressions[].values</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[fast]</code></td>
					<td>values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty.</td>
			</tr>
			<tr>
					<td><code>spec.selector.matchLabels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{tier: fast}</code></td>
					<td>matchLabels is a map of {key,value} pairs.</td>
			</tr>
			<tr>
					<td><code>spec.storageClassName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>vsan-default-storage-policy</code></td>
					<td>storageClassName is the name of the StorageClass required by the claim.</td>
			</tr>
			<tr>
					<td><code>spec.volumeAttributesClassName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;volume attributes class&gt;</code></td>
					<td>volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim.</td>
			</tr>
			<tr>
					<td><code>spec.volumeMode</code></td>
					<td>string</td>
					<td></td>
					<td><code>Block</code>, <code>Filesystem</code></td>
					<td>volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.</td>
			</tr>
			<tr>
					<td><code>spec.volumeName</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;existing PersistentVolume&gt;</code></td>
					<td>volumeName is the binding reference to the PersistentVolume backing this claim.</td>
			</tr>
	</tbody>
</table>

</details></p>

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">dataDisk</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Resource</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">context</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.namespace.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">manifest</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">PersistentVolumeClaim</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">web-01-data}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">accessModes</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">ReadWriteOnce]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">storageClassName</span><span class="p">:</span><span class="w"> </span><span class="l">vsan-default-storage-policy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">resources</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">requests</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="l">5Gi</span><span class="w">
</span></span></span></code></pre></div><p><strong>Status worth reading:</strong> <code>status.phase</code> (<code>Bound</code>), <code>status.capacity.storage</code>.</p>
<p><strong>Gotchas</strong></p>
<ul>
<li>The designer&rsquo;s form calls the field <code>accessMode</code>; the Supervisor refuses
that spelling (<code>unknown field &quot;spec.accessMode&quot;</code>).</li>
<li>A <code>-latebinding</code> storage class (WaitForFirstConsumer) puts no constraint on
where the VM lands; our nested hosts&rsquo; vSAN capacity disks use one.</li>
</ul>
<h2 id="secret">Secret</h2>
<p><code>CCI.Supervisor.Resource</code> with <code>apiVersion: v1</code>, <code>kind: Secret</code>. Key/value
data in the namespace. In a blueprint it mostly carries a VM&rsquo;s cloud-init or
Sysprep data, or a password a VM&rsquo;s <code>cloudConfig</code> references.</p>
<table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>stringData</code></td>
					<td>Plain values; the Supervisor encodes them. The easy one in a blueprint.</td>
			</tr>
			<tr>
					<td><code>data</code></td>
					<td>Base64-encoded values.</td>
			</tr>
			<tr>
					<td><code>type</code></td>
					<td><code>Opaque</code> for your own data; <code>kubernetes.io/tls</code> and the other standard types.</td>
			</tr>
			<tr>
					<td><code>immutable</code></td>
					<td><code>true</code> stops changes after creation.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (4)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>data</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{password: &lt;base64&gt;}</code></td>
					<td>Data contains the secret data. Each key must consist of alphanumeric characters, &lsquo;-&rsquo;, &lsquo;_&rsquo; or &lsquo;.&rsquo;.</td>
			</tr>
			<tr>
					<td><code>immutable</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>Immutable, if set to true, ensures that data stored in the Secret cannot be updated (only object metadata can be modified).</td>
			</tr>
			<tr>
					<td><code>stringData</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{password: ${input.password}}</code></td>
					<td>stringData allows specifying non-binary secret data in string form. It is provided as a write-only input field for convenience.</td>
			</tr>
			<tr>
					<td><code>type</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>Opaque</code></td>
					<td>Used to facilitate programmatic handling of secret data.</td>
			</tr>
	</tbody>
</table>

</details></p>

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">jumpConfig</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Resource</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">context</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.namespace.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">manifest</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Secret</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">jump-bootstrap}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">Opaque</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">stringData</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">user-data</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="cl"><span class="sd">            #cloud-config
</span></span></span><span class="line"><span class="cl"><span class="sd">            users:
</span></span></span><span class="line"><span class="cl"><span class="sd">              - name: student
</span></span></span><span class="line"><span class="cl"><span class="sd">                passwd: ${input.jumpPassword}</span><span class="w">
</span></span></span></code></pre></div><p><strong>Gotcha:</strong> an input marked <code>encrypted: true</code> stays hidden in the request,
but whatever a Secret holds can be read by anyone allowed to read Secrets in
the namespace.</p>
<h2 id="kubernetes-cluster">Kubernetes Cluster</h2>
<p><code>CCI.Supervisor.Resource</code> with <code>apiVersion: cluster.x-k8s.io/v1beta1</code>,
<code>kind: Cluster</code>. A VKS cluster, described by a ClusterClass topology. The
designer&rsquo;s schema stops at <code>topology.variables</code>. What the variables can be
comes from the ClusterClass: <code>builtin-generic-v3.6.0</code> on our platform.</p>
<table>
	<thead>
			<tr>
					<th><code>spec</code> field</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>clusterNetwork</code></td>
					<td><strong>Required.</strong> <code>pods.cidrBlocks</code>, <code>services.cidrBlocks</code>, <code>serviceDomain</code>. Without <code>services</code> VKS refuses the cluster: <code>spec.ClusterNetwork.Services must be defined</code>.</td>
			</tr>
			<tr>
					<td><code>topology.class</code></td>
					<td><strong>Required.</strong> The ClusterClass.</td>
			</tr>
			<tr>
					<td><code>topology.classNamespace</code></td>
					<td>Where the ClusterClass lives; not in the designer&rsquo;s form. See the gotchas.</td>
			</tr>
			<tr>
					<td><code>topology.version</code></td>
					<td><strong>Required.</strong> A Kubernetes release the Supervisor offers, for example <code>v1.35.5+vmware.1-vkr.1</code>.</td>
			</tr>
			<tr>
					<td><code>topology.controlPlane</code></td>
					<td><code>replicas</code> (1 or 3), <code>metadata</code>, <code>machineHealthCheck</code>, node drain and deletion timeouts.</td>
			</tr>
			<tr>
					<td><code>topology.workers.machineDeployments[]</code></td>
					<td><code>class: node-pool</code> (the only worker class), <code>name</code>, <code>replicas</code>, and <code>variables.overrides[]</code> per pool.</td>
			</tr>
			<tr>
					<td><code>topology.variables[]</code></td>
					<td><code>name</code> and <code>value</code> pairs, below.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (85)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>spec.availabilityGates</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{conditionType: &lt;condition type&gt;, polarity: Positive}]</code></td>
					<td>availabilityGates specifies additional conditions to include when evaluating Cluster Available condition.</td>
			</tr>
			<tr>
					<td><code>spec.availabilityGates[].conditionType</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;condition type&gt;</code></td>
					<td>conditionType refers to a condition with matching type in the Cluster&rsquo;s condition list. If the conditions doesn&rsquo;t exist, it will be treated as unknown.</td>
			</tr>
			<tr>
					<td><code>spec.availabilityGates[].polarity</code></td>
					<td>string</td>
					<td></td>
					<td><code>Positive</code>, <code>Negative</code></td>
					<td>polarity of the conditionType specified in this availabilityGate. Valid values are Positive, Negative and omitted. When omitted, the default behaviour will be Positive.</td>
			</tr>
			<tr>
					<td><code>spec.clusterNetwork</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{pods: {cidrBlocks: [192.168.156.0/20]}, serviceDomain: cluster.local}</code></td>
					<td>clusterNetwork represents the cluster network configuration.</td>
			</tr>
			<tr>
					<td><code>spec.clusterNetwork.apiServerPort</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>6443</code></td>
					<td>apiServerPort specifies the port the API Server should bind to. Defaults to 6443.</td>
			</tr>
			<tr>
					<td><code>spec.clusterNetwork.pods</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{cidrBlocks: [192.168.156.0/20]}</code></td>
					<td>pods is the network ranges from which Pod networks are allocated.</td>
			</tr>
			<tr>
					<td><code>spec.clusterNetwork.pods.cidrBlocks</code></td>
					<td>array of string</td>
					<td>yes</td>
					<td>e.g. <code>[192.168.156.0/20]</code></td>
					<td>cidrBlocks is a list of CIDR blocks.</td>
			</tr>
			<tr>
					<td><code>spec.clusterNetwork.serviceDomain</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>cluster.local</code></td>
					<td>serviceDomain is the domain name for services.</td>
			</tr>
			<tr>
					<td><code>spec.clusterNetwork.services</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{cidrBlocks: [10.96.0.0/12]}</code></td>
					<td>services is the network ranges from which service VIPs are allocated.</td>
			</tr>
			<tr>
					<td><code>spec.clusterNetwork.services.cidrBlocks</code></td>
					<td>array of string</td>
					<td>yes</td>
					<td>e.g. <code>[10.96.0.0/12]</code></td>
					<td>cidrBlocks is a list of CIDR blocks.</td>
			</tr>
			<tr>
					<td><code>spec.controlPlaneEndpoint</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{host: 192.168.144.40, port: 6443}</code></td>
					<td>controlPlaneEndpoint represents the endpoint used to communicate with the control plane.</td>
			</tr>
			<tr>
					<td><code>spec.controlPlaneEndpoint.host</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>192.168.144.40</code></td>
					<td>host is the hostname on which the API server is serving.</td>
			</tr>
			<tr>
					<td><code>spec.controlPlaneEndpoint.port</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>6443</code></td>
					<td>port is the port on which the API server is serving.</td>
			</tr>
			<tr>
					<td><code>spec.controlPlaneRef</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{kind: KubeadmControlPlane, name: lab-vks-cp}</code></td>
					<td>controlPlaneRef is an optional reference to a provider-specific resource that holds the details for provisioning the Control Plane for a Cluster.</td>
			</tr>
			<tr>
					<td><code>spec.controlPlaneRef.apiVersion</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>controlplane.cluster.x-k8s.io/v1beta1</code></td>
					<td>API version of the referent.</td>
			</tr>
			<tr>
					<td><code>spec.controlPlaneRef.fieldPath</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>(set by the platform)</code></td>
					<td>If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].</td>
			</tr>
			<tr>
					<td><code>spec.controlPlaneRef.kind</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>KubeadmControlPlane</code></td>
					<td>Kind of the referent.</td>
			</tr>
			<tr>
					<td><code>spec.controlPlaneRef.name</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>lab-vks-cp</code></td>
					<td>Name of the referent.</td>
			</tr>
			<tr>
					<td><code>spec.controlPlaneRef.namespace</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>ns-lab</code></td>
					<td>Namespace of the referent.</td>
			</tr>
			<tr>
					<td><code>spec.controlPlaneRef.resourceVersion</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>(set by the platform)</code></td>
					<td>Specific resourceVersion to which this reference is made, if any.</td>
			</tr>
			<tr>
					<td><code>spec.controlPlaneRef.uid</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>(set by the platform)</code></td>
					<td>UID of the referent.</td>
			</tr>
			<tr>
					<td><code>spec.infrastructureRef</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{kind: VSphereCluster, name: lab-vks}</code></td>
					<td>infrastructureRef is a reference to a provider-specific resource that holds the details for provisioning infrastructure for a cluster in said provider.</td>
			</tr>
			<tr>
					<td><code>spec.infrastructureRef.apiVersion</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>vmware.infrastructure.cluster.x-k8s.io/v1beta1</code></td>
					<td>API version of the referent.</td>
			</tr>
			<tr>
					<td><code>spec.infrastructureRef.fieldPath</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>(set by the platform)</code></td>
					<td>If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].</td>
			</tr>
			<tr>
					<td><code>spec.infrastructureRef.kind</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>VSphereCluster</code></td>
					<td>Kind of the referent.</td>
			</tr>
			<tr>
					<td><code>spec.infrastructureRef.name</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>lab-vks</code></td>
					<td>Name of the referent.</td>
			</tr>
			<tr>
					<td><code>spec.infrastructureRef.namespace</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>ns-lab</code></td>
					<td>Namespace of the referent.</td>
			</tr>
			<tr>
					<td><code>spec.infrastructureRef.resourceVersion</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>(set by the platform)</code></td>
					<td>Specific resourceVersion to which this reference is made, if any.</td>
			</tr>
			<tr>
					<td><code>spec.infrastructureRef.uid</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>(set by the platform)</code></td>
					<td>UID of the referent.</td>
			</tr>
			<tr>
					<td><code>spec.paused</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>paused can be used to prevent controllers from processing the Cluster and all its associated objects.</td>
			</tr>
			<tr>
					<td><code>spec.topology</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{class: builtin-generic-v3.6.0, classNamespace: vmware-system-vks-public}</code></td>
					<td>topology encapsulates the topology for the cluster.</td>
			</tr>
			<tr>
					<td><code>spec.topology.class</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>builtin-generic-v3.6.0</code></td>
					<td>class is the name of the ClusterClass object to create the topology.</td>
			</tr>
			<tr>
					<td><code>spec.topology.classNamespace</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>vmware-system-vks-public</code></td>
					<td>classNamespace is the namespace of the ClusterClass that should be used for the topology. If classNamespace is empty or not set, it is defaulted to the namespace of the Cluster object.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{replicas: 1, machineHealthCheck: {maxUnhealthy: 40%, nodeStartupTimeout: 10m}}</code></td>
					<td>controlPlane describes the cluster control plane.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.machineHealthCheck</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{maxUnhealthy: 40%, nodeStartupTimeout: 10m}</code></td>
					<td>machineHealthCheck allows to enable, disable and override the MachineHealthCheck configuration in the ClusterClass for this control plane.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.machineHealthCheck.enable</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>enable controls if a MachineHealthCheck should be created for the target machines. If false: No MachineHealthCheck will be created.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.machineHealthCheck.maxUnhealthy</code></td>
					<td>int or string</td>
					<td></td>
					<td>e.g. <code>40%</code></td>
					<td>maxUnhealthy specifies the maximum number of unhealthy machines allowed. Any further remediation is only allowed if at most &ldquo;maxUnhealthy&rdquo; machines selected by &ldquo;selector&rdquo; are not healthy.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.machineHealthCheck.nodeStartupTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10m</code></td>
					<td>nodeStartupTimeout allows to set the maximum time for MachineHealthCheck to consider a Machine unhealthy if a corresponding Node isn&rsquo;t associated through a <code>Spec.ProviderID</code> field.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.machineHealthCheck.remediationTemplate</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{apiVersion: &lt;group&gt;/&lt;version&gt;, kind: &lt;remediation template kind&gt;, name: &lt;name&gt;}</code></td>
					<td>remediationTemplate is a reference to a remediation template provided by an infrastructure provider.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.machineHealthCheck.unhealthyConditions</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{type: Ready, status: Unknown, timeout: 300s}]</code></td>
					<td>unhealthyConditions contains a list of the conditions that determine whether a node is considered unhealthy. The conditions are combined in a logical OR, i.e.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.machineHealthCheck.unhealthyRange</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>'[1-3]'</code></td>
					<td>unhealthyRange specifies the range of unhealthy machines allowed.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.metadata</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{annotations: {owner: team-a}, labels: {app: web}}</code></td>
					<td>metadata is the metadata applied to the ControlPlane and the Machines of the ControlPlane if the ControlPlaneTemplate referenced by the ClusterClass is machine based.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.metadata.annotations</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{owner: team-a}</code></td>
					<td>annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.metadata.labels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{app: web}</code></td>
					<td>labels is a map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.nodeDeletionTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10m</code></td>
					<td>nodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine hosts after the Machine is marked for deletion.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.nodeDrainTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10m</code></td>
					<td>nodeDrainTimeout is the total amount of time that the controller will spend on draining a node. The default value is 0, meaning that the node can be drained without any time limitations.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.nodeVolumeDetachTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10m</code></td>
					<td>nodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes to be detached.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.readinessGates</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{conditionType: &lt;condition type&gt;, polarity: Positive}]</code></td>
					<td>readinessGates specifies additional conditions to include when evaluating Machine Ready condition. This field can be used e.g.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.readinessGates[].conditionType</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;condition type&gt;</code></td>
					<td>conditionType refers to a condition with matching type in the Machine&rsquo;s condition list. If the conditions doesn&rsquo;t exist, it will be treated as unknown.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.readinessGates[].polarity</code></td>
					<td>string</td>
					<td></td>
					<td><code>Positive</code>, <code>Negative</code></td>
					<td>polarity of the conditionType specified in this readinessGate. Valid values are Positive, Negative and omitted. When omitted, the default behaviour will be Positive.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.replicas</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>1</code></td>
					<td>replicas is the number of control plane nodes.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.variables</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{overrides: [{name: vmClass, value: best-effort-medium}]}</code></td>
					<td>variables can be used to customize the ControlPlane through patches.</td>
			</tr>
			<tr>
					<td><code>spec.topology.controlPlane.variables.overrides</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: vmClass, value: best-effort-medium}]</code></td>
					<td>overrides can be used to override Cluster level variables.</td>
			</tr>
			<tr>
					<td><code>spec.topology.rolloutAfter</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>2026-10-01T22:00:00Z</code></td>
					<td>rolloutAfter performs a rollout of the entire cluster one component at a time, control plane first and then machine deployments.</td>
			</tr>
			<tr>
					<td><code>spec.topology.variables</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: vmClass, value: best-effort-small}]</code></td>
					<td>variables can be used to customize the Cluster through patches. They must comply to the corresponding VariableClasses defined in the ClusterClass.</td>
			</tr>
			<tr>
					<td><code>spec.topology.variables[].definitionFrom</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;patch name&gt;</code></td>
					<td>definitionFrom specifies where the definition of this Variable is from. Deprecated: This field is deprecated, must not be set anymore and is going to be removed in the next apiVersion.</td>
			</tr>
			<tr>
					<td><code>spec.topology.variables[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>vmClass</code></td>
					<td>name of the variable.</td>
			</tr>
			<tr>
					<td><code>spec.topology.variables[].value</code></td>
					<td>any</td>
					<td>yes</td>
					<td>e.g. <code>best-effort-small</code></td>
					<td>value of the variable. Note: the value will be validated against the schema of the corresponding ClusterClassVariable from the ClusterClass.</td>
			</tr>
			<tr>
					<td><code>spec.topology.version</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>v1.35.5+vmware.1-vkr.1</code></td>
					<td>version is the Kubernetes version of the cluster.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{machineDeployments: [{name: np-1, class: node-pool}], machinePools: [{name: mp-1, ...}]}</code></td>
					<td>workers encapsulates the different constructs that form the worker nodes for the cluster.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: np-1, class: node-pool}]</code></td>
					<td>machineDeployments is a list of machine deployments in the cluster.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].class</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>node-pool</code></td>
					<td>class is the name of the MachineDeploymentClass used to create the set of worker nodes.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].failureDomain</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>domain-c9</code></td>
					<td>failureDomain is the failure domain the machines will be created in. Must match a key in the FailureDomains map stored on the cluster object.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].machineHealthCheck</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{enable: true}</code></td>
					<td>machineHealthCheck allows to enable, disable and override the MachineHealthCheck configuration in the ClusterClass for this MachineDeployment.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].metadata</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{labels: {pool: np-1}}</code></td>
					<td>metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment. At runtime this metadata is merged with the corresponding metadata from the ClusterClass.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].minReadySeconds</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>10</code></td>
					<td>minReadySeconds is the minimum number of seconds for which a newly created machine should be ready. Defaults to 0 (machine will be considered available as soon as it is ready)</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>np-1</code></td>
					<td>name is the unique identifier for this MachineDeploymentTopology. The value is used with other unique identifiers to create a MachineDeployment&rsquo;s Name (e.g.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].nodeDeletionTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10m</code></td>
					<td>nodeDeletionTimeout defines how long the controller will attempt to delete the Node that the Machine hosts after the Machine is marked for deletion.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].nodeDrainTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10m</code></td>
					<td>nodeDrainTimeout is the total amount of time that the controller will spend on draining a node. The default value is 0, meaning that the node can be drained without any time limitations.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].nodeVolumeDetachTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10m</code></td>
					<td>nodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes to be detached.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].readinessGates</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{conditionType: &lt;condition type&gt;}]</code></td>
					<td>readinessGates specifies additional conditions to include when evaluating Machine Ready condition. This field can be used e.g.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].replicas</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>1</code></td>
					<td>replicas is the number of worker nodes belonging to this set.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].strategy</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{type: RollingUpdate, rollingUpdate: {maxSurge: 1}}</code></td>
					<td>strategy is the deployment strategy to use to replace existing machines with new ones.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machineDeployments[].variables</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{overrides: [{name: vmClass, value: best-effort-large}]}</code></td>
					<td>variables can be used to customize the MachineDeployment through patches.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machinePools</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: mp-1, class: &lt;machine pool class&gt;}]</code></td>
					<td>machinePools is a list of machine pools in the cluster.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machinePools[].class</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;machine pool class&gt;</code></td>
					<td>class is the name of the MachinePoolClass used to create the pool of worker nodes.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machinePools[].failureDomains</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[domain-c9]</code></td>
					<td>failureDomains is the list of failure domains the machine pool will be created in. Must match a key in the FailureDomains map stored on the cluster object.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machinePools[].metadata</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{labels: {pool: mp-1}}</code></td>
					<td>metadata is the metadata applied to the MachinePool. At runtime this metadata is merged with the corresponding metadata from the ClusterClass.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machinePools[].minReadySeconds</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>10</code></td>
					<td>minReadySeconds is the minimum number of seconds for which a newly created machine pool should be ready. Defaults to 0 (machine will be considered available as soon as it is ready)</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machinePools[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>mp-1</code></td>
					<td>name is the unique identifier for this MachinePoolTopology. The value is used with other unique identifiers to create a MachinePool&rsquo;s Name (e.g.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machinePools[].nodeDeletionTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10m</code></td>
					<td>nodeDeletionTimeout defines how long the controller will attempt to delete the Node that the MachinePool hosts after the MachinePool is marked for deletion.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machinePools[].nodeDrainTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10m</code></td>
					<td>nodeDrainTimeout is the total amount of time that the controller will spend on draining a node. The default value is 0, meaning that the node can be drained without any time limitations.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machinePools[].nodeVolumeDetachTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10m</code></td>
					<td>nodeVolumeDetachTimeout is the total amount of time that the controller will spend on waiting for all volumes to be detached.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machinePools[].replicas</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>2</code></td>
					<td>replicas is the number of nodes belonging to this pool.</td>
			</tr>
			<tr>
					<td><code>spec.topology.workers.machinePools[].variables</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{overrides: [{name: vmClass, value: best-effort-large}]}</code></td>
					<td>variables can be used to customize the MachinePool through patches.</td>
			</tr>
	</tbody>
</table>

</details></p>

<p>The ClusterClass&rsquo;s variables (<code>builtin-generic-v3.6.0</code>); <code>vmClass</code> and
<code>storageClass</code> are required:</p>
<table>
	<thead>
			<tr>
					<th>Variable</th>
					<th>What it sets</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>vmClass</code></td>
					<td>The VM class for the nodes.</td>
			</tr>
			<tr>
					<td><code>storageClass</code></td>
					<td>The storage class for node disks.</td>
			</tr>
			<tr>
					<td><code>volumes</code></td>
					<td>Extra node disks: <code>name</code>, <code>capacity</code>, <code>mountPath</code>, <code>storageClass</code>.</td>
			</tr>
			<tr>
					<td><code>node</code></td>
					<td><code>labels</code>, <code>taints</code> and <code>firewall</code> for the nodes.</td>
			</tr>
			<tr>
					<td><code>osConfiguration</code></td>
					<td><code>ntp.servers</code>, <code>trust.additionalTrustedCAs</code>, <code>systemProxy</code> (<code>http</code>, <code>https</code>, <code>noProxy</code>), <code>user</code> (an administrator and its SSH key), <code>sshd</code>, <code>fips</code>, <code>grub</code>, <code>directoryJoin</code>, <code>ubuntuPro</code>, <code>tuned</code>, <code>securityContext</code>.</td>
			</tr>
			<tr>
					<td><code>kubernetes</code></td>
					<td><code>endpointFQDNs</code>, <code>certificateRotation</code> (on by default), and API server, kubelet, controller-manager and etcd settings.</td>
			</tr>
			<tr>
					<td><code>networks</code></td>
					<td>The nodes&rsquo; interfaces: one primary and optional secondary networks.</td>
			</tr>
			<tr>
					<td><code>resourceConfiguration</code></td>
					<td><code>systemReserved</code> CPU and memory for the kubelet.</td>
			</tr>
			<tr>
					<td><code>vsphereOptions</code></td>
					<td><code>persistentVolumes</code>: which storage classes the cluster&rsquo;s PVCs may use.</td>
			</tr>
			<tr>
					<td><code>bootstrapAddons</code></td>
					<td>The CNI, through <code>cniRef</code>.</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (147)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>bootstrapAddons</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{cniRef: {name: &lt;CNI package config&gt;, namespace: &lt;its namespace&gt;}}</code></td>
					<td>BootstrapAddons defines Addons to be installed on Cluster during bootstrapping. Only supported with Kubernetes 1.35 and above.</td>
			</tr>
			<tr>
					<td><code>bootstrapAddons.cniRef</code></td>
					<td>object</td>
					<td>yes</td>
					<td>e.g. <code>{name: &lt;CNI package config&gt;, namespace: &lt;its namespace&gt;}</code></td>
					<td>CNI Addon to instantiate for Cluster. Used to select CNI rather than ClusterBootstrap spec.CNI field. Compatible Addon/AddonRelease must exist.</td>
			</tr>
			<tr>
					<td><code>bootstrapAddons.cniRef.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;CNI package config&gt;</code></td>
					<td>Name of the Addon being referenced.</td>
			</tr>
			<tr>
					<td><code>bootstrapAddons.cniRef.namespace</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>&lt;its namespace&gt;</code></td>
					<td>Namespace of the addon being referenced. If not specified, will use the default public namespace defined by the addon manager.</td>
			</tr>
			<tr>
					<td><code>kubeAPIServerFQDNs</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[api.lab.example.com]</code></td>
					<td>Deprecated: This variable is deprecated. Use kubernetes.endpointFQDNs instead. This variable will be removed in a future release.</td>
			</tr>
			<tr>
					<td><code>kubernetes</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{apiServerConfiguration: {logs: {flushFrequency: 5s, verbosity: 2}, ...}}</code></td>
					<td>Kubernetes configures cluster-wide settings for the Kubernetes cluster, typically applied to the control plane. Supported scopes: cluster, controlPlane, workers</td>
			</tr>
			<tr>
					<td><code>kubernetes.apiServerConfiguration</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{logs: {flushFrequency: 5s, verbosity: 2}, maxMutatingRequestsInFlight: 200}</code></td>
					<td>APIServerConfiguration contains configuration options for the Kubernetes API server.</td>
			</tr>
			<tr>
					<td><code>kubernetes.apiServerConfiguration.logs</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{flushFrequency: 5s, verbosity: 2}</code></td>
					<td>Logging configures the logging options for the API server, including log levels, formats, and output destinations. Refer to the Kubernetes component-base logs options for more information.</td>
			</tr>
			<tr>
					<td><code>kubernetes.apiServerConfiguration.logs.flushFrequency</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>5s</code></td>
					<td>FlushFrequency is the maximum time between log flushes. If specified as a string, it&rsquo;s parsed as a duration (e.g., &ldquo;1s&rdquo;).</td>
			</tr>
			<tr>
					<td><code>kubernetes.apiServerConfiguration.logs.format</code></td>
					<td>string</td>
					<td></td>
					<td><code>text</code>, <code>json</code></td>
					<td>Format specifies the structure of log messages. Supported values are &ldquo;text&rdquo; (default) and &ldquo;json&rdquo;. Corresponds to &ndash;logging-format flag.</td>
			</tr>
			<tr>
					<td><code>kubernetes.apiServerConfiguration.logs.verbosity</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>2</code></td>
					<td>Verbosity is the threshold that determines which log messages are logged. Default is zero which logs only the most important messages.</td>
			</tr>
			<tr>
					<td><code>kubernetes.apiServerConfiguration.maxMutatingRequestsInFlight</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>200</code></td>
					<td>MaxMutatingRequestsInFlight is the maximum number of parallel mutating requests. Every further request has to wait.</td>
			</tr>
			<tr>
					<td><code>kubernetes.apiServerConfiguration.maxRequestsInFlight</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>400</code></td>
					<td>MaxRequestsInFlight is the maximum number of parallel non-long-running requests. Every further request has to wait.</td>
			</tr>
			<tr>
					<td><code>kubernetes.apiServerConfiguration.profiling</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>Profiling enables profiling via web interface host:port/debug/pprof/ Default: false</td>
			</tr>
			<tr>
					<td><code>kubernetes.apiServerConfiguration.requestTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>60s</code></td>
					<td>RequestTimeout is the duration after which all non-long-running requests will be timed out. Corresponds to the &ndash;request-timeout flag.</td>
			</tr>
			<tr>
					<td><code>kubernetes.certificateRotation</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{enabled: true, renewalDaysBeforeExpiry: 90}</code></td>
					<td>CertificateRotation configures options for the automatic rotation of control plane certificates which have a default validity of 12 months.</td>
			</tr>
			<tr>
					<td><code>kubernetes.certificateRotation.enabled</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>true</code></td>
					<td>Enabled controls enablement of auto certificate rotation</td>
			</tr>
			<tr>
					<td><code>kubernetes.certificateRotation.renewalDaysBeforeExpiry</code></td>
					<td>integer</td>
					<td></td>
					<td>default <code>90</code></td>
					<td>RenewalDaysBeforeExpiry states the number of days before certificate expiry to initiate the renewal of certificates.</td>
			</tr>
			<tr>
					<td><code>kubernetes.endpointFQDNs</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[api.lab.example.com]</code></td>
					<td>EndpointFQDNs Configure FQDN aliases for the control plane endpoint for example to allow users to connect to the cluster using <a href="https://k8s.prod.example.com/">https://k8s.prod.example.com/</a></td>
			</tr>
			<tr>
					<td><code>kubernetes.etcdConfiguration</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{maximumDBSizeGiB: 8}</code></td>
					<td>EtcdConfiguration contains configuration options for the etcd database used by Kubernetes. These settings control etcd behavior including database size limits and performance tuning.</td>
			</tr>
			<tr>
					<td><code>kubernetes.etcdConfiguration.maximumDBSizeGiB</code></td>
					<td>integer</td>
					<td>yes</td>
					<td>e.g. <code>8</code></td>
					<td>MaximumDBSizeGiB specifies the maximum size of the etcd database in GiB. This value is used to set &ndash;quota-backend-bytes for etcd.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeControllerManagerConfiguration</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{terminatedPodGCThreshold: 1000}</code></td>
					<td>KubeControllerManagerConfiguration contains configuration options for the kube-controller-manager. Supported scopes: cluster, controlPlane</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeControllerManagerConfiguration.terminatedPodGCThreshold</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>1000</code></td>
					<td>TerminatedPodGCThreshold is the number of terminated pods that can exist before the terminated pod garbage collector starts deleting terminated pods.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{allowedUnsafeSysctls: [net.core.somaxconn], eventBurst: 100}</code></td>
					<td>KubeletConfiguration contains configuration options for the kubelet running on worker nodes.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.allowedUnsafeSysctls</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[net.core.somaxconn]</code></td>
					<td>AllowedUnsafeSysctls is a comma separated allowlist of unsafe sysctls or sysctl patterns (ending in <code>*</code>). All safe sysctls are enabled by default.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.containerLogMaxFiles</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>5</code></td>
					<td>ContainerLogMaxFiles is the maximum number of container log files that can be present for a container. Default: 5</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.containerLogMaxSizeMiB</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>10</code></td>
					<td>ContainerLogMaxSize defines the maximum size of the container log file before it is rotated in MiB.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.eventBurst</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>100</code></td>
					<td>EventBurst is the maximum size of a burst of event creations, temporarily allows event creations to burst to this number, while still not exceeding eventRecordQPS.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.eventRecordQPS</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>50</code></td>
					<td>EventRecordQPS is the maximum event creations per second. If 0, there is no limit enforced. Corresponds to &ndash;event-qps kubelet flag.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.healthzBindAddress</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>127.0.0.1</code></td>
					<td>HealthzBindAddress is the IP address for the healthz server to serve on. Default: &ldquo;127.0.0.1&rdquo;</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.imageGCHighThresholdPercent</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>85</code></td>
					<td>ImageGCHighThresholdPercent is the percent of disk usage after which image garbage collection is always run. The percent is calculated as this field value out of 100.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.imageGCLowThresholdPercent</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>80</code></td>
					<td>ImageGCLowThresholdPercent is the percent of disk usage before which image garbage collection is never run. Lowest disk usage to garbage collect to.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.imageMaximumGCAge</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>168h</code></td>
					<td>ImageMaximumGCAge is the maximum age an image can be unused before it is garbage collected.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.imageMinimumGCAge</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>2m</code></td>
					<td>ImageMinimumGCAge is the minimum age for an unused image before it is garbage collected. Default: &ldquo;2m&rdquo;</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.imagePullCredentialsVerificationPolicy</code></td>
					<td>string</td>
					<td></td>
					<td><code>NeverVerify</code>, <code>NeverVerifyPreloadedImages</code>, <code>NeverVerifyAllowlistedImages</code>, <code>AlwaysVerify</code></td>
					<td>ImagePullCredentialsVerificationPolicy determines how credentials should be verified when pod requests an image that is already present on the node.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.logging</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{flushFrequency: 5s, verbosity: 2}</code></td>
					<td>Logging specifies the logging configuration options for the kubelet. This controls log levels, formats, and output destinations for kubelet logs.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.logging.flushFrequency</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>5s</code></td>
					<td>FlushFrequency is the maximum time between log flushes. If specified as a string, it&rsquo;s parsed as a duration (e.g., &ldquo;1s&rdquo;).</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.logging.format</code></td>
					<td>string</td>
					<td></td>
					<td><code>text</code>, <code>json</code></td>
					<td>Format specifies the structure of log messages. Supported values are &ldquo;text&rdquo; (default) and &ldquo;json&rdquo;. Corresponds to &ndash;logging-format flag.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.logging.verbosity</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>2</code></td>
					<td>Verbosity is the threshold that determines which log messages are logged. Default is zero which logs only the most important messages.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.maxParallelImagePulls</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>5</code></td>
					<td>MaxParallelImagePulls sets the maximum number of image pulls in parallel. This field is only used when SerializeImagePulls is false.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.maxPods</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>110</code></td>
					<td>MaxPods is the number of pods that can run on this Kubelet. Default: 110 NOTE: By default, the maximum allowed value is 250.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.podPidsLimit</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>4096</code></td>
					<td>PodPidsLimit is the maximum number of PIDs in any pod. Use Kubelet default (-1) when omitted. Default: nil</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.preloadedImagesVerificationAllowlist</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[registry.example.local/*]</code></td>
					<td>PreloadedImagesVerificationAllowlist specifies a list of images that are exempted from credential reverification for the &ldquo;NeverVerifyAllowlistedImages&rdquo; <code>imagePullCredentialsVerificationPolicy</code>.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.registryBurst</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>10</code></td>
					<td>RegistryBurst is the maximum size of bursty pulls, temporarily allows pulls to burst to this number, while still not exceeding registryPullQPS.</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.registryPullQPS</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>5</code></td>
					<td>RegistryPullQPS is the limit of registry pulls per second. Set to 0 for no limit. Default: 5</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.serializeImagePulls</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>SerializeImagePulls when enabled, tells the Kubelet to pull images one at a time. Default: true</td>
			</tr>
			<tr>
					<td><code>kubernetes.kubeletConfiguration.streamingConnectionIdleTimeout</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>4h</code></td>
					<td>StreamingConnectionIdleTimeout is the maximum time a streaming connection can be idle before the connection is automatically closed.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{podSecurityStandard: {auditVersion: latest, enforceVersion: latest}, ...}</code></td>
					<td>Security configures Kubernetes specific security settings.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security.podSecurityStandard</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{auditVersion: latest, enforceVersion: latest}</code></td>
					<td>PodSecurityStandard configures the PodSecurityStandard settings for the cluster.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security.podSecurityStandard.audit</code></td>
					<td>string</td>
					<td></td>
					<td>``, <code>privileged</code>, <code>baseline</code>, <code>restricted</code></td>
					<td>Audit sets the level for the audit PodSecurityConfiguration mode. Policy violations trigger an audit annotation, but are otherwise allowed One of &ldquo;&rdquo;, privileged, baseline, restricted.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security.podSecurityStandard.auditVersion</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>latest</code></td>
					<td>AuditVersion can be used to pin the policy to the version that shipped with a given Kubernetes minor version (e.g. v1.31) when in audit mode.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security.podSecurityStandard.deactivated</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Deactivated disables the patches for Pod Security Standard via AdmissionConfiguration.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security.podSecurityStandard.enforce</code></td>
					<td>string</td>
					<td></td>
					<td>``, <code>privileged</code>, <code>baseline</code>, <code>restricted</code></td>
					<td>Enforce sets the level for the enforce PodSecurityConfiguration mode. Policy violations cause the pod to be rejected.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security.podSecurityStandard.enforceVersion</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>latest</code></td>
					<td>EnforceVersion can be used to pin the policy to the version that shipped with a given Kubernetes minor version (e.g.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security.podSecurityStandard.exemptions</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{namespaces: [monitoring]}</code></td>
					<td>Exemptions can be statically configured based on (requesting) user, RuntimeClass, or namespace. A request meeting exemption criteria is ignored by the admission plugin.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security.podSecurityStandard.warn</code></td>
					<td>string</td>
					<td></td>
					<td>``, <code>privileged</code>, <code>baseline</code>, <code>restricted</code></td>
					<td>Warn sets the level for the warn PodSecurityConfiguration mode. Policy violations trigger a user-facing warning, but are otherwise allowed.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security.podSecurityStandard.warnVersion</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>latest</code></td>
					<td>WarnVersion can be used to pin the policy to the version that shipped with a given Kubernetes minor version (e.g. v1.31) when in warn mode.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security.resourceQuotaConfiguration</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{enabled: false}</code></td>
					<td>ResourceQuotaConfiguration configures the ResourceQuota admission control settings for the cluster.</td>
			</tr>
			<tr>
					<td><code>kubernetes.security.resourceQuotaConfiguration.enabled</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Enabled enables the patches for ResourceQuotaConfiguration via AdmissionConfiguration.</td>
			</tr>
			<tr>
					<td><code>networks</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{interfaces: {primary: {network: {apiVersion: crd.nsx.vmware.com/v1alpha1, ...}}}}</code></td>
					<td>Networks defines the network configuration for the cluster</td>
			</tr>
			<tr>
					<td><code>networks.interfaces</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{primary: {network: {apiVersion: crd.nsx.vmware.com/v1alpha1, kind: SubnetSet, ...}}}</code></td>
					<td>Interfaces describes one primary (eth0) and zero or more secondary interfaces attached to Node virtual machine.</td>
			</tr>
			<tr>
					<td><code>networks.interfaces.primary</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{network: {apiVersion: crd.nsx.vmware.com/v1alpha1, kind: SubnetSet, ...}}</code></td>
					<td>Primary is the primary network interface which is used to connect the Kubernetes primary network for Load balancer, Service discovery, Pod traffic and management traffic etc.</td>
			</tr>
			<tr>
					<td><code>networks.interfaces.primary.mtu</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>1500</code></td>
					<td>MTU is the Maximum Transmission Unit size in bytes.</td>
			</tr>
			<tr>
					<td><code>networks.interfaces.primary.network</code></td>
					<td>object</td>
					<td>yes</td>
					<td>e.g. <code>{apiVersion: crd.nsx.vmware.com/v1alpha1, kind: SubnetSet, name: &lt;subnet set&gt;}</code></td>
					<td>Network is the name of the network resource to which this interface is connected.</td>
			</tr>
			<tr>
					<td><code>networks.interfaces.primary.routes</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{to: 172.16.0.0/16, via: 10.244.0.1}]</code></td>
					<td>Routes is a list of optional, static routes.</td>
			</tr>
			<tr>
					<td><code>networks.interfaces.secondary</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: eth1, network: {apiVersion: crd.nsx.vmware.com/v1alpha1, kind: Subnet, ...}}]</code></td>
					<td>Secondary network is supported with network provider NSX-VPC and vsphere-network.</td>
			</tr>
			<tr>
					<td><code>networks.interfaces.secondary[].mtu</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>1500</code></td>
					<td>MTU is the Maximum Transmission Unit size in bytes.</td>
			</tr>
			<tr>
					<td><code>networks.interfaces.secondary[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>eth1</code></td>
					<td>Name describes the unique name of this network interface, used to distinguish it from other network interfaces attached to node Virtual Machine.</td>
			</tr>
			<tr>
					<td><code>networks.interfaces.secondary[].network</code></td>
					<td>object</td>
					<td>yes</td>
					<td>e.g. <code>{apiVersion: crd.nsx.vmware.com/v1alpha1, kind: Subnet, name: storage-net}</code></td>
					<td>Network is the name of the network resource to which this interface is connected.</td>
			</tr>
			<tr>
					<td><code>networks.interfaces.secondary[].routes</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{to: 10.50.0.0/16, via: 10.250.0.1}]</code></td>
					<td>Routes is a list of optional, static routes.</td>
			</tr>
			<tr>
					<td><code>node</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{firewall: {inboundRules: [{fromPort: 30000, protocol: TCP}]}, labels: {workload: web}}</code></td>
					<td>Node configures Kubernetes node specific settings. Supported scopes: cluster, controlPlane, workers</td>
			</tr>
			<tr>
					<td><code>node.firewall</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{inboundRules: [{fromPort: 30000, protocol: TCP}]}</code></td>
					<td>Firewall specifies the firewall configuration that should be created on the node to allow specific kinds of traffic.</td>
			</tr>
			<tr>
					<td><code>node.firewall.inboundRules</code></td>
					<td>array of object</td>
					<td>yes</td>
					<td>e.g. <code>[{fromPort: 30000, protocol: TCP}]</code></td>
					<td>InboundRules is a list of firewall rules that will be configured on each node to allow or deny specific kinds of traffic.</td>
			</tr>
			<tr>
					<td><code>node.firewall.inboundRules[].fromPort</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>30000</code></td>
					<td>FromPort is the low end (inclusive) of the port range that this rule applies to.</td>
			</tr>
			<tr>
					<td><code>node.firewall.inboundRules[].protocol</code></td>
					<td>int or string</td>
					<td>yes</td>
					<td>e.g. <code>TCP</code></td>
					<td>Protocol is the type of traffic that this rule applies to. Allowed protocols include &ldquo;tcp&rdquo;, &ldquo;udp&rdquo;, &ldquo;icmp&rdquo;, or an any valid IANA protocol number.</td>
			</tr>
			<tr>
					<td><code>node.firewall.inboundRules[].source</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>10.0.0.0/8</code></td>
					<td>Source is the CIDR range of the originating traffic that this rule applies to. If unset, the rule will apply to any source network.</td>
			</tr>
			<tr>
					<td><code>node.firewall.inboundRules[].toPort</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>32767</code></td>
					<td>ToPort is the high end (inclusive) of the port range that this rule applies to.</td>
			</tr>
			<tr>
					<td><code>node.labels</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{workload: web}</code></td>
					<td>Labels is a list of user defined name-value pairs</td>
			</tr>
			<tr>
					<td><code>node.taints</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: dedicated, value: gpu}]</code></td>
					<td>Taints specifies the taints the Node API object should be registered with. If this field is unset, i.e. nil, it will be defaulted with a control-plane taint for control-plane nodes.</td>
			</tr>
			<tr>
					<td><code>node.taints[].effect</code></td>
					<td>string</td>
					<td>yes</td>
					<td><code>NoSchedule</code>, <code>PreferNoSchedule</code>, <code>NoExecute</code></td>
					<td>Effect of the taint on pods that do not tolerate the taint. Valid effects are NoSchedule, PreferNoSchedule and NoExecute.</td>
			</tr>
			<tr>
					<td><code>node.taints[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>dedicated</code></td>
					<td>Key is the taint key to be applied to a node.</td>
			</tr>
			<tr>
					<td><code>node.taints[].value</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>gpu</code></td>
					<td>Value is the taint value corresponding to the taint key.</td>
			</tr>
			<tr>
					<td><code>osConfiguration</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{ntp: {servers: [172.30.0.34]}, ...}</code></td>
					<td>OSConfiguration configures the system settings of nodes that are independent of Kubernetes. Supported scopes: cluster, controlPlane, workers</td>
			</tr>
			<tr>
					<td><code>osConfiguration.directoryJoin</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{credentialSecretRef: &lt;Secret with the join account&gt;, domain: example.local}</code></td>
					<td>DirectoryJoin configures the node to join a Windows Active Directory. Only supported on Windows at present.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.directoryJoin.credentialSecretRef</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret with the join account&gt;</code></td>
					<td>CredentialSecretRef is the name of the secret containing Active Directory join credentials.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.directoryJoin.domain</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>example.local</code></td>
					<td>Domain is the FQDN of the Active Directory Kerberos domain to join.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.directoryJoin.gmsaControlSecurityGroupDN</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>CN=gmsa-k8s,OU=Groups,DC=example,DC=local</code></td>
					<td>GMSAControlSecurityGroupDN is an optional Windows Active Directory security group that has permissions to access the password of the Group Managed Service Accounts.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.directoryJoin.organizationalUnitDN</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>OU=K8s,DC=example,DC=local</code></td>
					<td>OrganizationalUnitDN is an optional organizational unit where the node will be added to in Active Directory. The value will be validated according to <a href="https://tools.ietf.org/html/rfc4514">https://tools.ietf.org/html/rfc4514</a></td>
			</tr>
			<tr>
					<td><code>osConfiguration.fips</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{enabled: false}</code></td>
					<td>FIPS configures FIPS related settings for the Kubernetes cluster to run in FIPS mode. Supported scopes: cluster</td>
			</tr>
			<tr>
					<td><code>osConfiguration.fips.enabled</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Enable specifies whether FIPS settings are enabled and enforced on the node</td>
			</tr>
			<tr>
					<td><code>osConfiguration.grub</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{password: {secretRef: {name: &lt;Secret&gt;, key: password}, user: root}}</code></td>
					<td>GRUB configures GRUB Boot Loader.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.grub.password</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{secretRef: {name: &lt;Secret&gt;, key: password}, user: root}</code></td>
					<td>Password configures the password protection for GRUB Boot Loader (Only applicable on Linux).</td>
			</tr>
			<tr>
					<td><code>osConfiguration.grub.password.enabled</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>false</code></td>
					<td>Enabled defines if the GRUB Boot Loader must be protected with a password</td>
			</tr>
			<tr>
					<td><code>osConfiguration.grub.password.secretRef</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{name: &lt;Secret&gt;, key: password}</code></td>
					<td>SecretRef is the name of the secret containing the password to protect GRUB Key is the data.key field within the secret containing the password value.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.grub.password.user</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>root</code></td>
					<td>User specifies the username to use for GRUB password protection.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.ntp</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{servers: [172.30.0.34]}</code></td>
					<td>NTP sets the time servers that will be used by nodes in the cluster. By default, NTP servers are inherited from vCenter.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.ntp.servers</code></td>
					<td>array of string</td>
					<td>yes</td>
					<td>e.g. <code>[172.30.0.34]</code></td>
					<td>NTP sets the time servers that will be used by nodes in this cluster. By default, NTP servers are inherited from vCenter.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.securityContext</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{appArmor: {profiles: [{name: &lt;AppArmor profile&gt;}]}}</code></td>
					<td>SecurityContext holds security configurations that will be applied to node.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.securityContext.appArmor</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{profiles: [{name: &lt;AppArmor profile&gt;}]}</code></td>
					<td>AppArmor configures the appArmor profiles of the node. Supported scopes: cluster, controlPlane, workers Only supported on Ubuntu and Photon nodes.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.securityContext.appArmor.profiles</code></td>
					<td>array of object</td>
					<td>yes</td>
					<td>e.g. <code>[{name: &lt;AppArmor profile&gt;}]</code></td>
					<td>Profiles is a list of appArmor profiles to be added to the node.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.sshd</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{banner: Authorised use only}</code></td>
					<td>SSHD configures the sshd config of the node.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.sshd.banner</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>Authorised use only</code></td>
					<td>Banner specifies the login message used for sending a legal warning message before authentication</td>
			</tr>
			<tr>
					<td><code>osConfiguration.systemProxy</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{http: http://proxy.example.local:3128, https: http://proxy.example.local:3128}</code></td>
					<td>SystemProxy configures parameters that reference a proxy server for outbound cluster connections.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.systemProxy.http</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>http://proxy.example.local:3128</code></td>
					<td>HTTP is the proxy server to be used for all http connections. This should be a hostname or dotted numerical IP address.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.systemProxy.https</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>http://proxy.example.local:3128</code></td>
					<td>HTTPS configures the proxy server to be used for all https connections. This should be a hostname or dotted numerical IP address.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.systemProxy.noProxy</code></td>
					<td>array of string</td>
					<td>yes</td>
					<td>e.g. <code>[.example.local, 10.0.0.0/8]</code></td>
					<td>NoProxy configures the list of hostnames and CIDR ranges that should be reached without the configured proxy servers.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.trust</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{additionalTrustedCAs: [{caCert: {secretRef: {name: corp-ca}}}]}</code></td>
					<td>Trust configures system-wide certificate trust for nodes</td>
			</tr>
			<tr>
					<td><code>osConfiguration.trust.additionalTrustedCAs</code></td>
					<td>array of object</td>
					<td>yes</td>
					<td>e.g. <code>[{caCert: {secretRef: {name: corp-ca}}}]</code></td>
					<td>AdditionalTrustedCAs is a list of additional CAs to be added to the system trust store of nodes.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.trust.additionalTrustedCAs[].caCert</code></td>
					<td>object</td>
					<td>yes</td>
					<td>e.g. <code>{secretRef: {name: corp-ca, key: ca.crt}}</code></td>
					<td>SecretContent configures a reference to or content of secret data.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.tuned</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{active: [&lt;tuned profile&gt;], profiles: {&lt;profile name&gt;: &lt;TunedProfile reference&gt;}}</code></td>
					<td>TuneD injects TuneD profiles and activate specified profile on Linux nodes. Only supported on Linux.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.tuned.active</code></td>
					<td>array of string</td>
					<td>yes</td>
					<td>e.g. <code>[&lt;tuned profile&gt;]</code></td>
					<td>Active is a list of tuned profile name will be activated on node.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.tuned.profiles</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{&lt;profile name&gt;: &lt;TunedProfile reference&gt;}</code></td>
					<td>Profiles is a map of tuned profiles will be injected on node. Key is the desired tuned profile name, value is the TunedProfile CR reference which contains the profile content.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.ubuntuPro</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{services: [usg], settings: [{key: &lt;setting&gt;, value: &lt;value&gt;}]}</code></td>
					<td>UbuntuPro configures the Ubuntu Pro subscription of the node. Only supported on Ubuntu.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.ubuntuPro.services</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[usg]</code></td>
					<td>Services specifies the Ubuntu Pro services to be enabled.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.ubuntuPro.settings</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{key: &lt;setting&gt;, value: &lt;value&gt;}]</code></td>
					<td>Settings specifies the Ubuntu Pro client (ubuntu-advantage-tools) settings to be configured.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.ubuntuPro.settings[].key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;setting&gt;</code></td>
					<td></td>
			</tr>
			<tr>
					<td><code>osConfiguration.ubuntuPro.settings[].value</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;value&gt;</code></td>
					<td></td>
			</tr>
			<tr>
					<td><code>osConfiguration.ubuntuPro.tokenSecretRef</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret with the Pro token&gt;</code></td>
					<td>TokenSecretRef is the name of the secret containing a valid Ubuntu Pro Subscription token. The secret must have a key token with the content of a valid token.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.user</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{passwordSecret: {key: password, name: &lt;Secret&gt;}, ...}</code></td>
					<td>User is an administrative user that will be created on all nodes. If not set, this is defaulted to &ldquo;vmware-system-user&rdquo;.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.user.password</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{renewalDaysBeforeExpiry: 30}</code></td>
					<td>Password configures the password policy such as password max age and renewal settings.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.user.password.renewalDaysBeforeExpiry</code></td>
					<td>integer</td>
					<td></td>
					<td>e.g. <code>30</code></td>
					<td>RenewalDaysBeforeExpiry configures the days to renew the password before it gets expired.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.user.passwordSecret</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{key: password, name: &lt;Secret&gt;}</code></td>
					<td>Key is the data.key field within the secret containing the password value. If not specified, the secret will be automatically generated as <!-- raw HTML omitted -->-ssh-password.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.user.passwordSecret.key</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>password</code></td>
					<td>Key is the data.key field within the secret containing the password value. For Linux, this must be the hashed value that should be inserted into /etc/shadow.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.user.passwordSecret.name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>&lt;Secret&gt;</code></td>
					<td>Name is the name of the secret containing the password for the administrative account.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.user.requirePasswordOnSudo</code></td>
					<td>boolean</td>
					<td></td>
					<td>e.g. <code>true</code></td>
					<td>RequirePasswordOnSudo configures whether password re-authentication is required on sudo.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.user.sshAuthorizedKey</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>ssh-ed25519 AAAA... ops@admin</code></td>
					<td>The string of the SSH public key that is to be used for the administrative account. The public key must be of any FIPS-140 approved algorithm.</td>
			</tr>
			<tr>
					<td><code>osConfiguration.user.user</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>vmware-system-user</code></td>
					<td>Name is the name of the user to be created. By default, this is vmware-system-user.</td>
			</tr>
			<tr>
					<td><code>resourceConfiguration</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{systemReserved: {cpu: 500m, memory: 1Gi}}</code></td>
					<td>ResourceConfiguration configures kubelet resource options. Currently, only CPU and memory reservations are supported.</td>
			</tr>
			<tr>
					<td><code>resourceConfiguration.systemReserved</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{cpu: 500m, memory: 1Gi}</code></td>
					<td>SystemReserved defines the system reserved CPU and memory reservations.</td>
			</tr>
			<tr>
					<td><code>resourceConfiguration.systemReserved.automatic</code></td>
					<td>boolean</td>
					<td></td>
					<td>default <code>true</code></td>
					<td>Automatic controls the automatic calculation of system reserved resources.</td>
			</tr>
			<tr>
					<td><code>resourceConfiguration.systemReserved.cpu</code></td>
					<td>int or string</td>
					<td></td>
					<td>e.g. <code>500m</code></td>
					<td>CPU describes the number of CPU cores reserved for system processes.</td>
			</tr>
			<tr>
					<td><code>resourceConfiguration.systemReserved.memory</code></td>
					<td>int or string</td>
					<td></td>
					<td>e.g. <code>1Gi</code></td>
					<td>Memory describes the memory resources reserved for system processes.</td>
			</tr>
			<tr>
					<td><code>storageClass</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>vsan-default-storage-policy</code></td>
					<td>StorageClass sets the StorageClass that will be used to create node root volumes.</td>
			</tr>
			<tr>
					<td><code>vmClass</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>best-effort-small</code></td>
					<td>VMClass sets the VMClass that will be used to create nodes. Supported scopes: cluster, controlPlane, workers</td>
			</tr>
			<tr>
					<td><code>volumes</code></td>
					<td>array of object</td>
					<td></td>
					<td>e.g. <code>[{name: containerd, capacity: 50Gi}]</code></td>
					<td>Volumes configures additional disks to be attached to node virtual machines. Supported scopes: cluster, controlPlane, workers</td>
			</tr>
			<tr>
					<td><code>volumes[].capacity</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>50Gi</code></td>
					<td>Capacity defines the storage capacity of the volume.</td>
			</tr>
			<tr>
					<td><code>volumes[].mountPath</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>/var/lib/containerd</code></td>
					<td>MountPath defines the mount path for the volume.</td>
			</tr>
			<tr>
					<td><code>volumes[].name</code></td>
					<td>string</td>
					<td>yes</td>
					<td>e.g. <code>containerd</code></td>
					<td>Name defines the name of the volume.</td>
			</tr>
			<tr>
					<td><code>volumes[].storageClass</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>vsan-default-storage-policy</code></td>
					<td>StorageClass defines the Storage class to use for the volume.</td>
			</tr>
			<tr>
					<td><code>vsphereOptions</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{persistentVolumes: {availableStorageClasses: [vsan-default-storage-policy], ...}}</code></td>
					<td>VSphereOptions configures vSphere specific options related to nodes Supported scopes: cluster, controlPlane, workers</td>
			</tr>
			<tr>
					<td><code>vsphereOptions.persistentVolumes</code></td>
					<td>object</td>
					<td></td>
					<td>e.g. <code>{availableStorageClasses: [vsan-default-storage-policy], ...}</code></td>
					<td>PersistentVolumes configures what is available for PVCs to be used in the cluster.</td>
			</tr>
			<tr>
					<td><code>vsphereOptions.persistentVolumes.availableStorageClasses</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[vsan-default-storage-policy]</code></td>
					<td>AvailableStorageClasses lists the storage classes that can be used in the cluster.</td>
			</tr>
			<tr>
					<td><code>vsphereOptions.persistentVolumes.availableVolumeSnapshotClasses</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[volumesnapshotclass-delete]</code></td>
					<td>AvailableVolumeSnapshotClasses lists the volume snapshot classes that can be used in the cluster.</td>
			</tr>
			<tr>
					<td><code>vsphereOptions.persistentVolumes.customizableStorageClassAnnotations</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[&lt;annotation&gt;]</code></td>
					<td>CustomizableStorageClassAnnotations is a list of annotation keys set on the storage classes within the cluster which can be customized by the user.</td>
			</tr>
			<tr>
					<td><code>vsphereOptions.persistentVolumes.customizableStorageClassLabels</code></td>
					<td>array of string</td>
					<td></td>
					<td>e.g. <code>[&lt;label&gt;]</code></td>
					<td>CustomizableStorageClassLabels is a list of label keys set on the storage classes within the cluster which can be customized by the user.</td>
			</tr>
			<tr>
					<td><code>vsphereOptions.persistentVolumes.defaultStorageClass</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>vsan-default-storage-policy</code></td>
					<td>DefaultStorageClass sets the default storage class inside the cluster.</td>
			</tr>
			<tr>
					<td><code>vsphereOptions.persistentVolumes.defaultVolumeSnapshotClass</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>volumesnapshotclass-delete</code></td>
					<td>DefaultVolumeSnapshotClass sets the default volume snapshot class inside the cluster.</td>
			</tr>
	</tbody>
</table>

</details></p>

<p>Recipe, one control plane node and one worker, as we deployed it (ready in
four minutes):</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">k8s</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Resource</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">context</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.namespace.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">manifest</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">cluster.x-k8s.io/v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Cluster</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">dev-01}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">clusterNetwork</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">pods</span><span class="p">:</span><span class="w"> </span>{<span class="nt">cidrBlocks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="m">192.168.156.0</span><span class="l">/20]}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">services</span><span class="p">:</span><span class="w"> </span>{<span class="nt">cidrBlocks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="m">10.96.0.0</span><span class="l">/12]}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">serviceDomain</span><span class="p">:</span><span class="w"> </span><span class="l">cluster.local</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">topology</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">class</span><span class="p">:</span><span class="w"> </span><span class="l">builtin-generic-v3.6.0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">classNamespace</span><span class="p">:</span><span class="w"> </span><span class="l">vmware-system-vks-public</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l">v1.35.5+vmware.1-vkr.1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">controlPlane</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">replicas</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">workers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">machineDeployments</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span>- <span class="nt">class</span><span class="p">:</span><span class="w"> </span><span class="l">node-pool</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">np-1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span><span class="nt">replicas</span><span class="p">:</span><span class="w"> </span><span class="m">1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">variables</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">vmClass</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l">best-effort-small</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">storageClass</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">value</span><span class="p">:</span><span class="w"> </span><span class="l">vsan-default-storage-policy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">osConfiguration</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nt">value</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                  </span><span class="nt">ntp</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                    </span><span class="nt">servers</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="m">172.30.0.34</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">wait</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">conditions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span>- <span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">Ready</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">status</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;True&#34;</span><span class="w">
</span></span></span></code></pre></div><p>The same cluster in <code>v1beta2</code>, the version the Supervisor recommends; the
class becomes a reference with its namespace:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">        </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">cluster.x-k8s.io/v1beta2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Cluster</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">dev-01}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">clusterNetwork</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">pods</span><span class="p">:</span><span class="w"> </span>{<span class="nt">cidrBlocks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="m">192.168.156.0</span><span class="l">/20]}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">services</span><span class="p">:</span><span class="w"> </span>{<span class="nt">cidrBlocks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="m">10.96.0.0</span><span class="l">/12]}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">serviceDomain</span><span class="p">:</span><span class="w"> </span><span class="l">cluster.local</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">topology</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">classRef</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">builtin-generic-v3.6.0</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">vmware-system-vks-public</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l">v1.35.5+vmware.1-vkr.1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">controlPlane</span><span class="p">:</span><span class="w"> </span>{<span class="nt">replicas</span><span class="p">:</span><span class="w"> </span><span class="m">1</span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">workers</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span><span class="nt">machineDeployments</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span>- {<span class="nt">class</span><span class="p">:</span><span class="w"> </span><span class="nt">node-pool, name</span><span class="p">:</span><span class="w"> </span><span class="nt">np-1, replicas</span><span class="p">:</span><span class="w"> </span><span class="m">1</span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">variables</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span>- {<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="nt">vmClass, value</span><span class="p">:</span><span class="w"> </span><span class="l">best-effort-small}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">              </span>- {<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="nt">storageClass, value</span><span class="p">:</span><span class="w"> </span><span class="l">vsan-default-storage-policy}</span><span class="w">
</span></span></span></code></pre></div><p><strong>Status worth reading:</strong> <code>status.phase</code>, <code>status.conditions</code>; the kubeconfig
is in the namespace as the Secret <code>&lt;cluster&gt;-kubeconfig</code> (ours:
<code>dev-01-kubeconfig</code>).</p>
<p><strong>Gotchas</strong></p>
<ul>
<li>Every namespace gets copies of a few ClusterClasses, on f06
<code>builtin-generic-v3.1.0</code> to <code>v3.3.0</code>; Broadcom&rsquo;s ClusterClass matrix marks
<code>v3.3.0</code> deprecated for VKS 3.6 and 3.7, and Broadcom&rsquo;s own 9.1 sample still
uses it. The newer classes live only in <code>vmware-system-vks-public</code>: name
that namespace (<code>classNamespace</code>, or <code>classRef.namespace</code> in <code>v1beta2</code>) to
use them.</li>
<li>The palette&rsquo;s <code>v1beta1</code> works, with a deprecation warning.</li>
<li>Nodes run Photon OS unless the cluster carries the annotation
<code>run.tanzu.vmware.com/resolve-os-image: os-name=ubuntu</code>.</li>
<li><code>topology.version</code> must be a release the Supervisor lists as ready and
compatible; on f06 those were <code>v1.32.x</code> to <code>v1.35.5</code>.</li>
<li>VKS needs the VPC&rsquo;s load balancer for the cluster&rsquo;s API endpoint, so the
namespace must use a VPC that has one.</li>
</ul>
<h2 id="utilpasswordentry">Util.PasswordEntry</h2>
<p><code>type: Util.PasswordEntry</code>. Not in the palette, but one of the five types: it
generates a password, or takes one you give it, and hashes it at request
time.</p>
<table>
	<thead>
			<tr>
					<th>Property</th>
					<th>Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>length</code></td>
					<td>Generate a password of this length. Default 14.</td>
			</tr>
			<tr>
					<td><code>password</code></td>
					<td>A password to use instead, when <code>length</code> is not set.</td>
			</tr>
			<tr>
					<td><code>generatedPassword</code></td>
					<td>Computed: the generated password.</td>
			</tr>
			<tr>
					<td><code>sha512crypt</code></td>
					<td>Computed: the password&rsquo;s SHA-512 crypt hash (<code>$6$...</code>).</td>
			</tr>
	</tbody>
</table>


<p><details >
  <summary markdown="span">Every field the platform accepts (3)</summary>
  <table>
	<thead>
			<tr>
					<th>Field</th>
					<th>Type</th>
					<th>Req.</th>
					<th>Values</th>
					<th>Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>count</code></td>
					<td>integer</td>
					<td></td>
					<td>default <code>1</code></td>
					<td>The number of resource instances to be created.</td>
			</tr>
			<tr>
					<td><code>length</code></td>
					<td>integer</td>
					<td></td>
					<td>default <code>14</code></td>
					<td>Length of the password to be auto generated</td>
			</tr>
			<tr>
					<td><code>password</code></td>
					<td>string</td>
					<td></td>
					<td>e.g. <code>${input.adminPassword}</code></td>
					<td>Password value received as an input when length is not specified</td>
			</tr>
	</tbody>
</table>

</details></p>

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">pw</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">Util.PasswordEntry</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">length</span><span class="p">:</span><span class="w"> </span><span class="m">20</span><span class="w">
</span></span></span></code></pre></div><p>VCF Automation stores both computed values as encrypted secrets
(<code>((secret:v1:...))</code>), so the deployment doesn&rsquo;t show them. Where the hash is
used decides how to write it:</p>
<ul>
<li>
<p>In a raw cloud-config held in a Secret, it is a string:
<code>hashed_passwd: ${resource.pw.sha512crypt}</code>.</p>
</li>
<li>
<p>In a VM&rsquo;s inline <code>cloudConfig</code> it must be a Secret reference, so put it in
a Secret first:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">webPw</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">CCI.Supervisor.Resource</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">context</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.ns.id}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">manifest</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">Secret</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">metadata</span><span class="p">:</span><span class="w"> </span>{<span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">web-pw}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">Opaque</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">stringData</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">ops-passwd</span><span class="p">:</span><span class="w"> </span><span class="l">${resource.pw.sha512crypt}</span><span class="w">
</span></span></span></code></pre></div></li>
</ul>
<h2 id="complete-tested-blueprints">Complete, tested blueprints</h2>
<p>The five blueprints we deployed to test this guide, as they ran:</p>
<table>
	<thead>
			<tr>
					<th>File</th>
					<th>What it builds</th>
					<th>Result</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>test1-vpc.yaml</code></td>
					<td>A VPC, its attachment, an external IP allocation, a group, a gateway firewall policy referencing the group, a namespace in the new VPC, a generated password, two counted Secrets holding its hash</td>
					<td>Created in 2 min 15 s; every VPC object <code>Realized</code></td>
			</tr>
			<tr>
					<td><code>test1b-nat.yaml</code></td>
					<td>A DNAT rule on that VPC</td>
					<td>Created; NSX realized it without the port</td>
			</tr>
			<tr>
					<td><code>test3-workload.yaml</code></td>
					<td>In an existing VPC with a load balancer: a namespace, a subnet, a PVC, a VM group with a boot order, two Ubuntu VMs (cloud-init user with key and hashed password, data disk, subnet, anti-affinity), a LoadBalancer service</td>
					<td>Created in 2 min; SSH through the load balancer as the cloud-init user</td>
			</tr>
			<tr>
					<td><code>test4-vks.yaml</code></td>
					<td>A VKS cluster, one control plane node and one worker, <code>builtin-generic-v3.6.0</code></td>
					<td>Ready in 4 min</td>
			</tr>
			<tr>
					<td><code>test5-ipwait.yaml</code></td>
					<td>One VM whose output is its IP</td>
					<td>Output <code>172.30.0.2</code></td>
			</tr>
	</tbody>
</table>
<h2 id="downloads">Downloads</h2>
<ul>
<li><a href="/files/vcfa-91-blueprint-reference.zip"><code>vcfa-91-blueprint-reference.zip</code></a>:
the five test blueprints; the five base types as VCF Automation&rsquo;s API
returns them; the fifteen palette schemas from the designer and the palette
map; and the field tables of this guide as Markdown.</li>
</ul>
<h2 id="why-this-matters-outside-the-lab">Why this matters outside the lab</h2>
<p>Self-service on VCF Automation All Apps is only as good as its blueprints.
And a blueprint is only as good as its author&rsquo;s knowledge of the fields,
which are mostly documented somewhere else, or nowhere.</p>
<p>The cost of not knowing shows up late. The designer saves the blueprint,
the validator passes it, and the request fails ten minutes in. Or worse, it
succeeds, with a NAT rule that forwards every port or a firewall rule that
allows any service.</p>
<p>Knowing what the platform actually enforces turns that into a five-second
dry run. It also turns a catalog item from a demo into something a team can
depend on.</p>
<h2 id="rules-learned">Rules learned</h2>
<ul>
<li>The palette is five resource types. Learn <code>CCI.Supervisor.Resource</code> and
<code>CCI.VPC.Configuration</code> and you can write every item by hand, including
kinds the palette doesn&rsquo;t show.</li>
<li>VCF Automation&rsquo;s validation checks a resource&rsquo;s own properties, never the
manifest or the VPC spec inside. Dry-run manifests against the Supervisor;
test VPC objects by deploying them.</li>
<li>Where the designer&rsquo;s form and the platform disagree, the platform wins:
<code>accessModes</code>, <code>labelSelector</code>, VM affinity terms ending
<code>PreferredDuringExecution</code>.</li>
<li>Outputs are computed once. Wait for what they read: a VM&rsquo;s address needs
the condition <code>VirtualMachineGuestNetworkConfigSynced</code>.</li>
<li>A blueprint VPC has no load balancer and can&rsquo;t get one, so LoadBalancer
services and VKS need a VPC made in the UI.</li>
<li>Name firewall services (<code>&quot;:HTTPS&quot;</code>) instead of port sets, give every rule a
<code>from</code>, and treat a NAT rule as mapping the whole address.</li>
<li>Inline cloud-init passwords are Secret references; <code>count.index</code> needs
<code>allocatePerInstance: true</code>.</li>
</ul>
<h2 id="broadcom-documentation">Broadcom documentation</h2>
<ul>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-9-0-and-later/9-1/organization-management/managing-blueprints-in-vcf-automation.html">Managing Blueprints in VCF Automation</a>: blueprints, the designer, inputs, versions, property groups and custom forms.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-9-0-and-later/9-1/organization-management/managing-blueprints-in-vcf-automation/sample-blueprints-in-vcf-automation-for-all-apps.html">Sample Blueprints in VCF Automation</a>: Broadcom&rsquo;s samples: VMs, <code>count</code> with <code>allocatePerInstance</code>, a VM with a VKS cluster, a VPC with a namespace, a VM group with affinity.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-9-0-and-later/9-1/organization-management/managing-blueprints-in-vcf-automation/specifying-formatversion-in-your-blueprints.html">Specifying formatVersion in Blueprints</a>: what <code>formatVersion: 2</code> adds, including outputs and <code>__deploymentOverview</code>.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-9-0-and-later/9-1/organization-management/managing-blueprints-in-vcf-automation/bindings-and-dependencies.html">Creating bindings and dependencies between resources</a>: <code>dependsOn</code> and property bindings, and how each orders the build.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-9-0-and-later/9-1/organization-management/managing-blueprints-in-vcf-automation/property-groups/input-property-groups.html">Input Property Groups</a> and <a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-9-0-and-later/9-1/organization-management/managing-blueprints-in-vcf-automation/property-groups/constant-property-groups-in-vcf-automation-for-all-apps.html">Constant Property Groups</a>: <code>${input.&lt;group&gt;.&lt;property&gt;}</code> and <code>${propgroup.&lt;group&gt;.&lt;property&gt;}</code>.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-9-0-and-later/9-1/organization-management/administering-all-apps-organizations-in-vcfa-automation/managing-secrets-in-vcfa.html">Managing Secrets in VCF Automation</a>: <code>${secret.&lt;name&gt;}</code>, organization and project secrets.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-9-0-and-later/9-1/organization-management/managing-blueprints-in-vcf-automation/preparing-for-day-2.html">VCF Automation blueprint designs that prepare for day 2 changes</a>: re-applying a blueprint versus day-2 actions, and bindings in day 2.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-9-0-and-later/9-1/organization-management/managing-projects-in-vcfa/create-a-namespace-class.html">Create a Namespace Class in VCF Automation</a>: what a namespace class sets, and so what a blueprint namespace must add.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-9-0-and-later/9-1/organization-management/adding-and-managing-virtual-private-clouds/add-a-vpc.html">Create a Virtual Private Cloud in VCF Automation</a>: a VPC&rsquo;s connectivity profile, private CIDRs and load balancing, and that VKS needs load balancing.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-9-0-and-later/9-1/organization-management/adding-and-managing-virtual-private-clouds/add-a-vpc/create-a-nat-rule-for-a-vpc-in-vcf-automation(1).html">Create a NAT Rule for a VPC in VCF Automation</a>: the NAT actions, external addresses and priorities behind <code>VPCNATRule</code>.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-security-load-balancing/vdefend/vdefend-firewall/9-1/vcf-automation-integration-with-vdefend-firewall/security-management-workflow.html">Secure North-South boundaries for Transit Gateways and VPCs (vDefend 9.1)</a>: VPC gateway firewall policies, rules realized on the edges, and the activation flag in the security profile.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-service-administration-and-development/9-1/provision-and-manage-virtual-machines/deploying-and-managing-virtual-machines-in-vsphere-iaas-control-plane.html">Deploying and Managing Virtual Machines in vSphere Supervisor</a>: VM classes, images, storage classes and zones, with a pointer to the VM Operator API.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-consumption/latest/managing-vsphere-kuberenetes-service-clusters-and-workloads/provisioning-tkg-service-clusters/using-the-cluster-v1beta1-api/using-the-versioned-clusterclass.html">Using the Versioned ClusterClass</a>: the ClusterClass matrix per VKS release and <code>vmware-system-vks-public</code>.</li>
<li><a href="https://techdocs.broadcom.com/us/en/vmware-cis/vcf/vcf-consumption/latest/managing-vsphere-kuberenetes-service-clusters-and-workloads/provisioning-tkg-service-clusters/using-the-cluster-v1beta1-api/using-the-versioned-clusterclass/v1beta1-example-default-cluster.html">v1beta1/v1beta2 Example: Default Cluster</a>: the minimum cluster and the CIDR rules.</li>
<li><a href="https://developer.broadcom.com/xapis/vmware-vsphere-kubernetes-service/3.7.0/variable-docs.html">ClusterClass Variable Reference</a>: every variable of the builtin-generic classes, and where each can be overridden.</li>
<li><a href="https://knowledge.broadcom.com/external/article/435137/vm-status-information-missing-in-vcf-aut.html">VM Status Information Missing in VCF Automation 9.0.x Deployments (KB 435137)</a>: where the designer&rsquo;s default VM <code>wait</code> comes from.</li>
</ul>
<p>The VM Operator API itself is documented upstream, outside Broadcom, and
Broadcom&rsquo;s VM Service pages link there: <a href="https://vm-operator.readthedocs.io/en/latest/ref/api/v1alpha5/">v1alpha5 reference</a>.</p>
<hr>
<p><em>Lab environment; opinions my own. Every snippet was validated, dry-run or
deployed on a live VCF 9.1 environment; the field tables come from the
platform&rsquo;s own schemas.</em></p>
]]></content:encoded>
    </item>
  </channel>
</rss>
