/
scaledown.go
160 lines (132 loc) · 4.83 KB
/
scaledown.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package cmd
/*
Copyright 2018 - 2022 Crunchy Data Solutions, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import (
"fmt"
"os"
"github.com/crunchydata/postgres-operator/pgo/api"
"github.com/crunchydata/postgres-operator/pgo/util"
msgs "github.com/crunchydata/postgres-operator/pkg/apiservermsgs"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
var scaledownCmd = &cobra.Command{
Use: "scaledown",
Short: "Scale down a PostgreSQL cluster",
Long: `The scale command allows you to scale down a Cluster's replica configuration. For example:
To list targetable replicas:
pgo scaledown mycluster --query
To scale down a specific replica:
pgo scaledown mycluster --target=mycluster-replica-xxxx`,
Run: func(cmd *cobra.Command, args []string) {
if Namespace == "" {
Namespace = PGONamespace
}
log.Debug("scaledown called")
if len(args) == 0 {
fmt.Println(`Error: You must specify the clusters to scale down.`)
} else {
if Query {
queryCluster(args, Namespace)
} else {
if util.AskForConfirmation(NoPrompt, "") {
} else {
fmt.Println("Aborting...")
os.Exit(2)
}
scaleDownCluster(args[0], Namespace)
}
}
},
}
func init() {
RootCmd.AddCommand(scaledownCmd)
scaledownCmd.Flags().BoolVarP(&Query, "query", "", false, "Prints the list of targetable replica candidates.")
scaledownCmd.Flags().StringVarP(&Target, "target", "", "", "The replica to target for scaling down")
scaledownCmd.Flags().BoolVarP(&DeleteData, "delete-data", "d", true,
"Causes the data for the scaled down replica to be removed permanently.")
scaledownCmd.Flags().MarkDeprecated("delete-data", "Data is deleted by default.")
scaledownCmd.Flags().BoolVar(&KeepData, "keep-data", false,
"Causes data for the scale down replica to *not* be deleted")
scaledownCmd.Flags().BoolVar(&NoPrompt, "no-prompt", false, "No command line confirmation.")
}
// queryCluster is a helper function that returns information about the
// available replicas that can be scaled down. This is called when the "--query"
// flag is specified
func queryCluster(args []string, ns string) {
// iterate through the clusters and output information about each one
for _, arg := range args {
// call the API
response, err := api.ScaleQuery(httpclient, arg, &SessionCredentials, ns)
// indicate which cluster this is. Put a newline before to put some
// separation between each line
if !response.Standby {
fmt.Printf("\nCluster: %s\n", arg)
} else {
fmt.Printf("\nCluster (standby): %s\n", arg)
}
// If the API returns in error, just bail out here
if err != nil {
fmt.Println("Error: " + err.Error())
os.Exit(2)
}
// If there is a controlled error, output the message here and continue
// to iterate through the list
if response.Status.Code != msgs.Ok {
fmt.Println("Error: " + response.Status.Msg)
continue
}
// If there are no replicas found for this cluster, indicate so, and
// continue to iterate through the list
if len(response.Results) == 0 {
fmt.Println("No replicas found.")
continue
}
// output the information about each instance
fmt.Printf("%-20s\t%-10s\t%-10s\t%-20s\t%s\n", "REPLICA", "STATUS", "NODE", "REPLICATION LAG",
"PENDING RESTART")
for i := 0; i < len(response.Results); i++ {
instance := response.Results[i]
log.Debugf("postgresql instance: %v", instance)
if instance.ReplicationLag != -1 {
fmt.Printf("%-20s\t%-10s\t%-10s\t%12d %-7s\t%15t\n",
instance.Name, instance.Status, instance.Node, instance.ReplicationLag, "MB",
instance.PendingRestart)
} else {
fmt.Printf("%-20s\t%-10s\t%-10s\t%15s\t%23t\n",
instance.Name, instance.Status, instance.Node, "unknown",
instance.PendingRestart)
}
}
}
}
func scaleDownCluster(clusterName, ns string) {
// determine if the data should be deleted. The modern flag for handling this
// is "KeepData" which defaults to "false". We will honor the "DeleteData"
// flag (which defaults to "true"), but this will be removed in a future
// release
deleteData := !KeepData && DeleteData
response, err := api.ScaleDownCluster(httpclient, clusterName, Target, deleteData,
&SessionCredentials, ns)
if err != nil {
fmt.Println("Error: ", err.Error())
return
}
if response.Status.Code == msgs.Ok {
for _, v := range response.Results {
fmt.Println(v)
}
} else {
fmt.Println("Error: " + response.Status.Msg)
}
}