Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -254,17 +254,24 @@ jobs:
echo "Testing: breeder show"
$BINARY_PATH --hostname=localhost --port=4010 breeder show --id=550e8400-e29b-41d4-a716-446655440000

# Create update test file
echo 'uuid: "550e8400-e29b-41d4-a716-446655440000"' > test_breeder_update.yml
echo 'name: "Updated Test Breeder"' >> test_breeder_update.yml
echo 'description: "Updated integration test breeder"' >> test_breeder_update.yml
echo 'config:' >> test_breeder_update.yml
echo ' setting1: "updated_value1"' >> test_breeder_update.yml
echo ' setting2: 100' >> test_breeder_update.yml
echo ' new_setting: "new_value"' >> test_breeder_update.yml
# Create update test file (config only, id passed via --id flag)
echo 'breeder:' > test_breeder_update.yml
echo ' type: "test_breeder"' >> test_breeder_update.yml
echo 'objectives:' >> test_breeder_update.yml
echo ' - name: "latency"' >> test_breeder_update.yml
echo 'settings:' >> test_breeder_update.yml
echo ' sysctl:' >> test_breeder_update.yml
echo ' net.core.somaxconn:' >> test_breeder_update.yml
echo ' constraints:' >> test_breeder_update.yml
echo ' - step: 100' >> test_breeder_update.yml
echo ' lower: 4096' >> test_breeder_update.yml
echo ' upper: 131072' >> test_breeder_update.yml

echo "Testing: breeder update"
$BINARY_PATH --hostname=localhost --port=4010 breeder update --file=test_breeder_update.yml
$BINARY_PATH --hostname=localhost --port=4010 breeder update --id=550e8400-e29b-41d4-a716-446655440000 --file=test_breeder_update.yml

echo "Testing: breeder update with --force"
$BINARY_PATH --hostname=localhost --port=4010 breeder update --id=550e8400-e29b-41d4-a716-446655440000 --file=test_breeder_update.yml --force

# Test breeder purge (safe mode)
echo "Testing: breeder purge (safe mode)"
Expand Down
48 changes: 8 additions & 40 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,23 +143,12 @@ impl GodonClient {
}
}

pub async fn update_breeder(&self, request: BreederUpdateRequest) -> ApiResponse<serde_json::Value> {
let url = format!("{}/breeders/{}", self.base_url(), urlencoding::encode(&request.uuid));

let config: serde_json::Value = match serde_json::from_str(&request.config) {
Ok(c) => c,
Err(e) => return ApiResponse::error(format!("Config JSON parse error: {}", e)),
};

let body = serde_json::json!({
"name": request.name,
"description": request.description,
"config": config
});
pub async fn update_breeder(&self, uuid: &str, request: BreederUpdateRequest) -> ApiResponse<serde_json::Value> {
let url = format!("{}/breeders/{}", self.base_url(), urlencoding::encode(uuid));

match self.client
.put(&url)
.json(&body)
.json(&request)
.send()
.await
{
Expand All @@ -168,39 +157,18 @@ impl GodonClient {
}
}

pub async fn update_breeder_from_yaml(&self, yaml_content: &str) -> ApiResponse<serde_json::Value> {
let yaml_data: serde_yaml::Value = match serde_yaml::from_str(yaml_content) {
Ok(d) => d,
pub async fn update_breeder_from_yaml(&self, uuid: &str, yaml_content: &str, force: bool) -> ApiResponse<serde_json::Value> {
let config: serde_json::Value = match serde_yaml::from_str(yaml_content) {
Ok(c) => c,
Err(e) => return ApiResponse::error(format!("YAML parse error: {}", e)),
};

let uuid = yaml_data.get("uuid")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string();

let name = yaml_data.get("name")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string();

let description = yaml_data.get("description")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string();

let config = yaml_data.get("config")
.map(|c| serde_json::to_string(c).unwrap_or_else(|_| "{}".to_string()))
.unwrap_or_else(|| "{}".to_string());

let request = BreederUpdateRequest {
uuid,
name,
description,
config,
force: if force { Some(true) } else { None },
};

self.update_breeder(request).await
self.update_breeder(uuid, request).await
}

pub async fn delete_breeder(&self, uuid: &str, force: bool) -> ApiResponse<serde_json::Value> {
Expand Down
7 changes: 3 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ pub struct BreederCreateRequest {

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BreederUpdateRequest {
pub uuid: String,
pub name: String,
pub description: String,
pub config: String,
pub config: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub force: Option<bool>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down
27 changes: 16 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,12 @@ enum BreederCommands {
},

Update {
#[arg(long)]
id: String,
#[arg(long)]
file: PathBuf,
#[arg(long, default_value_t = false)]
force: bool,
},

Stop {
Expand Down Expand Up @@ -389,24 +393,25 @@ async fn handle_breeder_command(client: &GodonClient, cmd: BreederCommands, outp
}
}

BreederCommands::Update { file } => {
BreederCommands::Update { id, file, force } => {
let content = match std::fs::read_to_string(&file) {
Ok(c) => c,
Err(e) => write_error(&format!("Failed to read file: {}", e)),
};

let response = client.update_breeder_from_yaml(&content).await;
let response = client.update_breeder_from_yaml(&id, &content, force).await;
if response.success {
if let Some(data) = response.data {
match data.get("id").and_then(|v| v.as_str()) {
Some(id) => {
if matches!(output, OutputFormat::Text) {
println!("Breeder updated successfully: {}", id);
} else {
format_output(&data, output);
}
}
None => write_error("Unexpected response format: missing 'id' field"),
if matches!(output, OutputFormat::Text) {
let breeder_id = data.get("breeder_id").and_then(|v| v.as_str()).unwrap_or(&id);
let trials_cleared = data.get("trials_cleared").and_then(|v| v.as_bool()).unwrap_or(false);
let history = data.get("config_history_entries").and_then(|v| v.as_u64()).unwrap_or(0);
println!("Breeder updated successfully:");
println!(" ID: {}", breeder_id);
println!(" Trials cleared: {}", trials_cleared);
println!(" Config history entries: {}", history);
} else {
format_output(&data, output);
}
}
} else {
Expand Down
Loading