Skip to content

Commit ba812bf

Browse files
committed
fix: Handle multiple meta mutators cleanly
This applies each of the mutators before generating patches.
1 parent 88f59a9 commit ba812bf

File tree

18 files changed

+644
-543
lines changed

18 files changed

+644
-543
lines changed

.golangci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,7 @@ issues:
8585
- path: "api/*"
8686
linters:
8787
- gochecknoinits
88+
# Idiomatic to use init functions to register APIs with scheme
89+
- text: "hugeParam: holderRef is heavy"
90+
linters:
91+
- gocritic

cmd/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ func main() {
136136
}
137137
// This metaPatchHandlers combines all other patch and variable handlers under a single handler.
138138
// It allows to specify configuration under a single variable.
139-
metaPatchHandlers := []mutation.GeneratePatches{
139+
metaPatchHandlers := []mutation.MetaMutater{
140140
httpproxy.NewMetaPatch(mgr.GetClient()),
141141
extraapiservercertsans.NewMetaPatch(),
142142
auditpolicy.NewPatch(),
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2023 D2iQ, Inc. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package handlers
5+
6+
import (
7+
"context"
8+
"errors"
9+
10+
capiv1 "sigs.k8s.io/cluster-api/api/v1beta1"
11+
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
12+
"sigs.k8s.io/controller-runtime/pkg/client"
13+
)
14+
15+
// clusterKeyContextKey is how we find a cluster key from a context.Context.
16+
type clusterKeyContextKey struct{}
17+
18+
func ClusterKeyFrom(ctx context.Context) (client.ObjectKey, error) {
19+
clusterKey, ok := ctx.Value(clusterKeyContextKey{}).(client.ObjectKey)
20+
if !ok || clusterKey.Name == "" {
21+
return client.ObjectKey{}, errors.New(
22+
"failed to detect cluster name from GeneratePatch request",
23+
)
24+
}
25+
26+
return clusterKey, nil
27+
}
28+
29+
func ClusterKeyInto(
30+
ctx context.Context, req *runtimehooksv1.GeneratePatchesRequest,
31+
) context.Context {
32+
clusterKey := client.ObjectKey{}
33+
34+
for i := range req.Items {
35+
item := req.Items[i]
36+
if item.HolderReference.Kind == "Cluster" &&
37+
item.HolderReference.APIVersion == capiv1.GroupVersion.String() {
38+
clusterKey.Name = item.HolderReference.Name
39+
clusterKey.Namespace = item.HolderReference.Namespace
40+
}
41+
}
42+
43+
if clusterKey.Name != "" {
44+
return context.WithValue(ctx, clusterKeyContextKey{}, clusterKey)
45+
}
46+
47+
return ctx
48+
}

common/pkg/capi/clustertopology/handlers/mutation/meta.go

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,44 @@ package mutation
55

66
import (
77
"context"
8-
"strings"
98

9+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
10+
"k8s.io/apimachinery/pkg/runtime"
11+
"k8s.io/apimachinery/pkg/runtime/serializer"
12+
bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1"
13+
controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1"
1014
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
15+
"sigs.k8s.io/cluster-api/exp/runtime/topologymutation"
1116

1217
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/handlers"
1318
)
1419

20+
type MetaMutater interface {
21+
Mutate(
22+
ctx context.Context,
23+
obj runtime.Object,
24+
vars map[string]apiextensionsv1.JSON,
25+
holderRef runtimehooksv1.HolderReference,
26+
) error
27+
}
28+
1529
type metaGeneratePatches struct {
16-
name string
17-
wrappedHandlers []GeneratePatches
30+
name string
31+
decoder runtime.Decoder
32+
mutaters []MetaMutater
1833
}
1934

20-
func NewMetaGeneratePatchesHandler(name string, gp ...GeneratePatches) handlers.Named {
35+
func NewMetaGeneratePatchesHandler(name string, m ...MetaMutater) handlers.Named {
36+
scheme := runtime.NewScheme()
37+
_ = bootstrapv1.AddToScheme(scheme)
38+
_ = controlplanev1.AddToScheme(scheme)
2139
return metaGeneratePatches{
22-
name: name,
23-
wrappedHandlers: gp,
40+
name: name,
41+
decoder: serializer.NewCodecFactory(scheme).UniversalDecoder(
42+
controlplanev1.GroupVersion,
43+
bootstrapv1.GroupVersion,
44+
),
45+
mutaters: m,
2446
}
2547
}
2648

@@ -33,20 +55,26 @@ func (mgp metaGeneratePatches) GeneratePatches(
3355
req *runtimehooksv1.GeneratePatchesRequest,
3456
resp *runtimehooksv1.GeneratePatchesResponse,
3557
) {
36-
for _, h := range mgp.wrappedHandlers {
37-
wrappedResp := &runtimehooksv1.GeneratePatchesResponse{}
38-
h.GeneratePatches(ctx, req, wrappedResp)
39-
resp.Items = append(resp.Items, wrappedResp.Items...)
40-
if wrappedResp.Message != "" {
41-
resp.Message = strings.TrimPrefix(resp.Message+"\n"+wrappedResp.Message, "\n")
42-
}
43-
resp.Status = wrappedResp.Status
44-
if resp.Status == runtimehooksv1.ResponseStatusFailure {
45-
return
46-
}
47-
}
58+
ctx = handlers.ClusterKeyInto(ctx, req)
4859

49-
if resp.Status == "" {
50-
resp.Status = runtimehooksv1.ResponseStatusSuccess
51-
}
60+
topologymutation.WalkTemplates(
61+
ctx,
62+
mgp.decoder,
63+
req,
64+
resp,
65+
func(
66+
ctx context.Context,
67+
obj runtime.Object,
68+
vars map[string]apiextensionsv1.JSON,
69+
holderRef runtimehooksv1.HolderReference,
70+
) error {
71+
for _, h := range mgp.mutaters {
72+
if err := h.Mutate(ctx, obj, vars, holderRef); err != nil {
73+
return err
74+
}
75+
}
76+
77+
return nil
78+
},
79+
)
5280
}

0 commit comments

Comments
 (0)