Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check if PV/PVC Access Modes are Supported by the Volume Provider #139

Merged
merged 41 commits into from Dec 14, 2022
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
6eead06
WIP: Check PVC access mode
rrpolanco Nov 3, 2022
3ac07a8
Still WIP
rrpolanco Nov 4, 2022
3ef7e7d
More WIP
rrpolanco Nov 16, 2022
aa01da4
Adding tests
rrpolanco Nov 17, 2022
61bc196
Add more unit test
rrpolanco Nov 17, 2022
00a0a86
Passing UT
rrpolanco Nov 18, 2022
7f3aabb
Add option to skip validation
rrpolanco Nov 18, 2022
d02b37c
Export PVCError
rrpolanco Nov 18, 2022
304e3d8
correctly return map
rrpolanco Nov 18, 2022
5f1f4a8
print when there are validation errors
rrpolanco Nov 18, 2022
0a40686
don't overwrite status for non-pending pvcs
rrpolanco Nov 18, 2022
24a161e
revert previous change
rrpolanco Nov 18, 2022
834ee8a
fix events and tab writer output
rrpolanco Nov 19, 2022
8c6683d
Add more unit test
rrpolanco Nov 21, 2022
b44e097
Add pod ready timeout out for volume validation pods
rrpolanco Nov 22, 2022
bacfe88
convert pod ready timeout to second units
rrpolanco Nov 22, 2022
26ab28b
accept an int for timeout instead of duration
rrpolanco Nov 22, 2022
59f1f05
specify PVC copy operation timeout in seconds
rrpolanco Nov 23, 2022
a44c4ba
rename flag
rrpolanco Nov 23, 2022
ee23c2c
Refactor WIP
rrpolanco Nov 30, 2022
efe96f3
WIP: PR Review Refactor
rrpolanco Dec 1, 2022
8333438
WIP: More PR review refactor
rrpolanco Dec 2, 2022
87666f5
Map all failures to exit code 1
rrpolanco Dec 2, 2022
a556650
Address Ethan's PR review comments and suggestions
rrpolanco Dec 2, 2022
ff3ea81
tweak Test_pvcForStorageClass test
rrpolanco Dec 2, 2022
f2b558b
convert podready timeout to correct unit
rrpolanco Dec 3, 2022
de8c668
allow os signals to context
rrpolanco Dec 3, 2022
0313d4a
fix pod and pvc cleanup
rrpolanco Dec 3, 2022
cf84ac3
simplify table output
rrpolanco Dec 3, 2022
7c8d9e5
speed up pod deletion
rrpolanco Dec 3, 2022
9e2f86c
validate storage class resource is present in the cluster
rrpolanco Dec 7, 2022
263427f
Change output message
rrpolanco Dec 7, 2022
0659ab5
Add todo
rrpolanco Dec 7, 2022
573e996
Update flags and README
rrpolanco Dec 7, 2022
9d3323d
Update text for pod-ready-timeout flag
rrpolanco Dec 7, 2022
25f7358
Add Ethan's suggestion
rrpolanco Dec 7, 2022
b8382ca
--skip-source-validation works with preflight validation
rrpolanco Dec 9, 2022
92cb2b7
Simplify deleteTmpPVC()
rrpolanco Dec 14, 2022
726a160
Update README with --delete-pv-timeout flag
rrpolanco Dec 14, 2022
54ba092
fix timeout flags
rrpolanco Dec 14, 2022
df71c22
log name of the tempt pvc and not the struct
rrpolanco Dec 14, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 18 additions & 1 deletion README.md
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,9 @@ 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 |

## Process

Expand Down
67 changes: 66 additions & 1 deletion cmd/main.go
@@ -1,16 +1,81 @@
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
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.DurationVar(&options.PodReadyTimeout, "pod-ready-timeout", 60*time.Second, "length of time to wait (in seconds) for validation pod(s) to go into Ready phase")
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()

// 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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be stderr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to separate the output of the validation failures to go to stdout and program errors to stderr.

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
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