11import std/ [parseopt, strutils, os, json]
2+ import yaml, yaml/ presenter, yaml/ dumping
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,39 @@ 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 by dumping JSON as text and transforming it
131+ let jsonString = pretty (%* data)
132+ var dumper = blockOnlyDumper ()
133+ echo dumper.transform (jsonString)
99134
100- proc handleBreederCommand (client: GodonClient , command: string , args: seq [string ]) =
135+ proc handleBreederCommand (client: GodonClient , command: string , args: seq [string ], outputFormat: OutputFormat ) =
101136 let subCommand = if args.len > 0 : args[0 ] else : " "
102137
103138 case subCommand:
104139 of " list" :
105- echo " Listing breeders..."
106140 let response = client.listBreeders ()
107141 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 " ---"
142+ if outputFormat == OutputFormat .Text :
143+ echo " Breeders:"
144+ for breeder in response.data:
145+ echo " ID: " , breeder.id
146+ echo " Name: " , breeder.name
147+ echo " Status: " , breeder.status
148+ echo " Created: " , breeder.createdAt
149+ echo " ---"
150+ else :
151+ formatOutput (response.data, outputFormat)
115152 else :
116153 writeError (response.error)
117154
@@ -133,14 +170,16 @@ proc handleBreederCommand(client: GodonClient, command: string, args: seq[string
133170 if not fileExists (file):
134171 writeError (" File not found: " & file)
135172
136- echo " Creating breeder '" , name, " ' from file: " , file
137173 let content = readFile (file)
138174 let response = client.createBreederFromYamlWithName (content, name)
139175 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
176+ if outputFormat == OutputFormat .Text :
177+ echo " Breeder created successfully:"
178+ echo " ID: " , response.data.id
179+ echo " Name: " , response.data.name
180+ echo " Status: " , response.data.status
181+ else :
182+ formatOutput (response.data, outputFormat)
144183 else :
145184 writeError (response.error)
146185
@@ -153,16 +192,18 @@ proc handleBreederCommand(client: GodonClient, command: string, args: seq[string
153192
154193 if id.len == 0 :
155194 writeError (" breeder show requires --id <id>" )
156-
157- echo " Getting breeder details for ID: " , id
195+
158196 let response = client.getBreeder (id)
159197 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
198+ if outputFormat == OutputFormat .Text :
199+ echo " Breeder Details:"
200+ echo " ID: " , response.data.id
201+ echo " Name: " , response.data.name
202+ echo " Status: " , response.data.status
203+ echo " Config: " , pretty (response.data.config)
204+ echo " Created: " , response.data.createdAt
205+ else :
206+ formatOutput (response.data, outputFormat)
166207 else :
167208 writeError (response.error)
168209
@@ -178,15 +219,17 @@ proc handleBreederCommand(client: GodonClient, command: string, args: seq[string
178219
179220 if not fileExists (file):
180221 writeError (" File not found: " & file)
181-
182- echo " Updating breeder from file: " , file
222+
183223 let content = readFile (file)
184224 let response = client.updateBreederFromYaml (content)
185225 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
226+ if outputFormat == OutputFormat .Text :
227+ echo " Breeder updated successfully:"
228+ echo " ID: " , response.data.id
229+ echo " Name: " , response.data.name
230+ echo " Status: " , response.data.status
231+ else :
232+ formatOutput (response.data, outputFormat)
190233 else :
191234 writeError (response.error)
192235
@@ -199,36 +242,38 @@ proc handleBreederCommand(client: GodonClient, command: string, args: seq[string
199242
200243 if id.len == 0 :
201244 writeError (" breeder purge requires --id <id>" )
202-
203- echo " Deleting breeder with ID: " , id
245+
204246 let response = client.deleteBreeder (id)
205247 if response.success:
206- echo " Breeder deleted successfully"
207- if response.data != nil :
208- echo " Response: " , pretty (response.data)
248+ if outputFormat == OutputFormat .Text :
249+ echo " Breeder deleted successfully: " , id
250+ else :
251+ formatOutput (response.data, outputFormat)
209252 else :
210253 writeError (response.error)
211254
212255 else :
213256 writeError (" Unknown breeder command: " & subCommand)
214257
215- proc handleCredentialCommand (client: GodonClient , command: string , args: seq [string ]) =
258+ proc handleCredentialCommand (client: GodonClient , command: string , args: seq [string ], outputFormat: OutputFormat ) =
216259 let subCommand = if args.len > 0 : args[0 ] else : " "
217260
218261 case subCommand:
219262 of " list" :
220- echo " Listing credentials..."
221263 let response = client.listCredentials ()
222264 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 " ---"
265+ if outputFormat == OutputFormat .Text :
266+ echo " Credentials:"
267+ for credential in response.data:
268+ echo " ID: " , credential.id
269+ echo " Name: " , credential.name
270+ echo " Type: " , credential.credentialType
271+ echo " Description: " , credential.description
272+ echo " windmillVariable: " , credential.windmillVariable
273+ echo " Created: " , credential.createdAt
274+ echo " ---"
275+ else :
276+ formatOutput (response.data, outputFormat)
232277 else :
233278 writeError (response.error)
234279
@@ -244,16 +289,18 @@ proc handleCredentialCommand(client: GodonClient, command: string, args: seq[str
244289
245290 if not fileExists (file):
246291 writeError (" File not found: " & file)
247-
248- echo " Creating credential from file: " , file
292+
249293 let content = readFile (file)
250294 let response = client.createCredentialFromYaml (content)
251295 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
296+ if outputFormat == OutputFormat .Text :
297+ echo " Credential created successfully:"
298+ echo " ID: " , response.data.id
299+ echo " Name: " , response.data.name
300+ echo " Type: " , response.data.credentialType
301+ echo " windmillVariable: " , response.data.windmillVariable
302+ else :
303+ formatOutput (response.data, outputFormat)
257304 else :
258305 writeError (response.error)
259306
@@ -266,20 +313,22 @@ proc handleCredentialCommand(client: GodonClient, command: string, args: seq[str
266313
267314 if id.len == 0 :
268315 writeError (" credential show requires --id <id>" )
269-
270- echo " Getting credential details for ID: " , id
316+
271317 let response = client.getCredential (id)
272318 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
319+ if outputFormat == OutputFormat .Text :
320+ echo " Credential Details:"
321+ echo " ID: " , response.data.id
322+ echo " Name: " , response.data.name
323+ echo " Type: " , response.data.credentialType
324+ echo " Description: " , response.data.description
325+ echo " windmillVariable: " , response.data.windmillVariable
326+ echo " Created: " , response.data.createdAt
327+ echo " Last Used: " , response.data.lastUsedAt
328+ echo " Content:"
329+ echo " " , response.data.content
330+ else :
331+ formatOutput (response.data, outputFormat)
283332 else :
284333 writeError (response.error)
285334
@@ -292,33 +341,33 @@ proc handleCredentialCommand(client: GodonClient, command: string, args: seq[str
292341
293342 if id.len == 0 :
294343 writeError (" credential delete requires --id <id>" )
295-
296- echo " Deleting credential with ID: " , id
344+
297345 let response = client.deleteCredential (id)
298346 if response.success:
299- echo " Credential deleted successfully"
300- if response.data != nil :
301- echo " Response: " , pretty (response.data)
347+ if outputFormat == OutputFormat .Text :
348+ echo " Credential deleted successfully: " , id
349+ else :
350+ formatOutput (response.data, outputFormat)
302351 else :
303352 writeError (response.error)
304353
305354 else :
306355 writeError (" Unknown credential command: " & subCommand)
307356
308- let (command, hostname, port, apiVersion, insecure, args) = parseArgs ()
357+ let (command, hostname, port, apiVersion, insecure, outputFormat, args) = parseArgs ()
309358
310359let godonClient = newGodonClient (hostname, port, apiVersion, insecure)
311360
312361case command:
313362of " breeder" :
314363 if args.len == 0 :
315364 writeError (" breeder command requires a subcommand (list, create, show, update, purge)" )
316- handleBreederCommand (godonClient, command, args)
365+ handleBreederCommand (godonClient, command, args, outputFormat )
317366
318367of " credential" :
319368 if args.len == 0 :
320369 writeError (" credential command requires a subcommand (list, create, show, delete)" )
321- handleCredentialCommand (godonClient, command, args)
370+ handleCredentialCommand (godonClient, command, args, outputFormat )
322371
323372else :
324373 writeError (" Unknown command: " & command)
0 commit comments