Skip to content

Extend NamespaceNetworkConfiguration to support VPC#48

Draft
ihgann wants to merge 4 commits into
vmware-tanzu:masterfrom
ihgann:topic/ig010188/nnc-add-vpc
Draft

Extend NamespaceNetworkConfiguration to support VPC#48
ihgann wants to merge 4 commits into
vmware-tanzu:masterfrom
ihgann:topic/ig010188/nnc-add-vpc

Conversation

@ihgann
Copy link
Copy Markdown
Contributor

@ihgann ihgann commented May 18, 2026

Adds VPCConfig as the second provider-specific config block alongside
VSphereDistributedConfig. VPC networking is activated by setting
spec.type to "vpc" and populating spec.vpcConfig.

VPCConfig supports two mutually exclusive VPC provisioning modes,
enforced by CEL mutual-exclusion guards on the type:

  • vpc: associates a pre-existing NSX VPC by its Manager API path.
  • managedVPCConfig: directs Net Operator to auto-provision a new VPC.

ManagedVPCConfig.project and ManagedVPCConfig.connectivityProfile
correspond to nsxProject and vpcConnectivityProfile in the nsx-operator
VPCNetworkConfiguration CRD [1]. Both fields are required when
managedVPCConfig is set; since all fields carry omitempty (KAL
convention), enforcement is via CEL rules on the type itself rather
than the OpenAPI required array — an absent field is seen as "" in CEL,
so self.project != '' catches the omitted case.

Both modes additionally accept:

  • sharedSubnets: list-map of pre-existing NSX Subnets (keyed by path)
    to inject into each associated Namespace, with optional podDefault
    and vmDefault markers to designate workload-class defaults.
    VPCSharedSubnet.name is immutable once set (CEL oldSelf guard).
  • defaultSubnetSize: number of IP addresses for auto-created subnets
    (maximum 65536, consistent with VPCNetworkConfiguration upstream [1]).

The temporary CEL restriction that limited spec.type to
"vsphere-distributed" is removed. A parallel CEL guard is added for
vpc: self.type == 'vpc' ? has(self.vpcConfig) : true.

All new types conform to kube-api-linter without suppressions or
exclusions. VPCConfig is embedded as *VPCConfig (pointer) because all
its fields are optional, meaning the zero value {} is only ruled out by
CEL, not by schema alone; the pointer satisfies KAL's optionalfields
linter which requires a pointer when schema validation is incomplete.

[1] https://github.com/vmware-tanzu/nsx-operator/blob/main/pkg/apis/vpc/v1alpha1/vpcnetworkconfiguration_types.go


Testing Done:

  • CEL testing completed - verification of installation of CRD for type VPC. Sample script referenced: TODO.

ihgann and others added 4 commits May 15, 2026 14:28
…etworking

Adds the public Net Operator API through which an administrator declares the
network configuration that Net Operator applies to one or more Namespaces,
starting with vSphere Distributed (VDS) networking. Support for nsx-tier1
and vpc will follow in subsequent branches.

## New files

**api/v1alpha1/common_types.go**

Introduces NetworkProvider, the shared enum used by both
NamespaceNetworkConfiguration (to declare the desired provider) and
NetworkSettings (to reflect the realized provider in a namespace). All
three provider values are defined here so that NetworkSettings can
continue to reflect the full set; NamespaceNetworkConfiguration will grow
support for nsx-tier1 and vpc in follow-up branches.

  NetworkProviderVSphereDistributed = "vsphere-distributed"
  NetworkProviderNSXTier1           = "nsx-tier1"
  NetworkProviderVPC                = "vpc"

**api/v1alpha1/namespacenetworkconfiguration_types.go**

Introduces NamespaceNetworkConfiguration, a cluster-scoped CRD (shortName:
nnc) that declares the network configuration Net Operator applies to one or
more Namespaces.

Association: a Namespace is associated by setting the annotation
netoperator.vmware.com/network-configuration: <name> on the Namespace
(cluster-admin only). Net Operator blocks deletion of the resource while
any Namespace holds this annotation, via the protection finalizer.

Well-known keys (all prefixed NNC for brevity):
  NNCAnnotationKey         netoperator.vmware.com/network-configuration
  NNCDefaultLabelKey       netoperator.vmware.com/default
  NNCProtectionFinalizer   netoperator.vmware.com/namespace-network-configuration-protection
  NNCConditionReady        "Ready"

