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

Adds Nexus Endpoint #23

Merged
merged 26 commits into from
Aug 27, 2024
Merged

Conversation

mastermanu
Copy link
Member

No description provided.

@mastermanu mastermanu marked this pull request as draft May 1, 2024 19:59
message EndpointTargetSpec {
// The type of target that this endpoint routes Nexus requests to.
// Possible values are: task_queue
string target_type = 1;
Copy link
Member Author

Choose a reason for hiding this comment

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

note: this is essentially a poor person's version of oneof

Copy link
Member

Choose a reason for hiding this comment

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

I'm fine with this but I'd like to understand why we can't use what's standard.

Copy link
Member Author

@mastermanu mastermanu May 7, 2024

Choose a reason for hiding this comment

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

will follow up with @anekkanti today just to have a solidified answer / reasoning here.

Copy link
Member

Choose a reason for hiding this comment

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

Same, seems unnecessary that you can't use the presence of the next field to determine type

Copy link
Member Author

Choose a reason for hiding this comment

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

Spoke with @anekkanti offline. as far as we can tell there are four options here:

  1. use oneoff. I think we just decided not to use that because there were concerns about around how this manifests in other languages, and even the generated go code to read the field seems janky: https://protobuf.dev/reference/go/go-generated/#oneof. We were also worried that adding new types in the future would complicate versioning. Maybe both of these worries are unfounded. This is the first time we are adding something like this to the Cloud API, so worth laying the groundwork for this now. Curious if @cretz or @bergundy have thoughts on "oneoff" and cross-platform/language usage and any issues around that.

  2. Don't use oneoff, but don't have the target_type field, just check that exactly one field is assigned a value. No reason we cannot do this. If I wanted to do a Get call for all endpoints of a specific target type, we would probably still need the string on that GetNexusEndpoints get request, but probably not a big deal.

  3. Use target_type as an enum (I think there was a previous discussion about not using enums, we can re-open that if need be).

  4. Use target_type as string (as is now). It's a bit more explicit, but agree its unnecessary. We'd probably still include it as an optional filter on GetNexusEndpoints() [but it can be added later down the line since there is only one type for now anyway]

Leaning towards option 2 (just get rid of target_type field). Any concerns with that?

Copy link
Member

Choose a reason for hiding this comment

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

I too lean towards option 2. Unrelated to this specifically, but I sure would like to re-open that never-use-proto-enum decision that was made long ago on this repo. I disagree with it.

Copy link
Member Author

Choose a reason for hiding this comment

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

ok cool. removed it completely for now. we have only one type so we can figure out if we want to add target_type later for the search/get

Copy link
Member

@bergundy bergundy left a comment

Choose a reason for hiding this comment

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

Overall LGTM. I had a few small comments and one that I think we should discuss.


message GetNexusEndpointRequest {
// The id of the nexus endpoint to get.
string endpoint_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.

I think you can just call this id, that's what I did in the operator API.

Copy link
Member Author

Choose a reason for hiding this comment

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

so I changed this to id, but this is now in-consistent with our other APIs related to user and namespace operations (where the request/path takes in user_id or namespace_id). am fine with having this as id, but will check with @anekkanti to be sure

Copy link
Member

Choose a reason for hiding this comment

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

We need to be consistent with the rest of the API here, that is more important than consistency with the self-hosted operator service

Copy link
Member Author

Choose a reason for hiding this comment

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

changed it back

// The spec for the nexus endpoint.
temporal.api.cloud.nexus.v1.EndpointSpec spec = 1;

// The id to use for this async operation - optional.
Copy link
Member

Choose a reason for hiding this comment

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

Do we have guidance anywhere explaining why you'd want to specify this? I understand the concept but I'm not sure users do.

Copy link
Member Author

Choose a reason for hiding this comment

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

Agree that this probably needs to be fleshed out more here: https://docs.temporal.io/ops. The API itself is still in preview. I have seen other APIs have a section about "idempotency" which describes the usage/semantics around similar fields. We may want something similar her.

cc @anekkanti @jlacefie in case there is some other documentation I am missing here, or to potentially track ensuring docs cover this 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.

@rachfop since he is working on docs

// Update a nexus endpoint
rpc UpdateNexusEndpoint(UpdateNexusEndpointRequest) returns (UpdateNexusEndpointResponse) {
option (google.api.http) = {
post: "/api/v1/nexus/endpoints/{endpoint_id}",
Copy link
Member

Choose a reason for hiding this comment

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

In OSS the route ends with /update to be consistent with other update methods.
Looks like Cloud took a different path.
CC @cretz

Copy link
Member

Choose a reason for hiding this comment

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

I almost missed this because it wasn't marked "ready for review" yet, heh.

We should combine these into one create-or-update, not sure the benefit of separating them. If you combine them you can use this URL, people expect POST to a resource like this to be able to create. If you must keep them separated, since we can't really support PUT accurately, I do think it deserves its own operation name.

Is there are good reason here or in operator service why we can't just have one mutation call?

Copy link
Member Author

Choose a reason for hiding this comment

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

So few things here:

  1. User and Namespace have separate create and update endpoints. We can definitely combine it for Nexus, but then that is inconsistent with the rest of our current Cloud APIs

  2. Having distinction between Create/Update has been generally useful for us given that it gives flexibility for the operations to have different auth permissions (and is actually the case for namespaces for instance). Note that from the Cloud Side, create generates an ID that must be passed for Update (same for namespace / user - we take the IDs not the name/email address). We can scrap the ID of the "id" and only rely on the user provided field, but having this decoupled ID seems better in the long-term.

  3. Namespace and User have POST as well for update on the resource path itself. If we were to keep these separate, should we update the existing paths on those two types to have an /update suffix hanging off of the end as well? I would think so, but just double-checking.

cc @anekkanti to go over this as well

Copy link
Member Author

Choose a reason for hiding this comment

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

Synced with @anekkanti offline - we will add "update" suffix to the other update operation paths here and keep CREATE/UPDATE as separate operations for the reasons stated above.

Copy link
Member

@cretz cretz May 8, 2024

Choose a reason for hiding this comment

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

Now that users can't provide their own ID, I think you should leave it as it is now. IIRC when I was reading before, it was a user-provided identifier which is why the ID-based URL made no sense to be update-only. Sorry if I misread and they never could provide their own ID. But since this is no longer a user-provided identifier, no suffix needed, the ID-based URL can clearly be for update. I hope that makes sense, sorry.

So no "update" suffix please. Match the other APIs in this repo.

Copy link
Member Author

Choose a reason for hiding this comment

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

reverted

temporal/api/cloud/nexus/v1/message.proto Outdated Show resolved Hide resolved
message EndpointTargetSpec {
// The type of target that this endpoint routes Nexus requests to.
// Possible values are: task_queue
string target_type = 1;
Copy link
Member

Choose a reason for hiding this comment

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

I'm fine with this but I'd like to understand why we can't use what's standard.

temporal/api/cloud/nexus/v1/message.proto Outdated Show resolved Hide resolved
CloudTaskQueueSpec cloud_task_queue_spec = 2;
}

message CloudTaskQueueSpec {
Copy link
Member

Choose a reason for hiding this comment

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

In OSS I'm considering calling this Worker target.

Copy link
Member Author

Choose a reason for hiding this comment

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

changed it to CloudWorkerTargetSpec for now to be more aligned

@mastermanu mastermanu marked this pull request as ready for review May 7, 2024 14:18
Comment on lines +79 to +83
// The date and time when the endpoint was created.
google.protobuf.Timestamp created_time = 6;

// The date and time when the endpoint was last modified.
google.protobuf.Timestamp last_modified_time = 7;
Copy link
Member

Choose a reason for hiding this comment

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

@mastermanu can we also show the identity that created and modified this endpoint?

Copy link
Member Author

Choose a reason for hiding this comment

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

i think we can, although we'd probably want to consider adding that across all the objects we have (e.g. users, namespaces, etc).

would probably consider adding that as a separate effort.


message GetNexusEndpointRequest {
// The id of the nexus endpoint to get.
string 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.

Suggested change
string id = 1;
string endpoint_id = 1;

Here and elsewhere to match what I see is already done in this repo

Copy link
Member Author

Choose a reason for hiding this comment

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

haha, yes, this is what it was before @bergundy commented, and gave the exact same response. happy to switch it back

Copy link
Member

Choose a reason for hiding this comment

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

We need to be consistent with ourselves, I updated that thread too

string page_token = 2;

// Filter endpoints based on their target specification - optional, treated as an AND if specified. Empty fields within the spec are treated as '*'.
temporal.api.cloud.nexus.v1.EndpointTargetSpec spec = 3;
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 to match what this API does, you should list out specific fields to filter on. I don't think it's consistent with other APIs here to accept an entire spec as a filter.

Copy link
Member Author

Choose a reason for hiding this comment

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

sure, can replace with flat fields

// Gets nexus endpoints
rpc GetNexusEndpoints(GetNexusEndpointsRequest) returns (GetNexusEndpointsResponse) {
option (google.api.http) = {
get: "/api/v1/nexus/endpoints",
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
get: "/api/v1/nexus/endpoints",
get: "/api/v1/cloud/nexus/endpoints",

Need to update the prefix to match others in this service (helps routing and may change soon anyways)

Copy link
Member Author

Choose a reason for hiding this comment

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

whoops, fixed

string name = 1;

// Indicates where the endpoint should forward received nexus requests to.
EndpointTargetSpec endpoint_target_spec = 2;
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
EndpointTargetSpec endpoint_target_spec = 2;
EndpointTargetSpec target_spec = 2;

Inconsistent in whether you choose to prefix fields in this message with "endpoint_"

Copy link
Member Author

Choose a reason for hiding this comment

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

removed endpoint_ suffix

Comment on lines 23 to 25
// Optional description. Can be in markdown for rendering in the UI.
// Note that this is an experimental field that may be deprecated in the future
string description = 4;
Copy link
Member

Choose a reason for hiding this comment

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

We support markdown-based descriptions in API elements? We have some other work trying to define the subset of markdown we're going to support. If we don't have description on namespaces or users or whatever, can we wait until we can consistently provide description on all of these types of resources instead of making Nexus endpoint the first? I support the idea, just think it should be generally applicable.

Copy link
Member Author

Choose a reason for hiding this comment

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

this is definitely open/experimental. we dont support description on any other resources (except for service accounts, which is also string description, and thats not released yet). Am fine removing this for now and adding it later. It's also why it was marked as "experimental" via a comment. @bergundy - any thoughts here?

Copy link
Member

@cretz cretz May 8, 2024

Choose a reason for hiding this comment

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

I think we should remove pending a general discussion of description on resources (a good discussion to have, not sure Nexus PR is the place for that though)

Copy link
Member Author

Choose a reason for hiding this comment

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

removed for now. can add it in a separate PR after more discussion

Copy link
Member

Choose a reason for hiding this comment

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

I missed this conversation.

Our designs all include description in markdown, we have to keep this field.
I have requested that we make it a Payload so eventually, when we support account level codecs in the UI we can encrypt them.

message EndpointPolicySpec {
// The policy set on this endpoint authorization spec.
// Possible values are: allowed_cloud_namespace
string policy_type = 1;
Copy link
Member

Choose a reason for hiding this comment

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

Is this necessary? Can the presence of the next field be enough to tell you what the policy type is?

Copy link
Member Author

Choose a reason for hiding this comment

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

removed

message EndpointTargetSpec {
// The type of target that this endpoint routes Nexus requests to.
// Possible values are: task_queue
string target_type = 1;
Copy link
Member

Choose a reason for hiding this comment

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

Same, seems unnecessary that you can't use the presence of the next field to determine type

message DeleteNexusEndpointResponse {
// The async operation
temporal.api.cloud.operation.v1.AsyncOperation async_operation = 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: add empty line.

CloudWorkerTargetSpec cloud_worker_target_spec = 1;
}

message CloudWorkerTargetSpec {
Copy link
Member

Choose a reason for hiding this comment

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

nit: I'd just call this Worker, it's not a cloud worker.

nikki-dag and others added 5 commits August 16, 2024 11:39
- Update endpoint name regex
- Add endpoint description
- Rename CloudWorkerTargetSpec to WorkerTargetSpec
- Add next_page_token to GetNexusEndpointsResponse
- Group nexus related request and responses together.
Merge main + Remove /api/v1 prefix for HTTP paths
option (google.api.http) = {
delete: "/cloud/nexus/endpoints/{endpoint_id}",
};
}
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
}
}

Copy link
Member

Choose a reason for hiding this comment

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

Is it time to add a formatter?

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 that can be discussed on the primary api repo and can apply to this if/when it moves there

@@ -179,6 +179,42 @@ service CloudService {
};
}

// Gets nexus endpoints
rpc GetNexusEndpoints(GetNexusEndpointsRequest) returns (GetNexusEndpointsResponse) {
option (google.api.http) = {
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
option (google.api.http) = {
option (google.api.http) = {

Spacing off elsewhere for this too. Make sure you are not using tabs.

// The current state of the endpoint.
// Possible values: activating, activationfailed, active, updating, updatefailed, deleting, deletefailed, deleted
// For any failed state, reach out to Temporal Cloud support for remediation.
string state = 4;
Copy link
Member

Choose a reason for hiding this comment

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

Lets move to using an enum here.
@nikki-dag

Copy link
Member

Choose a reason for hiding this comment

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

@nikki-dag nikki-dag merged commit 0a01b74 into temporalio:main Aug 27, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants