From f69b3ea43814eb12df510512c47f760d36ca710a Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Wed, 5 Aug 2020 17:15:08 +0300 Subject: [PATCH 01/22] Initial boilerplate for tasks integration --- google-cloud/Cargo.toml | 5 +- google-cloud/build.rs | 4 + google-cloud/src/lib.rs | 3 + google-cloud/src/tasks/api/google.api.rs | 617 ++++++ .../tasks/api/google.cloud.tasks.v2beta3.rs | 1677 +++++++++++++++++ google-cloud/src/tasks/api/google.iam.v1.rs | 408 ++++ google-cloud/src/tasks/api/google.protobuf.rs | 1 + google-cloud/src/tasks/api/google.r#type.rs | 28 + google-cloud/src/tasks/api/google.rpc.rs | 70 + 9 files changed, 2811 insertions(+), 2 deletions(-) create mode 100644 google-cloud/src/tasks/api/google.api.rs create mode 100644 google-cloud/src/tasks/api/google.cloud.tasks.v2beta3.rs create mode 100644 google-cloud/src/tasks/api/google.iam.v1.rs create mode 100644 google-cloud/src/tasks/api/google.protobuf.rs create mode 100644 google-cloud/src/tasks/api/google.r#type.rs create mode 100644 google-cloud/src/tasks/api/google.rpc.rs diff --git a/google-cloud/Cargo.toml b/google-cloud/Cargo.toml index 31707efc..ed0b70ed 100644 --- a/google-cloud/Cargo.toml +++ b/google-cloud/Cargo.toml @@ -37,10 +37,11 @@ tonic-build = "0.3.0" [features] default = [] -full = ["pubsub", "datastore", "vision", "storage"] -full-derive = ["pubsub", "datastore-derive", "vision", "storage"] +full = ["pubsub", "datastore", "vision", "storage", "tasks"] +full-derive = ["pubsub", "datastore-derive", "vision", "storage", "tasks"] pubsub = [] datastore = [] +tasks = [] datastore-derive = ["datastore", "google-cloud-derive"] vision = [] storage = ["reqwest"] diff --git a/google-cloud/build.rs b/google-cloud/build.rs index 7c7af44a..0e97d345 100644 --- a/google-cloud/build.rs +++ b/google-cloud/build.rs @@ -11,6 +11,10 @@ fn main() -> Result<(), Box> { ["protos/google/cloud/vision/v1/image_annotator.proto"], "src/vision/api", ), + ( + ["protos/google/cloud/tasks/v2beta3/cloudtasks.proto"], + "src/tasks/api" + ) ]; for (proto_files, out_dir) in protos.iter() { diff --git a/google-cloud/src/lib.rs b/google-cloud/src/lib.rs index b40efdc2..4d53c401 100644 --- a/google-cloud/src/lib.rs +++ b/google-cloud/src/lib.rs @@ -18,6 +18,9 @@ pub mod pubsub; /// Cloud Storage bindings. #[cfg(feature = "storage")] pub mod storage; +/// Cloud Tasks bindings. +#[cfg(feature = "tasks")] +pub mod tasks; /// Cloud Vision bindings. #[cfg(feature = "vision")] pub mod vision; diff --git a/google-cloud/src/tasks/api/google.api.rs b/google-cloud/src/tasks/api/google.api.rs new file mode 100644 index 00000000..f3b23dea --- /dev/null +++ b/google-cloud/src/tasks/api/google.api.rs @@ -0,0 +1,617 @@ +/// Defines the HTTP configuration for an API service. It contains a list of +/// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method +/// to one or more HTTP REST API methods. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Http { + /// A list of HTTP configuration rules that apply to individual API methods. + /// + /// **NOTE:** All service configuration rules follow "last one wins" order. + #[prost(message, repeated, tag = "1")] + pub rules: ::std::vec::Vec, + /// When set to true, URL path parameters will be fully URI-decoded except in + /// cases of single segment matches in reserved expansion, where "%2F" will be + /// left encoded. + /// + /// The default behavior is to not decode RFC 6570 reserved characters in multi + /// segment matches. + #[prost(bool, tag = "2")] + pub fully_decode_reserved_expansion: bool, +} +/// # gRPC Transcoding +/// +/// gRPC Transcoding is a feature for mapping between a gRPC method and one or +/// more HTTP REST endpoints. It allows developers to build a single API service +/// that supports both gRPC APIs and REST APIs. Many systems, including [Google +/// APIs](https://github.com/googleapis/googleapis), +/// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC +/// Gateway](https://github.com/grpc-ecosystem/grpc-gateway), +/// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature +/// and use it for large scale production services. +/// +/// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies +/// how different portions of the gRPC request message are mapped to the URL +/// path, URL query parameters, and HTTP request body. It also controls how the +/// gRPC response message is mapped to the HTTP response body. `HttpRule` is +/// typically specified as an `google.api.http` annotation on the gRPC method. +/// +/// Each mapping specifies a URL path template and an HTTP method. The path +/// template may refer to one or more fields in the gRPC request message, as long +/// as each field is a non-repeated field with a primitive (non-message) type. +/// The path template controls how fields of the request message are mapped to +/// the URL path. +/// +/// Example: +/// +/// service Messaging { +/// rpc GetMessage(GetMessageRequest) returns (Message) { +/// option (google.api.http) = { +/// get: "/v1/{name=messages/*}" +/// }; +/// } +/// } +/// message GetMessageRequest { +/// string name = 1; // Mapped to URL path. +/// } +/// message Message { +/// string text = 1; // The resource content. +/// } +/// +/// This enables an HTTP REST to gRPC mapping as below: +/// +/// HTTP | gRPC +/// -----|----- +/// `GET /v1/messages/123456` | `GetMessage(name: "messages/123456")` +/// +/// Any fields in the request message which are not bound by the path template +/// automatically become HTTP query parameters if there is no HTTP request body. +/// For example: +/// +/// service Messaging { +/// rpc GetMessage(GetMessageRequest) returns (Message) { +/// option (google.api.http) = { +/// get:"/v1/messages/{message_id}" +/// }; +/// } +/// } +/// message GetMessageRequest { +/// message SubMessage { +/// string subfield = 1; +/// } +/// string message_id = 1; // Mapped to URL path. +/// int64 revision = 2; // Mapped to URL query parameter `revision`. +/// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`. +/// } +/// +/// This enables a HTTP JSON to RPC mapping as below: +/// +/// HTTP | gRPC +/// -----|----- +/// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | +/// `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: +/// "foo"))` +/// +/// Note that fields which are mapped to URL query parameters must have a +/// primitive type or a repeated primitive type or a non-repeated message type. +/// In the case of a repeated type, the parameter can be repeated in the URL +/// as `...?param=A¶m=B`. In the case of a message type, each field of the +/// message is mapped to a separate parameter, such as +/// `...?foo.a=A&foo.b=B&foo.c=C`. +/// +/// For HTTP methods that allow a request body, the `body` field +/// specifies the mapping. Consider a REST update method on the +/// message resource collection: +/// +/// service Messaging { +/// rpc UpdateMessage(UpdateMessageRequest) returns (Message) { +/// option (google.api.http) = { +/// patch: "/v1/messages/{message_id}" +/// body: "message" +/// }; +/// } +/// } +/// message UpdateMessageRequest { +/// string message_id = 1; // mapped to the URL +/// Message message = 2; // mapped to the body +/// } +/// +/// The following HTTP JSON to RPC mapping is enabled, where the +/// representation of the JSON in the request body is determined by +/// protos JSON encoding: +/// +/// HTTP | gRPC +/// -----|----- +/// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +/// "123456" message { text: "Hi!" })` +/// +/// The special name `*` can be used in the body mapping to define that +/// every field not bound by the path template should be mapped to the +/// request body. This enables the following alternative definition of +/// the update method: +/// +/// service Messaging { +/// rpc UpdateMessage(Message) returns (Message) { +/// option (google.api.http) = { +/// patch: "/v1/messages/{message_id}" +/// body: "*" +/// }; +/// } +/// } +/// message Message { +/// string message_id = 1; +/// string text = 2; +/// } +/// +/// +/// The following HTTP JSON to RPC mapping is enabled: +/// +/// HTTP | gRPC +/// -----|----- +/// `PATCH /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: +/// "123456" text: "Hi!")` +/// +/// Note that when using `*` in the body mapping, it is not possible to +/// have HTTP parameters, as all fields not bound by the path end in +/// the body. This makes this option more rarely used in practice when +/// defining REST APIs. The common usage of `*` is in custom methods +/// which don't use the URL at all for transferring data. +/// +/// It is possible to define multiple HTTP methods for one RPC by using +/// the `additional_bindings` option. Example: +/// +/// service Messaging { +/// rpc GetMessage(GetMessageRequest) returns (Message) { +/// option (google.api.http) = { +/// get: "/v1/messages/{message_id}" +/// additional_bindings { +/// get: "/v1/users/{user_id}/messages/{message_id}" +/// } +/// }; +/// } +/// } +/// message GetMessageRequest { +/// string message_id = 1; +/// string user_id = 2; +/// } +/// +/// This enables the following two alternative HTTP JSON to RPC mappings: +/// +/// HTTP | gRPC +/// -----|----- +/// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")` +/// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: +/// "123456")` +/// +/// ## Rules for HTTP mapping +/// +/// 1. Leaf request fields (recursive expansion nested messages in the request +/// message) are classified into three categories: +/// - Fields referred by the path template. They are passed via the URL path. +/// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They are passed via the HTTP +/// request body. +/// - All other fields are passed via the URL query parameters, and the +/// parameter name is the field path in the request message. A repeated +/// field can be represented as multiple query parameters under the same +/// name. +/// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL query parameter, all fields +/// are passed via URL path and HTTP request body. +/// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP request body, all +/// fields are passed via URL path and URL query parameters. +/// +/// ### Path template syntax +/// +/// Template = "/" Segments [ Verb ] ; +/// Segments = Segment { "/" Segment } ; +/// Segment = "*" | "**" | LITERAL | Variable ; +/// Variable = "{" FieldPath [ "=" Segments ] "}" ; +/// FieldPath = IDENT { "." IDENT } ; +/// Verb = ":" LITERAL ; +/// +/// The syntax `*` matches a single URL path segment. The syntax `**` matches +/// zero or more URL path segments, which must be the last part of the URL path +/// except the `Verb`. +/// +/// The syntax `Variable` matches part of the URL path as specified by its +/// template. A variable template must not contain other variables. If a variable +/// matches a single path segment, its template may be omitted, e.g. `{var}` +/// is equivalent to `{var=*}`. +/// +/// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL` +/// contains any reserved character, such characters should be percent-encoded +/// before the matching. +/// +/// If a variable contains exactly one path segment, such as `"{var}"` or +/// `"{var=*}"`, when such a variable is expanded into a URL path on the client +/// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The +/// server side does the reverse decoding. Such variables show up in the +/// [Discovery +/// Document](https://developers.google.com/discovery/v1/reference/apis) as +/// `{var}`. +/// +/// If a variable contains multiple path segments, such as `"{var=foo/*}"` +/// or `"{var=**}"`, when such a variable is expanded into a URL path on the +/// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. +/// The server side does the reverse decoding, except "%2F" and "%2f" are left +/// unchanged. Such variables show up in the +/// [Discovery +/// Document](https://developers.google.com/discovery/v1/reference/apis) as +/// `{+var}`. +/// +/// ## Using gRPC API Service Configuration +/// +/// gRPC API Service Configuration (service config) is a configuration language +/// for configuring a gRPC service to become a user-facing product. The +/// service config is simply the YAML representation of the `google.api.Service` +/// proto message. +/// +/// As an alternative to annotating your proto file, you can configure gRPC +/// transcoding in your service config YAML files. You do this by specifying a +/// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same +/// effect as the proto annotation. This can be particularly useful if you +/// have a proto that is reused in multiple services. Note that any transcoding +/// specified in the service config will override any matching transcoding +/// configuration in the proto. +/// +/// Example: +/// +/// http: +/// rules: +/// # Selects a gRPC method and applies HttpRule to it. +/// - selector: example.v1.Messaging.GetMessage +/// get: /v1/messages/{message_id}/{sub.subfield} +/// +/// ## Special notes +/// +/// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the +/// proto to JSON conversion must follow the [proto3 +/// specification](https://developers.google.com/protocol-buffers/docs/proto3#json). +/// +/// While the single segment variable follows the semantics of +/// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String +/// Expansion, the multi segment variable **does not** follow RFC 6570 Section +/// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion +/// does not expand special characters like `?` and `#`, which would lead +/// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding +/// for multi segment variables. +/// +/// The path variables **must not** refer to any repeated or mapped field, +/// because client libraries are not capable of handling such variable expansion. +/// +/// The path variables **must not** capture the leading "/" character. The reason +/// is that the most common use case "{var}" does not capture the leading "/" +/// character. For consistency, all path variables must share the same behavior. +/// +/// Repeated message fields must not be mapped to URL query parameters, because +/// no client library can support such complicated mapping. +/// +/// If an API needs to use a JSON array for request or response body, it can map +/// the request or response body to a repeated field. However, some gRPC +/// Transcoding implementations may not support this feature. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct HttpRule { + /// Selects a method to which this rule applies. + /// + /// Refer to [selector][google.api.DocumentationRule.selector] for syntax details. + #[prost(string, tag = "1")] + pub selector: std::string::String, + /// The name of the request field whose value is mapped to the HTTP request + /// body, or `*` for mapping all request fields not captured by the path + /// pattern to the HTTP body, or omitted for not having any HTTP request body. + /// + /// NOTE: the referred field must be present at the top-level of the request + /// message type. + #[prost(string, tag = "7")] + pub body: std::string::String, + /// Optional. The name of the response field whose value is mapped to the HTTP + /// response body. When omitted, the entire response message will be used + /// as the HTTP response body. + /// + /// NOTE: The referred field must be present at the top-level of the response + /// message type. + #[prost(string, tag = "12")] + pub response_body: std::string::String, + /// Additional HTTP bindings for the selector. Nested bindings must + /// not contain an `additional_bindings` field themselves (that is, + /// the nesting may only be one level deep). + #[prost(message, repeated, tag = "11")] + pub additional_bindings: ::std::vec::Vec, + /// Determines the URL pattern is matched by this rules. This pattern can be + /// used with any of the {get|put|post|delete|patch} methods. A custom method + /// can be defined using the 'custom' field. + #[prost(oneof = "http_rule::Pattern", tags = "2, 3, 4, 5, 6, 8")] + pub pattern: ::std::option::Option, +} +pub mod http_rule { + /// Determines the URL pattern is matched by this rules. This pattern can be + /// used with any of the {get|put|post|delete|patch} methods. A custom method + /// can be defined using the 'custom' field. + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Pattern { + /// Maps to HTTP GET. Used for listing and getting information about + /// resources. + #[prost(string, tag = "2")] + Get(std::string::String), + /// Maps to HTTP PUT. Used for replacing a resource. + #[prost(string, tag = "3")] + Put(std::string::String), + /// Maps to HTTP POST. Used for creating a resource or performing an action. + #[prost(string, tag = "4")] + Post(std::string::String), + /// Maps to HTTP DELETE. Used for deleting a resource. + #[prost(string, tag = "5")] + Delete(std::string::String), + /// Maps to HTTP PATCH. Used for updating a resource. + #[prost(string, tag = "6")] + Patch(std::string::String), + /// The custom pattern is used for specifying an HTTP method that is not + /// included in the `pattern` field, such as HEAD, or "*" to leave the + /// HTTP method unspecified for this rule. The wild-card rule is useful + /// for services that provide content to Web (HTML) clients. + #[prost(message, tag = "8")] + Custom(super::CustomHttpPattern), + } +} +/// A custom pattern is used for defining custom HTTP verb. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CustomHttpPattern { + /// The name of this custom HTTP verb. + #[prost(string, tag = "1")] + pub kind: std::string::String, + /// The path matched by this custom verb. + #[prost(string, tag = "2")] + pub path: std::string::String, +} +/// An indicator of the behavior of a given field (for example, that a field +/// is required in requests, or given as output but ignored as input). +/// This **does not** change the behavior in protocol buffers itself; it only +/// denotes the behavior and may affect how API tooling handles the field. +/// +/// Note: This enum **may** receive new values in the future. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum FieldBehavior { + /// Conventional default for enums. Do not use this. + Unspecified = 0, + /// Specifically denotes a field as optional. + /// While all fields in protocol buffers are optional, this may be specified + /// for emphasis if appropriate. + Optional = 1, + /// Denotes a field as required. + /// This indicates that the field **must** be provided as part of the request, + /// and failure to do so will cause an error (usually `INVALID_ARGUMENT`). + Required = 2, + /// Denotes a field as output only. + /// This indicates that the field is provided in responses, but including the + /// field in a request does nothing (the server *must* ignore it and + /// *must not* throw an error as a result of the field's presence). + OutputOnly = 3, + /// Denotes a field as input only. + /// This indicates that the field is provided in requests, and the + /// corresponding field is not included in output. + InputOnly = 4, + /// Denotes a field as immutable. + /// This indicates that the field may be set once in a request to create a + /// resource, but may not be changed thereafter. + Immutable = 5, +} +/// A simple descriptor of a resource type. +/// +/// ResourceDescriptor annotates a resource message (either by means of a +/// protobuf annotation or use in the service config), and associates the +/// resource's schema, the resource type, and the pattern of the resource name. +/// +/// Example: +/// +/// message Topic { +/// // Indicates this message defines a resource schema. +/// // Declares the resource type in the format of {service}/{kind}. +/// // For Kubernetes resources, the format is {api group}/{kind}. +/// option (google.api.resource) = { +/// type: "pubsub.googleapis.com/Topic" +/// name_descriptor: { +/// pattern: "projects/{project}/topics/{topic}" +/// parent_type: "cloudresourcemanager.googleapis.com/Project" +/// parent_name_extractor: "projects/{project}" +/// } +/// }; +/// } +/// +/// The ResourceDescriptor Yaml config will look like: +/// +/// resources: +/// - type: "pubsub.googleapis.com/Topic" +/// name_descriptor: +/// - pattern: "projects/{project}/topics/{topic}" +/// parent_type: "cloudresourcemanager.googleapis.com/Project" +/// parent_name_extractor: "projects/{project}" +/// +/// Sometimes, resources have multiple patterns, typically because they can +/// live under multiple parents. +/// +/// Example: +/// +/// message LogEntry { +/// option (google.api.resource) = { +/// type: "logging.googleapis.com/LogEntry" +/// name_descriptor: { +/// pattern: "projects/{project}/logs/{log}" +/// parent_type: "cloudresourcemanager.googleapis.com/Project" +/// parent_name_extractor: "projects/{project}" +/// } +/// name_descriptor: { +/// pattern: "folders/{folder}/logs/{log}" +/// parent_type: "cloudresourcemanager.googleapis.com/Folder" +/// parent_name_extractor: "folders/{folder}" +/// } +/// name_descriptor: { +/// pattern: "organizations/{organization}/logs/{log}" +/// parent_type: "cloudresourcemanager.googleapis.com/Organization" +/// parent_name_extractor: "organizations/{organization}" +/// } +/// name_descriptor: { +/// pattern: "billingAccounts/{billing_account}/logs/{log}" +/// parent_type: "billing.googleapis.com/BillingAccount" +/// parent_name_extractor: "billingAccounts/{billing_account}" +/// } +/// }; +/// } +/// +/// The ResourceDescriptor Yaml config will look like: +/// +/// resources: +/// - type: 'logging.googleapis.com/LogEntry' +/// name_descriptor: +/// - pattern: "projects/{project}/logs/{log}" +/// parent_type: "cloudresourcemanager.googleapis.com/Project" +/// parent_name_extractor: "projects/{project}" +/// - pattern: "folders/{folder}/logs/{log}" +/// parent_type: "cloudresourcemanager.googleapis.com/Folder" +/// parent_name_extractor: "folders/{folder}" +/// - pattern: "organizations/{organization}/logs/{log}" +/// parent_type: "cloudresourcemanager.googleapis.com/Organization" +/// parent_name_extractor: "organizations/{organization}" +/// - pattern: "billingAccounts/{billing_account}/logs/{log}" +/// parent_type: "billing.googleapis.com/BillingAccount" +/// parent_name_extractor: "billingAccounts/{billing_account}" +/// +/// For flexible resources, the resource name doesn't contain parent names, but +/// the resource itself has parents for policy evaluation. +/// +/// Example: +/// +/// message Shelf { +/// option (google.api.resource) = { +/// type: "library.googleapis.com/Shelf" +/// name_descriptor: { +/// pattern: "shelves/{shelf}" +/// parent_type: "cloudresourcemanager.googleapis.com/Project" +/// } +/// name_descriptor: { +/// pattern: "shelves/{shelf}" +/// parent_type: "cloudresourcemanager.googleapis.com/Folder" +/// } +/// }; +/// } +/// +/// The ResourceDescriptor Yaml config will look like: +/// +/// resources: +/// - type: 'library.googleapis.com/Shelf' +/// name_descriptor: +/// - pattern: "shelves/{shelf}" +/// parent_type: "cloudresourcemanager.googleapis.com/Project" +/// - pattern: "shelves/{shelf}" +/// parent_type: "cloudresourcemanager.googleapis.com/Folder" +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ResourceDescriptor { + /// The resource type. It must be in the format of + /// {service_name}/{resource_type_kind}. The `resource_type_kind` must be + /// singular and must not include version numbers. + /// + /// Example: `storage.googleapis.com/Bucket` + /// + /// The value of the resource_type_kind must follow the regular expression + /// /[A-Za-z][a-zA-Z0-9]+/. It should start with an upper case character and + /// should use PascalCase (UpperCamelCase). The maximum number of + /// characters allowed for the `resource_type_kind` is 100. + #[prost(string, tag = "1")] + pub r#type: std::string::String, + /// Optional. The relative resource name pattern associated with this resource + /// type. The DNS prefix of the full resource name shouldn't be specified here. + /// + /// The path pattern must follow the syntax, which aligns with HTTP binding + /// syntax: + /// + /// Template = Segment { "/" Segment } ; + /// Segment = LITERAL | Variable ; + /// Variable = "{" LITERAL "}" ; + /// + /// Examples: + /// + /// - "projects/{project}/topics/{topic}" + /// - "projects/{project}/knowledgeBases/{knowledge_base}" + /// + /// The components in braces correspond to the IDs for each resource in the + /// hierarchy. It is expected that, if multiple patterns are provided, + /// the same component name (e.g. "project") refers to IDs of the same + /// type of resource. + #[prost(string, repeated, tag = "2")] + pub pattern: ::std::vec::Vec, + /// Optional. The field on the resource that designates the resource name + /// field. If omitted, this is assumed to be "name". + #[prost(string, tag = "3")] + pub name_field: std::string::String, + /// Optional. The historical or future-looking state of the resource pattern. + /// + /// Example: + /// + /// // The InspectTemplate message originally only supported resource + /// // names with organization, and project was added later. + /// message InspectTemplate { + /// option (google.api.resource) = { + /// type: "dlp.googleapis.com/InspectTemplate" + /// pattern: + /// "organizations/{organization}/inspectTemplates/{inspect_template}" + /// pattern: "projects/{project}/inspectTemplates/{inspect_template}" + /// history: ORIGINALLY_SINGLE_PATTERN + /// }; + /// } + #[prost(enumeration = "resource_descriptor::History", tag = "4")] + pub history: i32, + /// The plural name used in the resource name, such as 'projects' for + /// the name of 'projects/{project}'. It is the same concept of the `plural` + /// field in k8s CRD spec + /// https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ + #[prost(string, tag = "5")] + pub plural: std::string::String, + /// The same concept of the `singular` field in k8s CRD spec + /// https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/ + /// Such as "project" for the `resourcemanager.googleapis.com/Project` type. + #[prost(string, tag = "6")] + pub singular: std::string::String, +} +pub mod resource_descriptor { + /// A description of the historical or future-looking state of the + /// resource pattern. + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] + #[repr(i32)] + pub enum History { + /// The "unset" value. + Unspecified = 0, + /// The resource originally had one pattern and launched as such, and + /// additional patterns were added later. + OriginallySinglePattern = 1, + /// The resource has one pattern, but the API owner expects to add more + /// later. (This is the inverse of ORIGINALLY_SINGLE_PATTERN, and prevents + /// that from being necessary once there are multiple patterns.) + FutureMultiPattern = 2, + } +} +/// Defines a proto annotation that describes a string field that refers to +/// an API resource. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ResourceReference { + /// The resource type that the annotated field references. + /// + /// Example: + /// + /// message Subscription { + /// string topic = 2 [(google.api.resource_reference) = { + /// type: "pubsub.googleapis.com/Topic" + /// }]; + /// } + #[prost(string, tag = "1")] + pub r#type: std::string::String, + /// The resource type of a child collection that the annotated field + /// references. This is useful for annotating the `parent` field that + /// doesn't have a fixed resource type. + /// + /// Example: + /// + /// message ListLogEntriesRequest { + /// string parent = 1 [(google.api.resource_reference) = { + /// child_type: "logging.googleapis.com/LogEntry" + /// }; + /// } + #[prost(string, tag = "2")] + pub child_type: std::string::String, +} diff --git a/google-cloud/src/tasks/api/google.cloud.tasks.v2beta3.rs b/google-cloud/src/tasks/api/google.cloud.tasks.v2beta3.rs new file mode 100644 index 00000000..7217921d --- /dev/null +++ b/google-cloud/src/tasks/api/google.cloud.tasks.v2beta3.rs @@ -0,0 +1,1677 @@ +/// HTTP request. +/// +/// The task will be pushed to the worker as an HTTP request. If the worker +/// or the redirected worker acknowledges the task by returning a successful HTTP +/// response code ([`200` - `299`]), the task will removed from the queue. If +/// any other HTTP response code is returned or no response is received, the +/// task will be retried according to the following: +/// +/// * User-specified throttling: [retry configuration][google.cloud.tasks.v2beta3.Queue.retry_config], +/// [rate limits][google.cloud.tasks.v2beta3.Queue.rate_limits], and the [queue's state][google.cloud.tasks.v2beta3.Queue.state]. +/// +/// * System throttling: To prevent the worker from overloading, Cloud Tasks may +/// temporarily reduce the queue's effective rate. User-specified settings +/// will not be changed. +/// +/// System throttling happens because: +/// +/// * Cloud Tasks backs off on all errors. Normally the backoff specified in +/// [rate limits][google.cloud.tasks.v2beta3.Queue.rate_limits] will be used. But if the worker returns +/// `429` (Too Many Requests), `503` (Service Unavailable), or the rate of +/// errors is high, Cloud Tasks will use a higher backoff rate. The retry +/// specified in the `Retry-After` HTTP response header is considered. +/// +/// * To prevent traffic spikes and to smooth sudden large traffic spikes, +/// dispatches ramp up slowly when the queue is newly created or idle and +/// if large numbers of tasks suddenly become available to dispatch (due to +/// spikes in create task rates, the queue being unpaused, or many tasks +/// that are scheduled at the same time). +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct HttpRequest { + /// Required. The full url path that the request will be sent to. + /// + /// This string must begin with either "http://" or "https://". Some examples + /// are: `http://acme.com` and `https://acme.com/sales:8080`. Cloud Tasks will + /// encode some characters for safety and compatibility. The maximum allowed + /// URL length is 2083 characters after encoding. + /// + /// The `Location` header response from a redirect response [`300` - `399`] + /// may be followed. The redirect is not counted as a separate attempt. + #[prost(string, tag = "1")] + pub url: std::string::String, + /// The HTTP method to use for the request. The default is POST. + #[prost(enumeration = "HttpMethod", tag = "2")] + pub http_method: i32, + /// HTTP request headers. + /// + /// This map contains the header field names and values. + /// Headers can be set when the + /// [task is created][google.cloud.tasks.v2beta3.CloudTasks.CreateTask]. + /// + /// These headers represent a subset of the headers that will accompany the + /// task's HTTP request. Some HTTP request headers will be ignored or replaced. + /// + /// A partial list of headers that will be ignored or replaced is: + /// + /// * Host: This will be computed by Cloud Tasks and derived from + /// [HttpRequest.url][google.cloud.tasks.v2beta3.HttpRequest.url]. + /// * Content-Length: This will be computed by Cloud Tasks. + /// * User-Agent: This will be set to `"Google-Cloud-Tasks"`. + /// * X-Google-*: Google use only. + /// * X-AppEngine-*: Google use only. + /// + /// `Content-Type` won't be set by Cloud Tasks. You can explicitly set + /// `Content-Type` to a media type when the + /// [task is created][google.cloud.tasks.v2beta3.CloudTasks.CreateTask]. + /// For example, `Content-Type` can be set to `"application/octet-stream"` or + /// `"application/json"`. + /// + /// Headers which can have multiple values (according to RFC2616) can be + /// specified using comma-separated values. + /// + /// The size of the headers must be less than 80KB. + #[prost(map = "string, string", tag = "3")] + pub headers: ::std::collections::HashMap, + /// HTTP request body. + /// + /// A request body is allowed only if the + /// [HTTP method][google.cloud.tasks.v2beta3.HttpRequest.http_method] is POST, PUT, or PATCH. It is an + /// error to set body on a task with an incompatible [HttpMethod][google.cloud.tasks.v2beta3.HttpMethod]. + #[prost(bytes, tag = "4")] + pub body: std::vec::Vec, + /// The mode for generating an `Authorization` header for HTTP requests. + /// + /// If specified, all `Authorization` headers in the [HttpRequest.headers][google.cloud.tasks.v2beta3.HttpRequest.headers] + /// field will be overridden. + #[prost(oneof = "http_request::AuthorizationHeader", tags = "5, 6")] + pub authorization_header: ::std::option::Option, +} +pub mod http_request { + /// The mode for generating an `Authorization` header for HTTP requests. + /// + /// If specified, all `Authorization` headers in the [HttpRequest.headers][google.cloud.tasks.v2beta3.HttpRequest.headers] + /// field will be overridden. + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum AuthorizationHeader { + /// If specified, an + /// [OAuth token](https://developers.google.com/identity/protocols/OAuth2) + /// will be generated and attached as an `Authorization` header in the HTTP + /// request. + /// + /// This type of authorization should generally only be used when calling + /// Google APIs hosted on *.googleapis.com. + #[prost(message, tag = "5")] + OauthToken(super::OAuthToken), + /// If specified, an + /// [OIDC](https://developers.google.com/identity/protocols/OpenIDConnect) + /// token will be generated and attached as an `Authorization` header in the + /// HTTP request. + /// + /// This type of authorization can be used for many scenarios, including + /// calling Cloud Run, or endpoints where you intend to validate the token + /// yourself. + #[prost(message, tag = "6")] + OidcToken(super::OidcToken), + } +} +/// App Engine HTTP queue. +/// +/// The task will be delivered to the App Engine application hostname +/// specified by its [AppEngineHttpQueue][google.cloud.tasks.v2beta3.AppEngineHttpQueue] and [AppEngineHttpRequest][google.cloud.tasks.v2beta3.AppEngineHttpRequest]. +/// The documentation for [AppEngineHttpRequest][google.cloud.tasks.v2beta3.AppEngineHttpRequest] explains how the +/// task's host URL is constructed. +/// +/// Using [AppEngineHttpQueue][google.cloud.tasks.v2beta3.AppEngineHttpQueue] requires +/// [`appengine.applications.get`](https://cloud.google.com/appengine/docs/admin-api/access-control) +/// Google IAM permission for the project +/// and the following scope: +/// +/// `https://www.googleapis.com/auth/cloud-platform` +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AppEngineHttpQueue { + /// Overrides for the + /// [task-level app_engine_routing][google.cloud.tasks.v2beta3.AppEngineHttpRequest.app_engine_routing]. + /// + /// If set, `app_engine_routing_override` is used for all tasks in + /// the queue, no matter what the setting is for the + /// [task-level app_engine_routing][google.cloud.tasks.v2beta3.AppEngineHttpRequest.app_engine_routing]. + #[prost(message, optional, tag = "1")] + pub app_engine_routing_override: ::std::option::Option, +} +/// App Engine HTTP request. +/// +/// The message defines the HTTP request that is sent to an App Engine app when +/// the task is dispatched. +/// +/// Using [AppEngineHttpRequest][google.cloud.tasks.v2beta3.AppEngineHttpRequest] requires +/// [`appengine.applications.get`](https://cloud.google.com/appengine/docs/admin-api/access-control) +/// Google IAM permission for the project +/// and the following scope: +/// +/// `https://www.googleapis.com/auth/cloud-platform` +/// +/// The task will be delivered to the App Engine app which belongs to the same +/// project as the queue. For more information, see +/// [How Requests are +/// Routed](https://cloud.google.com/appengine/docs/standard/python/how-requests-are-routed) +/// and how routing is affected by +/// [dispatch +/// files](https://cloud.google.com/appengine/docs/python/config/dispatchref). +/// Traffic is encrypted during transport and never leaves Google datacenters. +/// Because this traffic is carried over a communication mechanism internal to +/// Google, you cannot explicitly set the protocol (for example, HTTP or HTTPS). +/// The request to the handler, however, will appear to have used the HTTP +/// protocol. +/// +/// The [AppEngineRouting][google.cloud.tasks.v2beta3.AppEngineRouting] used to construct the URL that the task is +/// delivered to can be set at the queue-level or task-level: +/// +/// * If set, +/// [app_engine_routing_override][google.cloud.tasks.v2beta3.AppEngineHttpQueue.app_engine_routing_override] +/// is used for all tasks in the queue, no matter what the setting +/// is for the +/// [task-level app_engine_routing][google.cloud.tasks.v2beta3.AppEngineHttpRequest.app_engine_routing]. +/// +/// +/// The `url` that the task will be sent to is: +/// +/// * `url =` [host][google.cloud.tasks.v2beta3.AppEngineRouting.host] `+` +/// [relative_uri][google.cloud.tasks.v2beta3.AppEngineHttpRequest.relative_uri] +/// +/// Tasks can be dispatched to secure app handlers, unsecure app handlers, and +/// URIs restricted with +/// [`login: +/// admin`](https://cloud.google.com/appengine/docs/standard/python/config/appref). +/// Because tasks are not run as any user, they cannot be dispatched to URIs +/// restricted with +/// [`login: +/// required`](https://cloud.google.com/appengine/docs/standard/python/config/appref) +/// Task dispatches also do not follow redirects. +/// +/// The task attempt has succeeded if the app's request handler returns an HTTP +/// response code in the range [`200` - `299`]. The task attempt has failed if +/// the app's handler returns a non-2xx response code or Cloud Tasks does +/// not receive response before the [deadline][google.cloud.tasks.v2beta3.Task.dispatch_deadline]. Failed +/// tasks will be retried according to the +/// [retry configuration][google.cloud.tasks.v2beta3.Queue.retry_config]. `503` (Service Unavailable) is +/// considered an App Engine system error instead of an application error and +/// will cause Cloud Tasks' traffic congestion control to temporarily throttle +/// the queue's dispatches. Unlike other types of task targets, a `429` (Too Many +/// Requests) response from an app handler does not cause traffic congestion +/// control to throttle the queue. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AppEngineHttpRequest { + /// The HTTP method to use for the request. The default is POST. + /// + /// The app's request handler for the task's target URL must be able to handle + /// HTTP requests with this http_method, otherwise the task attempt will fail + /// with error code 405 (Method Not Allowed). See + /// [Writing a push task request + /// handler](https://cloud.google.com/appengine/docs/java/taskqueue/push/creating-handlers#writing_a_push_task_request_handler) + /// and the documentation for the request handlers in the language your app is + /// written in e.g. + /// [Python Request + /// Handler](https://cloud.google.com/appengine/docs/python/tools/webapp/requesthandlerclass). + #[prost(enumeration = "HttpMethod", tag = "1")] + pub http_method: i32, + /// Task-level setting for App Engine routing. + /// + /// If set, + /// [app_engine_routing_override][google.cloud.tasks.v2beta3.AppEngineHttpQueue.app_engine_routing_override] + /// is used for all tasks in the queue, no matter what the setting is for the + /// [task-level app_engine_routing][google.cloud.tasks.v2beta3.AppEngineHttpRequest.app_engine_routing]. + #[prost(message, optional, tag = "2")] + pub app_engine_routing: ::std::option::Option, + /// The relative URI. + /// + /// The relative URI must begin with "/" and must be a valid HTTP relative URI. + /// It can contain a path and query string arguments. + /// If the relative URI is empty, then the root path "/" will be used. + /// No spaces are allowed, and the maximum length allowed is 2083 characters. + #[prost(string, tag = "3")] + pub relative_uri: std::string::String, + /// HTTP request headers. + /// + /// This map contains the header field names and values. + /// Headers can be set when the + /// [task is created][google.cloud.tasks.v2beta3.CloudTasks.CreateTask]. + /// Repeated headers are not supported but a header value can contain commas. + /// + /// Cloud Tasks sets some headers to default values: + /// + /// * `User-Agent`: By default, this header is + /// `"AppEngine-Google; (+http://code.google.com/appengine)"`. + /// This header can be modified, but Cloud Tasks will append + /// `"AppEngine-Google; (+http://code.google.com/appengine)"` to the + /// modified `User-Agent`. + /// + /// If the task has a [body][google.cloud.tasks.v2beta3.AppEngineHttpRequest.body], Cloud + /// Tasks sets the following headers: + /// + /// * `Content-Type`: By default, the `Content-Type` header is set to + /// `"application/octet-stream"`. The default can be overridden by explicitly + /// setting `Content-Type` to a particular media type when the + /// [task is created][google.cloud.tasks.v2beta3.CloudTasks.CreateTask]. + /// For example, `Content-Type` can be set to `"application/json"`. + /// * `Content-Length`: This is computed by Cloud Tasks. This value is + /// output only. It cannot be changed. + /// + /// The headers below cannot be set or overridden: + /// + /// * `Host` + /// * `X-Google-*` + /// * `X-AppEngine-*` + /// + /// In addition, Cloud Tasks sets some headers when the task is dispatched, + /// such as headers containing information about the task; see + /// [request + /// headers](https://cloud.google.com/appengine/docs/python/taskqueue/push/creating-handlers#reading_request_headers). + /// These headers are set only when the task is dispatched, so they are not + /// visible when the task is returned in a Cloud Tasks response. + /// + /// Although there is no specific limit for the maximum number of headers or + /// the size, there is a limit on the maximum size of the [Task][google.cloud.tasks.v2beta3.Task]. For more + /// information, see the [CreateTask][google.cloud.tasks.v2beta3.CloudTasks.CreateTask] documentation. + #[prost(map = "string, string", tag = "4")] + pub headers: ::std::collections::HashMap, + /// HTTP request body. + /// + /// A request body is allowed only if the HTTP method is POST or PUT. It is + /// an error to set a body on a task with an incompatible [HttpMethod][google.cloud.tasks.v2beta3.HttpMethod]. + #[prost(bytes, tag = "5")] + pub body: std::vec::Vec, +} +/// App Engine Routing. +/// +/// Defines routing characteristics specific to App Engine - service, version, +/// and instance. +/// +/// For more information about services, versions, and instances see +/// [An Overview of App +/// Engine](https://cloud.google.com/appengine/docs/python/an-overview-of-app-engine), +/// [Microservices Architecture on Google App +/// Engine](https://cloud.google.com/appengine/docs/python/microservices-on-app-engine), +/// [App Engine Standard request +/// routing](https://cloud.google.com/appengine/docs/standard/python/how-requests-are-routed), +/// and [App Engine Flex request +/// routing](https://cloud.google.com/appengine/docs/flexible/python/how-requests-are-routed). +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AppEngineRouting { + /// App service. + /// + /// By default, the task is sent to the service which is the default + /// service when the task is attempted. + /// + /// For some queues or tasks which were created using the App Engine + /// Task Queue API, [host][google.cloud.tasks.v2beta3.AppEngineRouting.host] is not parsable + /// into [service][google.cloud.tasks.v2beta3.AppEngineRouting.service], + /// [version][google.cloud.tasks.v2beta3.AppEngineRouting.version], and + /// [instance][google.cloud.tasks.v2beta3.AppEngineRouting.instance]. For example, some tasks + /// which were created using the App Engine SDK use a custom domain + /// name; custom domains are not parsed by Cloud Tasks. If + /// [host][google.cloud.tasks.v2beta3.AppEngineRouting.host] is not parsable, then + /// [service][google.cloud.tasks.v2beta3.AppEngineRouting.service], + /// [version][google.cloud.tasks.v2beta3.AppEngineRouting.version], and + /// [instance][google.cloud.tasks.v2beta3.AppEngineRouting.instance] are the empty string. + #[prost(string, tag = "1")] + pub service: std::string::String, + /// App version. + /// + /// By default, the task is sent to the version which is the default + /// version when the task is attempted. + /// + /// For some queues or tasks which were created using the App Engine + /// Task Queue API, [host][google.cloud.tasks.v2beta3.AppEngineRouting.host] is not parsable + /// into [service][google.cloud.tasks.v2beta3.AppEngineRouting.service], + /// [version][google.cloud.tasks.v2beta3.AppEngineRouting.version], and + /// [instance][google.cloud.tasks.v2beta3.AppEngineRouting.instance]. For example, some tasks + /// which were created using the App Engine SDK use a custom domain + /// name; custom domains are not parsed by Cloud Tasks. If + /// [host][google.cloud.tasks.v2beta3.AppEngineRouting.host] is not parsable, then + /// [service][google.cloud.tasks.v2beta3.AppEngineRouting.service], + /// [version][google.cloud.tasks.v2beta3.AppEngineRouting.version], and + /// [instance][google.cloud.tasks.v2beta3.AppEngineRouting.instance] are the empty string. + #[prost(string, tag = "2")] + pub version: std::string::String, + /// App instance. + /// + /// By default, the task is sent to an instance which is available when + /// the task is attempted. + /// + /// Requests can only be sent to a specific instance if + /// [manual scaling is used in App Engine + /// Standard](https://cloud.google.com/appengine/docs/python/an-overview-of-app-engine?hl=en_US#scaling_types_and_instance_classes). + /// App Engine Flex does not support instances. For more information, see + /// [App Engine Standard request + /// routing](https://cloud.google.com/appengine/docs/standard/python/how-requests-are-routed) + /// and [App Engine Flex request + /// routing](https://cloud.google.com/appengine/docs/flexible/python/how-requests-are-routed). + #[prost(string, tag = "3")] + pub instance: std::string::String, + /// Output only. The host that the task is sent to. + /// + /// The host is constructed from the domain name of the app associated with + /// the queue's project ID (for example .appspot.com), and the + /// [service][google.cloud.tasks.v2beta3.AppEngineRouting.service], [version][google.cloud.tasks.v2beta3.AppEngineRouting.version], + /// and [instance][google.cloud.tasks.v2beta3.AppEngineRouting.instance]. Tasks which were created using + /// the App Engine SDK might have a custom domain name. + /// + /// For more information, see + /// [How Requests are + /// Routed](https://cloud.google.com/appengine/docs/standard/python/how-requests-are-routed). + #[prost(string, tag = "4")] + pub host: std::string::String, +} +/// Contains information needed for generating an +/// [OAuth token](https://developers.google.com/identity/protocols/OAuth2). +/// This type of authorization should generally only be used when calling Google +/// APIs hosted on *.googleapis.com. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OAuthToken { + /// [Service account email](https://cloud.google.com/iam/docs/service-accounts) + /// to be used for generating OAuth token. + /// The service account must be within the same project as the queue. The + /// caller must have iam.serviceAccounts.actAs permission for the service + /// account. + #[prost(string, tag = "1")] + pub service_account_email: std::string::String, + /// OAuth scope to be used for generating OAuth access token. + /// If not specified, "https://www.googleapis.com/auth/cloud-platform" + /// will be used. + #[prost(string, tag = "2")] + pub scope: std::string::String, +} +/// Contains information needed for generating an +/// [OpenID Connect +/// token](https://developers.google.com/identity/protocols/OpenIDConnect). +/// This type of authorization can be used for many scenarios, including +/// calling Cloud Run, or endpoints where you intend to validate the token +/// yourself. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct OidcToken { + /// [Service account email](https://cloud.google.com/iam/docs/service-accounts) + /// to be used for generating OIDC token. + /// The service account must be within the same project as the queue. The + /// caller must have iam.serviceAccounts.actAs permission for the service + /// account. + #[prost(string, tag = "1")] + pub service_account_email: std::string::String, + /// Audience to be used when generating OIDC token. If not specified, the URI + /// specified in target will be used. + #[prost(string, tag = "2")] + pub audience: std::string::String, +} +/// The HTTP method used to execute the task. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum HttpMethod { + /// HTTP method unspecified + Unspecified = 0, + /// HTTP POST + Post = 1, + /// HTTP GET + Get = 2, + /// HTTP HEAD + Head = 3, + /// HTTP PUT + Put = 4, + /// HTTP DELETE + Delete = 5, + /// HTTP PATCH + Patch = 6, + /// HTTP OPTIONS + Options = 7, +} +/// A queue is a container of related tasks. Queues are configured to manage +/// how those tasks are dispatched. Configurable properties include rate limits, +/// retry options, queue types, and others. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Queue { + /// Caller-specified and required in [CreateQueue][google.cloud.tasks.v2beta3.CloudTasks.CreateQueue], + /// after which it becomes output only. + /// + /// The queue name. + /// + /// The queue name must have the following format: + /// `projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID` + /// + /// * `PROJECT_ID` can contain letters ([A-Za-z]), numbers ([0-9]), + /// hyphens (-), colons (:), or periods (.). + /// For more information, see + /// [Identifying + /// projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects) + /// * `LOCATION_ID` is the canonical ID for the queue's location. + /// The list of available locations can be obtained by calling + /// [ListLocations][google.cloud.location.Locations.ListLocations]. + /// For more information, see https://cloud.google.com/about/locations/. + /// * `QUEUE_ID` can contain letters ([A-Za-z]), numbers ([0-9]), or + /// hyphens (-). The maximum length is 100 characters. + #[prost(string, tag = "1")] + pub name: std::string::String, + /// Rate limits for task dispatches. + /// + /// [rate_limits][google.cloud.tasks.v2beta3.Queue.rate_limits] and [retry_config][google.cloud.tasks.v2beta3.Queue.retry_config] are + /// related because they both control task attempts. However they control task + /// attempts in different ways: + /// + /// * [rate_limits][google.cloud.tasks.v2beta3.Queue.rate_limits] controls the total rate of + /// dispatches from a queue (i.e. all traffic dispatched from the + /// queue, regardless of whether the dispatch is from a first + /// attempt or a retry). + /// * [retry_config][google.cloud.tasks.v2beta3.Queue.retry_config] controls what happens to + /// particular a task after its first attempt fails. That is, + /// [retry_config][google.cloud.tasks.v2beta3.Queue.retry_config] controls task retries (the + /// second attempt, third attempt, etc). + /// + /// The queue's actual dispatch rate is the result of: + /// + /// * Number of tasks in the queue + /// * User-specified throttling: [rate_limits][google.cloud.tasks.v2beta3.Queue.rate_limits], + /// [retry_config][google.cloud.tasks.v2beta3.Queue.retry_config], and the + /// [queue's state][google.cloud.tasks.v2beta3.Queue.state]. + /// * System throttling due to `429` (Too Many Requests) or `503` (Service + /// Unavailable) responses from the worker, high error rates, or to smooth + /// sudden large traffic spikes. + #[prost(message, optional, tag = "4")] + pub rate_limits: ::std::option::Option, + /// Settings that determine the retry behavior. + /// + /// * For tasks created using Cloud Tasks: the queue-level retry settings + /// apply to all tasks in the queue that were created using Cloud Tasks. + /// Retry settings cannot be set on individual tasks. + /// * For tasks created using the App Engine SDK: the queue-level retry + /// settings apply to all tasks in the queue which do not have retry settings + /// explicitly set on the task and were created by the App Engine SDK. See + /// [App Engine + /// documentation](https://cloud.google.com/appengine/docs/standard/python/taskqueue/push/retrying-tasks). + #[prost(message, optional, tag = "5")] + pub retry_config: ::std::option::Option, + /// Output only. The state of the queue. + /// + /// `state` can only be changed by called + /// [PauseQueue][google.cloud.tasks.v2beta3.CloudTasks.PauseQueue], + /// [ResumeQueue][google.cloud.tasks.v2beta3.CloudTasks.ResumeQueue], or uploading + /// [queue.yaml/xml](https://cloud.google.com/appengine/docs/python/config/queueref). + /// [UpdateQueue][google.cloud.tasks.v2beta3.CloudTasks.UpdateQueue] cannot be used to change `state`. + #[prost(enumeration = "queue::State", tag = "6")] + pub state: i32, + /// Output only. The last time this queue was purged. + /// + /// All tasks that were [created][google.cloud.tasks.v2beta3.Task.create_time] before this time + /// were purged. + /// + /// A queue can be purged using [PurgeQueue][google.cloud.tasks.v2beta3.CloudTasks.PurgeQueue], the + /// [App Engine Task Queue SDK, or the Cloud + /// Console](https://cloud.google.com/appengine/docs/standard/python/taskqueue/push/deleting-tasks-and-queues#purging_all_tasks_from_a_queue). + /// + /// Purge time will be truncated to the nearest microsecond. Purge + /// time will be unset if the queue has never been purged. + #[prost(message, optional, tag = "7")] + pub purge_time: ::std::option::Option<::prost_types::Timestamp>, + /// Configuration options for writing logs to + /// [Stackdriver Logging](https://cloud.google.com/logging/docs/). If this + /// field is unset, then no logs are written. + #[prost(message, optional, tag = "10")] + pub stackdriver_logging_config: ::std::option::Option, + #[prost(oneof = "queue::QueueType", tags = "3")] + pub queue_type: ::std::option::Option, +} +pub mod queue { + /// State of the queue. + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] + #[repr(i32)] + pub enum State { + /// Unspecified state. + Unspecified = 0, + /// The queue is running. Tasks can be dispatched. + /// + /// If the queue was created using Cloud Tasks and the queue has + /// had no activity (method calls or task dispatches) for 30 days, + /// the queue may take a few minutes to re-activate. Some method + /// calls may return [NOT_FOUND][google.rpc.Code.NOT_FOUND] and + /// tasks may not be dispatched for a few minutes until the queue + /// has been re-activated. + Running = 1, + /// Tasks are paused by the user. If the queue is paused then Cloud + /// Tasks will stop delivering tasks from it, but more tasks can + /// still be added to it by the user. + Paused = 2, + /// The queue is disabled. + /// + /// A queue becomes `DISABLED` when + /// [queue.yaml](https://cloud.google.com/appengine/docs/python/config/queueref) + /// or + /// [queue.xml](https://cloud.google.com/appengine/docs/standard/java/config/queueref) + /// is uploaded which does not contain the queue. You cannot directly disable + /// a queue. + /// + /// When a queue is disabled, tasks can still be added to a queue + /// but the tasks are not dispatched. + /// + /// To permanently delete this queue and all of its tasks, call + /// [DeleteQueue][google.cloud.tasks.v2beta3.CloudTasks.DeleteQueue]. + Disabled = 3, + } + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum QueueType { + /// [AppEngineHttpQueue][google.cloud.tasks.v2beta3.AppEngineHttpQueue] settings apply only to + /// [App Engine tasks][google.cloud.tasks.v2beta3.AppEngineHttpRequest] in this queue. + /// [Http tasks][google.cloud.tasks.v2beta3.HttpRequest] are not affected by this proto. + #[prost(message, tag = "3")] + AppEngineHttpQueue(super::AppEngineHttpQueue), + } +} +/// Rate limits. +/// +/// This message determines the maximum rate that tasks can be dispatched by a +/// queue, regardless of whether the dispatch is a first task attempt or a retry. +/// +/// Note: The debugging command, [RunTask][google.cloud.tasks.v2beta3.CloudTasks.RunTask], will run a task +/// even if the queue has reached its [RateLimits][google.cloud.tasks.v2beta3.RateLimits]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RateLimits { + /// The maximum rate at which tasks are dispatched from this queue. + /// + /// If unspecified when the queue is created, Cloud Tasks will pick the + /// default. + /// + /// * For [App Engine queues][google.cloud.tasks.v2beta3.AppEngineHttpQueue], the maximum allowed value + /// is 500. + /// + /// + /// This field has the same meaning as + /// [rate in + /// queue.yaml/xml](https://cloud.google.com/appengine/docs/standard/python/config/queueref#rate). + #[prost(double, tag = "1")] + pub max_dispatches_per_second: f64, + /// Output only. The max burst size. + /// + /// Max burst size limits how fast tasks in queue are processed when + /// many tasks are in the queue and the rate is high. This field + /// allows the queue to have a high rate so processing starts shortly + /// after a task is enqueued, but still limits resource usage when + /// many tasks are enqueued in a short period of time. + /// + /// The [token bucket](https://wikipedia.org/wiki/Token_Bucket) + /// algorithm is used to control the rate of task dispatches. Each + /// queue has a token bucket that holds tokens, up to the maximum + /// specified by `max_burst_size`. Each time a task is dispatched, a + /// token is removed from the bucket. Tasks will be dispatched until + /// the queue's bucket runs out of tokens. The bucket will be + /// continuously refilled with new tokens based on + /// [max_dispatches_per_second][google.cloud.tasks.v2beta3.RateLimits.max_dispatches_per_second]. + /// + /// Cloud Tasks will pick the value of `max_burst_size` based on the + /// value of + /// [max_dispatches_per_second][google.cloud.tasks.v2beta3.RateLimits.max_dispatches_per_second]. + /// + /// For App Engine queues that were created or updated using + /// `queue.yaml/xml`, `max_burst_size` is equal to + /// [bucket_size](https://cloud.google.com/appengine/docs/standard/python/config/queueref#bucket_size). + /// Since `max_burst_size` is output only, if + /// [UpdateQueue][google.cloud.tasks.v2beta3.CloudTasks.UpdateQueue] is called on a queue + /// created by `queue.yaml/xml`, `max_burst_size` will be reset based + /// on the value of + /// [max_dispatches_per_second][google.cloud.tasks.v2beta3.RateLimits.max_dispatches_per_second], + /// regardless of whether + /// [max_dispatches_per_second][google.cloud.tasks.v2beta3.RateLimits.max_dispatches_per_second] + /// is updated. + /// + #[prost(int32, tag = "2")] + pub max_burst_size: i32, + /// The maximum number of concurrent tasks that Cloud Tasks allows + /// to be dispatched for this queue. After this threshold has been + /// reached, Cloud Tasks stops dispatching tasks until the number of + /// concurrent requests decreases. + /// + /// If unspecified when the queue is created, Cloud Tasks will pick the + /// default. + /// + /// + /// The maximum allowed value is 5,000. + /// + /// + /// This field has the same meaning as + /// [max_concurrent_requests in + /// queue.yaml/xml](https://cloud.google.com/appengine/docs/standard/python/config/queueref#max_concurrent_requests). + #[prost(int32, tag = "3")] + pub max_concurrent_dispatches: i32, +} +/// Retry config. +/// +/// These settings determine when a failed task attempt is retried. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RetryConfig { + /// Number of attempts per task. + /// + /// Cloud Tasks will attempt the task `max_attempts` times (that is, if the + /// first attempt fails, then there will be `max_attempts - 1` retries). Must + /// be >= -1. + /// + /// If unspecified when the queue is created, Cloud Tasks will pick the + /// default. + /// + /// -1 indicates unlimited attempts. + /// + /// This field has the same meaning as + /// [task_retry_limit in + /// queue.yaml/xml](https://cloud.google.com/appengine/docs/standard/python/config/queueref#retry_parameters). + #[prost(int32, tag = "1")] + pub max_attempts: i32, + /// If positive, `max_retry_duration` specifies the time limit for + /// retrying a failed task, measured from when the task was first + /// attempted. Once `max_retry_duration` time has passed *and* the + /// task has been attempted [max_attempts][google.cloud.tasks.v2beta3.RetryConfig.max_attempts] + /// times, no further attempts will be made and the task will be + /// deleted. + /// + /// If zero, then the task age is unlimited. + /// + /// If unspecified when the queue is created, Cloud Tasks will pick the + /// default. + /// + /// + /// `max_retry_duration` will be truncated to the nearest second. + /// + /// This field has the same meaning as + /// [task_age_limit in + /// queue.yaml/xml](https://cloud.google.com/appengine/docs/standard/python/config/queueref#retry_parameters). + #[prost(message, optional, tag = "2")] + pub max_retry_duration: ::std::option::Option<::prost_types::Duration>, + /// A task will be [scheduled][google.cloud.tasks.v2beta3.Task.schedule_time] for retry between + /// [min_backoff][google.cloud.tasks.v2beta3.RetryConfig.min_backoff] and + /// [max_backoff][google.cloud.tasks.v2beta3.RetryConfig.max_backoff] duration after it fails, + /// if the queue's [RetryConfig][google.cloud.tasks.v2beta3.RetryConfig] specifies that the task should be + /// retried. + /// + /// If unspecified when the queue is created, Cloud Tasks will pick the + /// default. + /// + /// + /// `min_backoff` will be truncated to the nearest second. + /// + /// This field has the same meaning as + /// [min_backoff_seconds in + /// queue.yaml/xml](https://cloud.google.com/appengine/docs/standard/python/config/queueref#retry_parameters). + #[prost(message, optional, tag = "3")] + pub min_backoff: ::std::option::Option<::prost_types::Duration>, + /// A task will be [scheduled][google.cloud.tasks.v2beta3.Task.schedule_time] for retry between + /// [min_backoff][google.cloud.tasks.v2beta3.RetryConfig.min_backoff] and + /// [max_backoff][google.cloud.tasks.v2beta3.RetryConfig.max_backoff] duration after it fails, + /// if the queue's [RetryConfig][google.cloud.tasks.v2beta3.RetryConfig] specifies that the task should be + /// retried. + /// + /// If unspecified when the queue is created, Cloud Tasks will pick the + /// default. + /// + /// + /// `max_backoff` will be truncated to the nearest second. + /// + /// This field has the same meaning as + /// [max_backoff_seconds in + /// queue.yaml/xml](https://cloud.google.com/appengine/docs/standard/python/config/queueref#retry_parameters). + #[prost(message, optional, tag = "4")] + pub max_backoff: ::std::option::Option<::prost_types::Duration>, + /// The time between retries will double `max_doublings` times. + /// + /// A task's retry interval starts at + /// [min_backoff][google.cloud.tasks.v2beta3.RetryConfig.min_backoff], then doubles + /// `max_doublings` times, then increases linearly, and finally + /// retries retries at intervals of + /// [max_backoff][google.cloud.tasks.v2beta3.RetryConfig.max_backoff] up to + /// [max_attempts][google.cloud.tasks.v2beta3.RetryConfig.max_attempts] times. + /// + /// For example, if [min_backoff][google.cloud.tasks.v2beta3.RetryConfig.min_backoff] is 10s, + /// [max_backoff][google.cloud.tasks.v2beta3.RetryConfig.max_backoff] is 300s, and + /// `max_doublings` is 3, then the a task will first be retried in + /// 10s. The retry interval will double three times, and then + /// increase linearly by 2^3 * 10s. Finally, the task will retry at + /// intervals of [max_backoff][google.cloud.tasks.v2beta3.RetryConfig.max_backoff] until the + /// task has been attempted [max_attempts][google.cloud.tasks.v2beta3.RetryConfig.max_attempts] + /// times. Thus, the requests will retry at 10s, 20s, 40s, 80s, 160s, + /// 240s, 300s, 300s, .... + /// + /// If unspecified when the queue is created, Cloud Tasks will pick the + /// default. + /// + /// + /// This field has the same meaning as + /// [max_doublings in + /// queue.yaml/xml](https://cloud.google.com/appengine/docs/standard/python/config/queueref#retry_parameters). + #[prost(int32, tag = "5")] + pub max_doublings: i32, +} +/// Configuration options for writing logs to +/// [Stackdriver Logging](https://cloud.google.com/logging/docs/). +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StackdriverLoggingConfig { + /// Specifies the fraction of operations to write to + /// [Stackdriver Logging](https://cloud.google.com/logging/docs/). + /// This field may contain any value between 0.0 and 1.0, inclusive. + /// 0.0 is the default and means that no operations are logged. + #[prost(double, tag = "1")] + pub sampling_ratio: f64, +} +/// A unit of scheduled work. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Task { + /// Optionally caller-specified in [CreateTask][google.cloud.tasks.v2beta3.CloudTasks.CreateTask]. + /// + /// The task name. + /// + /// The task name must have the following format: + /// `projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID/tasks/TASK_ID` + /// + /// * `PROJECT_ID` can contain letters ([A-Za-z]), numbers ([0-9]), + /// hyphens (-), colons (:), or periods (.). + /// For more information, see + /// [Identifying + /// projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects) + /// * `LOCATION_ID` is the canonical ID for the task's location. + /// The list of available locations can be obtained by calling + /// [ListLocations][google.cloud.location.Locations.ListLocations]. + /// For more information, see https://cloud.google.com/about/locations/. + /// * `QUEUE_ID` can contain letters ([A-Za-z]), numbers ([0-9]), or + /// hyphens (-). The maximum length is 100 characters. + /// * `TASK_ID` can contain only letters ([A-Za-z]), numbers ([0-9]), + /// hyphens (-), or underscores (_). The maximum length is 500 characters. + #[prost(string, tag = "1")] + pub name: std::string::String, + /// The time when the task is scheduled to be attempted. + /// + /// For App Engine queues, this is when the task will be attempted or retried. + /// + /// `schedule_time` will be truncated to the nearest microsecond. + #[prost(message, optional, tag = "4")] + pub schedule_time: ::std::option::Option<::prost_types::Timestamp>, + /// Output only. The time that the task was created. + /// + /// `create_time` will be truncated to the nearest second. + #[prost(message, optional, tag = "5")] + pub create_time: ::std::option::Option<::prost_types::Timestamp>, + /// The deadline for requests sent to the worker. If the worker does not + /// respond by this deadline then the request is cancelled and the attempt + /// is marked as a `DEADLINE_EXCEEDED` failure. Cloud Tasks will retry the + /// task according to the [RetryConfig][google.cloud.tasks.v2beta3.RetryConfig]. + /// + /// Note that when the request is cancelled, Cloud Tasks will stop listing for + /// the response, but whether the worker stops processing depends on the + /// worker. For example, if the worker is stuck, it may not react to cancelled + /// requests. + /// + /// The default and maximum values depend on the type of request: + /// + /// * For [HTTP tasks][google.cloud.tasks.v2beta3.HttpRequest], the default is 10 minutes. The deadline + /// must be in the interval [15 seconds, 30 minutes]. + /// + /// * For [App Engine tasks][google.cloud.tasks.v2beta3.AppEngineHttpRequest], 0 indicates that the + /// request has the default deadline. The default deadline depends on the + /// [scaling + /// type](https://cloud.google.com/appengine/docs/standard/go/how-instances-are-managed#instance_scaling) + /// of the service: 10 minutes for standard apps with automatic scaling, 24 + /// hours for standard apps with manual and basic scaling, and 60 minutes for + /// flex apps. If the request deadline is set, it must be in the interval [15 + /// seconds, 24 hours 15 seconds]. Regardless of the task's + /// `dispatch_deadline`, the app handler will not run for longer than than + /// the service's timeout. We recommend setting the `dispatch_deadline` to + /// at most a few seconds more than the app handler's timeout. For more + /// information see + /// [Timeouts](https://cloud.google.com/tasks/docs/creating-appengine-handlers#timeouts). + /// + /// `dispatch_deadline` will be truncated to the nearest millisecond. The + /// deadline is an approximate deadline. + #[prost(message, optional, tag = "12")] + pub dispatch_deadline: ::std::option::Option<::prost_types::Duration>, + /// Output only. The number of attempts dispatched. + /// + /// This count includes attempts which have been dispatched but haven't + /// received a response. + #[prost(int32, tag = "6")] + pub dispatch_count: i32, + /// Output only. The number of attempts which have received a response. + #[prost(int32, tag = "7")] + pub response_count: i32, + /// Output only. The status of the task's first attempt. + /// + /// Only [dispatch_time][google.cloud.tasks.v2beta3.Attempt.dispatch_time] will be set. + /// The other [Attempt][google.cloud.tasks.v2beta3.Attempt] information is not retained by Cloud Tasks. + #[prost(message, optional, tag = "8")] + pub first_attempt: ::std::option::Option, + /// Output only. The status of the task's last attempt. + #[prost(message, optional, tag = "9")] + pub last_attempt: ::std::option::Option, + /// Output only. The view specifies which subset of the [Task][google.cloud.tasks.v2beta3.Task] has + /// been returned. + #[prost(enumeration = "task::View", tag = "10")] + pub view: i32, + /// Required. The message to send to the worker. + #[prost(oneof = "task::PayloadType", tags = "3, 11")] + pub payload_type: ::std::option::Option, +} +pub mod task { + /// The view specifies a subset of [Task][google.cloud.tasks.v2beta3.Task] data. + /// + /// When a task is returned in a response, not all + /// information is retrieved by default because some data, such as + /// payloads, might be desirable to return only when needed because + /// of its large size or because of the sensitivity of data that it + /// contains. + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] + #[repr(i32)] + pub enum View { + /// Unspecified. Defaults to BASIC. + Unspecified = 0, + /// The basic view omits fields which can be large or can contain + /// sensitive data. + /// + /// This view does not include the + /// [body in AppEngineHttpRequest][google.cloud.tasks.v2beta3.AppEngineHttpRequest.body]. + /// Bodies are desirable to return only when needed, because they + /// can be large and because of the sensitivity of the data that you + /// choose to store in it. + Basic = 1, + /// All information is returned. + /// + /// Authorization for [FULL][google.cloud.tasks.v2beta3.Task.View.FULL] requires + /// `cloudtasks.tasks.fullView` [Google IAM](https://cloud.google.com/iam/) + /// permission on the [Queue][google.cloud.tasks.v2beta3.Queue] resource. + Full = 2, + } + /// Required. The message to send to the worker. + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum PayloadType { + /// HTTP request that is sent to the App Engine app handler. + /// + /// An App Engine task is a task that has [AppEngineHttpRequest][google.cloud.tasks.v2beta3.AppEngineHttpRequest] set. + #[prost(message, tag = "3")] + AppEngineHttpRequest(super::AppEngineHttpRequest), + /// HTTP request that is sent to the task's target. + /// + /// An HTTP task is a task that has [HttpRequest][google.cloud.tasks.v2beta3.HttpRequest] set. + #[prost(message, tag = "11")] + HttpRequest(super::HttpRequest), + } +} +/// The status of a task attempt. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Attempt { + /// Output only. The time that this attempt was scheduled. + /// + /// `schedule_time` will be truncated to the nearest microsecond. + #[prost(message, optional, tag = "1")] + pub schedule_time: ::std::option::Option<::prost_types::Timestamp>, + /// Output only. The time that this attempt was dispatched. + /// + /// `dispatch_time` will be truncated to the nearest microsecond. + #[prost(message, optional, tag = "2")] + pub dispatch_time: ::std::option::Option<::prost_types::Timestamp>, + /// Output only. The time that this attempt response was received. + /// + /// `response_time` will be truncated to the nearest microsecond. + #[prost(message, optional, tag = "3")] + pub response_time: ::std::option::Option<::prost_types::Timestamp>, + /// Output only. The response from the worker for this attempt. + /// + /// If `response_time` is unset, then the task has not been attempted or is + /// currently running and the `response_status` field is meaningless. + #[prost(message, optional, tag = "4")] + pub response_status: ::std::option::Option, +} +/// Request message for [ListQueues][google.cloud.tasks.v2beta3.CloudTasks.ListQueues]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListQueuesRequest { + /// Required. The location name. + /// For example: `projects/PROJECT_ID/locations/LOCATION_ID` + #[prost(string, tag = "1")] + pub parent: std::string::String, + /// `filter` can be used to specify a subset of queues. Any [Queue][google.cloud.tasks.v2beta3.Queue] + /// field can be used as a filter and several operators as supported. + /// For example: `<=, <, >=, >, !=, =, :`. The filter syntax is the same as + /// described in + /// [Stackdriver's Advanced Logs + /// Filters](https://cloud.google.com/logging/docs/view/advanced_filters). + /// + /// Sample filter "state: PAUSED". + /// + /// Note that using filters might cause fewer queues than the + /// requested page_size to be returned. + #[prost(string, tag = "2")] + pub filter: std::string::String, + /// Requested page size. + /// + /// The maximum page size is 9800. If unspecified, the page size will + /// be the maximum. Fewer queues than requested might be returned, + /// even if more queues exist; use the + /// [next_page_token][google.cloud.tasks.v2beta3.ListQueuesResponse.next_page_token] in the + /// response to determine if more queues exist. + #[prost(int32, tag = "3")] + pub page_size: i32, + /// A token identifying the page of results to return. + /// + /// To request the first page results, page_token must be empty. To + /// request the next page of results, page_token must be the value of + /// [next_page_token][google.cloud.tasks.v2beta3.ListQueuesResponse.next_page_token] returned + /// from the previous call to [ListQueues][google.cloud.tasks.v2beta3.CloudTasks.ListQueues] + /// method. It is an error to switch the value of the + /// [filter][google.cloud.tasks.v2beta3.ListQueuesRequest.filter] while iterating through pages. + #[prost(string, tag = "4")] + pub page_token: std::string::String, +} +/// Response message for [ListQueues][google.cloud.tasks.v2beta3.CloudTasks.ListQueues]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListQueuesResponse { + /// The list of queues. + #[prost(message, repeated, tag = "1")] + pub queues: ::std::vec::Vec, + /// A token to retrieve next page of results. + /// + /// To return the next page of results, call + /// [ListQueues][google.cloud.tasks.v2beta3.CloudTasks.ListQueues] with this value as the + /// [page_token][google.cloud.tasks.v2beta3.ListQueuesRequest.page_token]. + /// + /// If the next_page_token is empty, there are no more results. + /// + /// The page token is valid for only 2 hours. + #[prost(string, tag = "2")] + pub next_page_token: std::string::String, +} +/// Request message for [GetQueue][google.cloud.tasks.v2beta3.CloudTasks.GetQueue]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetQueueRequest { + /// Required. The resource name of the queue. For example: + /// `projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID` + #[prost(string, tag = "1")] + pub name: std::string::String, +} +/// Request message for [CreateQueue][google.cloud.tasks.v2beta3.CloudTasks.CreateQueue]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CreateQueueRequest { + /// Required. The location name in which the queue will be created. + /// For example: `projects/PROJECT_ID/locations/LOCATION_ID` + /// + /// The list of allowed locations can be obtained by calling Cloud + /// Tasks' implementation of + /// [ListLocations][google.cloud.location.Locations.ListLocations]. + #[prost(string, tag = "1")] + pub parent: std::string::String, + /// Required. The queue to create. + /// + /// [Queue's name][google.cloud.tasks.v2beta3.Queue.name] cannot be the same as an existing queue. + #[prost(message, optional, tag = "2")] + pub queue: ::std::option::Option, +} +/// Request message for [UpdateQueue][google.cloud.tasks.v2beta3.CloudTasks.UpdateQueue]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpdateQueueRequest { + /// Required. The queue to create or update. + /// + /// The queue's [name][google.cloud.tasks.v2beta3.Queue.name] must be specified. + /// + /// Output only fields cannot be modified using UpdateQueue. + /// Any value specified for an output only field will be ignored. + /// The queue's [name][google.cloud.tasks.v2beta3.Queue.name] cannot be changed. + #[prost(message, optional, tag = "1")] + pub queue: ::std::option::Option, + /// A mask used to specify which fields of the queue are being updated. + /// + /// If empty, then all fields will be updated. + #[prost(message, optional, tag = "2")] + pub update_mask: ::std::option::Option<::prost_types::FieldMask>, +} +/// Request message for [DeleteQueue][google.cloud.tasks.v2beta3.CloudTasks.DeleteQueue]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DeleteQueueRequest { + /// Required. The queue name. For example: + /// `projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID` + #[prost(string, tag = "1")] + pub name: std::string::String, +} +/// Request message for [PurgeQueue][google.cloud.tasks.v2beta3.CloudTasks.PurgeQueue]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PurgeQueueRequest { + /// Required. The queue name. For example: + /// `projects/PROJECT_ID/location/LOCATION_ID/queues/QUEUE_ID` + #[prost(string, tag = "1")] + pub name: std::string::String, +} +/// Request message for [PauseQueue][google.cloud.tasks.v2beta3.CloudTasks.PauseQueue]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PauseQueueRequest { + /// Required. The queue name. For example: + /// `projects/PROJECT_ID/location/LOCATION_ID/queues/QUEUE_ID` + #[prost(string, tag = "1")] + pub name: std::string::String, +} +/// Request message for [ResumeQueue][google.cloud.tasks.v2beta3.CloudTasks.ResumeQueue]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ResumeQueueRequest { + /// Required. The queue name. For example: + /// `projects/PROJECT_ID/location/LOCATION_ID/queues/QUEUE_ID` + #[prost(string, tag = "1")] + pub name: std::string::String, +} +/// Request message for listing tasks using [ListTasks][google.cloud.tasks.v2beta3.CloudTasks.ListTasks]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListTasksRequest { + /// Required. The queue name. For example: + /// `projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID` + #[prost(string, tag = "1")] + pub parent: std::string::String, + /// The response_view specifies which subset of the [Task][google.cloud.tasks.v2beta3.Task] will be + /// returned. + /// + /// By default response_view is [BASIC][google.cloud.tasks.v2beta3.Task.View.BASIC]; not all + /// information is retrieved by default because some data, such as + /// payloads, might be desirable to return only when needed because + /// of its large size or because of the sensitivity of data that it + /// contains. + /// + /// Authorization for [FULL][google.cloud.tasks.v2beta3.Task.View.FULL] requires + /// `cloudtasks.tasks.fullView` [Google IAM](https://cloud.google.com/iam/) + /// permission on the [Task][google.cloud.tasks.v2beta3.Task] resource. + #[prost(enumeration = "task::View", tag = "2")] + pub response_view: i32, + /// Maximum page size. + /// + /// Fewer tasks than requested might be returned, even if more tasks exist; use + /// [next_page_token][google.cloud.tasks.v2beta3.ListTasksResponse.next_page_token] in the response to + /// determine if more tasks exist. + /// + /// The maximum page size is 1000. If unspecified, the page size will be the + /// maximum. + #[prost(int32, tag = "3")] + pub page_size: i32, + /// A token identifying the page of results to return. + /// + /// To request the first page results, page_token must be empty. To + /// request the next page of results, page_token must be the value of + /// [next_page_token][google.cloud.tasks.v2beta3.ListTasksResponse.next_page_token] returned + /// from the previous call to [ListTasks][google.cloud.tasks.v2beta3.CloudTasks.ListTasks] + /// method. + /// + /// The page token is valid for only 2 hours. + #[prost(string, tag = "4")] + pub page_token: std::string::String, +} +/// Response message for listing tasks using [ListTasks][google.cloud.tasks.v2beta3.CloudTasks.ListTasks]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListTasksResponse { + /// The list of tasks. + #[prost(message, repeated, tag = "1")] + pub tasks: ::std::vec::Vec, + /// A token to retrieve next page of results. + /// + /// To return the next page of results, call + /// [ListTasks][google.cloud.tasks.v2beta3.CloudTasks.ListTasks] with this value as the + /// [page_token][google.cloud.tasks.v2beta3.ListTasksRequest.page_token]. + /// + /// If the next_page_token is empty, there are no more results. + #[prost(string, tag = "2")] + pub next_page_token: std::string::String, +} +/// Request message for getting a task using [GetTask][google.cloud.tasks.v2beta3.CloudTasks.GetTask]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetTaskRequest { + /// Required. The task name. For example: + /// `projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID/tasks/TASK_ID` + #[prost(string, tag = "1")] + pub name: std::string::String, + /// The response_view specifies which subset of the [Task][google.cloud.tasks.v2beta3.Task] will be + /// returned. + /// + /// By default response_view is [BASIC][google.cloud.tasks.v2beta3.Task.View.BASIC]; not all + /// information is retrieved by default because some data, such as + /// payloads, might be desirable to return only when needed because + /// of its large size or because of the sensitivity of data that it + /// contains. + /// + /// Authorization for [FULL][google.cloud.tasks.v2beta3.Task.View.FULL] requires + /// `cloudtasks.tasks.fullView` [Google IAM](https://cloud.google.com/iam/) + /// permission on the [Task][google.cloud.tasks.v2beta3.Task] resource. + #[prost(enumeration = "task::View", tag = "2")] + pub response_view: i32, +} +/// Request message for [CreateTask][google.cloud.tasks.v2beta3.CloudTasks.CreateTask]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CreateTaskRequest { + /// Required. The queue name. For example: + /// `projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID` + /// + /// The queue must already exist. + #[prost(string, tag = "1")] + pub parent: std::string::String, + /// Required. The task to add. + /// + /// Task names have the following format: + /// `projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID/tasks/TASK_ID`. + /// The user can optionally specify a task [name][google.cloud.tasks.v2beta3.Task.name]. If a + /// name is not specified then the system will generate a random + /// unique task id, which will be set in the task returned in the + /// [response][google.cloud.tasks.v2beta3.Task.name]. + /// + /// If [schedule_time][google.cloud.tasks.v2beta3.Task.schedule_time] is not set or is in the + /// past then Cloud Tasks will set it to the current time. + /// + /// Task De-duplication: + /// + /// Explicitly specifying a task ID enables task de-duplication. If + /// a task's ID is identical to that of an existing task or a task + /// that was deleted or executed recently then the call will fail + /// with [ALREADY_EXISTS][google.rpc.Code.ALREADY_EXISTS]. + /// If the task's queue was created using Cloud Tasks, then another task with + /// the same name can't be created for ~1hour after the original task was + /// deleted or executed. If the task's queue was created using queue.yaml or + /// queue.xml, then another task with the same name can't be created + /// for ~9days after the original task was deleted or executed. + /// + /// Because there is an extra lookup cost to identify duplicate task + /// names, these [CreateTask][google.cloud.tasks.v2beta3.CloudTasks.CreateTask] calls have significantly + /// increased latency. Using hashed strings for the task id or for + /// the prefix of the task id is recommended. Choosing task ids that + /// are sequential or have sequential prefixes, for example using a + /// timestamp, causes an increase in latency and error rates in all + /// task commands. The infrastructure relies on an approximately + /// uniform distribution of task ids to store and serve tasks + /// efficiently. + #[prost(message, optional, tag = "2")] + pub task: ::std::option::Option, + /// The response_view specifies which subset of the [Task][google.cloud.tasks.v2beta3.Task] will be + /// returned. + /// + /// By default response_view is [BASIC][google.cloud.tasks.v2beta3.Task.View.BASIC]; not all + /// information is retrieved by default because some data, such as + /// payloads, might be desirable to return only when needed because + /// of its large size or because of the sensitivity of data that it + /// contains. + /// + /// Authorization for [FULL][google.cloud.tasks.v2beta3.Task.View.FULL] requires + /// `cloudtasks.tasks.fullView` [Google IAM](https://cloud.google.com/iam/) + /// permission on the [Task][google.cloud.tasks.v2beta3.Task] resource. + #[prost(enumeration = "task::View", tag = "3")] + pub response_view: i32, +} +/// Request message for deleting a task using +/// [DeleteTask][google.cloud.tasks.v2beta3.CloudTasks.DeleteTask]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DeleteTaskRequest { + /// Required. The task name. For example: + /// `projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID/tasks/TASK_ID` + #[prost(string, tag = "1")] + pub name: std::string::String, +} +/// Request message for forcing a task to run now using +/// [RunTask][google.cloud.tasks.v2beta3.CloudTasks.RunTask]. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RunTaskRequest { + /// Required. The task name. For example: + /// `projects/PROJECT_ID/locations/LOCATION_ID/queues/QUEUE_ID/tasks/TASK_ID` + #[prost(string, tag = "1")] + pub name: std::string::String, + /// The response_view specifies which subset of the [Task][google.cloud.tasks.v2beta3.Task] will be + /// returned. + /// + /// By default response_view is [BASIC][google.cloud.tasks.v2beta3.Task.View.BASIC]; not all + /// information is retrieved by default because some data, such as + /// payloads, might be desirable to return only when needed because + /// of its large size or because of the sensitivity of data that it + /// contains. + /// + /// Authorization for [FULL][google.cloud.tasks.v2beta3.Task.View.FULL] requires + /// `cloudtasks.tasks.fullView` [Google IAM](https://cloud.google.com/iam/) + /// permission on the [Task][google.cloud.tasks.v2beta3.Task] resource. + #[prost(enumeration = "task::View", tag = "2")] + pub response_view: i32, +} +#[doc = r" Generated client implementations."] +pub mod cloud_tasks_client { + #![allow(unused_variables, dead_code, missing_docs)] + use tonic::codegen::*; + #[doc = " Cloud Tasks allows developers to manage the execution of background"] + #[doc = " work in their applications."] + pub struct CloudTasksClient { + inner: tonic::client::Grpc, + } + impl CloudTasksClient { + #[doc = r" Attempt to create a new client by connecting to a given endpoint."] + pub async fn connect(dst: D) -> Result + where + D: std::convert::TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl CloudTasksClient + where + T: tonic::client::GrpcService, + T::ResponseBody: Body + HttpBody + Send + 'static, + T::Error: Into, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_interceptor(inner: T, interceptor: impl Into) -> Self { + let inner = tonic::client::Grpc::with_interceptor(inner, interceptor); + Self { inner } + } + #[doc = " Lists queues."] + #[doc = ""] + #[doc = " Queues are returned in lexicographical order."] + pub async fn list_queues( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/ListQueues", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Gets a queue."] + pub async fn get_queue( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/GetQueue", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Creates a queue."] + #[doc = ""] + #[doc = " Queues created with this method allow tasks to live for a maximum of 31"] + #[doc = " days. After a task is 31 days old, the task will be deleted regardless of whether"] + #[doc = " it was dispatched or not."] + #[doc = ""] + #[doc = " WARNING: Using this method may have unintended side effects if you are"] + #[doc = " using an App Engine `queue.yaml` or `queue.xml` file to manage your queues."] + #[doc = " Read"] + #[doc = " [Overview of Queue Management and"] + #[doc = " queue.yaml](https://cloud.google.com/tasks/docs/queue-yaml) before using"] + #[doc = " this method."] + pub async fn create_queue( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/CreateQueue", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Updates a queue."] + #[doc = ""] + #[doc = " This method creates the queue if it does not exist and updates"] + #[doc = " the queue if it does exist."] + #[doc = ""] + #[doc = " Queues created with this method allow tasks to live for a maximum of 31"] + #[doc = " days. After a task is 31 days old, the task will be deleted regardless of whether"] + #[doc = " it was dispatched or not."] + #[doc = ""] + #[doc = " WARNING: Using this method may have unintended side effects if you are"] + #[doc = " using an App Engine `queue.yaml` or `queue.xml` file to manage your queues."] + #[doc = " Read"] + #[doc = " [Overview of Queue Management and"] + #[doc = " queue.yaml](https://cloud.google.com/tasks/docs/queue-yaml) before using"] + #[doc = " this method."] + pub async fn update_queue( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/UpdateQueue", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Deletes a queue."] + #[doc = ""] + #[doc = " This command will delete the queue even if it has tasks in it."] + #[doc = ""] + #[doc = " Note: If you delete a queue, a queue with the same name can't be created"] + #[doc = " for 7 days."] + #[doc = ""] + #[doc = " WARNING: Using this method may have unintended side effects if you are"] + #[doc = " using an App Engine `queue.yaml` or `queue.xml` file to manage your queues."] + #[doc = " Read"] + #[doc = " [Overview of Queue Management and"] + #[doc = " queue.yaml](https://cloud.google.com/tasks/docs/queue-yaml) before using"] + #[doc = " this method."] + pub async fn delete_queue( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/DeleteQueue", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Purges a queue by deleting all of its tasks."] + #[doc = ""] + #[doc = " All tasks created before this method is called are permanently deleted."] + #[doc = ""] + #[doc = " Purge operations can take up to one minute to take effect. Tasks"] + #[doc = " might be dispatched before the purge takes effect. A purge is irreversible."] + pub async fn purge_queue( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/PurgeQueue", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Pauses the queue."] + #[doc = ""] + #[doc = " If a queue is paused then the system will stop dispatching tasks"] + #[doc = " until the queue is resumed via"] + #[doc = " [ResumeQueue][google.cloud.tasks.v2beta3.CloudTasks.ResumeQueue]. Tasks can still be added"] + #[doc = " when the queue is paused. A queue is paused if its"] + #[doc = " [state][google.cloud.tasks.v2beta3.Queue.state] is [PAUSED][google.cloud.tasks.v2beta3.Queue.State.PAUSED]."] + pub async fn pause_queue( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/PauseQueue", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Resume a queue."] + #[doc = ""] + #[doc = " This method resumes a queue after it has been"] + #[doc = " [PAUSED][google.cloud.tasks.v2beta3.Queue.State.PAUSED] or"] + #[doc = " [DISABLED][google.cloud.tasks.v2beta3.Queue.State.DISABLED]. The state of a queue is stored"] + #[doc = " in the queue's [state][google.cloud.tasks.v2beta3.Queue.state]; after calling this method it"] + #[doc = " will be set to [RUNNING][google.cloud.tasks.v2beta3.Queue.State.RUNNING]."] + #[doc = ""] + #[doc = " WARNING: Resuming many high-QPS queues at the same time can"] + #[doc = " lead to target overloading. If you are resuming high-QPS"] + #[doc = " queues, follow the 500/50/5 pattern described in"] + #[doc = " [Managing Cloud Tasks Scaling"] + #[doc = " Risks](https://cloud.google.com/tasks/docs/manage-cloud-task-scaling)."] + pub async fn resume_queue( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/ResumeQueue", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Gets the access control policy for a [Queue][google.cloud.tasks.v2beta3.Queue]."] + #[doc = " Returns an empty policy if the resource exists and does not have a policy"] + #[doc = " set."] + #[doc = ""] + #[doc = " Authorization requires the following"] + #[doc = " [Google IAM](https://cloud.google.com/iam) permission on the specified"] + #[doc = " resource parent:"] + #[doc = ""] + #[doc = " * `cloudtasks.queues.getIamPolicy`"] + pub async fn get_iam_policy( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/GetIamPolicy", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Sets the access control policy for a [Queue][google.cloud.tasks.v2beta3.Queue]. Replaces any existing"] + #[doc = " policy."] + #[doc = ""] + #[doc = " Note: The Cloud Console does not check queue-level IAM permissions yet."] + #[doc = " Project-level permissions are required to use the Cloud Console."] + #[doc = ""] + #[doc = " Authorization requires the following"] + #[doc = " [Google IAM](https://cloud.google.com/iam) permission on the specified"] + #[doc = " resource parent:"] + #[doc = ""] + #[doc = " * `cloudtasks.queues.setIamPolicy`"] + pub async fn set_iam_policy( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/SetIamPolicy", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Returns permissions that a caller has on a [Queue][google.cloud.tasks.v2beta3.Queue]."] + #[doc = " If the resource does not exist, this will return an empty set of"] + #[doc = " permissions, not a [NOT_FOUND][google.rpc.Code.NOT_FOUND] error."] + #[doc = ""] + #[doc = " Note: This operation is designed to be used for building permission-aware"] + #[doc = " UIs and command-line tools, not for authorization checking. This operation"] + #[doc = " may \"fail open\" without warning."] + pub async fn test_iam_permissions( + &mut self, + request: impl tonic::IntoRequest< + super::super::super::super::iam::v1::TestIamPermissionsRequest, + >, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/TestIamPermissions", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Lists the tasks in a queue."] + #[doc = ""] + #[doc = " By default, only the [BASIC][google.cloud.tasks.v2beta3.Task.View.BASIC] view is retrieved"] + #[doc = " due to performance considerations;"] + #[doc = " [response_view][google.cloud.tasks.v2beta3.ListTasksRequest.response_view] controls the"] + #[doc = " subset of information which is returned."] + #[doc = ""] + #[doc = " The tasks may be returned in any order. The ordering may change at any"] + #[doc = " time."] + pub async fn list_tasks( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/ListTasks", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Gets a task."] + pub async fn get_task( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/GetTask", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Creates a task and adds it to a queue."] + #[doc = ""] + #[doc = " Tasks cannot be updated after creation; there is no UpdateTask command."] + #[doc = ""] + #[doc = " * The maximum task size is 100KB."] + pub async fn create_task( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/CreateTask", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Deletes a task."] + #[doc = ""] + #[doc = " A task can be deleted if it is scheduled or dispatched. A task"] + #[doc = " cannot be deleted if it has executed successfully or permanently"] + #[doc = " failed."] + pub async fn delete_task( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/DeleteTask", + ); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Forces a task to run now."] + #[doc = ""] + #[doc = " When this method is called, Cloud Tasks will dispatch the task, even if"] + #[doc = " the task is already running, the queue has reached its [RateLimits][google.cloud.tasks.v2beta3.RateLimits] or"] + #[doc = " is [PAUSED][google.cloud.tasks.v2beta3.Queue.State.PAUSED]."] + #[doc = ""] + #[doc = " This command is meant to be used for manual debugging. For"] + #[doc = " example, [RunTask][google.cloud.tasks.v2beta3.CloudTasks.RunTask] can be used to retry a failed"] + #[doc = " task after a fix has been made or to manually force a task to be"] + #[doc = " dispatched now."] + #[doc = ""] + #[doc = " The dispatched task is returned. That is, the task that is returned"] + #[doc = " contains the [status][Task.status] after the task is dispatched but"] + #[doc = " before the task is received by its target."] + #[doc = ""] + #[doc = " If Cloud Tasks receives a successful response from the task's"] + #[doc = " target, then the task will be deleted; otherwise the task's"] + #[doc = " [schedule_time][google.cloud.tasks.v2beta3.Task.schedule_time] will be reset to the time that"] + #[doc = " [RunTask][google.cloud.tasks.v2beta3.CloudTasks.RunTask] was called plus the retry delay specified"] + #[doc = " in the queue's [RetryConfig][google.cloud.tasks.v2beta3.RetryConfig]."] + #[doc = ""] + #[doc = " [RunTask][google.cloud.tasks.v2beta3.CloudTasks.RunTask] returns"] + #[doc = " [NOT_FOUND][google.rpc.Code.NOT_FOUND] when it is called on a"] + #[doc = " task that has already succeeded or permanently failed."] + pub async fn run_task( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/google.cloud.tasks.v2beta3.CloudTasks/RunTask", + ); + self.inner.unary(request.into_request(), path, codec).await + } + } + impl Clone for CloudTasksClient { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } + } + impl std::fmt::Debug for CloudTasksClient { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "CloudTasksClient {{ ... }}") + } + } +} diff --git a/google-cloud/src/tasks/api/google.iam.v1.rs b/google-cloud/src/tasks/api/google.iam.v1.rs new file mode 100644 index 00000000..83a9b47d --- /dev/null +++ b/google-cloud/src/tasks/api/google.iam.v1.rs @@ -0,0 +1,408 @@ +/// Encapsulates settings provided to GetIamPolicy. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetPolicyOptions { + /// Optional. The policy format version to be returned. + /// + /// Valid values are 0, 1, and 3. Requests specifying an invalid value will be + /// rejected. + /// + /// Requests for policies with any conditional bindings must specify version 3. + /// Policies without any conditional bindings may specify any valid value or + /// leave the field unset. + #[prost(int32, tag = "1")] + pub requested_policy_version: i32, +} +/// Defines an Identity and Access Management (IAM) policy. It is used to +/// specify access control policies for Cloud Platform resources. +/// +/// +/// A `Policy` is a collection of `bindings`. A `binding` binds one or more +/// `members` to a single `role`. Members can be user accounts, service accounts, +/// Google groups, and domains (such as G Suite). A `role` is a named list of +/// permissions (defined by IAM or configured by users). A `binding` can +/// optionally specify a `condition`, which is a logic expression that further +/// constrains the role binding based on attributes about the request and/or +/// target resource. +/// +/// **JSON Example** +/// +/// { +/// "bindings": [ +/// { +/// "role": "roles/resourcemanager.organizationAdmin", +/// "members": [ +/// "user:mike@example.com", +/// "group:admins@example.com", +/// "domain:google.com", +/// "serviceAccount:my-project-id@appspot.gserviceaccount.com" +/// ] +/// }, +/// { +/// "role": "roles/resourcemanager.organizationViewer", +/// "members": ["user:eve@example.com"], +/// "condition": { +/// "title": "expirable access", +/// "description": "Does not grant access after Sep 2020", +/// "expression": "request.time < +/// timestamp('2020-10-01T00:00:00.000Z')", +/// } +/// } +/// ] +/// } +/// +/// **YAML Example** +/// +/// bindings: +/// - members: +/// - user:mike@example.com +/// - group:admins@example.com +/// - domain:google.com +/// - serviceAccount:my-project-id@appspot.gserviceaccount.com +/// role: roles/resourcemanager.organizationAdmin +/// - members: +/// - user:eve@example.com +/// role: roles/resourcemanager.organizationViewer +/// condition: +/// title: expirable access +/// description: Does not grant access after Sep 2020 +/// expression: request.time < timestamp('2020-10-01T00:00:00.000Z') +/// +/// For a description of IAM and its features, see the +/// [IAM developer's guide](https://cloud.google.com/iam/docs). +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Policy { + /// Specifies the format of the policy. + /// + /// Valid values are 0, 1, and 3. Requests specifying an invalid value will be + /// rejected. + /// + /// Operations affecting conditional bindings must specify version 3. This can + /// be either setting a conditional policy, modifying a conditional binding, + /// or removing a conditional binding from the stored conditional policy. + /// Operations on non-conditional policies may specify any valid value or + /// leave the field unset. + /// + /// If no etag is provided in the call to `setIamPolicy`, any version + /// compliance checks on the incoming and/or stored policy is skipped. + #[prost(int32, tag = "1")] + pub version: i32, + /// Associates a list of `members` to a `role`. Optionally may specify a + /// `condition` that determines when binding is in effect. + /// `bindings` with no members will result in an error. + #[prost(message, repeated, tag = "4")] + pub bindings: ::std::vec::Vec, + /// `etag` is used for optimistic concurrency control as a way to help + /// prevent simultaneous updates of a policy from overwriting each other. + /// It is strongly suggested that systems make use of the `etag` in the + /// read-modify-write cycle to perform policy updates in order to avoid race + /// conditions: An `etag` is returned in the response to `getIamPolicy`, and + /// systems are expected to put that etag in the request to `setIamPolicy` to + /// ensure that their change will be applied to the same version of the policy. + /// + /// If no `etag` is provided in the call to `setIamPolicy`, then the existing + /// policy is overwritten. Due to blind-set semantics of an etag-less policy, + /// 'setIamPolicy' will not fail even if either of incoming or stored policy + /// does not meet the version requirements. + #[prost(bytes, tag = "3")] + pub etag: std::vec::Vec, +} +/// Associates `members` with a `role`. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Binding { + /// Role that is assigned to `members`. + /// For example, `roles/viewer`, `roles/editor`, or `roles/owner`. + #[prost(string, tag = "1")] + pub role: std::string::String, + /// Specifies the identities requesting access for a Cloud Platform resource. + /// `members` can have the following values: + /// + /// * `allUsers`: A special identifier that represents anyone who is + /// on the internet; with or without a Google account. + /// + /// * `allAuthenticatedUsers`: A special identifier that represents anyone + /// who is authenticated with a Google account or a service account. + /// + /// * `user:{emailid}`: An email address that represents a specific Google + /// account. For example, `alice@example.com` . + /// + /// + /// * `serviceAccount:{emailid}`: An email address that represents a service + /// account. For example, `my-other-app@appspot.gserviceaccount.com`. + /// + /// * `group:{emailid}`: An email address that represents a Google group. + /// For example, `admins@example.com`. + /// + /// + /// * `domain:{domain}`: The G Suite domain (primary) that represents all the + /// users of that domain. For example, `google.com` or `example.com`. + /// + /// + #[prost(string, repeated, tag = "2")] + pub members: ::std::vec::Vec, + /// The condition that is associated with this binding. + /// NOTE: An unsatisfied condition will not allow user access via current + /// binding. Different bindings, including their conditions, are examined + /// independently. + #[prost(message, optional, tag = "3")] + pub condition: ::std::option::Option, +} +/// The difference delta between two policies. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PolicyDelta { + /// The delta for Bindings between two policies. + #[prost(message, repeated, tag = "1")] + pub binding_deltas: ::std::vec::Vec, + /// The delta for AuditConfigs between two policies. + #[prost(message, repeated, tag = "2")] + pub audit_config_deltas: ::std::vec::Vec, +} +/// One delta entry for Binding. Each individual change (only one member in each +/// entry) to a binding will be a separate entry. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct BindingDelta { + /// The action that was performed on a Binding. + /// Required + #[prost(enumeration = "binding_delta::Action", tag = "1")] + pub action: i32, + /// Role that is assigned to `members`. + /// For example, `roles/viewer`, `roles/editor`, or `roles/owner`. + /// Required + #[prost(string, tag = "2")] + pub role: std::string::String, + /// A single identity requesting access for a Cloud Platform resource. + /// Follows the same format of Binding.members. + /// Required + #[prost(string, tag = "3")] + pub member: std::string::String, + /// The condition that is associated with this binding. + #[prost(message, optional, tag = "4")] + pub condition: ::std::option::Option, +} +pub mod binding_delta { + /// The type of action performed on a Binding in a policy. + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] + #[repr(i32)] + pub enum Action { + /// Unspecified. + Unspecified = 0, + /// Addition of a Binding. + Add = 1, + /// Removal of a Binding. + Remove = 2, + } +} +/// One delta entry for AuditConfig. Each individual change (only one +/// exempted_member in each entry) to a AuditConfig will be a separate entry. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AuditConfigDelta { + /// The action that was performed on an audit configuration in a policy. + /// Required + #[prost(enumeration = "audit_config_delta::Action", tag = "1")] + pub action: i32, + /// Specifies a service that was configured for Cloud Audit Logging. + /// For example, `storage.googleapis.com`, `cloudsql.googleapis.com`. + /// `allServices` is a special value that covers all services. + /// Required + #[prost(string, tag = "2")] + pub service: std::string::String, + /// A single identity that is exempted from "data access" audit + /// logging for the `service` specified above. + /// Follows the same format of Binding.members. + #[prost(string, tag = "3")] + pub exempted_member: std::string::String, + /// Specifies the log_type that was be enabled. ADMIN_ACTIVITY is always + /// enabled, and cannot be configured. + /// Required + #[prost(string, tag = "4")] + pub log_type: std::string::String, +} +pub mod audit_config_delta { + /// The type of action performed on an audit configuration in a policy. + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] + #[repr(i32)] + pub enum Action { + /// Unspecified. + Unspecified = 0, + /// Addition of an audit configuration. + Add = 1, + /// Removal of an audit configuration. + Remove = 2, + } +} +/// Request message for `SetIamPolicy` method. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SetIamPolicyRequest { + /// REQUIRED: The resource for which the policy is being specified. + /// See the operation documentation for the appropriate value for this field. + #[prost(string, tag = "1")] + pub resource: std::string::String, + /// REQUIRED: The complete policy to be applied to the `resource`. The size of + /// the policy is limited to a few 10s of KB. An empty policy is a + /// valid policy but certain Cloud Platform services (such as Projects) + /// might reject them. + #[prost(message, optional, tag = "2")] + pub policy: ::std::option::Option, +} +/// Request message for `GetIamPolicy` method. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetIamPolicyRequest { + /// REQUIRED: The resource for which the policy is being requested. + /// See the operation documentation for the appropriate value for this field. + #[prost(string, tag = "1")] + pub resource: std::string::String, + /// OPTIONAL: A `GetPolicyOptions` object for specifying options to + /// `GetIamPolicy`. This field is only used by Cloud IAM. + #[prost(message, optional, tag = "2")] + pub options: ::std::option::Option, +} +/// Request message for `TestIamPermissions` method. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TestIamPermissionsRequest { + /// REQUIRED: The resource for which the policy detail is being requested. + /// See the operation documentation for the appropriate value for this field. + #[prost(string, tag = "1")] + pub resource: std::string::String, + /// The set of permissions to check for the `resource`. Permissions with + /// wildcards (such as '*' or 'storage.*') are not allowed. For more + /// information see + /// [IAM Overview](https://cloud.google.com/iam/docs/overview#permissions). + #[prost(string, repeated, tag = "2")] + pub permissions: ::std::vec::Vec, +} +/// Response message for `TestIamPermissions` method. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TestIamPermissionsResponse { + /// A subset of `TestPermissionsRequest.permissions` that the caller is + /// allowed. + #[prost(string, repeated, tag = "1")] + pub permissions: ::std::vec::Vec, +} +#[doc = r" Generated client implementations."] +pub mod iam_policy_client { + #![allow(unused_variables, dead_code, missing_docs)] + use tonic::codegen::*; + #[doc = " ## API Overview"] + #[doc = ""] + #[doc = " Manages Identity and Access Management (IAM) policies."] + #[doc = ""] + #[doc = " Any implementation of an API that offers access control features"] + #[doc = " implements the google.iam.v1.IAMPolicy interface."] + #[doc = ""] + #[doc = " ## Data model"] + #[doc = ""] + #[doc = " Access control is applied when a principal (user or service account), takes"] + #[doc = " some action on a resource exposed by a service. Resources, identified by"] + #[doc = " URI-like names, are the unit of access control specification. Service"] + #[doc = " implementations can choose the granularity of access control and the"] + #[doc = " supported permissions for their resources."] + #[doc = " For example one database service may allow access control to be"] + #[doc = " specified only at the Table level, whereas another might allow access control"] + #[doc = " to also be specified at the Column level."] + #[doc = ""] + #[doc = " ## Policy Structure"] + #[doc = ""] + #[doc = " See google.iam.v1.Policy"] + #[doc = ""] + #[doc = " This is intentionally not a CRUD style API because access control policies"] + #[doc = " are created and deleted implicitly with the resources to which they are"] + #[doc = " attached."] + pub struct IamPolicyClient { + inner: tonic::client::Grpc, + } + impl IamPolicyClient { + #[doc = r" Attempt to create a new client by connecting to a given endpoint."] + pub async fn connect(dst: D) -> Result + where + D: std::convert::TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl IamPolicyClient + where + T: tonic::client::GrpcService, + T::ResponseBody: Body + HttpBody + Send + 'static, + T::Error: Into, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_interceptor(inner: T, interceptor: impl Into) -> Self { + let inner = tonic::client::Grpc::with_interceptor(inner, interceptor); + Self { inner } + } + #[doc = " Sets the access control policy on the specified resource. Replaces any"] + #[doc = " existing policy."] + pub async fn set_iam_policy( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = + http::uri::PathAndQuery::from_static("/google.iam.v1.IAMPolicy/SetIamPolicy"); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Gets the access control policy for a resource."] + #[doc = " Returns an empty policy if the resource exists and does not have a policy"] + #[doc = " set."] + pub async fn get_iam_policy( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = + http::uri::PathAndQuery::from_static("/google.iam.v1.IAMPolicy/GetIamPolicy"); + self.inner.unary(request.into_request(), path, codec).await + } + #[doc = " Returns permissions that a caller has on the specified resource."] + #[doc = " If the resource does not exist, this will return an empty set of"] + #[doc = " permissions, not a NOT_FOUND error."] + #[doc = ""] + #[doc = " Note: This operation is designed to be used for building permission-aware"] + #[doc = " UIs and command-line tools, not for authorization checking. This operation"] + #[doc = " may \"fail open\" without warning."] + pub async fn test_iam_permissions( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = + http::uri::PathAndQuery::from_static("/google.iam.v1.IAMPolicy/TestIamPermissions"); + self.inner.unary(request.into_request(), path, codec).await + } + } + impl Clone for IamPolicyClient { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } + } + impl std::fmt::Debug for IamPolicyClient { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "IamPolicyClient {{ ... }}") + } + } +} diff --git a/google-cloud/src/tasks/api/google.protobuf.rs b/google-cloud/src/tasks/api/google.protobuf.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/google-cloud/src/tasks/api/google.protobuf.rs @@ -0,0 +1 @@ + diff --git a/google-cloud/src/tasks/api/google.r#type.rs b/google-cloud/src/tasks/api/google.r#type.rs new file mode 100644 index 00000000..f93f29fb --- /dev/null +++ b/google-cloud/src/tasks/api/google.r#type.rs @@ -0,0 +1,28 @@ +/// Represents an expression text. Example: +/// +/// title: "User account presence" +/// description: "Determines whether the request has a user account" +/// expression: "size(request.user) > 0" +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Expr { + /// Textual representation of an expression in + /// Common Expression Language syntax. + /// + /// The application context of the containing message determines which + /// well-known feature set of CEL is supported. + #[prost(string, tag = "1")] + pub expression: std::string::String, + /// An optional title for the expression, i.e. a short string describing + /// its purpose. This can be used e.g. in UIs which allow to enter the + /// expression. + #[prost(string, tag = "2")] + pub title: std::string::String, + /// An optional description of the expression. This is a longer text which + /// describes the expression, e.g. when hovered over it in a UI. + #[prost(string, tag = "3")] + pub description: std::string::String, + /// An optional string indicating the location of the expression for error + /// reporting, e.g. a file name and a position in the file. + #[prost(string, tag = "4")] + pub location: std::string::String, +} diff --git a/google-cloud/src/tasks/api/google.rpc.rs b/google-cloud/src/tasks/api/google.rpc.rs new file mode 100644 index 00000000..5a2b8e64 --- /dev/null +++ b/google-cloud/src/tasks/api/google.rpc.rs @@ -0,0 +1,70 @@ +/// The `Status` type defines a logical error model that is suitable for +/// different programming environments, including REST APIs and RPC APIs. It is +/// used by [gRPC](https://github.com/grpc). The error model is designed to be: +/// +/// - Simple to use and understand for most users +/// - Flexible enough to meet unexpected needs +/// +/// # Overview +/// +/// The `Status` message contains three pieces of data: error code, error +/// message, and error details. The error code should be an enum value of +/// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes +/// if needed. The error message should be a developer-facing English message +/// that helps developers *understand* and *resolve* the error. If a localized +/// user-facing error message is needed, put the localized message in the error +/// details or localize it in the client. The optional error details may contain +/// arbitrary information about the error. There is a predefined set of error +/// detail types in the package `google.rpc` that can be used for common error +/// conditions. +/// +/// # Language mapping +/// +/// The `Status` message is the logical representation of the error model, but it +/// is not necessarily the actual wire format. When the `Status` message is +/// exposed in different client libraries and different wire protocols, it can be +/// mapped differently. For example, it will likely be mapped to some exceptions +/// in Java, but more likely mapped to some error codes in C. +/// +/// # Other uses +/// +/// The error model and the `Status` message can be used in a variety of +/// environments, either with or without APIs, to provide a +/// consistent developer experience across different environments. +/// +/// Example uses of this error model include: +/// +/// - Partial errors. If a service needs to return partial errors to the client, +/// it may embed the `Status` in the normal response to indicate the partial +/// errors. +/// +/// - Workflow errors. A typical workflow has multiple steps. Each step may +/// have a `Status` message for error reporting. +/// +/// - Batch operations. If a client uses batch request and batch response, the +/// `Status` message should be used directly inside batch response, one for +/// each error sub-response. +/// +/// - Asynchronous operations. If an API call embeds asynchronous operation +/// results in its response, the status of those operations should be +/// represented directly using the `Status` message. +/// +/// - Logging. If some API errors are stored in logs, the message `Status` could +/// be used directly after any stripping needed for security/privacy reasons. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Status { + /// The status code, which should be an enum value of + /// [google.rpc.Code][google.rpc.Code]. + #[prost(int32, tag = "1")] + pub code: i32, + /// A developer-facing error message, which should be in English. Any + /// user-facing error message should be localized and sent in the + /// [google.rpc.Status.details][google.rpc.Status.details] field, or localized + /// by the client. + #[prost(string, tag = "2")] + pub message: std::string::String, + /// A list of messages that carry the error details. There is a common set of + /// message types for APIs to use. + #[prost(message, repeated, tag = "3")] + pub details: ::std::vec::Vec<::prost_types::Any>, +} From e4d5e9aa7e2ed71cc77fb7e93ab4833e86d0ee58 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Wed, 5 Aug 2020 17:50:41 +0300 Subject: [PATCH 02/22] Add tasks client --- google-cloud/src/tasks/client.rs | 127 +++++++++++++++++++++++++++++++ google-cloud/src/tasks/mod.rs | 16 ++++ 2 files changed, 143 insertions(+) create mode 100644 google-cloud/src/tasks/client.rs create mode 100644 google-cloud/src/tasks/mod.rs diff --git a/google-cloud/src/tasks/client.rs b/google-cloud/src/tasks/client.rs new file mode 100644 index 00000000..d58560f9 --- /dev/null +++ b/google-cloud/src/tasks/client.rs @@ -0,0 +1,127 @@ +use std::env; +use std::fs::File; +use std::sync::Arc; + +use tokio::sync::Mutex; +use tonic::transport::{Certificate, Channel, ClientTlsConfig}; +use tonic::{IntoRequest, Request}; + +use crate::authorize::{ApplicationCredentials, TokenManager, TLS_CERTS}; +use crate::tasks::api; +use crate::tasks::api::cloud_tasks_client::CloudTasksClient; +use crate::tasks::{Error, Queue, Task}; + +/// The Cloud Tasks client, tied to a specific project and location. +#[derive(Clone)] +pub struct Client { + pub(crate) project_name: String, + pub(crate) location_id: String, + pub(crate) service: CloudTasksClient, + pub(crate) token_manager: Arc>, +} + +impl Client { + pub(crate) const DOMAIN_NAME: &'static str = "cloudtasks.googleapis.com"; + pub(crate) const ENDPOINT: &'static str = "https://cloudtasks.googleapis.com"; + pub(crate) const SCOPES: [&'static str; 2] = [ + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/cloud-tasks", + ]; + + pub(crate) async fn construct_request>( + &mut self, + request: T, + ) -> Result, Error> { + let mut request = request.into_request(); + let token = self.token_manager.lock().await.token().await?; + let metadata = request.metadata_mut(); + metadata.insert("authorization", token.parse().unwrap()); + Ok(request) + } + + /// Create a new client for the specified project. + /// + /// Credentials are looked up in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. + pub async fn new(project_name: impl Into, location_id: impl Into) -> Result { + let path = env::var("GOOGLE_APPLICATION_CREDENTIALS")?; + let file = File::open(path)?; + let creds = json::from_reader(file)?; + + Client::from_credentials(project_name, location_id, creds).await + } + + /// Create a new client for the specified project with custom credentials. + pub async fn from_credentials( + project_name: impl Into, + location_id: impl Into, + creds: ApplicationCredentials, + ) -> Result { + let tls_config = ClientTlsConfig::new() + .ca_certificate(Certificate::from_pem(TLS_CERTS)) + .domain_name(Client::DOMAIN_NAME); + + let channel = Channel::from_static(Client::ENDPOINT) + .tls_config(tls_config)? + .connect() + .await?; + + Ok(Client { + project_name: project_name.into(), + location_id: location_id.into(), + service: CloudTasksClient::new(channel), + token_manager: Arc::new(Mutex::new(TokenManager::new( + creds, + Client::SCOPES.as_ref(), + ))), + }) + } + + /// List queues + /// `filter` argument allows returning only a subset of queues, sample filter: "state: PAUSED" + pub async fn queues(&mut self, filter: impl Into) -> Result, Error> { + let mut queues = Vec::new(); + let page_size = 25; + let mut page_token = String::default(); + + loop { + let request = api::ListQueuesRequest { + parent: format!("projects/{0}/locations/{1}", self.project_name.as_str(), self.location_id.as_str()), + filter: filter.into(), + page_size, + page_token, + }; + let request = self.construct_request(request).await?; + let response = self.service.list_queues(request).await?; + let response = response.into_inner(); + page_token = response.next_page_token; + queues.extend( + response + .queues + .into_iter() + .map(|queue| Queue::new(self.clone(), queue.name)), + ); + if page_token.is_empty() { + break; + } + } + + Ok(queues) + } + + /// Get a handle of a specific subscription. + pub async fn queue(&mut self, id: &str) -> Result, Error> { + let request = api::GetQueueRequest { + name: format!( + "projects/{0}/locations/{1}/queues/{2}", + self.project_name.as_str(), + self.location_id.as_str(), + id, + ), + }; + let request = self.construct_request(request).await?; + let response = self.service.get_queue(request).await?; + let queue = response.into_inner(); + + Ok(Some(Queue::new(self.clone(), queue.name))) + } +} diff --git a/google-cloud/src/tasks/mod.rs b/google-cloud/src/tasks/mod.rs new file mode 100644 index 00000000..4e8945c8 --- /dev/null +++ b/google-cloud/src/tasks/mod.rs @@ -0,0 +1,16 @@ +mod client; +mod task; +mod queue; +mod api { + #[path = "google.cloud.tasks.v2beta3.rs"] + mod tasks_api; + pub use self::tasks_api::*; +} + +pub use self::client::*; +pub use self::task::*; +pub use self::queue::*; +pub use self::topic::*; + +/// The error type for the Tasks module. +pub type Error = crate::error::Error; From 5a06aeddf7328f68973032b6b5f3592f67cf0165 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 12:55:35 +0300 Subject: [PATCH 03/22] Add config and main structs --- google-cloud/src/tasks/mod.rs | 4 + google-cloud/src/tasks/queue.rs | 48 ++++ google-cloud/src/tasks/task.rs | 130 ++++++++++ google-cloud/src/tasks/task_authorization.rs | 43 ++++ google-cloud/src/tasks/task_request_types.rs | 247 +++++++++++++++++++ 5 files changed, 472 insertions(+) create mode 100644 google-cloud/src/tasks/queue.rs create mode 100644 google-cloud/src/tasks/task.rs create mode 100644 google-cloud/src/tasks/task_authorization.rs create mode 100644 google-cloud/src/tasks/task_request_types.rs diff --git a/google-cloud/src/tasks/mod.rs b/google-cloud/src/tasks/mod.rs index 4e8945c8..7808fa0f 100644 --- a/google-cloud/src/tasks/mod.rs +++ b/google-cloud/src/tasks/mod.rs @@ -1,3 +1,5 @@ +mod task_request_types; +mod task_authorization; mod client; mod task; mod queue; @@ -11,6 +13,8 @@ pub use self::client::*; pub use self::task::*; pub use self::queue::*; pub use self::topic::*; +pub use self::task_authorization::*; +pub use self::task_request_types::*; /// The error type for the Tasks module. pub type Error = crate::error::Error; diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs new file mode 100644 index 00000000..a1c93106 --- /dev/null +++ b/google-cloud/src/tasks/queue.rs @@ -0,0 +1,48 @@ +use std::collections::{HashMap, VecDeque}; + +use chrono::Duration; + +use crate::tasks::api; +use crate::tasks::api::queue::State; +use crate::tasks::{Client, Error, Task}; + +/// Represents a Queue +#[derive(Clone, Debug)] +pub struct Queue { + pub(crate) client: Client, + pub(crate) name: String, +} + +impl Queue { + pub(crate) fn new(client: Client, name: impl Into) -> Queue { + Queue { + client, + name: name.into(), + } + } + + /// Returns the unique identifier within its project + pub fn id(&self) -> &str { + self.name.rsplit('/').next().unwrap() + } + + /// Delete the queue. + pub async fn delete(mut self) -> Result<(), Error> { + let request = api::DeleteQueueRequest { + name: self.name.clone(), + }; + let request = self.client.construct_request(request).await?; + self.client.service.delete_queue(request).await?; + + Ok(()) + } + + pub async fn new_task(&mut self) -> Result{ + let request = api::CreateTaskRequest{ + parent: self.name.clone(), + task: None, + response_view: 0 + }; + todo!() + } +} diff --git a/google-cloud/src/tasks/task.rs b/google-cloud/src/tasks/task.rs new file mode 100644 index 00000000..ab0c697e --- /dev/null +++ b/google-cloud/src/tasks/task.rs @@ -0,0 +1,130 @@ +use std::collections::HashMap; + +use crate::tasks::{api, PayloadTypeConfig, PayloadType}; +use crate::tasks::{Client, Error}; +use chrono::{NaiveDateTime, Duration}; +use tonic::Status; + +#[derive(Clone, Copy, Debug)] +pub enum View { + /// Unspecified. Defaults to BASIC. + Unspecified, + /// The basic view omits fields which can be large or can contain + /// sensitive data. + /// + /// This view does not include the + /// body in AppEngineHttpRequest. + /// Bodies are desirable to return only when needed, because they + /// can be large and because of the sensitivity of the data that you + /// choose to store in it. + Basic, + /// All information is returned. + /// + /// Authorization for Full requires `cloudtasks.tasks.fullView` permission on the resource. + Full, +} + +/// Configuration for creating a new task +#[derive(Debug)] +pub struct TaskConfig { + /// Optional ID of the task. This can be used for task deduplication, although since + /// this will require looking up existing tasks, latency for creating task with an ID is much + /// higher than for task without an ID. + /// An ID is only freed about an hour after the task with the same ID was completed, + /// so even if there are no task with the same ID in the queue at the moment of call, if + /// a task with the same ID existed up to an hour earlier, the call will fail + pub id: Option, + pub schedule_time: Option, + /// The deadline for requests sent to the worker. If the worker does not + /// respond by this deadline then the request is cancelled and the attempt + /// is marked as a `DEADLINE_EXCEEDED` failure. Cloud Tasks will retry the + /// task according to the RetryConfig + pub dispatch_deadline: Option, + pub payload_type: PayloadTypeConfig, +} + +#[derive(Clone, Debug)] +pub struct Attempt { + pub schedule_time: Option, + pub dispatch_time: Option, + pub response_time: Option, + pub response_status: Option, +} + +impl Attempt{ + ///The time that this attempt was scheduled. + pub fn schedule_time(&self) -> Option { + self.schedule_time + } + ///The time that this attempt was scheduled. + pub fn dispatch_time(&self) -> Option { + self.dispatch_time + } + ///The time that this attempt was scheduled. + pub fn response_time(&self) -> Option { + self.response_time + } + ///The time that this attempt was scheduled. + pub fn response_status(&self) -> Option<&Status> { + self.response_status.as_deref() + } +} + +/// Represents a task +#[derive(Clone, Debug)] +pub struct Task { + pub(crate) client: Client, + pub(crate) name: String, + pub(crate) schedule_time: Option, + pub(crate) create_time: Option, + pub(crate) dispatch_deadline: Option, + pub(crate) dispatch_count: i32, + pub(crate) response_count: i32, + pub(crate) first_attempt: Option, + pub(crate) last_attempt: Option, + pub(crate) view: View, + pub(crate) payload_type: Option, +} + +impl Task { + /// The task's full name. + pub fn name(&self) -> &str { + self.name.as_str() + } + /// The time when the task is scheduled to be attempted. + pub fn schedule_time(&self) -> Option { + self.schedule_time + } + /// The time that the task was created. + pub fn create_time(&self) -> Option { + self.create_time + } + /// The deadline for requests sent to the worker. + pub fn dispatch_deadline(&self) -> Option { + self.dispatch_deadline + } + /// The number of attempts dispatched. + pub fn dispatch_count(&self) -> i32 { + self.dispatch_count + } + /// The number of attempts which have received a response. + pub fn response_count(&self) -> i32 { + self.response_count + } + /// The status of the task's first attempt. + pub fn first_attempt(&self) -> Option<&Attempt> { + self.first_attempt.as_deref() + } + /// The status of the task's last attempt. + pub fn last_attempt(&self) -> Option<&Attempt> { + self.last_attempt.as_deref() + } + /// The view specifies which subset of the Task has been returned. + pub fn view(&self) -> View { + self.view + } + /// The message to send to the worker. May be absent in Basic view + pub fn payload_type(&self) -> Option<&PayloadType> { + self.payload_type.as_deref() + } +} diff --git a/google-cloud/src/tasks/task_authorization.rs b/google-cloud/src/tasks/task_authorization.rs new file mode 100644 index 00000000..51f39cd3 --- /dev/null +++ b/google-cloud/src/tasks/task_authorization.rs @@ -0,0 +1,43 @@ +#[derive(Clone, Debug)] +pub enum AuthorizationHeader { + /// If specified, an OAuth token + /// will be generated and attached as an `Authorization` header in the HTTP + /// request. + /// + /// This type of authorization should generally only be used when calling + /// Google APIs hosted on *.googleapis.com. + OauthToken(OAuthToken), + /// If specified, an OIDC token will be generated and attached + /// as an `Authorization` header in the HTTP request. + /// + /// This type of authorization can be used for many scenarios, including + /// calling Cloud Run, or endpoints where you intend to validate the token + /// yourself. + OidcToken(OidcToken), +} + +#[derive(Clone, Debug)] +pub struct OAuthToken { + /// Service account email to be used for generating OAuth token. + /// The service account must be within the same project as the queue. The + /// caller must have iam.serviceAccounts.actAs permission for the service + /// account. + pub service_account_email: String, + /// OAuth scope to be used for generating OAuth access token. + /// If not specified, "https://www.googleapis.com/auth/cloud-platform" + /// will be used. + pub scope: String, +} + +#[derive(Clone, Debug)] +pub struct OidcToken { + /// Service account email to be used for generating OIDC token. + /// The service account must be within the same project as the queue. The + /// caller must have iam.serviceAccounts.actAs permission for the service + /// account. + pub service_account_email: String, + /// Audience to be used when generating OIDC token. If not specified, the URI + /// specified in target will be used. + pub audience: String, +} + diff --git a/google-cloud/src/tasks/task_request_types.rs b/google-cloud/src/tasks/task_request_types.rs new file mode 100644 index 00000000..8d82b23b --- /dev/null +++ b/google-cloud/src/tasks/task_request_types.rs @@ -0,0 +1,247 @@ +use std::collections::HashMap; +use crate::tasks::AuthorizationHeader; + +#[derive(Clone, Copy, Debug)] +pub enum HttpMethod { + /// HTTP method unspecified + Unspecified, + /// HTTP POST + Post, + /// HTTP GET + Get, + /// HTTP HEAD + Head, + /// HTTP PUT + Put, + /// HTTP DELETE + Delete, + /// HTTP PATCH + Patch, + /// HTTP OPTIONS + Options, +} + +#[derive(Clone, Debug)] +pub struct AppEngineRoutingConfig { + /// App service. + /// + /// By default, the task is sent to the service which is the default + /// service when the task is attempted. + pub service: Option, + /// App version. + /// + /// By default, the task is sent to the version which is the default + /// version when the task is attempted. + pub version: Option, +} + +#[derive(Clone, Debug)] +pub struct AppEngineRouting { + pub(crate) service: String, + pub(crate) version: String, + pub(crate) instance: String, + pub(crate) host: String, +} + +impl AppEngineRouting { + pub fn service(&self) -> &str { + self.service.as_str() + } + pub fn version(&self) -> &str { + self.version.as_str() + } + pub fn instance(&self) -> &str { + self.instance.as_str() + } + pub fn host(&self) -> &str { + self.host.as_str() + } +} + +#[derive(Clone, Debug)] +pub struct AppEngineHttpRequestConfig { + /// The HTTP method to use for the request. + pub http_method: HttpMethod, + /// Task-level setting for App Engine routing. + pub app_engine_routing: AppEngineRoutingConfig, + /// The relative URI. + /// + /// The relative URI must begin with "/" and must be a valid HTTP relative URI. + /// It can contain a path and query string arguments. + /// If the relative URI is empty, then the root path "/" will be used. + /// No spaces are allowed, and the maximum length allowed is 2083 characters. + pub relative_uri: String, + /// HTTP request headers. + /// + /// This map contains the header field names and values. + /// Headers can be set when the + /// Repeated headers are not supported but a header value can contain commas. + /// + /// Cloud Tasks sets some headers to default values: + /// + /// * `User-Agent`: By default, this header is + /// `"AppEngine-Google; (+http://code.google.com/appengine)"`. + /// This header can be modified, but Cloud Tasks will append + /// `"AppEngine-Google; (+http://code.google.com/appengine)"` to the + /// modified `User-Agent`. + /// + /// If the task has a body, Cloud Tasks sets the following headers: + /// + /// * `Content-Type`: By default, the `Content-Type` header is set to + /// `"application/octet-stream"`. The default can be overridden by explicitly + /// setting `Content-Type` to a particular media type when the + /// task is created. + /// For example, `Content-Type` can be set to `"application/json"`. + /// * `Content-Length`: This is computed by Cloud Tasks. This value is + /// output only. It cannot be changed. + /// + /// The headers below cannot be set or overridden: + /// + /// * `Host` + /// * `X-Google-*` + /// * `X-AppEngine-*` + /// + /// In addition, Cloud Tasks sets some headers when the task is dispatched, + /// such as headers containing information about the task; see + /// [request + /// headers](https://cloud.google.com/appengine/docs/python/taskqueue/push/creating-handlers#reading_request_headers). + /// These headers are set only when the task is dispatched, so they are not + /// visible when the task is returned in a Cloud Tasks response. + /// + /// Although there is no specific limit for the maximum number of headers or + /// the size, there is a limit on the maximum size of the Task. + pub headers: HashMap, + /// HTTP request body. + /// + /// A request body is allowed only if the HTTP method is POST or PUT. It is + /// an error to set a body on a task with an incompatible HttpMethod. + pub body: Vec, +} + +#[derive(Clone, Debug)] +pub struct AppEngineHttpRequest { + pub http_method: HttpMethod, + pub app_engine_routing: Option, + pub relative_uri: String, + pub headers: HashMap, + pub body: Vec, +} + +impl AppEngineHttpRequest { + /// The HTTP method of this request. + pub fn http_method(&self) -> HttpMethod { + self.http_method + } + /// Task-level setting for App Engine routing. + pub fn app_engine_routing(&self) -> Option<&AppEngineRouting> { + self.app_engine_routing.as_deref() + } + /// The relative URI. + pub fn relative_uri(&self) -> &str { + self.relative_uri.as_str() + } + /// HTTP request headers. + pub fn headers(&self) -> &HashMap { + self.headers.as_ref() + } + /// HTTP request body. + pub fn body(&self) -> &[u8] { + self.body.as_slice() + } +} + +#[derive(Clone, Debug)] +pub struct HttpRequestConfig { + /// Required. The full url path that the request will be sent to. + /// + /// This string must begin with either "http://" or "https://". Some examples + /// are: `http://acme.com` and `https://acme.com/sales:8080`. Cloud Tasks will + /// encode some characters for safety and compatibility. The maximum allowed + /// URL length is 2083 characters after encoding. + /// + /// The `Location` header response from a redirect response [`300` - `399`] + /// may be followed. The redirect is not counted as a separate attempt. + pub url: String, + /// The HTTP method to use for the request + pub http_method: HttpMethod, + /// HTTP request headers. + /// + /// This map contains the header field names and values. + /// Headers can be set when the task is created. + /// + /// These headers represent a subset of the headers that will accompany the + /// task's HTTP request. Some HTTP request headers will be ignored or replaced. + /// + /// A partial list of headers that will be ignored or replaced is: + /// + /// * Host: This will be computed by Cloud Tasks and derived from HttpRequest.url. + /// * Content-Length: This will be computed by Cloud Tasks. + /// * User-Agent: This will be set to `"Google-Cloud-Tasks"`. + /// * X-Google-*: Google use only. + /// * X-AppEngine-*: Google use only. + /// + /// `Content-Type` won't be set by Cloud Tasks. You can explicitly set + /// `Content-Type` to a media type when the task is created. + /// For example, `Content-Type` can be set to `"application/octet-stream"` or + /// `"application/json"`. + /// + /// Headers which can have multiple values (according to RFC2616) can be + /// specified using comma-separated values. + /// + /// The size of the headers must be less than 80KB. + pub headers: HashMap, + /// HTTP request body. + /// + /// A request body is allowed only if the HTTP method is POST, PUT, or PATCH. It is an + /// error to set body on a task with an incompatible HttpMethod. + pub body: Vec, + /// The mode for generating an `Authorization` header for HTTP requests. + /// + /// If specified, all `Authorization` headers in the `HttpRequest.headers` + /// field will be overridden. + pub authorization_header: Option, +} + +#[derive(Clone, Debug)] +pub struct HttpRequest { + pub(crate) url: String, + pub(crate) http_method: HttpMethod, + pub(crate) headers: HashMap, + pub(crate) body: Vec, + pub(crate) authorization_header: Option, +} + +impl HttpRequest { + /// The full url path that the request will be sent to. + pub fn url(&self) -> &str { + self.url.as_str() + } + /// The HTTP method of this request. + pub fn http_method(&self) -> HttpMethod { + self.http_method + } + /// HTTP request headers. + pub fn headers(&self) -> &HashMap { + self.headers.as_ref() + } + /// HTTP request body. + pub fn body(&self) -> &[u8] { + self.body.as_slice() + } + /// Google-generated authorization headers. + pub fn authorization_header(&self) -> Option<&AuthorizationHeader> { + self.authorization_header.as_deref() + } +} + +#[derive(Clone, Debug)] +pub enum PayloadTypeConfig { + AppEngineHttpRequest(AppEngineHttpRequestConfig), + HttpRequest(HttpRequestConfig), +} + +#[derive(Clone, Debug)] +pub enum PayloadType { + AppEngineHttpRequest(AppEngineHttpRequest), + HttpRequest(HttpRequest), +} From 1a9e48d75cb6d38e5e7e2c22f270ab5c7e4747a3 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 16:05:47 +0300 Subject: [PATCH 04/22] [WIP] Type conversions --- google-cloud/src/tasks/client.rs | 8 +- google-cloud/src/tasks/mod.rs | 33 ++- google-cloud/src/tasks/queue.rs | 8 +- google-cloud/src/tasks/task.rs | 109 +++++++-- google-cloud/src/tasks/task_authorization.rs | 49 +++++ google-cloud/src/tasks/task_request_types.rs | 220 +++++++++++++++++-- google-cloud/src/tasks/utils.rs | 12 + 7 files changed, 385 insertions(+), 54 deletions(-) create mode 100644 google-cloud/src/tasks/utils.rs diff --git a/google-cloud/src/tasks/client.rs b/google-cloud/src/tasks/client.rs index d58560f9..946d6905 100644 --- a/google-cloud/src/tasks/client.rs +++ b/google-cloud/src/tasks/client.rs @@ -9,7 +9,7 @@ use tonic::{IntoRequest, Request}; use crate::authorize::{ApplicationCredentials, TokenManager, TLS_CERTS}; use crate::tasks::api; use crate::tasks::api::cloud_tasks_client::CloudTasksClient; -use crate::tasks::{Error, Queue, Task}; +use crate::tasks::{Error, Queue}; /// The Cloud Tasks client, tied to a specific project and location. #[derive(Clone)] @@ -78,7 +78,7 @@ impl Client { /// List queues /// `filter` argument allows returning only a subset of queues, sample filter: "state: PAUSED" - pub async fn queues(&mut self, filter: impl Into) -> Result, Error> { + pub async fn queues(&mut self, filter: &str) -> Result, Error> { let mut queues = Vec::new(); let page_size = 25; let mut page_token = String::default(); @@ -86,7 +86,7 @@ impl Client { loop { let request = api::ListQueuesRequest { parent: format!("projects/{0}/locations/{1}", self.project_name.as_str(), self.location_id.as_str()), - filter: filter.into(), + filter: filter.to_string(), page_size, page_token, }; @@ -108,7 +108,7 @@ impl Client { Ok(queues) } - /// Get a handle of a specific subscription. + /// Get a queue by name. pub async fn queue(&mut self, id: &str) -> Result, Error> { let request = api::GetQueueRequest { name: format!( diff --git a/google-cloud/src/tasks/mod.rs b/google-cloud/src/tasks/mod.rs index 7808fa0f..16a83176 100644 --- a/google-cloud/src/tasks/mod.rs +++ b/google-cloud/src/tasks/mod.rs @@ -1,20 +1,45 @@ +mod utils; mod task_request_types; mod task_authorization; mod client; mod task; mod queue; mod api { - #[path = "google.cloud.tasks.v2beta3.rs"] - mod tasks_api; - pub use self::tasks_api::*; + pub mod google{ + pub mod api { + include!("api/google.api.rs"); + } + pub mod cloud { + pub mod tasks { + pub mod v2beta3 { + include!("api/google.cloud.tasks.v2beta3.rs"); + } + } + } + pub mod iam { + pub mod v1 { + include!("api/google.iam.v1.rs"); + } + } + pub mod protobuf { + include!("api/google.protobuf.rs"); + } + pub mod r#type { + include!("api/google.r#type.rs"); + } + pub mod rpc { + include!("api/google.rpc.rs"); + } + } + pub use self::google::cloud::tasks::v2beta3::*; } pub use self::client::*; pub use self::task::*; pub use self::queue::*; -pub use self::topic::*; pub use self::task_authorization::*; pub use self::task_request_types::*; +pub(crate) use self::utils::*; /// The error type for the Tasks module. pub type Error = crate::error::Error; diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs index a1c93106..1a9e5e99 100644 --- a/google-cloud/src/tasks/queue.rs +++ b/google-cloud/src/tasks/queue.rs @@ -1,13 +1,8 @@ -use std::collections::{HashMap, VecDeque}; - -use chrono::Duration; - use crate::tasks::api; -use crate::tasks::api::queue::State; use crate::tasks::{Client, Error, Task}; /// Represents a Queue -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct Queue { pub(crate) client: Client, pub(crate) name: String, @@ -37,6 +32,7 @@ impl Queue { Ok(()) } + /// Create a new task in this queue pub async fn new_task(&mut self) -> Result{ let request = api::CreateTaskRequest{ parent: self.name.clone(), diff --git a/google-cloud/src/tasks/task.rs b/google-cloud/src/tasks/task.rs index ab0c697e..783970d7 100644 --- a/google-cloud/src/tasks/task.rs +++ b/google-cloud/src/tasks/task.rs @@ -1,10 +1,9 @@ -use std::collections::HashMap; - -use crate::tasks::{api, PayloadTypeConfig, PayloadType}; -use crate::tasks::{Client, Error}; +use crate::tasks::{api, PayloadTypeConfig, PayloadType, AppEngineHttpRequestConfig, HttpRequestConfig, convert_timestamp, convert_duration}; +use crate::tasks::Client; use chrono::{NaiveDateTime, Duration}; use tonic::Status; +/// Type of task view - basic or full #[derive(Clone, Copy, Debug)] pub enum View { /// Unspecified. Defaults to BASIC. @@ -24,6 +23,26 @@ pub enum View { Full, } +impl From for api::task::View{ + fn from(item: View) -> Self { + match item{ + View::Unspecified => api::task::View::Unspecified, + View::Basic => api::task::View::Basic, + View::Full => api::task::View::Full, + } + } +} + +impl From for View{ + fn from(item: api::task::View) -> Self { + match item{ + api::task::View::Unspecified => View::Unspecified, + api::task::View::Basic => View::Basic, + api::task::View::Full => View::Full, + } + } +} + /// Configuration for creating a new task #[derive(Debug)] pub struct TaskConfig { @@ -33,22 +52,78 @@ pub struct TaskConfig { /// An ID is only freed about an hour after the task with the same ID was completed, /// so even if there are no task with the same ID in the queue at the moment of call, if /// a task with the same ID existed up to an hour earlier, the call will fail - pub id: Option, - pub schedule_time: Option, + id: Option, + schedule_time: Option, /// The deadline for requests sent to the worker. If the worker does not /// respond by this deadline then the request is cancelled and the attempt /// is marked as a `DEADLINE_EXCEEDED` failure. Cloud Tasks will retry the /// task according to the RetryConfig - pub dispatch_deadline: Option, - pub payload_type: PayloadTypeConfig, + dispatch_deadline: Option, + payload_type: PayloadTypeConfig, +} + +impl From for api::Task { + fn from(item: TaskConfig) -> Self { + Self{ + name: item.id.unwrap_or("".to_string()), + schedule_time: item.schedule_time.map(convert_timestamp), + create_time: None, + dispatch_deadline: item.dispatch_deadline.map(convert_duration), + dispatch_count: 0, + response_count: 0, + first_attempt: None, + last_attempt: None, + view: 0, + payload_type: Some(item.payload_type.into()) + } + } } +impl TaskConfig{ + /// Create new AppEngine HTTP task + pub fn new_appengine_http_task(task: AppEngineHttpRequestConfig) -> Self{ + Self{ + id: None, + schedule_time: None, + dispatch_deadline: None, + payload_type: PayloadTypeConfig::AppEngineHttpRequest(task) + } + } + /// Create new HTTP task + pub fn new_http_task(task: HttpRequestConfig) -> Self{ + Self{ + id: None, + schedule_time: None, + dispatch_deadline: None, + payload_type: PayloadTypeConfig::HttpRequest(task) + } + } + /// Set Task ID + /// Parent is the name of the queue the task should go into + /// ID is the ID of the task + pub fn id(mut self, parent: &str, id: &str) -> Self { + self.id.replace(format!("{}/{}", parent, id)); + self + } + /// Schedule Task for a specific time + pub fn schedule_time(mut self, time: NaiveDateTime) -> Self { + self.schedule_time.replace(time); + self + } + /// Set Dispatch deadline + pub fn dispatch_deadline(mut self, deadline: Duration) -> Self { + self.dispatch_deadline.replace(deadline); + self + } +} + +/// Describes Cloud Task delivery attempts #[derive(Clone, Debug)] pub struct Attempt { - pub schedule_time: Option, - pub dispatch_time: Option, - pub response_time: Option, - pub response_status: Option, + pub(crate) schedule_time: Option, + pub(crate) dispatch_time: Option, + pub(crate) response_time: Option, + pub(crate) response_status: Option, } impl Attempt{ @@ -66,12 +141,12 @@ impl Attempt{ } ///The time that this attempt was scheduled. pub fn response_status(&self) -> Option<&Status> { - self.response_status.as_deref() + self.response_status.as_ref() } } /// Represents a task -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct Task { pub(crate) client: Client, pub(crate) name: String, @@ -113,11 +188,11 @@ impl Task { } /// The status of the task's first attempt. pub fn first_attempt(&self) -> Option<&Attempt> { - self.first_attempt.as_deref() + self.first_attempt.as_ref() } /// The status of the task's last attempt. pub fn last_attempt(&self) -> Option<&Attempt> { - self.last_attempt.as_deref() + self.last_attempt.as_ref() } /// The view specifies which subset of the Task has been returned. pub fn view(&self) -> View { @@ -125,6 +200,6 @@ impl Task { } /// The message to send to the worker. May be absent in Basic view pub fn payload_type(&self) -> Option<&PayloadType> { - self.payload_type.as_deref() + self.payload_type.as_ref() } } diff --git a/google-cloud/src/tasks/task_authorization.rs b/google-cloud/src/tasks/task_authorization.rs index 51f39cd3..02e85197 100644 --- a/google-cloud/src/tasks/task_authorization.rs +++ b/google-cloud/src/tasks/task_authorization.rs @@ -1,3 +1,6 @@ +use crate::tasks::api; + +/// Configuration for Google-generated Authorization header #[derive(Clone, Debug)] pub enum AuthorizationHeader { /// If specified, an OAuth token @@ -16,6 +19,26 @@ pub enum AuthorizationHeader { OidcToken(OidcToken), } +impl From for api::http_request::AuthorizationHeader{ + fn from(item: AuthorizationHeader) -> Self { + match item{ + AuthorizationHeader::OauthToken(token_config) => api::http_request::AuthorizationHeader::OauthToken(token_config.into()), + AuthorizationHeader::OidcToken(token_config) => api::http_request::AuthorizationHeader::OidcToken(token_config.into()), + } + } +} + +impl From for AuthorizationHeader{ + fn from(item: api::http_request::AuthorizationHeader) -> Self { + match item{ + api::http_request::AuthorizationHeader::OauthToken(token_config) => AuthorizationHeader::OauthToken(token_config.into()), + api::http_request::AuthorizationHeader::OidcToken(token_config) => AuthorizationHeader::OidcToken(token_config.into()), + } + } +} + +/// Config for google-generated Oauth token +/// https://cloud.google.com/tasks/docs/creating-http-target-tasks#sa #[derive(Clone, Debug)] pub struct OAuthToken { /// Service account email to be used for generating OAuth token. @@ -29,6 +52,20 @@ pub struct OAuthToken { pub scope: String, } +impl From for api::OAuthToken{ + fn from(item: OAuthToken) -> Self { + Self{ service_account_email: item.service_account_email, scope: item.scope } + } +} + +impl From for OAuthToken{ + fn from(item: api::OAuthToken) -> Self { + Self{ service_account_email: item.service_account_email, scope: item.scope } + } +} + +/// Config for google-generated Oidc token +/// https://cloud.google.com/tasks/docs/creating-http-target-tasks#token #[derive(Clone, Debug)] pub struct OidcToken { /// Service account email to be used for generating OIDC token. @@ -41,3 +78,15 @@ pub struct OidcToken { pub audience: String, } +impl From for api::OidcToken{ + fn from(item: OidcToken) -> Self { + Self{ service_account_email: item.service_account_email, audience: item.audience } + } +} + +impl From for OidcToken{ + fn from(item: api::OidcToken) -> Self { + Self{ service_account_email: item.service_account_email, audience: item.audience } + } +} + diff --git a/google-cloud/src/tasks/task_request_types.rs b/google-cloud/src/tasks/task_request_types.rs index 8d82b23b..28ddfb45 100644 --- a/google-cloud/src/tasks/task_request_types.rs +++ b/google-cloud/src/tasks/task_request_types.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; -use crate::tasks::AuthorizationHeader; +use crate::tasks::{AuthorizationHeader, api}; +/// All supported HTTP methods for Cloud Tasks #[derive(Clone, Copy, Debug)] pub enum HttpMethod { /// HTTP method unspecified @@ -21,6 +22,37 @@ pub enum HttpMethod { Options, } +impl From for HttpMethod{ + fn from(item: api::HttpMethod) -> Self { + match item{ + api::HttpMethod::Unspecified => HttpMethod::Unspecified, + api::HttpMethod::Post => HttpMethod::Post, + api::HttpMethod::Get => HttpMethod::Get, + api::HttpMethod::Head => HttpMethod::Head, + api::HttpMethod::Put => HttpMethod::Put, + api::HttpMethod::Delete => HttpMethod::Delete, + api::HttpMethod::Patch => HttpMethod::Patch, + api::HttpMethod::Options => HttpMethod::Options, + } + } +} + +impl From for api::HttpMethod{ + fn from(item: HttpMethod) -> Self { + match item{ + HttpMethod::Unspecified => api::HttpMethod::Unspecified, + HttpMethod::Post => api::HttpMethod::Post, + HttpMethod::Get => api::HttpMethod::Get, + HttpMethod::Head => api::HttpMethod::Head, + HttpMethod::Put => api::HttpMethod::Put, + HttpMethod::Delete => api::HttpMethod::Delete, + HttpMethod::Patch => api::HttpMethod::Patch, + HttpMethod::Options => api::HttpMethod::Options, + } + } +} + +/// Configuration to create custom AppEngine target for AppEngine HTTP request #[derive(Clone, Debug)] pub struct AppEngineRoutingConfig { /// App service. @@ -35,6 +67,18 @@ pub struct AppEngineRoutingConfig { pub version: Option, } +impl From for api::AppEngineRouting{ + fn from(item: AppEngineRoutingConfig) -> Self { + Self{ + service: item.service.unwrap_or("".to_string()), + version: item.version.unwrap_or("".to_string()), + instance: "".to_string(), + host: "".to_string() + } + } +} + +/// Target configuration for AppEngine HTTP request #[derive(Clone, Debug)] pub struct AppEngineRouting { pub(crate) service: String, @@ -43,34 +87,50 @@ pub struct AppEngineRouting { pub(crate) host: String, } +impl From for AppEngineRouting{ + fn from(item: api::AppEngineRouting) -> Self { + Self{ + service: item.service, + version: item.version, + instance: item.instance, + host: item.host + } + } +} + impl AppEngineRouting { + /// Target service pub fn service(&self) -> &str { self.service.as_str() } + /// Target app version. pub fn version(&self) -> &str { self.version.as_str() } + /// Target app instance. pub fn instance(&self) -> &str { self.instance.as_str() } + /// The host that the task is sent to. pub fn host(&self) -> &str { self.host.as_str() } } +/// Configuration to create new AppEngine HTTP request #[derive(Clone, Debug)] pub struct AppEngineHttpRequestConfig { - /// The HTTP method to use for the request. - pub http_method: HttpMethod, + /// The HTTP method to use for the request. The default is POST. + http_method: HttpMethod, /// Task-level setting for App Engine routing. - pub app_engine_routing: AppEngineRoutingConfig, + app_engine_routing: Option, /// The relative URI. /// /// The relative URI must begin with "/" and must be a valid HTTP relative URI. /// It can contain a path and query string arguments. /// If the relative URI is empty, then the root path "/" will be used. /// No spaces are allowed, and the maximum length allowed is 2083 characters. - pub relative_uri: String, + relative_uri: String, /// HTTP request headers. /// /// This map contains the header field names and values. @@ -110,21 +170,74 @@ pub struct AppEngineHttpRequestConfig { /// /// Although there is no specific limit for the maximum number of headers or /// the size, there is a limit on the maximum size of the Task. - pub headers: HashMap, + headers: HashMap, /// HTTP request body. /// /// A request body is allowed only if the HTTP method is POST or PUT. It is /// an error to set a body on a task with an incompatible HttpMethod. - pub body: Vec, + body: Vec, +} + +impl From for api::AppEngineHttpRequest{ + fn from(item: AppEngineHttpRequestConfig) -> Self { + let mut request = Self{ + http_method: 0, + app_engine_routing: item.app_engine_routing.map(|routing| routing.into()), + relative_uri: item.relative_uri, + headers: item.headers, + body: item.body + }; + request.set_http_method(item.http_method.into()); + request + } +} + +impl AppEngineHttpRequestConfig{ + /// Create new App Engine HTTP request + pub fn new() -> Self { + Self { + http_method: HttpMethod::Post, + app_engine_routing: None, + relative_uri: "".to_string(), + headers: Default::default(), + body: vec![] + } + } + /// Set http method + pub fn http_method(mut self, method: HttpMethod) -> Self { + self.http_method = method; + self + } + /// Configure task-level routing + pub fn app_engine_routing(mut self, routing: AppEngineRoutingConfig) -> Self { + self.app_engine_routing.replace(routing); + self + } + /// Set uri for the request. Default is `/` + pub fn relative_uri(mut self, uri: &str) -> Self { + self.relative_uri = uri.to_string(); + self + } + /// Add header. Repeated headers are not supported but a header value can contain commas. + pub fn header(mut self, key: &str, value: &str) -> Self { + self.headers.insert(key.to_string(), value.to_string()); + self + } + /// Set request body. Should only be set for POST, PUT and PATCH requests + pub fn body>>(mut self, data: T) -> Self { + self.body = data.into(); + self + } } +/// Represents HTTP rtequest that targets AppEngine App #[derive(Clone, Debug)] pub struct AppEngineHttpRequest { - pub http_method: HttpMethod, - pub app_engine_routing: Option, - pub relative_uri: String, - pub headers: HashMap, - pub body: Vec, + http_method: HttpMethod, + app_engine_routing: Option, + relative_uri: String, + headers: HashMap, + body: Vec, } impl AppEngineHttpRequest { @@ -134,7 +247,7 @@ impl AppEngineHttpRequest { } /// Task-level setting for App Engine routing. pub fn app_engine_routing(&self) -> Option<&AppEngineRouting> { - self.app_engine_routing.as_deref() + self.app_engine_routing.as_ref() } /// The relative URI. pub fn relative_uri(&self) -> &str { @@ -142,7 +255,7 @@ impl AppEngineHttpRequest { } /// HTTP request headers. pub fn headers(&self) -> &HashMap { - self.headers.as_ref() + &self.headers } /// HTTP request body. pub fn body(&self) -> &[u8] { @@ -150,6 +263,7 @@ impl AppEngineHttpRequest { } } +/// Configuration to create HTTP request #[derive(Clone, Debug)] pub struct HttpRequestConfig { /// Required. The full url path that the request will be sent to. @@ -161,9 +275,9 @@ pub struct HttpRequestConfig { /// /// The `Location` header response from a redirect response [`300` - `399`] /// may be followed. The redirect is not counted as a separate attempt. - pub url: String, - /// The HTTP method to use for the request - pub http_method: HttpMethod, + url: String, + /// The HTTP method to use for the request. The default is POST. + http_method: HttpMethod, /// HTTP request headers. /// /// This map contains the header field names and values. @@ -189,19 +303,67 @@ pub struct HttpRequestConfig { /// specified using comma-separated values. /// /// The size of the headers must be less than 80KB. - pub headers: HashMap, + headers: HashMap, /// HTTP request body. /// /// A request body is allowed only if the HTTP method is POST, PUT, or PATCH. It is an /// error to set body on a task with an incompatible HttpMethod. - pub body: Vec, + body: Vec, /// The mode for generating an `Authorization` header for HTTP requests. /// /// If specified, all `Authorization` headers in the `HttpRequest.headers` /// field will be overridden. - pub authorization_header: Option, + authorization_header: Option, +} + +impl From for api::HttpRequest{ + fn from(item: HttpRequestConfig) -> Self { + let mut request = Self{ + url: item.url, + http_method: 0, + headers: item.headers, + body: item.body, + authorization_header: item.authorization_header.map(|header| header.into()) + }; + request.set_http_method(item.http_method.into()); + request + } +} + +impl HttpRequestConfig{ + /// Create new HttpRequest. URI must be specified at a minimum + pub fn new(url: &str) -> Self { + Self { + url: url.to_string(), + http_method: HttpMethod::Post, + headers: Default::default(), + body: vec![], + authorization_header: None + } + } + /// Set http method + pub fn http_method(mut self, method: HttpMethod) -> Self { + self.http_method = method; + self + } + /// Add header. Repeated headers are not supported but a header value can contain commas. + pub fn header(mut self, key: &str, value: &str) -> Self { + self.headers.insert(key.to_string(), value.to_string()); + self + } + /// Set request body. Should only be set for POST, PUT and PATCH requests + pub fn body>>(mut self, data: T) -> Self { + self.body = data.into(); + self + } + /// Allows setting data for Google-generated authorization header + pub fn authorization_header(mut self, authorization: AuthorizationHeader) -> Self { + self.authorization_header.replace(authorization); + self + } } +/// Represents HTTP Request #[derive(Clone, Debug)] pub struct HttpRequest { pub(crate) url: String, @@ -222,7 +384,7 @@ impl HttpRequest { } /// HTTP request headers. pub fn headers(&self) -> &HashMap { - self.headers.as_ref() + &self.headers } /// HTTP request body. pub fn body(&self) -> &[u8] { @@ -230,18 +392,30 @@ impl HttpRequest { } /// Google-generated authorization headers. pub fn authorization_header(&self) -> Option<&AuthorizationHeader> { - self.authorization_header.as_deref() + self.authorization_header.as_ref() } } #[derive(Clone, Debug)] -pub enum PayloadTypeConfig { +pub(crate) enum PayloadTypeConfig { AppEngineHttpRequest(AppEngineHttpRequestConfig), HttpRequest(HttpRequestConfig), } +impl From for api::task::PayloadType{ + fn from(item: PayloadTypeConfig) -> Self { + match item { + PayloadTypeConfig::HttpRequest(request) => api::task::PayloadType::HttpRequest(request.into()), + PayloadTypeConfig::AppEngineHttpRequest(request) => api::task::PayloadType::AppEngineHttpRequest(request.into()), + } + } +} + +/// Types of CLoud Task payloads #[derive(Clone, Debug)] pub enum PayloadType { + /// HTTP request that targets AppEngine App AppEngineHttpRequest(AppEngineHttpRequest), + /// HTTP request that targets any public URI HttpRequest(HttpRequest), } diff --git a/google-cloud/src/tasks/utils.rs b/google-cloud/src/tasks/utils.rs new file mode 100644 index 00000000..76d40d9e --- /dev/null +++ b/google-cloud/src/tasks/utils.rs @@ -0,0 +1,12 @@ +use chrono::{NaiveDateTime, Duration}; + +pub fn convert_timestamp(timestamp: NaiveDateTime) -> prost_types::Timestamp{ + prost_types::Timestamp{ seconds: timestamp.timestamp(), nanos: timestamp.timestamp_subsec_nanos() as i32 } +} + +pub fn convert_duration(duration: Duration) -> prost_types::Duration{ + let seconds = duration.num_seconds(); + let duration_rem = duration - chrono::Duration::seconds(seconds); + let nanos = duration_rem.num_nanoseconds().unwrap_or(0) as i32; + prost_types::Duration{ seconds, nanos } +} From c9c58fc3f0c218018f98ab543cd90f27e86f10cc Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 17:04:06 +0300 Subject: [PATCH 05/22] Finish conversions --- google-cloud/src/tasks/task.rs | 37 ++++++++++++++++++-- google-cloud/src/tasks/task_request_types.rs | 34 ++++++++++++++++++ google-cloud/src/tasks/utils.rs | 21 +++++++++-- 3 files changed, 87 insertions(+), 5 deletions(-) diff --git a/google-cloud/src/tasks/task.rs b/google-cloud/src/tasks/task.rs index 783970d7..44b78ae0 100644 --- a/google-cloud/src/tasks/task.rs +++ b/google-cloud/src/tasks/task.rs @@ -1,4 +1,4 @@ -use crate::tasks::{api, PayloadTypeConfig, PayloadType, AppEngineHttpRequestConfig, HttpRequestConfig, convert_timestamp, convert_duration}; +use crate::tasks::{api, PayloadTypeConfig, PayloadType, AppEngineHttpRequestConfig, HttpRequestConfig, timestamp_to_prost, duration_to_prost, prost_to_timestamp, convert_status, prost_to_duration}; use crate::tasks::Client; use chrono::{NaiveDateTime, Duration}; use tonic::Status; @@ -66,9 +66,9 @@ impl From for api::Task { fn from(item: TaskConfig) -> Self { Self{ name: item.id.unwrap_or("".to_string()), - schedule_time: item.schedule_time.map(convert_timestamp), + schedule_time: item.schedule_time.map(timestamp_to_prost), create_time: None, - dispatch_deadline: item.dispatch_deadline.map(convert_duration), + dispatch_deadline: item.dispatch_deadline.map(duration_to_prost), dispatch_count: 0, response_count: 0, first_attempt: None, @@ -126,6 +126,17 @@ pub struct Attempt { pub(crate) response_status: Option, } +impl From for Attempt{ + fn from(item: api::Attempt) -> Self { + Self{ + schedule_time: item.schedule_time.map(prost_to_timestamp), + dispatch_time: item.dispatch_time.map(prost_to_timestamp), + response_time: item.response_time.map(prost_to_timestamp), + response_status: item.response_status.map(convert_status) + } + } +} + impl Attempt{ ///The time that this attempt was scheduled. pub fn schedule_time(&self) -> Option { @@ -161,6 +172,26 @@ pub struct Task { pub(crate) payload_type: Option, } +impl From<(Client, api::Task)> for Task{ + fn from(item: (Client, api::Task)) -> Self { + let (client, task) = item; + let view = task.view(); + Self{ + client, + name: task.name, + schedule_time: task.schedule_time.map(prost_to_timestamp), + create_time: task.create_time.map(prost_to_timestamp), + dispatch_deadline: task.dispatch_deadline.map(prost_to_duration), + dispatch_count: task.dispatch_count, + response_count: task.response_count, + first_attempt: task.first_attempt.map(Attempt::from), + last_attempt: task.last_attempt.map(Attempt::from), + view: view.into(), + payload_type: task.payload_type.map(PayloadType::from) + } + } +} + impl Task { /// The task's full name. pub fn name(&self) -> &str { diff --git a/google-cloud/src/tasks/task_request_types.rs b/google-cloud/src/tasks/task_request_types.rs index 28ddfb45..026d6f99 100644 --- a/google-cloud/src/tasks/task_request_types.rs +++ b/google-cloud/src/tasks/task_request_types.rs @@ -240,6 +240,18 @@ pub struct AppEngineHttpRequest { body: Vec, } +impl From for AppEngineHttpRequest{ + fn from(item: api::AppEngineHttpRequest) -> Self { + Self{ + http_method: item.http_method().into(), + app_engine_routing: item.app_engine_routing.map(AppEngineRouting::from), + relative_uri: item.relative_uri, + headers: item.headers, + body: item.body + } + } +} + impl AppEngineHttpRequest { /// The HTTP method of this request. pub fn http_method(&self) -> HttpMethod { @@ -373,6 +385,19 @@ pub struct HttpRequest { pub(crate) authorization_header: Option, } +impl From for HttpRequest{ + fn from(item: api::HttpRequest) -> Self { + let method = item.http_method(); + Self{ + url: item.url, + http_method: method.into(), + headers: item.headers, + body: item.body, + authorization_header: item.authorization_header.map(AuthorizationHeader::from) + } + } +} + impl HttpRequest { /// The full url path that the request will be sent to. pub fn url(&self) -> &str { @@ -419,3 +444,12 @@ pub enum PayloadType { /// HTTP request that targets any public URI HttpRequest(HttpRequest), } + +impl From for PayloadType{ + fn from(item: api::task::PayloadType) -> Self { + match item{ + api::task::PayloadType::AppEngineHttpRequest(request) => PayloadType::AppEngineHttpRequest(request.into()), + api::task::PayloadType::HttpRequest(request) => PayloadType::HttpRequest(request.into()), + } + } +} diff --git a/google-cloud/src/tasks/utils.rs b/google-cloud/src/tasks/utils.rs index 76d40d9e..4e94d068 100644 --- a/google-cloud/src/tasks/utils.rs +++ b/google-cloud/src/tasks/utils.rs @@ -1,12 +1,29 @@ use chrono::{NaiveDateTime, Duration}; +use tonic::Status; +use crate::tasks::api; -pub fn convert_timestamp(timestamp: NaiveDateTime) -> prost_types::Timestamp{ +const NANOS_PER_SEC: i64 = 1_000_000_000; + +pub fn timestamp_to_prost(timestamp: NaiveDateTime) -> prost_types::Timestamp{ prost_types::Timestamp{ seconds: timestamp.timestamp(), nanos: timestamp.timestamp_subsec_nanos() as i32 } } -pub fn convert_duration(duration: Duration) -> prost_types::Duration{ +pub fn prost_to_timestamp(timestamp: prost_types::Timestamp) -> NaiveDateTime { + NaiveDateTime::from_timestamp(timestamp.seconds, timestamp.nanos as u32) +} + +pub fn duration_to_prost(duration: Duration) -> prost_types::Duration{ let seconds = duration.num_seconds(); let duration_rem = duration - chrono::Duration::seconds(seconds); let nanos = duration_rem.num_nanoseconds().unwrap_or(0) as i32; prost_types::Duration{ seconds, nanos } } + +pub fn prost_to_duration(duration: prost_types::Duration) -> Duration { + Duration::nanoseconds(duration.seconds * NANOS_PER_SEC + (duration.nanos as i64)) +} + +/// For now this drops details as not sure how to convert +pub fn convert_status(prost_status: api::google::rpc::Status) -> Status { + Status::new(prost_status.code.into(), prost_status.message) +} From 0ddec6c851d18b330826af1a5ad9bfd6a0122e9e Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 17:07:31 +0300 Subject: [PATCH 06/22] Add create_task --- google-cloud/src/tasks/queue.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs index 1a9e5e99..595697cb 100644 --- a/google-cloud/src/tasks/queue.rs +++ b/google-cloud/src/tasks/queue.rs @@ -1,4 +1,4 @@ -use crate::tasks::api; +use crate::tasks::{api, TaskConfig}; use crate::tasks::{Client, Error, Task}; /// Represents a Queue @@ -33,12 +33,15 @@ impl Queue { } /// Create a new task in this queue - pub async fn new_task(&mut self) -> Result{ + pub async fn new_task(&mut self, config: TaskConfig) -> Result{ let request = api::CreateTaskRequest{ parent: self.name.clone(), - task: None, + task: Some(config.into()), response_view: 0 }; - todo!() + let request = self.client.construct_request(request).await?; + let response = self.client.service.create_task(request).await?; + let task = response.into_inner(); + Ok((self.client.clone(), task).into()) } } From 5a96b1af96d6c59ad4b917d86424394decc08d0f Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 18:15:02 +0300 Subject: [PATCH 07/22] Add comments --- google-cloud/src/tasks/queue.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs index 595697cb..4bc6a2f8 100644 --- a/google-cloud/src/tasks/queue.rs +++ b/google-cloud/src/tasks/queue.rs @@ -33,6 +33,9 @@ impl Queue { } /// Create a new task in this queue + /// Requires the following roles on service account: + /// - roles/cloudtasks.viewer + /// - roles/cloudtasks.enqueuer pub async fn new_task(&mut self, config: TaskConfig) -> Result{ let request = api::CreateTaskRequest{ parent: self.name.clone(), From 40edce8bc3bc7a87ae28e313f50e759f5a231c46 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 19:12:49 +0300 Subject: [PATCH 08/22] Try adding routing metadata --- google-cloud/src/tasks/client.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/google-cloud/src/tasks/client.rs b/google-cloud/src/tasks/client.rs index 946d6905..e5a00284 100644 --- a/google-cloud/src/tasks/client.rs +++ b/google-cloud/src/tasks/client.rs @@ -11,6 +11,8 @@ use crate::tasks::api; use crate::tasks::api::cloud_tasks_client::CloudTasksClient; use crate::tasks::{Error, Queue}; +const ROUTING_METADATA_KEY: &str = "x-goog-request-params"; + /// The Cloud Tasks client, tied to a specific project and location. #[derive(Clone)] pub struct Client { @@ -110,15 +112,18 @@ impl Client { /// Get a queue by name. pub async fn queue(&mut self, id: &str) -> Result, Error> { + let name = format!( + "projects/{0}/locations/{1}/queues/{2}", + self.project_name.as_str(), + self.location_id.as_str(), + id, + ); let request = api::GetQueueRequest { - name: format!( - "projects/{0}/locations/{1}/queues/{2}", - self.project_name.as_str(), - self.location_id.as_str(), - id, - ), + name: name.clone(), }; - let request = self.construct_request(request).await?; + let mut request = self.construct_request(request).await?; + // Add routing metadata + request.metadata_mut().insert(ROUTING_METADATA_KEY, format!("name:{}", name).parse().unwrap()); let response = self.service.get_queue(request).await?; let queue = response.into_inner(); From eb9b6dd88ef57c00551120182d7ac637b63f6eef Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 19:48:40 +0300 Subject: [PATCH 09/22] Update metadata --- google-cloud/src/tasks/client.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/google-cloud/src/tasks/client.rs b/google-cloud/src/tasks/client.rs index e5a00284..47da92a2 100644 --- a/google-cloud/src/tasks/client.rs +++ b/google-cloud/src/tasks/client.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use tokio::sync::Mutex; use tonic::transport::{Certificate, Channel, ClientTlsConfig}; use tonic::{IntoRequest, Request}; +use tonic::metadata::MetadataValue; use crate::authorize::{ApplicationCredentials, TokenManager, TLS_CERTS}; use crate::tasks::api; @@ -123,7 +124,7 @@ impl Client { }; let mut request = self.construct_request(request).await?; // Add routing metadata - request.metadata_mut().insert(ROUTING_METADATA_KEY, format!("name:{}", name).parse().unwrap()); + request.metadata_mut().insert(ROUTING_METADATA_KEY, MetadataValue::from_str(format!("name:{}", name).as_str()).unwrap()); let response = self.service.get_queue(request).await?; let queue = response.into_inner(); From 0f48e4e87a717a0b93872dad1ffa94e9289856f9 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 19:50:53 +0300 Subject: [PATCH 10/22] Update metadata --- google-cloud/src/tasks/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud/src/tasks/client.rs b/google-cloud/src/tasks/client.rs index 47da92a2..88e79bd3 100644 --- a/google-cloud/src/tasks/client.rs +++ b/google-cloud/src/tasks/client.rs @@ -124,7 +124,7 @@ impl Client { }; let mut request = self.construct_request(request).await?; // Add routing metadata - request.metadata_mut().insert(ROUTING_METADATA_KEY, MetadataValue::from_str(format!("name:{}", name).as_str()).unwrap()); + request.metadata_mut().insert("x-goog-request-params", MetadataValue::from_str(format!("name:{}", name).as_str()).unwrap()); let response = self.service.get_queue(request).await?; let queue = response.into_inner(); From 7d81acee535a465303dbcf1a8bcee636c4e234b8 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 19:51:37 +0300 Subject: [PATCH 11/22] Update metadata --- google-cloud/src/tasks/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud/src/tasks/client.rs b/google-cloud/src/tasks/client.rs index 88e79bd3..296109d8 100644 --- a/google-cloud/src/tasks/client.rs +++ b/google-cloud/src/tasks/client.rs @@ -124,7 +124,7 @@ impl Client { }; let mut request = self.construct_request(request).await?; // Add routing metadata - request.metadata_mut().insert("x-goog-request-params", MetadataValue::from_str(format!("name:{}", name).as_str()).unwrap()); + request.metadata_mut().insert(ROUTING_METADATA_KEY, MetadataValue::from_str(format!("name={}", name).as_str()).unwrap()); let response = self.service.get_queue(request).await?; let queue = response.into_inner(); From 5599bf031e354e663f2e2105569238f4428c938c Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 20:02:29 +0300 Subject: [PATCH 12/22] Add parent to task creation --- google-cloud/src/tasks/client.rs | 6 +++--- google-cloud/src/tasks/queue.rs | 16 +++------------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/google-cloud/src/tasks/client.rs b/google-cloud/src/tasks/client.rs index 296109d8..094040d7 100644 --- a/google-cloud/src/tasks/client.rs +++ b/google-cloud/src/tasks/client.rs @@ -12,7 +12,7 @@ use crate::tasks::api; use crate::tasks::api::cloud_tasks_client::CloudTasksClient; use crate::tasks::{Error, Queue}; -const ROUTING_METADATA_KEY: &str = "x-goog-request-params"; +pub(crate) const ROUTING_METADATA_KEY: &str = "x-goog-request-params"; /// The Cloud Tasks client, tied to a specific project and location. #[derive(Clone)] @@ -112,7 +112,7 @@ impl Client { } /// Get a queue by name. - pub async fn queue(&mut self, id: &str) -> Result, Error> { + pub async fn queue(&mut self, id: &str) -> Result { let name = format!( "projects/{0}/locations/{1}/queues/{2}", self.project_name.as_str(), @@ -128,6 +128,6 @@ impl Client { let response = self.service.get_queue(request).await?; let queue = response.into_inner(); - Ok(Some(Queue::new(self.clone(), queue.name))) + Ok(Queue::new(self.clone(), queue.name)) } } diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs index 4bc6a2f8..da5761a2 100644 --- a/google-cloud/src/tasks/queue.rs +++ b/google-cloud/src/tasks/queue.rs @@ -1,4 +1,4 @@ -use crate::tasks::{api, TaskConfig}; +use crate::tasks::{api, TaskConfig, ROUTING_METADATA_KEY}; use crate::tasks::{Client, Error, Task}; /// Represents a Queue @@ -21,17 +21,6 @@ impl Queue { self.name.rsplit('/').next().unwrap() } - /// Delete the queue. - pub async fn delete(mut self) -> Result<(), Error> { - let request = api::DeleteQueueRequest { - name: self.name.clone(), - }; - let request = self.client.construct_request(request).await?; - self.client.service.delete_queue(request).await?; - - Ok(()) - } - /// Create a new task in this queue /// Requires the following roles on service account: /// - roles/cloudtasks.viewer @@ -42,7 +31,8 @@ impl Queue { task: Some(config.into()), response_view: 0 }; - let request = self.client.construct_request(request).await?; + let mut request = self.client.construct_request(request).await?; + request.metadata_mut().insert(ROUTING_METADATA_KEY, MetadataValue::from_str(format!("parent={}", self.name.clone()).as_str()).unwrap()); let response = self.client.service.create_task(request).await?; let task = response.into_inner(); Ok((self.client.clone(), task).into()) From 7b739d3a6b3d7e68de9e83684e5517810577d2b6 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 20:03:50 +0300 Subject: [PATCH 13/22] Cargo fmt --- google-cloud/build.rs | 4 +- google-cloud/src/tasks/client.rs | 22 ++++-- google-cloud/src/tasks/mod.rs | 12 ++-- google-cloud/src/tasks/queue.rs | 11 +-- google-cloud/src/tasks/task.rs | 48 +++++++------ google-cloud/src/tasks/task_authorization.rs | 53 +++++++++----- google-cloud/src/tasks/task_request_types.rs | 76 +++++++++++--------- google-cloud/src/tasks/utils.rs | 15 ++-- 8 files changed, 143 insertions(+), 98 deletions(-) diff --git a/google-cloud/build.rs b/google-cloud/build.rs index 0e97d345..2dd918b0 100644 --- a/google-cloud/build.rs +++ b/google-cloud/build.rs @@ -13,8 +13,8 @@ fn main() -> Result<(), Box> { ), ( ["protos/google/cloud/tasks/v2beta3/cloudtasks.proto"], - "src/tasks/api" - ) + "src/tasks/api", + ), ]; for (proto_files, out_dir) in protos.iter() { diff --git a/google-cloud/src/tasks/client.rs b/google-cloud/src/tasks/client.rs index 094040d7..3d08d238 100644 --- a/google-cloud/src/tasks/client.rs +++ b/google-cloud/src/tasks/client.rs @@ -3,9 +3,9 @@ use std::fs::File; use std::sync::Arc; use tokio::sync::Mutex; +use tonic::metadata::MetadataValue; use tonic::transport::{Certificate, Channel, ClientTlsConfig}; use tonic::{IntoRequest, Request}; -use tonic::metadata::MetadataValue; use crate::authorize::{ApplicationCredentials, TokenManager, TLS_CERTS}; use crate::tasks::api; @@ -45,7 +45,10 @@ impl Client { /// Create a new client for the specified project. /// /// Credentials are looked up in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. - pub async fn new(project_name: impl Into, location_id: impl Into) -> Result { + pub async fn new( + project_name: impl Into, + location_id: impl Into, + ) -> Result { let path = env::var("GOOGLE_APPLICATION_CREDENTIALS")?; let file = File::open(path)?; let creds = json::from_reader(file)?; @@ -88,7 +91,11 @@ impl Client { loop { let request = api::ListQueuesRequest { - parent: format!("projects/{0}/locations/{1}", self.project_name.as_str(), self.location_id.as_str()), + parent: format!( + "projects/{0}/locations/{1}", + self.project_name.as_str(), + self.location_id.as_str() + ), filter: filter.to_string(), page_size, page_token, @@ -119,12 +126,13 @@ impl Client { self.location_id.as_str(), id, ); - let request = api::GetQueueRequest { - name: name.clone(), - }; + let request = api::GetQueueRequest { name: name.clone() }; let mut request = self.construct_request(request).await?; // Add routing metadata - request.metadata_mut().insert(ROUTING_METADATA_KEY, MetadataValue::from_str(format!("name={}", name).as_str()).unwrap()); + request.metadata_mut().insert( + ROUTING_METADATA_KEY, + MetadataValue::from_str(format!("name={}", name).as_str()).unwrap(), + ); let response = self.service.get_queue(request).await?; let queue = response.into_inner(); diff --git a/google-cloud/src/tasks/mod.rs b/google-cloud/src/tasks/mod.rs index 16a83176..a6348f09 100644 --- a/google-cloud/src/tasks/mod.rs +++ b/google-cloud/src/tasks/mod.rs @@ -1,11 +1,11 @@ -mod utils; -mod task_request_types; -mod task_authorization; mod client; -mod task; mod queue; +mod task; +mod task_authorization; +mod task_request_types; +mod utils; mod api { - pub mod google{ + pub mod google { pub mod api { include!("api/google.api.rs"); } @@ -35,8 +35,8 @@ mod api { } pub use self::client::*; -pub use self::task::*; pub use self::queue::*; +pub use self::task::*; pub use self::task_authorization::*; pub use self::task_request_types::*; pub(crate) use self::utils::*; diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs index da5761a2..16699717 100644 --- a/google-cloud/src/tasks/queue.rs +++ b/google-cloud/src/tasks/queue.rs @@ -25,14 +25,17 @@ impl Queue { /// Requires the following roles on service account: /// - roles/cloudtasks.viewer /// - roles/cloudtasks.enqueuer - pub async fn new_task(&mut self, config: TaskConfig) -> Result{ - let request = api::CreateTaskRequest{ + pub async fn new_task(&mut self, config: TaskConfig) -> Result { + let request = api::CreateTaskRequest { parent: self.name.clone(), task: Some(config.into()), - response_view: 0 + response_view: 0, }; let mut request = self.client.construct_request(request).await?; - request.metadata_mut().insert(ROUTING_METADATA_KEY, MetadataValue::from_str(format!("parent={}", self.name.clone()).as_str()).unwrap()); + request.metadata_mut().insert( + ROUTING_METADATA_KEY, + MetadataValue::from_str(format!("parent={}", self.name.clone()).as_str()).unwrap(), + ); let response = self.client.service.create_task(request).await?; let task = response.into_inner(); Ok((self.client.clone(), task).into()) diff --git a/google-cloud/src/tasks/task.rs b/google-cloud/src/tasks/task.rs index 44b78ae0..1bdc9187 100644 --- a/google-cloud/src/tasks/task.rs +++ b/google-cloud/src/tasks/task.rs @@ -1,6 +1,10 @@ -use crate::tasks::{api, PayloadTypeConfig, PayloadType, AppEngineHttpRequestConfig, HttpRequestConfig, timestamp_to_prost, duration_to_prost, prost_to_timestamp, convert_status, prost_to_duration}; use crate::tasks::Client; -use chrono::{NaiveDateTime, Duration}; +use crate::tasks::{ + api, convert_status, duration_to_prost, prost_to_duration, prost_to_timestamp, + timestamp_to_prost, AppEngineHttpRequestConfig, HttpRequestConfig, PayloadType, + PayloadTypeConfig, +}; +use chrono::{Duration, NaiveDateTime}; use tonic::Status; /// Type of task view - basic or full @@ -23,9 +27,9 @@ pub enum View { Full, } -impl From for api::task::View{ +impl From for api::task::View { fn from(item: View) -> Self { - match item{ + match item { View::Unspecified => api::task::View::Unspecified, View::Basic => api::task::View::Basic, View::Full => api::task::View::Full, @@ -33,9 +37,9 @@ impl From for api::task::View{ } } -impl From for View{ +impl From for View { fn from(item: api::task::View) -> Self { - match item{ + match item { api::task::View::Unspecified => View::Unspecified, api::task::View::Basic => View::Basic, api::task::View::Full => View::Full, @@ -64,7 +68,7 @@ pub struct TaskConfig { impl From for api::Task { fn from(item: TaskConfig) -> Self { - Self{ + Self { name: item.id.unwrap_or("".to_string()), schedule_time: item.schedule_time.map(timestamp_to_prost), create_time: None, @@ -74,28 +78,28 @@ impl From for api::Task { first_attempt: None, last_attempt: None, view: 0, - payload_type: Some(item.payload_type.into()) + payload_type: Some(item.payload_type.into()), } } } -impl TaskConfig{ +impl TaskConfig { /// Create new AppEngine HTTP task - pub fn new_appengine_http_task(task: AppEngineHttpRequestConfig) -> Self{ - Self{ + pub fn new_appengine_http_task(task: AppEngineHttpRequestConfig) -> Self { + Self { id: None, schedule_time: None, dispatch_deadline: None, - payload_type: PayloadTypeConfig::AppEngineHttpRequest(task) + payload_type: PayloadTypeConfig::AppEngineHttpRequest(task), } } /// Create new HTTP task - pub fn new_http_task(task: HttpRequestConfig) -> Self{ - Self{ + pub fn new_http_task(task: HttpRequestConfig) -> Self { + Self { id: None, schedule_time: None, dispatch_deadline: None, - payload_type: PayloadTypeConfig::HttpRequest(task) + payload_type: PayloadTypeConfig::HttpRequest(task), } } /// Set Task ID @@ -126,18 +130,18 @@ pub struct Attempt { pub(crate) response_status: Option, } -impl From for Attempt{ +impl From for Attempt { fn from(item: api::Attempt) -> Self { - Self{ + Self { schedule_time: item.schedule_time.map(prost_to_timestamp), dispatch_time: item.dispatch_time.map(prost_to_timestamp), response_time: item.response_time.map(prost_to_timestamp), - response_status: item.response_status.map(convert_status) + response_status: item.response_status.map(convert_status), } } } -impl Attempt{ +impl Attempt { ///The time that this attempt was scheduled. pub fn schedule_time(&self) -> Option { self.schedule_time @@ -172,11 +176,11 @@ pub struct Task { pub(crate) payload_type: Option, } -impl From<(Client, api::Task)> for Task{ +impl From<(Client, api::Task)> for Task { fn from(item: (Client, api::Task)) -> Self { let (client, task) = item; let view = task.view(); - Self{ + Self { client, name: task.name, schedule_time: task.schedule_time.map(prost_to_timestamp), @@ -187,7 +191,7 @@ impl From<(Client, api::Task)> for Task{ first_attempt: task.first_attempt.map(Attempt::from), last_attempt: task.last_attempt.map(Attempt::from), view: view.into(), - payload_type: task.payload_type.map(PayloadType::from) + payload_type: task.payload_type.map(PayloadType::from), } } } diff --git a/google-cloud/src/tasks/task_authorization.rs b/google-cloud/src/tasks/task_authorization.rs index 02e85197..d05b527e 100644 --- a/google-cloud/src/tasks/task_authorization.rs +++ b/google-cloud/src/tasks/task_authorization.rs @@ -19,20 +19,28 @@ pub enum AuthorizationHeader { OidcToken(OidcToken), } -impl From for api::http_request::AuthorizationHeader{ +impl From for api::http_request::AuthorizationHeader { fn from(item: AuthorizationHeader) -> Self { - match item{ - AuthorizationHeader::OauthToken(token_config) => api::http_request::AuthorizationHeader::OauthToken(token_config.into()), - AuthorizationHeader::OidcToken(token_config) => api::http_request::AuthorizationHeader::OidcToken(token_config.into()), + match item { + AuthorizationHeader::OauthToken(token_config) => { + api::http_request::AuthorizationHeader::OauthToken(token_config.into()) + } + AuthorizationHeader::OidcToken(token_config) => { + api::http_request::AuthorizationHeader::OidcToken(token_config.into()) + } } } } -impl From for AuthorizationHeader{ +impl From for AuthorizationHeader { fn from(item: api::http_request::AuthorizationHeader) -> Self { - match item{ - api::http_request::AuthorizationHeader::OauthToken(token_config) => AuthorizationHeader::OauthToken(token_config.into()), - api::http_request::AuthorizationHeader::OidcToken(token_config) => AuthorizationHeader::OidcToken(token_config.into()), + match item { + api::http_request::AuthorizationHeader::OauthToken(token_config) => { + AuthorizationHeader::OauthToken(token_config.into()) + } + api::http_request::AuthorizationHeader::OidcToken(token_config) => { + AuthorizationHeader::OidcToken(token_config.into()) + } } } } @@ -52,15 +60,21 @@ pub struct OAuthToken { pub scope: String, } -impl From for api::OAuthToken{ +impl From for api::OAuthToken { fn from(item: OAuthToken) -> Self { - Self{ service_account_email: item.service_account_email, scope: item.scope } + Self { + service_account_email: item.service_account_email, + scope: item.scope, + } } } -impl From for OAuthToken{ +impl From for OAuthToken { fn from(item: api::OAuthToken) -> Self { - Self{ service_account_email: item.service_account_email, scope: item.scope } + Self { + service_account_email: item.service_account_email, + scope: item.scope, + } } } @@ -78,15 +92,20 @@ pub struct OidcToken { pub audience: String, } -impl From for api::OidcToken{ +impl From for api::OidcToken { fn from(item: OidcToken) -> Self { - Self{ service_account_email: item.service_account_email, audience: item.audience } + Self { + service_account_email: item.service_account_email, + audience: item.audience, + } } } -impl From for OidcToken{ +impl From for OidcToken { fn from(item: api::OidcToken) -> Self { - Self{ service_account_email: item.service_account_email, audience: item.audience } + Self { + service_account_email: item.service_account_email, + audience: item.audience, + } } } - diff --git a/google-cloud/src/tasks/task_request_types.rs b/google-cloud/src/tasks/task_request_types.rs index 026d6f99..b5741a12 100644 --- a/google-cloud/src/tasks/task_request_types.rs +++ b/google-cloud/src/tasks/task_request_types.rs @@ -1,5 +1,5 @@ +use crate::tasks::{api, AuthorizationHeader}; use std::collections::HashMap; -use crate::tasks::{AuthorizationHeader, api}; /// All supported HTTP methods for Cloud Tasks #[derive(Clone, Copy, Debug)] @@ -22,9 +22,9 @@ pub enum HttpMethod { Options, } -impl From for HttpMethod{ +impl From for HttpMethod { fn from(item: api::HttpMethod) -> Self { - match item{ + match item { api::HttpMethod::Unspecified => HttpMethod::Unspecified, api::HttpMethod::Post => HttpMethod::Post, api::HttpMethod::Get => HttpMethod::Get, @@ -37,9 +37,9 @@ impl From for HttpMethod{ } } -impl From for api::HttpMethod{ +impl From for api::HttpMethod { fn from(item: HttpMethod) -> Self { - match item{ + match item { HttpMethod::Unspecified => api::HttpMethod::Unspecified, HttpMethod::Post => api::HttpMethod::Post, HttpMethod::Get => api::HttpMethod::Get, @@ -67,13 +67,13 @@ pub struct AppEngineRoutingConfig { pub version: Option, } -impl From for api::AppEngineRouting{ +impl From for api::AppEngineRouting { fn from(item: AppEngineRoutingConfig) -> Self { - Self{ + Self { service: item.service.unwrap_or("".to_string()), version: item.version.unwrap_or("".to_string()), instance: "".to_string(), - host: "".to_string() + host: "".to_string(), } } } @@ -87,13 +87,13 @@ pub struct AppEngineRouting { pub(crate) host: String, } -impl From for AppEngineRouting{ +impl From for AppEngineRouting { fn from(item: api::AppEngineRouting) -> Self { - Self{ + Self { service: item.service, version: item.version, instance: item.instance, - host: item.host + host: item.host, } } } @@ -178,21 +178,21 @@ pub struct AppEngineHttpRequestConfig { body: Vec, } -impl From for api::AppEngineHttpRequest{ +impl From for api::AppEngineHttpRequest { fn from(item: AppEngineHttpRequestConfig) -> Self { - let mut request = Self{ + let mut request = Self { http_method: 0, app_engine_routing: item.app_engine_routing.map(|routing| routing.into()), relative_uri: item.relative_uri, headers: item.headers, - body: item.body + body: item.body, }; request.set_http_method(item.http_method.into()); request } } -impl AppEngineHttpRequestConfig{ +impl AppEngineHttpRequestConfig { /// Create new App Engine HTTP request pub fn new() -> Self { Self { @@ -200,7 +200,7 @@ impl AppEngineHttpRequestConfig{ app_engine_routing: None, relative_uri: "".to_string(), headers: Default::default(), - body: vec![] + body: vec![], } } /// Set http method @@ -240,14 +240,14 @@ pub struct AppEngineHttpRequest { body: Vec, } -impl From for AppEngineHttpRequest{ +impl From for AppEngineHttpRequest { fn from(item: api::AppEngineHttpRequest) -> Self { - Self{ + Self { http_method: item.http_method().into(), app_engine_routing: item.app_engine_routing.map(AppEngineRouting::from), relative_uri: item.relative_uri, headers: item.headers, - body: item.body + body: item.body, } } } @@ -328,21 +328,21 @@ pub struct HttpRequestConfig { authorization_header: Option, } -impl From for api::HttpRequest{ +impl From for api::HttpRequest { fn from(item: HttpRequestConfig) -> Self { - let mut request = Self{ + let mut request = Self { url: item.url, http_method: 0, headers: item.headers, body: item.body, - authorization_header: item.authorization_header.map(|header| header.into()) + authorization_header: item.authorization_header.map(|header| header.into()), }; request.set_http_method(item.http_method.into()); request } } -impl HttpRequestConfig{ +impl HttpRequestConfig { /// Create new HttpRequest. URI must be specified at a minimum pub fn new(url: &str) -> Self { Self { @@ -350,7 +350,7 @@ impl HttpRequestConfig{ http_method: HttpMethod::Post, headers: Default::default(), body: vec![], - authorization_header: None + authorization_header: None, } } /// Set http method @@ -385,15 +385,15 @@ pub struct HttpRequest { pub(crate) authorization_header: Option, } -impl From for HttpRequest{ +impl From for HttpRequest { fn from(item: api::HttpRequest) -> Self { let method = item.http_method(); - Self{ + Self { url: item.url, http_method: method.into(), headers: item.headers, body: item.body, - authorization_header: item.authorization_header.map(AuthorizationHeader::from) + authorization_header: item.authorization_header.map(AuthorizationHeader::from), } } } @@ -427,11 +427,15 @@ pub(crate) enum PayloadTypeConfig { HttpRequest(HttpRequestConfig), } -impl From for api::task::PayloadType{ +impl From for api::task::PayloadType { fn from(item: PayloadTypeConfig) -> Self { match item { - PayloadTypeConfig::HttpRequest(request) => api::task::PayloadType::HttpRequest(request.into()), - PayloadTypeConfig::AppEngineHttpRequest(request) => api::task::PayloadType::AppEngineHttpRequest(request.into()), + PayloadTypeConfig::HttpRequest(request) => { + api::task::PayloadType::HttpRequest(request.into()) + } + PayloadTypeConfig::AppEngineHttpRequest(request) => { + api::task::PayloadType::AppEngineHttpRequest(request.into()) + } } } } @@ -445,11 +449,15 @@ pub enum PayloadType { HttpRequest(HttpRequest), } -impl From for PayloadType{ +impl From for PayloadType { fn from(item: api::task::PayloadType) -> Self { - match item{ - api::task::PayloadType::AppEngineHttpRequest(request) => PayloadType::AppEngineHttpRequest(request.into()), - api::task::PayloadType::HttpRequest(request) => PayloadType::HttpRequest(request.into()), + match item { + api::task::PayloadType::AppEngineHttpRequest(request) => { + PayloadType::AppEngineHttpRequest(request.into()) + } + api::task::PayloadType::HttpRequest(request) => { + PayloadType::HttpRequest(request.into()) + } } } } diff --git a/google-cloud/src/tasks/utils.rs b/google-cloud/src/tasks/utils.rs index 4e94d068..e07a6c89 100644 --- a/google-cloud/src/tasks/utils.rs +++ b/google-cloud/src/tasks/utils.rs @@ -1,22 +1,25 @@ -use chrono::{NaiveDateTime, Duration}; -use tonic::Status; use crate::tasks::api; +use chrono::{Duration, NaiveDateTime}; +use tonic::Status; const NANOS_PER_SEC: i64 = 1_000_000_000; -pub fn timestamp_to_prost(timestamp: NaiveDateTime) -> prost_types::Timestamp{ - prost_types::Timestamp{ seconds: timestamp.timestamp(), nanos: timestamp.timestamp_subsec_nanos() as i32 } +pub fn timestamp_to_prost(timestamp: NaiveDateTime) -> prost_types::Timestamp { + prost_types::Timestamp { + seconds: timestamp.timestamp(), + nanos: timestamp.timestamp_subsec_nanos() as i32, + } } pub fn prost_to_timestamp(timestamp: prost_types::Timestamp) -> NaiveDateTime { NaiveDateTime::from_timestamp(timestamp.seconds, timestamp.nanos as u32) } -pub fn duration_to_prost(duration: Duration) -> prost_types::Duration{ +pub fn duration_to_prost(duration: Duration) -> prost_types::Duration { let seconds = duration.num_seconds(); let duration_rem = duration - chrono::Duration::seconds(seconds); let nanos = duration_rem.num_nanoseconds().unwrap_or(0) as i32; - prost_types::Duration{ seconds, nanos } + prost_types::Duration { seconds, nanos } } pub fn prost_to_duration(duration: prost_types::Duration) -> Duration { From 0805fa1350842a583267ec59e1aa677501a1d233 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Thu, 6 Aug 2020 20:15:14 +0300 Subject: [PATCH 14/22] Fix import --- google-cloud/src/tasks/client.rs | 3 +-- google-cloud/src/tasks/queue.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/google-cloud/src/tasks/client.rs b/google-cloud/src/tasks/client.rs index 3d08d238..7c34112f 100644 --- a/google-cloud/src/tasks/client.rs +++ b/google-cloud/src/tasks/client.rs @@ -3,7 +3,6 @@ use std::fs::File; use std::sync::Arc; use tokio::sync::Mutex; -use tonic::metadata::MetadataValue; use tonic::transport::{Certificate, Channel, ClientTlsConfig}; use tonic::{IntoRequest, Request}; @@ -131,7 +130,7 @@ impl Client { // Add routing metadata request.metadata_mut().insert( ROUTING_METADATA_KEY, - MetadataValue::from_str(format!("name={}", name).as_str()).unwrap(), + format!("name={}", name).parse().unwrap(), ); let response = self.service.get_queue(request).await?; let queue = response.into_inner(); diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs index 16699717..6db454ee 100644 --- a/google-cloud/src/tasks/queue.rs +++ b/google-cloud/src/tasks/queue.rs @@ -34,7 +34,7 @@ impl Queue { let mut request = self.client.construct_request(request).await?; request.metadata_mut().insert( ROUTING_METADATA_KEY, - MetadataValue::from_str(format!("parent={}", self.name.clone()).as_str()).unwrap(), + format!("parent={}", self.name.clone()).parse().unwrap(), ); let response = self.client.service.create_task(request).await?; let task = response.into_inner(); From 9173f249ee138a3480ca480e757e05e97a90aa0f Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Fri, 7 Aug 2020 13:27:54 +0300 Subject: [PATCH 15/22] Add routing metadata for ListQueues --- google-cloud/src/tasks/client.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/google-cloud/src/tasks/client.rs b/google-cloud/src/tasks/client.rs index 7c34112f..99a621f6 100644 --- a/google-cloud/src/tasks/client.rs +++ b/google-cloud/src/tasks/client.rs @@ -89,17 +89,23 @@ impl Client { let mut page_token = String::default(); loop { + let parent = format!( + "projects/{0}/locations/{1}", + self.project_name.as_str(), + self.location_id.as_str() + ); let request = api::ListQueuesRequest { - parent: format!( - "projects/{0}/locations/{1}", - self.project_name.as_str(), - self.location_id.as_str() - ), + parent: parent.clone(), filter: filter.to_string(), page_size, page_token, }; - let request = self.construct_request(request).await?; + let mut request = self.construct_request(request).await?; + // Add routing metadata + request.metadata_mut().insert( + ROUTING_METADATA_KEY, + format!("parent={}", parent).parse().unwrap(), + ); let response = self.service.list_queues(request).await?; let response = response.into_inner(); page_token = response.next_page_token; From 67698a57b45adc990152405e83f947ca25d05a6e Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Mon, 10 Aug 2020 11:47:54 +0300 Subject: [PATCH 16/22] Rename `new_task` to `create_task` to match gRPC name --- google-cloud/src/tasks/queue.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs index 6db454ee..5d539cb3 100644 --- a/google-cloud/src/tasks/queue.rs +++ b/google-cloud/src/tasks/queue.rs @@ -25,7 +25,7 @@ impl Queue { /// Requires the following roles on service account: /// - roles/cloudtasks.viewer /// - roles/cloudtasks.enqueuer - pub async fn new_task(&mut self, config: TaskConfig) -> Result { + pub async fn create_task(&mut self, config: TaskConfig) -> Result { let request = api::CreateTaskRequest { parent: self.name.clone(), task: Some(config.into()), From 935b1954c7cb5f91eece71b19c39661f490e1e3c Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Mon, 10 Aug 2020 12:05:33 +0300 Subject: [PATCH 17/22] Add `get_task` and `delete_task` --- google-cloud/src/tasks/queue.rs | 17 ++++++++++++++++- google-cloud/src/tasks/task.rs | 22 ++++++++++++++++++++-- google-cloud/src/tests/tasks.rs | 0 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 google-cloud/src/tests/tasks.rs diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs index 5d539cb3..9e04a1c9 100644 --- a/google-cloud/src/tasks/queue.rs +++ b/google-cloud/src/tasks/queue.rs @@ -1,4 +1,4 @@ -use crate::tasks::{api, TaskConfig, ROUTING_METADATA_KEY}; +use crate::tasks::{api, TaskConfig, ROUTING_METADATA_KEY, View}; use crate::tasks::{Client, Error, Task}; /// Represents a Queue @@ -40,4 +40,19 @@ impl Queue { let task = response.into_inner(); Ok((self.client.clone(), task).into()) } + + /// Get task from this queue by ID (name) + pub async fn get_task(&mut self, task_id: &str, view: Option) -> Result { + let name = format!("{}/{}", self.name.clone(), task_id); + let view : api::task::View = view.unwrap_or_default().into(); + let request = api::GetTaskRequest{ name: name.clone(), response_view: view as i32 }; + let mut request = self.client.construct_request(request).await?; + request.metadata_mut().insert( + ROUTING_METADATA_KEY, + format!("name={}", name).parse().unwrap(), + ); + let response = self.client.service.get_task(request).await?; + let task = response.into_inner(); + Ok((self.client.clone(), task).into()) + } } diff --git a/google-cloud/src/tasks/task.rs b/google-cloud/src/tasks/task.rs index 1bdc9187..59bfb3a1 100644 --- a/google-cloud/src/tasks/task.rs +++ b/google-cloud/src/tasks/task.rs @@ -1,8 +1,8 @@ -use crate::tasks::Client; +use crate::tasks::{Client, ROUTING_METADATA_KEY}; use crate::tasks::{ api, convert_status, duration_to_prost, prost_to_duration, prost_to_timestamp, timestamp_to_prost, AppEngineHttpRequestConfig, HttpRequestConfig, PayloadType, - PayloadTypeConfig, + PayloadTypeConfig, Error }; use chrono::{Duration, NaiveDateTime}; use tonic::Status; @@ -27,6 +27,12 @@ pub enum View { Full, } +impl Default for View { + fn default() -> Self { + Self::Unspecified + } +} + impl From for api::task::View { fn from(item: View) -> Self { match item { @@ -237,4 +243,16 @@ impl Task { pub fn payload_type(&self) -> Option<&PayloadType> { self.payload_type.as_ref() } + + /// Delete this task + pub async fn delete_task(mut self) -> Result<(), Error> { + let request = api::DeleteTaskRequest{ name: name.clone() }; + let mut request = self.client.construct_request(request).await?; + request.metadata_mut().insert( + ROUTING_METADATA_KEY, + format!("name={}", name).parse().unwrap(), + ); + let response = self.client.service.delete_task(request).await?; + Ok(response.into_inner()) + } } diff --git a/google-cloud/src/tests/tasks.rs b/google-cloud/src/tests/tasks.rs new file mode 100644 index 00000000..e69de29b From ef8c17c0f977eb59f799d471bdfdbbaa584320ae Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Mon, 10 Aug 2020 12:09:50 +0300 Subject: [PATCH 18/22] Fix reference --- google-cloud/src/tasks/task.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/google-cloud/src/tasks/task.rs b/google-cloud/src/tasks/task.rs index 59bfb3a1..5be79d98 100644 --- a/google-cloud/src/tasks/task.rs +++ b/google-cloud/src/tasks/task.rs @@ -246,11 +246,11 @@ impl Task { /// Delete this task pub async fn delete_task(mut self) -> Result<(), Error> { - let request = api::DeleteTaskRequest{ name: name.clone() }; + let request = api::DeleteTaskRequest{ name: self.name.clone() }; let mut request = self.client.construct_request(request).await?; request.metadata_mut().insert( ROUTING_METADATA_KEY, - format!("name={}", name).parse().unwrap(), + format!("name={}", self.name()).parse().unwrap(), ); let response = self.client.service.delete_task(request).await?; Ok(response.into_inner()) From 007e0c1f00c0799c32475387df176acf33e0f041 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Mon, 10 Aug 2020 12:26:52 +0300 Subject: [PATCH 19/22] Clarify docs --- google-cloud/src/tasks/queue.rs | 1 + google-cloud/src/tasks/task.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs index 9e04a1c9..070d9101 100644 --- a/google-cloud/src/tasks/queue.rs +++ b/google-cloud/src/tasks/queue.rs @@ -42,6 +42,7 @@ impl Queue { } /// Get task from this queue by ID (name) + /// Only the `id` part of the task name should be supplied pub async fn get_task(&mut self, task_id: &str, view: Option) -> Result { let name = format!("{}/{}", self.name.clone(), task_id); let view : api::task::View = view.unwrap_or_default().into(); diff --git a/google-cloud/src/tasks/task.rs b/google-cloud/src/tasks/task.rs index 5be79d98..07520e1c 100644 --- a/google-cloud/src/tasks/task.rs +++ b/google-cloud/src/tasks/task.rs @@ -203,6 +203,11 @@ impl From<(Client, api::Task)> for Task { } impl Task { + /// Returns the unique identifier within its queue + pub fn id(&self) -> &str { + self.name.rsplit('/').next().unwrap() + } + /// The task's full name. pub fn name(&self) -> &str { self.name.as_str() From 94f96fafcdf318a5f49225b33de68b1571ca9151 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Mon, 10 Aug 2020 12:33:01 +0300 Subject: [PATCH 20/22] Fix task name --- google-cloud/src/tasks/queue.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs index 070d9101..f6cd77a1 100644 --- a/google-cloud/src/tasks/queue.rs +++ b/google-cloud/src/tasks/queue.rs @@ -44,7 +44,7 @@ impl Queue { /// Get task from this queue by ID (name) /// Only the `id` part of the task name should be supplied pub async fn get_task(&mut self, task_id: &str, view: Option) -> Result { - let name = format!("{}/{}", self.name.clone(), task_id); + let name = format!("{}/tasks/{}", self.name.clone(), task_id); let view : api::task::View = view.unwrap_or_default().into(); let request = api::GetTaskRequest{ name: name.clone(), response_view: view as i32 }; let mut request = self.client.construct_request(request).await?; From 9a98da4a663c066498e41353b693090fffbb4077 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Mon, 10 Aug 2020 13:02:12 +0300 Subject: [PATCH 21/22] Add disabled test --- google-cloud/src/tests/mod.rs | 3 ++ google-cloud/src/tests/tasks.rs | 62 +++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/google-cloud/src/tests/mod.rs b/google-cloud/src/tests/mod.rs index ad78f479..a3b1c9bb 100644 --- a/google-cloud/src/tests/mod.rs +++ b/google-cloud/src/tests/mod.rs @@ -6,6 +6,9 @@ mod pubsub; mod storage; #[cfg(feature = "vision")] mod vision; +#[cfg(feature = "tasks")] +mod tasks; + use crate::authorize::ApplicationCredentials; diff --git a/google-cloud/src/tests/tasks.rs b/google-cloud/src/tests/tasks.rs index e69de29b..cdc64e84 100644 --- a/google-cloud/src/tests/tasks.rs +++ b/google-cloud/src/tests/tasks.rs @@ -0,0 +1,62 @@ +// use crate::tasks; +// use chrono::{Utc, Duration}; +// +// macro_rules! assert_ok { +// ($expr:expr) => { +// match $expr { +// Ok(value) => value, +// Err(err) => { +// panic!("asserted result is an error: {}", err); +// } +// } +// }; +// } +// +// macro_rules! assert_some { +// ($expr:expr) => { +// match $expr { +// Some(value) => value, +// None => { +// panic!("asserted option is an none"); +// } +// } +// }; +// } +// +// async fn setup_client() -> Result { +// let creds = super::load_creds(); +// let location = env!("GCP_QUEUE_LOCATION_ID"); +// tasks::Client::from_credentials(env!("GCP_TEST_PROJECT"), location, creds).await +// } +// +// #[tokio::test] +// async fn test_task_create_read_delete() { +// //? Setup test client. +// let mut client = assert_ok!(setup_client().await); +// +// //? Get test queue +// let queue = client.queue(env!("GCP_TEST_TOPIC")).await; +// let mut queue = assert_ok!(queue); +// +// //? Create test task +// let request_config = tasks::HttpRequestConfig::new("https://example.com") +// .http_method(tasks::HttpMethod::Get) +// .header( +// "X-Test-Header-One", +// "Header value one", +// ) +// .header("X-Test-Header-Two", "Header Value Two") +// .body("some payload"); +// +// let task_config = tasks::TaskConfig::new_http_task(request_config) +// .schedule_time(Utc::now().naive_utc() + Duration::minutes(10)); +// let task = assert_ok!(queue.create_task(task_config).await); +// +// //? Check can retrieve created task +// let stored_task = queue.get_task(task.id(), None).await; +// let mut stored_task = assert_ok!(stored_task); +// +// //? Check can delete the task +// let delete_result = stored_task.delete_task().await; +// assert_ok!(delete_result); +// } From 6736c915b8a5fe053e5e8a49a8bbb0fe84eec367 Mon Sep 17 00:00:00 2001 From: oleksandr <0init0@gmail.com> Date: Mon, 10 Aug 2020 13:04:49 +0300 Subject: [PATCH 22/22] Cargo fmt --- google-cloud/src/tasks/queue.rs | 9 ++++++--- google-cloud/src/tasks/task.rs | 10 ++++++---- google-cloud/src/tests/mod.rs | 5 ++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/google-cloud/src/tasks/queue.rs b/google-cloud/src/tasks/queue.rs index f6cd77a1..123ad402 100644 --- a/google-cloud/src/tasks/queue.rs +++ b/google-cloud/src/tasks/queue.rs @@ -1,4 +1,4 @@ -use crate::tasks::{api, TaskConfig, ROUTING_METADATA_KEY, View}; +use crate::tasks::{api, TaskConfig, View, ROUTING_METADATA_KEY}; use crate::tasks::{Client, Error, Task}; /// Represents a Queue @@ -45,8 +45,11 @@ impl Queue { /// Only the `id` part of the task name should be supplied pub async fn get_task(&mut self, task_id: &str, view: Option) -> Result { let name = format!("{}/tasks/{}", self.name.clone(), task_id); - let view : api::task::View = view.unwrap_or_default().into(); - let request = api::GetTaskRequest{ name: name.clone(), response_view: view as i32 }; + let view: api::task::View = view.unwrap_or_default().into(); + let request = api::GetTaskRequest { + name: name.clone(), + response_view: view as i32, + }; let mut request = self.client.construct_request(request).await?; request.metadata_mut().insert( ROUTING_METADATA_KEY, diff --git a/google-cloud/src/tasks/task.rs b/google-cloud/src/tasks/task.rs index 07520e1c..0a106327 100644 --- a/google-cloud/src/tasks/task.rs +++ b/google-cloud/src/tasks/task.rs @@ -1,9 +1,9 @@ -use crate::tasks::{Client, ROUTING_METADATA_KEY}; use crate::tasks::{ api, convert_status, duration_to_prost, prost_to_duration, prost_to_timestamp, - timestamp_to_prost, AppEngineHttpRequestConfig, HttpRequestConfig, PayloadType, - PayloadTypeConfig, Error + timestamp_to_prost, AppEngineHttpRequestConfig, Error, HttpRequestConfig, PayloadType, + PayloadTypeConfig, }; +use crate::tasks::{Client, ROUTING_METADATA_KEY}; use chrono::{Duration, NaiveDateTime}; use tonic::Status; @@ -251,7 +251,9 @@ impl Task { /// Delete this task pub async fn delete_task(mut self) -> Result<(), Error> { - let request = api::DeleteTaskRequest{ name: self.name.clone() }; + let request = api::DeleteTaskRequest { + name: self.name.clone(), + }; let mut request = self.client.construct_request(request).await?; request.metadata_mut().insert( ROUTING_METADATA_KEY, diff --git a/google-cloud/src/tests/mod.rs b/google-cloud/src/tests/mod.rs index a3b1c9bb..7e00e458 100644 --- a/google-cloud/src/tests/mod.rs +++ b/google-cloud/src/tests/mod.rs @@ -4,11 +4,10 @@ mod datastore; mod pubsub; #[cfg(feature = "storage")] mod storage; -#[cfg(feature = "vision")] -mod vision; #[cfg(feature = "tasks")] mod tasks; - +#[cfg(feature = "vision")] +mod vision; use crate::authorize::ApplicationCredentials;