Skip to content

Commit

Permalink
CopyVolumeData improvements (#4130)
Browse files Browse the repository at this point in the history
1) Return backupID, backupRoot, backupArtifactLocation as
   function outputs
2) Add an improved test that tests data changes to the PVC
   are picked up and the artifacts created are compatible
   with RestoreData
  • Loading branch information
Vaibhav Kamra authored Oct 15, 2018
1 parent 6367d83 commit f6b60cd
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 22 deletions.
22 changes: 15 additions & 7 deletions pkg/function/copy_volume_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ import (
)

const (
kanisterToolsImage = "kanisterio/kanister-tools:0.12.0"
copyVolumeDataMountPoint = "/mnt/vol_data/%s"
copyVolumeDataJobPrefix = "copy-vol-data-"
CopyVolumeDataNamespaceArg = "namespace"
CopyVolumeDataVolumeArg = "volume"
CopyVolumeDataArtifactPrefixArg = "dataArtifactPrefix"
kanisterToolsImage = "kanisterio/kanister-tools:0.12.0"
copyVolumeDataMountPoint = "/mnt/vol_data/%s"
copyVolumeDataJobPrefix = "copy-vol-data-"
CopyVolumeDataNamespaceArg = "namespace"
CopyVolumeDataVolumeArg = "volume"
CopyVolumeDataArtifactPrefixArg = "dataArtifactPrefix"
CopyVolumeDataOutputBackupID = "backupID"
CopyVolumeDataOutputBackupRoot = "backupRoot"
CopyVolumeDataOutputBackupArtifactLocation = "backupArtifactLocation"
)

