Skip to content

Commit 2bf8667

Browse files
authored
fix: move managed resource VAP out of CRDinstaller (#1202)
2 parents 3abacb9 + f0ed0f4 commit 2bf8667

File tree

13 files changed

+1021
-267
lines changed

13 files changed

+1021
-267
lines changed

.codespellignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ CROs
44
NotIn
55
fo
66
allReady
7+
AtLeast

cmd/crdinstaller/main.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,6 @@ func main() {
7171
}
7272

7373
klog.Infof("Successfully installed %s CRDs", *mode)
74-
75-
if err := utils.InstallManagedResourceVAP(ctx, client, *mode); err != nil {
76-
klog.Warningf("Failed to install managed resource ValidatingAdmissionPolicy: %v", err)
77-
return
78-
}
79-
80-
klog.Infof("Successfully installed %s managed resource ValidatingAdmissionPolicy", *mode)
8174
}
8275

8376
// installCRDs installs the CRDs from the specified directory based on the mode.

cmd/crdinstaller/utils/util.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,12 @@ import (
1515
"strings"
1616

1717
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
18-
"k8s.io/apimachinery/pkg/api/meta"
1918
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2019
"k8s.io/apimachinery/pkg/runtime"
2120
"k8s.io/apimachinery/pkg/runtime/serializer"
2221
"k8s.io/klog/v2"
2322
"sigs.k8s.io/controller-runtime/pkg/client"
2423
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
25-
26-
"go.goms.io/fleet/pkg/webhook/managedresource"
2724
)
2825

2926
const (
@@ -174,19 +171,3 @@ func GetCRDFromPath(crdPath string, scheme *runtime.Scheme) (*apiextensionsv1.Cu
174171

175172
return crd, nil
176173
}
177-
178-
func InstallManagedResourceVAP(ctx context.Context, c client.Client, mode string) error {
179-
vap := managedresource.GetValidatingAdmissionPolicy(mode == "hub")
180-
vapBinding := managedresource.GetValidatingAdmissionPolicyBinding()
181-
for _, ob := range []client.Object{vap, vapBinding} {
182-
if err := install(ctx, c, ob, nil); err != nil {
183-
if meta.IsNoMatchError(err) {
184-
klog.Infof("Cluster does not support %s resource, skipping installation", ob.GetObjectKind().GroupVersionKind().Kind)
185-
return nil
186-
}
187-
return err
188-
}
189-
}
190-
klog.Infof("Successfully installed managed resource ValidatingAdmissionPolicy")
191-
return nil
192-
}

cmd/crdinstaller/utils/util_test.go

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313

1414
"github.com/google/go-cmp/cmp"
1515
"github.com/google/go-cmp/cmp/cmpopts"
16-
admv1 "k8s.io/api/admissionregistration/v1"
1716
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
1817
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1918
"k8s.io/apimachinery/pkg/runtime"
@@ -301,38 +300,3 @@ func TestInstall(t *testing.T) {
301300
})
302301
}
303302
}
304-
305-
func TestInstallManagedResourceVAP(t *testing.T) {
306-
tests := []struct {
307-
name string
308-
mode string
309-
}{
310-
{
311-
name: "hub mode",
312-
mode: "hub",
313-
},
314-
{
315-
name: "member mode",
316-
mode: "member",
317-
},
318-
}
319-
320-
for _, tt := range tests {
321-
t.Run(tt.name, func(t *testing.T) {
322-
scheme := runtime.NewScheme()
323-
if err := admv1.AddToScheme(scheme); err != nil {
324-
t.Fatalf("Failed to add admissionregistration scheme: %v", err)
325-
}
326-
327-
fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build()
328-
err := InstallManagedResourceVAP(context.Background(), fakeClient, tt.mode)
329-
330-
// The function should complete without errors
331-
// The actual installation behavior depends on the RESTMapper implementation
332-
// which is difficult to test reliably with the fake client
333-
if err != nil {
334-
t.Errorf("InstallManagedResourceVAP() unexpected error: %v", err)
335-
}
336-
})
337-
}
338-
}

cmd/hubagent/main.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import (
5252
mcv1beta1 "go.goms.io/fleet/pkg/controllers/membercluster/v1beta1"
5353
fleetmetrics "go.goms.io/fleet/pkg/metrics"
5454
"go.goms.io/fleet/pkg/webhook"
55+
"go.goms.io/fleet/pkg/webhook/managedresource"
5556
// +kubebuilder:scaffold:imports
5657
)
5758

@@ -210,6 +211,18 @@ func main() {
210211
klog.InfoS("The controller manager has exited")
211212
}()
212213

214+
// Wait for the cache to sync before creating managed resources
215+
if !mgr.GetCache().WaitForCacheSync(ctx) {
216+
klog.Error("failed to wait for cache sync")
217+
exitWithErrorFunc()
218+
}
219+
220+
if err := managedresource.EnsureVAP(ctx, mgr.GetClient(), true); err != nil {
221+
klog.Errorf("unable to create managed resource validating admission policy: %s", err)
222+
exitWithErrorFunc()
223+
}
224+
klog.Info("managed resource validating admission policy is successfully setup")
225+
213226
// Wait for the controller manager and the scheduler to exit.
214227
wg.Wait()
215228
}

