Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cloud API: Nexus Incoming/Outgoing Service Definitions #16

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions temporal/api/cloud/account/v1/message.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
syntax = "proto3";

package temporal.api.cloud.account.v1;

option go_package = "go.temporal.io/api/cloud/account/v1;account";

message MetricsSpec {
// Enables the endpoint from which clients can scrape all their namespace metrics.
bool enabled = 1;
// The base64 encoded ca cert(s) in PEM format that clients connecting to the metrics endpoint can use for authentication.
// This must only be one value, but the CA can have a chain.
string accepted_client_ca = 2;
}

message AccountSpec {
// The metrics specification for this account.
MetricsSpec metrics = 1;
}

message Metrics {
// The prometheus metrics endpoint uri.
// This is only populated when the metrics is enabled in the metrics specification.
string uri = 1;
}

message Account {
// The account specification.
AccountSpec spec = 1;
// The current version of the account specification.
// The next update operation will have to include this version.
string resource_version = 2;
// The current state of the account.
// Possible values: activating, activationfailed, active, updating, updatefailed, deleting, deletefailed, deleted, suspending, suspendfailed, suspended.
// For any failed state, reach out to Temporal Cloud support for remediation.
string state = 3;
// The id of the async operation that is updating the account, if any.
string async_operation_id = 4;
// Information related to metrics.
Metrics metrics = 5;
}
210 changes: 210 additions & 0 deletions temporal/api/cloud/cloudservice/v1/request_response.proto
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ option go_package = "go.temporal.io/api/cloud/cloudservice/v1;cloudservice";
import "temporal/api/cloud/operation/v1/message.proto";
import "temporal/api/cloud/identity/v1/message.proto";
import "temporal/api/cloud/namespace/v1/message.proto";
import "temporal/api/cloud/nexus/v1/message.proto";
import "temporal/api/cloud/region/v1/message.proto";
import "temporal/api/cloud/account/v1/message.proto";

