Skip to content

Commit

Permalink
test(generator/protobuf): add iam/v1 protos (#179)
Browse files Browse the repository at this point in the history
Include the IAM protos to the Rust golden file sources.

These both use external packages (`google.type`) and are used in the
secretmanager service protos.
  • Loading branch information
coryan authored Nov 14, 2024
1 parent cf220b8 commit 08822d4
Show file tree
Hide file tree
Showing 8 changed files with 798 additions and 11 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ members = [
"types",
"gax",
"generator/testdata/rust/openapi/golden",
"generator/testdata/rust/gclient/golden/iam/v1",
"generator/testdata/rust/gclient/golden/type",
"generator/testdata/rust/gclient/golden/secretmanager",
]
44 changes: 33 additions & 11 deletions generator/cmd/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ package main
import (
"errors"
"flag"
"fmt"
"os"
"os/exec"
"path"
"strings"
"testing"

"github.com/googleapis/google-cloud-rust/generator/internal/genclient"
Expand Down Expand Up @@ -74,39 +76,59 @@ func TestRustFromProtobuf(t *testing.T) {
)

type Config struct {
Source string
Name string
Source string
Name string
ExtraOptions map[string]string
}

configs := []Config{
{
Source: "../testdata/rust/gclient/protos",
Name: "secretmanager",
},
{
Source: "../testdata/googleapis/google/type",
Name: "type",
},
{
Source: "../testdata/googleapis/google/iam/v1",
Name: "iam/v1",
ExtraOptions: map[string]string{
"package:gtype": "package=type-golden-gclient,path=../../type,source=google.type",
},
},
{
Source: "../testdata/rust/gclient/protos",
Name: "secretmanager",
ExtraOptions: map[string]string{
"package:iam": "package=iam-v1-golden-gclient,path=../iam/v1,source=google.iam.v1",
},
},
}

for _, config := range configs {
depth := strings.Count(outDir, "/") + strings.Count(config.Name, "/") + 2
toProjectRoot := ".."
for range depth {
toProjectRoot = path.Join(toProjectRoot, "..")
}
popts := &genclient.ParserOptions{
Source: config.Source,
Options: map[string]string{
"googleapis-root": "../testdata/googleapis",
"input-root": "../testdata",
},
}
options := map[string]string{
"package-name-override": strings.Replace(config.Name, "/", "-", -1) + "-golden-gclient",
"package:gax_placeholder": fmt.Sprintf("package=types,path=%s/types,source=google.protobuf", toProjectRoot),
"package:gax": fmt.Sprintf("package=gax,path=%s/gax", toProjectRoot),
}
for k, v := range config.ExtraOptions {
options[k] = v
}
copts := &genclient.CodecOptions{
Language: "rust",
ProjectRoot: projectRoot,
OutDir: path.Join(outDir, config.Name),
TemplateDir: "../templates",
Options: map[string]string{
"package-name-override": config.Name + "-golden-gclient",
"package:gax_placeholder": "package=types,path=../../../../../../types,source=google.protobuf",
"package:gax": "package=gax,path=../../../../../../gax",
},
Options: options,
}
err := Generate("protobuf", popts, copts)
if err != nil {
Expand Down
15 changes: 15 additions & 0 deletions generator/testdata/rust/gclient/golden/iam/v1/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "iam-v1-golden-gclient"
version = "0.1.0"
edition = "2021"

[dependencies]
serde = { version = "1.0.214", features = ["serde_derive"] }
serde_with = "3.11.0"
serde_json = "1.0.132"
time = { version = "0.3.36", features = ["formatting", "parsing"] }
reqwest = { version = "0.12.9", features = ["json"] }
bytes = { version = "1.8.0", features = ["serde"] }
gax = { path = "../../../../../../../gax", package = "gax" }
gax_placeholder = { path = "../../../../../../../types", package = "types" }
gtype = { path = "../../type", package = "type-golden-gclient" }
3 changes: 3 additions & 0 deletions generator/testdata/rust/gclient/golden/iam/v1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# - Rust Client Library


208 changes: 208 additions & 0 deletions generator/testdata/rust/gclient/golden/iam/v1/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#![allow(dead_code)]

use std::sync::Arc;

pub mod model;

#[derive(Clone, Debug)]
pub struct Client {
inner: Arc<ClientRef>,
}

#[derive(Debug)]
struct ClientRef {
http_client: reqwest::Client,
token: String,
}

impl Client {
pub fn new(tok: String) -> Self {
let client = reqwest::Client::builder().build().unwrap();
let inner = ClientRef {
http_client: client,
token: tok,
};
Self {
inner: Arc::new(inner),
}
}

/// API Overview
///
///
/// Manages Identity and Access Management (IAM) policies.
///
/// Any implementation of an API that offers access control features
/// implements the google.iam.v1.IAMPolicy interface.
///
/// ## Data model
///
/// Access control is applied when a principal (user or service account), takes
/// some action on a resource exposed by a service. Resources, identified by
/// URI-like names, are the unit of access control specification. Service
/// implementations can choose the granularity of access control and the
/// supported permissions for their resources.
/// For example one database service may allow access control to be
/// specified only at the Table level, whereas another might allow access control
/// to also be specified at the Column level.
///
/// ## Policy Structure
///
/// See google.iam.v1.Policy
///
/// This is intentionally not a CRUD style API because access control policies
/// are created and deleted implicitly with the resources to which they are
/// attached.
pub fn iam_policy(&self) -> Iampolicy {
Iampolicy {
client: self.clone(),
base_path: "https://iam-meta-api.googleapis.com/".to_string(),
}
}
}

/// API Overview
///
///
/// Manages Identity and Access Management (IAM) policies.
///
/// Any implementation of an API that offers access control features
/// implements the google.iam.v1.IAMPolicy interface.
///
/// ## Data model
///
/// Access control is applied when a principal (user or service account), takes
/// some action on a resource exposed by a service. Resources, identified by
/// URI-like names, are the unit of access control specification. Service
/// implementations can choose the granularity of access control and the
/// supported permissions for their resources.
/// For example one database service may allow access control to be
/// specified only at the Table level, whereas another might allow access control
/// to also be specified at the Column level.
///
/// ## Policy Structure
///
/// See google.iam.v1.Policy
///
/// This is intentionally not a CRUD style API because access control policies
/// are created and deleted implicitly with the resources to which they are
/// attached.
#[derive(Debug)]
pub struct Iampolicy {
client: Client,
base_path: String,
}

impl Iampolicy {
/// Sets the access control policy on the specified resource. Replaces any
/// existing policy.
///
/// Can return `NOT_FOUND`, `INVALID_ARGUMENT`, and `PERMISSION_DENIED` errors.
pub async fn set_iam_policy(
&self,
req: crate::model::SetIamPolicyRequest,
) -> Result<crate::model::Policy, Box<dyn std::error::Error>> {
let query_parameters = [None::<(&str, String)>; 0];
let client = self.client.inner.clone();
let res = client
.http_client
.post(format!(
"{}/v1/{}:setIamPolicy",
self.base_path, req.resource,
))
.query(&[("alt", "json")])
.query(
&query_parameters
.into_iter()
.flatten()
.collect::<Vec<(&str, String)>>(),
)
.bearer_auth(&client.token)
.json(&req)
.send()
.await?;
if !res.status().is_success() {
return Err(
"sorry the api you are looking for is not available, please try again".into(),
);
}
let response = res.json::<crate::model::Policy>().await?;
Ok(response)
}

/// Gets the access control policy for a resource.
/// Returns an empty policy if the resource exists and does not have a policy
/// set.
pub async fn get_iam_policy(
&self,
req: crate::model::GetIamPolicyRequest,
) -> Result<crate::model::Policy, Box<dyn std::error::Error>> {
let query_parameters = [None::<(&str, String)>; 0];
let client = self.client.inner.clone();
let res = client
.http_client
.post(format!(
"{}/v1/{}:getIamPolicy",
self.base_path, req.resource,
))
.query(&[("alt", "json")])
.query(
&query_parameters
.into_iter()
.flatten()
.collect::<Vec<(&str, String)>>(),
)
.bearer_auth(&client.token)
.json(&req)
.send()
.await?;
if !res.status().is_success() {
return Err(
"sorry the api you are looking for is not available, please try again".into(),
);
}
let response = res.json::<crate::model::Policy>().await?;
Ok(response)
}

/// Returns permissions that a caller has on the specified resource.
/// If the resource does not exist, this will return an empty set of
/// permissions, not a `NOT_FOUND` error.
///
/// Note: This operation is designed to be used for building permission-aware
/// UIs and command-line tools, not for authorization checking. This operation
/// may "fail open" without warning.
pub async fn test_iam_permissions(
&self,
req: crate::model::TestIamPermissionsRequest,
) -> Result<crate::model::TestIamPermissionsResponse, Box<dyn std::error::Error>> {
let query_parameters = [None::<(&str, String)>; 0];
let client = self.client.inner.clone();
let res = client
.http_client
.post(format!(
"{}/v1/{}:testIamPermissions",
self.base_path, req.resource,
))
.query(&[("alt", "json")])
.query(
&query_parameters
.into_iter()
.flatten()
.collect::<Vec<(&str, String)>>(),
)
.bearer_auth(&client.token)
.json(&req)
.send()
.await?;
if !res.status().is_success() {
return Err(
"sorry the api you are looking for is not available, please try again".into(),
);
}
let response = res
.json::<crate::model::TestIamPermissionsResponse>()
.await?;
Ok(response)
}
}
Loading

0 comments on commit 08822d4

Please sign in to comment.