Skip to content

Commit

Permalink
feat: support artifact registry (#207)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminch authored Nov 19, 2023
1 parent 62c4dee commit 58ee24d
Show file tree
Hide file tree
Showing 15 changed files with 6,147 additions and 1 deletion.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ members = [
"storage",
"bigquery",
"spanner-derive",
"artifact-registry",
]
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Providing a high level API for gRPC API like [Google Cloud Go](https://github.co
* [google-cloud-pubsub](./pubsub)
* [google-cloud-storage](./storage)
* [google-cloud-bigquery](./bigquery)
* [google-cloud-artifact-registry](./artifact-registry)

## Example
* [google-cloud-rust-example](https://github.com/yoshidan/google-cloud-rust-example)
Expand Down
49 changes: 49 additions & 0 deletions artifact-registry/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
[package]
name = "google-artifact-registry"
version = "0.1.0"
edition = "2021"
authors = ["yoshidan <[email protected]>"]
repository = "https://github.com/yoshidan/google-cloud-rust/tree/main/artifact-registry"
keywords = ["gcp", "artifacts-registry","googleapis","google-cloud-rust"]
license = "MIT"
readme = "README.md"
description = "Google Cloud Platform Artifact Registry client library."
documentation = "https://docs.rs/google-artifact-registry/latest/google_artifact_registry/"

[dependencies]
google-cloud-token = { version = "0.1.1", path = "../foundation/token" }
reqwest = "0.11.22"

google-cloud-metadata = { optional = true, version = "0.4", path = "../foundation/metadata" }
google-cloud-auth = { optional = true, version = "0.13", path="../foundation/auth", default-features=false }
google-cloud-googleapis = { version="0.11.0", path = "../googleapis", features=["artifact-registry"]}
google-cloud-gax = { version = "0.16.0", path = "../foundation/gax"}
google-cloud-longrunning = { version = "0.16.0", path = "../foundation/longrunning" }
tracing = "0.1.40"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0.50"
base64 = "0.21.5"
once_cell = "1.18.0"
regex = "1.10.2"
sha2 = "0.10.8"
time = "0.3.30"
url = "2.4.1"
prost-types = "0.11.9"

[dev-dependencies]
tokio = { version="1.32", features=["rt-multi-thread"] }
serial_test = "0.9"
tracing-subscriber = { version="0.3.17", features=["env-filter"]}
ctor = "0.1.26"
tokio-util = {version ="0.7", features = ["codec"] }
google-cloud-auth = { path = "../foundation/auth", default-features=false }
uuid = { version = "1.5.0", features = ["v4"] }

[features]
default = ["default-tls", "auth"]
default-tls = ["reqwest/default-tls","google-cloud-auth?/default-tls"]
rustls-tls = ["reqwest/rustls-tls","google-cloud-auth?/rustls-tls"]
trace = []
auth = ["google-cloud-auth", "google-cloud-metadata"]
external-account = ["google-cloud-auth?/external-account"]
299 changes: 299 additions & 0 deletions artifact-registry/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
# google-cloud-artifact-registry

Google Cloud Platform Artifact Registry Client library.

[![crates.io](https://img.shields.io/crates/v/google-cloud-artifact-registry.svg)](https://crates.io/crates/google-cloud-artifact-registry)

* [About Artifact Registry](https://cloud.google.com/artifact-registry/)
* [JSON API Documentation](https://cloud.google.com/artifact-registry/docs/reference/rest)
* [RPC Documentation](https://cloud.google.com/artifact-registry/docs/reference/rpc)

## Installation

```toml
[dependencies]
google-cloud-artifact-registry = "version"
```

## Quickstart

### Authentication
There are two ways to create a client that is authenticated against the google cloud.

#### Automatically

The function `with_auth()` will try and read the credentials from a file specified in the environment variable `GOOGLE_APPLICATION_CREDENTIALS`, `GOOGLE_APPLICATION_CREDENTIALS_JSON` or
from a metadata server.

This is also described in [google-cloud-auth](https://github.com/yoshidan/google-cloud-rust/blob/main/foundation/auth/README.md)

```rust
use google_artifact_registry::client::{Client, ClientConfig};

async fn run() {
let config = ClientConfig::default().with_auth().await.unwrap();
let client = Client::new(config);
}
```

#### Manually

When you can't use the `gcloud` authentication but you have a different way to get your credentials (e.g a different environment variable)
you can parse your own version of the 'credentials-file' and use it like that:

```rust
use google_cloud_auth::credentials::CredentialsFile;
// or google_artifact_registry::client::google_cloud_auth::credentials::CredentialsFile
use google_artifact_registry::client::{Client, ClientConfig};

async fn run(cred: CredentialsFile) {
let config = ClientConfig::default().with_credentials(cred).await.unwrap();
let client = Client::new(config);
}
```

### Usage

#### Repository operations

```rust
async fn run(config: ClientConfig) -> Result<(), Error> {

// Create client.
let mut client = Client::new(config);

// Retry settings
let retry_settings = RetrySetting {
from_millis: 1000,
max_delay: Some(Duration::from_secs(5)),
factor: 1,
take: 5,
..Default::default()
};

// Repository
// create
match client
.create_repository(
CreateRepositoryRequest {
parent: "projects/qovery-gcp-tests/locations/europe-west9".to_string(),
repository_id: "repository-for-documentation".to_string(),
repository: Some(Repository {
name: "repository-for-documentation".to_string(),
format: Format::Docker.into(),
description: "Example repository for documentation".to_string(),
labels: HashMap::from_iter(vec![
("a_label".to_string(), "a_label_value".to_string()),
("another_label".to_string(), "another_label_value".to_string()),
]),
..Default::default()
}),
},
Some(retry_settings.clone()),
)
.await
{
Ok(r) => println!("Created repository {:?}", r),
Err(err) => panic!("err: {:?}", err),
};

// update
match client
.update_repository(
UpdateRepositoryRequest {
repository: Some(Repository {
name: "projects/qovery-gcp-tests/locations/europe-west9/repositories/repository-for-documentation"
.to_string(),
description: "updated description".to_string(),
labels: HashMap::from_iter(vec![(
"yet_another_label".to_string(),
"yet_another_label_value".to_string(),
)]),
..Default::default()
}),
update_mask: Some(FieldMask {
paths: vec!["description".to_string(), "labels".to_string()],
}),
},
Some(retry_settings.clone()),
)
.await
{
Ok(r) => println!("Updated repository {:?}", r),
Err(err) => panic!("err: {:?}", err),
};

// list
match client
.list_repositories(
ListRepositoriesRequest {
parent: "projects/qovery-gcp-tests/locations/europe-west9".to_string(),
page_size: 100,
page_token: "".to_string(),
},
None,
)
.await
{
Ok(repositories) => {
println!("List repositories");
for r in repositories {
println!("- {:?}", r);
}
}
Err(err) => panic!("err: {:?}", err),
}

// get
match client
.get_repository(
GetRepositoryRequest {
name: "projects/qovery-gcp-tests/locations/europe-west9/repositories/repository-for-documentation"
.to_string(),
},
None,
)
.await
{
Ok(r) => println!("Get repository {:?}", r),
Err(err) => panic!("err: {:?}", err),
}

// delete
match client
.delete_repository(
DeleteRepositoryRequest {
name: "projects/qovery-gcp-tests/locations/europe-west9/repositories/repository-for-documentation"
.to_string(),
},
None,
)
.await
{
Ok(r) => println!("Delete repository `repository-for-documentation`"),
Err(err) => panic!("err: {:?}", err),
}

// get repository IAM policy
match client
.get_iam_policy(
GetIamPolicyRequest {
resource: "projects/qovery-gcp-tests/locations/europe-west9/repositories/repository-for-documentation"
.to_string(),
..Default::default()
},
None,
)
.await
{
Ok(policy) => println!("Get IAM Policy for `repository-for-documentation` {:?}", policy),
Err(err) => panic!("err: {:?}", err),
}

// update repository IAM policy
match client
.set_iam_policy(
SetIamPolicyRequest {
resource: "projects/qovery-gcp-tests/locations/europe-west9/repositories/repository-for-documentation"
.to_string(),
policy: Some(Policy {
version: 3,
..Default::default()
}),
update_mask: Some(FieldMask {
paths: vec!["policy.version".to_string()],
}),
},
None,
)
.await
{
Ok(policy) => println!("Update IAM Policy for `repository-for-documentation` {:?}", policy),
Err(err) => panic!("err: {:?}", err),
}

// test IAM repository IAM policy
match client
.test_iam_permissions(
TestIamPermissionsRequest {
resource: "projects/qovery-gcp-tests/locations/europe-west9/repositories/repository-for-documentation"
.to_string(),
..Default::default()
},
None,
)
.await
{
Ok(permissions) => {
println!("Test permissions for `repository-for-documentation`, permissions:");
for p in permissions {
println!("- Permission: {}", p);
}
}
Err(err) => panic!("err: {:?}", err),
}

Ok(())
}
```

#### Docker images operations

```rust
async fn run(config: ClientConfig) -> Result<(), Error> {

// Create client.
let mut client = Client::new(config);

// Retry settings
let retry_settings = RetrySetting {
from_millis: 1000,
max_delay: Some(Duration::from_secs(5)),
factor: 1,
take: 5,
..Default::default()
};

// Docker images
// list
match client
.list_docker_images(
ListDockerImagesRequest {
parent: "projects/qovery-gcp-tests/locations/europe-west9/repositories/repository-for-documentation"
.to_string(),
..Default::default()
},
Some(retry_settings.clone()),
)
.await
{
Ok(images) => {
println!("Docker images for repository `repository-for-documentation`: ");
for image in images {
println!("- Image: {:?}", image);
}
}
Err(e) => {
println!("Error: {}", e);
println!("Error details: {:?}", e.metadata())
}
}

// get
let result = client.get_docker_image(GetDockerImageRequest{
name: "projects/qovery-gcp-tests/locations/europe-west9/repositories/repository-for-documentation/dockerImages/quickstart-image@sha256:2571d3a406da0ecafff96a9c707bc2eba954352dabc85dd918af2e3ec40c263a".to_string(),
}, Some(retry_settings.clone()),).await;

match result {
Ok(d) => {
println!("Image: {:?}", d);
}
Err(e) => {
println!("Error: {}", e);
println!("Error details: {:?}", e.metadata())
}
}

Ok(())
}
```
Loading

0 comments on commit 58ee24d

Please sign in to comment.