Skip to content

Commit

Permalink
Merge pull request #32 from wack/eric/impl-apig-release
Browse files Browse the repository at this point in the history
MULTI-295: Add ability to create new canary deployment
  • Loading branch information
EricGhildyal authored Nov 21, 2024
2 parents 9be33ec + af20baa commit 39ec82c
Showing 1 changed file with 78 additions and 3 deletions.
81 changes: 78 additions & 3 deletions src/adapters/ingresses/apig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ use crate::utils::load_default_aws_config;

use super::Ingress;
use async_trait::async_trait;
use miette::miette;
use miette::{IntoDiagnostic, Result};
use tokio::{fs::File, io::AsyncReadExt};

use aws_sdk_apigateway::client::Client as GatewayClient;
use aws_sdk_lambda::client::Client as LambdaClient;
use aws_sdk_apigateway::{client::Client as GatewayClient, types::DeploymentCanarySettings};
use aws_sdk_lambda::{client::Client as LambdaClient, primitives::Blob, types::FunctionCode};

/// AwsApiGateway is the Ingress implementation for AWS API Gateway + Lambda.
/// It's responsible for creating canary deployments on API Gateway, updating their
Expand All @@ -31,12 +32,78 @@ impl AwsApiGateway {
let config = load_default_aws_config().await;
let apig_client = GatewayClient::new(config);
let lambda_client = LambdaClient::new(config);

Ok(Self {
lambda_artifact: artifact,
apig_client,
lambda_client,
})
}

pub async fn upload_lambda(&self, lambda_name: &str) -> Result<String> {
// Parse the bytes into the format AWS wants
let code = Blob::from(self.lambda_artifact.clone());

// Turn it into an uploadable zip file
let function_code = FunctionCode::builder().zip_file(code).build();
let zip_file = function_code
.zip_file()
.ok_or(miette!("Couldn't zip lambda code"))?;

// Upload it to Lambda
let res = self
.lambda_client
.update_function_code()
.function_name(lambda_name)
.zip_file(zip_file.clone())
.send()
.await
.into_diagnostic()?;

let version = res
.version()
.ok_or(miette!("Couldn't get version of deployed lambda"))?;

Ok(version.to_string())
}

pub async fn create_apig_deployment(
&self,
api_id: &str,
stage_name: &str,
lambda_name: &str,
lambda_version: &str,
traffic_percentage: f64,
) -> Result<()> {
// Update the APIG with the new lambda version
self.apig_client
.put_integration()
.rest_api_id(api_id)
.uri(format!(
"arn:aws:lambda:us-east-2:471112630982:function:{}:{}",
lambda_name, lambda_version
))
.send()
.await
.into_diagnostic()?;

// Create a deployment with canary settings to deploy our new lambda
self.apig_client
.create_deployment()
.rest_api_id(api_id)
.stage_name(stage_name)
.canary_settings(
DeploymentCanarySettings::builder()
.percent_traffic(traffic_percentage)
.use_stage_cache(false)
.build(),
)
.send()
.await
.into_diagnostic()?;

Ok(())
}
}

/// given a path to a file, load it as an array of bytes.
Expand All @@ -51,6 +118,14 @@ async fn read_file(artifact_path: PathBuf) -> Result<Vec<u8>> {
#[async_trait]
impl Ingress for AwsApiGateway {
async fn deploy(&mut self) -> Result<()> {
todo!()
// First, we need to deploy the new version of the lambda
let lambda_version = self.upload_lambda("releases").await?;

// Next, we need to create a new deployment, pointing at our
// new lambda version with canary settings
self.create_apig_deployment("Releases", "prod", "releases", &lambda_version, 0.0)
.await?;

Ok(())
}
}

0 comments on commit 39ec82c

Please sign in to comment.