Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ spec:
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
legacyProvider:
description: |-
legacyProvider is the network provider to which this namespace was previously affined.
When set, the namespace has transitioned from legacyProvider to the current provider.
APIs and resources associated with legacyProvider remain functional within this namespace
but are no longer the governing provider; new network resources will be created under
the current provider's APIs.

This field is absent when the namespace has never undergone a provider transition.
enum:
- vsphere-distributed
- nsx-tier1
- vpc
type: string
x-kubernetes-validations:
- message: legacyProvider must be vsphere-distributed or nsx-tier1
rule: self in ['vsphere-distributed', 'nsx-tier1']
metadata:
type: object
provider:
Expand All @@ -53,5 +70,8 @@ spec:
required:
- provider
type: object
x-kubernetes-validations:
- message: legacyProvider must differ from provider
rule: '!has(self.legacyProvider) || self.legacyProvider != self.provider'
served: true
storage: true
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ require (
github.com/onsi/gomega v1.40.0
github.com/prometheus/client_golang v1.23.2
github.com/vmware-tanzu/image-registry-operator-api v0.0.0-20250813160346-0f6259af5cbb
github.com/vmware-tanzu/net-operator-api v0.0.0-20260521184348-f9c023dead14
github.com/vmware-tanzu/net-operator-api v0.0.0-20260611174009-a2d7e608727d
github.com/vmware-tanzu/nsx-operator/pkg/apis v0.0.0-20260423081355-beab2417344a
github.com/vmware/govmomi v0.55.0-alpha.0.0.20260518191903-48ab34adb211
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/vmware-tanzu/image-registry-operator-api v0.0.0-20250813160346-0f6259af5cbb h1:2dVpNgnwahauhEhRTrqEvN97URr79JHIel1dZ8WjpAk=
github.com/vmware-tanzu/image-registry-operator-api v0.0.0-20250813160346-0f6259af5cbb/go.mod h1:sh4NJb1tCbzNRJ+ajRuu3thDovFN10Hic2wYmyklG/M=
github.com/vmware-tanzu/net-operator-api v0.0.0-20260521184348-f9c023dead14 h1:QdHz/WzDkNCzeN3sFyG9bdlNrn/j7osp3qgrwBMv+TU=
github.com/vmware-tanzu/net-operator-api v0.0.0-20260521184348-f9c023dead14/go.mod h1:w6QJGm3crIA16ZIz1FVQXD2NVeJhOgGXxW05RbVTSTo=
github.com/vmware-tanzu/net-operator-api v0.0.0-20260611174009-a2d7e608727d h1:JrTKl9lT9G62iZbPN/rqaisx5pR3TO+lif0GYiWU8G8=
github.com/vmware-tanzu/net-operator-api v0.0.0-20260611174009-a2d7e608727d/go.mod h1:w6QJGm3crIA16ZIz1FVQXD2NVeJhOgGXxW05RbVTSTo=
github.com/vmware-tanzu/nsx-operator/pkg/apis v0.0.0-20260423081355-beab2417344a h1:yqGxhqSJ78veQjdOHINJLE9IWDcreMTzwDsOAdwrUWM=
github.com/vmware-tanzu/nsx-operator/pkg/apis v0.0.0-20260423081355-beab2417344a/go.mod h1:Q4JzNkNMvjo7pXtlB5/R3oME4Nhah7fAObWgghVmtxk=
github.com/vmware/govmomi v0.55.0-alpha.0.0.20260518191903-48ab34adb211 h1:n8hoHi/26x5GaTKTS04PqC7bNrCh7Wa7Eh44RKTM214=
Expand Down
56 changes: 53 additions & 3 deletions pkg/util/kube/networksettings/networksettings.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,66 @@ func GetProviderType(
return pkgcfg.FromContext(ctx).NetworkProviderType, nil
}

ns, err := getNetworkSettings(ctx, reader, namespace)
if err != nil {
return "", err
}

return providerToType(ns.Provider)
}

// GetSupportedProviderTypes returns the supported NetworkProviderType for the given
// namespace. A namespace that underwent network provider migration, the prior (legacy)
// network provider is still supported.
func GetSupportedProviderTypes(
ctx context.Context,
reader ctrlclient.Reader,
namespace string) ([]pkgcfg.NetworkProviderType, error) {

t := make([]pkgcfg.NetworkProviderType, 0, 2)

if !pkgcfg.FromContext(ctx).Features.PerNamespaceNetworkProvider {
return append(t, pkgcfg.FromContext(ctx).NetworkProviderType), nil
}

ns, err := getNetworkSettings(ctx, reader, namespace)
if err != nil {
return nil, err
}

defaultProvider, err := providerToType(ns.Provider)
if err != nil {
return nil, err
}

t = append(t, defaultProvider)

if ns.LegacyProvider != "" {
legacyProvider, err := providerToType(ns.LegacyProvider)
if err != nil {
return nil, err
}
t = append(t, legacyProvider)
}

return t, nil
}

