@@ -18,27 +18,28 @@ limitations under the License.
18
18
package cmd
19
19
20
20
import (
21
- "encoding/json"
22
- "fmt"
23
- "io/ioutil"
24
- "log"
25
- "net/http"
26
- "os"
27
- "path/filepath"
28
- "strconv"
29
-
30
- "github.com/spf13/cobra"
21
+ "bytes"
22
+ "encoding/json"
23
+ "fmt"
24
+ "io/ioutil"
25
+ "log"
26
+ "net/http"
27
+ "os"
28
+ "path/filepath"
29
+ "strconv"
30
+
31
+ "github.com/spf13/cobra"
31
32
)
32
33
33
34
var (
34
- // Used for flags and config
35
- configDir string
36
- configPath string
37
- defaultConfigPath string
38
- user string
39
- host string
40
- port string
41
- password string
35
+ // Used for flags and config
36
+ configDir string
37
+ configPath string
38
+ defaultConfigPath string
39
+ user string
40
+ host string
41
+ port string
42
+ password string
42
43
)
43
44
44
45
const clientVersion = "1.0.0"
@@ -48,7 +49,7 @@ const apiVersion = "v0"
48
49
var rootCmd = & cobra.Command {
49
50
Use : "rdctl" ,
50
51
Short : "A CLI for Rancher Desktop" ,
51
- Long : `The eventual goal of this CLI is to enable any UI-based operation to be done from the command-line as well.` ,
52
+ Long : `The eventual goal of this CLI is to enable any UI-based operation to be done from the command-line as well.` ,
52
53
}
53
54
54
55
// Execute adds all child commands to the root command and sets flags appropriately.
@@ -61,101 +62,120 @@ func Execute() {
61
62
}
62
63
63
64
func init () {
64
- var err error
65
-
66
- cobra .OnInitialize (initConfig )
67
- configDir , err = os .UserConfigDir ()
68
- if err != nil {
69
- log .Fatal ("Can't get config-dir: " , err )
70
- }
71
- defaultConfigPath = filepath .Join (configDir , "rancher-desktop" , "rd-engine.json" )
72
- rootCmd .PersistentFlags ().StringVar (& configPath , "config-path" , "" , fmt .Sprintf ("config file (default %s)" , defaultConfigPath ))
73
- rootCmd .PersistentFlags ().StringVar (& user , "user" , "" , "overrides the user setting in the config file" )
74
- rootCmd .PersistentFlags ().StringVar (& host , "host" , "" , "default is localhost; most useful for WSL" )
75
- rootCmd .PersistentFlags ().StringVar (& port , "port" , "" , "overrides the port setting in the config file" )
76
- rootCmd .PersistentFlags ().StringVar (& password , "password" , "" , "overrides the password setting in the config file" )
65
+ var err error
66
+
67
+ cobra .OnInitialize (initConfig )
68
+ configDir , err = os .UserConfigDir ()
69
+ if err != nil {
70
+ log .Fatal ("Can't get config-dir: " , err )
71
+ }
72
+ defaultConfigPath = filepath .Join (configDir , "rancher-desktop" , "rd-engine.json" )
73
+ rootCmd .PersistentFlags ().StringVar (& configPath , "config-path" , "" , fmt .Sprintf ("config file (default %s)" , defaultConfigPath ))
74
+ rootCmd .PersistentFlags ().StringVar (& user , "user" , "" , "overrides the user setting in the config file" )
75
+ rootCmd .PersistentFlags ().StringVar (& host , "host" , "" , "default is localhost; most useful for WSL" )
76
+ rootCmd .PersistentFlags ().StringVar (& port , "port" , "" , "overrides the port setting in the config file" )
77
+ rootCmd .PersistentFlags ().StringVar (& password , "password" , "" , "overrides the password setting in the config file" )
77
78
}
78
79
79
- func doRequest (method string , command string ) error {
80
- req , err := getRequestObject (method , command )
81
- if err != nil {
82
- return err
83
- }
84
- return doRestOfRequest (req )
80
+ func doRequest (method string , command string ) ([]byte , error ) {
81
+ req , err := getRequestObject (method , command )
82
+ if err != nil {
83
+ return nil , err
84
+ }
85
+ return doRestOfRequest (req )
86
+ }
87
+
88
+ func doRequestWithPayload (method string , command string , payload * bytes.Buffer ) ([]byte , error ) {
89
+ req , err := http .NewRequest (method , fmt .Sprintf ("http://%s:%s/%s/%s" , host , port , apiVersion , command ), payload )
90
+ if err != nil {
91
+ return nil , err
92
+ }
93
+ req .SetBasicAuth (user , password )
94
+ req .Header .Add ("Content-Type" , "application/json" )
95
+ req .Close = true
96
+ return doRestOfRequest (req )
85
97
}
86
98
87
99
func getRequestObject (method string , command string ) (* http.Request , error ) {
88
- req , err := http .NewRequest (method , fmt .Sprintf ("http://%s:%s/%s/%s" , host , port , apiVersion , command ), nil )
89
- if err != nil {
90
- return nil , err
91
- }
92
- req .SetBasicAuth (user , password )
93
- req .Header .Add ("Content-Type" , "text/plain" )
94
- req .Close = true
95
- return req , nil
100
+ req , err := http .NewRequest (method , fmt .Sprintf ("http://%s:%s/%s/%s" , host , port , apiVersion , command ), nil )
101
+ if err != nil {
102
+ return nil , err
103
+ }
104
+ req .SetBasicAuth (user , password )
105
+ req .Header .Add ("Content-Type" , "text/plain" )
106
+ req .Close = true
107
+ return req , nil
96
108
}
97
109
98
- func doRestOfRequest (req * http.Request ) error {
99
- client := http.Client {}
100
- response , err := client .Do (req )
101
- if err != nil {
102
- return err
103
- }
104
- if response .StatusCode < 200 || response .StatusCode >= 300 {
105
- switch (response .StatusCode ) {
106
- case 401 :
107
- return fmt .Errorf ("user/password not accepted" )
108
- case 500 :
109
- return fmt .Errorf ("server-side problem: please consult the server logs for more information." )
110
- }
111
- return fmt .Errorf ("%s" , response .Status )
112
- }
113
-
114
- defer response .Body .Close ()
115
-
116
- body , err := ioutil .ReadAll (response .Body )
117
- if err != nil {
118
- return err
119
- }
120
-
121
- fmt .Println (string (body ))
122
- return nil
110
+ func doRestOfRequest (req * http.Request ) ([]byte , error ) {
111
+ client := http.Client {}
112
+ response , err := client .Do (req )
113
+ if err != nil {
114
+ return nil , err
115
+ }
116
+ statusMessage := ""
117
+ if response .StatusCode < 200 || response .StatusCode >= 300 {
118
+ switch response .StatusCode {
119
+ case 400 :
120
+ statusMessage = response .Status
121
+ // Prefer the error message in the body written by the command-server, not the one from the http server.
122
+ break
123
+ case 401 :
124
+ return nil , fmt .Errorf ("user/password not accepted" )
125
+ case 500 :
126
+ return nil , fmt .Errorf ("server-side problem: please consult the server logs for more information" )
127
+ default :
128
+ return nil , fmt .Errorf ("server error return-code %d: %s" , response .StatusCode , response .Status )
129
+ }
130
+ }
131
+
132
+ defer response .Body .Close ()
133
+
134
+ body , err := ioutil .ReadAll (response .Body )
135
+ if err != nil {
136
+ if statusMessage != "" {
137
+ return nil , fmt .Errorf ("server error return-code %d: %s" , response .StatusCode , statusMessage )
138
+ }
139
+ return nil , err
140
+ } else if statusMessage != "" {
141
+ return nil , fmt .Errorf ("%s" , string (body ))
142
+ }
143
+
144
+ return body , nil
123
145
}
124
146
125
147
// The CLIConfig struct is used to store the json data read from the config file.
126
148
type CLIConfig struct {
127
- User string
128
- Password string
129
- Port int
149
+ User string
150
+ Password string
151
+ Port int
130
152
}
131
153
132
154
func initConfig () {
133
- if configPath == "" {
134
- configPath = defaultConfigPath
135
- }
136
- content , err := ioutil .ReadFile (configPath )
137
- if err != nil {
138
- log .Fatalf ("Error trying to read file %s: %v" , configPath , err )
139
- }
140
-
141
- var settings CLIConfig
142
- err = json .Unmarshal (content , & settings )
143
- if err != nil {
144
- log .Fatalf ("Error trying to json-load file %s: %v" , configPath , err )
145
- }
146
-
147
- if user == "" {
148
- user = settings .User
149
- }
150
- if password == "" {
151
- password = settings .Password
152
- }
153
- if host == "" {
154
- host = "localhost"
155
- }
156
- if port == "" {
157
- port = strconv .Itoa (settings .Port )
158
- }
159
- }
155
+ if configPath == "" {
156
+ configPath = defaultConfigPath
157
+ }
158
+ content , err := ioutil .ReadFile (configPath )
159
+ if err != nil {
160
+ log .Fatalf ("Error trying to read file %s: %v" , configPath , err )
161
+ }
160
162
163
+ var settings CLIConfig
164
+ err = json .Unmarshal (content , & settings )
165
+ if err != nil {
166
+ log .Fatalf ("Error trying to json-load file %s: %v" , configPath , err )
167
+ }
161
168
169
+ if user == "" {
170
+ user = settings .User
171
+ }
172
+ if password == "" {
173
+ password = settings .Password
174
+ }
175
+ if host == "" {
176
+ host = "localhost"
177
+ }
178
+ if port == "" {
179
+ port = strconv .Itoa (settings .Port )
180
+ }
181
+ }
0 commit comments