Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/dev/gpctl/cmd/clusters-swap.go
2498 views
1
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package cmd
6
7
import (
8
"context"
9
"fmt"
10
"io"
11
12
"github.com/spf13/cobra"
13
14
"github.com/gitpod-io/gitpod/common-go/log"
15
"github.com/gitpod-io/gitpod/ws-manager-bridge/api"
16
)
17
18
// clustersSwapCmd represents the clustersSwapCmd command
19
var clustersSwapCmd = &cobra.Command{
20
Use: "swap [source cluster] [target cluster]",
21
Short: "Swaps the status and score of two clusters",
22
Long: "Swaps the status and score of two clusters. Beware: this is not an atomic operation.",
23
Args: cobra.ExactArgs(2),
24
Run: func(cmd *cobra.Command, args []string) {
25
ctx, cancel := context.WithCancel(context.Background())
26
defer cancel()
27
28
conn, client, err := getClustersClient(ctx)
29
if err != nil {
30
log.WithError(err).Fatal("cannot connect")
31
}
32
defer conn.Close()
33
34
resp, err := client.List(ctx, &api.ListRequest{})
35
if err != nil {
36
log.Fatal(err)
37
}
38
var (
39
src *api.ClusterStatus
40
dst *api.ClusterStatus
41
)
42
for _, c := range resp.Status {
43
if c.Name == args[0] {
44
src = c
45
}
46
if c.Name == args[1] {
47
dst = c
48
}
49
}
50
if src == nil {
51
log.Fatalf("source cluster \"%s\" not found", args[0])
52
}
53
if dst == nil {
54
log.Fatalf("destination cluster \"%s\" not found", args[1])
55
}
56
if ignore, _ := cmd.Flags().GetBool("ignore-admission-constraints"); !ignore {
57
if len(src.AdmissionConstraint) > 0 || len(dst.AdmissionConstraint) > 0 {
58
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")
59
}
60
}
61
if !src.Governed || !dst.Governed {
62
log.Fatal("can only swap goverened cluster")
63
}
64
if src.Static || dst.Static {
65
log.Fatal("can only swap non-static cluster")
66
}
67
68
reqs := []*api.UpdateRequest{
69
{Name: dst.Name, Property: &api.UpdateRequest_Cordoned{Cordoned: src.State == api.ClusterState_CORDONED}},
70
{Name: dst.Name, Property: &api.UpdateRequest_Score{Score: src.Score}},
71
{Name: src.Name, Property: &api.UpdateRequest_Cordoned{Cordoned: dst.State == api.ClusterState_CORDONED}},
72
{Name: src.Name, Property: &api.UpdateRequest_Score{Score: dst.Score}},
73
}
74
for _, r := range reqs {
75
_, err = client.Update(ctx, r)
76
if err != nil && err != io.EOF {
77
log.Fatal(err)
78
}
79
}
80
81
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)
82
},
83
}
84
85
func init() {
86
clustersCmd.AddCommand(clustersSwapCmd)
87
clustersSwapCmd.Flags().Bool("ignore-admission-constraints", false, "swap despite existing admission constraints")
88
}
89
90