func getNetworkSettings(
ctx context.Context,
reader ctrlclient.Reader,
namespace string) (*netopv1alpha1.NetworkSettings, error) {

var ns netopv1alpha1.NetworkSettings
err := reader.Get(ctx, ctrlclient.ObjectKey{Name: defaultNetworkSettingsName, Namespace: namespace}, &ns)
if err != nil {
if apierrors.IsNotFound(err) {
return "", ErrNetworkSettingsNotFound
return nil, ErrNetworkSettingsNotFound
}
return "", err
return nil, err
}

return providerToType(ns.Provider)
return &ns, nil
}

// providerToType maps a netopv1alpha1.NetworkProvider value to the
Expand Down
213 changes: 211 additions & 2 deletions pkg/util/kube/networksettings/networksettings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ var _ = Describe("GetProviderType", func() {
It("returns a not-found error", func() {
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(netsetutil.ErrNetworkSettingsNotFound))
Expect(result).To(BeEmpty())
})
})

Expand All @@ -89,9 +90,10 @@ var _ = Describe("GetProviderType", func() {
}
})

It("propagates the error", func() {
It("returns error", func() {
Expect(err).To(HaveOccurred())
Expect(apierrors.IsNotFound(err)).To(BeFalse())
Expect(apierrors.IsServiceUnavailable(err)).To(BeTrue())
Expect(result).To(BeEmpty())
})
})

Expand Down Expand Up @@ -164,3 +166,210 @@ var _ = Describe("GetProviderType", func() {
})
})
})

var _ = Describe("GetSupportedProviderTypes", func() {
const namespace = "test-ns"

var (
ctx context.Context
reader ctrlclient.Reader
withObjects []ctrlclient.Object
withFuncs interceptor.Funcs
result []pkgcfg.NetworkProviderType
err error
)

BeforeEach(func() {
ctx = pkgcfg.NewContext()
withFuncs = interceptor.Funcs{}
withObjects = nil
})

JustBeforeEach(func() {
reader = builder.NewFakeClientWithInterceptors(withFuncs, withObjects...)
result, err = netsetutil.GetSupportedProviderTypes(ctx, reader, namespace)
})

When("PerNamespaceNetworkProvider capability is disabled", func() {
BeforeEach(func() {
pkgcfg.SetContext(ctx, func(config *pkgcfg.Config) {
config.Features.PerNamespaceNetworkProvider = false
config.NetworkProviderType = pkgcfg.NetworkProviderTypeVDS
})
})

It("returns a single-element slice with the global network provider config value", func() {
Expect(err).ToNot(HaveOccurred())
Expect(result).To(ConsistOf(pkgcfg.NetworkProviderTypeVDS))
})
})

When("PerNamespaceNetworkProvider capability is enabled", func() {
BeforeEach(func() {
pkgcfg.SetContext(ctx, func(config *pkgcfg.Config) {
config.Features.PerNamespaceNetworkProvider = true
})
})

When("NetworkSettings/default does not exist", func() {
It("returns a not-found error", func() {
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(netsetutil.ErrNetworkSettingsNotFound))
Expect(result).To(BeNil())
})
})

When("the client returns an unexpected error", func() {
BeforeEach(func() {
withFuncs.Get = func(
ctx context.Context,
client ctrlclient.WithWatch,
key ctrlclient.ObjectKey,
obj ctrlclient.Object,
opts ...ctrlclient.GetOption) error {

if _, ok := obj.(*netopv1alpha1.NetworkSettings); ok {
return apierrors.NewServiceUnavailable("fake error")
}
return client.Get(ctx, key, obj, opts...)
}
})

It("propagates the error", func() {
Expect(err).To(HaveOccurred())
Expect(apierrors.IsNotFound(err)).To(BeFalse())
Expect(result).To(BeNil())
})
})

When("NetworkSettings/default has provider vsphere-distributed and no legacy provider", func() {
BeforeEach(func() {
withObjects = append(withObjects, &netopv1alpha1.NetworkSettings{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
Namespace: namespace,
},
Provider: netopv1alpha1.NetworkProviderVSphereDistributed,
})
})

It("returns a single-element slice with NetworkProviderTypeVDS", func() {
Expect(err).ToNot(HaveOccurred())
Expect(result).To(ConsistOf(pkgcfg.NetworkProviderTypeVDS))
})
})

When("NetworkSettings/default has provider nsx-tier1 and no legacy provider", func() {
BeforeEach(func() {
withObjects = append(withObjects, &netopv1alpha1.NetworkSettings{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
Namespace: namespace,
},
Provider: netopv1alpha1.NetworkProviderNSXTier1,
})
})

It("returns a single-element slice with NetworkProviderTypeNSXT", func() {
Expect(err).ToNot(HaveOccurred())
Expect(result).To(ConsistOf(pkgcfg.NetworkProviderTypeNSXT))
})
})

When("NetworkSettings/default has provider vpc and no legacy provider", func() {
BeforeEach(func() {
withObjects = append(withObjects, &netopv1alpha1.NetworkSettings{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
Namespace: namespace,
},
Provider: netopv1alpha1.NetworkProviderVPC,
})
})

It("returns a single-element slice with NetworkProviderTypeVPC", func() {
Expect(err).ToNot(HaveOccurred())
Expect(result).To(ConsistOf(pkgcfg.NetworkProviderTypeVPC))
})
})

