Skip to content

Commit 1c55f17

Browse files
authored
Merge pull request #123 from enoodle/erez/use-k8s-1-34-v1-api
Ensure compatibility with default Kubernetes v1.34 clusters
2 parents ba82bf5 + f5336c9 commit 1c55f17

File tree

9 files changed

+445
-98
lines changed

9 files changed

+445
-98
lines changed

cmd/dra-example-kubeletplugin/health.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131
"google.golang.org/grpc/health/grpc_health_v1"
3232
"google.golang.org/grpc/status"
3333
"k8s.io/klog/v2"
34-
drapb "k8s.io/kubelet/pkg/apis/dra/v1beta1"
34+
drapb "k8s.io/kubelet/pkg/apis/dra/v1"
3535
registerapi "k8s.io/kubelet/pkg/apis/pluginregistration/v1"
3636

3737
"sigs.k8s.io/dra-example-driver/pkg/consts"

cmd/dra-example-webhook/main.go

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,16 @@ import (
2727
"github.com/urfave/cli/v2"
2828

2929
admissionv1 "k8s.io/api/admission/v1"
30-
resourceapi "k8s.io/api/resource/v1beta1"
30+
resourceapi "k8s.io/api/resource/v1"
3131
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3232
"k8s.io/apimachinery/pkg/runtime"
33-
"k8s.io/apimachinery/pkg/runtime/serializer"
34-
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
3533
"k8s.io/klog/v2"
3634

3735
configapi "sigs.k8s.io/dra-example-driver/api/example.com/resource/gpu/v1alpha1"
3836
"sigs.k8s.io/dra-example-driver/pkg/consts"
3937
"sigs.k8s.io/dra-example-driver/pkg/flags"
4038
)
4139

