Add support for Azure Disk to csi-translation-lib
rename to azure_disk add more translation fields fix typo
This commit is contained in:
		@@ -4,6 +4,7 @@ go_library(
 | 
				
			|||||||
    name = "go_default_library",
 | 
					    name = "go_default_library",
 | 
				
			||||||
    srcs = [
 | 
					    srcs = [
 | 
				
			||||||
        "aws_ebs.go",
 | 
					        "aws_ebs.go",
 | 
				
			||||||
 | 
					        "azure_disk.go",
 | 
				
			||||||
        "gce_pd.go",
 | 
					        "gce_pd.go",
 | 
				
			||||||
        "in_tree_volume.go",
 | 
					        "in_tree_volume.go",
 | 
				
			||||||
        "openstack_cinder.go",
 | 
					        "openstack_cinder.go",
 | 
				
			||||||
@@ -37,6 +38,7 @@ go_test(
 | 
				
			|||||||
    name = "go_default_test",
 | 
					    name = "go_default_test",
 | 
				
			||||||
    srcs = [
 | 
					    srcs = [
 | 
				
			||||||
        "aws_ebs_test.go",
 | 
					        "aws_ebs_test.go",
 | 
				
			||||||
 | 
					        "azure_disk_test.go",
 | 
				
			||||||
        "gce_pd_test.go",
 | 
					        "gce_pd_test.go",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    embed = [":go_default_library"],
 | 
					    embed = [":go_default_library"],
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										168
									
								
								staging/src/k8s.io/csi-translation-lib/plugins/azure_disk.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								staging/src/k8s.io/csi-translation-lib/plugins/azure_disk.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2019 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 plugins
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/api/core/v1"
 | 
				
			||||||
 | 
						storage "k8s.io/api/storage/v1"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						// AzureDiskDriverName is the name of the CSI driver for Azure Disk
 | 
				
			||||||
 | 
						AzureDiskDriverName = "disk.csi.azure.com"
 | 
				
			||||||
 | 
						// AzureDiskInTreePluginName is the name of the intree plugin for Azure Disk
 | 
				
			||||||
 | 
						AzureDiskInTreePluginName = "kubernetes.io/azure-disk"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Parameter names defined in azure disk CSI driver, refer to
 | 
				
			||||||
 | 
						// https://github.com/kubernetes-sigs/azuredisk-csi-driver/blob/master/docs/driver-parameters.md
 | 
				
			||||||
 | 
						azureDiskCachingMode = "cachingMode"
 | 
				
			||||||
 | 
						azureDiskFSType      = "fsType"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						managedDiskPathRE   = regexp.MustCompile(`.*/subscriptions/(?:.*)/resourceGroups/(?:.*)/providers/Microsoft.Compute/disks/(.+)`)
 | 
				
			||||||
 | 
						unmanagedDiskPathRE = regexp.MustCompile(`http(?:.*)://(?:.*)/vhds/(.+)`)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var _ InTreePlugin = &azureDiskCSITranslator{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// azureDiskCSITranslator handles translation of PV spec from In-tree
 | 
				
			||||||
 | 
					// Azure Disk to CSI Azure Disk and vice versa
 | 
				
			||||||
 | 
					type azureDiskCSITranslator struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewAzureDiskCSITranslator returns a new instance of azureDiskTranslator
 | 
				
			||||||
 | 
					func NewAzureDiskCSITranslator() InTreePlugin {
 | 
				
			||||||
 | 
						return &azureDiskCSITranslator{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TranslateInTreeStorageClassParametersToCSI translates InTree Azure Disk storage class parameters to CSI storage class
 | 
				
			||||||
 | 
					func (t *azureDiskCSITranslator) TranslateInTreeStorageClassToCSI(sc *storage.StorageClass) (*storage.StorageClass, error) {
 | 
				
			||||||
 | 
						return sc, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TranslateInTreePVToCSI takes a PV with AzureDisk set from in-tree
 | 
				
			||||||
 | 
					// and converts the AzureDisk source to a CSIPersistentVolumeSource
 | 
				
			||||||
 | 
					func (t *azureDiskCSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
 | 
				
			||||||
 | 
						if pv == nil || pv.Spec.AzureDisk == nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("pv is nil or Azure Disk source not defined on pv")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						azureSource := pv.Spec.PersistentVolumeSource.AzureDisk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// refer to https://github.com/kubernetes-sigs/azuredisk-csi-driver/blob/master/docs/driver-parameters.md
 | 
				
			||||||
 | 
						csiSource := &v1.CSIPersistentVolumeSource{
 | 
				
			||||||
 | 
							Driver:           AzureDiskDriverName,
 | 
				
			||||||
 | 
							VolumeHandle:     azureSource.DataDiskURI,
 | 
				
			||||||
 | 
							ReadOnly:         *azureSource.ReadOnly,
 | 
				
			||||||
 | 
							FSType:           *azureSource.FSType,
 | 
				
			||||||
 | 
							VolumeAttributes: map[string]string{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if *azureSource.CachingMode != "" {
 | 
				
			||||||
 | 
							csiSource.VolumeAttributes[azureDiskCachingMode] = string(*azureSource.CachingMode)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if *azureSource.FSType != "" {
 | 
				
			||||||
 | 
							csiSource.VolumeAttributes[azureDiskFSType] = *azureSource.FSType
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pv.Spec.PersistentVolumeSource.AzureDisk = nil
 | 
				
			||||||
 | 
						pv.Spec.PersistentVolumeSource.CSI = csiSource
 | 
				
			||||||
 | 
						pv.Spec.AccessModes = backwardCompatibleAccessModes(pv.Spec.AccessModes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pv, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TranslateCSIPVToInTree takes a PV with CSIPersistentVolumeSource set and
 | 
				
			||||||
 | 
					// translates the Azure Disk CSI source to a AzureDisk source.
 | 
				
			||||||
 | 
					func (t *azureDiskCSITranslator) TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
 | 
				
			||||||
 | 
						if pv == nil || pv.Spec.CSI == nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("pv is nil or CSI source not defined on pv")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						csiSource := pv.Spec.CSI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						diskURI := csiSource.VolumeHandle
 | 
				
			||||||
 | 
						diskName, err := getDiskName(diskURI)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// refer to https://github.com/kubernetes-sigs/azuredisk-csi-driver/blob/master/docs/driver-parameters.md
 | 
				
			||||||
 | 
						azureSource := &v1.AzureDiskVolumeSource{
 | 
				
			||||||
 | 
							DiskName:    diskName,
 | 
				
			||||||
 | 
							DataDiskURI: diskURI,
 | 
				
			||||||
 | 
							FSType:      &csiSource.FSType,
 | 
				
			||||||
 | 
							ReadOnly:    &csiSource.ReadOnly,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if csiSource.VolumeAttributes != nil {
 | 
				
			||||||
 | 
							if cachingMode, ok := csiSource.VolumeAttributes[azureDiskCachingMode]; ok {
 | 
				
			||||||
 | 
								mode := v1.AzureDataDiskCachingMode(cachingMode)
 | 
				
			||||||
 | 
								azureSource.CachingMode = &mode
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if fsType, ok := csiSource.VolumeAttributes[azureDiskFSType]; ok && fsType != "" {
 | 
				
			||||||
 | 
								azureSource.FSType = &fsType
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pv.Spec.CSI = nil
 | 
				
			||||||
 | 
						pv.Spec.AzureDisk = azureSource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pv, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CanSupport tests whether the plugin supports a given volume
 | 
				
			||||||
 | 
					// specification from the API.  The spec pointer should be considered
 | 
				
			||||||
 | 
					// const.
 | 
				
			||||||
 | 
					func (t *azureDiskCSITranslator) CanSupport(pv *v1.PersistentVolume) bool {
 | 
				
			||||||
 | 
						return pv != nil && pv.Spec.AzureDisk != nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetInTreePluginName returns the name of the intree plugin driver
 | 
				
			||||||
 | 
					func (t *azureDiskCSITranslator) GetInTreePluginName() string {
 | 
				
			||||||
 | 
						return AzureDiskInTreePluginName
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetCSIPluginName returns the name of the CSI plugin
 | 
				
			||||||
 | 
					func (t *azureDiskCSITranslator) GetCSIPluginName() string {
 | 
				
			||||||
 | 
						return AzureDiskDriverName
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isManagedDisk(diskURI string) bool {
 | 
				
			||||||
 | 
						if len(diskURI) > 4 && strings.ToLower(diskURI[:4]) == "http" {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getDiskName(diskURI string) (string, error) {
 | 
				
			||||||
 | 
						diskPathRE := managedDiskPathRE
 | 
				
			||||||
 | 
						if !isManagedDisk(diskURI) {
 | 
				
			||||||
 | 
							diskPathRE = unmanagedDiskPathRE
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						matches := diskPathRE.FindStringSubmatch(diskURI)
 | 
				
			||||||
 | 
						if len(matches) != 2 {
 | 
				
			||||||
 | 
							return "", fmt.Errorf("could not get disk name from %s, correct format: %s", diskURI, diskPathRE)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return matches[1], nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,93 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2019 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 plugins
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestIsManagedDisk(t *testing.T) {
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							options  string
 | 
				
			||||||
 | 
							expected bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								options:  "testurl/subscriptions/12/resourceGroups/23/providers/Microsoft.Compute/disks/name",
 | 
				
			||||||
 | 
								expected: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								options:  "test.com",
 | 
				
			||||||
 | 
								expected: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								options:  "HTTP://test.com",
 | 
				
			||||||
 | 
								expected: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								options:  "http://test.com/vhds/name",
 | 
				
			||||||
 | 
								expected: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, test := range tests {
 | 
				
			||||||
 | 
							result := isManagedDisk(test.options)
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(result, test.expected) {
 | 
				
			||||||
 | 
								t.Errorf("input: %q, isManagedDisk result: %t, expected: %t", test.options, result, test.expected)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGetDiskName(t *testing.T) {
 | 
				
			||||||
 | 
						mDiskPathRE := managedDiskPathRE
 | 
				
			||||||
 | 
						uDiskPathRE := unmanagedDiskPathRE
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							options   string
 | 
				
			||||||
 | 
							expected1 string
 | 
				
			||||||
 | 
							expected2 error
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								options:   "testurl/subscriptions/12/resourceGroups/23/providers/Microsoft.Compute/disks/name",
 | 
				
			||||||
 | 
								expected1: "name",
 | 
				
			||||||
 | 
								expected2: nil,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								options:   "testurl/subscriptions/23/providers/Microsoft.Compute/disks/name",
 | 
				
			||||||
 | 
								expected1: "",
 | 
				
			||||||
 | 
								expected2: fmt.Errorf("could not get disk name from testurl/subscriptions/23/providers/Microsoft.Compute/disks/name, correct format: %s", mDiskPathRE),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								options:   "http://test.com/vhds/name",
 | 
				
			||||||
 | 
								expected1: "name",
 | 
				
			||||||
 | 
								expected2: nil,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								options:   "http://test.io/name",
 | 
				
			||||||
 | 
								expected1: "",
 | 
				
			||||||
 | 
								expected2: fmt.Errorf("could not get disk name from http://test.io/name, correct format: %s", uDiskPathRE),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, test := range tests {
 | 
				
			||||||
 | 
							result1, result2 := getDiskName(test.options)
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(result1, test.expected1) || !reflect.DeepEqual(result2, test.expected2) {
 | 
				
			||||||
 | 
								t.Errorf("input: %q, getDiskName result1: %q, expected1: %q, result2: %q, expected2: %q", test.options, result1, test.expected1,
 | 
				
			||||||
 | 
									result2, test.expected2)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user