-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathstart.go
More file actions
155 lines (135 loc) · 4.57 KB
/
start.go
File metadata and controls
155 lines (135 loc) · 4.57 KB
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
// Copyright 2021 - 2026 Crunchy Data Solutions, Inc.
//
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
"context"
"fmt"
"github.com/spf13/cobra"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/dynamic"
"github.com/crunchydata/postgres-operator-client/internal"
"github.com/crunchydata/postgres-operator-client/internal/apis/postgres-operator.crunchydata.com/v1beta1"
)
type ShutdownRequestArgs struct {
ClusterName string
Config *internal.Config
ForceConflicts bool
Namespace string
NewShutdownValue bool
Mapping *meta.RESTMapping
}
func newStartCommand(config *internal.Config) *cobra.Command {
cmdStart := &cobra.Command{
Use: "start CLUSTER_NAME",
Short: "Start cluster",
Long: `Start sets the spec.shutdown field to false, allowing you to start a PostgreSQL cluster.
The --force-conflicts flag may be required if the spec.shutdown field has been updated by another client.
### RBAC Requirements
Resources Verbs
--------- -----
postgresclusters.postgres-operator.crunchydata.com [get patch]
### Usage`,
}
cmdStart.Example = internal.FormatExample(`# Start a 'hippo' postgrescluster.
pgo start hippo
# Resolve ownership conflict
pgo start hippo --force-conflicts
### Example output
postgresclusters/hippo start initiated`)
// Limit the number of args, that is, only one cluster name
cmdStart.Args = cobra.ExactArgs(1)
var forceConflicts bool
cmdStart.Flags().BoolVar(&forceConflicts, "force-conflicts", false, "take ownership and overwrite the shutdown setting")
cmdStart.RunE = func(cmd *cobra.Command, args []string) error {
mapping, client, err := v1beta1.NewPostgresClusterClient(config)
if err != nil {
return err
}
namespace, err := config.Namespace()
if err != nil {
return err
}
requestArgs := ShutdownRequestArgs{
ClusterName: args[0],
Config: config,
ForceConflicts: forceConflicts,
Namespace: namespace,
NewShutdownValue: false,
Mapping: mapping,
}
cluster, err := getPostgresCluster(client, requestArgs)
if err != nil {
return err
}
msg, err := patchClusterShutdown(cluster, client, requestArgs)
if msg != "" {
cmd.Print(msg)
}
if err != nil {
return err
}
return nil
}
return cmdStart
}
func patchClusterShutdown(cluster *unstructured.Unstructured, client dynamic.NamespaceableResourceInterface, args ShutdownRequestArgs) (string, error) {
ctx := context.Background()
currShutdownVal, found, err := unstructured.NestedBool(cluster.Object, "spec", "shutdown")
if err != nil {
return "", err
}
// If the shutdown status is equal to the intent of the command, do nothing.
if found && currShutdownVal == args.NewShutdownValue {
// If NewShutdownValue == true, we intend to stop the cluster.
if args.NewShutdownValue {
return "Cluster already Stopped. Nothing to do.\n", nil
}
return "Cluster already Started. Nothing to do.\n", nil
}
// Construct the payload.
intent := new(unstructured.Unstructured)
if err := internal.ExtractFieldsInto(cluster, intent, args.Config.Patch.FieldManager); err != nil {
return "", err
}
if err := unstructured.SetNestedField(intent.Object, args.NewShutdownValue, "spec", "shutdown"); err != nil {
return "", err
}
patch, err := intent.MarshalJSON()
if err != nil {
return "", err
}
patchOptions := metav1.PatchOptions{}
if args.ForceConflicts {
b := true
patchOptions.Force = &b
}
// Patch the update.
_, err = client.Namespace(args.Namespace).Patch(ctx,
args.ClusterName, types.ApplyPatchType, patch,
args.Config.Patch.PatchOptions(patchOptions))
if err != nil {
if apierrors.IsConflict(err) {
return "SUGGESTION: The --force-conflicts flag may help in performing this operation.\n", err
}
return "", err
}
var initiatedMsg string
// If NewShutdownValue == true, we intend to stop the cluster.
if args.NewShutdownValue {
initiatedMsg = "stop initiated"
} else {
initiatedMsg = "start initiated"
}
return fmt.Sprintf("%s/%s %s\n", args.Mapping.Resource.Resource, args.ClusterName, initiatedMsg), err
}
func getPostgresCluster(client dynamic.NamespaceableResourceInterface, args ShutdownRequestArgs) (*unstructured.Unstructured, error) {
ctx := context.Background()
cluster, err := client.Namespace(args.Namespace).Get(ctx,
args.ClusterName, metav1.GetOptions{})
return cluster, err
}