42-
var (
43-
resourceClaimResource = metav1.GroupVersionResource{
44-
Group: resourceapi.SchemeGroupVersion.Group,
45-
Version: resourceapi.SchemeGroupVersion.Version,
46-
Resource: "resourceclaims",
47-
}
48-
resourceClaimTemplateResource = metav1.GroupVersionResource{
49-
Group: resourceapi.SchemeGroupVersion.Group,
50-
Version: resourceapi.SchemeGroupVersion.Version,
51-
Resource: "resourceclaimtemplates",
52-
}
53-
)
54-
5540
type Flags struct {
5641
loggingConfig *flags.LoggingConfig
5742

@@ -60,13 +45,6 @@ type Flags struct {
6045
port int
6146
}
6247

63-
var scheme = runtime.NewScheme()
64-
var codecs = serializer.NewCodecFactory(scheme)
65-
66-
func init() {
67-
utilruntime.Must(admissionv1.AddToScheme(scheme))
68-
}
69-
7048
func main() {
7149
if err := newApp().Run(os.Args); err != nil {
7250
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
@@ -219,13 +197,10 @@ func admitResourceClaimParameters(ar admissionv1.AdmissionReview) *admissionv1.A
219197
var deviceConfigs []resourceapi.DeviceClaimConfiguration
220198
var specPath string
221199

222-
raw := ar.Request.Object.Raw
223-
deserializer := codecs.UniversalDeserializer()
224-
225200
switch ar.Request.Resource {
226-
case resourceClaimResource:
227-
claim := resourceapi.ResourceClaim{}
228-
if _, _, err := deserializer.Decode(raw, nil, &claim); err != nil {
201+
case resourceClaimResourceV1, resourceClaimResourceV1Beta1, resourceClaimResourceV1Beta2:
202+
claim, err := extractResourceClaim(ar)
203+
if err != nil {
229204
klog.Error(err)
230205
return &admissionv1.AdmissionResponse{
231206
Result: &metav1.Status{
@@ -236,9 +211,9 @@ func admitResourceClaimParameters(ar admissionv1.AdmissionReview) *admissionv1.A
236211
}
237212
deviceConfigs = claim.Spec.Devices.Config
238213
specPath = "spec"
239-
case resourceClaimTemplateResource:
240-
claimTemplate := resourceapi.ResourceClaimTemplate{}
241-
if _, _, err := deserializer.Decode(raw, nil, &claimTemplate); err != nil {
214+
case resourceClaimTemplateResourceV1, resourceClaimTemplateResourceV1Beta1, resourceClaimTemplateResourceV1Beta2:
215+
claimTemplate, err := extractResourceClaimTemplate(ar)
216+
if err != nil {
242217
klog.Error(err)
243218
return &admissionv1.AdmissionResponse{
244219
Result: &metav1.Status{
@@ -250,7 +225,14 @@ func admitResourceClaimParameters(ar admissionv1.AdmissionReview) *admissionv1.A
250225
deviceConfigs = claimTemplate.Spec.Spec.Devices.Config
251226
specPath = "spec.spec"
252227
default:
253-
msg := fmt.Sprintf("expected resource to be %s or %s, got %s", resourceClaimResource, resourceClaimTemplateResource, ar.Request.Resource)
228+
msg := fmt.Sprintf(
229+
"expected resource to be one of %v, got %s",
230+
[]metav1.GroupVersionResource{
231+
resourceClaimResourceV1, resourceClaimResourceV1Beta1, resourceClaimResourceV1Beta2,
232+
resourceClaimTemplateResourceV1, resourceClaimTemplateResourceV1Beta1, resourceClaimTemplateResourceV1Beta2,
233+
},
234+
ar.Request.Resource,
235+
)
254236
klog.Error(msg)
255237
return &admissionv1.AdmissionResponse{
256238
Result: &metav1.Status{

cmd/dra-example-webhook/main_test.go

Lines changed: 99 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package main
1919
import (
2020
"bytes"
2121
"encoding/json"
22+
"fmt"
2223
"io"
2324
"net/http"
2425
"net/http/httptest"
@@ -28,7 +29,8 @@ import (
2829
"github.com/stretchr/testify/require"
2930

3031
admissionv1 "k8s.io/api/admission/v1"
31-
resourceapi "k8s.io/api/resource/v1beta1"
32+
resourceapi "k8s.io/api/resource/v1"
33+
resourcev1beta1 "k8s.io/api/resource/v1beta1"
3234
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3335
"k8s.io/apimachinery/pkg/runtime"
3436
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -47,6 +49,40 @@ func TestReadyEndpoint(t *testing.T) {
4749
}
4850

4951
func TestResourceClaimValidatingWebhook(t *testing.T) {
52+
unknownResource := metav1.GroupVersionResource{
53+
Group: "resource.k8s.io",
54+
Version: "v1",
55+
Resource: "unknownresources",
56+
}
57+
58+
validGPUConfig := &configapi.GpuConfig{
59+
Sharing: &configapi.GpuSharing{
60+
Strategy: configapi.TimeSlicingStrategy,
61+
TimeSlicingConfig: &configapi.TimeSlicingConfig{
62+
Interval: configapi.DefaultTimeSlice,
63+
},
64+
},
65+
}
66+
67+
invalidGPUConfigs := []*configapi.GpuConfig{
68+
{
69+
Sharing: &configapi.GpuSharing{
70+
Strategy: configapi.TimeSlicingStrategy,
71+
TimeSlicingConfig: &configapi.TimeSlicingConfig{
72+
Interval: "InvalidInterval",
73+
},
74+
},
75+
},
76+
{
77+
Sharing: &configapi.GpuSharing{
78+
Strategy: configapi.SpacePartitioningStrategy,
79+
SpacePartitioningConfig: &configapi.SpacePartitioningConfig{
80+
PartitionCount: -1,
81+
},
82+
},
83+
},
84+
}
85+
5086
tests := map[string]struct {
5187
admissionReview *admissionv1.AdmissionReview
5288
requestContentType string
@@ -64,86 +100,72 @@ func TestResourceClaimValidatingWebhook(t *testing.T) {
64100
},
65101
"valid GpuConfig in ResourceClaim": {
66102
admissionReview: admissionReviewWithObject(
67-
resourceClaimWithGpuConfigs(
68-
&configapi.GpuConfig{
69-
Sharing: &configapi.GpuSharing{
70-
Strategy: configapi.TimeSlicingStrategy,
71-
TimeSlicingConfig: &configapi.TimeSlicingConfig{
72-
Interval: configapi.DefaultTimeSlice,
73-
},
74-
},
75-
},
76-
),
77-
resourceClaimResource,
103+
resourceClaimWithGpuConfigs(validGPUConfig),
104+
resourceClaimResourceV1,
78105
),
79106
expectedAllowed: true,
80107
},
81108
"invalid GpuConfigs in ResourceClaim": {
82109
admissionReview: admissionReviewWithObject(
83-
resourceClaimWithGpuConfigs(
84-
&configapi.GpuConfig{
85-
Sharing: &configapi.GpuSharing{
86-
Strategy: configapi.TimeSlicingStrategy,
87-
TimeSlicingConfig: &configapi.TimeSlicingConfig{
88-
Interval: "InvalidInterval",
89-
},
90-
},
91-
},
92-
&configapi.GpuConfig{
93-
Sharing: &configapi.GpuSharing{
94-
Strategy: configapi.SpacePartitioningStrategy,
95-
SpacePartitioningConfig: &configapi.SpacePartitioningConfig{
96-
PartitionCount: -1,
97-
},
98-
},
99-
},
100-
),
101-
resourceClaimResource,
110+
resourceClaimWithGpuConfigs(invalidGPUConfigs...),
111+
resourceClaimResourceV1,
102112
),
103113
expectedAllowed: false,
104114
expectedMessage: "2 configs failed to validate: object at spec.devices.config[0].opaque.parameters is invalid: unknown time-slice interval: InvalidInterval; object at spec.devices.config[1].opaque.parameters is invalid: invalid partition count: -1",
105115
},
106116
"valid GpuConfig in ResourceClaimTemplate": {
107117
admissionReview: admissionReviewWithObject(
108-
resourceClaimTemplateWithGpuConfigs(
109-
&configapi.GpuConfig{
110-
Sharing: &configapi.GpuSharing{
111-
Strategy: configapi.TimeSlicingStrategy,
112-
TimeSlicingConfig: &configapi.TimeSlicingConfig{
113-
Interval: configapi.DefaultTimeSlice,
114-
},
115-
},
116-
},
117-
),
118-
resourceClaimTemplateResource,
118+
resourceClaimTemplateWithGpuConfigs(validGPUConfig),
119+
resourceClaimTemplateResourceV1,
119120
),
120121
expectedAllowed: true,
121122
},
122123
"invalid GpuConfigs in ResourceClaimTemplate": {
123124
admissionReview: admissionReviewWithObject(
124-
resourceClaimTemplateWithGpuConfigs(
125-
&configapi.GpuConfig{
126-
Sharing: &configapi.GpuSharing{
127-
Strategy: configapi.TimeSlicingStrategy,
128-
TimeSlicingConfig: &configapi.TimeSlicingConfig{
129-
Interval: "InvalidInterval",
130-
},
131-
},
132-
},
133-
&configapi.GpuConfig{
134-
Sharing: &configapi.GpuSharing{
135-
Strategy: configapi.SpacePartitioningStrategy,
136-
SpacePartitioningConfig: &configapi.SpacePartitioningConfig{
137-
PartitionCount: -1,
138-
},
139-
},
140-
},
141-
),
142-
resourceClaimTemplateResource,
125+
resourceClaimTemplateWithGpuConfigs(invalidGPUConfigs...),
126+
resourceClaimTemplateResourceV1,
127+
),
128+
expectedAllowed: false,
129+
expectedMessage: "2 configs failed to validate: object at spec.spec.devices.config[0].opaque.parameters is invalid: unknown time-slice interval: InvalidInterval; object at spec.spec.devices.config[1].opaque.parameters is invalid: invalid partition count: -1",
130+
},
131+
"valid GpuConfig in ResourceClaim v1beta1": {
132+
admissionReview: admissionReviewWithObject(
133+
toResourceClaimV1Beta1(resourceClaimWithGpuConfigs(validGPUConfig)),
134+
resourceClaimResourceV1Beta1,
135+
),
136+
expectedAllowed: true,
137+
},
138+
"invalid GpuConfigs in ResourceClaim v1beta1": {
139+
admissionReview: admissionReviewWithObject(
140+
toResourceClaimV1Beta1(resourceClaimWithGpuConfigs(invalidGPUConfigs...)),
141+
resourceClaimResourceV1Beta1,
142+
),
143+
expectedAllowed: false,
144+
expectedMessage: "2 configs failed to validate: object at spec.devices.config[0].opaque.parameters is invalid: unknown time-slice interval: InvalidInterval; object at spec.devices.config[1].opaque.parameters is invalid: invalid partition count: -1",
145+
},
146+
"valid GpuConfig in ResourceClaimTemplate v1beta1": {
147+
admissionReview: admissionReviewWithObject(
148+
toResourceClaimTemplateV1Beta1(resourceClaimTemplateWithGpuConfigs(validGPUConfig)),
149+
resourceClaimTemplateResourceV1Beta1,
150+
),
151+
expectedAllowed: true,
152+
},
153+
"invalid GpuConfigs in ResourceClaimTemplate v1beta1": {
154+
admissionReview: admissionReviewWithObject(
155+
toResourceClaimTemplateV1Beta1(resourceClaimTemplateWithGpuConfigs(invalidGPUConfigs...)),
156+
resourceClaimTemplateResourceV1Beta1,
143157
),
144158
expectedAllowed: false,
145159
expectedMessage: "2 configs failed to validate: object at spec.spec.devices.config[0].opaque.parameters is invalid: unknown time-slice interval: InvalidInterval; object at spec.spec.devices.config[1].opaque.parameters is invalid: invalid partition count: -1",
146160
},
161+
"unknown resource type": {
162+
admissionReview: admissionReviewWithObject(
163+
resourceClaimWithGpuConfigs(validGPUConfig),
164+
unknownResource,
165+
),
166+
expectedAllowed: false,
167+
expectedMessage: "expected resource to be one of [{resource.k8s.io v1 resourceclaims} {resource.k8s.io v1beta1 resourceclaims} {resource.k8s.io v1beta2 resourceclaims} {resource.k8s.io v1 resourceclaimtemplates} {resource.k8s.io v1beta1 resourceclaimtemplates} {resource.k8s.io v1beta2 resourceclaimtemplates}], got {resource.k8s.io v1 unknownresources}",
168+
},
147169
}
148170

149171
s := httptest.NewServer(newMux())
@@ -238,3 +260,19 @@ func resourceClaimSpecWithGpuConfigs(gpuConfigs ...*configapi.GpuConfig) resourc
238260
}
239261
return resourceClaimSpec
240262
}
263+
264+
func toResourceClaimV1Beta1(v1Claim *resourceapi.ResourceClaim) *resourcev1beta1.ResourceClaim {
265+
v1beta1Claim := &resourcev1beta1.ResourceClaim{}
266+
if err := scheme.Convert(v1Claim, v1beta1Claim, nil); err != nil {
267+
panic(fmt.Sprintf("failed to convert ResourceClaim to v1beta1: %v", err))
268+
}
269+
return v1beta1Claim
270+
}
271+
272+
func toResourceClaimTemplateV1Beta1(v1Template *resourceapi.ResourceClaimTemplate) *resourcev1beta1.ResourceClaimTemplate {
273+
v1beta1Template := &resourcev1beta1.ResourceClaimTemplate{}
274+
if err := scheme.Convert(v1Template, v1beta1Template, nil); err != nil {
275+
panic(fmt.Sprintf("failed to convert ResourceClaimTemplate to v1beta1: %v", err))
276+
}
277+
return v1beta1Template
278+
}

0 commit comments

Comments
 (0)