Ejemplos de Auto Scaling que se utilizan SDK para Rust - AWS SDKEjemplos de código

Hay más AWS SDK ejemplos disponibles en el GitHub repositorio de AWS Doc SDK Examples.

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Ejemplos de Auto Scaling que se utilizan SDK para Rust

Los siguientes ejemplos de código muestran cómo realizar acciones e implementar escenarios comunes mediante el uso de Rust AWS SDK with Auto Scaling.

Los conceptos básicos son ejemplos de código que muestran cómo realizar las operaciones esenciales dentro de un servicio.

Las acciones son extractos de código de programas más grandes y deben ejecutarse en contexto. Mientras las acciones muestran cómo llamar a las funciones de servicio individuales, es posible ver las acciones en contexto en los escenarios relacionados.

Cada ejemplo incluye un enlace al código fuente completo, donde puedes encontrar instrucciones sobre cómo configurar y ejecutar el código en su contexto.

Introducción

En los siguientes ejemplos de código se muestra cómo empezar a utilizar el escalado automático.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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(()) }

Conceptos básicos

En el siguiente ejemplo de código, se muestra cómo:

  • Cree un grupo de Amazon EC2 Auto Scaling con una plantilla de lanzamiento y zonas de disponibilidad, y obtenga información sobre las instancias en ejecución.

  • Habilita la recopilación de CloudWatch métricas de Amazon.

  • Actualizar la capacidad deseada del grupo y esperar a que una instancia se inicie

  • Terminar una instancia del grupo.

  • Mostrar las actividades de escalado que se producen como respuesta a las solicitudes de los usuarios y a los cambios de capacidad

  • Obtén estadísticas para CloudWatch las métricas y, a continuación, limpia los recursos.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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) }

Acciones

En el siguiente ejemplo de código se muestra cómo usar CreateAutoScalingGroup.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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(()) }

En el siguiente ejemplo de código se muestra cómo usar DeleteAutoScalingGroup.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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(()) }

En el siguiente ejemplo de código se muestra cómo usar DescribeAutoScalingGroups.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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(()) }

En el siguiente ejemplo de código se muestra cómo usar DescribeAutoScalingInstances.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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)) }

En el siguiente ejemplo de código se muestra cómo usar DescribeScalingActivities.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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, } }

En el siguiente ejemplo de código se muestra cómo usar DisableMetricsCollection.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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;

En el siguiente ejemplo de código se muestra cómo usar EnableMetricsCollection.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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;

En el siguiente ejemplo de código se muestra cómo usar SetDesiredCapacity.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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(()) }
  • Para API obtener más información, consulte SetDesiredCapacityla APIreferencia AWS SDK de Rust.

En el siguiente ejemplo de código se muestra cómo usar TerminateInstanceInAutoScalingGroup.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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()) }

En el siguiente ejemplo de código se muestra cómo usar UpdateAutoScalingGroup.

SDKpara Rust
nota

Hay más información GitHub. Busque el ejemplo completo y aprenda a configurar y ejecutar en el Repositorio de ejemplos de código de 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(()) }