mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-20 06:00:06 +08:00
* feat(api): return typed deletion outcomes with explicit missing-target semantics Implement phase 2 of #3051 across the public gateway API and first-party SDKs. Preserve asynchronous sandbox deletion and observed resource identities, reserve legacy wire fields, and document the coordinated migration. Signed-off-by: Mrunal Patel <mrunalp@gmail.com> * fix(sdk): bind deletion waits to sandbox identity Track accepted deletions by original sandbox identity in Rust and TypeScript. Preserve name-only waits and cover replacement races and lookup failures. Merge the phase-one cleanup fix and adapt its interceptor regressions to typed deletion outcomes. Refs #3051. Signed-off-by: Mrunal Patel <mrunalp@gmail.com> * test(e2e): accept asynchronous stopped sandbox deletion Allow either completed or accepted deletion output, then continue polling for actual sandbox absence. This preserves the lifecycle assertion under the phase-two deletion contract. Refs #3051. Signed-off-by: Mrunal Patel <mrunalp@gmail.com> --------- Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
73 lines
2.5 KiB
Go
73 lines
2.5 KiB
Go
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package v1
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/NVIDIA/OpenShell/sdk/go/openshell/v1/internal/converter"
|
|
pb "github.com/NVIDIA/OpenShell/sdk/go/proto/openshellv1"
|
|
"google.golang.org/grpc"
|
|
)
|
|
|
|
type refreshClient struct {
|
|
client pb.OpenShellClient
|
|
}
|
|
|
|
func newRefreshClient(conn grpc.ClientConnInterface) *refreshClient {
|
|
return &refreshClient{client: pb.NewOpenShellClient(conn)}
|
|
}
|
|
|
|
func (r *refreshClient) GetStatus(ctx context.Context, workspace, provider, credentialKey string) ([]*RefreshStatus, error) {
|
|
resp, err := r.client.GetProviderRefreshStatus(ctx, &pb.GetProviderRefreshStatusRequest{
|
|
Provider: provider,
|
|
CredentialKey: credentialKey,
|
|
WorkspaceScope: namedWorkspaceScope(workspace),
|
|
})
|
|
if err != nil {
|
|
return nil, converter.FromGRPCError(err)
|
|
}
|
|
|
|
statuses := make([]*RefreshStatus, 0, len(resp.GetCredentials()))
|
|
for _, s := range resp.GetCredentials() {
|
|
statuses = append(statuses, converter.RefreshStatusFromProto(s))
|
|
}
|
|
return statuses, nil
|
|
}
|
|
|
|
func (r *refreshClient) Configure(ctx context.Context, workspace string, config *RefreshConfig) (*RefreshStatus, error) {
|
|
req := converter.RefreshConfigToProto(config)
|
|
req.WorkspaceScope = namedWorkspaceScope(workspace)
|
|
resp, err := r.client.ConfigureProviderRefresh(ctx, req)
|
|
if err != nil {
|
|
return nil, converter.FromGRPCError(err)
|
|
}
|
|
return converter.RefreshStatusFromProto(resp.GetStatus()), nil
|
|
}
|
|
|
|
func (r *refreshClient) Rotate(ctx context.Context, workspace, provider, credentialKey string) (*RefreshStatus, error) {
|
|
resp, err := r.client.RotateProviderCredential(ctx, &pb.RotateProviderCredentialRequest{
|
|
Provider: provider,
|
|
CredentialKey: credentialKey,
|
|
WorkspaceScope: namedWorkspaceScope(workspace),
|
|
})
|
|
if err != nil {
|
|
return nil, converter.FromGRPCError(err)
|
|
}
|
|
return converter.RefreshStatusFromProto(resp.GetStatus()), nil
|
|
}
|
|
|
|
func (r *refreshClient) Delete(ctx context.Context, workspace, provider, credentialKey string, opts ...DeleteOptions) (*DeletionResult, error) {
|
|
resp, err := r.client.DeleteProviderRefresh(ctx, &pb.DeleteProviderRefreshRequest{
|
|
AllowMissing: allowMissing(opts),
|
|
Provider: provider,
|
|
CredentialKey: credentialKey,
|
|
WorkspaceScope: namedWorkspaceScope(workspace),
|
|
})
|
|
if err != nil {
|
|
return nil, converter.FromGRPCError(err)
|
|
}
|
|
return &DeletionResult{Outcome: DeletionOutcome(resp.GetOutcome())}, nil
|
|
}
|