Skip to content

Commit

Permalink
Add the ability to migrate objects between rancher environments (#8)
Browse files Browse the repository at this point in the history
* Add the ability to migrate objects between rancher environments

* Add user migrate and status

* fix
  • Loading branch information
galal-hussein authored Mar 27, 2024
1 parent f351692 commit 792928f
Show file tree
Hide file tree
Showing 15 changed files with 468 additions and 62 deletions.
75 changes: 60 additions & 15 deletions cli/cmds/interactive/interactive.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"galal-hussein/cattle-drive/pkg/cluster/tui"

v3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)

Expand Down Expand Up @@ -53,8 +53,6 @@ func NewCommand() *cli.Command {

func migrate(clx *cli.Context) error {
ctx := context.Background()
cmds.Spinner.Prefix = fmt.Sprintf("initiating source [%s] and target [%s] clusters objects.. ", source, target)
cmds.Spinner.Start()
restConfig, err := clientcmd.BuildConfigFromFlags("", cmds.Kubeconfig)
if err != nil {
return err
Expand All @@ -63,8 +61,31 @@ func migrate(clx *cli.Context) error {
if err != nil {
return err
}

// check for target rancher
var (
targetRancherConfig *rest.Config
targetRancherClient *client.Clients
)
if cmds.TargetRancherConfig != "" {
targetRancherConfig, err = clientcmd.BuildConfigFromFlags("", cmds.TargetRancherConfig)
if err != nil {
return err
}
targetRancherClient, err = client.New(ctx, targetRancherConfig)
if err != nil {
return err
}
}
prefixMsg := fmt.Sprintf("initiating source [%s] and target [%s] clusters objects.. ", source, target)
if cmds.TargetRancherConfig != "" {
prefixMsg = fmt.Sprintf("initiating source cluster [%s] on rancher host [%s] and target cluster [%s] on rancher host [%s] ", source, restConfig.Host, target, targetRancherConfig.Host)
}
cmds.Spinner.Prefix = prefixMsg
cmds.Spinner.Start()

if source == "" || target == "" {
logrus.Fatalf("source or target is not specified")
return fmt.Errorf("source or target is not specified")
}

var clusters v3.ClusterList
Expand All @@ -74,18 +95,28 @@ func migrate(clx *cli.Context) error {
}

for _, cluster := range clusters.Items {
logrus.Debugf("check cluster: %s", cluster.Spec.DisplayName)
if cluster.Spec.DisplayName == source {
logrus.Debugf("cluster %s found", source)
sourceCluster = cluster.DeepCopy()
}
if cluster.Spec.DisplayName == target {
logrus.Debugf("cluster %s found", target)
targetCluster = cluster.DeepCopy()
if targetRancherClient == nil {
if cluster.Spec.DisplayName == target {
targetCluster = cluster.DeepCopy()
}
}
}
if targetRancherClient != nil {
// find the target cluster on the target rancher environment
if err := targetRancherClient.Clusters.List(ctx, "", &clusters, v1.ListOptions{}); err != nil {
return err
}
for _, cluster := range clusters.Items {
if cluster.Spec.DisplayName == target {
targetCluster = cluster.DeepCopy()
}
}
}
if sourceCluster == nil || targetCluster == nil {
logrus.Fatal("failed to find source or target cluster")
return fmt.Errorf("failed to find source or target cluster")
}
// initiate client for the cluster
scConfig := *restConfig
Expand All @@ -100,6 +131,10 @@ func migrate(clx *cli.Context) error {
}
tcConfig := *restConfig
tcConfig.Host = restConfig.Host + "/k8s/clusters/" + targetCluster.Name
if targetRancherClient != nil {
tcConfig = *targetRancherConfig
tcConfig.Host = targetRancherConfig.Host + "/k8s/clusters/" + targetCluster.Name
}
tcClient, err := client.New(ctx, &tcConfig)
if err != nil {
return err
Expand All @@ -108,16 +143,26 @@ func migrate(clx *cli.Context) error {
Obj: targetCluster,
Client: tcClient,
}

// check if the target cluster is in external rancher environment then set external rancher to true
if targetRancherClient != nil {
tc.ExternalRancher = true
sc.ExternalRancher = true
}
if err := sc.Populate(ctx, cl); err != nil {
return err
}
if err := tc.Populate(ctx, cl); err != nil {
return err
if targetRancherClient != nil {
if err := tc.Populate(ctx, targetRancherClient); err != nil {
return err
}
} else {
if err := tc.Populate(ctx, cl); err != nil {
return err
}
}
if err := sc.Compare(ctx, cl, tc); err != nil {
if err := sc.Compare(ctx, tc); err != nil {
return err
}
cmds.Spinner.Stop()
return tui.StartTea(sc, tc, cl, logFilePath)
return tui.StartTea(sc, tc, cl, targetRancherClient, logFilePath)
}
71 changes: 60 additions & 11 deletions cli/cmds/migrate/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)

Expand Down Expand Up @@ -45,8 +46,6 @@ func NewCommand() *cli.Command {

func migrate(clx *cli.Context) error {
ctx := context.Background()
cmds.Spinner.Prefix = fmt.Sprintf("initiating source [%s] and target [%s] clusters objects.. ", source, target)
cmds.Spinner.Start()
restConfig, err := clientcmd.BuildConfigFromFlags("", cmds.Kubeconfig)
if err != nil {
return err
Expand All @@ -55,8 +54,30 @@ func migrate(clx *cli.Context) error {
if err != nil {
return err
}
// check for target rancher
var (
targetRancherConfig *rest.Config
targetRancherClient *client.Clients
)
if cmds.TargetRancherConfig != "" {
targetRancherConfig, err = clientcmd.BuildConfigFromFlags("", cmds.TargetRancherConfig)
if err != nil {
return err
}
targetRancherClient, err = client.New(ctx, targetRancherConfig)
if err != nil {
return err
}
}
prefixMsg := fmt.Sprintf("initiating source [%s] and target [%s] clusters objects.. ", source, target)
if cmds.TargetRancherConfig != "" {
prefixMsg = fmt.Sprintf("initiating source cluster [%s] on rancher host [%s] and target cluster [%s] on rancher host [%s] ", source, restConfig.Host, target, targetRancherConfig.Host)
}
cmds.Spinner.Prefix = prefixMsg
cmds.Spinner.Start()

if source == "" || target == "" {
logrus.Fatalf("source or target is not specified")
return fmt.Errorf("source or target is not specified")
}

var clusters v3.ClusterList
Expand All @@ -66,14 +87,24 @@ func migrate(clx *cli.Context) error {
}

for _, cluster := range clusters.Items {
logrus.Debugf("check cluster: %s", cluster.Spec.DisplayName)
if cluster.Spec.DisplayName == source {
logrus.Debugf("cluster %s found", source)
sourceCluster = cluster.DeepCopy()
}
if cluster.Spec.DisplayName == target {
logrus.Debugf("cluster %s found", target)
targetCluster = cluster.DeepCopy()
if targetRancherClient == nil {
if cluster.Spec.DisplayName == target {
targetCluster = cluster.DeepCopy()
}
}
}
if targetRancherClient != nil {
// find the target cluster on the target rancher environment
if err := targetRancherClient.Clusters.List(ctx, "", &clusters, v1.ListOptions{}); err != nil {
return err
}
for _, cluster := range clusters.Items {
if cluster.Spec.DisplayName == target {
targetCluster = cluster.DeepCopy()
}
}
}
if sourceCluster == nil || targetCluster == nil {
Expand All @@ -92,6 +123,10 @@ func migrate(clx *cli.Context) error {
}
tcConfig := *restConfig
tcConfig.Host = restConfig.Host + "/k8s/clusters/" + targetCluster.Name
if targetRancherClient != nil {
tcConfig = *targetRancherConfig
tcConfig.Host = targetRancherConfig.Host + "/k8s/clusters/" + targetCluster.Name
}
tcClient, err := client.New(ctx, &tcConfig)
if err != nil {
return err
Expand All @@ -100,15 +135,29 @@ func migrate(clx *cli.Context) error {
Obj: targetCluster,
Client: tcClient,
}
// check if the target cluster is in external rancher environment then set external rancher to true
if targetRancherClient != nil {
tc.ExternalRancher = true
sc.ExternalRancher = true
}
if err := sc.Populate(ctx, cl); err != nil {
return err
}
if err := tc.Populate(ctx, cl); err != nil {
return err
if targetRancherClient != nil {
if err := tc.Populate(ctx, targetRancherClient); err != nil {
return err
}
} else {
if err := tc.Populate(ctx, cl); err != nil {
return err
}
}
if err := sc.Compare(ctx, cl, tc); err != nil {
if err := sc.Compare(ctx, tc); err != nil {
return err
}
cmds.Spinner.Stop()
if targetRancherClient != nil {
return sc.Migrate(ctx, targetRancherClient, tc, os.Stdout)
}
return sc.Migrate(ctx, cl, tc, os.Stdout)
}
11 changes: 9 additions & 2 deletions cli/cmds/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,21 @@ import (
)

var (
Kubeconfig string
CommonFlags = []cli.Flag{
Kubeconfig string
TargetRancherConfig string
CommonFlags = []cli.Flag{
&cli.StringFlag{
Name: "kubeconfig",
EnvVars: []string{"KUBECONFIG"},
Usage: "Kubeconfig path",
Destination: &Kubeconfig,
},
&cli.StringFlag{
Name: "target-rancher-config",
EnvVars: []string{"TARGET_RANCHER"},
Usage: "(experimental) migrate cluster objects to another rancher deployment",
Destination: &TargetRancherConfig,
},
}
Spinner *spinner.Spinner
)
Expand Down
Loading

0 comments on commit 792928f

Please sign in to comment.