Skip to content

Commit 9850865

Browse files
committed
native yaml configs & separate breeder naming
BREAKING CHANGE: breeder create now requires --name parameter Changes: - Add --name parameter to breeder create command - Parse YAML configs as generic JsonNode (no rigid type structure) - Remove JSON-as-string format, support native YAML objects - Update CI tests to use new flat YAML config format Usage: godon_cli breeder create --name my-breeder --file config.yaml Config file (config.yaml) now contains flat structure without name: meta: configVersion: "0.2" breeder: type: "linux_performance" settings: {...} run: {...} cooperation: {...} objectives: [...] effectuation: {...} The name is provided separately via CLI parameter and combined with config when sending to API: {"name": "my-breeder", "config": {...}}
1 parent 945c79d commit 9850865

5 files changed

Lines changed: 55 additions & 30 deletions

File tree

.github/workflows/ci.yml

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,19 @@ jobs:
228228
$BINARY_PATH --help | grep -q "insecure" && echo "✅ --insecure flag documented in help" || echo "❌ --insecure flag missing from help"
229229
230230
# Create test YAML files using echo
231-
echo 'name: "Test Breeder"' > test_breeder.yml
232-
echo 'config: >' >> test_breeder.yml
233-
echo ' {"setting1": "value1", "setting2": 42}' >> test_breeder.yml
231+
echo 'meta:' > test_breeder.yml
232+
echo ' configVersion: "0.2"' >> test_breeder.yml
233+
echo 'breeder:' >> test_breeder.yml
234+
echo ' type: "linux_performance"' >> test_breeder.yml
235+
echo 'settings:' >> test_breeder.yml
236+
echo ' sysctl:' >> test_breeder.yml
237+
echo ' vm.swappiness:' >> test_breeder.yml
238+
echo ' constraints:' >> test_breeder.yml
239+
echo ' lower: 0' >> test_breeder.yml
240+
echo ' upper: 100' >> test_breeder.yml
234241
235242
echo "Testing: breeder create"
236-
$BINARY_PATH --hostname=localhost --port=4010 breeder create --file=test_breeder.yml
243+
$BINARY_PATH --hostname=localhost --port=4010 breeder create --name="test-breeder" --file=test_breeder.yml
237244
238245
# Test breeder show with a mock UUID
239246
echo "Testing: breeder show"
@@ -243,8 +250,10 @@ jobs:
243250
echo 'uuid: "550e8400-e29b-41d4-a716-446655440000"' > test_breeder_update.yml
244251
echo 'name: "Updated Test Breeder"' >> test_breeder_update.yml
245252
echo 'description: "Updated integration test breeder"' >> test_breeder_update.yml
246-
echo 'config: >' >> test_breeder_update.yml
247-
echo ' {"setting1": "updated_value1", "setting2": 100, "new_setting": "new_value"}' >> test_breeder_update.yml
253+
echo 'config:' >> test_breeder_update.yml
254+
echo ' setting1: "updated_value1"' >> test_breeder_update.yml
255+
echo ' setting2: 100' >> test_breeder_update.yml
256+
echo ' new_setting: "new_value"' >> test_breeder_update.yml
248257
249258
echo "Testing: breeder update"
250259
$BINARY_PATH --hostname=localhost --port=4010 breeder update --file=test_breeder_update.yml

godon_cli.nimble

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ license = "AGPL-3.0"
77

88
# Dependencies
99

10-
requires "nim >= 2.0.0", "yaml"
10+
requires "nim >= 2.0.0"
11+
requires "yaml == 2.1.1"
1112

1213
# Task definitions
1314

src/godon/breeder.nim

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
## Implementation of breeder-related API endpoints
33

44
import std/[httpclient, json, strutils, uri]
5-
import yaml
5+
import yaml, yaml/tojson
66
import client, types
77

88
proc listBreeders*(client: GodonClient): ApiResponse[seq[BreederSummary]] =
@@ -18,10 +18,10 @@ proc createBreeder*(client: GodonClient, request: BreederCreateRequest): ApiResp
1818
## Create a new breeder
1919
try:
2020
let url = client.baseUrl() & "/breeders"
21-
# Convert config string to JsonNode
21+
# Config is already a JsonNode, no parsing needed
2222
var jsonData = %*{
2323
"name": request.name,
24-
"config": parseJson(request.config)
24+
"config": request.config
2525
}
2626
echo "Sending JSON: ", $jsonData
2727
client.httpClient.headers = newHttpHeaders({"Content-Type": "application/json"})
@@ -30,17 +30,24 @@ proc createBreeder*(client: GodonClient, request: BreederCreateRequest): ApiResp
3030
except CatchableError as e:
3131
result = ApiResponse[BreederSummary](success: false, data: default(BreederSummary), error: e.msg)
3232

