From a03ed0572c2fd01d46e5cc5d030929cf20197ac5 Mon Sep 17 00:00:00 2001 From: Eric Ghildyal Date: Thu, 21 Nov 2024 16:49:13 -0500 Subject: [PATCH 1/3] Add canary promoting --- src/adapters/ingresses/apig.rs | 29 +++++++++++++++++++++++++++++ src/adapters/ingresses/mod.rs | 7 +++++++ 2 files changed, 36 insertions(+) diff --git a/src/adapters/ingresses/apig.rs b/src/adapters/ingresses/apig.rs index ea5c4f2..bfcc947 100644 --- a/src/adapters/ingresses/apig.rs +++ b/src/adapters/ingresses/apig.rs @@ -178,6 +178,29 @@ impl AwsApiGateway { .rest_api_id(api.id.unwrap_or_default()) .stage_name(stage_name) .patch_operations(patch_op) + pub async fn promote_apig_canary(&self, api_id: &str, stage_name: &str) -> Result<()> { + // Overwrite the main deployment's ID with the canary's + let replace_deployment_op = PatchOperation::builder() + .op(Op::Copy) + .from("/canarySettings/deploymentId") + .path("/deploymentId") + .build(); + + // Reset canary traffic to 0% so we're ready for another release + let reset_traffic_op = PatchOperation::builder() + .op(Op::Replace) + .path("/canarySettings/percentTraffic") + // Note: this must be a string to pass into Value, but it's actually an f64 in AWS + .value("0.0") + .build(); + + // Send request to update stage + self.apig_client + .update_stage() + .rest_api_id(api_id) + .stage_name(stage_name) + .patch_operations(replace_deployment_op) + .patch_operations(reset_traffic_op) .send() .await .into_diagnostic()?; @@ -228,4 +251,10 @@ impl Ingress for AwsApiGateway { Ok(()) } + + async fn promote_canary(&mut self) -> Result<()> { + self.promote_apig_canary("Releases", "prod").await?; + + Ok(()) + } } diff --git a/src/adapters/ingresses/mod.rs b/src/adapters/ingresses/mod.rs index 83bbf08..1b2a7b1 100644 --- a/src/adapters/ingresses/mod.rs +++ b/src/adapters/ingresses/mod.rs @@ -16,6 +16,9 @@ pub trait Ingress { async fn rollback_canary(&mut self) -> Result<()>; // async fn promote_canary(&mut self) -> Result<()>; async fn set_canary_traffic(&mut self, percent: WholePercent) -> Result<()>; + // async fn yank_canary(&mut self) -> Result<()>; + async fn promote_canary(&mut self) -> Result<()>; + // async fn set_canary_traffic(&mut self, percent: u8); } pub struct MockIngress; @@ -33,6 +36,10 @@ impl Ingress for MockIngress { async fn rollback_canary(&mut self) -> Result<()> { todo!() } + + async fn promote_canary(&mut self) -> Result<()> { + todo!() + } } impl From for BoxIngress { From c213265b39633959735d37f42e0e2fc6f05d589e Mon Sep 17 00:00:00 2001 From: Eric Ghildyal Date: Mon, 25 Nov 2024 15:31:54 -0500 Subject: [PATCH 2/3] Add helper method for apig name -> apig id --- src/adapters/ingresses/apig.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/adapters/ingresses/apig.rs b/src/adapters/ingresses/apig.rs index bfcc947..6faf377 100644 --- a/src/adapters/ingresses/apig.rs +++ b/src/adapters/ingresses/apig.rs @@ -179,6 +179,9 @@ impl AwsApiGateway { .stage_name(stage_name) .patch_operations(patch_op) pub async fn promote_apig_canary(&self, api_id: &str, stage_name: &str) -> Result<()> { + pub async fn promote_apig_canary(&self, api_name: &str, stage_name: &str) -> Result<()> { + let api = self.get_api_id_by_name(api_name).await?; + // Overwrite the main deployment's ID with the canary's let replace_deployment_op = PatchOperation::builder() .op(Op::Copy) @@ -197,7 +200,7 @@ impl AwsApiGateway { // Send request to update stage self.apig_client .update_stage() - .rest_api_id(api_id) + .rest_api_id(api.id.unwrap_or_default()) .stage_name(stage_name) .patch_operations(replace_deployment_op) .patch_operations(reset_traffic_op) From 9bbe840225455ac4839a7cc9e40c4b0d2c7f5a96 Mon Sep 17 00:00:00 2001 From: Eric Ghildyal Date: Tue, 26 Nov 2024 14:43:37 -0500 Subject: [PATCH 3/3] Merge all changes --- src/adapters/ingresses/apig.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/adapters/ingresses/apig.rs b/src/adapters/ingresses/apig.rs index 6faf377..2270ca4 100644 --- a/src/adapters/ingresses/apig.rs +++ b/src/adapters/ingresses/apig.rs @@ -178,7 +178,13 @@ impl AwsApiGateway { .rest_api_id(api.id.unwrap_or_default()) .stage_name(stage_name) .patch_operations(patch_op) - pub async fn promote_apig_canary(&self, api_id: &str, stage_name: &str) -> Result<()> { + .send() + .await + .into_diagnostic()?; + + Ok(()) + } + pub async fn promote_apig_canary(&self, api_name: &str, stage_name: &str) -> Result<()> { let api = self.get_api_id_by_name(api_name).await?;