google_cloud_artifact_registry/
client.rs1use crate::grpc::apiv1::artifact_registry_client::Client as ArtifactRegistryGrpcClient;
2use google_cloud_gax::conn::{ConnectionManager, ConnectionOptions, Environment, Error};
3use google_cloud_token::{NopeTokenSourceProvider, TokenSourceProvider};
4use std::ops::{Deref, DerefMut};
5use std::time::Duration;
6
7use crate::grpc::apiv1::{ARTIFACT_REGISTRY, AUDIENCE, SCOPES};
8
9use google_cloud_googleapis::devtools::artifact_registry::v1::artifact_registry_client::ArtifactRegistryClient;
10use google_cloud_longrunning::autogen::operations_client::OperationsClient;
11
12#[derive(Debug)]
13pub struct ClientConfig {
14 pub artifact_registry_endpoint: String,
15 pub token_source_provider: Box<dyn TokenSourceProvider>,
16 pub timeout: Option<Duration>,
17 pub connect_timeout: Option<Duration>,
18}
19
20#[cfg(feature = "auth")]
21pub use google_cloud_auth;
22
23#[cfg(feature = "auth")]
24impl ClientConfig {
25 pub async fn with_auth(self) -> Result<Self, google_cloud_auth::error::Error> {
26 let ts = google_cloud_auth::token::DefaultTokenSourceProvider::new(Self::auth_config()).await?;
27 Ok(self.with_token_source(ts).await)
28 }
29
30 pub async fn with_credentials(
31 self,
32 credentials: google_cloud_auth::credentials::CredentialsFile,
33 ) -> Result<Self, google_cloud_auth::error::Error> {
34 let ts = google_cloud_auth::token::DefaultTokenSourceProvider::new_with_credentials(
35 Self::auth_config(),
36 Box::new(credentials),
37 )
38 .await?;
39 Ok(self.with_token_source(ts).await)
40 }
41
42 async fn with_token_source(mut self, ts: google_cloud_auth::token::DefaultTokenSourceProvider) -> Self {
43 self.token_source_provider = Box::new(ts);
44 self
45 }
46
47 fn auth_config() -> google_cloud_auth::project::Config<'static> {
48 google_cloud_auth::project::Config::default().with_scopes(&SCOPES)
49 }
50}
51
52impl Default for ClientConfig {
53 fn default() -> Self {
54 Self {
55 artifact_registry_endpoint: ARTIFACT_REGISTRY.to_string(),
56 token_source_provider: Box::new(NopeTokenSourceProvider {}),
57 timeout: Some(Duration::from_secs(30)),
58 connect_timeout: Some(Duration::from_secs(30)),
59 }
60 }
61}
62
63#[derive(Clone)]
64pub struct Client {
65 artifact_registry_client: ArtifactRegistryGrpcClient,
66}
67
68impl Client {
69 pub async fn new(config: ClientConfig) -> Result<Self, Error> {
70 let conn_options = ConnectionOptions {
71 timeout: config.timeout,
72 connect_timeout: config.connect_timeout,
73 };
74 let conn_pool = ConnectionManager::new(
75 1,
76 config.artifact_registry_endpoint,
77 AUDIENCE,
78 &Environment::GoogleCloud(config.token_source_provider),
79 &conn_options,
80 )
81 .await?;
82 let conn = conn_pool.conn();
83 let lro_client = OperationsClient::new(conn_pool.conn()).await.unwrap();
84
85 Ok(Self {
86 artifact_registry_client: ArtifactRegistryGrpcClient::new(ArtifactRegistryClient::new(conn), lro_client),
87 })
88 }
89}
90
91impl Deref for Client {
92 type Target = ArtifactRegistryGrpcClient;
93
94 fn deref(&self) -> &Self::Target {
95 &self.artifact_registry_client
96 }
97}
98
99impl DerefMut for Client {
100 fn deref_mut(&mut self) -> &mut Self::Target {
101 &mut self.artifact_registry_client
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use crate::client::{Client, ClientConfig};
108
109 use google_cloud_googleapis::devtools::artifact_registry::v1::repository::Format;
110 use google_cloud_googleapis::devtools::artifact_registry::v1::{
111 CreateRepositoryRequest, DeleteRepositoryRequest, GetRepositoryRequest, ListRepositoriesRequest, Repository,
112 UpdateRepositoryRequest,
113 };
114 use prost_types::FieldMask;
115 use serial_test::serial;
116 use std::time::{SystemTime, UNIX_EPOCH};
117
118 async fn new_client() -> (Client, String) {
119 let cred = google_cloud_auth::credentials::CredentialsFile::new().await.unwrap();
120 let project = cred.project_id.clone().unwrap();
121 let config = ClientConfig::default().with_credentials(cred).await.unwrap();
122 (Client::new(config).await.unwrap(), project)
123 }
124
125 #[ctor::ctor]
126 fn init() {
127 let _ = tracing_subscriber::fmt().try_init();
128 }
129
130 #[tokio::test]
131 #[serial]
132 async fn test_crud_repository() {
133 let (mut client, project) = new_client().await;
134 let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
135 let repository_id = format!("gcrar{now}");
136
137 let create_request = CreateRepositoryRequest {
139 parent: format!("projects/{project}/locations/us-central1"),
140 repository_id,
141 repository: Some(Repository {
142 name: "".to_string(),
143 format: Format::Docker as i32,
144 description: "test repository".to_string(),
145 labels: Default::default(),
146 create_time: None,
147 update_time: None,
148 kms_key_name: "".to_string(),
149 mode: 0,
150 cleanup_policies: Default::default(),
151 size_bytes: 0,
152 satisfies_pzs: false,
153 cleanup_policy_dry_run: false,
154 format_config: None,
155 mode_config: None,
156 }),
157 };
158 let mut created_repository = client.create_repository(create_request.clone(), None).await.unwrap();
159 let result = created_repository.wait(None).await.unwrap().unwrap();
160 assert_eq!(
161 format!("{}/repositories/{}", create_request.parent, create_request.repository_id),
162 result.name
163 );
164
165 let get_request = GetRepositoryRequest {
167 name: result.name.to_string(),
168 };
169 let get_repository = client.get_repository(get_request.clone(), None).await.unwrap();
170 assert_eq!(get_repository.name, get_request.name);
171
172 let update_request = UpdateRepositoryRequest {
174 repository: Some(Repository {
175 description: "update test".to_string(),
176 ..get_repository.clone()
177 }),
178 update_mask: Some(FieldMask {
179 paths: vec!["description".to_string()],
180 }),
181 };
182 let update_repository = client.update_repository(update_request.clone(), None).await.unwrap();
183 assert_eq!(update_repository.description, update_request.repository.unwrap().description);
184
185 let list_request = ListRepositoriesRequest {
187 parent: create_request.parent.to_string(),
188 page_size: 0,
189 page_token: "".to_string(),
190 };
191 let list_result = client.list_repositories(list_request, None).await.unwrap();
192 assert!(!list_result.repositories.is_empty());
193
194 let delete_request = DeleteRepositoryRequest {
196 name: get_repository.name.to_string(),
197 };
198 client.delete_repository(delete_request, None).await.unwrap();
199 }
200}