33-
proc parseBreederFromYaml*(yamlContent: string): BreederCreateRequest =
34-
## Parse breeder configuration from YAML content using yaml library
33+
proc createBreederFromYamlWithName*(client: GodonClient, yamlContent: string, name: string): ApiResponse[BreederSummary] =
34+
## Create a breeder from YAML content with explicit name parameter
35+
## YAML contains only the config (no name field), name comes from parameter
3536
try:
36-
result = yaml.loadAs[BreederCreateRequest](yamlContent)
37-
except CatchableError as e:
38-
raise newException(ValueError, "Failed to parse YAML: " & e.msg)
37+
# Parse YAML and convert to JsonNode
38+
let jsonNodes = loadToJson(yamlContent)
3939

40-
proc createBreederFromYaml*(client: GodonClient, yamlContent: string): ApiResponse[BreederSummary] =
41-
## Create a breeder from YAML content
42-
try:
43-
let request = parseBreederFromYaml(yamlContent)
40+
# Take the first document (should be only one)
41+
if jsonNodes.len == 0:
42+
return ApiResponse[BreederSummary](success: false, data: default(BreederSummary), error: "No YAML documents found")
43+
44+
let configNode = jsonNodes[0]
45+
46+
# Create BreederCreateRequest with name from parameter and config from YAML
47+
let request = BreederCreateRequest(
48+
name: name,
49+
config: configNode
50+
)
4451
result = client.createBreeder(request)
4552
except CatchableError as e:
4653
result = ApiResponse[BreederSummary](success: false, data: default(BreederSummary), error: e.msg)
@@ -58,7 +65,7 @@ proc updateBreeder*(client: GodonClient, request: BreederUpdateRequest): ApiResp
5865
## Update an existing breeder
5966
try:
6067
let url = client.baseUrl() & "/breeders/" & encodeUrl(request.uuid)
61-
# Convert config string to JsonNode
68+
# Config is a string (JSON), parse it first
6269
var jsonData = %*{
6370
"name": request.name,
6471
"description": request.description,

src/godon/types.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type
1919

2020
BreederCreateRequest* = object
2121
name*: string
22-
config*: string
22+
config*: JsonNode
2323

2424
BreederUpdateRequest* = object
2525
uuid*: string

src/godon_cli.nim

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Usage:
99
1010
Commands:
1111
breeder list List all configured breeders
12-
breeder create --file <path> Create a breeder from file
12+
breeder create --name <name> --file <path> Create a breeder from file
1313
breeder show --id <id> Show breeder details
1414
breeder update --file <path> Update a breeder from file
1515
breeder purge --id <id> Delete a breeder
@@ -29,7 +29,7 @@ Global Options:
2929
Examples:
3030
godon_cli breeder list
3131
godon_cli --hostname api.example.com --port 9090 breeder list
32-
godon_cli breeder create --file breeder.yaml
32+
godon_cli breeder create --name my-breeder --file breeder-config.yaml
3333
godon_cli breeder show --id 550e8400-e29b-41d4-a716-446655440000
3434
godon_cli credential list
3535
godon_cli credential create --file credential.yaml
@@ -74,8 +74,11 @@ proc parseArgs(): (string, string, int, string, bool, seq[string]) =
7474
of "file":
7575
# Reconstruct as argument for subcommand parsing
7676
args.add("--file=" & val)
77+
of "name":
78+
# Reconstruct as argument for subcommand parsing
79+
args.add("--name=" & val)
7780
of "id":
78-
# Reconstruct as argument for subcommand parsing
81+
# Reconstruct as argument for subcommand parsing
7982
args.add("--id=" & val)
8083
of "insecure":
8184
insecure = true
@@ -114,20 +117,25 @@ proc handleBreederCommand(client: GodonClient, command: string, args: seq[string
114117

115118
of "create":
116119
var file = ""
120+
var name = ""
117121
for arg in args:
118122
if arg.startsWith("--file="):
119123
file = arg.split("=")[1]
120-
break
121-
124+
elif arg.startsWith("--name="):
125+
name = arg.split("=")[1]
126+
122127
if file.len == 0:
123128
writeError("breeder create requires --file <path>")
124-
129+
130+
if name.len == 0:
131+
writeError("breeder create requires --name <name>")
132+
125133
if not fileExists(file):
126134
writeError("File not found: " & file)
127-
128-
echo "Creating breeder from file: ", file
135+
136+
echo "Creating breeder '", name, "' from file: ", file
129137
let content = readFile(file)
130-
let response = client.createBreederFromYaml(content)
138+
let response = client.createBreederFromYamlWithName(content, name)
131139
if response.success:
132140
echo "Breeder created successfully:"
133141
echo " ID: ", response.data.id

0 commit comments

Comments
 (0)