Skip to content

Commit 4a4809b

Browse files
committed
Add APIExport annotation to skip APIExportEndpointSlice creation
1 parent 2bba901 commit 4a4809b

File tree

3 files changed

+51
-17
lines changed

3 files changed

+51
-17
lines changed

pkg/reconciler/apis/apiexport/apiexport_controller_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ func TestReconcile(t *testing.T) {
5050
hasPreexistingVerifyFailure bool
5151
listShardsError error
5252
apiExportEndpointSliceNotFound bool
53+
skipEndpointSliceAnnotation bool
5354

5455
apiBindings []interface{}
5556

@@ -133,11 +134,22 @@ func TestReconcile(t *testing.T) {
133134
wantCreateAPIExportEndpointSlice: true,
134135
wantIdentityValid: true,
135136
},
137+
"skip APIExportEndpointSlice creation when skip annotation is present": {
138+
secretRefSet: true,
139+
secretExists: true,
140+
141+
wantStatusHashSet: true,
142+
apiExportEndpointSliceNotFound: true,
143+
wantCreateAPIExportEndpointSlice: false,
144+
wantIdentityValid: true,
145+
skipEndpointSliceAnnotation: true,
146+
},
136147
}
137148

138149
for name, tc := range tests {
139150
t.Run(name, func(t *testing.T) {
140151
createSecretCalled := false
152+
createEndpointSliceCalled := false
141153

142154
expectedKey := "abc"
143155
expectedHash := fmt.Sprintf("%x", sha256.Sum256([]byte(expectedKey)))
@@ -158,6 +170,7 @@ func TestReconcile(t *testing.T) {
158170
return &apisv1alpha1.APIExportEndpointSlice{}, nil
159171
},
160172
createAPIExportEndpointSlice: func(ctx context.Context, clusterName logicalcluster.Path, apiExportEndpointSlice *apisv1alpha1.APIExportEndpointSlice) error {
173+
createEndpointSliceCalled = true
161174
return nil
162175
},
163176
getSecret: func(ctx context.Context, clusterName logicalcluster.Name, ns, name string) (*corev1.Secret, error) {
@@ -242,6 +255,10 @@ func TestReconcile(t *testing.T) {
242255
conditions.MarkFalse(apiExport, apisv1alpha2.APIExportIdentityValid, apisv1alpha2.IdentityVerificationFailedReason, conditionsv1alpha1.ConditionSeverityError, "")
243256
}
244257

258+
if tc.skipEndpointSliceAnnotation {
259+
apiExport.Annotations[apisv1alpha2.APIExportEndpointSliceSkipAnnotation] = "true"
260+
}
261+
245262
err := c.reconcile(context.Background(), apiExport)
246263
if tc.wantError {
247264
require.Error(t, err, "expected an error")
@@ -292,6 +309,8 @@ func TestReconcile(t *testing.T) {
292309
if tc.wantIdentityValid {
293310
requireConditionMatches(t, apiExport, conditions.TrueCondition(apisv1alpha2.APIExportIdentityValid))
294311
}
312+
313+
require.Equal(t, tc.wantCreateAPIExportEndpointSlice, createEndpointSliceCalled, "expected createEndpointSliceCalled to be %v", tc.wantCreateAPIExportEndpointSlice)
295314
})
296315
}
297316
}

pkg/reconciler/apis/apiexport/apiexport_reconcile.go

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -101,26 +101,36 @@ func (c *controller) reconcile(ctx context.Context, apiExport *apisv1alpha2.APIE
101101
}
102102

103103
// Ensure the APIExportEndpointSlice exists
104-
_, err := c.getAPIExportEndpointSlice(clusterName, apiExport.Name)
105-
if err != nil {
106-
if errors.IsNotFound(err) {
107-
// Create the APIExportEndpointSlice
108-
apiExportEndpointSlice := &apisv1alpha1.APIExportEndpointSlice{
109-
ObjectMeta: metav1.ObjectMeta{
110-
Name: apiExport.Name,
111-
},
112-
Spec: apisv1alpha1.APIExportEndpointSliceSpec{
113-
APIExport: apisv1alpha1.ExportBindingReference{
104+
if _, ok := apiExport.Annotations[apisv1alpha2.APIExportEndpointSliceSkipAnnotation]; !ok {
105+
_, err := c.getAPIExportEndpointSlice(clusterName, apiExport.Name)
106+
if err != nil {
107+
if errors.IsNotFound(err) {
108+
// Create the APIExportEndpointSlice
109+
apiExportEndpointSlice := &apisv1alpha1.APIExportEndpointSlice{
110+
ObjectMeta: metav1.ObjectMeta{
114111
Name: apiExport.Name,
115-
Path: clusterPath,
112+
OwnerReferences: []metav1.OwnerReference{
113+
{
114+
APIVersion: apisv1alpha1.SchemeGroupVersion.String(),
115+
Kind: "APIExport",
116+
Name: apiExport.Name,
117+
UID: apiExport.UID,
118+
},
119+
},
116120
},
117-
},
118-
}
119-
if err := c.createAPIExportEndpointSlice(ctx, clusterName.Path(), apiExportEndpointSlice); err != nil {
120-
return fmt.Errorf("error creating APIExportEndpointSlice for APIExport %s|%s: %w", clusterName, apiExport.Name, err)
121+
Spec: apisv1alpha1.APIExportEndpointSliceSpec{
122+
APIExport: apisv1alpha1.ExportBindingReference{
123+
Name: apiExport.Name,
124+
Path: clusterPath,
125+
},
126+
},
127+
}
128+
if err := c.createAPIExportEndpointSlice(ctx, clusterName.Path(), apiExportEndpointSlice); err != nil {
129+
return fmt.Errorf("error creating APIExportEndpointSlice for APIExport %s|%s: %w", clusterName, apiExport.Name, err)
130+
}
131+
} else {
132+
return fmt.Errorf("error getting APIExportEndpointSlice for APIExport %s|%s: %w", clusterName, apiExport.Name, err)
121133
}
122-
} else {
123-
return fmt.Errorf("error getting APIExportEndpointSlice for APIExport %s|%s: %w", clusterName, apiExport.Name, err)
124134
}
125135
}
126136

sdk/apis/apis/v1alpha2/types_apiexport.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ import (
2626
conditionsv1alpha1 "github.com/kcp-dev/kcp/sdk/apis/third_party/conditions/apis/conditions/v1alpha1"
2727
)
2828

29+
const (
30+
// APIExportEndpointSliceSkipAnnotation is an annotation that can be set on an APIExport to skip the creation of default APIExportEndpointSlice.
31+
APIExportEndpointSliceSkipAnnotation = "apiexports.apis.kcp.io/skip-endpointslice"
32+
)
33+
2934
// These are valid conditions of APIExport.
3035
const (
3136
APIExportIdentityValid conditionsv1alpha1.ConditionType = "IdentityValid"

0 commit comments

Comments
 (0)