diff --git a/pkg/csi/manila/adapters_test.go b/pkg/csi/manila/adapters_test.go new file mode 100644 index 0000000000..c3d4b15c82 --- /dev/null +++ b/pkg/csi/manila/adapters_test.go @@ -0,0 +1,66 @@ +/* +Copyright 2026 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 manila + +import ( + "testing" + + "k8s.io/cloud-provider-openstack/pkg/csi/manila/options" +) + +func TestGetAccessIDs(t *testing.T) { + tests := []struct { + name string + opts *options.NodeVolumeContext + expected []string + }{ + { + name: "shareAccessIDs takes precedence over shareAccessID", + opts: &options.NodeVolumeContext{ShareAccessIDs: "new-1,new-2", ShareAccessID: "old-1"}, + expected: []string{"new-1", "new-2"}, + }, + { + name: "only shareAccessIDs", + opts: &options.NodeVolumeContext{ShareAccessIDs: "id-1,id-2,id-3"}, + expected: []string{"id-1", "id-2", "id-3"}, + }, + { + name: "only shareAccessID (deprecated)", + opts: &options.NodeVolumeContext{ShareAccessID: "id-1"}, + expected: []string{"id-1"}, + }, + { + name: "neither set", + opts: &options.NodeVolumeContext{}, + expected: nil, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + result := getAccessIDs(tc.opts) + if len(result) != len(tc.expected) { + t.Fatalf("got %v, want %v", result, tc.expected) + } + for i := range result { + if result[i] != tc.expected[i] { + t.Errorf("index %d: got %q, want %q", i, result[i], tc.expected[i]) + } + } + }) + } +} diff --git a/pkg/csi/manila/options/shareoptions.go b/pkg/csi/manila/options/shareoptions.go index af6668e9b6..fb3c2950dc 100644 --- a/pkg/csi/manila/options/shareoptions.go +++ b/pkg/csi/manila/options/shareoptions.go @@ -43,8 +43,8 @@ type ControllerVolumeContext struct { type NodeVolumeContext struct { ShareID string `name:"shareID" value:"optionalIf:shareName=." precludes:"shareName"` ShareName string `name:"shareName" value:"optionalIf:shareID=." precludes:"shareID"` - ShareAccessID string `name:"shareAccessID" value:"optionalIf:shareAccessIDs=." precludes:"shareAccessIDs"` // Keep this for backwards compatibility - ShareAccessIDs string `name:"shareAccessIDs" value:"optionalIf:shareAccessID=." precludes:"shareAccessID"` + ShareAccessID string `name:"shareAccessID" value:"optional"` // Deprecated: use shareAccessIDs + ShareAccessIDs string `name:"shareAccessIDs" value:"optional"` // Preferred; takes precedence over shareAccessID // Adapter options diff --git a/pkg/csi/manila/options/shareoptions_test.go b/pkg/csi/manila/options/shareoptions_test.go new file mode 100644 index 0000000000..f7826e5a10 --- /dev/null +++ b/pkg/csi/manila/options/shareoptions_test.go @@ -0,0 +1,82 @@ +/* +Copyright 2026 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 options + +import ( + "testing" +) + +func TestNewNodeVolumeContextShareAccessIDBackwardsCompat(t *testing.T) { + tests := []struct { + name string + data map[string]string + wantAccessID string + wantAccessIDs string + wantErr bool + }{ + { + name: "only shareAccessIDs set", + data: map[string]string{ + "shareID": "share-1", + "shareAccessIDs": "access-1,access-2", + }, + wantAccessIDs: "access-1,access-2", + }, + { + name: "only shareAccessID set (deprecated)", + data: map[string]string{ + "shareID": "share-1", + "shareAccessID": "access-1", + }, + wantAccessID: "access-1", + }, + { + name: "both set, should not error", + data: map[string]string{ + "shareID": "share-1", + "shareAccessID": "access-old", + "shareAccessIDs": "access-new-1,access-new-2", + }, + wantAccessID: "access-old", + wantAccessIDs: "access-new-1,access-new-2", + }, + { + name: "neither set", + data: map[string]string{ + "shareID": "share-1", + }, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + opts, err := NewNodeVolumeContext(tc.data) + if (err != nil) != tc.wantErr { + t.Fatalf("unexpected error: %v", err) + } + if tc.wantErr { + return + } + if opts.ShareAccessID != tc.wantAccessID { + t.Errorf("ShareAccessID = %q, want %q", opts.ShareAccessID, tc.wantAccessID) + } + if opts.ShareAccessIDs != tc.wantAccessIDs { + t.Errorf("ShareAccessIDs = %q, want %q", opts.ShareAccessIDs, tc.wantAccessIDs) + } + }) + } +}