Merge pull request #132700 from pohly/dra-kubelet-grpc-v1

DRA kubelet: add v1 gRPC
This commit is contained in:
Kubernetes Prow Robot
2025-07-23 17:36:26 -07:00
committed by GitHub
12 changed files with 3276 additions and 63 deletions

View File

@@ -32,7 +32,7 @@ import (
"k8s.io/component-base/metrics"
"k8s.io/dynamic-resource-allocation/resourceclaim"
"k8s.io/klog/v2"
drapb "k8s.io/kubelet/pkg/apis/dra/v1beta1"
drapb "k8s.io/kubelet/pkg/apis/dra/v1"
draplugin "k8s.io/kubernetes/pkg/kubelet/cm/dra/plugin"
"k8s.io/kubernetes/pkg/kubelet/cm/dra/state"
"k8s.io/kubernetes/pkg/kubelet/config"

View File

@@ -25,6 +25,7 @@ import (
"google.golang.org/grpc/status"
"k8s.io/klog/v2"
drapbv1 "k8s.io/kubelet/pkg/apis/dra/v1"
drapbv1beta1 "k8s.io/kubelet/pkg/apis/dra/v1beta1"
"k8s.io/kubernetes/pkg/kubelet/metrics"
)
@@ -41,6 +42,7 @@ const defaultClientCallTimeout = 45 * time.Second
// All API versions supported by this wrapper.
// Sorted by most recent first, oldest last.
var servicesSupportedByKubelet = []string{
drapbv1.DRAPluginService,
drapbv1beta1.DRAPluginService,
}
@@ -51,7 +53,7 @@ type DRAPlugin struct {
driverName string
conn *grpc.ClientConn
endpoint string
chosenService string // e.g. drapbv1beta1.DRAPluginService
chosenService string // e.g. drapbv1.DRAPluginService
clientCallTimeout time.Duration
}
@@ -61,9 +63,9 @@ func (p *DRAPlugin) DriverName() string {
func (p *DRAPlugin) NodePrepareResources(
ctx context.Context,
req *drapbv1beta1.NodePrepareResourcesRequest,
req *drapbv1.NodePrepareResourcesRequest,
opts ...grpc.CallOption,
) (*drapbv1beta1.NodePrepareResourcesResponse, error) {
) (*drapbv1.NodePrepareResourcesResponse, error) {
logger := klog.FromContext(ctx)
logger = klog.LoggerWithValues(logger, "driverName", p.driverName, "endpoint", p.endpoint)
ctx = klog.NewContext(ctx, logger)
@@ -73,11 +75,14 @@ func (p *DRAPlugin) NodePrepareResources(
defer cancel()
var err error
var response *drapbv1beta1.NodePrepareResourcesResponse
var response *drapbv1.NodePrepareResourcesResponse
switch p.chosenService {
case drapbv1beta1.DRAPluginService:
nodeClient := drapbv1beta1.NewDRAPluginClient(p.conn)
response, err = nodeClient.NodePrepareResources(ctx, req)
client := drapbv1beta1.NewDRAPluginClient(p.conn)
response, err = drapbv1beta1.V1Beta1ClientWrapper{DRAPluginClient: client}.NodePrepareResources(ctx, req)
case drapbv1.DRAPluginService:
client := drapbv1.NewDRAPluginClient(p.conn)
response, err = client.NodePrepareResources(ctx, req)
default:
// Shouldn't happen, validateSupportedServices should only
// return services we support here.
@@ -89,9 +94,9 @@ func (p *DRAPlugin) NodePrepareResources(
func (p *DRAPlugin) NodeUnprepareResources(
ctx context.Context,
req *drapbv1beta1.NodeUnprepareResourcesRequest,
req *drapbv1.NodeUnprepareResourcesRequest,
opts ...grpc.CallOption,
) (*drapbv1beta1.NodeUnprepareResourcesResponse, error) {
) (*drapbv1.NodeUnprepareResourcesResponse, error) {
logger := klog.FromContext(ctx)
logger.V(4).Info("Calling NodeUnprepareResource rpc", "request", req)
logger = klog.LoggerWithValues(logger, "driverName", p.driverName, "endpoint", p.endpoint)
@@ -101,11 +106,14 @@ func (p *DRAPlugin) NodeUnprepareResources(
defer cancel()
var err error
var response *drapbv1beta1.NodeUnprepareResourcesResponse
var response *drapbv1.NodeUnprepareResourcesResponse
switch p.chosenService {
case drapbv1beta1.DRAPluginService:
nodeClient := drapbv1beta1.NewDRAPluginClient(p.conn)
response, err = nodeClient.NodeUnprepareResources(ctx, req)
client := drapbv1beta1.NewDRAPluginClient(p.conn)
response, err = drapbv1beta1.V1Beta1ClientWrapper{DRAPluginClient: client}.NodeUnprepareResources(ctx, req)
case drapbv1.DRAPluginService:
client := drapbv1.NewDRAPluginClient(p.conn)
response, err = client.NodeUnprepareResources(ctx, req)
default:
// Shouldn't happen, validateSupportedServices should only
// return services we support here.

View File

@@ -29,6 +29,7 @@ import (
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
drapbv1 "k8s.io/kubelet/pkg/apis/dra/v1"
drapbv1beta1 "k8s.io/kubelet/pkg/apis/dra/v1beta1"
"k8s.io/kubernetes/test/utils/ktesting"
)
@@ -36,11 +37,11 @@ import (
type fakeGRPCServer struct {
}
var _ drapbv1beta1.DRAPluginServer = &fakeGRPCServer{}
var _ drapbv1.DRAPluginServer = &fakeGRPCServer{}
func (f *fakeGRPCServer) NodePrepareResources(ctx context.Context, in *drapbv1beta1.NodePrepareResourcesRequest) (*drapbv1beta1.NodePrepareResourcesResponse, error) {
return &drapbv1beta1.NodePrepareResourcesResponse{Claims: map[string]*drapbv1beta1.NodePrepareResourceResponse{"claim-uid": {
Devices: []*drapbv1beta1.Device{
func (f *fakeGRPCServer) NodePrepareResources(ctx context.Context, in *drapbv1.NodePrepareResourcesRequest) (*drapbv1.NodePrepareResourcesResponse, error) {
return &drapbv1.NodePrepareResourcesResponse{Claims: map[string]*drapbv1.NodePrepareResourceResponse{"claim-uid": {
Devices: []*drapbv1.Device{
{
RequestNames: []string{"test-request"},
CDIDeviceIDs: []string{"test-cdi-id"},
@@ -49,9 +50,9 @@ func (f *fakeGRPCServer) NodePrepareResources(ctx context.Context, in *drapbv1be
}}}, nil
}
func (f *fakeGRPCServer) NodeUnprepareResources(ctx context.Context, in *drapbv1beta1.NodeUnprepareResourcesRequest) (*drapbv1beta1.NodeUnprepareResourcesResponse, error) {
func (f *fakeGRPCServer) NodeUnprepareResources(ctx context.Context, in *drapbv1.NodeUnprepareResourcesRequest) (*drapbv1.NodeUnprepareResourcesResponse, error) {
return &drapbv1beta1.NodeUnprepareResourcesResponse{}, nil
return &drapbv1.NodeUnprepareResourcesResponse{}, nil
}
// tearDown is an idempotent cleanup function.
@@ -72,8 +73,10 @@ func setupFakeGRPCServer(service, addr string) (tearDown, error) {
s := grpc.NewServer()
fakeGRPCServer := &fakeGRPCServer{}
switch service {
case drapbv1.DRAPluginService:
drapbv1.RegisterDRAPluginServer(s, fakeGRPCServer)
case drapbv1beta1.DRAPluginService:
drapbv1beta1.RegisterDRAPluginServer(s, fakeGRPCServer)
drapbv1beta1.RegisterDRAPluginServer(s, drapbv1beta1.V1ServerWrapper{DRAPluginServer: fakeGRPCServer})
default:
return nil, fmt.Errorf("unsupported gRPC service: %s", service)
}
@@ -93,7 +96,7 @@ func setupFakeGRPCServer(service, addr string) (tearDown, error) {
func TestGRPCConnIsReused(t *testing.T) {
tCtx := ktesting.Init(t)
service := drapbv1beta1.DRAPluginService
service := drapbv1.DRAPluginService
addr := path.Join(t.TempDir(), "dra.sock")
teardown, err := setupFakeGRPCServer(service, addr)
if err != nil {
@@ -125,8 +128,8 @@ func TestGRPCConnIsReused(t *testing.T) {
return
}
req := &drapbv1beta1.NodePrepareResourcesRequest{
Claims: []*drapbv1beta1.Claim{
req := &drapbv1.NodePrepareResourcesRequest{
Claims: []*drapbv1.Claim{
{
Namespace: "dummy-namespace",
UID: "dummy-uid",
@@ -210,10 +213,22 @@ func TestGRPCMethods(t *testing.T) {
service: drapbv1beta1.DRAPluginService,
chosenService: drapbv1beta1.DRAPluginService,
},
{
description: "v1",
service: drapbv1.DRAPluginService,
chosenService: drapbv1.DRAPluginService,
},
{
// In practice, such a mismatch between plugin and kubelet should not happen.
description: "mismatch",
service: drapbv1.DRAPluginService,
chosenService: drapbv1beta1.DRAPluginService,
expectError: "unknown service k8s.io.kubelet.pkg.apis.dra.v1beta1.DRAPlugin",
},
{
// In practice, kubelet wouldn't choose an invalid service.
description: "internal-error",
service: drapbv1beta1.DRAPluginService,
service: drapbv1.DRAPluginService,
chosenService: "some-other-service",
expectError: "unsupported chosen service",
},
@@ -235,10 +250,10 @@ func TestGRPCMethods(t *testing.T) {
t.Fatal(err)
}
_, err = plugin.NodePrepareResources(tCtx, &drapbv1beta1.NodePrepareResourcesRequest{})
_, err = plugin.NodePrepareResources(tCtx, &drapbv1.NodePrepareResourcesRequest{})
assertError(t, test.expectError, err)
_, err = plugin.NodeUnprepareResources(tCtx, &drapbv1beta1.NodeUnprepareResourcesRequest{})
_, err = plugin.NodeUnprepareResources(tCtx, &drapbv1.NodeUnprepareResourcesRequest{})
assertError(t, test.expectError, err)
})
}

View File

@@ -37,7 +37,8 @@ import (
draclient "k8s.io/dynamic-resource-allocation/client"
"k8s.io/dynamic-resource-allocation/resourceclaim"
"k8s.io/dynamic-resource-allocation/resourceslice"
drapb "k8s.io/kubelet/pkg/apis/dra/v1beta1"
drapbv1 "k8s.io/kubelet/pkg/apis/dra/v1"
drapbv1beta1 "k8s.io/kubelet/pkg/apis/dra/v1beta1"
registerapi "k8s.io/kubelet/pkg/apis/pluginregistration/v1"
)
@@ -379,6 +380,18 @@ func NodeV1beta1(enabled bool) Option {
}
}
// NodeV1 explicitly chooses whether the DRA gRPC API v1
// gets enabled. True by default.
//
// This is used in Kubernetes for end-to-end testing. The default should
// be fine for DRA drivers.
func NodeV1(enabled bool) Option {
return func(o *options) error {
o.nodeV1 = enabled
return nil
}
}
// KubeClient grants the plugin access to the API server. This is needed
// for syncing ResourceSlice objects. It's the responsibility of the DRA driver
// developer to ensure that this client has permission to read, write,
@@ -471,6 +484,7 @@ type options struct {
serialize bool
flockDirectoryPath string
nodeV1beta1 bool
nodeV1 bool
registrationService bool
draService bool
}
@@ -520,6 +534,7 @@ func Start(ctx context.Context, plugin DRAPlugin, opts ...Option) (result *Helpe
grpcVerbosity: 6, // Logs requests and responses, which can be large.
serialize: true,
nodeV1beta1: true,
nodeV1: true,
pluginRegistrationEndpoint: endpoint{
dir: KubeletRegistryDir,
},
@@ -597,9 +612,11 @@ func Start(ctx context.Context, plugin DRAPlugin, opts ...Option) (result *Helpe
}()
var supportedServices []string
if o.nodeV1 {
supportedServices = append(supportedServices, drapbv1.DRAPluginService)
}
if o.nodeV1beta1 {
logger.V(5).Info("registering v1beta1.DRAPlugin gRPC service")
supportedServices = append(supportedServices, drapb.DRAPluginService)
supportedServices = append(supportedServices, drapbv1beta1.DRAPluginService)
}
if len(supportedServices) == 0 {
return nil, errors.New("no supported DRA gRPC API is implemented and enabled")
@@ -622,9 +639,13 @@ func Start(ctx context.Context, plugin DRAPlugin, opts ...Option) (result *Helpe
plugin.HandleError(ctx, err, "DRA gRPC server failed")
},
func(grpcServer *grpc.Server) {
if o.nodeV1 {
logger.V(5).Info("registering v1.DRAPlugin gRPC service")
drapbv1.RegisterDRAPluginServer(grpcServer, &nodePluginImplementation{Helper: d})
}
if o.nodeV1beta1 {
logger.V(5).Info("registering v1beta1.DRAPlugin gRPC service")
drapb.RegisterDRAPluginServer(grpcServer, &nodePluginImplementation{Helper: d})
drapbv1beta1.RegisterDRAPluginServer(grpcServer, drapbv1beta1.V1ServerWrapper{DRAPluginServer: &nodePluginImplementation{Helper: d}})
}
},
)
@@ -803,8 +824,8 @@ type nodePluginImplementation struct {
*Helper
}
// NodePrepareResources implements [drapb.NodePrepareResources].
func (d *nodePluginImplementation) NodePrepareResources(ctx context.Context, req *drapb.NodePrepareResourcesRequest) (*drapb.NodePrepareResourcesResponse, error) {
// NodePrepareResources implements [drapbv1.NodePrepareResources].
func (d *nodePluginImplementation) NodePrepareResources(ctx context.Context, req *drapbv1.NodePrepareResourcesRequest) (*drapbv1.NodePrepareResourcesResponse, error) {
// Do slow API calls before serializing.
claims, err := d.getResourceClaims(ctx, req.Claims)
if err != nil {
@@ -822,11 +843,11 @@ func (d *nodePluginImplementation) NodePrepareResources(ctx context.Context, req
return nil, fmt.Errorf("prepare resource claims: %w", err)
}
resp := &drapb.NodePrepareResourcesResponse{Claims: map[string]*drapb.NodePrepareResourceResponse{}}
resp := &drapbv1.NodePrepareResourcesResponse{Claims: map[string]*drapbv1.NodePrepareResourceResponse{}}
for uid, claimResult := range result {
var devices []*drapb.Device
var devices []*drapbv1.Device
for _, result := range claimResult.Devices {
device := &drapb.Device{
device := &drapbv1.Device{
RequestNames: stripSubrequestNames(result.Requests),
PoolName: result.PoolName,
DeviceName: result.DeviceName,
@@ -834,7 +855,7 @@ func (d *nodePluginImplementation) NodePrepareResources(ctx context.Context, req
}
devices = append(devices, device)
}
resp.Claims[string(uid)] = &drapb.NodePrepareResourceResponse{
resp.Claims[string(uid)] = &drapbv1.NodePrepareResourceResponse{
Error: errorString(claimResult.Err),
Devices: devices,
}
@@ -857,7 +878,7 @@ func stripSubrequestNames(names []string) []string {
return stripped
}
func (d *nodePluginImplementation) getResourceClaims(ctx context.Context, claims []*drapb.Claim) ([]*resourceapi.ResourceClaim, error) {
func (d *nodePluginImplementation) getResourceClaims(ctx context.Context, claims []*drapbv1.Claim) ([]*resourceapi.ResourceClaim, error) {
var resourceClaims []*resourceapi.ResourceClaim
for _, claimReq := range claims {
claim, err := d.resourceClient.ResourceClaims(claimReq.Namespace).Get(ctx, claimReq.Name, metav1.GetOptions{})
@@ -876,7 +897,7 @@ func (d *nodePluginImplementation) getResourceClaims(ctx context.Context, claims
}
// NodeUnprepareResources implements [draapi.NodeUnprepareResources].
func (d *nodePluginImplementation) NodeUnprepareResources(ctx context.Context, req *drapb.NodeUnprepareResourcesRequest) (*drapb.NodeUnprepareResourcesResponse, error) {
func (d *nodePluginImplementation) NodeUnprepareResources(ctx context.Context, req *drapbv1.NodeUnprepareResourcesRequest) (*drapbv1.NodeUnprepareResourcesResponse, error) {
unlock, err := d.serializeGRPCIfEnabled()
if err != nil {
return nil, fmt.Errorf("serialize gRPC: %w", err)
@@ -892,9 +913,9 @@ func (d *nodePluginImplementation) NodeUnprepareResources(ctx context.Context, r
return nil, fmt.Errorf("unprepare resource claims: %w", err)
}
resp := &drapb.NodeUnprepareResourcesResponse{Claims: map[string]*drapb.NodeUnprepareResourceResponse{}}
resp := &drapbv1.NodeUnprepareResourcesResponse{Claims: map[string]*drapbv1.NodeUnprepareResourceResponse{}}
for uid, err := range result {
resp.Claims[string(uid)] = &drapb.NodeUnprepareResourceResponse{
resp.Claims[string(uid)] = &drapbv1.NodeUnprepareResourceResponse{
Error: errorString(err),
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,118 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// To regenerate api.pb.go run `hack/update-codegen.sh protobindings`
syntax = "proto3";
package k8s.io.kubelet.pkg.apis.dra.v1;
option go_package = "k8s.io/kubelet/pkg/apis/dra/v1";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
option (gogoproto.goproto_stringer_all) = false;
option (gogoproto.stringer_all) = true;
option (gogoproto.goproto_getters_all) = true;
option (gogoproto.marshaler_all) = true;
option (gogoproto.sizer_all) = true;
option (gogoproto.unmarshaler_all) = true;
option (gogoproto.goproto_unrecognized_all) = false;
service DRAPlugin {
// NodePrepareResources prepares several ResourceClaims
// for use on the node. If an error is returned, the
// response is ignored. Failures for individual claims
// can be reported inside NodePrepareResourcesResponse.
rpc NodePrepareResources (NodePrepareResourcesRequest)
returns (NodePrepareResourcesResponse) {}
// NodeUnprepareResources is the opposite of NodePrepareResources.
// The same error handling rules apply,
rpc NodeUnprepareResources (NodeUnprepareResourcesRequest)
returns (NodeUnprepareResourcesResponse) {}
}
message NodePrepareResourcesRequest {
// The list of ResourceClaims that are to be prepared.
repeated Claim claims = 1;
}
message NodePrepareResourcesResponse {
// The ResourceClaims for which preparation was done
// or attempted, with claim_uid as key.
//
// It is an error if some claim listed in NodePrepareResourcesRequest
// does not get prepared. NodePrepareResources
// will be called again for those that are missing.
map<string, NodePrepareResourceResponse> claims = 1;
}
message NodePrepareResourceResponse {
// These are the additional devices that kubelet must
// make available via the container runtime. A claim
// may have zero or more requests and each request
// may have zero or more devices.
repeated Device devices = 1;
// If non-empty, preparing the ResourceClaim failed.
// Devices are ignored in that case.
string error = 2;
}
message Device {
// The requests in the claim that this device is associated with.
// Optional. If empty, the device is associated with all requests.
repeated string request_names = 1;
// The pool which contains the device. Required.
string pool_name = 2;
// The device itself. Required.
string device_name = 3;
// A single device instance may map to several CDI device IDs.
// None is also valid.
repeated string cdi_device_ids = 4 [(gogoproto.customname) = "CDIDeviceIDs"];
}
message NodeUnprepareResourcesRequest {
// The list of ResourceClaims that are to be unprepared.
repeated Claim claims = 1;
}
message NodeUnprepareResourcesResponse {
// The ResourceClaims for which preparation was reverted.
// The same rules as for NodePrepareResourcesResponse.claims
// apply. In particular, all claims in the request must
// have an entry in the response, even if that entry is nil.
map<string, NodeUnprepareResourceResponse> claims = 1;
}
message NodeUnprepareResourceResponse {
// If non-empty, unpreparing the ResourceClaim failed.
string error = 1;
}
message Claim {
// The ResourceClaim namespace (ResourceClaim.meta.Namespace).
// This field is REQUIRED.
string namespace = 1;
// The UID of the Resource claim (ResourceClaim.meta.UUID).
// This field is REQUIRED.
string uid = 2 [(gogoproto.customname) = "UID"];
// The name of the Resource claim (ResourceClaim.meta.Name)
// This field is REQUIRED.
string name = 3;
}

View File

@@ -0,0 +1,24 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
const (
// DRAPluginService needs to be listed in the "supported versions"
// array during plugin registration by a DRA plugin which provides
// an implementation of the v1 DRAPlugin service.
DRAPluginService = "v1.DRAPlugin"
)

View File

@@ -0,0 +1,188 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
context "context"
fmt "fmt"
grpc "google.golang.org/grpc"
"k8s.io/apimachinery/pkg/runtime"
v1 "k8s.io/kubelet/pkg/apis/dra/v1"
)
var (
localSchemeBuilder runtime.SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)
// V1ServerWrapper implements the [NodeServer] interface by wrapping a [v1.DRAPluginServer].
type V1ServerWrapper struct {
v1.DRAPluginServer
}
var _ DRAPluginServer = V1ServerWrapper{}
func (w V1ServerWrapper) NodePrepareResources(ctx context.Context, req *NodePrepareResourcesRequest) (*NodePrepareResourcesResponse, error) {
var convertedReq v1.NodePrepareResourcesRequest
if err := Convert_v1beta1_NodePrepareResourcesRequest_To_v1_NodePrepareResourcesRequest(req, &convertedReq, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodePrepareResourcesRequest from v1beta1 to v1: %w", err)
}
resp, err := w.DRAPluginServer.NodePrepareResources(ctx, &convertedReq)
if err != nil {
return nil, err
}
var convertedResp NodePrepareResourcesResponse
if err := Convert_v1_NodePrepareResourcesResponse_To_v1beta1_NodePrepareResourcesResponse(resp, &convertedResp, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodePrepareResourcesResponse from v1 to v1beta1: %w", err)
}
return &convertedResp, nil
}
func (w V1ServerWrapper) NodeUnprepareResources(ctx context.Context, req *NodeUnprepareResourcesRequest) (*NodeUnprepareResourcesResponse, error) {
var convertedReq v1.NodeUnprepareResourcesRequest
if err := Convert_v1beta1_NodeUnprepareResourcesRequest_To_v1_NodeUnprepareResourcesRequest(req, &convertedReq, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesRequest from v1beta1 to v1: %w", err)
}
resp, err := w.DRAPluginServer.NodeUnprepareResources(ctx, &convertedReq)
if err != nil {
return nil, err
}
var convertedResp NodeUnprepareResourcesResponse
if err := Convert_v1_NodeUnprepareResourcesResponse_To_v1beta1_NodeUnprepareResourcesResponse(resp, &convertedResp, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesResponse from v1 to v1beta1: %w", err)
}
return &convertedResp, nil
}
// V1Beta1ServerWrapper implements the [v1.DRAPluginServer] interface by wrapping a [NodeServer].
type V1Beta1ServerWrapper struct {
DRAPluginServer
}
var _ v1.DRAPluginServer = V1Beta1ServerWrapper{}
func (w V1Beta1ServerWrapper) NodePrepareResources(ctx context.Context, req *v1.NodePrepareResourcesRequest) (*v1.NodePrepareResourcesResponse, error) {
var convertedReq NodePrepareResourcesRequest
if err := Convert_v1_NodePrepareResourcesRequest_To_v1beta1_NodePrepareResourcesRequest(req, &convertedReq, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodePrepareResourcesRequest from v1 to v1beta1: %w", err)
}
resp, err := w.DRAPluginServer.NodePrepareResources(ctx, &convertedReq)
if err != nil {
return nil, err
}
var convertedResp v1.NodePrepareResourcesResponse
if err := Convert_v1beta1_NodePrepareResourcesResponse_To_v1_NodePrepareResourcesResponse(resp, &convertedResp, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodePrepareResourcesResponse from v1beta1 to v1: %w", err)
}
return &convertedResp, nil
}
func (w V1Beta1ServerWrapper) NodeUnprepareResources(ctx context.Context, req *v1.NodeUnprepareResourcesRequest) (*v1.NodeUnprepareResourcesResponse, error) {
var convertedReq NodeUnprepareResourcesRequest
if err := Convert_v1_NodeUnprepareResourcesRequest_To_v1beta1_NodeUnprepareResourcesRequest(req, &convertedReq, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesRequest from v1 to v1beta1: %w", err)
}
resp, err := w.DRAPluginServer.NodeUnprepareResources(ctx, &convertedReq)
if err != nil {
return nil, err
}
var convertedResp v1.NodeUnprepareResourcesResponse
if err := Convert_v1beta1_NodeUnprepareResourcesResponse_To_v1_NodeUnprepareResourcesResponse(resp, &convertedResp, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesResponse from v1beta1 to v1: %w", err)
}
return &convertedResp, nil
}
// V1ClientWrapper implements the [NodeClient] interface by wrapping a [v1.DRAPluginClient].
type V1ClientWrapper struct {
v1.DRAPluginClient
}
var _ DRAPluginClient = V1ClientWrapper{}
func (w V1ClientWrapper) NodePrepareResources(ctx context.Context, req *NodePrepareResourcesRequest, options ...grpc.CallOption) (*NodePrepareResourcesResponse, error) {
var convertedReq v1.NodePrepareResourcesRequest
if err := Convert_v1beta1_NodePrepareResourcesRequest_To_v1_NodePrepareResourcesRequest(req, &convertedReq, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodePrepareResourcesRequest from v1beta1 to v1: %w", err)
}
resp, err := w.DRAPluginClient.NodePrepareResources(ctx, &convertedReq, options...)
if err != nil {
return nil, err
}
var convertedResp NodePrepareResourcesResponse
if err := Convert_v1_NodePrepareResourcesResponse_To_v1beta1_NodePrepareResourcesResponse(resp, &convertedResp, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodePrepareResourcesResponse from v1 to v1beta1: %w", err)
}
return &convertedResp, nil
}
func (w V1ClientWrapper) NodeUnprepareResources(ctx context.Context, req *NodeUnprepareResourcesRequest, options ...grpc.CallOption) (*NodeUnprepareResourcesResponse, error) {
var convertedReq v1.NodeUnprepareResourcesRequest
if err := Convert_v1beta1_NodeUnprepareResourcesRequest_To_v1_NodeUnprepareResourcesRequest(req, &convertedReq, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesRequest from v1beta1 to v1: %w", err)
}
resp, err := w.DRAPluginClient.NodeUnprepareResources(ctx, &convertedReq, options...)
if err != nil {
return nil, err
}
var convertedResp NodeUnprepareResourcesResponse
if err := Convert_v1_NodeUnprepareResourcesResponse_To_v1beta1_NodeUnprepareResourcesResponse(resp, &convertedResp, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesResponse from v1 to v1beta1: %w", err)
}
return &convertedResp, nil
}
// V1Beta1ClientWrapper implements the [v1.DRAPluginClient] interface by wrapping a [NodeClient].
type V1Beta1ClientWrapper struct {
DRAPluginClient
}
var _ v1.DRAPluginClient = V1Beta1ClientWrapper{}
func (w V1Beta1ClientWrapper) NodePrepareResources(ctx context.Context, req *v1.NodePrepareResourcesRequest, options ...grpc.CallOption) (*v1.NodePrepareResourcesResponse, error) {
var convertedReq NodePrepareResourcesRequest
if err := Convert_v1_NodePrepareResourcesRequest_To_v1beta1_NodePrepareResourcesRequest(req, &convertedReq, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodePrepareResourcesRequest from v1 to v1beta1: %w", err)
}
resp, err := w.DRAPluginClient.NodePrepareResources(ctx, &convertedReq, options...)
if err != nil {
return nil, err
}
var convertedResp v1.NodePrepareResourcesResponse
if err := Convert_v1beta1_NodePrepareResourcesResponse_To_v1_NodePrepareResourcesResponse(resp, &convertedResp, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodePrepareResourcesResponse from v1beta1 to v1: %w", err)
}
return &convertedResp, nil
}
func (w V1Beta1ClientWrapper) NodeUnprepareResources(ctx context.Context, req *v1.NodeUnprepareResourcesRequest, options ...grpc.CallOption) (*v1.NodeUnprepareResourcesResponse, error) {
var convertedReq NodeUnprepareResourcesRequest
if err := Convert_v1_NodeUnprepareResourcesRequest_To_v1beta1_NodeUnprepareResourcesRequest(req, &convertedReq, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesRequest from v1 to v1beta1: %w", err)
}
resp, err := w.DRAPluginClient.NodeUnprepareResources(ctx, &convertedReq, options...)
if err != nil {
return nil, err
}
var convertedResp v1.NodeUnprepareResourcesResponse
if err := Convert_v1beta1_NodeUnprepareResourcesResponse_To_v1_NodeUnprepareResourcesResponse(resp, &convertedResp, nil); err != nil {
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesResponse from v1beta1 to v1: %w", err)
}
return &convertedResp, nil
}

View File

@@ -0,0 +1,21 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package v1beta1 contains a legacy implementation of the DRA gRPC
// interface. Support for it in kubelet is provided via conversion.
//
// +k8s:conversion-gen=k8s.io/kubelet/pkg/apis/dra/v1
package v1beta1

View File

@@ -0,0 +1,352 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by conversion-gen. DO NOT EDIT.
package v1beta1
import (
unsafe "unsafe"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
v1 "k8s.io/kubelet/pkg/apis/dra/v1"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*Claim)(nil), (*v1.Claim)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_Claim_To_v1_Claim(a.(*Claim), b.(*v1.Claim), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.Claim)(nil), (*Claim)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_Claim_To_v1beta1_Claim(a.(*v1.Claim), b.(*Claim), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Device)(nil), (*v1.Device)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_Device_To_v1_Device(a.(*Device), b.(*v1.Device), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.Device)(nil), (*Device)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_Device_To_v1beta1_Device(a.(*v1.Device), b.(*Device), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*NodePrepareResourceResponse)(nil), (*v1.NodePrepareResourceResponse)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_NodePrepareResourceResponse_To_v1_NodePrepareResourceResponse(a.(*NodePrepareResourceResponse), b.(*v1.NodePrepareResourceResponse), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.NodePrepareResourceResponse)(nil), (*NodePrepareResourceResponse)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_NodePrepareResourceResponse_To_v1beta1_NodePrepareResourceResponse(a.(*v1.NodePrepareResourceResponse), b.(*NodePrepareResourceResponse), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*NodePrepareResourcesRequest)(nil), (*v1.NodePrepareResourcesRequest)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_NodePrepareResourcesRequest_To_v1_NodePrepareResourcesRequest(a.(*NodePrepareResourcesRequest), b.(*v1.NodePrepareResourcesRequest), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.NodePrepareResourcesRequest)(nil), (*NodePrepareResourcesRequest)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_NodePrepareResourcesRequest_To_v1beta1_NodePrepareResourcesRequest(a.(*v1.NodePrepareResourcesRequest), b.(*NodePrepareResourcesRequest), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*NodePrepareResourcesResponse)(nil), (*v1.NodePrepareResourcesResponse)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_NodePrepareResourcesResponse_To_v1_NodePrepareResourcesResponse(a.(*NodePrepareResourcesResponse), b.(*v1.NodePrepareResourcesResponse), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.NodePrepareResourcesResponse)(nil), (*NodePrepareResourcesResponse)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_NodePrepareResourcesResponse_To_v1beta1_NodePrepareResourcesResponse(a.(*v1.NodePrepareResourcesResponse), b.(*NodePrepareResourcesResponse), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*NodeUnprepareResourceResponse)(nil), (*v1.NodeUnprepareResourceResponse)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_NodeUnprepareResourceResponse_To_v1_NodeUnprepareResourceResponse(a.(*NodeUnprepareResourceResponse), b.(*v1.NodeUnprepareResourceResponse), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.NodeUnprepareResourceResponse)(nil), (*NodeUnprepareResourceResponse)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_NodeUnprepareResourceResponse_To_v1beta1_NodeUnprepareResourceResponse(a.(*v1.NodeUnprepareResourceResponse), b.(*NodeUnprepareResourceResponse), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*NodeUnprepareResourcesRequest)(nil), (*v1.NodeUnprepareResourcesRequest)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_NodeUnprepareResourcesRequest_To_v1_NodeUnprepareResourcesRequest(a.(*NodeUnprepareResourcesRequest), b.(*v1.NodeUnprepareResourcesRequest), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.NodeUnprepareResourcesRequest)(nil), (*NodeUnprepareResourcesRequest)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_NodeUnprepareResourcesRequest_To_v1beta1_NodeUnprepareResourcesRequest(a.(*v1.NodeUnprepareResourcesRequest), b.(*NodeUnprepareResourcesRequest), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*NodeUnprepareResourcesResponse)(nil), (*v1.NodeUnprepareResourcesResponse)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_NodeUnprepareResourcesResponse_To_v1_NodeUnprepareResourcesResponse(a.(*NodeUnprepareResourcesResponse), b.(*v1.NodeUnprepareResourcesResponse), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.NodeUnprepareResourcesResponse)(nil), (*NodeUnprepareResourcesResponse)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_NodeUnprepareResourcesResponse_To_v1beta1_NodeUnprepareResourcesResponse(a.(*v1.NodeUnprepareResourcesResponse), b.(*NodeUnprepareResourcesResponse), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*UnimplementedDRAPluginServer)(nil), (*v1.UnimplementedDRAPluginServer)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_UnimplementedDRAPluginServer_To_v1_UnimplementedDRAPluginServer(a.(*UnimplementedDRAPluginServer), b.(*v1.UnimplementedDRAPluginServer), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.UnimplementedDRAPluginServer)(nil), (*UnimplementedDRAPluginServer)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_UnimplementedDRAPluginServer_To_v1beta1_UnimplementedDRAPluginServer(a.(*v1.UnimplementedDRAPluginServer), b.(*UnimplementedDRAPluginServer), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1beta1_Claim_To_v1_Claim(in *Claim, out *v1.Claim, s conversion.Scope) error {
out.Namespace = in.Namespace
out.UID = in.UID
out.Name = in.Name
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1beta1_Claim_To_v1_Claim is an autogenerated conversion function.
func Convert_v1beta1_Claim_To_v1_Claim(in *Claim, out *v1.Claim, s conversion.Scope) error {
return autoConvert_v1beta1_Claim_To_v1_Claim(in, out, s)
}
func autoConvert_v1_Claim_To_v1beta1_Claim(in *v1.Claim, out *Claim, s conversion.Scope) error {
out.Namespace = in.Namespace
out.UID = in.UID
out.Name = in.Name
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1_Claim_To_v1beta1_Claim is an autogenerated conversion function.
func Convert_v1_Claim_To_v1beta1_Claim(in *v1.Claim, out *Claim, s conversion.Scope) error {
return autoConvert_v1_Claim_To_v1beta1_Claim(in, out, s)
}
func autoConvert_v1beta1_Device_To_v1_Device(in *Device, out *v1.Device, s conversion.Scope) error {
out.RequestNames = *(*[]string)(unsafe.Pointer(&in.RequestNames))
out.PoolName = in.PoolName
out.DeviceName = in.DeviceName
out.CDIDeviceIDs = *(*[]string)(unsafe.Pointer(&in.CDIDeviceIDs))
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1beta1_Device_To_v1_Device is an autogenerated conversion function.
func Convert_v1beta1_Device_To_v1_Device(in *Device, out *v1.Device, s conversion.Scope) error {
return autoConvert_v1beta1_Device_To_v1_Device(in, out, s)
}
func autoConvert_v1_Device_To_v1beta1_Device(in *v1.Device, out *Device, s conversion.Scope) error {
out.RequestNames = *(*[]string)(unsafe.Pointer(&in.RequestNames))
out.PoolName = in.PoolName
out.DeviceName = in.DeviceName
out.CDIDeviceIDs = *(*[]string)(unsafe.Pointer(&in.CDIDeviceIDs))
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1_Device_To_v1beta1_Device is an autogenerated conversion function.
func Convert_v1_Device_To_v1beta1_Device(in *v1.Device, out *Device, s conversion.Scope) error {
return autoConvert_v1_Device_To_v1beta1_Device(in, out, s)
}
func autoConvert_v1beta1_NodePrepareResourceResponse_To_v1_NodePrepareResourceResponse(in *NodePrepareResourceResponse, out *v1.NodePrepareResourceResponse, s conversion.Scope) error {
out.Devices = *(*[]*v1.Device)(unsafe.Pointer(&in.Devices))
out.Error = in.Error
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1beta1_NodePrepareResourceResponse_To_v1_NodePrepareResourceResponse is an autogenerated conversion function.
func Convert_v1beta1_NodePrepareResourceResponse_To_v1_NodePrepareResourceResponse(in *NodePrepareResourceResponse, out *v1.NodePrepareResourceResponse, s conversion.Scope) error {
return autoConvert_v1beta1_NodePrepareResourceResponse_To_v1_NodePrepareResourceResponse(in, out, s)
}
func autoConvert_v1_NodePrepareResourceResponse_To_v1beta1_NodePrepareResourceResponse(in *v1.NodePrepareResourceResponse, out *NodePrepareResourceResponse, s conversion.Scope) error {
out.Devices = *(*[]*Device)(unsafe.Pointer(&in.Devices))
out.Error = in.Error
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1_NodePrepareResourceResponse_To_v1beta1_NodePrepareResourceResponse is an autogenerated conversion function.
func Convert_v1_NodePrepareResourceResponse_To_v1beta1_NodePrepareResourceResponse(in *v1.NodePrepareResourceResponse, out *NodePrepareResourceResponse, s conversion.Scope) error {
return autoConvert_v1_NodePrepareResourceResponse_To_v1beta1_NodePrepareResourceResponse(in, out, s)
}
func autoConvert_v1beta1_NodePrepareResourcesRequest_To_v1_NodePrepareResourcesRequest(in *NodePrepareResourcesRequest, out *v1.NodePrepareResourcesRequest, s conversion.Scope) error {
out.Claims = *(*[]*v1.Claim)(unsafe.Pointer(&in.Claims))
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1beta1_NodePrepareResourcesRequest_To_v1_NodePrepareResourcesRequest is an autogenerated conversion function.
func Convert_v1beta1_NodePrepareResourcesRequest_To_v1_NodePrepareResourcesRequest(in *NodePrepareResourcesRequest, out *v1.NodePrepareResourcesRequest, s conversion.Scope) error {
return autoConvert_v1beta1_NodePrepareResourcesRequest_To_v1_NodePrepareResourcesRequest(in, out, s)
}
func autoConvert_v1_NodePrepareResourcesRequest_To_v1beta1_NodePrepareResourcesRequest(in *v1.NodePrepareResourcesRequest, out *NodePrepareResourcesRequest, s conversion.Scope) error {
out.Claims = *(*[]*Claim)(unsafe.Pointer(&in.Claims))
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1_NodePrepareResourcesRequest_To_v1beta1_NodePrepareResourcesRequest is an autogenerated conversion function.
func Convert_v1_NodePrepareResourcesRequest_To_v1beta1_NodePrepareResourcesRequest(in *v1.NodePrepareResourcesRequest, out *NodePrepareResourcesRequest, s conversion.Scope) error {
return autoConvert_v1_NodePrepareResourcesRequest_To_v1beta1_NodePrepareResourcesRequest(in, out, s)
}
func autoConvert_v1beta1_NodePrepareResourcesResponse_To_v1_NodePrepareResourcesResponse(in *NodePrepareResourcesResponse, out *v1.NodePrepareResourcesResponse, s conversion.Scope) error {
out.Claims = *(*map[string]*v1.NodePrepareResourceResponse)(unsafe.Pointer(&in.Claims))
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1beta1_NodePrepareResourcesResponse_To_v1_NodePrepareResourcesResponse is an autogenerated conversion function.
func Convert_v1beta1_NodePrepareResourcesResponse_To_v1_NodePrepareResourcesResponse(in *NodePrepareResourcesResponse, out *v1.NodePrepareResourcesResponse, s conversion.Scope) error {
return autoConvert_v1beta1_NodePrepareResourcesResponse_To_v1_NodePrepareResourcesResponse(in, out, s)
}
func autoConvert_v1_NodePrepareResourcesResponse_To_v1beta1_NodePrepareResourcesResponse(in *v1.NodePrepareResourcesResponse, out *NodePrepareResourcesResponse, s conversion.Scope) error {
out.Claims = *(*map[string]*NodePrepareResourceResponse)(unsafe.Pointer(&in.Claims))
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1_NodePrepareResourcesResponse_To_v1beta1_NodePrepareResourcesResponse is an autogenerated conversion function.
func Convert_v1_NodePrepareResourcesResponse_To_v1beta1_NodePrepareResourcesResponse(in *v1.NodePrepareResourcesResponse, out *NodePrepareResourcesResponse, s conversion.Scope) error {
return autoConvert_v1_NodePrepareResourcesResponse_To_v1beta1_NodePrepareResourcesResponse(in, out, s)
}
func autoConvert_v1beta1_NodeUnprepareResourceResponse_To_v1_NodeUnprepareResourceResponse(in *NodeUnprepareResourceResponse, out *v1.NodeUnprepareResourceResponse, s conversion.Scope) error {
out.Error = in.Error
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1beta1_NodeUnprepareResourceResponse_To_v1_NodeUnprepareResourceResponse is an autogenerated conversion function.
func Convert_v1beta1_NodeUnprepareResourceResponse_To_v1_NodeUnprepareResourceResponse(in *NodeUnprepareResourceResponse, out *v1.NodeUnprepareResourceResponse, s conversion.Scope) error {
return autoConvert_v1beta1_NodeUnprepareResourceResponse_To_v1_NodeUnprepareResourceResponse(in, out, s)
}
func autoConvert_v1_NodeUnprepareResourceResponse_To_v1beta1_NodeUnprepareResourceResponse(in *v1.NodeUnprepareResourceResponse, out *NodeUnprepareResourceResponse, s conversion.Scope) error {
out.Error = in.Error
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1_NodeUnprepareResourceResponse_To_v1beta1_NodeUnprepareResourceResponse is an autogenerated conversion function.
func Convert_v1_NodeUnprepareResourceResponse_To_v1beta1_NodeUnprepareResourceResponse(in *v1.NodeUnprepareResourceResponse, out *NodeUnprepareResourceResponse, s conversion.Scope) error {
return autoConvert_v1_NodeUnprepareResourceResponse_To_v1beta1_NodeUnprepareResourceResponse(in, out, s)
}
func autoConvert_v1beta1_NodeUnprepareResourcesRequest_To_v1_NodeUnprepareResourcesRequest(in *NodeUnprepareResourcesRequest, out *v1.NodeUnprepareResourcesRequest, s conversion.Scope) error {
out.Claims = *(*[]*v1.Claim)(unsafe.Pointer(&in.Claims))
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1beta1_NodeUnprepareResourcesRequest_To_v1_NodeUnprepareResourcesRequest is an autogenerated conversion function.
func Convert_v1beta1_NodeUnprepareResourcesRequest_To_v1_NodeUnprepareResourcesRequest(in *NodeUnprepareResourcesRequest, out *v1.NodeUnprepareResourcesRequest, s conversion.Scope) error {
return autoConvert_v1beta1_NodeUnprepareResourcesRequest_To_v1_NodeUnprepareResourcesRequest(in, out, s)
}
func autoConvert_v1_NodeUnprepareResourcesRequest_To_v1beta1_NodeUnprepareResourcesRequest(in *v1.NodeUnprepareResourcesRequest, out *NodeUnprepareResourcesRequest, s conversion.Scope) error {
out.Claims = *(*[]*Claim)(unsafe.Pointer(&in.Claims))
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1_NodeUnprepareResourcesRequest_To_v1beta1_NodeUnprepareResourcesRequest is an autogenerated conversion function.
func Convert_v1_NodeUnprepareResourcesRequest_To_v1beta1_NodeUnprepareResourcesRequest(in *v1.NodeUnprepareResourcesRequest, out *NodeUnprepareResourcesRequest, s conversion.Scope) error {
return autoConvert_v1_NodeUnprepareResourcesRequest_To_v1beta1_NodeUnprepareResourcesRequest(in, out, s)
}
func autoConvert_v1beta1_NodeUnprepareResourcesResponse_To_v1_NodeUnprepareResourcesResponse(in *NodeUnprepareResourcesResponse, out *v1.NodeUnprepareResourcesResponse, s conversion.Scope) error {
out.Claims = *(*map[string]*v1.NodeUnprepareResourceResponse)(unsafe.Pointer(&in.Claims))
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1beta1_NodeUnprepareResourcesResponse_To_v1_NodeUnprepareResourcesResponse is an autogenerated conversion function.
func Convert_v1beta1_NodeUnprepareResourcesResponse_To_v1_NodeUnprepareResourcesResponse(in *NodeUnprepareResourcesResponse, out *v1.NodeUnprepareResourcesResponse, s conversion.Scope) error {
return autoConvert_v1beta1_NodeUnprepareResourcesResponse_To_v1_NodeUnprepareResourcesResponse(in, out, s)
}
func autoConvert_v1_NodeUnprepareResourcesResponse_To_v1beta1_NodeUnprepareResourcesResponse(in *v1.NodeUnprepareResourcesResponse, out *NodeUnprepareResourcesResponse, s conversion.Scope) error {
out.Claims = *(*map[string]*NodeUnprepareResourceResponse)(unsafe.Pointer(&in.Claims))
out.XXX_NoUnkeyedLiteral = in.XXX_NoUnkeyedLiteral
out.XXX_sizecache = in.XXX_sizecache
return nil
}
// Convert_v1_NodeUnprepareResourcesResponse_To_v1beta1_NodeUnprepareResourcesResponse is an autogenerated conversion function.
func Convert_v1_NodeUnprepareResourcesResponse_To_v1beta1_NodeUnprepareResourcesResponse(in *v1.NodeUnprepareResourcesResponse, out *NodeUnprepareResourcesResponse, s conversion.Scope) error {
return autoConvert_v1_NodeUnprepareResourcesResponse_To_v1beta1_NodeUnprepareResourcesResponse(in, out, s)
}
func autoConvert_v1beta1_UnimplementedDRAPluginServer_To_v1_UnimplementedDRAPluginServer(in *UnimplementedDRAPluginServer, out *v1.UnimplementedDRAPluginServer, s conversion.Scope) error {
return nil
}
// Convert_v1beta1_UnimplementedDRAPluginServer_To_v1_UnimplementedDRAPluginServer is an autogenerated conversion function.
func Convert_v1beta1_UnimplementedDRAPluginServer_To_v1_UnimplementedDRAPluginServer(in *UnimplementedDRAPluginServer, out *v1.UnimplementedDRAPluginServer, s conversion.Scope) error {
return autoConvert_v1beta1_UnimplementedDRAPluginServer_To_v1_UnimplementedDRAPluginServer(in, out, s)
}
func autoConvert_v1_UnimplementedDRAPluginServer_To_v1beta1_UnimplementedDRAPluginServer(in *v1.UnimplementedDRAPluginServer, out *UnimplementedDRAPluginServer, s conversion.Scope) error {
return nil
}
// Convert_v1_UnimplementedDRAPluginServer_To_v1beta1_UnimplementedDRAPluginServer is an autogenerated conversion function.
func Convert_v1_UnimplementedDRAPluginServer_To_v1beta1_UnimplementedDRAPluginServer(in *v1.UnimplementedDRAPluginServer, out *UnimplementedDRAPluginServer, s conversion.Scope) error {
return autoConvert_v1_UnimplementedDRAPluginServer_To_v1beta1_UnimplementedDRAPluginServer(in, out, s)
}

View File

@@ -87,10 +87,13 @@ var _ = framework.SIGDescribe("node")(framework.WithLabel("DRA"), framework.With
})
ginkgo.It("must retry NodePrepareResources", func(ctx context.Context) {
// We have exactly one host.
m := drautils.MethodInstance{NodeName: driver.Nodenames()[0], FullMethod: drautils.NodePrepareResourcesMethod}
// We have exactly one host. The API version depends on the kubelet
// we test with (version skew!), so we need to be a bit flexible.
mV1Beta1 := drautils.MethodInstance{NodeName: driver.Nodenames()[0], FullMethod: "/k8s.io.kubelet.pkg.apis.dra.v1beta1.DRAPlugin/NodePrepareResources"}
mV1 := drautils.MethodInstance{NodeName: driver.Nodenames()[0], FullMethod: "/k8s.io.kubelet.pkg.apis.dra.v1.DRAPlugin/NodePrepareResources"}
driver.Fail(m, true)
driver.Fail(mV1Beta1, true)
driver.Fail(mV1, true)
ginkgo.By("waiting for container startup to fail")
pod, template := b.PodInline()
@@ -99,18 +102,19 @@ var _ = framework.SIGDescribe("node")(framework.WithLabel("DRA"), framework.With
ginkgo.By("wait for NodePrepareResources call")
gomega.Eventually(ctx, func(ctx context.Context) error {
if driver.CallCount(m) == 0 {
if driver.CallCount(mV1Beta1)+driver.CallCount(mV1) == 0 {
return errors.New("NodePrepareResources not called yet")
}
return nil
}).WithTimeout(podStartTimeout).Should(gomega.Succeed())
ginkgo.By("allowing container startup to succeed")
callCount := driver.CallCount(m)
driver.Fail(m, false)
callCount := driver.CallCount(mV1Beta1) + driver.CallCount(mV1)
driver.Fail(mV1, false)
driver.Fail(mV1Beta1, false)
err := e2epod.WaitForPodNameRunningInNamespace(ctx, f.ClientSet, pod.Name, pod.Namespace)
framework.ExpectNoError(err, "start pod with inline resource claim")
if driver.CallCount(m) == callCount {
if driver.CallCount(mV1Beta1)+driver.CallCount(mV1) == callCount {
framework.Fail("NodePrepareResources should have been called again")
}
})
@@ -302,7 +306,7 @@ var _ = framework.SIGDescribe("node")(framework.WithLabel("DRA"), framework.With
framework.ExpectNoError(f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(ctx, pod.Name, forceDelete))
// Fail NodeUnprepareResources to simulate long grace period
unprepareResources := drautils.MethodInstance{NodeName: node, FullMethod: drautils.NodeUnprepareResourcesMethod}
unprepareResources := drautils.MethodInstance{NodeName: node, FullMethod: "/k8s.io.kubelet.pkg.apis.dra.v1.DRAPlugin/NodeUnprepareResources"}
driver.Fail(unprepareResources, true)
// The pod should get deleted immediately.
@@ -2548,14 +2552,16 @@ var _ = framework.SIGDescribe("node")(framework.WithLabel("DRA"), framework.With
})
})
multipleDrivers := func(nodeV1beta1 bool) {
multipleDrivers := func(nodeV1beta1, nodeV1 bool) {
nodes := drautils.NewNodes(f, 1, 4)
driver1 := drautils.NewDriver(f, nodes, drautils.DriverResources(2))
driver1.NodeV1beta1 = nodeV1beta1
driver1.NodeV1 = nodeV1
b1 := drautils.NewBuilder(f, driver1)
driver2 := drautils.NewDriver(f, nodes, drautils.DriverResources(2))
driver2.NodeV1beta1 = nodeV1beta1
driver2.NodeV1 = nodeV1
driver2.NameSuffix = "-other"
b2 := drautils.NewBuilder(f, driver2)
@@ -2578,14 +2584,26 @@ var _ = framework.SIGDescribe("node")(framework.WithLabel("DRA"), framework.With
b1.TestPod(ctx, f, pod)
})
}
multipleDriversContext := func(prefix string, nodeV1beta1 bool) {
ginkgo.Context(prefix, func() {
multipleDrivers(nodeV1beta1)
})
multipleDriversContext := func(prefix string, nodeV1beta1, nodeV1 bool) {
args := []any{
prefix,
func() {
multipleDrivers(nodeV1beta1, nodeV1)
},
}
if !nodeV1beta1 {
// If the v1beta1 gRPC API is disabled, then
// kubelet from 1.34 is required because that is
// when v1 was introduced.
args = append(args, f.WithLabel("KubeletMinVersion:1.34"))
}
framework.Context(args...)
}
framework.Context("kubelet", feature.DynamicResourceAllocation, "with multiple drivers", func() {
multipleDriversContext("using only drapbv1beta1", true)
multipleDriversContext("using only drapbv1beta1", true, false)
multipleDriversContext("using only drapbv1", false, true)
multipleDriversContext("using drapbv1beta1 and drapbv1", true, true)
})
})

View File

@@ -79,11 +79,6 @@ import (
"sigs.k8s.io/yaml"
)
const (
NodePrepareResourcesMethod = "/k8s.io.kubelet.pkg.apis.dra.v1beta1.DRAPlugin/NodePrepareResources"
NodeUnprepareResourcesMethod = "/k8s.io.kubelet.pkg.apis.dra.v1beta1.DRAPlugin/NodeUnprepareResources"
)
type Nodes struct {
NodeNames []string
tempDir string
@@ -290,9 +285,10 @@ func NewDriverInstance(f *framework.Framework) *Driver {
f: f,
fail: map[MethodInstance]bool{},
callCounts: map[MethodInstance]int64{},
// By default, test only with the latest gRPC API.
NodeV1alpha4: false,
NodeV1beta1: true,
// By default, test with all gRPC APIs.
// TODO: should setting this be optional to test the actual helper defaults?
NodeV1: true,
NodeV1beta1: true,
// By default, assume that the kubelet supports DRA and that
// the driver's removal causes ResourceSlice cleanup.
WithKubelet: true,
@@ -355,8 +351,8 @@ type Driver struct {
// /var/run/cdi are writable by the current user.
IsLocal bool
NodeV1alpha4 bool
NodeV1beta1 bool
NodeV1 bool
NodeV1beta1 bool
// Register the DRA test driver with the kubelet and expect DRA to work (= feature.DynamicResourceAllocation).
WithKubelet bool
@@ -603,6 +599,8 @@ func (d *Driver) SetUp(nodes *Nodes, driverResources map[string]resourceslice.Dr
kubeletplugin.GRPCStreamInterceptor(func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) (err error) {
return d.streamInterceptor(nodename, srv, ss, info, handler)
}),
kubeletplugin.NodeV1(d.NodeV1),
kubeletplugin.NodeV1beta1(d.NodeV1beta1),
kubeletplugin.RollingUpdate(rollingUpdateUID),
kubeletplugin.Serialize(serialize),