From 00bcd2ff4dad7444faf210f3f950e1f7ec408600 Mon Sep 17 00:00:00 2001 From: Harry Sadoyan Date: Wed, 14 Oct 2026 13:43:04 -0700 Subject: [PATCH 1/2] Point cloud-sdk at a local checkout carrying MoveNexusEndpointToProject The RPC is in saas-proto but not yet in cloud-api, so no released cloud-sdk exposes it. Build against a local regeneration until cloud-api v0.24.0 ships and the matching cloud-sdk release is cut. Revert this commit and take the released SDK before merging. Co-Authored-By: Claude Opus 5.5 --- go.mod | 2 + go.sum | 2 - internal/cloudservice/mock/mock.go | 83 +++++++++++++++++++ ...eprecated_field_without_suffix.golden.json | 1 + 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 7fe6c50..e6e7b38 100644 --- a/go.mod +++ b/go.mod @@ -84,3 +84,5 @@ require ( ) tool github.com/vektra/mockery/v3 + +replace go.temporal.io/cloud-sdk => /Users/harry/work/cloud-sdk-go diff --git a/go.sum b/go.sum index 091d97a..d94b080 100644 --- a/go.sum +++ b/go.sum @@ -154,8 +154,6 @@ go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09 go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.temporal.io/api v1.63.6-0.20260811224032-89570b10e9e2 h1:VeNTxlOHETym01zX6kSXHIVw4nc2RrX/KVgepQ/dr/8= go.temporal.io/api v1.63.6-0.20260811224032-89570b10e9e2/go.mod h1:SrlW2JMwVlDP4nRWSNznUFqnSHd+YeMDS1BkYo63HCQ= -go.temporal.io/cloud-sdk v0.19.0 h1:Vjr8a75hdxbq6VAiZJz7WboqhGA2NhmXl5A6ZFrVt60= -go.temporal.io/cloud-sdk v0.19.0/go.mod h1:W2O9t9tvo3Q/LhGgYdj8JijWbN5C84os+cz/BadIHYI= go.temporal.io/sdk v1.44.1 h1:Mt2OZLZpqkzDIdg9YyQzO0Rb/HqCDnnqHlIAGAJ5gqM= go.temporal.io/sdk v1.44.1/go.mod h1:vkApR12F9/Y8OR+hkxe7WyXQFuCX6clhzqnAk6rzDAM= go.temporal.io/sdk/contrib/envconfig v1.0.0 h1:1Q/swVgB4EW/p3k7rI9/4hpU4/DC57FSRbU90+UisXw= diff --git a/internal/cloudservice/mock/mock.go b/internal/cloudservice/mock/mock.go index 19bf16b..c3c6189 100644 --- a/internal/cloudservice/mock/mock.go +++ b/internal/cloudservice/mock/mock.go @@ -5600,6 +5600,89 @@ func (_c *MockCloudServiceClient_MoveNamespaceToProject_Call) RunAndReturn(run f return _c } +// MoveNexusEndpointToProject provides a mock function for the type MockCloudServiceClient +func (_mock *MockCloudServiceClient) MoveNexusEndpointToProject(ctx context.Context, in *cloudservice.MoveNexusEndpointToProjectRequest, opts ...grpc.CallOption) (*cloudservice.MoveNexusEndpointToProjectResponse, error) { + var tmpRet mock.Arguments + if len(opts) > 0 { + tmpRet = _mock.Called(ctx, in, opts) + } else { + tmpRet = _mock.Called(ctx, in) + } + ret := tmpRet + + if len(ret) == 0 { + panic("no return value specified for MoveNexusEndpointToProject") + } + + var r0 *cloudservice.MoveNexusEndpointToProjectResponse + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, *cloudservice.MoveNexusEndpointToProjectRequest, ...grpc.CallOption) (*cloudservice.MoveNexusEndpointToProjectResponse, error)); ok { + return returnFunc(ctx, in, opts...) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, *cloudservice.MoveNexusEndpointToProjectRequest, ...grpc.CallOption) *cloudservice.MoveNexusEndpointToProjectResponse); ok { + r0 = returnFunc(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudservice.MoveNexusEndpointToProjectResponse) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, *cloudservice.MoveNexusEndpointToProjectRequest, ...grpc.CallOption) error); ok { + r1 = returnFunc(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// MockCloudServiceClient_MoveNexusEndpointToProject_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'MoveNexusEndpointToProject' +type MockCloudServiceClient_MoveNexusEndpointToProject_Call struct { + *mock.Call +} + +// MoveNexusEndpointToProject is a helper method to define mock.On call +// - ctx context.Context +// - in *cloudservice.MoveNexusEndpointToProjectRequest +// - opts ...grpc.CallOption +func (_e *MockCloudServiceClient_Expecter) MoveNexusEndpointToProject(ctx interface{}, in interface{}, opts ...interface{}) *MockCloudServiceClient_MoveNexusEndpointToProject_Call { + return &MockCloudServiceClient_MoveNexusEndpointToProject_Call{Call: _e.mock.On("MoveNexusEndpointToProject", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *MockCloudServiceClient_MoveNexusEndpointToProject_Call) Run(run func(ctx context.Context, in *cloudservice.MoveNexusEndpointToProjectRequest, opts ...grpc.CallOption)) *MockCloudServiceClient_MoveNexusEndpointToProject_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 *cloudservice.MoveNexusEndpointToProjectRequest + if args[1] != nil { + arg1 = args[1].(*cloudservice.MoveNexusEndpointToProjectRequest) + } + var arg2 []grpc.CallOption + var variadicArgs []grpc.CallOption + if len(args) > 2 { + variadicArgs = args[2].([]grpc.CallOption) + } + arg2 = variadicArgs + run( + arg0, + arg1, + arg2..., + ) + }) + return _c +} + +func (_c *MockCloudServiceClient_MoveNexusEndpointToProject_Call) Return(moveNexusEndpointToProjectResponse *cloudservice.MoveNexusEndpointToProjectResponse, err error) *MockCloudServiceClient_MoveNexusEndpointToProject_Call { + _c.Call.Return(moveNexusEndpointToProjectResponse, err) + return _c +} + +func (_c *MockCloudServiceClient_MoveNexusEndpointToProject_Call) RunAndReturn(run func(ctx context.Context, in *cloudservice.MoveNexusEndpointToProjectRequest, opts ...grpc.CallOption) (*cloudservice.MoveNexusEndpointToProjectResponse, error)) *MockCloudServiceClient_MoveNexusEndpointToProject_Call { + _c.Call.Return(run) + return _c +} + // RemoveUserGroupMember provides a mock function for the type MockCloudServiceClient func (_mock *MockCloudServiceClient) RemoveUserGroupMember(ctx context.Context, in *cloudservice.RemoveUserGroupMemberRequest, opts ...grpc.CallOption) (*cloudservice.RemoveUserGroupMemberResponse, error) { var tmpRet mock.Arguments diff --git a/temporalcloudcli/internal/protoutils/testdata/strip_deprecated/removes_option_deprecated_field_without_suffix.golden.json b/temporalcloudcli/internal/protoutils/testdata/strip_deprecated/removes_option_deprecated_field_without_suffix.golden.json index b376d63..a47a6af 100644 --- a/temporalcloudcli/internal/protoutils/testdata/strip_deprecated/removes_option_deprecated_field_without_suffix.golden.json +++ b/temporalcloudcli/internal/protoutils/testdata/strip_deprecated/removes_option_deprecated_field_without_suffix.golden.json @@ -4,6 +4,7 @@ "codecServer": null, "connectivityRuleIds": [], "description": "", + "encryptionValidation": null, "fairness": null, "highAvailability": null, "lifecycle": null, From 9bf1bb095ced2d15244efad31a56ed9c1f075093 Mon Sep 17 00:00:00 2001 From: Harry Sadoyan Date: Wed, 14 Oct 2026 13:44:57 -0700 Subject: [PATCH 2/2] Add nexus endpoint move-to-project command Moves a Nexus endpoint to a different project without recreating it, so Nexus calls through it keep working and only the project governing access to it changes. Identifies the endpoint by --name or --id, like the other nexus endpoint commands. The confirmation prompt shows each project's name next to its ID, and an unknown destination fails before it, as the namespace move does. There is no --idempotent flag: the command reads the endpoint's current resource version unless one is given, so re-running a completed move succeeds rather than producing the rejection that flag translates. Co-Authored-By: Claude Opus 5.5 --- temporalcloudcli/commands.gen.go | 47 ++++++ temporalcloudcli/commands.nexus.move.go | 59 ++++++++ temporalcloudcli/commands.nexus.move_test.go | 151 +++++++++++++++++++ temporalcloudcli/commands.yml | 61 ++++++++ 4 files changed, 318 insertions(+) create mode 100644 temporalcloudcli/commands.nexus.move.go create mode 100644 temporalcloudcli/commands.nexus.move_test.go diff --git a/temporalcloudcli/commands.gen.go b/temporalcloudcli/commands.gen.go index 3fd8327..6e318a4 100644 --- a/temporalcloudcli/commands.gen.go +++ b/temporalcloudcli/commands.gen.go @@ -4611,6 +4611,7 @@ func NewCloudNexusEndpointCommand(cctx *CommandContext, parent *CloudNexusComman s.Command.AddCommand(&NewCloudNexusEndpointDeleteCommand(cctx, &s).Command) s.Command.AddCommand(&NewCloudNexusEndpointGetCommand(cctx, &s).Command) s.Command.AddCommand(&NewCloudNexusEndpointListCommand(cctx, &s).Command) + s.Command.AddCommand(&NewCloudNexusEndpointMoveToProjectCommand(cctx, &s).Command) s.Command.AddCommand(&NewCloudNexusEndpointUpdateCommand(cctx, &s).Command) return &s } @@ -4900,6 +4901,52 @@ func NewCloudNexusEndpointListCommand(cctx *CommandContext, parent *CloudNexusEn return &s } +type CloudNexusEndpointMoveToProjectCommand struct { + Parent *CloudNexusEndpointCommand + Command cobra.Command + ClientOptions + ResourceVersionOptions + Name string + Id string + DestinationProjectId string + SourceProjectId string + AsyncOperationId string + Async bool + PollInterval cliext.FlagDuration +} + +func NewCloudNexusEndpointMoveToProjectCommand(cctx *CommandContext, parent *CloudNexusEndpointCommand) *CloudNexusEndpointMoveToProjectCommand { + var s CloudNexusEndpointMoveToProjectCommand + s.Parent = parent + s.Command.DisableFlagsInUseLine = true + s.Command.Use = "move-to-project [flags]" + s.Command.Short = "Move a Nexus Endpoint to a different project" + if hasHighlighting { + s.Command.Long = "Move a Nexus Endpoint to a different project within the same account.\nSpecify either \x1b[1m--name\x1b[0m or \x1b[1m--id\x1b[0m (exactly one is required).\n\nThe endpoint keeps its ID, name, target, allowed caller namespaces, and\nrouting, so Nexus calls through it are unaffected. Only the project that\ngoverns access to it changes: access granted through the source project\nis lost, and access granted through the destination project applies.\n\nExample:\n\n\x1b[1mtemporal cloud nexus endpoint move-to-project \\\n --name my-endpoint \\\n --destination-project-id my-destination-project \\\n --source-project-id my-source-project\x1b[0m" + } else { + s.Command.Long = "Move a Nexus Endpoint to a different project within the same account.\nSpecify either `--name` or `--id` (exactly one is required).\n\nThe endpoint keeps its ID, name, target, allowed caller namespaces, and\nrouting, so Nexus calls through it are unaffected. Only the project that\ngoverns access to it changes: access granted through the source project\nis lost, and access granted through the destination project applies.\n\nExample:\n\n```\ntemporal cloud nexus endpoint move-to-project \\\n --name my-endpoint \\\n --destination-project-id my-destination-project \\\n --source-project-id my-source-project\n```" + } + s.Command.Args = cobra.NoArgs + s.Command.Flags().StringVar(&s.Name, "name", "", "The name of the Nexus Endpoint to move.") + s.Command.Flags().StringVar(&s.Id, "id", "", "The ID of the Nexus Endpoint to move.") + s.Command.Flags().StringVar(&s.DestinationProjectId, "destination-project-id", "", "The ID of the project to move the Nexus Endpoint to. Required.") + _ = cobra.MarkFlagRequired(s.Command.Flags(), "destination-project-id") + s.Command.Flags().StringVar(&s.SourceProjectId, "source-project-id", "", "The ID of the project the Nexus Endpoint is expected to currently belong to. The move fails if the endpoint has since moved elsewhere. Required.") + _ = cobra.MarkFlagRequired(s.Command.Flags(), "source-project-id") + s.Command.Flags().StringVar(&s.AsyncOperationId, "async-operation-id", "", "Custom identifier for tracking this async operation. If not provided, a unique ID is generated automatically.") + s.Command.Flags().BoolVar(&s.Async, "async", false, "Return immediately after initiating the operation instead of waiting for completion. Use the returned operation ID to check status later.") + s.PollInterval = cliext.MustParseFlagDuration("1s") + s.Command.Flags().Var(&s.PollInterval, "poll-interval", "Time to wait between status checks when waiting for operation completion. Cannot be greater than 10 minutes. Supports minutes (m) and seconds (s).") + s.ClientOptions.BuildFlags(s.Command.Flags()) + s.ResourceVersionOptions.BuildFlags(s.Command.Flags()) + s.Command.Run = func(c *cobra.Command, args []string) { + if err := s.run(cctx, args); err != nil { + cctx.Options.Fail(err) + } + } + return &s +} + type CloudNexusEndpointUpdateCommand struct { Parent *CloudNexusEndpointCommand Command cobra.Command diff --git a/temporalcloudcli/commands.nexus.move.go b/temporalcloudcli/commands.nexus.move.go new file mode 100644 index 0000000..74366ba --- /dev/null +++ b/temporalcloudcli/commands.nexus.move.go @@ -0,0 +1,59 @@ +package temporalcloudcli + +import ( + "errors" + "fmt" + + cloudservice "go.temporal.io/cloud-sdk/api/cloudservice/v1" +) + +func (c *CloudNexusEndpointMoveToProjectCommand) run(cctx *CommandContext, _ []string) error { + client, err := cctx.GetCloudClient(c.ClientOptions) + if err != nil { + return err + } + + endpoint, err := resolveNexusEndpoint(cctx, client, c.Name, c.Id) + if err != nil { + return err + } + + names, err := projectDisplayNames(cctx, client, endpoint.GetProjectId(), c.DestinationProjectId) + if err != nil { + return err + } + if _, ok := names[c.DestinationProjectId]; !ok { + return fmt.Errorf("destination project %q not found", c.DestinationProjectId) + } + + yes, err := cctx.GetPrompter().PromptYes(fmt.Sprintf( + "Move Nexus Endpoint %q from project %s to project %s", + endpoint.GetSpec().GetName(), + projectLabel(names, endpoint.GetProjectId()), + projectLabel(names, c.DestinationProjectId), + )) + if err != nil { + return err + } + if !yes { + return errors.New("Aborting move.") + } + + rv := endpoint.GetResourceVersion() + if c.ResourceVersion != "" { + rv = c.ResourceVersion + } + resp, err := client.MoveNexusEndpointToProject(cctx, &cloudservice.MoveNexusEndpointToProjectRequest{ + EndpointId: endpoint.GetId(), + DestinationProjectId: c.DestinationProjectId, + ExpectedSourceProjectId: c.SourceProjectId, + ResourceVersion: rv, + AsyncOperationId: c.AsyncOperationId, + }) + poller := cctx.GetPoller(client, AsyncOperationOptions{ + AsyncOperationId: c.AsyncOperationId, + Async: c.Async, + PollInterval: c.PollInterval, + }) + return poller.HandleIdempotentOperation(cctx, resp, err) +} diff --git a/temporalcloudcli/commands.nexus.move_test.go b/temporalcloudcli/commands.nexus.move_test.go new file mode 100644 index 0000000..711ef6d --- /dev/null +++ b/temporalcloudcli/commands.nexus.move_test.go @@ -0,0 +1,151 @@ +package temporalcloudcli_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/mock" + cloudservice "go.temporal.io/cloud-sdk/api/cloudservice/v1" + nexusv1 "go.temporal.io/cloud-sdk/api/nexus/v1" + operation "go.temporal.io/cloud-sdk/api/operation/v1" + + cloudmock "github.com/temporalio/cloud-cli/internal/cloudservice/mock" + "github.com/temporalio/cloud-cli/temporalcloudcli" +) + +var testMoveEndpoint = &nexusv1.Endpoint{ + Id: "ep-123", + ResourceVersion: "v1", + ProjectId: testMoveSource, + Spec: &nexusv1.EndpointSpec{Name: "my-endpoint"}, +} + +func expectEndpointByName(c *cloudmock.MockCloudServiceClient) { + c.EXPECT(). + GetNexusEndpoints(mock.Anything, &cloudservice.GetNexusEndpointsRequest{Name: "my-endpoint"}, mock.Anything). + Return(&cloudservice.GetNexusEndpointsResponse{Endpoints: []*nexusv1.Endpoint{testMoveEndpoint}}, nil) +} + +func expectEndpointByID(c *cloudmock.MockCloudServiceClient) { + c.EXPECT(). + GetNexusEndpoint(mock.Anything, &cloudservice.GetNexusEndpointRequest{EndpointId: "ep-123"}, mock.Anything). + Return(&cloudservice.GetNexusEndpointResponse{Endpoint: testMoveEndpoint}, nil) +} + +func expectBothProjectsFound(c *cloudmock.MockCloudServiceClient) { + expectProjectLookup(c, testMoveProject(testMoveSource, "source"), testMoveProject(testMoveDest, "destination")) +} + +func expectEndpointMove(c *cloudmock.MockCloudServiceClient, want *cloudservice.MoveNexusEndpointToProjectRequest) { + c.EXPECT(). + MoveNexusEndpointToProject(mock.Anything, want, mock.Anything). + Return(&cloudservice.MoveNexusEndpointToProjectResponse{ + AsyncOperation: &operation.AsyncOperation{Id: "op-move"}, + }, nil) +} + +func TestNexusEndpointMoveToProject(t *testing.T) { + tests := []struct { + name string + cmd temporalcloudcli.CloudNexusEndpointMoveToProjectCommand + resourceVersion string + cloudClientExpectations func(*cloudmock.MockCloudServiceClient) + }{ + { + name: "ByNameWithFetchedResourceVersion", + cmd: temporalcloudcli.CloudNexusEndpointMoveToProjectCommand{Name: "my-endpoint"}, + cloudClientExpectations: func(c *cloudmock.MockCloudServiceClient) { + expectEndpointByName(c) + expectBothProjectsFound(c) + expectEndpointMove(c, &cloudservice.MoveNexusEndpointToProjectRequest{ + EndpointId: "ep-123", + DestinationProjectId: testMoveDest, + ExpectedSourceProjectId: testMoveSource, + ResourceVersion: "v1", + }) + }, + }, + { + name: "ByIDWithResourceVersionOverride", + cmd: temporalcloudcli.CloudNexusEndpointMoveToProjectCommand{Id: "ep-123"}, + resourceVersion: "v-override", + cloudClientExpectations: func(c *cloudmock.MockCloudServiceClient) { + expectEndpointByID(c) + expectBothProjectsFound(c) + expectEndpointMove(c, &cloudservice.MoveNexusEndpointToProjectRequest{ + EndpointId: "ep-123", + DestinationProjectId: testMoveDest, + ExpectedSourceProjectId: testMoveSource, + ResourceVersion: "v-override", + }) + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := tt.cmd + cmd.DestinationProjectId = testMoveDest + cmd.SourceProjectId = testMoveSource + cmd.ResourceVersion = tt.resourceVersion + temporalcloudcli.TestCommand(t, &cmd, temporalcloudcli.TestCommandOptions{ + CloudClientExpectations: tt.cloudClientExpectations, + PromptOptions: temporalcloudcli.TestPromptOptions{ + ExpectPromptYes: true, + ExpectPromptYesMessage: `Move Nexus Endpoint "my-endpoint" from project "source" (proj-source) to project "destination" (proj-dest)`, + PromptResult: true, + }, + AsyncPollerOptions: temporalcloudcli.TestAsyncPollerOptions{AsyncOperationID: "op-move"}, + }) + }) + } +} + +func TestNexusEndpointMoveToProjectUnknownDestination(t *testing.T) { + cmd := temporalcloudcli.CloudNexusEndpointMoveToProjectCommand{ + Name: "my-endpoint", + DestinationProjectId: testMoveDest, + SourceProjectId: testMoveSource, + } + temporalcloudcli.TestCommand(t, &cmd, temporalcloudcli.TestCommandOptions{ + CloudClientExpectations: func(c *cloudmock.MockCloudServiceClient) { + expectEndpointByName(c) + expectProjectLookup(c, testMoveProject(testMoveSource, "source")) + }, + ExpectedError: `destination project "proj-dest" not found`, + }) +} + +func TestNexusEndpointMoveToProjectPromptDeclined(t *testing.T) { + cmd := temporalcloudcli.CloudNexusEndpointMoveToProjectCommand{ + Name: "my-endpoint", + DestinationProjectId: testMoveDest, + SourceProjectId: testMoveSource, + } + temporalcloudcli.TestCommand(t, &cmd, temporalcloudcli.TestCommandOptions{ + CloudClientExpectations: func(c *cloudmock.MockCloudServiceClient) { + expectEndpointByName(c) + expectBothProjectsFound(c) + }, + PromptOptions: temporalcloudcli.TestPromptOptions{ExpectPromptYes: true, PromptResult: false}, + ExpectedError: "Aborting move.", + }) +} + +func TestNexusEndpointMoveToProjectSurfacesRejection(t *testing.T) { + cmd := temporalcloudcli.CloudNexusEndpointMoveToProjectCommand{ + Name: "my-endpoint", + DestinationProjectId: testMoveDest, + SourceProjectId: testMoveSource, + } + temporalcloudcli.TestCommand(t, &cmd, temporalcloudcli.TestCommandOptions{ + CloudClientExpectations: func(c *cloudmock.MockCloudServiceClient) { + expectEndpointByName(c) + expectBothProjectsFound(c) + c.EXPECT(). + MoveNexusEndpointToProject(mock.Anything, mock.Anything, mock.Anything). + Return(nil, errors.New("resource limit reached: 5")) + }, + PromptOptions: temporalcloudcli.TestPromptOptions{ExpectPromptYes: true, PromptResult: true}, + ExpectedError: "resource limit reached: 5", + }) +} diff --git a/temporalcloudcli/commands.yml b/temporalcloudcli/commands.yml index 63e6855..f7973d7 100644 --- a/temporalcloudcli/commands.yml +++ b/temporalcloudcli/commands.yml @@ -2097,6 +2097,67 @@ commands: description: | The ID of the Nexus Endpoint to delete. + - name: cloud nexus endpoint move-to-project + summary: Move a Nexus Endpoint to a different project + description: | + Move a Nexus Endpoint to a different project within the same account. + Specify either `--name` or `--id` (exactly one is required). + + The endpoint keeps its ID, name, target, allowed caller namespaces, and + routing, so Nexus calls through it are unaffected. Only the project that + governs access to it changes: access granted through the source project + is lost, and access granted through the destination project applies. + + Example: + + ``` + temporal cloud nexus endpoint move-to-project \ + --name my-endpoint \ + --destination-project-id my-destination-project \ + --source-project-id my-source-project + ``` + has-init: false + option-sets: + - client + - resource-version + options: + - name: name + type: string + description: | + The name of the Nexus Endpoint to move. + - name: id + type: string + description: | + The ID of the Nexus Endpoint to move. + - name: destination-project-id + type: string + description: | + The ID of the project to move the Nexus Endpoint to. + required: true + - name: source-project-id + type: string + description: | + The ID of the project the Nexus Endpoint is expected to currently + belong to. The move fails if the endpoint has since moved elsewhere. + required: true + - name: async-operation-id + type: string + description: | + Custom identifier for tracking this async operation. If not provided, + a unique ID is generated automatically. + - name: async + type: bool + description: | + Return immediately after initiating the operation instead of waiting + for completion. Use the returned operation ID to check status later. + - name: poll-interval + type: duration + default: 1s + description: | + Time to wait between status checks when waiting for operation completion. + Cannot be greater than 10 minutes. + Supports minutes (m) and seconds (s). + - name: cloud nexus endpoint update summary: Update an existing Nexus Endpoint by name or ID description: |