Skip to content

Commit 26b283d

Browse files
Merge pull request #96 from v-harihar/migration-rsync
CLI: Migration rsync
2 parents cf053a4 + 3f47578 commit 26b283d

4 files changed

Lines changed: 246 additions & 67 deletions

File tree

kubectl-volsync/cmd/migration.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
package cmd
1818

1919
import (
20+
"context"
21+
"fmt"
22+
"time"
23+
2024
"github.com/spf13/cobra"
2125
"github.com/spf13/viper"
26+
"k8s.io/apimachinery/pkg/types"
27+
"k8s.io/apimachinery/pkg/util/wait"
28+
"k8s.io/klog/v2"
2229
"k8s.io/kubectl/pkg/util/i18n"
2330
"k8s.io/kubectl/pkg/util/templates"
31+
"sigs.k8s.io/controller-runtime/pkg/client"
2432

2533
volsyncv1alpha1 "github.com/backube/volsync/api/v1alpha1"
2634
)
@@ -104,3 +112,62 @@ func init() {
104112
cobra.CheckErr(migrationCmd.MarkPersistentFlagRequired("relationship"))
105113
cobra.CheckErr(viper.BindPFlag("relationship", migrationCmd.PersistentFlags().Lookup("relationship")))
106114
}
115+
116+
func loadMigrationRelationship(cmd *cobra.Command) (*migrationRelationship, error) {
117+
r, err := LoadRelationshipFromCommand(cmd, MigrationRelationshipType)
118+
if err != nil {
119+
return nil, err
120+
}
121+
122+
mr := &migrationRelationship{
123+
Relationship: *r,
124+
}
125+
126+
// Decode according to the file version
127+
version := mr.GetInt("data.version")
128+
switch version {
129+
case 1:
130+
if err := mr.GetData(&mr.data); err != nil {
131+
return nil, err
132+
}
133+
default:
134+
return nil, fmt.Errorf("unsupported config file version %d", version)
135+
}
136+
return mr, nil
137+
}
138+
139+
func (mrd *migrationRelationshipDestination) waitForRDStatus(ctx context.Context, clientObject client.Client) (
140+
*volsyncv1alpha1.ReplicationDestination, error) {
141+
// wait for migrationdestination to become ready
142+
nsName := types.NamespacedName{
143+
Namespace: mrd.Namespace,
144+
Name: mrd.RDName,
145+
}
146+
rd := &volsyncv1alpha1.ReplicationDestination{}
147+
err := wait.PollImmediate(5*time.Second, 2*time.Minute, func() (bool, error) {
148+
err := clientObject.Get(ctx, nsName, rd)
149+
if err != nil {
150+
return false, err
151+
}
152+
if rd.Status == nil || rd.Status.Rsync == nil {
153+
return false, nil
154+
}
155+
if rd.Status.Rsync.Address == nil {
156+
klog.V(2).Infof("Waiting for MigrationDestination %s RSync address to populate", rd.Name)
157+
return false, nil
158+
}
159+
160+
if rd.Status.Rsync.SSHKeys == nil {
161+
klog.V(2).Infof("Waiting for MigrationDestination %s RSync sshkeys to populate", rd.Name)
162+
return false, nil
163+
}
164+
165+
klog.V(2).Infof("Found MigrationDestination RSync Address: %s", *rd.Status.Rsync.Address)
166+
return true, nil
167+
})
168+
if err != nil {
169+
return nil, fmt.Errorf("failed to fetch rd status: %w,", err)
170+
}
171+
172+
return rd, nil
173+
}

kubectl-volsync/cmd/migration_create.go