NNCSpec selects the provider via a required type field and carries a
provider-specific config section. A CEL rule on NNCSpec restricts type to
vsphere-distributed for this iteration (removed when nsx-tier1 and vpc are
introduced in follow-up branches).

For vsphere-distributed, the section is VSphereDistributedConfig, which
holds two required fields:

  networks        — one or more VSphereDistributedNetworkRef entries
                    (MinItems=1, MaxItems=32, listType=map). Net Operator
                    creates a Network CR in each Namespace for every entry
                    and deletes it when the entry is removed.
  defaultNetwork  — name of one of the entries in networks. The corresponding
                    Network CR is labeled netoperator.vmware.com/is-default:
                    "true". Unlike the VMODL (where this field is optional,
                    defaulting to the first entry), this field is required to
                    make intent unambiguous in a declarative API. The referenced
                    VSphereDistributedNetwork must not use IP assignment mode
                    None (enforced at admission/controller time; CEL cannot
                    dereference external resources).

CEL rules on VSphereDistributedConfig:
  - defaultNetwork must name an entry in networks.
  - defaultNetwork is immutable once set (aligned with the VMODL constraint
    "this field does not allow update once applied").

CEL rules on NNCSpec:
  - type must be vsphere-distributed (temporary; relaxed in follow-up branches).
  - networks must be non-empty when type is vsphere-distributed.

NNCStatus carries a standard metav1.Condition list (Ready condition) and an
appliedToNamespaces list (NNCAppliedNamespace entries with name, status, and
optional message) that Net Operator updates as Namespaces are associated or
disassociated via the annotation. GetConditions/SetConditions helpers are
provided on the root type.

## Modified files

**api/v1alpha1/vspheredistributednetwork_types.go**

Adds VSphereDistributedNetworkRef, a by-name reference to a
VSphereDistributedNetwork resource used by VSphereDistributedConfig.networks.

**api/v1alpha1/networksettings_types.go**

Removes the now-redundant NetworkSettingsProvider type and its constants.
NetworkSettings.provider is re-typed to NetworkProvider (from common_types.go),
which carries the same enum values. The duplicate inline kubebuilder:validation:Enum
marker on the field is also removed since the type-level marker is sufficient;
the enum constraint is still emitted in the generated CRD schema.

Co-authored-by: Cursor <cursoragent@cursor.com>
Adds VPCConfig as the second provider-specific config block alongside
VSphereDistributedConfig. VPC networking is activated by setting
spec.type to "vpc" and populating spec.vpcConfig.

VPCConfig supports two mutually exclusive VPC provisioning modes,
enforced by CEL mutual-exclusion guards on the type:

  - vpc: associates a pre-existing NSX VPC by its Manager API path.
  - managedVPCConfig: directs Net Operator to auto-provision a new VPC.

ManagedVPCConfig.project and ManagedVPCConfig.connectivityProfile
correspond to nsxProject and vpcConnectivityProfile in the nsx-operator
VPCNetworkConfiguration CRD [1]. Both fields are required when
managedVPCConfig is set; since all fields carry omitempty (KAL
convention), enforcement is via CEL rules on the type itself rather
than the OpenAPI required array — an absent field is seen as "" in CEL,
so self.project != '' catches the omitted case.

Both modes additionally accept:

  - sharedSubnets: list-map of pre-existing NSX Subnets (keyed by path)
    to inject into each associated Namespace, with optional podDefault
    and vmDefault markers to designate workload-class defaults.
    VPCSharedSubnet.name is immutable once set (CEL oldSelf guard).
  - defaultSubnetSize: number of IP addresses for auto-created subnets
    (maximum 65536, consistent with VPCNetworkConfiguration upstream [1]).

The temporary CEL restriction that limited spec.type to
"vsphere-distributed" is removed. A parallel CEL guard is added for
vpc: self.type == 'vpc' ? has(self.vpcConfig) : true.

All new types conform to kube-api-linter without suppressions or
exclusions. VPCConfig is embedded as *VPCConfig (pointer) because all
its fields are optional, meaning the zero value {} is only ruled out by
CEL, not by schema alone; the pointer satisfies KAL's optionalfields
linter which requires a pointer when schema validation is incomplete.

[1] https://github.com/vmware-tanzu/nsx-operator/blob/main/pkg/apis/vpc/v1alpha1/vpcnetworkconfiguration_types.go

Co-authored-by: Cursor <cursoragent@cursor.com>
@ihgann ihgann force-pushed the topic/ig010188/nnc-add-vpc branch from 8643cc0 to 11b44ef Compare May 19, 2026 15:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant