Skip to content

Commit

Permalink
Adds start and stop commands (#88)
Browse files Browse the repository at this point in the history
* Adds start and stop commands

Issue: PGO-450
  • Loading branch information
tony-landreth authored Nov 13, 2023
1 parent aa50506 commit 8ea30a4
Show file tree
Hide file tree
Showing 19 changed files with 606 additions and 82 deletions.
2 changes: 2 additions & 0 deletions docs/content/reference/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pgo is a kubectl plugin for PGO, the open source Postgres Operator from Crunchy
* [pgo delete](/reference/pgo_delete/) - Delete a resource
* [pgo restore](/reference/pgo_restore/) - Restore cluster
* [pgo show](/reference/pgo_show/) - Show PostgresCluster details
* [pgo start](/reference/pgo_start/) - Start cluster
* [pgo stop](/reference/pgo_stop/) - Stop cluster
* [pgo support](/reference/pgo_support/) - Crunchy Support commands for PGO
* [pgo version](/reference/pgo_version/) - PGO client and operator versions

71 changes: 71 additions & 0 deletions docs/content/reference/pgo_start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
title: pgo start
---
## pgo start

Start cluster

### Synopsis

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

```
pgo start CLUSTER_NAME [flags]
```

### Examples

```
# Start a 'hippo' postgrescluster.
pgo start hippo
# Resolve ownership conflict
pgo start hippo --force-conflicts
```
### Example output
```
postgresclusters/hippo start initiated
```

### Options

```
--force-conflicts take ownership and overwrite the shutdown setting
-h, --help help for start
```

### Options inherited from parent commands

```
--as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace.
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation.
--cache-dir string Default cache directory (default "$HOME/.kube/cache")
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
-n, --namespace string If present, the namespace scope for this CLI request
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
-s, --server string The address and port of the Kubernetes API server
--tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
```

### SEE ALSO

* [pgo](/reference/) - pgo is a kubectl plugin for PGO, the open source Postgres Operator

71 changes: 71 additions & 0 deletions docs/content/reference/pgo_stop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
title: pgo stop
---
## pgo stop

Stop cluster

### Synopsis

Stop sets the spec.shutdown field to true, allowing you to stop a PostgreSQL cluster.
The --force-conflicts flag may be required if the spec.shutdown field has been used before.

### RBAC Requirements
Resources Verbs
--------- -----
postgresclusters.postgres-operator.crunchydata.com [get patch]

### Usage

```
pgo stop CLUSTER_NAME [flags]
```

### Examples

```
# Stop a 'hippo' postgrescluster.
pgo stop hippo
# Resolve ownership conflict
pgo stop hippo --force-conflicts
```
### Example output
```
postgresclusters/hippo stop initiated
```

### Options

```
--force-conflicts take ownership and overwrite the shutdown setting
-h, --help help for stop
```

### Options inherited from parent commands

```
--as string Username to impersonate for the operation. User could be a regular user or a service account in a namespace.
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation.
--cache-dir string Default cache directory (default "$HOME/.kube/cache")
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
-n, --namespace string If present, the namespace scope for this CLI request
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
-s, --server string The address and port of the Kubernetes API server
--tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
```

### SEE ALSO

* [pgo](/reference/) - pgo is a kubectl plugin for PGO, the open source Postgres Operator

37 changes: 2 additions & 35 deletions internal/cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@
package cmd

import (
"bufio"
"context"
"fmt"
"io"
"os"

"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/crunchydata/postgres-operator-client/internal"
"github.com/crunchydata/postgres-operator-client/internal/apis/postgres-operator.crunchydata.com/v1beta1"
"github.com/crunchydata/postgres-operator-client/internal/util"
)

// newDeleteCommand returns the delete subcommand of the PGO plugin.
Expand Down Expand Up @@ -80,7 +79,7 @@ postgresclusters/hippo deleted`)
for i := 0; confirmed == nil && i < 10; i++ {
// retry 10 times or until a confirmation is given or denied,
// whichever comes first
confirmed = confirm(os.Stdin, os.Stdout)
confirmed = util.Confirm(os.Stdin, os.Stdout)
}

if confirmed == nil || !*confirmed {
Expand Down Expand Up @@ -112,38 +111,6 @@ postgresclusters/hippo deleted`)
return cmd
}

