Skip to content

Commit

Permalink
add import snapshot e2e test
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyXiangLi committed Jan 7, 2021
1 parent 049fc73 commit 6b6239d
Show file tree
Hide file tree
Showing 9 changed files with 322 additions and 11 deletions.
79 changes: 79 additions & 0 deletions examples/kubernetes/snapshot/specs/snapshot-import/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Volume Snapshots

## Overview

This driver implements basic volume snapshotting functionality using
the [external snapshotter](https://github.com/kubernetes-csi/external-snapshotter) sidecar and creates snapshots of EBS
volumes using the `VolumeSnapshot` custom resources.

## Prerequisites

1. Kubernetes 1.17+ (CSI 1.0).

2. The `VolumeSnapshotDataSource` must be set in `--feature-gates=` in the `kube-apiserver`. This feature is enabled by
default from Kubernetes v1.17+.

3. Install Snapshot Beta CRDs, Common Snapshot Controller, & CSI Driver (with alpha features) per CSI
Snapshotter [Doc](https://github.com/kubernetes-csi/external-snapshotter#usage)

### Usage

1. Edit the PersistentVolume spec in [example manifest](./static-snapshot/volume-snapshot-content.yaml).
Update `snapshotHandle` with EBS snapshot ID that you are going to use. In this example, I have a pre-created EBS
snapshot in us-west-2b availability zone.

```
apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotContent
metadata:
name: static-snapshot-content
spec:
volumeSnapshotRef:
kind: VolumeSnapshot
name: static-snapshot-demo
namespace: default
source:
snapshotHandle: snap-0fba4d7649d765c50
driver: ebs.csi.aws.com
deletionPolicy: Delete
volumeSnapshotClassName: csi-aws-vsc
```

2. Create the `StorageClass` and `VolumeSnapshotClass`:

```
kubectl apply -f specs/classes/
```

3. Create the `VolumeSnapshotContent` and `VolumeSnapshot`:

```
kubectl apply -f specs/snapshot-import/static-snapshot/
```

4. Validate the VolumeSnapshot was created and `snapshotHandle` contains an EBS snapshotID:

```
kubectl describe VolumeSnapshotContent
kubectl describe VolumeSnapshot
```

5. Create the `PersistentVolumeClaim` and `Pod`:

```
kubectl apply -f specs/snapshot-import/app/
```

6. Validate the pod successfully wrote data to the volume:

```
kubectl exec -it app cat /data/out.txt
```

7. Cleanup resources:

```
kubectl delete -f specs/snapshot-import/app
kubectl delete -f specs/snapshot-import/static-snapshot
kubectl delete -f specs/classes
```
15 changes: 15 additions & 0 deletions examples/kubernetes/snapshot/specs/snapshot-import/app/claim.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ebs-snapshot-restored-claim
spec:
accessModes:
- ReadWriteOnce
storageClassName: ebs-sc
resources:
requests:
storage: 4Gi
dataSource:
name: static-snapshot-demo
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
17 changes: 17 additions & 0 deletions examples/kubernetes/snapshot/specs/snapshot-import/app/pod.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: v1
kind: Pod
metadata:
name: app
spec:
containers:
- name: app
image: centos
command: ["/bin/sh"]
args: ["-c", "while true; do echo $(date -u) >> /data/out.txt; sleep 5; done"]
volumeMounts:
- name: persistent-storage
mountPath: /data
volumes:
- name: persistent-storage
persistentVolumeClaim:
claimName: ebs-snapshot-restored-claim
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ spec:
source:
snapshotHandle: snap-0fba4d7649d765c50
driver: ebs.csi.aws.com
deletionPolicy: Delete
volumeSnapshotClassName: csi-aws-vsc
53 changes: 46 additions & 7 deletions tests/e2e/pre_provsioning.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package e2e
import (
"context"
"fmt"
k8srestclient "k8s.io/client-go/rest"
"math/rand"
"os"
"strings"
Expand All @@ -38,7 +39,8 @@ const (

awsAvailabilityZonesEnv = "AWS_AVAILABILITY_ZONES"

dummyVolumeName = "pre-provisioned"
dummyVolumeName = "pre-provisioned"
dummySnapshotName = "pre-provisioned-snapshot"
)

var (
Expand All @@ -50,12 +52,15 @@ var _ = Describe("[ebs-csi-e2e] [single-az] Pre-Provisioned", func() {
f := framework.NewDefaultFramework("ebs")

var (
cs clientset.Interface
ns *v1.Namespace
ebsDriver driver.PreProvisionedVolumeTestDriver
cloud awscloud.Cloud
volumeID string
diskSize string
cs clientset.Interface
ns *v1.Namespace
ebsDriver driver.PreProvisionedVolumeTestDriver
pvTestDriver driver.PVTestDriver
snapshotrcs k8srestclient.Interface
cloud awscloud.Cloud
volumeID string
snapshotID string
diskSize string
// Set to true if the volume should be deleted automatically after test
skipManuallyDeletingVolume bool
)
Expand Down Expand Up @@ -90,7 +95,21 @@ var _ = Describe("[ebs-csi-e2e] [single-az] Pre-Provisioned", func() {
}
volumeID = disk.VolumeID
diskSize = fmt.Sprintf("%dGi", defaultDiskSize)
snapshotrcs, err = restClient(testsuites.SnapshotAPIGroup, testsuites.APIVersionv1beta1)
if err != nil {
Fail(fmt.Sprintf("could not get rest clientset: %v", err))
}
pvTestDriver = driver.InitEbsCSIDriver()
By(fmt.Sprintf("Successfully provisioned EBS volume: %q\n", volumeID))
snapshotOptions := &awscloud.SnapshotOptions{
Tags: map[string]string{awscloud.SnapshotNameTagKey: dummySnapshotName},
}
snapshot, err := cloud.CreateSnapshot(context.Background(), volumeID, snapshotOptions)
if err != nil {
Fail(fmt.Sprintf("could not provision a snapshot from volume: %v", volumeID))
}
snapshotID = snapshot.SnapshotID
By(fmt.Sprintf("Successfully provisioned EBS volume snapshot: %q\n", snapshotID))
})

AfterEach(func() {
Expand Down Expand Up @@ -130,6 +149,26 @@ var _ = Describe("[ebs-csi-e2e] [single-az] Pre-Provisioned", func() {
test.Run(cs, ns)
})

It("[env] should use a pre-defined snapshot and create pv from that", func() {
pod := testsuites.PodDetails{
Cmd: "echo 'hello world' >> /mnt/test-1/data && grep 'hello world' /mnt/test-1/data && sync",
Volumes: []testsuites.VolumeDetails{
{
ClaimSize: diskSize,
VolumeMount: testsuites.VolumeMountDetails{
NameGenerate: "test-volume-",
MountPathGenerate: "/mnt/test-",
},
},
},
}
test := testsuites.PreProvisionedVolumeSnapshotTest{
CSIDriver: pvTestDriver,
Pod: pod,
}
test.Run(cs, snapshotrcs, ns, snapshotID)
})

It("[env] should use a pre-provisioned volume and mount it as readOnly in a pod", func() {
pods := []testsuites.PodDetails{
{
Expand Down
71 changes: 71 additions & 0 deletions tests/e2e/testsuites/pre_provisioned_snapshot_volume_tester.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
Copyright 2018 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 testsuites

import (
"fmt"
"github.com/kubernetes-sigs/aws-ebs-csi-driver/tests/e2e/driver"
v1 "k8s.io/api/core/v1"
storagev1 "k8s.io/api/storage/v1"
clientset "k8s.io/client-go/kubernetes"
k8srestclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/test/e2e/framework"

awscloud "github.com/kubernetes-sigs/aws-ebs-csi-driver/pkg/cloud"

. "github.com/onsi/ginkgo"
)

type PreProvisionedVolumeSnapshotTest struct {
CSIDriver driver.PVTestDriver
Pod PodDetails
}

var (
tCloud awscloud.Cloud
)

func (t *PreProvisionedVolumeSnapshotTest) Run(client clientset.Interface, restclient k8srestclient.Interface, namespace *v1.Namespace, snapshotId string) {

By("taking snapshots")
tvsc, cleanup := CreateVolumeSnapshotClass(restclient, namespace, t.CSIDriver)
defer cleanup()

tvolumeSnapshotContent := tvsc.CreateStaticVolumeSnapshotContent(snapshotId)
tvs := tvsc.CreateStaticVolumeSnapshot(tvolumeSnapshotContent)

defer tvsc.DeleteVolumeSnapshotContent(tvolumeSnapshotContent)
defer tvsc.DeleteSnapshot(tvs)
if len(t.Pod.Volumes) < 1 {
err := fmt.Errorf("Volume is not setup for testing pod, exit. ")
framework.ExpectNoError(err)
}

volume := t.Pod.Volumes[0]
volume.DataSource = &DataSource{Name: tvs.Name}
binding := storagev1.VolumeBindingWaitForFirstConsumer
volume.VolumeBindingMode = &binding
tPod := NewTestPod(client, namespace, t.Pod.Cmd)
tpvc, pvcCleanup := volume.SetupDynamicPersistentVolumeClaim(client, namespace, t.CSIDriver)
for i := range pvcCleanup {
defer pvcCleanup[i]()
}
tPod.SetupVolume(tpvc.persistentVolumeClaim, volume.VolumeMount.NameGenerate+"1", volume.VolumeMount.MountPathGenerate+"1", volume.VolumeMount.ReadOnly)
By("deploying a second pod with a volume restored from the snapshot")
tPod.Create()
defer tPod.Cleanup()
By("checking that the pods command exits with no error")
tPod.WaitForSuccess()
}
7 changes: 4 additions & 3 deletions tests/e2e/testsuites/specs.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ const (
)

const (
VolumeSnapshotKind = "VolumeSnapshot"
SnapshotAPIVersion = "snapshot.storage.k8s.io/v1beta1"
APIVersionv1beta1 = "v1beta1"
VolumeSnapshotKind = "VolumeSnapshot"
VolumeSnapshotContentKind = "VolumeSnapshotContent"
SnapshotAPIVersion = "snapshot.storage.k8s.io/v1beta1"
APIVersionv1beta1 = "v1beta1"
)

var (
Expand Down
Loading

0 comments on commit 6b6239d

Please sign in to comment.