Skip to content

Commit

Permalink
Check if PV/PVC Access Modes are Supported by the Destination Volume …
Browse files Browse the repository at this point in the history
…Provider (#139)

* WIP: Check PVC access mode

* Still WIP

* More WIP

* Adding tests

* Add more unit test

* Passing UT

* Add option to skip validation

* Export PVCError

* correctly return map

* print when there are validation errors

* don't overwrite status for non-pending pvcs

* revert previous change

* fix events and tab writer output

* Add more unit test

* Add pod ready timeout out for volume validation pods

* convert pod ready timeout to second units

* accept an int for timeout instead of duration

* specify PVC copy operation timeout in seconds

* rename flag

* Refactor WIP

* WIP: PR Review Refactor

* WIP: More PR review refactor

* Map all failures to exit code 1

* Address Ethan's PR review comments and suggestions

* tweak Test_pvcForStorageClass test

* convert podready timeout to correct unit

* allow os signals to context

* fix pod and pvc cleanup

* simplify table output

* speed up pod deletion

* validate storage class resource is present in the cluster

* Change output message

* Add todo

* Update flags and README

* Update text for pod-ready-timeout flag

* Add Ethan's suggestion

* --skip-source-validation works with preflight validation

* Simplify deleteTmpPVC()

* Update README with --delete-pv-timeout flag

* fix timeout flags

* log name of the tempt pvc and not the struct
  • Loading branch information
rrpolanco authored Dec 14, 2022
1 parent ca80a97 commit 19f941d
Show file tree
Hide file tree
Showing 12 changed files with 2,115 additions and 539 deletions.
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,26 @@
pvmigrate allows migrating PVCs between two StorageClasses by creating new PVs, copying over the data, and then changing
PVCs to refer to the new PVs.

## Preflight Validation

`pvmigrate` will run preflight migration validation to catch any potential failures prior to the migration.

Currently supported validations are:
- Checking for existence of storage classes
- Checking existing PVC access modes are supported on the destination storage provider

## Examples

To migrate PVs from the 'default' StorageClass to mynewsc:

```bash
pvmigrate --source-sc default --dest-sc mynewsc
pvmigrate --source-sc "default" --dest-sc "mynewsc"
```

To run preflight migration validation without actually running the migration operation:

```bash
pvmigrate --source-sc "source" --dest-sc "destination" --preflight-validation-only
```

## Flags
Expand All @@ -22,6 +36,10 @@ pvmigrate --source-sc default --dest-sc mynewsc
| --set-defaults | Bool | | false | change default storage class from source to dest |
| --verbose-copy | Bool | | false | show output from the rsync command used to copy data between PVCs |
| --skip-source-validation | Bool | | false | migrate from PVCs using a particular StorageClass name, even if that StorageClass does not exist |
| --preflight-validation-only | Bool | | false | skip the migration and run preflight validation only |
| --skip-preflight-validation | Bool | | false | skip preflight migration validation on the destination storage provider |
| --pod-ready-timeout | time.Duration | | 60 seconds | length of time to wait (in seconds) for validation pod(s) to go into Ready phase |
| --delete-pv-timeout | time.Duration | | 5 minutes | length of time to wait (in seconds) for backing PV to be removed when the temporary PVC is deleted |

## Process

Expand Down
74 changes: 73 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,88 @@
package main

import (
"context"
"flag"
"fmt"
"log"
"os"
"os/signal"
"time"

"github.com/replicatedhq/pvmigrate/pkg/migrate"
"github.com/replicatedhq/pvmigrate/pkg/preflight"
"github.com/replicatedhq/pvmigrate/pkg/version"
k8sclient "k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth" // this allows accessing a larger array of cloud providers
"sigs.k8s.io/controller-runtime/pkg/client/config"
)

func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()

fmt.Printf("Running pvmigrate build:\n")
version.Print()

migrate.Cli()
// Cli uses CLI options to run Migrate
var options migrate.Options
var skipPreflightValidation bool
var preflightValidationOnly bool
var podReadyTimeout int
var deletePVTimeout int
flag.StringVar(&options.SourceSCName, "source-sc", "", "storage provider name to migrate from")
flag.StringVar(&options.DestSCName, "dest-sc", "", "storage provider name to migrate to")
flag.StringVar(&options.RsyncImage, "rsync-image", "eeacms/rsync:2.3", "the image to use to copy PVCs - must have 'rsync' on the path")
flag.StringVar(&options.Namespace, "namespace", "", "only migrate PVCs within this namespace")
flag.BoolVar(&options.SetDefaults, "set-defaults", false, "change default storage class from source to dest")
flag.BoolVar(&options.VerboseCopy, "verbose-copy", false, "show output from the rsync command used to copy data between PVCs")
flag.BoolVar(&options.SkipSourceValidation, "skip-source-validation", false, "migrate from PVCs using a particular StorageClass name, even if that StorageClass does not exist")
flag.IntVar(&podReadyTimeout, "pod-ready-timeout", 60, "length of time to wait (in seconds) for validation pod(s) to go into Ready phase")
flag.IntVar(&deletePVTimeout, "delete-pv-timeout", 300, "length of time to wait (in seconds) for backing PV to be removed when temporary PVC is deleted")
flag.BoolVar(&skipPreflightValidation, "skip-preflight-validation", false, "skip preflight migration validation on the destination storage provider")
flag.BoolVar(&preflightValidationOnly, "preflight-validation-only", false, "skip the migration and run preflight validation only")

flag.Parse()

// update options with flag values
options.PodReadyTimeout = time.Duration(podReadyTimeout) * time.Second
options.DeletePVTimeout = time.Duration(deletePVTimeout) * time.Second

// setup logger
logger := log.New(os.Stderr, "", 0) // this has no time prefix etc

// setup k8s
cfg, err := config.GetConfig()
if err != nil {
logger.Printf("failed to get config: %s", err)
os.Exit(1)
}

clientset, err := k8sclient.NewForConfig(cfg)
if err != nil {
logger.Printf("failed to create kubernetes clientset: %s", err)
os.Exit(1)
}

if !skipPreflightValidation {
failures, err := preflight.Validate(ctx, logger, clientset, options)
if err != nil {
logger.Printf("failed to run preflight validation checks")
os.Exit(1)
}

if len(failures) != 0 {
preflight.PrintValidationFailures(os.Stdout, failures)
os.Exit(1)
}
}

// start the migration
if !preflightValidationOnly {
err = migrate.Migrate(ctx, logger, clientset, options)
if err != nil {
logger.Printf("migration failed: %s", err)
os.Exit(1)
}
}
}
33 changes: 18 additions & 15 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ module github.com/replicatedhq/pvmigrate
go 1.19

require (
github.com/google/go-cmp v0.5.9
github.com/stretchr/testify v1.8.1
k8s.io/api v0.25.4
k8s.io/apimachinery v0.25.4
k8s.io/client-go v0.25.3
k8s.io/client-go v0.25.4
k8s.io/kubernetes v1.25.4
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
sigs.k8s.io/controller-runtime v0.13.1
)

require (
cloud.google.com/go v0.97.0 // indirect
cloud.google.com/go/compute v1.12.1 // indirect
cloud.google.com/go/compute/metadata v0.2.1 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.27 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect
Expand All @@ -26,36 +29,36 @@ require (
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/swag v0.21.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.70.1 // indirect
k8s.io/klog/v2 v2.80.1 // indirect
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
Expand Down
Loading

0 comments on commit 19f941d

Please sign in to comment.