Lines changed: 7 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@ package cmd
1919
import (
2020
"context"
2121
"fmt"
22-
"time"
2322

2423
"github.com/spf13/cobra"
2524
corev1 "k8s.io/api/core/v1"
2625
kerrs "k8s.io/apimachinery/pkg/api/errors"
2726
"k8s.io/apimachinery/pkg/api/resource"
2827
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2928
"k8s.io/apimachinery/pkg/types"
30-
"k8s.io/apimachinery/pkg/util/wait"
3129
"k8s.io/klog/v2"
3230
"k8s.io/kubectl/pkg/util/i18n"
3331
"k8s.io/kubectl/pkg/util/templates"
@@ -63,7 +61,7 @@ type migrationCreate struct {
6361
// SSH connections.
6462
ServiceType *corev1.ServiceType
6563
// client object to communicate with a cluster
66-
clientObject client.Client
64+
client client.Client
6765
// PVC object associated with pvcName used to create destination object
6866
PVC *corev1.PersistentVolumeClaim
6967
}
@@ -216,7 +214,7 @@ func (mc *migrationCreate) Run(ctx context.Context) error {
216214
if err != nil {
217215
return err
218216
}
219-
mc.clientObject = k8sClient
217+
mc.client = k8sClient
220218

221219
// Get the pvc from cluster
222220
mc.PVC, err = mc.getDestinationPVC(ctx)
@@ -247,7 +245,7 @@ func (mc *migrationCreate) Run(ctx context.Context) error {
247245
}
248246

249247
// Wait for ReplicationDestination to post address, sshkeys
250-
err = mc.waitForRDStatus(ctx)
248+
_, err = mc.mr.data.Destination.waitForRDStatus(ctx, mc.client)
251249
if err != nil {
252250
return err
253251
}
@@ -264,7 +262,7 @@ func (mc *migrationCreate) ensureNamespace(ctx context.Context) (*corev1.Namespa
264262
Name: mc.Namespace,
265263
},
266264
}
267-
if err := mc.clientObject.Create(ctx, ns); err != nil {
265+
if err := mc.client.Create(ctx, ns); err != nil {
268266
if kerrs.IsAlreadyExists(err) {
269267
klog.Infof("Namespace: \"%s\" is found, proceeding with the same",
270268
mc.Namespace)
@@ -309,7 +307,7 @@ func (mc *migrationCreate) createDestinationPVC(ctx context.Context) (*corev1.Pe
309307
},
310308
}
311309

312-
if err := mc.clientObject.Create(ctx, destPVC); err != nil {
310+
if err := mc.client.Create(ctx, destPVC); err != nil {
313311
return nil, err
314312
}
315313

@@ -325,7 +323,7 @@ func (mc *migrationCreate) getDestinationPVC(ctx context.Context) (*corev1.Persi
325323
Namespace: mc.Namespace,
326324
Name: mc.DestinationPVC,
327325
}
328-
err := mc.clientObject.Get(ctx, pvcInfo, destPVC)
326+
err := mc.client.Get(ctx, pvcInfo, destPVC)
329327
if err != nil {
330328
if client.IgnoreNotFound(err) == nil {
331329
klog.Infof("pvc: \"%s\" not found, creating the same", mc.DestinationPVC)
@@ -353,47 +351,11 @@ func (mc *migrationCreate) ensureReplicationDestination(ctx context.Context) (
353351
},
354352
},
355353
}
356-
if err := mc.clientObject.Create(ctx, rd); err != nil {
354+
if err := mc.client.Create(ctx, rd); err != nil {
357355
return nil, err
358356
}
359357
klog.Infof("Created ReplicationDestination: \"%s\" in Namespace: \"%s\" and Cluster: \"%s\"",
360358
rd.Name, rd.Namespace, rd.ClusterName)
361359

362360
return rd, nil
363361
}
364-
365-
func (mc *migrationCreate) waitForRDStatus(ctx context.Context) error {
366-
mrd := mc.mr.data.Destination
367-
// wait for migrationdestination to become ready
368-
nsName := types.NamespacedName{
369-
Namespace: mrd.Namespace,
370-
Name: mrd.RDName,
371-
}
372-
rd := &volsyncv1alpha1.ReplicationDestination{}
373-
err := wait.PollImmediate(5*time.Second, 2*time.Minute, func() (bool, error) {
374-
err := mc.clientObject.Get(ctx, nsName, rd)
375-
if err != nil {
376-
return false, err
377-
}
378-
if rd.Status == nil || rd.Status.Rsync == nil {
379-
return false, nil
380-
}
381-
if rd.Status.Rsync.Address == nil {
382-
klog.V(2).Infof("Waiting for MigrationDestination %s RSync address to populate", rd.Name)
383-
return false, nil
384-
}
385-
386-
if rd.Status.Rsync.SSHKeys == nil {
387-
klog.V(2).Infof("Waiting for MigrationDestination %s RSync sshkeys to populate", rd.Name)
388-
return false, nil
389-
}
390-
391-
klog.V(2).Infof("Found MigrationDestination RSync Address: %s", *rd.Status.Rsync.Address)
392-
return true, nil
393-
})
394-
if err != nil {
395-
return fmt.Errorf("failed to fetch rd status: %w,", err)
396-
}
397-
398-
return nil
399-
}

kubectl-volsync/cmd/migration_create_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ var _ = Describe("migration", func() {
5353
err = mc.parseCLI(cmd)
5454
Expect(err).NotTo(HaveOccurred())
5555

56-
mc.clientObject = k8sClient
56+
mc.client = k8sClient
5757
mc.Namespace = "foo-" + krand.String(5)
5858
// create namespace
5959
ns, err = mc.ensureNamespace(context.Background())
@@ -166,7 +166,7 @@ var _ = Describe("migration", func() {
166166
}}
167167
Expect(k8sClient.Status().Update(context.Background(), rd)).To(Succeed())
168168
// Wait for mock address and sshKey to pop up
169-
err = mc.waitForRDStatus(context.Background())
169+
_, err = mc.mr.data.Destination.waitForRDStatus(context.Background(), mc.client)
170170
Expect(err).ToNot(HaveOccurred())
171171
// Retry creation of replicationdestination and it should fail as destination already exists
172172
rd, err = mc.ensureReplicationDestination(context.Background())
@@ -176,7 +176,7 @@ var _ = Describe("migration", func() {
176176
Expect(k8sClient.Get(context.Background(), types.NamespacedName{Namespace: mc.Namespace,
177177
Name: mc.RDName}, rd)).To(Succeed())
178178
// Should return existing address and sshkey
179-
err = mc.waitForRDStatus(context.Background())
179+
_, err = mc.mr.data.Destination.waitForRDStatus(context.Background(), mc.client)
180180
Expect(err).ToNot(HaveOccurred())
181181
})
182182
})

0 commit comments

Comments
 (0)