11import std/ [parseopt, strutils, os, json]
2+ import yaml
23import godon/ [client, breeder, credential, types]
34
5+ type
6+ OutputFormat * = enum
7+ Text = " text"
8+ Json = " json"
9+ Yaml = " yaml"
10+
411proc writeHelp () =
512 echo """ Godon CLI - Command line interface for Godon API
613
@@ -23,8 +30,9 @@ Global Options:
2330 --hostname, -h <host> Godon hostname (default: localhost)
2431 --port, -p <port> Godon port (default: 8080)
2532 --api-version, -v <ver> API version (default: v0)
33+ --output, -o <format> Output format: text, json, or yaml (default: text)
2634 --insecure Skip SSL certificate verification (HTTPS only)
27- --help, -h Show this help message
35+ --help Show this help message
2836
2937Examples:
3038 godon_cli breeder list
@@ -40,12 +48,13 @@ proc writeError(message: string) =
4048 stderr.writeLine (" Error: " & message)
4149 quit (1 )
4250
43- proc parseArgs (): (string , string , int , string , bool , seq [string ]) =
51+ proc parseArgs (): (string , string , int , string , bool , OutputFormat , seq [string ]) =
4452 var command = " "
4553 var hostname = " localhost"
4654 var port = 8080
4755 var apiVersion = " v0"
4856 var insecure = false
57+ var outputFormat = OutputFormat .Text
4958 var args: seq [string ] = @ []
5059
5160 var p = initOptParser (commandLineParams ())
@@ -82,7 +91,19 @@ proc parseArgs(): (string, string, int, string, bool, seq[string]) =
8291 args.add (" --id=" & val)
8392 of " insecure" :
8493 insecure = true
85- of " help" , " h" :
94+ of " output" , " o" :
95+ if val.len == 0 :
96+ writeError (" Output option requires a value (text, json, or yaml)" )
97+ case val.normalize ()
98+ of " text" :
99+ outputFormat = OutputFormat .Text
100+ of " json" :
101+ outputFormat = OutputFormat .Json
102+ of " yaml" :
103+ outputFormat = OutputFormat .Yaml
104+ else :
105+ writeError (" Unknown output format: " & val & " . Use text, json, or yaml" )
106+ of " help" :
86107 writeHelp ()
87108 quit (0 )
88109 else :
@@ -95,23 +116,37 @@ proc parseArgs(): (string, string, int, string, bool, seq[string]) =
95116 writeHelp ()
96117 quit (0 )
97118
98- (command, hostname, port, apiVersion, insecure, args)
119+ (command, hostname, port, apiVersion, insecure, outputFormat, args)
120+
121+ proc formatOutput * [T](data: T, outputFormat: OutputFormat ) =
122+ # # Format data according to output format preference
123+ case outputFormat
124+ of OutputFormat .Text :
125+ # Text mode is handled by caller with custom formatting
126+ discard
127+ of OutputFormat .Json :
128+ echo pretty (%* data)
129+ of OutputFormat .Yaml :
130+ # Convert to YAML
131+ echo yaml.dump (data)
99132
100- proc handleBreederCommand (client: GodonClient , command: string , args: seq [string ]) =
133+ proc handleBreederCommand (client: GodonClient , command: string , args: seq [string ], outputFormat: OutputFormat ) =
101134 let subCommand = if args.len > 0 : args[0 ] else : " "
102135
103136 case subCommand:
104137 of " list" :
105- echo " Listing breeders..."
106138 let response = client.listBreeders ()
107139 if response.success:
108- echo " Breeders:"
109- for breeder in response.data:
110- echo " ID: " , breeder.id
111- echo " Name: " , breeder.name
112- echo " Status: " , breeder.status
113- echo " Created: " , breeder.createdAt
114- echo " ---"
140+ if outputFormat == OutputFormat .Text :
141+ echo " Breeders:"
142+ for breeder in response.data:
143+ echo " ID: " , breeder.id
144+ echo " Name: " , breeder.name
145+ echo " Status: " , breeder.status
146+ echo " Created: " , breeder.createdAt
147+ echo " ---"
148+ else :
149+ formatOutput (response.data, outputFormat)
115150 else :
116151 writeError (response.error)
117152
@@ -133,14 +168,16 @@ proc handleBreederCommand(client: GodonClient, command: string, args: seq[string
133168 if not fileExists (file):
134169 writeError (" File not found: " & file)
135170
136- echo " Creating breeder '" , name, " ' from file: " , file
137171 let content = readFile (file)
138172 let response = client.createBreederFromYamlWithName (content, name)
139173 if response.success:
140- echo " Breeder created successfully:"
141- echo " ID: " , response.data.id
142- echo " Name: " , response.data.name
143- echo " Status: " , response.data.status
174+ if outputFormat == OutputFormat .Text :
175+ echo " Breeder created successfully:"
176+ echo " ID: " , response.data.id
177+ echo " Name: " , response.data.name
178+ echo " Status: " , response.data.status
179+ else :
180+ formatOutput (response.data, outputFormat)
144181 else :
145182 writeError (response.error)
146183
@@ -153,16 +190,18 @@ proc handleBreederCommand(client: GodonClient, command: string, args: seq[string
153190
154191 if id.len == 0 :
155192 writeError (" breeder show requires --id <id>" )
156-
157- echo " Getting breeder details for ID: " , id
193+
158194 let response = client.getBreeder (id)
159195 if response.success:
160- echo " Breeder Details:"
161- echo " ID: " , response.data.id
162- echo " Name: " , response.data.name
163- echo " Status: " , response.data.status
164- echo " Config: " , pretty (response.data.config)
165- echo " Created: " , response.data.createdAt
196+ if outputFormat == OutputFormat .Text :
197+ echo " Breeder Details:"
198+ echo " ID: " , response.data.id
199+ echo " Name: " , response.data.name
200+ echo " Status: " , response.data.status
201+ echo " Config: " , pretty (response.data.config)
202+ echo " Created: " , response.data.createdAt
203+ else :
204+ formatOutput (response.data, outputFormat)
166205 else :
167206 writeError (response.error)
168207
@@ -178,15 +217,17 @@ proc handleBreederCommand(client: GodonClient, command: string, args: seq[string
178217
179218 if not fileExists (file):
180219 writeError (" File not found: " & file)
181-
182- echo " Updating breeder from file: " , file
220+
183221 let content = readFile (file)
184222 let response = client.updateBreederFromYaml (content)
185223 if response.success:
186- echo " Breeder updated successfully:"
187- echo " ID: " , response.data.id
188- echo " Name: " , response.data.name
189- echo " Status: " , response.data.status
224+ if outputFormat == OutputFormat .Text :
225+ echo " Breeder updated successfully:"
226+ echo " ID: " , response.data.id
227+ echo " Name: " , response.data.name
228+ echo " Status: " , response.data.status
229+ else :
230+ formatOutput (response.data, outputFormat)
190231 else :
191232 writeError (response.error)
192233
@@ -199,36 +240,38 @@ proc handleBreederCommand(client: GodonClient, command: string, args: seq[string
199240
200241 if id.len == 0 :
201242 writeError (" breeder purge requires --id <id>" )
202-
203- echo " Deleting breeder with ID: " , id
243+
204244 let response = client.deleteBreeder (id)
205245 if response.success:
206- echo " Breeder deleted successfully"
207- if response.data != nil :
208- echo " Response: " , pretty (response.data)
246+ if outputFormat == OutputFormat .Text :
247+ echo " Breeder deleted successfully: " , id
248+ else :
249+ formatOutput (response.data, outputFormat)
209250 else :
210251 writeError (response.error)
211252
212253 else :
213254 writeError (" Unknown breeder command: " & subCommand)
214255
215- proc handleCredentialCommand (client: GodonClient , command: string , args: seq [string ]) =
256+ proc handleCredentialCommand (client: GodonClient , command: string , args: seq [string ], outputFormat: OutputFormat ) =
216257 let subCommand = if args.len > 0 : args[0 ] else : " "
217258
218259 case subCommand:
219260 of " list" :
220- echo " Listing credentials..."
221261 let response = client.listCredentials ()
222262 if response.success:
223- echo " Credentials:"
224- for credential in response.data:
225- echo " ID: " , credential.id
226- echo " Name: " , credential.name
227- echo " Type: " , credential.credentialType
228- echo " Description: " , credential.description
229- echo " Windmill Variable: " , credential.windmillVariable
230- echo " Created: " , credential.createdAt
231- echo " ---"
263+ if outputFormat == OutputFormat .Text :
264+ echo " Credentials:"
265+ for credential in response.data:
266+ echo " ID: " , credential.id
267+ echo " Name: " , credential.name
268+ echo " Type: " , credential.credentialType
269+ echo " Description: " , credential.description
270+ echo " windmillVariable: " , credential.windmillVariable
271+ echo " Created: " , credential.createdAt
272+ echo " ---"
273+ else :
274+ formatOutput (response.data, outputFormat)
232275 else :
233276 writeError (response.error)
234277
@@ -244,16 +287,18 @@ proc handleCredentialCommand(client: GodonClient, command: string, args: seq[str
244287
245288 if not fileExists (file):
246289 writeError (" File not found: " & file)
247-
248- echo " Creating credential from file: " , file
290+
249291 let content = readFile (file)
250292 let response = client.createCredentialFromYaml (content)
251293 if response.success:
252- echo " Credential created successfully:"
253- echo " ID: " , response.data.id
254- echo " Name: " , response.data.name
255- echo " Type: " , response.data.credentialType
256- echo " Windmill Variable: " , response.data.windmillVariable
294+ if outputFormat == OutputFormat .Text :
295+ echo " Credential created successfully:"
296+ echo " ID: " , response.data.id
297+ echo " Name: " , response.data.name
298+ echo " Type: " , response.data.credentialType
299+ echo " windmillVariable: " , response.data.windmillVariable
300+ else :
301+ formatOutput (response.data, outputFormat)
257302 else :
258303 writeError (response.error)
259304
@@ -266,20 +311,22 @@ proc handleCredentialCommand(client: GodonClient, command: string, args: seq[str
266311
267312 if id.len == 0 :
268313 writeError (" credential show requires --id <id>" )
269-
270- echo " Getting credential details for ID: " , id
314+
271315 let response = client.getCredential (id)
272316 if response.success:
273- echo " Credential Details:"
274- echo " ID: " , response.data.id
275- echo " Name: " , response.data.name
276- echo " Type: " , response.data.credentialType
277- echo " Description: " , response.data.description
278- echo " Windmill Variable: " , response.data.windmillVariable
279- echo " Created: " , response.data.createdAt
280- echo " Last Used: " , response.data.lastUsedAt
281- echo " Content:"
282- echo " " , response.data.content # Show actual credential content
317+ if outputFormat == OutputFormat .Text :
318+ echo " Credential Details:"
319+ echo " ID: " , response.data.id
320+ echo " Name: " , response.data.name
321+ echo " Type: " , response.data.credentialType
322+ echo " Description: " , response.data.description
323+ echo " windmillVariable: " , response.data.windmillVariable
324+ echo " Created: " , response.data.createdAt
325+ echo " Last Used: " , response.data.lastUsedAt
326+ echo " Content:"
327+ echo " " , response.data.content
328+ else :
329+ formatOutput (response.data, outputFormat)
283330 else :
284331 writeError (response.error)
285332
@@ -292,33 +339,33 @@ proc handleCredentialCommand(client: GodonClient, command: string, args: seq[str
292339
293340 if id.len == 0 :
294341 writeError (" credential delete requires --id <id>" )
295-
296- echo " Deleting credential with ID: " , id
342+
297343 let response = client.deleteCredential (id)
298344 if response.success:
299- echo " Credential deleted successfully"
300- if response.data != nil :
301- echo " Response: " , pretty (response.data)
345+ if outputFormat == OutputFormat .Text :
346+ echo " Credential deleted successfully: " , id
347+ else :
348+ formatOutput (response.data, outputFormat)
302349 else :
303350 writeError (response.error)
304351
305352 else :
306353 writeError (" Unknown credential command: " & subCommand)
307354
308- let (command, hostname, port, apiVersion, insecure, args) = parseArgs ()
355+ let (command, hostname, port, apiVersion, insecure, outputFormat, args) = parseArgs ()
309356
310357let godonClient = newGodonClient (hostname, port, apiVersion, insecure)
311358
312359case command:
313360of " breeder" :
314361 if args.len == 0 :
315362 writeError (" breeder command requires a subcommand (list, create, show, update, purge)" )
316- handleBreederCommand (godonClient, command, args)
363+ handleBreederCommand (godonClient, command, args, outputFormat )
317364
318365of " credential" :
319366 if args.len == 0 :
320367 writeError (" credential command requires a subcommand (list, create, show, delete)" )
321- handleCredentialCommand (godonClient, command, args)
368+ handleCredentialCommand (godonClient, command, args, outputFormat )
322369
323370else :
324371 writeError (" Unknown command: " & command)
0 commit comments