Rust AWS SDK EFS插件库的使用,aws-sdk-efs实现Amazon Elastic File System的云端文件存储管理

Rust AWS SDK EFS插件库的使用,aws-sdk-efs实现Amazon Elastic File System的云端文件存储管理

Amazon Elastic File System (Amazon EFS) 提供了简单、可扩展的文件存储,可与Amazon EC2 Linux和Mac实例配合使用。存储容量是弹性的,会根据文件添加和删除自动增长和收缩,使应用程序在需要时获得所需存储。

开始使用

SDK为每个AWS服务提供一个crate。您必须在Rust项目中添加Tokio作为依赖项来执行异步代码。要将aws-sdk-efs添加到您的项目中,请在Cargo.toml文件中添加以下内容:

[dependencies]
aws-config = { version = "1.1.7", features = ["behavior-version-latest"] }
aws-sdk-efs = "1.81.0"
tokio = { version = "1", features = ["full"] }

然后在代码中,可以创建如下客户端:

use aws_sdk_efs as efs;

#[::tokio::main]
async fn main() -> Result<(), efs::Error> {
    let config = aws_config::load_from_env().await;
    let client = aws_sdk_efs::Client::new(&config);

    // ... 使用客户端进行调用

    Ok(())
}

完整示例

以下是一个完整的示例,展示如何使用aws-sdk-efs创建EFS文件系统:

use aws_sdk_efs as efs;
use aws_sdk_efs::model::PerformanceMode;

#[tokio::main]
async fn main() -> Result<(), efs::Error> {
    // 加载AWS配置
    let config = aws_config::load_from_env().await;
    
    // 创建EFS客户端
    let client = efs::Client::new(&config);

    // 创建文件系统
    let create_response = client
        .create_file_system()
        .performance_mode(PerformanceMode::GeneralPurpose)
        .tags("Name", "my-efs")
        .send()
        .await?;

    println!("Created EFS filesystem: {:?}", create_response.file_system_id);

    Ok(())
}

另一个示例,列出所有EFS文件系统:

use aws_sdk_efs as efs;

#[tokio::main]
async fn main() -> Result<(), efs::Error> {
    let config = aws_config::load_from_env().await;
    let client = efs::Client::new(&config);

    // 列出所有文件系统
    let response = client
        .describe_file_systems()
        .send()
        .await?;

    if let Some(filesystems) = response.file_systems {
        println!("Found {} EFS filesystems:", filesystems.len());
        for fs in filesystems {
            println!("- ID: {} | Name: {} | State: {}",
                fs.file_system_id.unwrap_or_default(),
                fs.name.unwrap_or_default(),
                fs.life_cycle_state.unwrap_or_default()
            );
        }
    }

    Ok(())
}

完整示例DEMO

以下是一个更完整的EFS管理示例,包含创建、列出和删除文件系统的操作:

use aws_sdk_efs as efs;
use aws_sdk_efs::model::PerformanceMode;
use std::io;

#[tokio::main]
async fn main() -> Result<(), efs::Error> {
    // 加载AWS配置
    let config = aws_config::load_from_env().await;
    let client = efs::Client::new(&config);

    println!("选择操作:");
    println!("1. 创建EFS文件系统");
    println!("2. 列出所有EFS文件系统");
    println!("3. 删除EFS文件系统");
    
    let mut choice = String::new();
    io::stdin().read_line(&mut choice).expect("读取输入失败");
    
    match choice.trim() {
        "1" => create_filesystem(&client).await,
        "2" => list_filesystems(&client).await,
        "3" => delete_filesystem(&client).await,
        _ => {
            println!("无效选择");
            Ok(())
        }
    }
}

// 创建EFS文件系统
async fn create_filesystem(client: &efs::Client) -> Result<(), efs::Error> {
    println!("请输入文件系统名称:");
    let mut name = String::new();
    io::stdin().read_line(&mut name).expect("读取输入失败");
    let name = name.trim();

    let response = client
        .create_file_system()
        .performance_mode(PerformanceMode::GeneralPurpose)
        .tags("Name", name)
        .send()
        .await?;

    println!("创建成功! 文件系统ID: {:?}", response.file_system_id);
    Ok(())
}

