mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Add RepairVolumeHandle to the csi translation struct
This commit is contained in:
parent
5c8d219dfe
commit
93f7cec5b3
@ -23,7 +23,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
storage "k8s.io/api/storage/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@ -161,6 +161,10 @@ func (t *awsElasticBlockStoreCSITranslator) GetCSIPluginName() string {
|
||||
return AWSEBSDriverName
|
||||
}
|
||||
|
||||
func (t *awsElasticBlockStoreCSITranslator) RepairVolumeHandle(volumeHandle, nodeID string) (string, error) {
|
||||
return volumeHandle, nil
|
||||
}
|
||||
|
||||
// awsVolumeRegMatch represents Regex Match for AWS volume.
|
||||
var awsVolumeRegMatch = regexp.MustCompile("^vol-[^/]*$")
|
||||
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
storage "k8s.io/api/storage/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@ -209,6 +209,10 @@ func (t *azureDiskCSITranslator) GetCSIPluginName() string {
|
||||
return AzureDiskDriverName
|
||||
}
|
||||
|
||||
func (t *azureDiskCSITranslator) RepairVolumeHandle(volumeHandle, nodeID string) (string, error) {
|
||||
return volumeHandle, nil
|
||||
}
|
||||
|
||||
func isManagedDisk(diskURI string) bool {
|
||||
if len(diskURI) > 4 && strings.ToLower(diskURI[:4]) == "http" {
|
||||
return false
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
storage "k8s.io/api/storage/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@ -176,6 +176,10 @@ func (t *azureFileCSITranslator) GetCSIPluginName() string {
|
||||
return AzureFileDriverName
|
||||
}
|
||||
|
||||
func (t *azureFileCSITranslator) RepairVolumeHandle(volumeHandle, nodeID string) (string, error) {
|
||||
return volumeHandle, nil
|
||||
}
|
||||
|
||||
// get file share info according to volume id, e.g.
|
||||
// input: "rg#f5713de20cde511e8ba4900#pvc-file-dynamic-17e43f84-f474-11e8-acd0-000d3a00df41"
|
||||
// output: rg, f5713de20cde511e8ba4900, pvc-file-dynamic-17e43f84-f474-11e8-acd0-000d3a00df41
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
storage "k8s.io/api/storage/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
@ -41,9 +41,14 @@ const (
|
||||
// "projects/{projectName}/zones/{zoneName}/disks/{diskName}"
|
||||
volIDZonalFmt = "projects/%s/zones/%s/disks/%s"
|
||||
// "projects/{projectName}/regions/{regionName}/disks/{diskName}"
|
||||
volIDRegionalFmt = "projects/%s/regions/%s/disks/%s"
|
||||
volIDDiskNameValue = 5
|
||||
volIDTotalElements = 6
|
||||
volIDRegionalFmt = "projects/%s/regions/%s/disks/%s"
|
||||
volIDProjectValue = 1
|
||||
volIDRegionalityValue = 2
|
||||
volIDZoneValue = 3
|
||||
volIDDiskNameValue = 5
|
||||
volIDTotalElements = 6
|
||||
|
||||
nodeIDFmt = "projects/%s/zones/%s/instances/%s"
|
||||
|
||||
// UnspecifiedValue is used for an unknown zone string
|
||||
UnspecifiedValue = "UNSPECIFIED"
|
||||
@ -328,10 +333,53 @@ func (g *gcePersistentDiskCSITranslator) GetCSIPluginName() string {
|
||||
return GCEPDDriverName
|
||||
}
|
||||
|
||||
// RepairVolumeHandle returns a fully specified volume handle by inferring
|
||||
// project, zone/region from the node ID if the volume handle has UNSPECIFIED
|
||||
// sections
|
||||
func (g *gcePersistentDiskCSITranslator) RepairVolumeHandle(volumeHandle, nodeID string) (string, error) {
|
||||
var err error
|
||||
tok := strings.Split(volumeHandle, "/")
|
||||
if len(tok) < volIDTotalElements {
|
||||
return "", fmt.Errorf("volume handle has wrong number of elements; got %v, wanted %v or more", len(tok), volIDTotalElements)
|
||||
}
|
||||
if tok[volIDProjectValue] != UnspecifiedValue {
|
||||
return volumeHandle, nil
|
||||
}
|
||||
|
||||
nodeTok := strings.Split(nodeID, "/")
|
||||
if len(nodeTok) < volIDTotalElements {
|
||||
return "", fmt.Errorf("node handle has wrong number of elements; got %v, wanted %v or more", len(nodeTok), volIDTotalElements)
|
||||
}
|
||||
|
||||
switch tok[volIDRegionalityValue] {
|
||||
case "zones":
|
||||
zone := ""
|
||||
if tok[volIDZoneValue] == UnspecifiedValue {
|
||||
zone = nodeTok[volIDZoneValue]
|
||||
} else {
|
||||
zone = tok[volIDZoneValue]
|
||||
}
|
||||
return fmt.Sprintf(volIDZonalFmt, nodeTok[volIDProjectValue], zone, tok[volIDDiskNameValue]), nil
|
||||
case "regions":
|
||||
region := ""
|
||||
if tok[volIDZoneValue] == UnspecifiedValue {
|
||||
region, err = getRegionFromZones([]string{nodeTok[volIDZoneValue]})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get region from zone %s: %v", nodeTok[volIDZoneValue], err)
|
||||
}
|
||||
} else {
|
||||
region = tok[volIDZoneValue]
|
||||
}
|
||||
return fmt.Sprintf(volIDRegionalFmt, nodeTok[volIDProjectValue], region, tok[volIDDiskNameValue]), nil
|
||||
default:
|
||||
return "", fmt.Errorf("expected volume handle to have zones or regions regionality value, got: %s", tok[volIDRegionalityValue])
|
||||
}
|
||||
}
|
||||
|
||||
func pdNameFromVolumeID(id string) (string, error) {
|
||||
splitID := strings.Split(id, "/")
|
||||
if len(splitID) != volIDTotalElements {
|
||||
return "", fmt.Errorf("failed to get id components. Expected projects/{project}/zones/{zone}/disks/{name}. Got: %s", id)
|
||||
if len(splitID) < volIDTotalElements {
|
||||
return "", fmt.Errorf("failed to get id components.Got: %v, wanted %v components or more. ", len(splitID), volIDTotalElements)
|
||||
}
|
||||
return splitID[volIDDiskNameValue], nil
|
||||
}
|
||||
|
@ -17,10 +17,11 @@ limitations under the License.
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
storage "k8s.io/api/storage/v1"
|
||||
)
|
||||
|
||||
@ -204,6 +205,84 @@ func TestTranslateAllowedTopologies(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepairVolumeHandle(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
volumeHandle string
|
||||
nodeID string
|
||||
expectedVolumeHandle string
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
name: "fully specified",
|
||||
volumeHandle: fmt.Sprintf(volIDZonalFmt, "foo", "bar", "baz"),
|
||||
nodeID: fmt.Sprintf(nodeIDFmt, "bing", "bada", "boom"),
|
||||
expectedVolumeHandle: fmt.Sprintf(volIDZonalFmt, "foo", "bar", "baz"),
|
||||
},
|
||||
{
|
||||
name: "fully specified (regional)",
|
||||
volumeHandle: fmt.Sprintf(volIDRegionalFmt, "foo", "us-central1-c", "baz"),
|
||||
nodeID: fmt.Sprintf(nodeIDFmt, "bing", "bada", "boom"),
|
||||
expectedVolumeHandle: fmt.Sprintf(volIDRegionalFmt, "foo", "us-central1-c", "baz"),
|
||||
},
|
||||
{
|
||||
name: "no project",
|
||||
volumeHandle: fmt.Sprintf(volIDZonalFmt, UnspecifiedValue, "bar", "baz"),
|
||||
nodeID: fmt.Sprintf(nodeIDFmt, "bing", "bada", "boom"),
|
||||
expectedVolumeHandle: fmt.Sprintf(volIDZonalFmt, "bing", "bar", "baz"),
|
||||
},
|
||||
{
|
||||
name: "no project or zone",
|
||||
volumeHandle: fmt.Sprintf(volIDZonalFmt, UnspecifiedValue, UnspecifiedValue, "baz"),
|
||||
nodeID: fmt.Sprintf(nodeIDFmt, "bing", "bada", "boom"),
|
||||
expectedVolumeHandle: fmt.Sprintf(volIDZonalFmt, "bing", "bada", "baz"),
|
||||
},
|
||||
{
|
||||
name: "no project or region",
|
||||
volumeHandle: fmt.Sprintf(volIDRegionalFmt, UnspecifiedValue, UnspecifiedValue, "baz"),
|
||||
nodeID: fmt.Sprintf(nodeIDFmt, "bing", "us-central1-c", "boom"),
|
||||
expectedVolumeHandle: fmt.Sprintf(volIDRegionalFmt, "bing", "us-central1", "baz"),
|
||||
},
|
||||
{
|
||||
name: "no project (regional)",
|
||||
volumeHandle: fmt.Sprintf(volIDRegionalFmt, UnspecifiedValue, "us-west1", "baz"),
|
||||
nodeID: fmt.Sprintf(nodeIDFmt, "bing", "us-central1-c", "boom"),
|
||||
expectedVolumeHandle: fmt.Sprintf(volIDRegionalFmt, "bing", "us-west1", "baz"),
|
||||
},
|
||||
{
|
||||
name: "invalid handle",
|
||||
volumeHandle: "foo",
|
||||
nodeID: fmt.Sprintf(nodeIDFmt, "bing", "us-central1-c", "boom"),
|
||||
expectedErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid node ID",
|
||||
volumeHandle: fmt.Sprintf(volIDRegionalFmt, UnspecifiedValue, "us-west1", "baz"),
|
||||
nodeID: "foo",
|
||||
expectedErr: true,
|
||||
},
|
||||
}
|
||||
g := NewGCEPersistentDiskCSITranslator()
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
gotVolumeHandle, err := g.RepairVolumeHandle(tc.volumeHandle, tc.nodeID)
|
||||
if err != nil && !tc.expectedErr {
|
||||
if !tc.expectedErr {
|
||||
t.Fatalf("Got error: %v, but expected none", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err == nil && tc.expectedErr {
|
||||
t.Fatal("Got no error, but expected one")
|
||||
}
|
||||
|
||||
if gotVolumeHandle != tc.expectedVolumeHandle {
|
||||
t.Fatalf("Got volume handle %s, but expected %s", gotVolumeHandle, tc.expectedVolumeHandle)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackwardCompatibleAccessModes(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
storage "k8s.io/api/storage/v1"
|
||||
)
|
||||
|
||||
@ -55,4 +55,7 @@ type InTreePlugin interface {
|
||||
|
||||
// GetCSIPluginName returns the name of the CSI plugin that supersedes the in-tree plugin
|
||||
GetCSIPluginName() string
|
||||
|
||||
// RepairVolumeHandle generates a correct volume handle based on node ID information.
|
||||
RepairVolumeHandle(volumeHandle, nodeID string) (string, error)
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ package plugins
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
storage "k8s.io/api/storage/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@ -140,3 +140,7 @@ func (t *osCinderCSITranslator) GetInTreePluginName() string {
|
||||
func (t *osCinderCSITranslator) GetCSIPluginName() string {
|
||||
return CinderDriverName
|
||||
}
|
||||
|
||||
func (t *osCinderCSITranslator) RepairVolumeHandle(volumeHandle, nodeID string) (string, error) {
|
||||
return volumeHandle, nil
|
||||
}
|
||||
|
@ -186,3 +186,11 @@ func (CSITranslator) IsInlineMigratable(vol *v1.Volume) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RepairVolumeHandle generates a correct volume handle based on node ID information.
|
||||
func (CSITranslator) RepairVolumeHandle(driverName, volumeHandle, nodeID string) (string, error) {
|
||||
if plugin, ok := inTreePlugins[driverName]; ok {
|
||||
return plugin.RepairVolumeHandle(volumeHandle, nodeID)
|
||||
}
|
||||
return "", fmt.Errorf("could not find In-Tree driver name for CSI plugin %v", driverName)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user