Skip to content

Commit 2655ee0

Browse files
authored
Recovery Mode on Instance (civo#518)
* Revert "Enable Vol Resize" This reverts commit 5876546. * added instance recovery * update docs * Revert "Revert "Enable Vol Resize"" This reverts commit 1357495. * bump civogo
1 parent f64aa37 commit 2655ee0

File tree

6 files changed

+175
-9
lines changed

6 files changed

+175
-9
lines changed

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,28 @@ Hello, world!
666666
667667
Please note that resizing can take a few minutes.
668668
669+
670+
### Recovery Mode
671+
672+
Recovery mode allows you to boot your instance into a recovery environment for troubleshooting.
673+
674+
```sh
675+
# Enable recovery mode for an instance
676+
civo instance recovery enable INSTANCE_ID/HOSTNAME
677+
678+
# Disable recovery mode for an instance
679+
civo instance recovery disable INSTANCE_ID/HOSTNAME
680+
681+
# Check recovery mode status
682+
civo instance recovery-status INSTANCE_ID/HOSTNAME
683+
```
684+
685+
The recovery-status command supports custom output formats with the following fields:
686+
* id - The instance ID
687+
* hostname - The instance hostname
688+
* status - Current recovery mode status
689+
690+
669691
### VNC Access
670692
671693
The VNC command allows you to access your instance through a browser-based VNC console.
@@ -688,6 +710,8 @@ When executed, the command will:
688710
2. Generate a secure VNC URL
689711
3. Automatically open the console in your default browser
690712
4. Attempt to connect for up to 35 seconds before timing out
713+
714+
691715
## Kubernetes clusters
692716
693717
#### Introduction

cmd/instance/instance.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ func init() {
3939
InstanceCmd.AddCommand(instancePasswordCmd)
4040
InstanceCmd.AddCommand(instanceTagCmd)
4141
InstanceCmd.AddCommand(instanceVncCmd)
42+
InstanceCmd.AddCommand(instanceRecoveryCmd)
43+
InstanceCmd.AddCommand(instanceRecoveryStatusCmd)
4244

4345
instanceUpdateCmd.Flags().StringVarP(&notes, "notes", "n", "", "notes stored against the instance")
4446
instanceUpdateCmd.Flags().StringVarP(&reverseDNS, "reverse-dns", "r", "", "the reverse DNS entry for the instance")

cmd/instance/instance_recovery.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package instance
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/civo/cli/common"
8+
"github.com/civo/cli/config"
9+
"github.com/civo/cli/utility"
10+
"github.com/spf13/cobra"
11+
)
12+
13+
var instanceRecoveryCmd = &cobra.Command{
14+
Use: "recovery",
15+
Example: "civo instance recovery enable/disable ID/HOSTNAME",
16+
Args: cobra.MinimumNArgs(2),
17+
Short: "Enable/disable recovery mode for an instance",
18+
Long: `Enable or disable recovery mode for a specified instance.
19+
Recovery mode allows you to boot your instance into a recovery environment for troubleshooting.
20+
21+
Example:
22+
* Enable recovery mode:
23+
civo instance recovery enable my-instance
24+
* Disable recovery mode:
25+
civo instance recovery disable my-instance`,
26+
Aliases: []string{"rescue"},
27+
Run: func(cmd *cobra.Command, args []string) {
28+
utility.EnsureCurrentRegion()
29+
30+
client, err := config.CivoAPIClient()
31+
if common.RegionSet != "" {
32+
client.Region = common.RegionSet
33+
}
34+
35+
if err != nil {
36+
utility.Error("Creating the connection to Civo's API failed with %s", err)
37+
os.Exit(1)
38+
}
39+
40+
if args[0] != "enable" && args[0] != "disable" {
41+
utility.Error("Please specify either enable or disable")
42+
os.Exit(1)
43+
}
44+
45+
instance, err := client.FindInstance(args[1])
46+
if err != nil {
47+
utility.Error("%s", err)
48+
os.Exit(1)
49+
}
50+
fmt.Println("Instance ID is: ", instance.ID)
51+
52+
if args[0] == "enable" {
53+
_, err := client.EnableRecoveryMode(instance.ID)
54+
if err != nil {
55+
utility.Error("%s", err)
56+
os.Exit(1)
57+
}
58+
} else {
59+
_, err := client.DisableRecoveryMode(instance.ID)
60+
if err != nil {
61+
utility.Error("%s", err)
62+
os.Exit(1)
63+
}
64+
}
65+
66+
if args[0] == "enable" {
67+
fmt.Printf("Recovery mode has been enabled for instance %s\n", utility.Green(instance.Hostname))
68+
} else {
69+
fmt.Printf("Recovery mode has been disabled for instance %s\n", utility.Green(instance.Hostname))
70+
}
71+
},
72+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package instance
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/civo/cli/common"
8+
"github.com/civo/cli/config"
9+
"github.com/civo/cli/utility"
10+
"github.com/spf13/cobra"
11+
)
12+
13+
var instanceRecoveryStatusCmd = &cobra.Command{
14+
Use: "recovery-status",
15+
Aliases: []string{"recovery"},
16+
Example: "civo instance recovery-status INSTANCE_ID/HOSTNAME",
17+
Short: "Get the recovery status of an instance",
18+
Long: `Show the current recovery mode status for a specified instance.
19+
If you wish to use a custom format, the available fields are:
20+
21+
* id
22+
* hostname
23+
* status
24+
25+
Example:
26+
* Check recovery status:
27+
civo instance recovery-status my-instance`,
28+
Args: cobra.MinimumNArgs(1),
29+
Run: func(cmd *cobra.Command, args []string) {
30+
utility.EnsureCurrentRegion()
31+
32+
client, err := config.CivoAPIClient()
33+
if common.RegionSet != "" {
34+
client.Region = common.RegionSet
35+
}
36+
37+
if err != nil {
38+
utility.Error("Creating the connection to Civo's API failed with %s", err)
39+
os.Exit(1)
40+
}
41+
42+
instance, err := client.FindInstance(args[0])
43+
if err != nil {
44+
utility.Error("Instance %s", err)
45+
os.Exit(1)
46+
}
47+
48+
status, err := client.GetRecoveryStatus(instance.ID)
49+
if err != nil {
50+
utility.Error("Failed to get recovery status: %s", err)
51+
os.Exit(1)
52+
}
53+
54+
ow := utility.NewOutputWriterWithMap(map[string]string{
55+
"id": instance.ID,
56+
"hostname": instance.Hostname,
57+
"status": string(status.Result),
58+
})
59+
60+
switch common.OutputFormat {
61+
case "json":
62+
ow.WriteSingleObjectJSON(common.PrettySet)
63+
case "custom":
64+
ow.WriteCustomOutput(common.OutputFields)
65+
default:
66+
fmt.Printf("Recovery Status for instance %s (%s):\n", utility.Green(instance.Hostname), instance.ID)
67+
ow.WriteKeyValues()
68+
}
69+
},
70+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ require (
99
github.com/adhocore/gronx v1.19.5
1010
github.com/alejandrojnm/go-pluralize v0.1.0
1111
github.com/briandowns/spinner v1.23.2
12-
github.com/civo/civogo v0.3.95
12+
github.com/civo/civogo v0.3.96
1313
github.com/google/go-github/v57 v57.0.0
1414
github.com/google/uuid v1.6.0
1515
github.com/gookit/color v1.5.4

go.sum

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,8 @@ github.com/briandowns/spinner v1.23.2 h1:Zc6ecUnI+YzLmJniCfDNaMbW0Wid1d5+qcTq4L2
2828
github.com/briandowns/spinner v1.23.2/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM=
2929
github.com/c4milo/unpackit v0.0.0-20170704181138-4ed373e9ef1c h1:aprLqMn7gSPT+vdDSl+/E6NLEuArwD/J7IWd8bJt5lQ=
3030
github.com/c4milo/unpackit v0.0.0-20170704181138-4ed373e9ef1c/go.mod h1:Ie6SubJv/NTO9Q0UBH0QCl3Ve50lu9hjbi5YJUw03TE=
31-
github.com/civo/civogo v0.3.94 h1:VhdqaJ2m4z8Jz8arzyzVjokRnO8JQ3lGjLKLshJ1eJI=
32-
github.com/civo/civogo v0.3.94/go.mod h1:LaEbkszc+9nXSh4YNG0sYXFGYqdQFmXXzQg0gESs2hc=
33-
github.com/civo/civogo v0.3.95 h1:QNe/uCYzbg1M//Z8ZvxiasLjrh9WvrpSb5spE7ln5lY=
34-
github.com/civo/civogo v0.3.95/go.mod h1:LaEbkszc+9nXSh4YNG0sYXFGYqdQFmXXzQg0gESs2hc=
31+
github.com/civo/civogo v0.3.96 h1:9R3yZS3B8B0oAqIlNDnMvsONk0mqZUkHREd0EH6HRIc=
32+
github.com/civo/civogo v0.3.96/go.mod h1:LaEbkszc+9nXSh4YNG0sYXFGYqdQFmXXzQg0gESs2hc=
3533
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
3634
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
3735
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
@@ -191,8 +189,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
191189
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
192190
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
193191
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
194-
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
195-
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
192+
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
193+
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
196194
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
197195
golang.org/x/image v0.0.0-20191206065243-da761ea9ff43 h1:gQ6GUSD102fPgli+Yb4cR/cGaHF7tNBt+GYoRCpGC7s=
198196
golang.org/x/image v0.0.0-20191206065243-da761ea9ff43/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@@ -206,8 +204,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
206204
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
207205
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
208206
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
209-
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
210-
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
207+
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
208+
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
211209
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
212210
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
213211
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=

0 commit comments

Comments
 (0)