Exemplos de Auto Scaling usando SDK para Rust - AWS SDKExemplos de código

Há mais AWS SDK exemplos disponíveis no GitHub repositório AWS Doc SDK Examples.

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Exemplos de Auto Scaling usando SDK para Rust

Os exemplos de código a seguir mostram como realizar ações e implementar cenários comuns usando o AWS SDK for Rust com Auto Scaling.

As noções básicas são exemplos de código que mostram como realizar as operações essenciais em um serviço.

Ações são trechos de código de programas maiores e devem ser executadas em contexto. Embora as ações mostrem como chamar funções de serviço individuais, é possível ver as ações no contexto em seus cenários relacionados.

Cada exemplo inclui um link para o código-fonte completo, onde você pode encontrar instruções sobre como configurar e executar o código no contexto.

Conceitos básicos

Os exemplos de código a seguir mostram como começar a usar o Auto Scaling.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

async fn list_groups(client: &Client) -> Result<(), Error> { let resp = client.describe_auto_scaling_groups().send().await?; println!("Groups:"); let groups = resp.auto_scaling_groups(); for group in groups { println!( "Name: {}", group.auto_scaling_group_name().unwrap_or("Unknown") ); println!( "Arn: {}", group.auto_scaling_group_arn().unwrap_or("unknown"), ); println!("Zones: {:?}", group.availability_zones(),); println!(); } println!("Found {} group(s)", groups.len()); Ok(()) }

Conceitos básicos

O exemplo de código a seguir mostra como:

  • Crie um grupo do Amazon EC2 Auto Scaling com um modelo de lançamento e zonas de disponibilidade e obtenha informações sobre instâncias em execução.

  • Ative a coleta de CloudWatch métricas da Amazon.

  • Atualizar a capacidade desejada do grupo e aguardar a inicialização de uma instância.

  • Encerrar uma instância no grupo.

  • Listar as atividades de ajuste de escala que ocorrem em resposta às solicitações do usuário e às mudanças de capacidade.

  • Obtenha estatísticas de CloudWatch métricas e, em seguida, limpe os recursos.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

