Skip to content

Commit eba0989

Browse files
committed
refactor: streamline workspace namespace handling with conversion functions
1 parent 7b5027f commit eba0989

4 files changed

Lines changed: 41 additions & 11 deletions

File tree

internal/client/client.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"path/filepath"
1313
"time"
1414

15+
"github.com/bacchus-snu/sgs-cli/internal/sgs"
1516
"gopkg.in/yaml.v3"
1617
"k8s.io/client-go/kubernetes"
1718
"k8s.io/client-go/rest"
@@ -377,7 +378,7 @@ func SetWorkspace(workspace string) error {
377378
context = make(map[string]interface{})
378379
ctxMap["context"] = context
379380
}
380-
context["namespace"] = workspace
381+
context["namespace"] = sgs.WorkspaceToNamespace(workspace)
381382
break
382383
}
383384
}

internal/cmd/get.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -419,12 +419,13 @@ func getWorkspaces(ctx context.Context, k8sClient *client.Client, verbose bool,
419419
}
420420
}
421421

422+
currentNS := workspace.FromNamespace(k8sClient.Namespace) // Strip ws- prefix for comparison
422423
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
423424
if verbose {
424425
fmt.Fprintln(w, "NAME\tACCESS\tGPU QUOTA\tCPU QUOTA\tMEM QUOTA")
425426
for _, ws := range workspaces {
426427
current := ""
427-
if ws.Name == k8sClient.Namespace {
428+
if ws.Name == currentNS {
428429
current = " (current)"
429430
}
430431
fmt.Fprintf(w, "%s%s\t%s\t%d\t%s\t%s\n",
@@ -434,7 +435,7 @@ func getWorkspaces(ctx context.Context, k8sClient *client.Client, verbose bool,
434435
fmt.Fprintln(w, "NAME\tACCESS\tGPU QUOTA")
435436
for _, ws := range workspaces {
436437
current := ""
437-
if ws.Name == k8sClient.Namespace {
438+
if ws.Name == currentNS {
438439
current = " (current)"
439440
}
440441
fmt.Fprintf(w, "%s%s\t%s\t%d\n", ws.Name, current, formatWorkspaceAccess(ws.NodeGroup), ws.GPUQuota)
@@ -460,7 +461,7 @@ func describeWorkspace(ctx context.Context, k8sClient *client.Client, name strin
460461
}
461462

462463
current := ""
463-
if ws.Name == k8sClient.Namespace {
464+
if ws.Name == workspace.FromNamespace(k8sClient.Namespace) {
464465
current = " (current)"
465466
}
466467

@@ -617,8 +618,8 @@ func describeWorkspaces(ctx context.Context, k8sClient *client.Client) {
617618

618619
// getAll displays all resources (nodes, volumes, sessions, workspaces)
619620
func getAll(ctx context.Context, k8sClient *client.Client, verbose bool) {
620-
// Get current workspace for header
621-
currentWS := k8sClient.Namespace
621+
// Get current workspace for header (strip ws- prefix for display)
622+
currentWS := workspace.FromNamespace(k8sClient.Namespace)
622623

623624
// Workspaces
624625
fmt.Println("--- Workspaces ---")

internal/sgs/constants.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Package sgs provides shared constants and types for the SGS CLI.
22
package sgs
33

4+
import "strings"
5+
46
// Label keys for Kubernetes resources
57
const (
68
LabelManagedBy = "app.kubernetes.io/managed-by"
@@ -39,3 +41,19 @@ const (
3941

4042
// Beacon mount path - the runtime wrapper detects this path to trigger root swap
4143
const BeaconMount = "/sgs-os-volume"
44+
45+
// Workspace namespace prefix - workspace namespaces are named ws-<workspace>
46+
const WorkspacePrefix = "ws-"
47+
48+
// WorkspaceToNamespace converts a workspace name to its Kubernetes namespace
49+
func WorkspaceToNamespace(workspace string) string {
50+
if strings.HasPrefix(workspace, WorkspacePrefix) {
51+
return workspace // already has prefix
52+
}
53+
return WorkspacePrefix + workspace
54+
}
55+
56+
// NamespaceToWorkspace converts a Kubernetes namespace to workspace name (strips ws- prefix)
57+
func NamespaceToWorkspace(namespace string) string {
58+
return strings.TrimPrefix(namespace, WorkspacePrefix)
59+
}

internal/workspace/workspace.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ import (
1313
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1414
)
1515

16+
// ToNamespace converts a workspace name to its Kubernetes namespace
17+
var ToNamespace = sgs.WorkspaceToNamespace
18+
19+
// FromNamespace converts a Kubernetes namespace to workspace name (strips ws- prefix)
20+
var FromNamespace = sgs.NamespaceToWorkspace
21+
1622
// WorkspaceInfo represents information about an SGS workspace
1723
type WorkspaceInfo struct {
1824
Name string
@@ -58,7 +64,7 @@ func List(ctx context.Context, c *client.Client) ([]WorkspaceInfo, error) {
5864
}
5965

6066
info := &WorkspaceInfo{
61-
Name: ns.Name,
67+
Name: FromNamespace(ns.Name),
6268
}
6369

6470
// Parse node selector annotation for node group
@@ -105,9 +111,12 @@ func List(ctx context.Context, c *client.Client) ([]WorkspaceInfo, error) {
105111

106112
// Get returns information about a specific workspace
107113
func Get(ctx context.Context, c *client.Client, name string) (*WorkspaceInfo, error) {
114+
// Convert workspace name to K8s namespace (add ws- prefix)
115+
nsName := ToNamespace(name)
116+
108117
// Get namespace with retry
109118
ns, err := client.RetryWithContext(ctx, func() (*corev1.Namespace, error) {
110-
return c.Clientset.CoreV1().Namespaces().Get(ctx, name, metav1.GetOptions{})
119+
return c.Clientset.CoreV1().Namespaces().Get(ctx, nsName, metav1.GetOptions{})
111120
})
112121
if err != nil {
113122
return nil, fmt.Errorf("workspace not found: %s", name)
@@ -120,14 +129,14 @@ func Get(ctx context.Context, c *client.Client, name string) (*WorkspaceInfo, er
120129

121130
// Try to access resource quotas to verify permission (with retry)
122131
quotas, err := client.RetryWithContext(ctx, func() (*corev1.ResourceQuotaList, error) {
123-
return c.Clientset.CoreV1().ResourceQuotas(name).List(ctx, metav1.ListOptions{})
132+
return c.Clientset.CoreV1().ResourceQuotas(nsName).List(ctx, metav1.ListOptions{})
124133
})
125134
if err != nil {
126135
return nil, fmt.Errorf("access denied to workspace: %s", name)
127136
}
128137

129138
info := &WorkspaceInfo{
130-
Name: name,
139+
Name: FromNamespace(nsName), // Use name without prefix
131140
}
132141

133142
// Parse node selector annotation
@@ -160,7 +169,8 @@ func GetCurrent(ctx context.Context, c *client.Client) (*WorkspaceInfo, error) {
160169

161170
// Exists checks if a workspace exists (but doesn't check permission)
162171
func Exists(ctx context.Context, c *client.Client, name string) bool {
163-
ns, err := c.Clientset.CoreV1().Namespaces().Get(ctx, name, metav1.GetOptions{})
172+
nsName := ToNamespace(name) // Add ws- prefix for K8s API
173+
ns, err := c.Clientset.CoreV1().Namespaces().Get(ctx, nsName, metav1.GetOptions{})
164174
if err != nil {
165175
return false
166176
}

0 commit comments

Comments
 (0)