github.com/aleksanderaleksic/tgmigrate@v0.1.7/migration/migration_reverter.go (about) 1 package migration 2 3 import ( 4 "fmt" 5 "github.com/aleksanderaleksic/tgmigrate/common" 6 "github.com/aleksanderaleksic/tgmigrate/config" 7 "github.com/aleksanderaleksic/tgmigrate/history" 8 "github.com/aws/aws-sdk-go/aws" 9 "github.com/aws/aws-sdk-go/service/s3" 10 "os" 11 "sort" 12 ) 13 14 type Reverter struct { 15 Context *common.Context 16 Config *config.Config 17 S3StateClient *s3.S3 18 HistoryInterface history.History 19 } 20 21 func (r Reverter) RevertToIncluding(migrationName string) error { 22 hist, err := r.HistoryInterface.InitializeHistory() 23 if err != nil { 24 return err 25 } 26 27 migration := getMigrationWithName(hist.AppliedMigration, migrationName) 28 if migration == nil { 29 return fmt.Errorf("could not find a applied migration with the name: %s", migrationName) 30 } 31 32 migrationsToRevert := migrationsToRevert(hist.AppliedMigration, *migration) 33 34 defer r.HistoryInterface.WriteToStorage() 35 36 for _, migration := range migrationsToRevert { 37 err := r.revert(migration) 38 if err != nil { 39 return err 40 } 41 r.HistoryInterface.RemoveAppliedMigration(migration.Name) 42 } 43 44 return nil 45 } 46 47 func getMigrationWithName(slice []history.AppliedStorageHistoryObject, migrationName string) *history.AppliedStorageHistoryObject { 48 for _, migration := range slice { 49 if migration.Name == migrationName { 50 return &migration 51 } 52 } 53 return nil 54 } 55 56 func migrationsToRevert(all []history.AppliedStorageHistoryObject, inclusive history.AppliedStorageHistoryObject) []history.AppliedStorageHistoryObject { 57 migrationsToRevert := []history.AppliedStorageHistoryObject{inclusive} 58 59 for _, migration := range all { 60 if migration.Applied.Time().After(inclusive.Applied.Time()) { 61 migrationsToRevert = append(migrationsToRevert, migration) 62 } 63 } 64 65 sort.Slice(migrationsToRevert, func(i, j int) bool { 66 return migrationsToRevert[i].Applied.Time().After(migrationsToRevert[j].Applied.Time()) 67 }) 68 69 return migrationsToRevert 70 } 71 72 func (r Reverter) revert(migration history.AppliedStorageHistoryObject) error { 73 s3Config := r.Config.State.Config.(*config.S3StateConfig) 74 75 fmt.Printf("The following object version will be deleted:\n") 76 objectIdentifiersToDelete := make([]*s3.ObjectIdentifier, 0) 77 for _, obj := range migration.Metadata.S3Metadata.ChangedObjects { 78 objectIdentifiersToDelete = append(objectIdentifiersToDelete, &s3.ObjectIdentifier{ 79 Key: aws.String(obj.Key), 80 VersionId: aws.String(obj.ToVersionId), 81 }) 82 fmt.Printf("\t- key: %s, version: %s\n", obj.Key, obj.ToVersionId) 83 } 84 fmt.Printf("Are you sure you would like to continue?\n") 85 if !common.AskUserToConfirm() { 86 fmt.Printf("Cancelled by user, will not delete objects.\n") 87 os.Exit(0) 88 } 89 90 _, err := r.S3StateClient.DeleteObjects(&s3.DeleteObjectsInput{ 91 Bucket: aws.String(s3Config.Bucket), 92 Delete: &s3.Delete{ 93 Objects: objectIdentifiersToDelete, 94 Quiet: aws.Bool(false), 95 }, 96 }) 97 if err != nil { 98 return err 99 } 100 fmt.Printf("Successfully deleted object versions\n") 101 102 return nil 103 }