// confirm uses a Scanner to parse user input. A user must type in "yes" or "no"
// and then press enter. It has fuzzy matching, so "y", "Y", "yes", "YES",
// and "Yes" all count as confirmations and return 'true'. Similarly, "n", "N",
// "no", "No", "NO" all deny confirmation and return 'false'. If the input is not
// recognized, nil is returned.
func confirm(reader io.Reader, writer io.Writer) *bool {
var response string
var boolVar bool

scanner := bufio.NewScanner(reader)
if scanner.Scan() {
response = scanner.Text()
}

if scanner.Err() != nil || response == "" {
fmt.Fprint(writer, "Please type yes or no and then press enter: ")
return nil
}

yesResponses := []string{"y", "Y", "yes", "Yes", "YES"}
noResponses := []string{"n", "N", "no", "No", "NO"}
if containsString(yesResponses, response) {
boolVar = true
return &boolVar
} else if containsString(noResponses, response) {
return &boolVar
} else {
fmt.Fprint(writer, "Please type yes or no and then press enter: ")
return nil
}
}

// containsString returns true if slice contains element
func containsString(slice []string, element string) bool {
for _, elem := range slice {
Expand Down
45 changes: 0 additions & 45 deletions internal/cmd/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,56 +15,11 @@
package cmd

import (
"bytes"
"io"
"strings"
"testing"

"gotest.tools/v3/assert"
)

func TestConfirmDelete(t *testing.T) {

testsCases := []struct {
input string
invalidResponse bool
confirmed bool
}{
{"abc", true, false}, // invalid
{"", true, false}, // invalid
{"y", false, true},
{"Y", false, true},
{"yes", false, true},
{"Yes", false, true},
{"YES", false, true},
{"n", false, false},
{"N", false, false},
{"no", false, false},
{"No", false, false},
{"NO", false, false},
{"yep", true, false}, // invalid
{"nope", true, false}, // invalid
}

for _, tc := range testsCases {
t.Run("input is "+tc.input, func(t *testing.T) {
var reader io.Reader = strings.NewReader(tc.input)
var writer bytes.Buffer
confirmed := confirm(reader, &writer)
if tc.invalidResponse {
assert.Assert(t, confirmed == nil)
response, err := writer.ReadString(':')
assert.NilError(t, err)
assert.Equal(t, response, "Please type yes or no and then press enter:")

} else {
assert.Assert(t, confirmed != nil)
assert.Assert(t, *confirmed == tc.confirmed)
}
})
}
}

func TestContainsString(t *testing.T) {
testsCases := []struct {
desc string
Expand Down
2 changes: 2 additions & 0 deletions internal/cmd/pgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e
root.AddCommand(newShowCommand(config))
root.AddCommand(newSupportCommand(config))
root.AddCommand(newVersionCommand(config))
root.AddCommand(newStopCommand(config))
root.AddCommand(newStartCommand(config))

return root
}
Expand Down
4 changes: 2 additions & 2 deletions internal/cmd/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (

"github.com/crunchydata/postgres-operator-client/internal"
"github.com/crunchydata/postgres-operator-client/internal/apis/postgres-operator.crunchydata.com/v1beta1"
"github.com/crunchydata/postgres-operator-client/internal/util"
)

func newRestoreCommand(config *internal.Config) *cobra.Command {
Expand Down Expand Up @@ -232,11 +233,10 @@ func (config pgBackRestRestore) Run(ctx context.Context) error {

func (config pgBackRestRestore) confirm(attempts int) *bool {
for i := 0; i < attempts; i++ {
if confirmed := confirm(config.In, config.Out); confirmed != nil {
if confirmed := util.Confirm(config.In, config.Out); confirmed != nil {
return confirmed
}
}

return nil
}

Expand Down
Loading

0 comments on commit 8ea30a4

Please sign in to comment.