[package] name = "autoscaling-code-examples" version = "0.1.0" authors = ["Doug Schwartz <dougsch@amazon.com>", "David Souther <dpsouth@amazon.com>"] edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] aws-config = { version = "1.0.1", features = ["behavior-version-latest"] } aws-sdk-autoscaling = { version = "1.3.0" } aws-sdk-ec2 = { version = "1.3.0" } aws-types = { version = "1.0.1" } tokio = { version = "1.20.1", features = ["full"] } clap = { version = "4.4", features = ["derive"] } tracing-subscriber = { version = "0.3.15", features = ["env-filter"] } anyhow = "1.0.75" tracing = "0.1.37" tokio-stream = "0.1.14" use std::{collections::BTreeSet, fmt::Display}; use anyhow::anyhow; use autoscaling_code_examples::scenario::{AutoScalingScenario, ScenarioError}; use tracing::{info, warn}; async fn show_scenario_description(scenario: &AutoScalingScenario, event: &str) { let description = scenario.describe_scenario().await; info!("DescribeAutoScalingInstances: {event}\n{description}"); } #[derive(Default, Debug)] struct Warnings(Vec<String>); impl Warnings { pub fn push(&mut self, warning: &str, error: ScenarioError) { let formatted = format!("{warning}: {error}"); warn!("{formatted}"); self.0.push(formatted); } pub fn is_empty(&self) -> bool { self.0.is_empty() } } impl Display for Warnings { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "Warnings:")?; for warning in &self.0 { writeln!(f, "{: >4}- {warning}", "")?; } Ok(()) } } #[tokio::main] async fn main() -> Result<(), anyhow::Error> { tracing_subscriber::fmt::init(); let shared_config = aws_config::from_env().load().await; let mut warnings = Warnings::default(); // 1. Create an EC2 launch template that you'll use to create an auto scaling group. Bonus: use SDK with EC2.CreateLaunchTemplate to create the launch template. // 2. CreateAutoScalingGroup: pass it the launch template you created in step 0. Give it min/max of 1 instance. // 4. EnableMetricsCollection: enable all metrics or a subset. let scenario = match AutoScalingScenario::prepare_scenario(&shared_config).await { Ok(scenario) => scenario, Err(errs) => { let err_str = errs .into_iter() .map(|e| e.to_string()) .collect::<Vec<String>>() .join(", "); return Err(anyhow!("Failed to initialize scenario: {err_str}")); } }; info!("Prepared autoscaling scenario:\n{scenario}"); let stable = scenario.wait_for_stable(1).await; if let Err(err) = stable { warnings.push( "There was a problem while waiting for group to be stable", err, ); } // 3. DescribeAutoScalingInstances: show that one instance has launched. show_scenario_description( &scenario, "show that the group was created and one instance has launched", ) .await; // 5. UpdateAutoScalingGroup: update max size to 3. let scale_max_size = scenario.scale_max_size(3).await; if let Err(err) = scale_max_size { warnings.push("There was a problem scaling max size", err); } // 6. DescribeAutoScalingGroups: the current state of the group show_scenario_description( &scenario, "show the current state of the group after setting max size", ) .await; // 7. SetDesiredCapacity: set desired capacity to 2. let scale_desired_capacity = scenario.scale_desired_capacity(2).await; if let Err(err) = scale_desired_capacity { warnings.push("There was a problem setting desired capacity", err); } // Wait for a second instance to launch. let stable = scenario.wait_for_stable(2).await; if let Err(err) = stable { warnings.push( "There was a problem while waiting for group to be stable", err, ); } // 8. DescribeAutoScalingInstances: show that two instances are launched. show_scenario_description( &scenario, "show that two instances are launched after setting desired capacity", ) .await; let ids_before = scenario .list_instances() .await .map(|v| v.into_iter().collect::<BTreeSet<_>>()) .unwrap_or_default(); // 9. TerminateInstanceInAutoScalingGroup: terminate one of the instances in the group. let terminate_some_instance = scenario.terminate_some_instance().await; if let Err(err) = terminate_some_instance { warnings.push("There was a problem replacing an instance", err); } let wait_after_terminate = scenario.wait_for_stable(1).await; if let Err(err) = wait_after_terminate { warnings.push( "There was a problem waiting after terminating an instance", err, ); } let wait_scale_up_after_terminate = scenario.wait_for_stable(2).await; if let Err(err) = wait_scale_up_after_terminate { warnings.push( "There was a problem waiting for scale up after terminating an instance", err, ); } let ids_after = scenario .list_instances() .await .map(|v| v.into_iter().collect::<BTreeSet<_>>()) .unwrap_or_default(); let difference = ids_after.intersection(&ids_before).count(); if !(difference == 1 && ids_before.len() == 2 && ids_after.len() == 2) { warnings.push( "Before and after set not different", ScenarioError::with(format!("{difference}")), ); } // 10. DescribeScalingActivities: list the scaling activities that have occurred for the group so far. show_scenario_description( &scenario, "list the scaling activities that have occurred for the group so far", ) .await; // 11. DisableMetricsCollection let scale_group = scenario.scale_group_to_zero().await; if let Err(err) = scale_group { warnings.push("There was a problem scaling the group to 0", err); } show_scenario_description(&scenario, "Scenario scaled to 0").await; // 12. DeleteAutoScalingGroup (to delete the group you must stop all instances): // 13. Delete LaunchTemplate. let clean_scenario = scenario.clean_scenario().await; if let Err(errs) = clean_scenario { for err in errs { warnings.push("There was a problem cleaning the scenario", err); } } else { info!("The scenario has been cleaned up!"); } if warnings.is_empty() { Ok(()) } else { Err(anyhow!( "There were warnings during scenario execution:\n{warnings}" )) } } pub mod scenario; use std::{ error::Error, fmt::{Debug, Display}, time::{Duration, SystemTime}, }; use anyhow::anyhow; use aws_config::SdkConfig; use aws_sdk_autoscaling::{ error::{DisplayErrorContext, ProvideErrorMetadata}, types::{Activity, AutoScalingGroup, LaunchTemplateSpecification}, }; use aws_sdk_ec2::types::RequestLaunchTemplateData; use tracing::trace; const LAUNCH_TEMPLATE_NAME: &str = "SDK_Code_Examples_EC2_Autoscaling_template_from_Rust_SDK"; const AUTOSCALING_GROUP_NAME: &str = "SDK_Code_Examples_EC2_Autoscaling_Group_from_Rust_SDK"; const MAX_WAIT: Duration = Duration::from_secs(5 * 60); // Wait at most 25 seconds. const WAIT_TIME: Duration = Duration::from_millis(500); // Wait half a second at a time. struct Waiter { start: SystemTime, max: Duration, } impl Waiter { fn new() -> Self { Waiter { start: SystemTime::now(), max: MAX_WAIT, } } async fn sleep(&self) -> Result<(), ScenarioError> { if SystemTime::now() .duration_since(self.start) .unwrap_or(Duration::MAX) > self.max { Err(ScenarioError::with( "Exceeded maximum wait duration for stable group", )) } else { tokio::time::sleep(WAIT_TIME).await; Ok(()) } } } pub struct AutoScalingScenario { ec2: aws_sdk_ec2::Client, autoscaling: aws_sdk_autoscaling::Client, launch_template_arn: String, auto_scaling_group_name: String, } impl Display for AutoScalingScenario { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!( "\tLaunch Template ID: {}\n", self.launch_template_arn ))?; f.write_fmt(format_args!( "\tScaling Group Name: {}\n", self.auto_scaling_group_name ))?; Ok(()) } } pub struct AutoScalingScenarioDescription { group: Result<Vec<String>, ScenarioError>, instances: Result<Vec<String>, anyhow::Error>, activities: Result<Vec<Activity>, anyhow::Error>, } impl Display for AutoScalingScenarioDescription { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "\t Group status:")?; match &self.group { Ok(groups) => { for status in groups { writeln!(f, "\t\t- {status}")?; } } Err(e) => writeln!(f, "\t\t! - {e}")?, } writeln!(f, "\t Instances:")?; match &self.instances { Ok(instances) => { for instance in instances { writeln!(f, "\t\t- {instance}")?; } } Err(e) => writeln!(f, "\t\t! {e}")?, } writeln!(f, "\t Activities:")?; match &self.activities { Ok(activities) => { for activity in activities { writeln!( f, "\t\t- {} Progress: {}% Status: {:?} End: {:?}", activity.cause().unwrap_or("Unknown"), activity.progress.unwrap_or(-1), activity.status_code(), // activity.status_message().unwrap_or_default() activity.end_time(), )?; } } Err(e) => writeln!(f, "\t\t! {e}")?, } Ok(()) } } #[derive(Debug)] struct MetadataError { message: Option<String>, code: Option<String>, } impl MetadataError { fn from(err: &dyn ProvideErrorMetadata) -> Self { MetadataError { message: err.message().map(|s| s.to_string()), code: err.code().map(|s| s.to_string()), } } } impl Display for MetadataError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let display = match (&self.message, &self.code) { (None, None) => "Unknown".to_string(), (None, Some(code)) => format!("({code})"), (Some(message), None) => message.to_string(), (Some(message), Some(code)) => format!("{message} ({code})"), }; write!(f, "{display}") } } #[derive(Debug)] pub struct ScenarioError { message: String, context: Option<MetadataError>, } impl ScenarioError { pub fn with(message: impl Into<String>) -> Self { ScenarioError { message: message.into(), context: None, } } pub fn new(message: impl Into<String>, err: &dyn ProvideErrorMetadata) -> Self { ScenarioError { message: message.into(), context: Some(MetadataError::from(err)), } } } impl Error for ScenarioError { // While `Error` can capture `source` information about the underlying error, for this example // the ScenarioError captures the underlying information in MetadataError and treats it as a // single Error from this Crate. In other contexts, it may be appropriate to model the error // as including the SdkError as its source. } impl Display for ScenarioError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self.context { Some(c) => write!(f, "{}: {}", self.message, c), None => write!(f, "{}", self.message), } } } impl AutoScalingScenario { pub async fn prepare_scenario(sdk_config: &SdkConfig) -> Result<Self, Vec<ScenarioError>> { let ec2 = aws_sdk_ec2::Client::new(sdk_config); let autoscaling = aws_sdk_autoscaling::Client::new(sdk_config); let auto_scaling_group_name = String::from(AUTOSCALING_GROUP_NAME); // Before creating any resources, prepare the list of AZs let availablity_zones = ec2.describe_availability_zones().send().await; if let Err(err) = availablity_zones { return Err(vec![ScenarioError::new("Failed to find AZs", &err)]); } let availability_zones: Vec<String> = availablity_zones .unwrap() .availability_zones .unwrap_or_default() .iter() .take(3) .map(|z| z.zone_name.clone().unwrap()) .collect(); // 1. Create an EC2 launch template that you'll use to create an auto scaling group. Bonus: use SDK with EC2.CreateLaunchTemplate to create the launch template. // * Recommended: InstanceType='t1.micro', ImageId='ami-0ca285d4c2cda3300' let create_launch_template = ec2 .create_launch_template() .launch_template_name(LAUNCH_TEMPLATE_NAME) .launch_template_data( RequestLaunchTemplateData::builder() .instance_type(aws_sdk_ec2::types::InstanceType::T1Micro) .image_id("ami-0ca285d4c2cda3300") .build(), ) .send() .await .map_err(|err| vec![ScenarioError::new("Failed to create launch template", &err)])?; let launch_template_arn = match create_launch_template.launch_template { Some(launch_template) => launch_template.launch_template_id.unwrap_or_default(), None => { // Try to delete the launch template let _ = ec2 .delete_launch_template() .launch_template_name(LAUNCH_TEMPLATE_NAME) .send() .await; return Err(vec![ScenarioError::with("Failed to load launch template")]); } }; // 2. CreateAutoScalingGroup: pass it the launch template you created in step 0. Give it min/max of 1 instance. // You can use EC2.describe_availability_zones() to get a list of AZs (you have to specify an AZ when you create the group). // Wait for instance to launch. Use a waiter if you have one, otherwise DescribeAutoScalingInstances until LifecycleState='InService' if let Err(err) = autoscaling .create_auto_scaling_group() .auto_scaling_group_name(auto_scaling_group_name.as_str()) .launch_template( LaunchTemplateSpecification::builder() .launch_template_id(launch_template_arn.clone()) .version("$Latest") .build(), ) .max_size(1) .min_size(1) .set_availability_zones(Some(availability_zones)) .send() .await { let mut errs = vec![ScenarioError::new( "Failed to create autoscaling group", &err, )]; if let Err(err) = autoscaling .delete_auto_scaling_group() .auto_scaling_group_name(auto_scaling_group_name.as_str()) .send() .await { errs.push(ScenarioError::new( "Failed to clean up autoscaling group", &err, )); } if let Err(err) = ec2 .delete_launch_template() .launch_template_id(launch_template_arn.clone()) .send() .await { errs.push(ScenarioError::new( "Failed to clean up launch template", &err, )); } return Err(errs); } let scenario = AutoScalingScenario { ec2, autoscaling: autoscaling.clone(), // Clients are cheap so cloning here to prevent a move is ok. auto_scaling_group_name: auto_scaling_group_name.clone(), launch_template_arn, }; let enable_metrics_collection = autoscaling .enable_metrics_collection() .auto_scaling_group_name(auto_scaling_group_name.as_str()) .granularity("1Minute") .set_metrics(Some(vec![ String::from("GroupMinSize"), String::from("GroupMaxSize"), String::from("GroupDesiredCapacity"), String::from("GroupInServiceInstances"), String::from("GroupTotalInstances"), ])) .send() .await; match enable_metrics_collection { Ok(_) => Ok(scenario), Err(err) => { scenario.clean_scenario().await?; Err(vec![ScenarioError::new( "Failed to enable metrics collections for group", &err, )]) } } } pub async fn clean_scenario(self) -> Result<(), Vec<ScenarioError>> { let _ = self.wait_for_no_scaling().await; let delete_group = self .autoscaling .delete_auto_scaling_group() .auto_scaling_group_name(self.auto_scaling_group_name.clone()) .send() .await; // 14. Delete LaunchTemplate. let delete_launch_template = self .ec2 .delete_launch_template() .launch_template_id(self.launch_template_arn.clone()) .send() .await; let early_exit = match (delete_group, delete_launch_template) { (Ok(_), Ok(_)) => Ok(()), (Ok(_), Err(e)) => Err(vec![ScenarioError::new( "There was an error cleaning the launch template", &e, )]), (Err(e), Ok(_)) => Err(vec![ScenarioError::new( "There was an error cleaning the scale group", &e, )]), (Err(e1), Err(e2)) => Err(vec![ ScenarioError::new("Multiple error cleaning the scenario Scale Group", &e1), ScenarioError::new("Multiple error cleaning the scenario Launch Template", &e2), ]), }; if early_exit.is_err() { early_exit } else { // Wait for delete_group to finish let waiter = Waiter::new(); let mut errors = Vec::<ScenarioError>::new(); while errors.len() < 3 { if let Err(e) = waiter.sleep().await { errors.push(e); continue; } let describe_group = self .autoscaling .describe_auto_scaling_groups() .auto_scaling_group_names(self.auto_scaling_group_name.clone()) .send() .await; match describe_group { Ok(group) => match group.auto_scaling_groups().first() { Some(group) => { if group.status() != Some("Delete in progress") { errors.push(ScenarioError::with(format!( "Group in an unknown state while deleting: {}", group.status().unwrap_or("unknown error") ))); return Err(errors); } } None => return Ok(()), }, Err(err) => { errors.push(ScenarioError::new("Failed to describe autoscaling group during cleanup 3 times, last error", &err)); } } if errors.len() > 3 { return Err(errors); } } Err(vec![ScenarioError::with( "Exited cleanup wait loop without retuning success or failing after three rounds", )]) } } pub async fn describe_scenario(&self) -> AutoScalingScenarioDescription { let group = self .autoscaling .describe_auto_scaling_groups() .auto_scaling_group_names(self.auto_scaling_group_name.clone()) .send() .await .map(|s| { s.auto_scaling_groups() .iter() .map(|s| { format!( "{}: {}", s.auto_scaling_group_name().unwrap_or("Unknown"), s.status().unwrap_or("Unknown") ) }) .collect::<Vec<String>>() }) .map_err(|e| { ScenarioError::new("Failed to describe auto scaling groups for scenario", &e) }); let instances = self .list_instances() .await .map_err(|e| anyhow!("There was an error listing instances: {e}",)); // 10. DescribeScalingActivities: list the scaling activities that have occurred for the group so far. // Bonus: use CloudWatch API to get and show some metrics collected for the group. // CW.ListMetrics with Namespace='AWS/AutoScaling' and Dimensions=[{'Name': 'AutoScalingGroupName', 'Value': }] // CW.GetMetricStatistics with Statistics='Sum'. Start and End times must be in UTC! let activities = self .autoscaling .describe_scaling_activities() .auto_scaling_group_name(self.auto_scaling_group_name.clone()) .into_paginator() .items() .send() .collect::<Result<Vec<_>, _>>() .await .map_err(|e| { anyhow!( "There was an error retrieving scaling activities: {}", DisplayErrorContext(&e) ) }); AutoScalingScenarioDescription { group, instances, activities, } } async fn get_group(&self) -> Result<AutoScalingGroup, ScenarioError> { let describe_auto_scaling_groups = self .autoscaling .describe_auto_scaling_groups() .auto_scaling_group_names(self.auto_scaling_group_name.clone()) .send() .await; if let Err(err) = describe_auto_scaling_groups { return Err(ScenarioError::new( format!( "Failed to get status of autoscaling group {}", self.auto_scaling_group_name.clone() ) .as_str(), &err, )); } let describe_auto_scaling_groups_output = describe_auto_scaling_groups.unwrap(); let auto_scaling_groups = describe_auto_scaling_groups_output.auto_scaling_groups(); let auto_scaling_group = auto_scaling_groups.first(); if auto_scaling_group.is_none() { return Err(ScenarioError::with(format!( "Could not find autoscaling group {}", self.auto_scaling_group_name.clone() ))); } Ok(auto_scaling_group.unwrap().clone()) } pub async fn wait_for_no_scaling(&self) -> Result<(), ScenarioError> { let waiter = Waiter::new(); let mut scaling = true; while scaling { waiter.sleep().await?; let describe_activities = self .autoscaling .describe_scaling_activities() .auto_scaling_group_name(self.auto_scaling_group_name.clone()) .send() .await .map_err(|e| { ScenarioError::new("Failed to get autoscaling activities for group", &e) })?; let activities = describe_activities.activities(); trace!( "Waiting for no scaling found {} activities", activities.len() ); scaling = activities.iter().any(|a| a.progress() < Some(100)); } Ok(()) } pub async fn wait_for_stable(&self, size: usize) -> Result<(), ScenarioError> { self.wait_for_no_scaling().await?; let mut group = self.get_group().await?; let mut count = count_group_instances(&group); let waiter = Waiter::new(); while count != size { trace!("Waiting for stable {size} (current: {count})"); waiter.sleep().await?; group = self.get_group().await?; count = count_group_instances(&group); } Ok(()) } pub async fn list_instances(&self) -> Result<Vec<String>, ScenarioError> { // The direct way to list instances is by using DescribeAutoScalingGroup's instances property. However, this returns a Vec<Instance>, as opposed to a Vec<AutoScalingInstanceDetails>. // Ok(self.get_group().await?.instances.unwrap_or_default().map(|i| i.instance_id.clone().unwrap_or_default()).filter(|id| !id.is_empty()).collect()) // Alternatively, and for the sake of example, DescribeAutoScalingInstances returns a list that can be filtered by the client. self.autoscaling .describe_auto_scaling_instances() .into_paginator() .items() .send() .try_collect() .await .map(|items| { items .into_iter() .filter(|i| { i.auto_scaling_group_name.as_deref() == Some(self.auto_scaling_group_name.as_str()) }) .map(|i| i.instance_id.unwrap_or_default()) .filter(|id| !id.is_empty()) .collect::<Vec<String>>() }) .map_err(|err| ScenarioError::new("Failed to get list of auto scaling instances", &err)) } pub async fn scale_min_size(&self, size: i32) -> Result<(), ScenarioError> { let update_group = self .autoscaling .update_auto_scaling_group() .auto_scaling_group_name(self.auto_scaling_group_name.clone()) .min_size(size) .send() .await; if let Err(err) = update_group { return Err(ScenarioError::new( format!("Failer to update group to min size ({size}))").as_str(), &err, )); } Ok(()) } pub async fn scale_max_size(&self, size: i32) -> Result<(), ScenarioError> { // 5. UpdateAutoScalingGroup: update max size to 3. let update_group = self .autoscaling .update_auto_scaling_group() .auto_scaling_group_name(self.auto_scaling_group_name.clone()) .max_size(size) .send() .await; if let Err(err) = update_group { return Err(ScenarioError::new( format!("Failed to update group to max size ({size})").as_str(), &err, )); } Ok(()) } pub async fn scale_desired_capacity(&self, capacity: i32) -> Result<(), ScenarioError> { // 7. SetDesiredCapacity: set desired capacity to 2. // Wait for a second instance to launch. let update_group = self .autoscaling .set_desired_capacity() .auto_scaling_group_name(self.auto_scaling_group_name.clone()) .desired_capacity(capacity) .send() .await; if let Err(err) = update_group { return Err(ScenarioError::new( format!("Failed to update group to desired capacity ({capacity}))").as_str(), &err, )); } Ok(()) } pub async fn scale_group_to_zero(&self) -> Result<(), ScenarioError> { // If this fails it's fine, just means there are extra cloudwatch metrics events for the scale-down. let _ = self .autoscaling .disable_metrics_collection() .auto_scaling_group_name(self.auto_scaling_group_name.clone()) .send() .await; // 12. DeleteAutoScalingGroup (to delete the group you must stop all instances): // UpdateAutoScalingGroup with MinSize=0 let update_group = self .autoscaling .update_auto_scaling_group() .auto_scaling_group_name(self.auto_scaling_group_name.clone()) .min_size(0) .desired_capacity(0) .send() .await; if let Err(err) = update_group { return Err(ScenarioError::new( "Failed to update group for scaling down&", &err, )); } let stable = self.wait_for_stable(0).await; if let Err(err) = stable { return Err(ScenarioError::with(format!( "Error while waiting for group to be stable on scale down: {err}" ))); } Ok(()) } pub async fn terminate_some_instance(&self) -> Result<(), ScenarioError> { // Retrieve a list of instances in the auto scaling group. let auto_scaling_group = self.get_group().await?; let instances = auto_scaling_group.instances(); // Or use other logic to find an instance to terminate. let instance = instances.first(); if let Some(instance) = instance { let instance_id = if let Some(instance_id) = instance.instance_id() { instance_id } else { return Err(ScenarioError::with("Missing instance id")); }; let termination = self .ec2 .terminate_instances() .instance_ids(instance_id) .send() .await; if let Err(err) = termination { Err(ScenarioError::new( "There was a problem terminating an instance", &err, )) } else { Ok(()) } } else { Err(ScenarioError::with("There was no instance to terminate")) } } } fn count_group_instances(group: &AutoScalingGroup) -> usize { group.instances.as_ref().map(|i| i.len()).unwrap_or(0) }

