-
Notifications
You must be signed in to change notification settings - Fork 196
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
351 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
pub(crate) mod paginator_canary; | ||
pub(crate) mod s3_canary; | ||
pub(crate) mod transcribe_canary; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
use crate::mk_canary; | ||
use anyhow::bail; | ||
|
||
use aws_sdk_ec2 as ec2; | ||
use aws_sdk_ec2::types::InstanceType; | ||
|
||
use crate::CanaryEnv; | ||
use tokio_stream::StreamExt; | ||
|
||
mk_canary!( | ||
"ec2_paginator", | ||
|sdk_config: &aws_config::SdkConfig, env: &CanaryEnv| { | ||
paginator_canary(ec2::Client::new(sdk_config), env.page_size) | ||
} | ||
); | ||
|
||
pub async fn paginator_canary(client: ec2::Client, page_size: usize) -> anyhow::Result<()> { | ||
let mut history = client | ||
.describe_spot_price_history() | ||
.instance_types(InstanceType::M1Medium) | ||
.into_paginator() | ||
.page_size(page_size as i32) | ||
.send(); | ||
|
||
let mut num_pages = 0; | ||
while let Some(page) = history.try_next().await? { | ||
let items_in_page = page.spot_price_history.unwrap_or_default().len(); | ||
if items_in_page > page_size as usize { | ||
bail!( | ||
"failed to retrieve results of correct page size (expected {}, got {})", | ||
page_size, | ||
items_in_page | ||
) | ||
} | ||
num_pages += 1; | ||
} | ||
if dbg!(num_pages) < 2 { | ||
bail!( | ||
"expected 3+ pages containing ~60 results but got {} pages", | ||
num_pages | ||
) | ||
} | ||
|
||
// https://github.com/awslabs/aws-sdk-rust/issues/405 | ||
let _ = client | ||
.describe_vpcs() | ||
.into_paginator() | ||
.items() | ||
.send() | ||
.collect::<Result<Vec<_>, _>>() | ||
.await?; | ||
|
||
Ok(()) | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use crate::paginator_canary::paginator_canary; | ||
|
||
#[tokio::test] | ||
async fn test_paginator() { | ||
let conf = aws_config::load_from_env().await; | ||
let client = aws_sdk_ec2::Client::new(&conf); | ||
paginator_canary(client, 20).await.unwrap() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
use crate::canary::CanaryError; | ||
use crate::{mk_canary, CanaryEnv}; | ||
use anyhow::Context; | ||
use aws_config::SdkConfig; | ||
use aws_sdk_s3 as s3; | ||
use s3::presigning::PresigningConfig; | ||
use s3::primitives::ByteStream; | ||
use std::time::Duration; | ||
use uuid::Uuid; | ||
|
||
const METADATA_TEST_VALUE: &str = "some value"; | ||
|
||
mk_canary!("s3", |sdk_config: &SdkConfig, env: &CanaryEnv| s3_canary( | ||
s3::Client::new(sdk_config), | ||
env.s3_bucket_name.clone() | ||
)); | ||
|
||
pub async fn s3_canary(client: s3::Client, s3_bucket_name: String) -> anyhow::Result<()> { | ||
let test_key = Uuid::new_v4().as_u128().to_string(); | ||
|
||
// Look for the test object and expect that it doesn't exist | ||
match client | ||
.get_object() | ||
.bucket(&s3_bucket_name) | ||
.key(&test_key) | ||
.send() | ||
.await | ||
{ | ||
Ok(_) => { | ||
return Err( | ||
CanaryError(format!("Expected object {} to not exist in S3", test_key)).into(), | ||
); | ||
} | ||
Err(err) => { | ||
let err = err.into_service_error(); | ||
// If we get anything other than "No such key", we have a problem | ||
if !err.is_no_such_key() { | ||
return Err(err).context("unexpected s3::GetObject failure"); | ||
} | ||
} | ||
} | ||
|
||
// Put the test object | ||
client | ||
.put_object() | ||
.bucket(&s3_bucket_name) | ||
.key(&test_key) | ||
.body(ByteStream::from_static(b"test")) | ||
.metadata("something", METADATA_TEST_VALUE) | ||
.send() | ||
.await | ||
.context("s3::PutObject")?; | ||
|
||
// Get the test object and verify it looks correct | ||
let output = client | ||
.get_object() | ||
.bucket(&s3_bucket_name) | ||
.key(&test_key) | ||
.send() | ||
.await | ||
.context("s3::GetObject[2]")?; | ||
|
||
// repeat the test with a presigned url | ||
let uri = client | ||
.get_object() | ||
.bucket(&s3_bucket_name) | ||
.key(&test_key) | ||
.presigned(PresigningConfig::expires_in(Duration::from_secs(120)).unwrap()) | ||
.await | ||
.unwrap(); | ||
let response = reqwest::get(uri.uri().to_string()) | ||
.await | ||
.context("s3::presigned")? | ||
.text() | ||
.await?; | ||
if response != "test" { | ||
return Err(CanaryError(format!("presigned URL returned bad data: {:?}", response)).into()); | ||
} | ||
|
||
let mut result = Ok(()); | ||
match output.metadata() { | ||
Some(map) => { | ||
// Option::as_deref doesn't work here since the deref of &String is String | ||
let value = map.get("something").map(|s| s.as_str()).unwrap_or(""); | ||
if value != METADATA_TEST_VALUE { | ||
result = Err(CanaryError(format!( | ||
"S3 metadata was incorrect. Expected `{}` but got `{}`.", | ||
METADATA_TEST_VALUE, value | ||
)) | ||
.into()); | ||
} | ||
} | ||
None => { | ||
result = Err(CanaryError("S3 metadata was missing".into()).into()); | ||
} | ||
} | ||
|
||
let payload = output | ||
.body | ||
.collect() | ||
.await | ||
.context("download s3::GetObject[2] body")? | ||
.into_bytes(); | ||
if std::str::from_utf8(payload.as_ref()).context("s3 payload")? != "test" { | ||
result = Err(CanaryError("S3 object body didn't match what was put there".into()).into()); | ||
} | ||
|
||
// Delete the test object | ||
client | ||
.delete_object() | ||
.bucket(&s3_bucket_name) | ||
.key(&test_key) | ||
.send() | ||
.await | ||
.context("s3::DeleteObject")?; | ||
|
||
result | ||
} | ||
|
||
// This test runs against an actual AWS account. Comment out the `ignore` to run it. | ||
// Be sure to set the `TEST_S3_BUCKET` environment variable to the S3 bucket to use, | ||
// and also make sure the credential profile sets the region (or set `AWS_DEFAULT_PROFILE`). | ||
#[ignore] | ||
#[cfg(test)] | ||
#[tokio::test] | ||
async fn test_s3_canary() { | ||
let config = aws_config::load_from_env().await; | ||
let client = s3::Client::new(&config); | ||
s3_canary( | ||
client, | ||
std::env::var("TEST_S3_BUCKET").expect("TEST_S3_BUCKET must be set"), | ||
) | ||
.await | ||
.expect("success"); | ||
} |
92 changes: 92 additions & 0 deletions
92
tools/ci-cdk/canary-lambda/src/latest/transcribe_canary.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
use crate::canary::CanaryError; | ||
use crate::mk_canary; | ||
use async_stream::stream; | ||
use aws_config::SdkConfig; | ||
use aws_sdk_transcribestreaming as transcribe; | ||
use bytes::BufMut; | ||
use transcribe::primitives::Blob; | ||
use transcribe::types::{ | ||
AudioEvent, AudioStream, LanguageCode, MediaEncoding, TranscriptResultStream, | ||
}; | ||
|
||
const CHUNK_SIZE: usize = 8192; | ||
use crate::canary::CanaryEnv; | ||
|
||
mk_canary!( | ||
"transcribe_canary", | ||
|sdk_config: &SdkConfig, env: &CanaryEnv| { | ||
transcribe_canary( | ||
transcribe::Client::new(sdk_config), | ||
env.expected_transcribe_result.clone(), | ||
) | ||
} | ||
); | ||
|
||
pub async fn transcribe_canary( | ||
client: transcribe::Client, | ||
expected_transcribe_result: String, | ||
) -> anyhow::Result<()> { | ||
let input_stream = stream! { | ||
let pcm = pcm_data(); | ||
for chunk in pcm.chunks(CHUNK_SIZE) { | ||
yield Ok(AudioStream::AudioEvent(AudioEvent::builder().audio_chunk(Blob::new(chunk)).build())); | ||
} | ||
}; | ||
|
||
let mut output = client | ||
.start_stream_transcription() | ||
.language_code(LanguageCode::EnGb) | ||
.media_sample_rate_hertz(8000) | ||
.media_encoding(MediaEncoding::Pcm) | ||
.audio_stream(input_stream.into()) | ||
.send() | ||
.await?; | ||
|
||
let mut full_message = String::new(); | ||
while let Some(event) = output.transcript_result_stream.recv().await? { | ||
match event { | ||
TranscriptResultStream::TranscriptEvent(transcript_event) => { | ||
let transcript = transcript_event.transcript.unwrap(); | ||
for result in transcript.results.unwrap_or_default() { | ||
if !result.is_partial { | ||
let first_alternative = &result.alternatives.as_ref().unwrap()[0]; | ||
full_message += first_alternative.transcript.as_ref().unwrap(); | ||
full_message.push(' '); | ||
} | ||
} | ||
} | ||
otherwise => panic!("received unexpected event type: {:?}", otherwise), | ||
} | ||
} | ||
|
||
if expected_transcribe_result != full_message.trim() { | ||
Err(CanaryError(format!( | ||
"Transcription from Transcribe doesn't look right:\n\ | ||
Expected: `{}`\n\ | ||
Actual: `{}`\n", | ||
expected_transcribe_result, | ||
full_message.trim() | ||
)) | ||
.into()) | ||
} else { | ||
Ok(()) | ||
} | ||
} | ||
|
||
fn pcm_data() -> Vec<u8> { | ||
let reader = | ||
hound::WavReader::new(&include_bytes!("../../audio/hello-transcribe-8000.wav")[..]) | ||
.expect("valid wav data"); | ||
let samples_result: hound::Result<Vec<i16>> = reader.into_samples::<i16>().collect(); | ||
|
||
let mut pcm: Vec<u8> = Vec::new(); | ||
for sample in samples_result.unwrap() { | ||
pcm.put_i16_le(sample); | ||
} | ||
pcm | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
pub(crate) mod paginator_canary; | ||
pub(crate) mod s3_canary; | ||
pub(crate) mod transcribe_canary; |
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.