pull_and_cache_demo/
pull_and_cache_demo.rs1use docker_image_pusher::{
7 AuthConfig, cli::operation_mode::OperationMode, error::Result,
8 image::image_manager::ImageManager, registry::RegistryClientBuilder,
9};
10use std::env;
11
12#[tokio::main]
13async fn main() -> Result<()> {
14 println!("🚀 Docker Image Pusher - Pull and Cache Demo");
15 println!("==================================================");
16
17 let registry = env::var("DOCKER_REGISTRY")
19 .unwrap_or_else(|_| "https://registry.cn-beijing.aliyuncs.com".to_string());
20 let repository = env::var("DOCKER_REPOSITORY").unwrap_or_else(|_| "yoce/cblt".to_string());
21 let reference = env::var("DOCKER_REFERENCE").unwrap_or_else(|_| "yoce".to_string());
22 let cache_dir = ".cache_demo";
23
24 println!("📥 Configuration:");
25 println!(" Registry: {}", registry);
26 println!(" Repository: {}", repository);
27 println!(" Reference: {}", reference);
28 println!(" Cache Directory: {}", cache_dir);
29 println!();
30
31 println!("🔧 Creating ImageManager...");
33 let mut image_manager = ImageManager::new(Some(cache_dir), true)?;
34 println!("✅ ImageManager created successfully");
35
36 println!("🌐 Building Registry Client...");
38 let client = RegistryClientBuilder::new(registry.to_string())
39 .with_timeout(3600)
40 .with_verbose(true)
41 .build()?;
42 println!("✅ Registry Client built successfully");
43
44 println!("🔐 Attempting authentication...");
46 let auth_token = if let (Ok(username), Ok(password)) =
47 (env::var("DOCKER_USERNAME"), env::var("DOCKER_PASSWORD"))
48 {
49 println!(" Using provided credentials for user: {}", username);
50 let auth_config = AuthConfig::new(username, password);
51 client
52 .authenticate_for_repository(&auth_config, &repository)
53 .await?
54 } else {
55 println!(" No credentials provided, trying anonymous authentication...");
56 let auth = docker_image_pusher::registry::auth::Auth::new();
58 let output = docker_image_pusher::logging::Logger::new(true);
59 auth.authenticate_with_registry(®istry, &repository, None, None, &output)
60 .await?
61 };
62
63 if auth_token.is_some() {
64 println!("✅ Authentication successful");
65 } else {
66 println!("ℹ️ No authentication required");
67 }
68
69 let mode = OperationMode::PullAndCache {
71 repository: repository.to_string(),
72 reference: reference.to_string(),
73 };
74
75 println!("📋 Operation Mode: {}", mode.description());
76 println!();
77
78 println!("🔄 Starting pull and cache operation...");
80 match image_manager
81 .execute_operation(&mode, Some(&client), auth_token.as_deref())
82 .await
83 {
84 Ok(()) => {
85 println!("✅ Pull and cache operation completed successfully!");
86 println!();
87 println!("📂 Image cached to: {}", cache_dir);
88 println!("🔍 You can now inspect the cache contents:");
89 println!(
90 " - Manifests: {}/manifests/{}/{}",
91 cache_dir, repository, reference
92 );
93 println!(" - Blobs: {}/blobs/sha256/", cache_dir);
94 println!(" - Index: {}/index.json", cache_dir);
95 }
96 Err(e) => {
97 eprintln!("❌ Pull and cache operation failed: {}", e);
98 std::process::exit(1);
99 }
100 }
101
102 show_cache_stats(cache_dir).await;
104
105 Ok(())
106}
107
108async fn show_cache_stats(cache_dir: &str) {
109 println!();
110 println!("📊 Cache Statistics:");
111
112 if let Ok(entries) = std::fs::read_dir(format!("{}/blobs/sha256", cache_dir)) {
114 let blob_count = entries.count();
115 println!(" 📦 Cached blobs: {}", blob_count);
116 }
117
118 if let Ok(index_content) = std::fs::read_to_string(format!("{}/index.json", cache_dir)) {
120 if let Ok(index) = serde_json::from_str::<serde_json::Value>(&index_content) {
121 if let Some(obj) = index.as_object() {
122 println!(" 📋 Cached images: {}", obj.len());
123 }
124 }
125 }
126
127 if let Ok(metadata) = std::fs::metadata(cache_dir) {
129 if metadata.is_dir() {
130 println!(" 💾 Cache directory exists and is ready");
131 }
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[tokio::test]
140 async fn test_pull_and_cache_creation() {
141 let result = ImageManager::new(Some(".test_cache"), false);
143 assert!(result.is_ok());
144
145 let _ = std::fs::remove_dir_all(".test_cache");
147 }
148
149 #[tokio::test]
150 async fn test_registry_client_creation() {
151 let result = RegistryClientBuilder::new("https://registry-1.docker.io".to_string())
153 .with_timeout(60)
154 .build();
155 assert!(result.is_ok());
156 }
157
158 #[test]
159 fn test_operation_mode_description() {
160 let mode = OperationMode::PullAndCache {
161 repository: "test/repo".to_string(),
162 reference: "latest".to_string(),
163 };
164 assert_eq!(mode.description(), "Pull from registry and cache locally");
165 }
166}