pkg/controllers/internalmembercluster/v1beta1/member_controller.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import (
4444
"go.goms.io/fleet/pkg/propertyprovider"
4545
"go.goms.io/fleet/pkg/utils/condition"
4646
"go.goms.io/fleet/pkg/utils/controller"
47+
"go.goms.io/fleet/pkg/webhook/managedresource"
4748
)
4849

4950
// propertyProviderConfig is a group of settings for configuring the the property provider.
@@ -213,6 +214,10 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
213214

214215
switch imc.Spec.State {
215216
case clusterv1beta1.ClusterStateJoin:
217+
if err := managedresource.EnsureVAP(ctx, r.memberClient, false); err != nil {
218+
return ctrl.Result{}, err
219+
}
220+
klog.V(2).InfoS("Successfully installed managed resource validating admission policy")
216221
if err := r.startAgents(ctx, &imc); err != nil {
217222
return ctrl.Result{}, err
218223
}
@@ -242,6 +247,10 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
242247
return ctrl.Result{RequeueAfter: time.Millisecond *
243248
(time.Duration(hbinterval) + time.Duration(utilrand.Int63nRange(0, jitterRange)-jitterRange/2))}, nil
244249
case clusterv1beta1.ClusterStateLeave:
250+
if err := managedresource.EnsureNoVAP(ctx, r.memberClient, false); err != nil {
251+
return ctrl.Result{}, err
252+
}
253+
klog.V(2).InfoS("Successfully uninstalled managed resource validating admission policy")
245254
if err := r.stopAgents(ctx, &imc); err != nil {
246255
return ctrl.Result{}, err
247256
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Copyright (c) Microsoft Corporation.
3+
Licensed under the MIT license.
4+
*/
5+
6+
package managedresource
7+
8+
import (
9+
"context"
10+
11+
v1 "k8s.io/api/admissionregistration/v1"
12+
apierrors "k8s.io/apimachinery/pkg/api/errors"
13+
"k8s.io/apimachinery/pkg/api/meta"
14+
"k8s.io/klog/v2"
15+
"sigs.k8s.io/controller-runtime/pkg/client"
16+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
17+
)
18+
19+
func EnsureNoVAP(ctx context.Context, c client.Client, isHub bool) error {
20+
objs := []client.Object{getValidatingAdmissionPolicy(isHub), getValidatingAdmissionPolicyBinding()}
21+
for _, obj := range objs {
22+
err := c.Delete(ctx, obj)
23+
switch {
24+
case err == nil, apierrors.IsNotFound(err):
25+
// continue
26+
case meta.IsNoMatchError(err):
27+
klog.Infof("object type %T is not supported in this cluster, continuing", obj)
28+
// continue
29+
default:
30+
klog.Errorf("Delete object type %T failed: %s", obj, err)
31+
return err
32+
}
33+
}
34+
return nil
35+
}
36+
37+
func EnsureVAP(ctx context.Context, c client.Client, isHub bool) error {
38+
type vapObjectAndMutator struct {
39+
obj client.Object
40+
mutate func() error
41+
}
42+
// TODO: this can be simplified by dealing with the specific type rather than using client.Object
43+
vap, mutateVAP := getVAPWithMutator(isHub)
44+
vapb, mutateVAPB := getVAPBindingWithMutator()
45+
objsAndMutators := []vapObjectAndMutator{
46+
{
47+
obj: vap,
48+
mutate: mutateVAP,
49+
},
50+
{
51+
obj: vapb,
52+
mutate: mutateVAPB,
53+
},
54+
}
55+
56+
for _, objectMutator := range objsAndMutators {
57+
opResult, err := controllerutil.CreateOrUpdate(ctx, c, objectMutator.obj, objectMutator.mutate)
58+
switch {
59+
case err == nil:
60+
// continue
61+
case meta.IsNoMatchError(err):
62+
klog.Infof("object type %T is not supported in this cluster, continuing", objectMutator.obj)
63+
// continue
64+
default:
65+
klog.Errorf("CreateOrUpdate (operation: %s) for object type %T failed: %s", opResult, objectMutator.obj, err)
66+
return err
67+
}
68+
}
69+
return nil
70+
}
71+
72+
func getVAPWithMutator(isHub bool) (*v1.ValidatingAdmissionPolicy, func() error) {
73+
vap := getValidatingAdmissionPolicy(isHub)
74+
return vap, func() error {
75+
mutateValidatingAdmissionPolicy(vap, isHub)
76+
return nil
77+
}
78+
}
79+
80+
func getVAPBindingWithMutator() (*v1.ValidatingAdmissionPolicyBinding, func() error) {
81+
vapb := getValidatingAdmissionPolicyBinding()
82+
return vapb, func() error {
83+
mutateValidatingAdmissionPolicyBinding(vapb)
84+
return nil
85+
}
86+
}

0 commit comments

Comments
 (0)