use std::sync::{Arc, RwLock};
use wami::provider::AwsProvider;
use wami::service::{GroupService, TenantService, UserService};
use wami::store::memory::InMemoryWamiStore;
use wami::wami::identity::group::requests::CreateGroupRequest;
use wami::wami::identity::user::requests::{CreateUserRequest, ListUsersRequest};
use wami::wami::tenant::model::TenantId;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Tenant Migration ===\n");
let store = Arc::new(RwLock::new(InMemoryWamiStore::default()));
let _provider = Arc::new(AwsProvider::new());
println!("Step 1: Creating source and destination tenants...\n");
let tenant_service = TenantService::new(store.clone(), "root".to_string());
let _old_tenant_id = TenantId::new("old-tenant");
tenant_service
.create_tenant(
"old-tenant".to_string(),
Some("Old Tenant (deprecated)".to_string()),
None,
)
.await?;
println!("✓ Created source tenant: old-tenant");
let _new_tenant_id = TenantId::new("new-tenant");
tenant_service
.create_tenant(
"new-tenant".to_string(),
Some("New Tenant (target)".to_string()),
None,
)
.await?;
println!("✓ Created destination tenant: new-tenant");
println!("\nStep 2: Creating resources in old tenant...\n");
let old_user_service = UserService::new(store.clone(), "old-tenant".to_string());
let old_group_service = GroupService::new(store.clone(), "old-tenant".to_string());
let user_req = CreateUserRequest {
user_name: "bob".to_string(),
path: Some("/users/".to_string()),
permissions_boundary: None,
tags: None,
};
let old_user = old_user_service.create_user(user_req).await?;
println!("✓ Created user in old-tenant:");
println!(" - Name: {}", old_user.user_name);
println!(" - ARN: {}", old_user.arn);
let group_req = CreateGroupRequest {
group_name: "developers".to_string(),
path: Some("/groups/".to_string()),
tags: None,
};
let old_group = old_group_service.create_group(group_req).await?;
println!("\n✓ Created group in old-tenant:");
println!(" - Name: {}", old_group.group_name);
println!(" - ARN: {}", old_group.arn);
old_group_service
.add_user_to_group("developers", "bob")
.await?;
println!("\n✓ Added bob to developers group in old-tenant");
println!("\n\nStep 3: Migrating resources to new tenant...\n");
let new_user_service = UserService::new(store.clone(), "new-tenant".to_string());
let new_group_service = GroupService::new(store.clone(), "new-tenant".to_string());
println!("Migrating user...");
let new_user_req = CreateUserRequest {
user_name: old_user.user_name.clone(),
path: Some(old_user.path.clone()),
permissions_boundary: old_user.permissions_boundary.clone(),
tags: Some(old_user.tags.clone()),
};
let new_user = new_user_service.create_user(new_user_req).await?;
println!("✓ Re-created user in new-tenant:");
println!(" - Old ARN: {}", old_user.arn);
println!(" - New ARN: {}", new_user.arn);
println!("\nMigrating group...");
let new_group_req = CreateGroupRequest {
group_name: old_group.group_name.clone(),
path: Some(old_group.path.clone()),
tags: Some(old_group.tags.clone()),
};
let new_group = new_group_service.create_group(new_group_req).await?;
println!("✓ Re-created group in new-tenant:");
println!(" - Old ARN: {}", old_group.arn);
println!(" - New ARN: {}", new_group.arn);
println!("\nRestoring group membership...");
new_group_service
.add_user_to_group("developers", "bob")
.await?;
println!("✓ Re-added bob to developers group in new-tenant");
println!("\n\nStep 4: Cleaning up old tenant (optional)...\n");
println!("In production, you would:");
println!("- Remove user from old group");
println!("- Delete user from old tenant");
println!("- Delete group from old tenant");
println!("- Audit all resource references");
println!("- Update application configurations");
println!("\n(Cleanup skipped for demonstration purposes)");
println!("\n\nStep 5: Verifying migration...\n");
let (old_users, _, _) = old_user_service
.list_users(ListUsersRequest {
path_prefix: None,
pagination: None,
})
.await?;
println!("Users remaining in old-tenant: {}", old_users.len());
let (new_users, _, _) = new_user_service
.list_users(ListUsersRequest {
path_prefix: None,
pagination: None,
})
.await?;
println!("Users now in new-tenant: {}", new_users.len());
for user in &new_users {
println!(" - {}", user.user_name);
}
println!("\n✅ Example completed successfully!");
println!("Key takeaways:");
println!("- Tenant migration requires re-creating resources in the target tenant");
println!("- ARNs change when resources move between tenants");
println!("- Preserve metadata (tags, paths) during migration");
println!("- Update all references after migration");
println!("- Consider phased migration for large-scale moves");
Ok(())
}