func init() {
Expand Down Expand Up @@ -70,7 +73,12 @@ func copyVolumeData(ctx context.Context, cli kubernetes.Interface, tp param.Temp
if err != nil {
return nil, errors.Wrapf(err, "Failed to create and upload backup")
}
return map[string]interface{}{"backupID": backupIdentifier}, nil
return map[string]interface{}{
CopyVolumeDataOutputBackupID: backupIdentifier,
CopyVolumeDataOutputBackupRoot: mountPoint,
CopyVolumeDataOutputBackupArtifactLocation: targetPath,
},
nil
}

func (*copyVolumeDataFunc) Exec(ctx context.Context, tp param.TemplateParams, args map[string]interface{}) (map[string]interface{}, error) {
Expand Down
116 changes: 101 additions & 15 deletions pkg/function/data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package function

import (
"context"
"fmt"

. "gopkg.in/check.v1"

"k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"

kanister "github.com/kanisterio/kanister/pkg"
Expand Down Expand Up @@ -154,9 +156,26 @@ func (s *DataSuite) TestBackupRestoreData(c *C) {
}
}

func newCopyDataBlueprint() crv1alpha1.Blueprint {
func newCopyDataTestBlueprint() crv1alpha1.Blueprint {
return crv1alpha1.Blueprint{
Actions: map[string]*crv1alpha1.BlueprintAction{
"addfile": {
Phases: []crv1alpha1.BlueprintPhase{
{
Name: "test1",
Func: "PrepareData",
Args: map[string]interface{}{
PrepareDataNamespaceArg: "{{ .PVC.Namespace }}",
PrepareDataImageArg: "busybox",
PrepareDataCommandArg: []string{
"touch",
"/mnt/data1/foo.txt",
},
PrepareDataVolumes: map[string]string{"{{ .PVC.Name }}": "/mnt/data1"},
},
},
},
},
"copy": &crv1alpha1.BlueprintAction{
Phases: []crv1alpha1.BlueprintPhase{
crv1alpha1.BlueprintPhase{
Expand All @@ -170,15 +189,90 @@ func newCopyDataBlueprint() crv1alpha1.Blueprint {
},
},
},
"restore": &crv1alpha1.BlueprintAction{
Phases: []crv1alpha1.BlueprintPhase{
crv1alpha1.BlueprintPhase{
Name: "testRestore",
Func: "RestoreData",
Args: map[string]interface{}{
RestoreDataNamespaceArg: "{{ .PVC.Namespace }}",
RestoreDataImageArg: "kanisterio/kanister-tools:0.12.0",
RestoreDataBackupArtifactPrefixArg: fmt.Sprintf("{{ .Options.%s }}", CopyVolumeDataOutputBackupArtifactLocation),
RestoreDataBackupIdentifierArg: fmt.Sprintf("{{ .Options.%s }}", CopyVolumeDataOutputBackupID),
RestoreDataVolsArg: map[string]string{
"{{ .PVC.Name }}": fmt.Sprintf("{{ .Options.%s }}", CopyVolumeDataOutputBackupRoot),
},
},
},
},
},
"checkfile": {
Phases: []crv1alpha1.BlueprintPhase{
{
Func: "PrepareData",
Args: map[string]interface{}{
PrepareDataNamespaceArg: "{{ .PVC.Namespace }}",
PrepareDataImageArg: "busybox",
PrepareDataCommandArg: []string{
"ls",
"-l",
"/mnt/datadir/foo.txt",
},
PrepareDataVolumes: map[string]string{"{{ .PVC.Name }}": "/mnt/datadir"},
},
},
},
},
},
}
}
func (s *DataSuite) TestCopyData(c *C) {
ctx := context.Background()
pvc := testutil.NewTestPVC()
pvc, err := s.cli.CoreV1().PersistentVolumeClaims(s.namespace).Create(pvc)
pvcSpec := testutil.NewTestPVC()
pvc, err := s.cli.CoreV1().PersistentVolumeClaims(s.namespace).Create(pvcSpec)
c.Assert(err, IsNil)
tp := s.initPVCTemplateParams(c, pvc, nil)
bp := newCopyDataTestBlueprint()

// Add a file on the source PVC
_ = runAction(c, bp, "addfile", tp)
// Copy PVC data
out := runAction(c, bp, "copy", tp)

// Validate outputs and setup as inputs for restore
c.Assert(out[CopyVolumeDataOutputBackupID].(string), Not(Equals), "")
c.Assert(out[CopyVolumeDataOutputBackupRoot].(string), Not(Equals), "")
c.Assert(out[CopyVolumeDataOutputBackupArtifactLocation].(string), Not(Equals), "")
options := map[string]string{
CopyVolumeDataOutputBackupID: out[CopyVolumeDataOutputBackupID].(string),
CopyVolumeDataOutputBackupRoot: out[CopyVolumeDataOutputBackupRoot].(string),
CopyVolumeDataOutputBackupArtifactLocation: out[CopyVolumeDataOutputBackupArtifactLocation].(string),
}

// Create a new PVC
pvc2, err := s.cli.CoreV1().PersistentVolumeClaims(s.namespace).Create(pvcSpec)
c.Assert(err, IsNil)
tp = s.initPVCTemplateParams(c, pvc2, options)
// Restore data from copy
_ = runAction(c, bp, "restore", tp)
// Validate file exists on this new PVC
_ = runAction(c, bp, "checkfile", tp)
}

func runAction(c *C, bp crv1alpha1.Blueprint, action string, tp *param.TemplateParams) map[string]interface{} {
phases, err := kanister.GetPhases(bp, action, *tp)
c.Assert(err, IsNil)
out := make(map[string]interface{})
for _, p := range phases {
o, err := p.Exec(context.Background(), bp, action, *tp)
c.Assert(err, IsNil)
for k, v := range o {
out[k] = v
}
}
return out
}

func (s *DataSuite) initPVCTemplateParams(c *C, pvc *v1.PersistentVolumeClaim, options map[string]string) *param.TemplateParams {
as := crv1alpha1.ActionSpec{
Object: crv1alpha1.ObjectReference{
Kind: param.PVCKind,
Expand All @@ -189,18 +283,10 @@ func (s *DataSuite) TestCopyData(c *C) {
Name: testutil.TestProfileName,
Namespace: s.namespace,
},
Options: options,
}

tp, err := param.New(ctx, s.cli, s.crCli, as)
tp, err := param.New(context.Background(), s.cli, s.crCli, as)
c.Assert(err, IsNil)

tp.Profile = testutil.ObjectStoreProfileOrSkip(c)

bp := newCopyDataBlueprint()
phases, err := kanister.GetPhases(bp, "copy", *tp)
c.Assert(err, IsNil)
for _, p := range phases {
_, err = p.Exec(context.Background(), bp, "copy", *tp)
c.Assert(err, IsNil)
}
return tp
}

0 comments on commit f6b60cd

Please sign in to comment.