When("NetworkSettings/default has provider vpc and legacy provider vsphere-distributed", func() {
BeforeEach(func() {
withObjects = append(withObjects, &netopv1alpha1.NetworkSettings{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
Namespace: namespace,
},
Provider: netopv1alpha1.NetworkProviderVPC,
LegacyProvider: netopv1alpha1.NetworkProviderVSphereDistributed,
})
})

It("returns NetworkProviderTypeVPC and NetworkProviderTypeVDS", func() {
Expect(err).ToNot(HaveOccurred())
Expect(result).To(ConsistOf(
pkgcfg.NetworkProviderTypeVPC,
pkgcfg.NetworkProviderTypeVDS,
))
})
})

When("NetworkSettings/default has provider vpc and legacy provider nsx-tier1", func() {
BeforeEach(func() {
withObjects = append(withObjects, &netopv1alpha1.NetworkSettings{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
Namespace: namespace,
},
Provider: netopv1alpha1.NetworkProviderVPC,
LegacyProvider: netopv1alpha1.NetworkProviderNSXTier1,
})
})

It("returns NetworkProviderTypeVPC and NetworkProviderTypeNSXT", func() {
Expect(err).ToNot(HaveOccurred())
Expect(result).To(ConsistOf(
pkgcfg.NetworkProviderTypeVPC,
pkgcfg.NetworkProviderTypeNSXT,
))
})
})

When("NetworkSettings/default has an unknown provider value", func() {
BeforeEach(func() {
withObjects = append(withObjects, &netopv1alpha1.NetworkSettings{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
Namespace: namespace,
},
Provider: "unknown-provider",
})
})

It("returns an error", func() {
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(ContainSubstring("unknown network provider")))
Expect(result).To(BeNil())
})
})

When("NetworkSettings/default has a valid provider and an unknown legacy provider value", func() {
BeforeEach(func() {
withObjects = append(withObjects, &netopv1alpha1.NetworkSettings{
ObjectMeta: metav1.ObjectMeta{
Name: "default",
Namespace: namespace,
},
Provider: netopv1alpha1.NetworkProviderVPC,
LegacyProvider: "unknown-legacy-provider",
})
})

It("returns an error", func() {
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(ContainSubstring("unknown network provider")))
Expect(result).To(BeNil())
})
})
})
})
2 changes: 1 addition & 1 deletion test/e2e/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ require (
github.com/onsi/ginkgo/v2 v2.28.1
github.com/onsi/gomega v1.40.0
github.com/sirupsen/logrus v1.9.4
github.com/vmware-tanzu/net-operator-api v0.0.0-20260521184348-f9c023dead14
github.com/vmware-tanzu/net-operator-api v0.0.0-20260611174009-a2d7e608727d
github.com/vmware-tanzu/nsx-operator/pkg/apis v0.0.0-20260423081355-beab2417344a
github.com/vmware-tanzu/vm-operator/api v0.0.0-00010101000000-000000000000
github.com/vmware-tanzu/vm-operator/external/image-registry-operator v0.0.0-00010101000000-000000000000
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/vmware-tanzu/net-operator-api v0.0.0-20260521184348-f9c023dead14 h1:QdHz/WzDkNCzeN3sFyG9bdlNrn/j7osp3qgrwBMv+TU=
github.com/vmware-tanzu/net-operator-api v0.0.0-20260521184348-f9c023dead14/go.mod h1:w6QJGm3crIA16ZIz1FVQXD2NVeJhOgGXxW05RbVTSTo=
github.com/vmware-tanzu/net-operator-api v0.0.0-20260611174009-a2d7e608727d h1:JrTKl9lT9G62iZbPN/rqaisx5pR3TO+lif0GYiWU8G8=
github.com/vmware-tanzu/net-operator-api v0.0.0-20260611174009-a2d7e608727d/go.mod h1:w6QJGm3crIA16ZIz1FVQXD2NVeJhOgGXxW05RbVTSTo=
github.com/vmware-tanzu/nsx-operator/pkg/apis v0.0.0-20260423081355-beab2417344a h1:yqGxhqSJ78veQjdOHINJLE9IWDcreMTzwDsOAdwrUWM=
github.com/vmware-tanzu/nsx-operator/pkg/apis v0.0.0-20260423081355-beab2417344a/go.mod h1:Q4JzNkNMvjo7pXtlB5/R3oME4Nhah7fAObWgghVmtxk=
github.com/vmware/govmomi v0.55.0-alpha.0.0.20260518191903-48ab34adb211 h1:n8hoHi/26x5GaTKTS04PqC7bNrCh7Wa7Eh44RKTM214=
Expand Down
Loading
Loading