// 列出所有EFS文件系统
async fn list_filesystems(client: &efs::Client) -> Result<(), efs::Error> {
    let response = client.describe_file_systems().send().await?;

    if let Some(filesystems) = response.file_systems {
        println!("找到 {} 个EFS文件系统:", filesystems.len());
        for fs in filesystems {
            println!(
                "- ID: {} | 名称: {} | 状态: {}",
                fs.file_system_id.unwrap_or_default(),
                fs.name.unwrap_or_default(),
                fs.life_cycle_state.unwrap_or_default()
            );
        }
    }
    Ok(())
}

// 删除EFS文件系统
async fn delete_filesystem(client: &efs::Client) -> Result<(), efs::Error> {
    println!("请输入要删除的文件系统ID:");
    let mut id = String::new();
    io::stdin().read_line(&mut id).expect("读取输入失败");
    let id = id.trim();

    client
        .delete_file_system()
        .file_system_id(id)
        .send()
        .await?;

    println!("文件系统 {} 删除成功", id);
    Ok(())
}

获取帮助

  • GitHub讨论 - 用于想法、RFC和一般问题
  • GitHub问题 - 用于错误报告和功能请求
  • 生成的文档
  • 使用示例

许可证

该项目采用Apache-2.0许可证。


1 回复

Rust AWS SDK EFS插件库的使用:aws-sdk-efs实现Amazon Elastic File System管理

完整示例代码

下面是一个完整的示例,展示了如何使用aws-sdk-efs库来创建、管理和删除EFS资源:

use aws_sdk_efs as efs;
use std::error::Error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // 1. 创建EFS客户端
    let client = create_efs_client().await;
    
    // 2. 创建文件系统
    let file_system_id = match create_file_system(&client).await {
        Ok(id) => id,
        Err(e) => {
            eprintln!("Failed to create file system: {}", e);
            return Err(e.into());
        }
    };
    
    // 3. 等待文件系统变为可用状态
    wait_for_file_system_available(&client, &file_system_id).await?;
    
    // 4. 列出所有文件系统
    list_file_systems(&client).await?;
    
    // 5. 创建挂载目标
    let subnet_id = "subnet-12345678"; // 替换为你的子网ID
    let security_groups = vec!["sg-12345678".to_string()]; // 替换为你的安全组ID
    create_mount_target(&client, &file_system_id, subnet_id, security_groups).await?;
    
    // 6. 创建访问点
    create_access_point(&client, &file_system_id, "my-access-point").await?;
    
    // 7. 使用分页列出所有文件系统
    list_all_file_systems_paginated(&client).await?;
    
    // 8. 清理资源
    delete_file_system(&client, &file_system_id).await?;
    
    Ok(())
}

async fn create_efs_client() -> efs::Client {
    // 从环境加载AWS配置
    let config = aws_config::load_from_env().await;
    efs::Client::new(&config)
}

async fn create_file_system(client: &efs::Client) -> Result<String, efs::Error> {
    let resp = client
        .create_file_system()
        .creation_token("my-unique-token")
        .tags(
            efs::types::Tag::builder()
                .key("Name")
                .value("MyEFS")
                .build()
        )
        .send()
        .await?;

    let file_system_id = resp.file_system_id().unwrap().to_string();
    println!("Created EFS with ID: {}", file_system_id);
    Ok(file_system_id)
}

async fn list_file_systems(client: &efs::Client) -> Result<(), efs::Error> {
    let resp = client.describe_file_systems().send().await?;

    println!("Listing all EFS file systems:");
    for fs in resp.file_systems().unwrap_or_default() {
        println!(
            "ID: {}, Size: {} GB, State: {:?}",
            fs.file_system_id().unwrap_or_default(),
            fs.size_in_bytes().unwrap().value() / (1024 * 1024 * 1024),
            fs.life_cycle_state().unwrap()
        );
    }
    Ok(())
}