Ações

O código de exemplo a seguir mostra como usar CreateAutoScalingGroup.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

async fn create_group(client: &Client, name: &str, id: &str) -> Result<(), Error> { client .create_auto_scaling_group() .auto_scaling_group_name(name) .instance_id(id) .min_size(1) .max_size(5) .send() .await?; println!("Created AutoScaling group"); Ok(()) }

O código de exemplo a seguir mostra como usar DeleteAutoScalingGroup.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

async fn delete_group(client: &Client, name: &str, force: bool) -> Result<(), Error> { client .delete_auto_scaling_group() .auto_scaling_group_name(name) .set_force_delete(if force { Some(true) } else { None }) .send() .await?; println!("Deleted Auto Scaling group"); Ok(()) }

O código de exemplo a seguir mostra como usar DescribeAutoScalingGroups.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

async fn list_groups(client: &Client) -> Result<(), Error> { let resp = client.describe_auto_scaling_groups().send().await?; println!("Groups:"); let groups = resp.auto_scaling_groups(); for group in groups { println!( "Name: {}", group.auto_scaling_group_name().unwrap_or("Unknown") ); println!( "Arn: {}", group.auto_scaling_group_arn().unwrap_or("unknown"), ); println!("Zones: {:?}", group.availability_zones(),); println!(); } println!("Found {} group(s)", groups.len()); Ok(()) }