message GetUsersRequest {
// The requested size of the page to retrieve - optional.
Expand Down Expand Up @@ -229,3 +231,211 @@ message GetRegionResponse {
// The temporal cloud region.
temporal.api.cloud.region.v1.Region region = 1;
}

message GetIncomingServicesRequest {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wonder why not call this "list" instead of "get", I find this confusing but I figure it's consistent with other cloud APIs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please mention if these are AND or OR filters in the comment for this message.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah the list vs get is for consistency with existing cloud apis. could have been list.

these are AND filters. will update comments

// The requested size of the page to retrieve - optional.
// Cannot exceed 1000. Defaults to 100.
int32 page_size = 1;

// The page token if this is continuing from another response - optional.
string page_token = 2;

// Filter incoming services by the namespace they route to - optional, treated as an AND if specified.
string namespace = 3;

// Filter incoming services by the task queue they route to - optional, treated as an AND if specified.
string task_queue = 4;

// Filter incoming services by their name - optional, treated as an AND if specified. Specifying this will result in zero or one results.
string name = 5;
}

message GetIncomingServicesResponse {
// The list of incoming services in ascending ids order.
repeated temporal.api.cloud.nexus.v1.IncomingService incoming_services = 1;

// The next page's token.
string next_page_token = 2;
}

message GetIncomingServiceRequest {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
message GetIncomingServiceRequest {
message GetIncomingServiceByIdRequest {

Just in case we want to add a "by name" request?
The list approach is also fine, just a bit harder to use IMHO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it simply be 'GetIncomingServiceRequest' and if/when we add by name, we'd add 'GetIncomingServiceByNameRequest'? Or is this against a convention for the 'ById' suffix we already use? I see that in

we named a similar message 'GetUserRequest' even though it takes a user ID.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreeing with sergey here. am inclined towards leaving this as is for now (e.g. GetIncomingServiceRequest) just to be consistent with existing cloud user apis

the weirdness is that when we translate this to HTTP path, we would end up creating a different path at that time probably, but not the end of the world if we have to introduce that

// The id of the incoming service to get.
string incoming_service_id = 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we just call this id? it's already in the context of an GetIncomingServiceRequest.

Copy link
Member Author

@mastermanu mastermanu Mar 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can. I was trying to be consistent with this one: https://github.com/temporalio/api-cloud/blob/main/temporal/api/cloud/cloudservice/v1/request_response.proto#L33 but I definitely wish that used id

will leave as-is for now unless there is strong feeling about it

}

message GetIncomingServiceResponse {
// The incoming service.
temporal.api.cloud.nexus.v1.IncomingService incoming_service = 1;
}

message CreateIncomingServiceRequest {
// The spec for the incoming service.
temporal.api.cloud.nexus.v1.IncomingServiceSpec spec = 1;

// The id to use for this async operation - optional.
string async_operation_id = 2;
}

message CreateIncomingServiceResponse {
// The id of the service that was created.
string incoming_service_id = 1;

// The async operation.
temporal.api.cloud.operation.v1.AsyncOperation async_operation = 2;
}

message UpdateIncomingServiceRequest {
// The id of the incoming service to update.
string incoming_service_id = 1;

// The updated incoming service specification.
temporal.api.cloud.nexus.v1.IncomingServiceSpec spec = 2;

// The version of the incoming service for which this update is intended for.
// The latest version can be found in the GetIncomingService operation response.
string resource_version = 3;

// The id to use for this async operation - optional.
string async_operation_id = 4;
}

message UpdateIncomingServiceResponse {
// The async operation.
temporal.api.cloud.operation.v1.AsyncOperation async_operation = 1;
}

message DeleteIncomingServiceRequest {
// The id of the incoming service to delete.
string incoming_service_id = 1;

// The version of the incoming service for which this delete is intended for.
// The latest version can be found in the GetIncomingService operation response.
string resource_version = 2;

// The id to use for this async operation - optional.
string async_operation_id = 3;
}

message DeleteIncomingServiceResponse {
// The async operation
temporal.api.cloud.operation.v1.AsyncOperation async_operation = 1;
}

message GetOutgoingServicesRequest {
// The requested size of the page to retrieve - optional.
// Cannot exceed 1000. Defaults to 100.
int32 page_size = 1;

// The page token if this is continuing from another response - optional.
string page_token = 2;

// The namespace to get all the outgoing services from.
string namespace = 3;

// The name of the outgoing service to filter on - optional. Specifying this will result in zero or one results.
string name = 4;
Comment on lines +335 to +336
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really useful as a filter, this is basically a Get request.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, this is what we did for our Users api (users have a static id, but you call GetUsersRequset and can supply an email address), so this is just an attempt to stay consistent.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anekkanti - thoughts? we basically followed the users model, which relies on this

}

message GetOutgoingServicesResponse {
// The list of outgoing services in ascending name order.
repeated temporal.api.cloud.nexus.v1.OutgoingService outgoing_services = 1;

// The next page's token
string next_page_token = 2;
}

message GetOutgoingServiceRequest {
// The name of the namespace the outgoing service is registered on.
string namespace = 1;

// The name of the outgoing service.
string name = 2;
}

message GetOutgoingServiceResponse {
// The outgoing service
temporal.api.cloud.nexus.v1.OutgoingService outgoing_service = 1;
}

message CreateOutgoingServiceRequest {
// The namespace to register this outgoing service request on.
string namespace = 1;

// The spec for the outgoing service.
temporal.api.cloud.nexus.v1.OutgoingServiceSpec spec = 2;

// The id to use for this async operation - optional.
string async_operation_id = 3;
}

message CreateOutgoingServiceResponse {
// The async operation.
temporal.api.cloud.operation.v1.AsyncOperation async_operation = 1;
}

message GetAccountRequest {
}

message GetAccountResponse {
// The account.
temporal.api.cloud.account.v1.Account account = 1;
}

message UpdateAccountRequest {
// The updated account specification to apply.
temporal.api.cloud.account.v1.AccountSpec spec = 1;
// The version of the account for which this update is intended for.
// The latest version can be found in the GetAccount operation response.
string resource_version = 2;
// The id to use for this async operation.
// Optional, if not provided a random id will be generated.
string async_operation_id = 3;
}

message UpdateAccountResponse {
// The async operation.
temporal.api.cloud.operation.v1.AsyncOperation async_operation = 1;
}

message UpdateOutgoingServiceRequest {
// The name of the namespace the outgoing service is registered on.
string namespace = 1;

// The name of the outgoing service to update.
string name = 2;

// The updated outcoming service specification.
temporal.api.cloud.nexus.v1.OutgoingServiceSpec spec = 3;

// The version of the outgoing service for which this update is intended for.
// The latest version can be found in the GetOutgoingService operation response.
string resource_version = 4;

// The id to use for this async operation - optional.
string async_operation_id = 5;
}

message UpdateOutgoingServiceResponse {
// The async operation.
temporal.api.cloud.operation.v1.AsyncOperation async_operation = 1;
}

message DeleteOutgoingServiceRequest {
// The id of the namespace to remove the outgoing service from.
string namespace = 1;

// The name outcoming service to delete.
string name = 2;

// The version of the outcoming service for which this delete is intended for.
// The latest version can be found in the GetOutgoingService operation response.
string resource_version = 3;

// The id to use for this async operation - optional.
string async_operation_id = 4;
}

message DeleteOutgoingServiceResponse {
// The async operation.
temporal.api.cloud.operation.v1.AsyncOperation async_operation = 1;
}
91 changes: 90 additions & 1 deletion temporal/api/cloud/cloudservice/v1/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ service CloudService {
body: "*"
};
}

// Get all namespaces
rpc GetNamespaces (GetNamespacesRequest) returns (GetNamespacesResponse) {
option (google.api.http) = {
Expand Down Expand Up @@ -118,4 +118,93 @@ service CloudService {
get: "/api/v1/regions/{region}",
};
}

// Gets all known incoming services
rpc GetIncomingServices(GetIncomingServicesRequest) returns (GetIncomingServicesResponse) {
option (google.api.http) = {
get: "/api/v1/nexus/incomingservices",
mastermanu marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a /by-id or /id suffix to this URL just in case we want to allow looking up by name eventually?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since I am following what we do for users, I've kept the same format (which doesn't have by-id or id either..). @anekkanti , thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for the default behavior (by ID) we don't need to add a suffix.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, am inclined to leave as-is as well. can always add suffix later if needed

};
}

// Get an incoming service
rpc GetIncomingService(GetIncomingServiceRequest) returns (GetIncomingServiceResponse) {
option (google.api.http) = {
get: "/api/v1/nexus/incomingservices/{incoming_service_id}",
};
}

// Create an incoming service
rpc CreateIncomingService(CreateIncomingServiceRequest) returns (CreateIncomingServiceResponse) {
option (google.api.http) = {
post: "/api/v1/nexus/incomingservices",
body: "*"
};
}

// Update an incoming service
rpc UpdateIncomingService(UpdateIncomingServiceRequest) returns (UpdateIncomingServiceResponse) {
option (google.api.http) = {
post: "/api/v1/nexus/incomingservices/{incoming_service_id}",
body: "*"
};
}

// Delete an incoming service
rpc DeleteIncomingService(DeleteIncomingServiceRequest) returns (DeleteIncomingServiceResponse) {
option (google.api.http) = {
delete: "/api/v1/nexus/incomingservices/{incoming_service_id}",
};
}

// Gets all outgoing services for a namespace
rpc GetOutgoingServices(GetOutgoingServicesRequest) returns (GetOutgoingServicesResponse) {
option (google.api.http) = {
get: "/api/v1/namespaces/{namespace}/nexus/outgoingservices",
};
}

// Get an outgoing service
rpc GetOutgoingService(GetOutgoingServiceRequest) returns (GetOutgoingServiceResponse) {
option (google.api.http) = {
get: "/api/v1/namespaces/{namespace}/nexus/outgoingservices/{name}",
};
}

// Create an outgoing service
rpc CreateOutgoingService(CreateOutgoingServiceRequest) returns (CreateOutgoingServiceResponse) {
option (google.api.http) = {
post: "/api/v1/namespaces/{namespace}/nexus/outgoingservices",
body: "*"
};
}

// Update an outgoing service
rpc UpdateOutgoingService(UpdateOutgoingServiceRequest) returns (UpdateOutgoingServiceResponse) {
option (google.api.http) = {
post: "/api/v1/namespaces/{namespace}/nexus/outgoingservices/{name}",
body: "*"
};
}

// Delete an outgoing service
rpc DeleteOutgoingService(DeleteOutgoingServiceRequest) returns (DeleteOutgoingServiceResponse) {
option (google.api.http) = {
delete: "/api/v1/namespaces/{namespace}/nexus/outgoingservices/{name}",
};
}

// Get account information
rpc GetAccount (GetAccountRequest) returns (GetAccountResponse) {
option (google.api.http) = {
get: "/api/v1/account",
};
}

// Update account information
rpc UpdateAccount (UpdateAccountRequest) returns (UpdateAccountResponse) {
option (google.api.http) = {
post: "/api/v1/account",
body: "*"
};
}
}
2 changes: 2 additions & 0 deletions temporal/api/cloud/identity/v1/message.proto
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ message User {
// The user specification
UserSpec spec = 3;
// The current state of the user
// Possible values: activating, activationfailed, active, updating, updatefailed, deleting, deletefailed, deleted, suspending, suspendfailed, suspended.
// For any failed state, reach out to Temporal Cloud support for remediation.
string state = 4;
// The id of the async operation that is creating/updating/deleting the user, if any
string async_operation_id = 5;
Expand Down
2 changes: 2 additions & 0 deletions temporal/api/cloud/namespace/v1/message.proto
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ message Namespace {
// The namespace specification.
NamespaceSpec spec = 3;
// The current state of the namespace.
// Possible values: activating, activationfailed, active, updating, updatefailed, deleting, deletefailed, deleted, suspending, suspendfailed, suspended.
// For any failed state, reach out to Temporal Cloud support for remediation.
string state = 4;
// The id of the async operation that is creating/updating/deleting the namespace, if any.
string async_operation_id = 5;
Expand Down
Loading
Loading