async fn wait_for_file_system_available(
    client: &efs::Client,
    file_system_id: &str,
) -> Result<(), efs::Error> {
    use tokio::time::{sleep, Duration};

    println!("Waiting for file system {} to become available...", file_system_id);
    
    loop {
        let resp = client
            .describe_file_systems()
            .file_system_id(file_system_id)
            .send()
            .await?;

        if let Some(fs) = resp.file_systems().and_then(|fs| fs.first()) {
            match fs.life_cycle_state() {
                Some(efs::types::LifeCycleState::Available) => {
                    println!("File system is now available");
                    return Ok(());
                }
                Some(efs::types::LifeCycleState::Creating) => {
                    println!("File system is still creating...");
                }
                _ => {
                    println!("Unexpected state: {:?}", fs.life_cycle_state());
                    return Err(efs::Error::unhandled("Unexpected file system state"));
                }
            }
        }

        sleep(Duration::from_secs(5)).await;
    }
}

async fn create_mount_target(
    client: &efs::Client,
    file_system_id: &str,
    subnet_id: &str,
    security_groups: Vec<String>,
) -> Result<(), efs::Error> {
    println!("Creating mount target for file system {}...", file_system_id);
    
    let resp = client
        .create_mount_target()
        .file_system_id(file_system_id)
        .subnet_id(subnet_id)
        .security_groups(security_groups)
        .send()
        .await?;

    println!(
        "Created mount target with ID: {}",
        resp.mount_target_id().unwrap()
    );
    Ok(())
}

async fn create_access_point(
    client: &efs::Client,
    file_system_id: &str,
    name: &str,
) -> Result<(), efs::Error> {
    println!("Creating access point for file system {}...", file_system_id);
    
    let resp = client
        .create_access_point()
        .file_system_id(file_system_id)
        .posix_user(
            efs::types::PosixUser::builder()
                .uid(1000)
                .gid(1000)
                .build()
        )
        .root_directory(
            efs::types::RootDirectory::builder()
                .path("/data")
                .creation_info(
                    efs::types::CreationInfo::builder()
                        .owner_uid(1000)
                        .owner_gid(1000)
                        .permissions("755")
                        .build()
                )
                .build()
        )
        .tags(
            efs::types::Tag::builder()
                .key("Name")
                .value(name)
                .build()
        )
        .send()
        .await?;

    println!("Created access point with ID: {}", resp.access_point_id().unwrap());
    Ok(())
}

async fn list_all_file_systems_paginated(client: &efs::Client) -> Result<(), efs::Error> {
    println!("Listing all file systems with pagination...");
    
    let mut paginator = client
        .describe_file_systems()
        .into_paginator()
        .send();

    while let Some(page) = paginator.next().await {
        let page = page?;
        for fs in page.file_systems().unwrap_or_default() {
            println!("Found EFS: {:?}", fs.file_system_id());
        }
    }
    Ok(())
}

async fn delete_file_system(client: &efs::Client, file_system_id: &str) -> Result<(), efs::Error> {
    println!("Deleting file system {}...", file_system_id);
    
    // 先删除所有挂载目标
    let mount_targets = client
        .describe_mount_targets()
        .file_system_id(file_system_id)
        .send()
        .await?;

    println!("Found {} mount targets to delete", mount_targets.mount_targets().unwrap_or_default().len());
    
    for target in mount_targets.mount_targets().unwrap_or_default() {
        client
            .delete_mount_target()
            .mount_target_id(target.mount_target_id().unwrap())
            .send()
            .await?;
        println!("Deleted mount target: {}", target.mount_target_id().unwrap());
    }

    // 然后删除文件系统
    client
        .delete_file_system()
        .file_system_id(file_system_id)
        .send()
        .await?;

    println!("Successfully deleted file system {}", file_system_id);
    Ok(())
}

使用说明

  1. 在运行此代码前,请确保:

    • 已配置好AWS凭证
    • 替换代码中的子网ID和安全组ID为你自己的值
    • 已安装Rust和Cargo
  2. 将上述代码保存为main.rs文件,并在Cargo.toml中添加以下依赖:

[dependencies]
aws-config = "0.55"
aws-sdk-efs = "0.25"
tokio = { version = "1", features = ["full"] }
  1. 运行程序:
cargo run

这个完整示例展示了aws-sdk-efs库的主要功能,包括创建文件系统、管理挂载目标和访问点、列出资源以及清理资源等操作。代码中包含了详细的注释和错误处理,可以帮助开发者快速上手使用Rust管理AWS EFS资源。

回到顶部