Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fa60556
Bump VMOP and add NodeAutoPlacement Feature Gate
zhanggbj Sep 26, 2025
b52056f
Add VMG controller of node auto placement
zhanggbj Sep 18, 2025
72fad61
Updates logic for VMG creation
srm09 Oct 6, 2025
124623a
Initial impl for VSphereMachine AAF changes
srm09 Sep 29, 2025
9f261d5
Removes cluster-name label from affinity rules
srm09 Oct 10, 2025
22d7db0
Selectively add node-pool AAF constraint
srm09 Oct 13, 2025
8474942
Refine VMG controller when generate per-MD zone labels (#71)
zhanggbj Oct 13, 2025
833cdb5
Sync VSphereMachines in VMG controller
zhanggbj Oct 22, 2025
36c3550
Add VMG reconciler unit test and bump VMOP
zhanggbj Oct 23, 2025
189f6d2
Surface error when VM is waiting for VMG
zhanggbj Oct 24, 2025
8cc8e8a
Update dependency in packaging&test
zhanggbj Oct 28, 2025
2a21acc
Fix UT errors
zhanggbj Oct 28, 2025
947dffa
Fix annotations
zhanggbj Nov 7, 2025
5847119
Fix vmg UT errors
zhanggbj Nov 10, 2025
e3078c9
Refine VMG controller
zhanggbj Nov 12, 2025
dc441f6
Address review comments
zhanggbj Nov 14, 2025
9cc5762
Fix UT failure
zhanggbj Nov 23, 2025
b981168
Refine godoc
zhanggbj Nov 23, 2025
2ac47d4
Refine VMG member update to avoid race condition
zhanggbj Nov 24, 2025
c41abeb
Update vm-operator package to v1.9.1-0.20251003150112-9b458d311c4c
zhanggbj Nov 26, 2025
516af84
Added reconcile flow cases
zhanggbj Nov 27, 2025
ac0ec4b
POC AAF
fabriziopandini Nov 26, 2025
822f8f0
Review comments / fixes
sbueringer Nov 26, 2025
db8095d
Final cleanup
fabriziopandini Nov 26, 2025
08b8304
Finalize VMG controller and UT
zhanggbj Nov 27, 2025
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
4 changes: 4 additions & 0 deletions apis/v1beta1/vspheremachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ const (
// Note: This reason is used only in supervisor mode.
VSphereMachineVirtualMachinePoweringOnV1Beta2Reason = "PoweringOn"

// VSphereMachineVirtualMachineWaitingForVirtualMachineGroupV1Beta2Reason surfaces that the VirtualMachine
// is waiting for its corresponding VirtualMachineGroup to be created and to include this VM as a member.
VSphereMachineVirtualMachineWaitingForVirtualMachineGroupV1Beta2Reason = "WaitingForVirtualMachineGroup"

// VSphereMachineVirtualMachineWaitingForNetworkAddressV1Beta2Reason surfaces when the VirtualMachine that is controlled
// by the VSphereMachine waiting for the machine network settings to be reported after machine being powered on.
VSphereMachineVirtualMachineWaitingForNetworkAddressV1Beta2Reason = "WaitingForNetworkAddress"
Expand Down
2 changes: 1 addition & 1 deletion config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ spec:
- "--diagnostics-address=${CAPI_DIAGNOSTICS_ADDRESS:=:8443}"
- "--insecure-diagnostics=${CAPI_INSECURE_DIAGNOSTICS:=false}"
- --v=4
- "--feature-gates=MultiNetworks=${EXP_MULTI_NETWORKS:=false},NodeAntiAffinity=${EXP_NODE_ANTI_AFFINITY:=false},NamespaceScopedZones=${EXP_NAMESPACE_SCOPED_ZONES:=false},PriorityQueue=${EXP_PRIORITY_QUEUE:=false}"
- "--feature-gates=MultiNetworks=${EXP_MULTI_NETWORKS:=false},NodeAntiAffinity=${EXP_NODE_ANTI_AFFINITY:=false},NamespaceScopedZones=${EXP_NAMESPACE_SCOPED_ZONES:=false},NodeAutoPlacement=${EXP_NODE_AUTO_PLACEMENT:=false},PriorityQueue=${EXP_PRIORITY_QUEUE:=false}"
image: controller:latest
imagePullPolicy: IfNotPresent
name: manager
Expand Down
2 changes: 2 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ rules:
- apiGroups:
- vmoperator.vmware.com
resources:
- virtualmachinegroups
- virtualmachinegroups/status
- virtualmachineimages
- virtualmachineimages/status
- virtualmachines
Expand Down
2 changes: 2 additions & 0 deletions controllers/vmware/controllers_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
. "github.com/onsi/ginkgo/v2"
"github.com/onsi/ginkgo/v2/types"
. "github.com/onsi/gomega"
vmoprv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha2"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
Expand Down Expand Up @@ -71,6 +72,7 @@ func setup(ctx context.Context) (*helpers.TestEnvironment, clustercache.ClusterC
utilruntime.Must(infrav1.AddToScheme(scheme.Scheme))
utilruntime.Must(clusterv1.AddToScheme(scheme.Scheme))
utilruntime.Must(vmwarev1.AddToScheme(scheme.Scheme))
utilruntime.Must(vmoprv1.AddToScheme(scheme.Scheme))

testEnv := helpers.NewTestEnvironment(ctx)

Expand Down
101 changes: 101 additions & 0 deletions controllers/vmware/virtualmachinegroup_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
Copyright 2025 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package vmware

import (
"context"

vmoprv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha2"
apitypes "k8s.io/apimachinery/pkg/types"
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2"
"sigs.k8s.io/cluster-api/util/predicates"
ctrl "sigs.k8s.io/controller-runtime"
ctrlbldr "sigs.k8s.io/controller-runtime/pkg/builder"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

vmwarev1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/vmware/v1beta1"
capvcontext "sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
)

// AddVirtualMachineGroupControllerToManager adds the VirtualMachineGroup controller to the provided manager.
func AddVirtualMachineGroupControllerToManager(ctx context.Context, controllerManagerCtx *capvcontext.ControllerManagerContext, mgr manager.Manager, options controller.Options) error {
predicateLog := ctrl.LoggerFrom(ctx).WithValues("controller", "virtualmachinegroup")

reconciler := &VirtualMachineGroupReconciler{
Client: controllerManagerCtx.Client,
Recorder: mgr.GetEventRecorderFor("virtualmachinegroup-controller"),
}

builder := ctrl.NewControllerManagedBy(mgr).
For(&clusterv1.Cluster{}).
WithOptions(options).
// Set the controller's name explicitly to virtualmachinegroup.
Named("virtualmachinegroup").
Watches(
&vmoprv1.VirtualMachineGroup{},
handler.EnqueueRequestForOwner(mgr.GetScheme(), reconciler.Client.RESTMapper(), &clusterv1.Cluster{}),
ctrlbldr.WithPredicates(predicates.ResourceIsChanged(mgr.GetScheme(), predicateLog)),
).
Watches(
&vmwarev1.VSphereMachine{},
handler.EnqueueRequestsFromMapFunc(reconciler.VSphereMachineToCluster),
ctrlbldr.WithPredicates(
predicate.Funcs{
UpdateFunc: func(event.UpdateEvent) bool { return false },
CreateFunc: func(e event.CreateEvent) bool {
// Only handle VSphereMachine which belongs to a MachineDeployment
_, found := e.Object.GetLabels()[clusterv1.MachineDeploymentNameLabel]
return found
},
DeleteFunc: func(e event.DeleteEvent) bool {
// Only handle VSphereMachine which belongs to a MachineDeployment
_, found := e.Object.GetLabels()[clusterv1.MachineDeploymentNameLabel]
return found
},
GenericFunc: func(event.GenericEvent) bool { return false },
}),
).
WithEventFilter(predicates.ResourceHasFilterLabel(mgr.GetScheme(), predicateLog, controllerManagerCtx.WatchFilterValue))

return builder.Complete(reconciler)
}

// VSphereMachineToCluster maps VSphereMachine events to Cluster reconcile requests.
func (r *VirtualMachineGroupReconciler) VSphereMachineToCluster(_ context.Context, a ctrlclient.Object) []reconcile.Request {
vSphereMachine, ok := a.(*vmwarev1.VSphereMachine)
if !ok {
return nil
}

clusterName, ok := vSphereMachine.Labels[clusterv1.ClusterNameLabel]
if !ok || clusterName == "" {
return nil
}

return []reconcile.Request{{
NamespacedName: apitypes.NamespacedName{
Namespace: vSphereMachine.Namespace,
Name: clusterName,
},
}}
}
Loading