@@ -23,12 +23,15 @@ import (
23
23
24
24
"github.com/pkg/errors"
25
25
corev1 "k8s.io/api/core/v1"
26
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
27
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26
28
"k8s.io/apimachinery/pkg/types"
27
29
"k8s.io/klog/v2"
28
30
ctrl "sigs.k8s.io/controller-runtime"
29
31
"sigs.k8s.io/controller-runtime/pkg/client"
30
32
"sigs.k8s.io/yaml"
31
33
34
+ clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
32
35
runtimecatalog "sigs.k8s.io/cluster-api/exp/runtime/catalog"
33
36
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
34
37
)
@@ -42,14 +45,13 @@ type Handler struct {
42
45
func (h * Handler ) DoBeforeClusterCreate (ctx context.Context , request * runtimehooksv1.BeforeClusterCreateRequest , response * runtimehooksv1.BeforeClusterCreateResponse ) {
43
46
log := ctrl .LoggerFrom (ctx )
44
47
log .Info ("BeforeClusterCreate is called" )
45
- cluster := request .Cluster
46
48
47
- if err := h .readResponseFromConfigMap (ctx , cluster . Namespace , runtimehooksv1 .BeforeClusterCreate , response ); err != nil {
49
+ if err := h .readResponseFromConfigMap (ctx , & request . Cluster , runtimehooksv1 .BeforeClusterCreate , response ); err != nil {
48
50
response .Status = runtimehooksv1 .ResponseStatusFailure
49
51
response .Message = err .Error ()
50
52
return
51
53
}
52
- if err := h .recordCallInConfigMap (ctx , cluster . Namespace , runtimehooksv1 .BeforeClusterCreate , response ); err != nil {
54
+ if err := h .recordCallInConfigMap (ctx , & request . Cluster , runtimehooksv1 .BeforeClusterCreate , response ); err != nil {
53
55
response .Status = runtimehooksv1 .ResponseStatusFailure
54
56
response .Message = err .Error ()
55
57
}
@@ -59,15 +61,14 @@ func (h *Handler) DoBeforeClusterCreate(ctx context.Context, request *runtimehoo
59
61
func (h * Handler ) DoBeforeClusterUpgrade (ctx context.Context , request * runtimehooksv1.BeforeClusterUpgradeRequest , response * runtimehooksv1.BeforeClusterUpgradeResponse ) {
60
62
log := ctrl .LoggerFrom (ctx )
61
63
log .Info ("BeforeClusterUpgrade is called" )
62
- cluster := request .Cluster
63
64
64
- if err := h .readResponseFromConfigMap (ctx , cluster . Namespace , runtimehooksv1 .BeforeClusterUpgrade , response ); err != nil {
65
+ if err := h .readResponseFromConfigMap (ctx , & request . Cluster , runtimehooksv1 .BeforeClusterUpgrade , response ); err != nil {
65
66
response .Status = runtimehooksv1 .ResponseStatusFailure
66
67
response .Message = err .Error ()
67
68
return
68
69
}
69
70
70
- if err := h .recordCallInConfigMap (ctx , cluster . Namespace , runtimehooksv1 .BeforeClusterUpgrade , response ); err != nil {
71
+ if err := h .recordCallInConfigMap (ctx , & request . Cluster , runtimehooksv1 .BeforeClusterUpgrade , response ); err != nil {
71
72
response .Status = runtimehooksv1 .ResponseStatusFailure
72
73
response .Message = err .Error ()
73
74
}
@@ -77,15 +78,14 @@ func (h *Handler) DoBeforeClusterUpgrade(ctx context.Context, request *runtimeho
77
78
func (h * Handler ) DoAfterControlPlaneInitialized (ctx context.Context , request * runtimehooksv1.AfterControlPlaneInitializedRequest , response * runtimehooksv1.AfterControlPlaneInitializedResponse ) {
78
79
log := ctrl .LoggerFrom (ctx )
79
80
log .Info ("AfterControlPlaneInitialized is called" )
80
- cluster := request .Cluster
81
81
82
- if err := h .readResponseFromConfigMap (ctx , cluster . Namespace , runtimehooksv1 .AfterControlPlaneInitialized , response ); err != nil {
82
+ if err := h .readResponseFromConfigMap (ctx , & request . Cluster , runtimehooksv1 .AfterControlPlaneInitialized , response ); err != nil {
83
83
response .Status = runtimehooksv1 .ResponseStatusFailure
84
84
response .Message = err .Error ()
85
85
return
86
86
}
87
87
88
- if err := h .recordCallInConfigMap (ctx , cluster . Namespace , runtimehooksv1 .AfterControlPlaneInitialized , response ); err != nil {
88
+ if err := h .recordCallInConfigMap (ctx , & request . Cluster , runtimehooksv1 .AfterControlPlaneInitialized , response ); err != nil {
89
89
response .Status = runtimehooksv1 .ResponseStatusFailure
90
90
response .Message = err .Error ()
91
91
}
@@ -95,15 +95,14 @@ func (h *Handler) DoAfterControlPlaneInitialized(ctx context.Context, request *r
95
95
func (h * Handler ) DoAfterControlPlaneUpgrade (ctx context.Context , request * runtimehooksv1.AfterControlPlaneUpgradeRequest , response * runtimehooksv1.AfterControlPlaneUpgradeResponse ) {
96
96
log := ctrl .LoggerFrom (ctx )
97
97
log .Info ("AfterControlPlaneUpgrade is called" )
98
- cluster := request .Cluster
99
98
100
- if err := h .readResponseFromConfigMap (ctx , cluster . Namespace , runtimehooksv1 .AfterControlPlaneUpgrade , response ); err != nil {
99
+ if err := h .readResponseFromConfigMap (ctx , & request . Cluster , runtimehooksv1 .AfterControlPlaneUpgrade , response ); err != nil {
101
100
response .Status = runtimehooksv1 .ResponseStatusFailure
102
101
response .Message = err .Error ()
103
102
return
104
103
}
105
104
106
- if err := h .recordCallInConfigMap (ctx , cluster . Namespace , runtimehooksv1 .AfterControlPlaneUpgrade , response ); err != nil {
105
+ if err := h .recordCallInConfigMap (ctx , & request . Cluster , runtimehooksv1 .AfterControlPlaneUpgrade , response ); err != nil {
107
106
response .Status = runtimehooksv1 .ResponseStatusFailure
108
107
response .Message = err .Error ()
109
108
}
@@ -113,15 +112,14 @@ func (h *Handler) DoAfterControlPlaneUpgrade(ctx context.Context, request *runti
113
112
func (h * Handler ) DoAfterClusterUpgrade (ctx context.Context , request * runtimehooksv1.AfterClusterUpgradeRequest , response * runtimehooksv1.AfterClusterUpgradeResponse ) {
114
113
log := ctrl .LoggerFrom (ctx )
115
114
log .Info ("AfterClusterUpgrade is called" )
116
- cluster := request .Cluster
117
115
118
- if err := h .readResponseFromConfigMap (ctx , cluster . Namespace , runtimehooksv1 .AfterClusterUpgrade , response ); err != nil {
116
+ if err := h .readResponseFromConfigMap (ctx , & request . Cluster , runtimehooksv1 .AfterClusterUpgrade , response ); err != nil {
119
117
response .Status = runtimehooksv1 .ResponseStatusFailure
120
118
response .Message = err .Error ()
121
119
return
122
120
}
123
121
124
- if err := h .recordCallInConfigMap (ctx , cluster . Namespace , runtimehooksv1 .AfterClusterUpgrade , response ); err != nil {
122
+ if err := h .recordCallInConfigMap (ctx , & request . Cluster , runtimehooksv1 .AfterClusterUpgrade , response ); err != nil {
125
123
response .Status = runtimehooksv1 .ResponseStatusFailure
126
124
response .Message = err .Error ()
127
125
}
@@ -131,25 +129,33 @@ func (h *Handler) DoAfterClusterUpgrade(ctx context.Context, request *runtimehoo
131
129
func (h * Handler ) DoBeforeClusterDelete (ctx context.Context , request * runtimehooksv1.BeforeClusterDeleteRequest , response * runtimehooksv1.BeforeClusterDeleteResponse ) {
132
130
log := ctrl .LoggerFrom (ctx )
133
131
log .Info ("BeforeClusterDelete is called" )
134
- cluster := request .Cluster
135
132
136
- if err := h .readResponseFromConfigMap (ctx , cluster . Namespace , runtimehooksv1 .BeforeClusterDelete , response ); err != nil {
133
+ if err := h .readResponseFromConfigMap (ctx , & request . Cluster , runtimehooksv1 .BeforeClusterDelete , response ); err != nil {
137
134
response .Status = runtimehooksv1 .ResponseStatusFailure
138
135
response .Message = err .Error ()
139
136
return
140
137
}
141
- if err := h .recordCallInConfigMap (ctx , cluster . Namespace , runtimehooksv1 .BeforeClusterDelete , response ); err != nil {
138
+ if err := h .recordCallInConfigMap (ctx , & request . Cluster , runtimehooksv1 .BeforeClusterDelete , response ); err != nil {
142
139
response .Status = runtimehooksv1 .ResponseStatusFailure
143
140
response .Message = err .Error ()
144
141
}
142
+
143
+ // TODO: consider if to cleanup the ConfigMap after gating Cluster deletion.
145
144
}
146
145
147
- func (h * Handler ) readResponseFromConfigMap (ctx context.Context , namespace string , hook runtimecatalog.Hook , response runtimehooksv1.ResponseObject ) error {
146
+ func (h * Handler ) readResponseFromConfigMap (ctx context.Context , cluster * clusterv1. Cluster , hook runtimecatalog.Hook , response runtimehooksv1.ResponseObject ) error {
148
147
hookName := runtimecatalog .HookName (hook )
149
148
configMap := & corev1.ConfigMap {}
150
- configMapName := "test-extension-hookresponses"
151
- if err := h .Client .Get (ctx , client.ObjectKey {Namespace : namespace , Name : configMapName }, configMap ); err != nil {
152
- return errors .Wrapf (err , "failed to read the ConfigMap %s" , klog .KRef (namespace , configMapName ))
149
+ configMapName := fmt .Sprintf ("%s-test-extension-hookresponses" , cluster .Name )
150
+ if err := h .Client .Get (ctx , client.ObjectKey {Namespace : cluster .Namespace , Name : configMapName }, configMap ); err != nil {
151
+ if apierrors .IsNotFound (err ) {
152
+ configMap = responsesConfigMap (cluster )
153
+ if err := h .Client .Create (ctx , configMap ); err != nil {
154
+ return errors .Wrapf (err , "failed to create the ConfigMap %s" , klog .KRef (cluster .Namespace , configMapName ))
155
+ }
156
+ } else {
157
+ return errors .Wrapf (err , "failed to read the ConfigMap %s" , klog .KRef (cluster .Namespace , configMapName ))
158
+ }
153
159
}
154
160
if err := yaml .Unmarshal ([]byte (configMap .Data [hookName + "-preloadedResponse" ]), response ); err != nil {
155
161
return errors .Wrapf (err , "failed to read %q response information from ConfigMap" , hook )
@@ -161,12 +167,34 @@ func (h *Handler) readResponseFromConfigMap(ctx context.Context, namespace strin
161
167
return nil
162
168
}
163
169
164
- func (h * Handler ) recordCallInConfigMap (ctx context.Context , namespace string , hook runtimecatalog.Hook , response runtimehooksv1.ResponseObject ) error {
170
+ // responsesConfigMap generates a ConfigMap with preloaded responses for the test extension.
171
+ func responsesConfigMap (cluster * clusterv1.Cluster ) * corev1.ConfigMap {
172
+ return & corev1.ConfigMap {
173
+ ObjectMeta : metav1.ObjectMeta {
174
+ Name : fmt .Sprintf ("%s-test-extension-hookresponses" , cluster .Name ),
175
+ Namespace : cluster .Namespace ,
176
+ },
177
+ // Set the initial preloadedResponses for each of the tested hooks.
178
+ Data : map [string ]string {
179
+ // Blocking hooks are set to return RetryAfterSeconds initially. These will be changed during the test.
180
+ "BeforeClusterCreate-preloadedResponse" : `{"Status": "Success", "RetryAfterSeconds": 5}` ,
181
+ "BeforeClusterUpgrade-preloadedResponse" : `{"Status": "Success", "RetryAfterSeconds": 5}` ,
182
+ "AfterControlPlaneUpgrade-preloadedResponse" : `{"Status": "Success", "RetryAfterSeconds": 5}` ,
183
+ "BeforeClusterDelete-preloadedResponse" : `{"Status": "Success", "RetryAfterSeconds": 5}` ,
184
+
185
+ // Non-blocking hooks are set to Status:Success.
186
+ "AfterControlPlaneInitialized-preloadedResponse" : `{"Status": "Success"}` ,
187
+ "AfterClusterUpgrade-preloadedResponse" : `{"Status": "Success"}` ,
188
+ },
189
+ }
190
+ }
191
+
192
+ func (h * Handler ) recordCallInConfigMap (ctx context.Context , cluster * clusterv1.Cluster , hook runtimecatalog.Hook , response runtimehooksv1.ResponseObject ) error {
165
193
hookName := runtimecatalog .HookName (hook )
166
194
configMap := & corev1.ConfigMap {}
167
- configMapName := " test-extension-hookresponses"
168
- if err := h .Client .Get (ctx , client.ObjectKey {Namespace : namespace , Name : configMapName }, configMap ); err != nil {
169
- return errors .Wrapf (err , "failed to read the ConfigMap %s" , klog .KRef (namespace , configMapName ))
195
+ configMapName := fmt . Sprintf ( "%s- test-extension-hookresponses", cluster . Name )
196
+ if err := h .Client .Get (ctx , client.ObjectKey {Namespace : cluster . Namespace , Name : configMapName }, configMap ); err != nil {
197
+ return errors .Wrapf (err , "failed to read the ConfigMap %s" , klog .KRef (cluster . Namespace , configMapName ))
170
198
}
171
199
var patch client.Patch
172
200
if r , ok := response .(runtimehooksv1.RetryResponseObject ); ok {
@@ -178,7 +206,7 @@ func (h *Handler) recordCallInConfigMap(ctx context.Context, namespace string, h
178
206
[]byte (fmt .Sprintf (`{"data":{"%s-actualResponseStatus":"%s"}}` , hookName , response .GetStatus ()))) //nolint:gocritic
179
207
}
180
208
if err := h .Client .Patch (ctx , configMap , patch ); err != nil {
181
- return errors .Wrapf (err , "failed to update the ConfigMap %s" , klog .KRef (namespace , configMapName ))
209
+ return errors .Wrapf (err , "failed to update the ConfigMap %s" , klog .KRef (cluster . Namespace , configMapName ))
182
210
}
183
211
return nil
184
212
}
0 commit comments