O código de exemplo a seguir mostra como usar DescribeAutoScalingInstances.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

pub async fn list_instances(&self) -> Result<Vec<String>, ScenarioError> { // The direct way to list instances is by using DescribeAutoScalingGroup's instances property. However, this returns a Vec<Instance>, as opposed to a Vec<AutoScalingInstanceDetails>. // Ok(self.get_group().await?.instances.unwrap_or_default().map(|i| i.instance_id.clone().unwrap_or_default()).filter(|id| !id.is_empty()).collect()) // Alternatively, and for the sake of example, DescribeAutoScalingInstances returns a list that can be filtered by the client. self.autoscaling .describe_auto_scaling_instances() .into_paginator() .items() .send() .try_collect() .await .map(|items| { items .into_iter() .filter(|i| { i.auto_scaling_group_name.as_deref() == Some(self.auto_scaling_group_name.as_str()) }) .map(|i| i.instance_id.unwrap_or_default()) .filter(|id| !id.is_empty()) .collect::<Vec<String>>() }) .map_err(|err| ScenarioError::new("Failed to get list of auto scaling instances", &err)) }

O código de exemplo a seguir mostra como usar DescribeScalingActivities.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

pub async fn describe_scenario(&self) -> AutoScalingScenarioDescription { let group = self .autoscaling .describe_auto_scaling_groups() .auto_scaling_group_names(self.auto_scaling_group_name.clone()) .send() .await .map(|s| { s.auto_scaling_groups() .iter() .map(|s| { format!( "{}: {}", s.auto_scaling_group_name().unwrap_or("Unknown"), s.status().unwrap_or("Unknown") ) }) .collect::<Vec<String>>() }) .map_err(|e| { ScenarioError::new("Failed to describe auto scaling groups for scenario", &e) }); let instances = self .list_instances() .await .map_err(|e| anyhow!("There was an error listing instances: {e}",)); // 10. DescribeScalingActivities: list the scaling activities that have occurred for the group so far. // Bonus: use CloudWatch API to get and show some metrics collected for the group. // CW.ListMetrics with Namespace='AWS/AutoScaling' and Dimensions=[{'Name': 'AutoScalingGroupName', 'Value': }] // CW.GetMetricStatistics with Statistics='Sum'. Start and End times must be in UTC! let activities = self .autoscaling .describe_scaling_activities() .auto_scaling_group_name(self.auto_scaling_group_name.clone()) .into_paginator() .items() .send() .collect::<Result<Vec<_>, _>>() .await .map_err(|e| { anyhow!( "There was an error retrieving scaling activities: {}", DisplayErrorContext(&e) ) }); AutoScalingScenarioDescription { group, instances, activities, } }

O código de exemplo a seguir mostra como usar DisableMetricsCollection.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

// If this fails it's fine, just means there are extra cloudwatch metrics events for the scale-down. let _ = self .autoscaling .disable_metrics_collection() .auto_scaling_group_name(self.auto_scaling_group_name.clone()) .send() .await;

O código de exemplo a seguir mostra como usar EnableMetricsCollection.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

let enable_metrics_collection = autoscaling .enable_metrics_collection() .auto_scaling_group_name(auto_scaling_group_name.as_str()) .granularity("1Minute") .set_metrics(Some(vec![ String::from("GroupMinSize"), String::from("GroupMaxSize"), String::from("GroupDesiredCapacity"), String::from("GroupInServiceInstances"), String::from("GroupTotalInstances"), ])) .send() .await;

O código de exemplo a seguir mostra como usar SetDesiredCapacity.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

pub async fn scale_desired_capacity(&self, capacity: i32) -> Result<(), ScenarioError> { // 7. SetDesiredCapacity: set desired capacity to 2. // Wait for a second instance to launch. let update_group = self .autoscaling .set_desired_capacity() .auto_scaling_group_name(self.auto_scaling_group_name.clone()) .desired_capacity(capacity) .send() .await; if let Err(err) = update_group { return Err(ScenarioError::new( format!("Failed to update group to desired capacity ({capacity}))").as_str(), &err, )); } Ok(()) }

O código de exemplo a seguir mostra como usar TerminateInstanceInAutoScalingGroup.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

pub async fn terminate_some_instance(&self) -> Result<(), ScenarioError> { // Retrieve a list of instances in the auto scaling group. let auto_scaling_group = self.get_group().await?; let instances = auto_scaling_group.instances(); // Or use other logic to find an instance to terminate. let instance = instances.first(); if let Some(instance) = instance { let instance_id = if let Some(instance_id) = instance.instance_id() { instance_id } else { return Err(ScenarioError::with("Missing instance id")); }; let termination = self .ec2 .terminate_instances() .instance_ids(instance_id) .send() .await; if let Err(err) = termination { Err(ScenarioError::new( "There was a problem terminating an instance", &err, )) } else { Ok(()) } } else { Err(ScenarioError::with("There was no instance to terminate")) } } async fn get_group(&self) -> Result<AutoScalingGroup, ScenarioError> { let describe_auto_scaling_groups = self .autoscaling .describe_auto_scaling_groups() .auto_scaling_group_names(self.auto_scaling_group_name.clone()) .send() .await; if let Err(err) = describe_auto_scaling_groups { return Err(ScenarioError::new( format!( "Failed to get status of autoscaling group {}", self.auto_scaling_group_name.clone() ) .as_str(), &err, )); } let describe_auto_scaling_groups_output = describe_auto_scaling_groups.unwrap(); let auto_scaling_groups = describe_auto_scaling_groups_output.auto_scaling_groups(); let auto_scaling_group = auto_scaling_groups.first(); if auto_scaling_group.is_none() { return Err(ScenarioError::with(format!( "Could not find autoscaling group {}", self.auto_scaling_group_name.clone() ))); } Ok(auto_scaling_group.unwrap().clone()) }

O código de exemplo a seguir mostra como usar UpdateAutoScalingGroup.

SDKpara Rust
nota

Tem mais sobre GitHub. Encontre o exemplo completo e saiba como configurar e executar no Repositório de exemplos de código da AWS.

async fn update_group(client: &Client, name: &str, size: i32) -> Result<(), Error> { client .update_auto_scaling_group() .auto_scaling_group_name(name) .max_size(size) .send() .await?; println!("Updated AutoScaling group"); Ok(()) }