package cmd
import (
"context"
"fmt"
"io"
"github.com/spf13/cobra"
"github.com/gitpod-io/gitpod/common-go/log"
"github.com/gitpod-io/gitpod/ws-manager-bridge/api"
)
var clustersSwapCmd = &cobra.Command{
Use: "swap [source cluster] [target cluster]",
Short: "Swaps the status and score of two clusters",
Long: "Swaps the status and score of two clusters. Beware: this is not an atomic operation.",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
conn, client, err := getClustersClient(ctx)
if err != nil {
log.WithError(err).Fatal("cannot connect")
}
defer conn.Close()
resp, err := client.List(ctx, &api.ListRequest{})
if err != nil {
log.Fatal(err)
}
var (
src *api.ClusterStatus
dst *api.ClusterStatus
)
for _, c := range resp.Status {
if c.Name == args[0] {
src = c
}
if c.Name == args[1] {
dst = c
}
}
if src == nil {
log.Fatalf("source cluster \"%s\" not found", args[0])
}
if dst == nil {
log.Fatalf("destination cluster \"%s\" not found", args[1])
}
if ignore, _ := cmd.Flags().GetBool("ignore-admission-constraints"); !ignore {
if len(src.AdmissionConstraint) > 0 || len(dst.AdmissionConstraint) > 0 {
log.Fatal("one of the clusters has admission constraints. Swapping their state/score is unlikely to have the desired effect. If you want to swap nonetheless, please remove the constraints or run with --ignore-admission-constraints")
}
}
if !src.Governed || !dst.Governed {
log.Fatal("can only swap goverened cluster")
}
if src.Static || dst.Static {
log.Fatal("can only swap non-static cluster")
}
reqs := []*api.UpdateRequest{
{Name: dst.Name, Property: &api.UpdateRequest_Cordoned{Cordoned: src.State == api.ClusterState_CORDONED}},
{Name: dst.Name, Property: &api.UpdateRequest_Score{Score: src.Score}},
{Name: src.Name, Property: &api.UpdateRequest_Cordoned{Cordoned: dst.State == api.ClusterState_CORDONED}},
{Name: src.Name, Property: &api.UpdateRequest_Score{Score: dst.Score}},
}
for _, r := range reqs {
_, err = client.Update(ctx, r)
if err != nil && err != io.EOF {
log.Fatal(err)
}
}
fmt.Printf("updated '%s' to score=%d,cordoned=%v and %s to score=%d,cordoned=%v \n", src.Name, dst.Score, dst.State == api.ClusterState_CORDONED, dst.Name, src.Score, src.State == api.ClusterState_CORDONED)
},
}
func init() {
clustersCmd.AddCommand(clustersSwapCmd)
clustersSwapCmd.Flags().Bool("ignore-admission-constraints", false, "swap despite existing admission constraints")
}