mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 04:33:26 +00:00
Merge pull request #106678 from bertinatto/azure-file-e2e
Add storage tests for Azure File in-tree storage plugin
This commit is contained in:
commit
36142cc0b7
@ -21,7 +21,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -97,6 +97,9 @@ type ProviderInterface interface {
|
|||||||
|
|
||||||
CreatePD(zone string) (string, error)
|
CreatePD(zone string) (string, error)
|
||||||
DeletePD(pdName string) error
|
DeletePD(pdName string) error
|
||||||
|
CreateShare() (string, string, string, error)
|
||||||
|
DeleteShare(accountName, shareName string) error
|
||||||
|
|
||||||
CreatePVSource(zone, diskName string) (*v1.PersistentVolumeSource, error)
|
CreatePVSource(zone, diskName string) (*v1.PersistentVolumeSource, error)
|
||||||
DeletePVSource(pvSource *v1.PersistentVolumeSource) error
|
DeletePVSource(pvSource *v1.PersistentVolumeSource) error
|
||||||
|
|
||||||
@ -137,6 +140,14 @@ func (n NullProvider) DeleteNode(node *v1.Node) error {
|
|||||||
return fmt.Errorf("provider does not support DeleteNode")
|
return fmt.Errorf("provider does not support DeleteNode")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n NullProvider) CreateShare() (string, string, string, error) {
|
||||||
|
return "", "", "", fmt.Errorf("provider does not support volume creation")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NullProvider) DeleteShare(accountName, shareName string) error {
|
||||||
|
return fmt.Errorf("provider does not support volume deletion")
|
||||||
|
}
|
||||||
|
|
||||||
// CreatePD is a base implementation which creates PD.
|
// CreatePD is a base implementation which creates PD.
|
||||||
func (n NullProvider) CreatePD(zone string) (string, error) {
|
func (n NullProvider) CreatePD(zone string) (string, error) {
|
||||||
return "", fmt.Errorf("provider does not support volume creation")
|
return "", fmt.Errorf("provider does not support volume creation")
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
"github.com/aws/aws-sdk-go/service/autoscaling"
|
"github.com/aws/aws-sdk-go/service/autoscaling"
|
||||||
"github.com/aws/aws-sdk-go/service/ec2"
|
"github.com/aws/aws-sdk-go/service/ec2"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
e2epv "k8s.io/kubernetes/test/e2e/framework/pv"
|
e2epv "k8s.io/kubernetes/test/e2e/framework/pv"
|
||||||
awscloud "k8s.io/legacy-cloud-providers/aws"
|
awscloud "k8s.io/legacy-cloud-providers/aws"
|
||||||
@ -93,6 +93,14 @@ func (p *Provider) DeleteNode(node *v1.Node) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) CreateShare() (string, string, string, error) {
|
||||||
|
return "", "", "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) DeleteShare(accountName, shareName string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// CreatePD creates a persistent volume on the specified availability zone
|
// CreatePD creates a persistent volume on the specified availability zone
|
||||||
func (p *Provider) CreatePD(zone string) (string, error) {
|
func (p *Provider) CreatePD(zone string) (string, error) {
|
||||||
client := newAWSClient(zone)
|
client := newAWSClient(zone)
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
"k8s.io/legacy-cloud-providers/azure"
|
"k8s.io/legacy-cloud-providers/azure"
|
||||||
|
"k8s.io/legacy-cloud-providers/azure/clients/fileclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -84,6 +85,39 @@ func (p *Provider) CreatePD(zone string) (string, error) {
|
|||||||
return p.azureCloud.CreateManagedDisk(volumeOptions)
|
return p.azureCloud.CreateManagedDisk(volumeOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateShare creates a share and return its account name and key.
|
||||||
|
func (p *Provider) CreateShare() (string, string, string, error) {
|
||||||
|
accountOptions := &azure.AccountOptions{
|
||||||
|
Name: "",
|
||||||
|
Type: string(compute.StandardLRS),
|
||||||
|
ResourceGroup: p.azureCloud.ResourceGroup,
|
||||||
|
Location: p.azureCloud.GetLocation(),
|
||||||
|
EnableHTTPSTrafficOnly: true,
|
||||||
|
Tags: nil,
|
||||||
|
VirtualNetworkResourceIDs: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
shareOptions := &fileclient.ShareOptions{
|
||||||
|
Name: fmt.Sprintf("%s-%s", framework.TestContext.Prefix, string(uuid.NewUUID())),
|
||||||
|
RequestGiB: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
accountName, accountKey, err := p.azureCloud.CreateFileShare(accountOptions, shareOptions)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return accountName, accountKey, shareOptions.Name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) DeleteShare(accountName, shareName string) error {
|
||||||
|
err := p.azureCloud.DeleteFileShare(p.azureCloud.ResourceGroup, accountName, shareName)
|
||||||
|
if err != nil {
|
||||||
|
framework.Logf("failed to delete Azure File share %q: %v", shareName, err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// DeletePD deletes a persistent volume
|
// DeletePD deletes a persistent volume
|
||||||
func (p *Provider) DeletePD(pdName string) error {
|
func (p *Provider) DeletePD(pdName string) error {
|
||||||
if err := p.azureCloud.DeleteManagedDisk(pdName); err != nil {
|
if err := p.azureCloud.DeleteManagedDisk(pdName); err != nil {
|
||||||
|
@ -225,6 +225,14 @@ func (p *Provider) DeleteNode(node *v1.Node) error {
|
|||||||
return p.gceCloud.DeleteInstance(project, zone, node.Name)
|
return p.gceCloud.DeleteInstance(project, zone, node.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Provider) CreateShare() (string, string, string, error) {
|
||||||
|
return "", "", "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Provider) DeleteShare(accountName, shareName string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// CreatePD creates a persistent volume
|
// CreatePD creates a persistent volume
|
||||||
func (p *Provider) CreatePD(zone string) (string, error) {
|
func (p *Provider) CreatePD(zone string) (string, error) {
|
||||||
pdName := fmt.Sprintf("%s-%s", framework.TestContext.Prefix, string(uuid.NewUUID()))
|
pdName := fmt.Sprintf("%s-%s", framework.TestContext.Prefix, string(uuid.NewUUID()))
|
||||||
|
@ -673,6 +673,14 @@ func createPDWithRetry(zone string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateShare() (string, string, string, error) {
|
||||||
|
return framework.TestContext.CloudConfig.Provider.CreateShare()
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteShare(accountName, shareName string) error {
|
||||||
|
return framework.TestContext.CloudConfig.Provider.DeleteShare(accountName, shareName)
|
||||||
|
}
|
||||||
|
|
||||||
// CreatePDWithRetry creates PD with retry.
|
// CreatePDWithRetry creates PD with retry.
|
||||||
func CreatePDWithRetry() (string, error) {
|
func CreatePDWithRetry() (string, error) {
|
||||||
return createPDWithRetry("")
|
return createPDWithRetry("")
|
||||||
|
@ -2025,3 +2025,131 @@ func cleanUpVolumeServerWithSecret(f *framework.Framework, serverPod *v1.Pod, se
|
|||||||
framework.Logf("Server pod delete failed: %v", err)
|
framework.Logf("Server pod delete failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Azure File
|
||||||
|
type azureFileDriver struct {
|
||||||
|
driverInfo storageframework.DriverInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type azureFileVolume struct {
|
||||||
|
accountName string
|
||||||
|
shareName string
|
||||||
|
secretName string
|
||||||
|
secretNamespace string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ storageframework.TestDriver = &azureFileDriver{}
|
||||||
|
var _ storageframework.PreprovisionedVolumeTestDriver = &azureFileDriver{}
|
||||||
|
var _ storageframework.InlineVolumeTestDriver = &azureFileDriver{}
|
||||||
|
var _ storageframework.PreprovisionedPVTestDriver = &azureFileDriver{}
|
||||||
|
var _ storageframework.DynamicPVTestDriver = &azureFileDriver{}
|
||||||
|
|
||||||
|
// InitAzureFileDriver returns azureFileDriver that implements TestDriver interface
|
||||||
|
func InitAzureFileDriver() storageframework.TestDriver {
|
||||||
|
return &azureFileDriver{
|
||||||
|
driverInfo: storageframework.DriverInfo{
|
||||||
|
Name: "azure-file",
|
||||||
|
InTreePluginName: "kubernetes.io/azure-file",
|
||||||
|
MaxFileSize: storageframework.FileSizeMedium,
|
||||||
|
SupportedSizeRange: e2evolume.SizeRange{
|
||||||
|
Min: "1Gi",
|
||||||
|
},
|
||||||
|
SupportedFsType: sets.NewString(
|
||||||
|
"", // Default fsType
|
||||||
|
),
|
||||||
|
Capabilities: map[storageframework.Capability]bool{
|
||||||
|
storageframework.CapPersistence: true,
|
||||||
|
storageframework.CapExec: true,
|
||||||
|
storageframework.CapRWX: true,
|
||||||
|
storageframework.CapMultiPODs: true,
|
||||||
|
storageframework.CapControllerExpansion: true,
|
||||||
|
storageframework.CapNodeExpansion: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *azureFileDriver) GetDriverInfo() *storageframework.DriverInfo {
|
||||||
|
return &a.driverInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *azureFileDriver) SkipUnsupportedTest(pattern storageframework.TestPattern) {
|
||||||
|
e2eskipper.SkipUnlessProviderIs("azure")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *azureFileDriver) GetVolumeSource(readOnly bool, fsType string, e2evolume storageframework.TestVolume) *v1.VolumeSource {
|
||||||
|
av, ok := e2evolume.(*azureFileVolume)
|
||||||
|
framework.ExpectEqual(ok, true, "Failed to cast test volume to Azure test volume")
|
||||||
|
volSource := v1.VolumeSource{
|
||||||
|
AzureFile: &v1.AzureFileVolumeSource{
|
||||||
|
SecretName: av.secretName,
|
||||||
|
ShareName: av.shareName,
|
||||||
|
ReadOnly: readOnly,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &volSource
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *azureFileDriver) GetPersistentVolumeSource(readOnly bool, fsType string, e2evolume storageframework.TestVolume) (*v1.PersistentVolumeSource, *v1.VolumeNodeAffinity) {
|
||||||
|
av, ok := e2evolume.(*azureFileVolume)
|
||||||
|
framework.ExpectEqual(ok, true, "Failed to cast test volume to Azure test volume")
|
||||||
|
pvSource := v1.PersistentVolumeSource{
|
||||||
|
AzureFile: &v1.AzureFilePersistentVolumeSource{
|
||||||
|
SecretName: av.secretName,
|
||||||
|
ShareName: av.shareName,
|
||||||
|
SecretNamespace: &av.secretNamespace,
|
||||||
|
ReadOnly: readOnly,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &pvSource, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *azureFileDriver) GetDynamicProvisionStorageClass(config *storageframework.PerTestConfig, fsType string) *storagev1.StorageClass {
|
||||||
|
provisioner := "kubernetes.io/azure-file"
|
||||||
|
parameters := map[string]string{}
|
||||||
|
ns := config.Framework.Namespace.Name
|
||||||
|
immediateBinding := storagev1.VolumeBindingImmediate
|
||||||
|
return storageframework.GetStorageClass(provisioner, parameters, &immediateBinding, ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *azureFileDriver) PrepareTest(f *framework.Framework) (*storageframework.PerTestConfig, func()) {
|
||||||
|
return &storageframework.PerTestConfig{
|
||||||
|
Driver: a,
|
||||||
|
Prefix: "azure-file",
|
||||||
|
Framework: f,
|
||||||
|
}, func() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *azureFileDriver) CreateVolume(config *storageframework.PerTestConfig, volType storageframework.TestVolType) storageframework.TestVolume {
|
||||||
|
ginkgo.By("creating a test azure file volume")
|
||||||
|
accountName, accountKey, shareName, err := e2epv.CreateShare()
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
|
secretName := "azure-storage-account-" + accountName + "-secret"
|
||||||
|
secret := &v1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Namespace: config.Framework.Namespace.Name,
|
||||||
|
Name: secretName,
|
||||||
|
},
|
||||||
|
|
||||||
|
Data: map[string][]byte{
|
||||||
|
"azurestorageaccountname": []byte(accountName),
|
||||||
|
"azurestorageaccountkey": []byte(accountKey),
|
||||||
|
},
|
||||||
|
Type: "Opaque",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = config.Framework.ClientSet.CoreV1().Secrets(config.Framework.Namespace.Name).Create(context.TODO(), secret, metav1.CreateOptions{})
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
return &azureFileVolume{
|
||||||
|
accountName: accountName,
|
||||||
|
shareName: shareName,
|
||||||
|
secretName: secretName,
|
||||||
|
secretNamespace: config.Framework.Namespace.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *azureFileVolume) DeleteVolume() {
|
||||||
|
err := e2epv.DeleteShare(v.accountName, v.shareName)
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
}
|
||||||
|
@ -39,6 +39,7 @@ var testDrivers = []func() storageframework.TestDriver{
|
|||||||
drivers.InitWindowsGcePdDriver,
|
drivers.InitWindowsGcePdDriver,
|
||||||
drivers.InitVSphereDriver,
|
drivers.InitVSphereDriver,
|
||||||
drivers.InitAzureDiskDriver,
|
drivers.InitAzureDiskDriver,
|
||||||
|
drivers.InitAzureFileDriver,
|
||||||
drivers.InitAwsDriver,
|
drivers.InitAwsDriver,
|
||||||
drivers.InitLocalDriverWithVolumeType(utils.LocalVolumeDirectory),
|
drivers.InitLocalDriverWithVolumeType(utils.LocalVolumeDirectory),
|
||||||
drivers.InitLocalDriverWithVolumeType(utils.LocalVolumeDirectoryLink),
|
drivers.InitLocalDriverWithVolumeType(utils.LocalVolumeDirectoryLink),
|
||||||
|
Loading…
Reference in New Issue
Block a user