This commit is contained in:
Harivansh Rathi 2026-02-07 14:39:14 -05:00
parent 7a067c3420
commit e5d7b7a7c5
11 changed files with 48 additions and 85 deletions

View file

@ -9,7 +9,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
) )
func NewCreateCmd() *cobra.Command { func NewCreateCmd() *cobra.Command {
@ -55,7 +54,7 @@ func NewCreateCmd() *cobra.Command {
}, },
} }
secretGVR := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"} secretGVR := coreGVR("secrets")
_, err = client.Dynamic().Resource(secretGVR).Namespace(ns).Create(ctx, secret, metav1.CreateOptions{}) _, err = client.Dynamic().Resource(secretGVR).Namespace(ns).Create(ctx, secret, metav1.CreateOptions{})
if err != nil { if err != nil {
return fmt.Errorf("creating secret %q: %w", name, err) return fmt.Errorf("creating secret %q: %w", name, err)
@ -65,7 +64,7 @@ func NewCreateCmd() *cobra.Command {
// Create the SandboxClaim // Create the SandboxClaim
claim := &unstructured.Unstructured{ claim := &unstructured.Unstructured{
Object: map[string]interface{}{ Object: map[string]interface{}{
"apiVersion": "agentsandbox.dev/v1", "apiVersion": "extensions.agents.x-k8s.io/v1alpha1",
"kind": "SandboxClaim", "kind": "SandboxClaim",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
"name": name, "name": name,
@ -82,12 +81,7 @@ func NewCreateCmd() *cobra.Command {
}, },
} }
claimGVR := schema.GroupVersionResource{ _, err = client.Dynamic().Resource(sandboxClaimGVR).Namespace(ns).Create(ctx, claim, metav1.CreateOptions{})
Group: "agentsandbox.dev",
Version: "v1",
Resource: "sandboxclaims",
}
_, err = client.Dynamic().Resource(claimGVR).Namespace(ns).Create(ctx, claim, metav1.CreateOptions{})
if err != nil { if err != nil {
return fmt.Errorf("creating SandboxClaim %q: %w", name, err) return fmt.Errorf("creating SandboxClaim %q: %w", name, err)
} }
@ -98,7 +92,7 @@ func NewCreateCmd() *cobra.Command {
waitCtx, cancel := context.WithTimeout(ctx, 3*time.Minute) waitCtx, cancel := context.WithTimeout(ctx, 3*time.Minute)
defer cancel() defer cancel()
if err := client.WaitForReady(waitCtx, ns, "sandboxclaims", name); err != nil { if err := client.WaitForReady(waitCtx, ns, sandboxClaimGVR, name); err != nil {
return fmt.Errorf("waiting for sandbox: %w", err) return fmt.Errorf("waiting for sandbox: %w", err)
} }

View file

@ -9,9 +9,8 @@ import (
"github.com/rathi/agentikube/internal/kube" "github.com/rathi/agentikube/internal/kube"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
func NewDestroyCmd() *cobra.Command { func NewDestroyCmd() *cobra.Command {
@ -50,17 +49,11 @@ func NewDestroyCmd() *cobra.Command {
ns := cfg.Namespace ns := cfg.Namespace
name := "sandbox-" + handle name := "sandbox-" + handle
claimGVR := schema.GroupVersionResource{ secretGVR := coreGVR("secrets")
Group: "agentsandbox.dev", pvcGVR := coreGVR("persistentvolumeclaims")
Version: "v1",
Resource: "sandboxclaims",
}
secretGVR := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"}
pvcGVR := schema.GroupVersionResource{Group: "", Version: "v1", Resource: "persistentvolumeclaims"}
// Delete SandboxClaim // Delete SandboxClaim
err = client.Dynamic().Resource(claimGVR).Namespace(ns).Delete(ctx, name, metav1.DeleteOptions{}) err = client.Dynamic().Resource(sandboxClaimGVR).Namespace(ns).Delete(ctx, name, metav1.DeleteOptions{})
if err != nil { if err != nil {
return fmt.Errorf("deleting SandboxClaim %q: %w", name, err) return fmt.Errorf("deleting SandboxClaim %q: %w", name, err)
} }

View file

@ -7,7 +7,6 @@ import (
"github.com/rathi/agentikube/internal/kube" "github.com/rathi/agentikube/internal/kube"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
) )
func NewDownCmd() *cobra.Command { func NewDownCmd() *cobra.Command {
@ -30,26 +29,14 @@ func NewDownCmd() *cobra.Command {
ns := cfg.Namespace ns := cfg.Namespace
warmPoolGVR := schema.GroupVersionResource{ err = client.Dynamic().Resource(sandboxWarmPoolGVR).Namespace(ns).Delete(ctx, "sandbox-warm-pool", metav1.DeleteOptions{})
Group: "agentsandbox.dev",
Version: "v1",
Resource: "sandboxwarmpools",
}
templateGVR := schema.GroupVersionResource{
Group: "agentsandbox.dev",
Version: "v1",
Resource: "sandboxtemplates",
}
err = client.Dynamic().Resource(warmPoolGVR).Namespace(ns).Delete(ctx, "sandbox-warm-pool", metav1.DeleteOptions{})
if err != nil { if err != nil {
fmt.Printf("[warn] could not delete SandboxWarmPool: %v\n", err) fmt.Printf("[warn] could not delete SandboxWarmPool: %v\n", err)
} else { } else {
fmt.Println("[ok] SandboxWarmPool deleted") fmt.Println("[ok] SandboxWarmPool deleted")
} }
err = client.Dynamic().Resource(templateGVR).Namespace(ns).Delete(ctx, "sandbox-template", metav1.DeleteOptions{}) err = client.Dynamic().Resource(sandboxTemplateGVR).Namespace(ns).Delete(ctx, "sandbox-template", metav1.DeleteOptions{})
if err != nil { if err != nil {
fmt.Printf("[warn] could not delete SandboxTemplate: %v\n", err) fmt.Printf("[warn] could not delete SandboxTemplate: %v\n", err)
} else { } else {

View file

@ -3,8 +3,31 @@ package commands
import ( import (
"github.com/rathi/agentikube/internal/config" "github.com/rathi/agentikube/internal/config"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime/schema"
) )
var (
sandboxClaimGVR = schema.GroupVersionResource{
Group: "extensions.agents.x-k8s.io",
Version: "v1alpha1",
Resource: "sandboxclaims",
}
sandboxTemplateGVR = schema.GroupVersionResource{
Group: "extensions.agents.x-k8s.io",
Version: "v1alpha1",
Resource: "sandboxtemplates",
}
sandboxWarmPoolGVR = schema.GroupVersionResource{
Group: "extensions.agents.x-k8s.io",
Version: "v1alpha1",
Resource: "sandboxwarmpools",
}
)
func coreGVR(resource string) schema.GroupVersionResource {
return schema.GroupVersionResource{Group: "", Version: "v1", Resource: resource}
}
func loadConfig(cmd *cobra.Command) (*config.Config, error) { func loadConfig(cmd *cobra.Command) (*config.Config, error) {
cfgPath, _ := cmd.Flags().GetString("config") cfgPath, _ := cmd.Flags().GetString("config")
return config.Load(cfgPath) return config.Load(cfgPath)

View file

@ -10,7 +10,6 @@ import (
"github.com/rathi/agentikube/internal/kube" "github.com/rathi/agentikube/internal/kube"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
) )
func NewListCmd() *cobra.Command { func NewListCmd() *cobra.Command {
@ -31,13 +30,7 @@ func NewListCmd() *cobra.Command {
return fmt.Errorf("connecting to cluster: %w", err) return fmt.Errorf("connecting to cluster: %w", err)
} }
claimGVR := schema.GroupVersionResource{ list, err := client.Dynamic().Resource(sandboxClaimGVR).Namespace(cfg.Namespace).List(ctx, metav1.ListOptions{})
Group: "agentsandbox.dev",
Version: "v1",
Resource: "sandboxclaims",
}
list, err := client.Dynamic().Resource(claimGVR).Namespace(cfg.Namespace).List(ctx, metav1.ListOptions{})
if err != nil { if err != nil {
return fmt.Errorf("listing SandboxClaims: %w", err) return fmt.Errorf("listing SandboxClaims: %w", err)
} }
@ -114,7 +107,7 @@ func extractPodName(obj map[string]interface{}) string {
if ok { if ok {
annotations, ok := metadata["annotations"].(map[string]interface{}) annotations, ok := metadata["annotations"].(map[string]interface{})
if ok { if ok {
if podName, ok := annotations["agentsandbox.dev/pod-name"].(string); ok { if podName, ok := annotations["agents.x-k8s.io/pod-name"].(string); ok {
return podName return podName
} }
} }

View file

@ -7,7 +7,6 @@ import (
"github.com/rathi/agentikube/internal/kube" "github.com/rathi/agentikube/internal/kube"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
) )
func NewSSHCmd() *cobra.Command { func NewSSHCmd() *cobra.Command {
@ -33,13 +32,7 @@ func NewSSHCmd() *cobra.Command {
ns := cfg.Namespace ns := cfg.Namespace
name := "sandbox-" + handle name := "sandbox-" + handle
claimGVR := schema.GroupVersionResource{ claim, err := client.Dynamic().Resource(sandboxClaimGVR).Namespace(ns).Get(ctx, name, metav1.GetOptions{})
Group: "agentsandbox.dev",
Version: "v1",
Resource: "sandboxclaims",
}
claim, err := client.Dynamic().Resource(claimGVR).Namespace(ns).Get(ctx, name, metav1.GetOptions{})
if err != nil { if err != nil {
return fmt.Errorf("getting SandboxClaim %q: %w", name, err) return fmt.Errorf("getting SandboxClaim %q: %w", name, err)
} }

View file

@ -7,7 +7,6 @@ import (
"github.com/rathi/agentikube/internal/kube" "github.com/rathi/agentikube/internal/kube"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
) )
func NewStatusCmd() *cobra.Command { func NewStatusCmd() *cobra.Command {
@ -31,13 +30,7 @@ func NewStatusCmd() *cobra.Command {
ns := cfg.Namespace ns := cfg.Namespace
// Warm pool status // Warm pool status
warmPoolGVR := schema.GroupVersionResource{ wp, err := client.Dynamic().Resource(sandboxWarmPoolGVR).Namespace(ns).Get(ctx, "sandbox-warm-pool", metav1.GetOptions{})
Group: "agentsandbox.dev",
Version: "v1",
Resource: "sandboxwarmpools",
}
wp, err := client.Dynamic().Resource(warmPoolGVR).Namespace(ns).Get(ctx, "sandbox-warm-pool", metav1.GetOptions{})
if err != nil { if err != nil {
fmt.Printf("warm pool: not found (%v)\n", err) fmt.Printf("warm pool: not found (%v)\n", err)
} else { } else {
@ -55,13 +48,7 @@ func NewStatusCmd() *cobra.Command {
} }
// Sandbox count // Sandbox count
claimGVR := schema.GroupVersionResource{ claims, err := client.Dynamic().Resource(sandboxClaimGVR).Namespace(ns).List(ctx, metav1.ListOptions{})
Group: "agentsandbox.dev",
Version: "v1",
Resource: "sandboxclaims",
}
claims, err := client.Dynamic().Resource(claimGVR).Namespace(ns).List(ctx, metav1.ListOptions{})
if err != nil { if err != nil {
fmt.Printf("\nsandboxes: error listing (%v)\n", err) fmt.Printf("\nsandboxes: error listing (%v)\n", err)
} else { } else {

View file

@ -46,7 +46,7 @@ func NewUpCmd() *cobra.Command {
if cfg.Sandbox.WarmPool.Enabled { if cfg.Sandbox.WarmPool.Enabled {
fmt.Println("waiting for warm pool to become ready...") fmt.Println("waiting for warm pool to become ready...")
if err := client.WaitForReady(ctx, cfg.Namespace, "sandboxwarmpools", "sandbox-warm-pool"); err != nil { if err := client.WaitForReady(ctx, cfg.Namespace, sandboxWarmPoolGVR, "sandbox-warm-pool"); err != nil {
return fmt.Errorf("waiting for warm pool: %w", err) return fmt.Errorf("waiting for warm pool: %w", err)
} }
fmt.Println("[ok] warm pool ready") fmt.Println("[ok] warm pool ready")

View file

@ -10,34 +10,27 @@ import (
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
) )
// WaitForReady watches a resource in the agentsandbox.dev/v1 group until its // WaitForReady watches a resource until its Ready condition becomes True
// Ready condition becomes True or the context is cancelled/times out. // or the context is cancelled/times out.
// The resource parameter is the plural resource name (e.g. "sandboxclaims", "sandboxwarmpools"). func (c *Client) WaitForReady(ctx context.Context, namespace string, gvr schema.GroupVersionResource, name string) error {
func (c *Client) WaitForReady(ctx context.Context, namespace, resource, name string) error {
gvr := schema.GroupVersionResource{
Group: "agentsandbox.dev",
Version: "v1",
Resource: resource,
}
watcher, err := c.Dynamic().Resource(gvr).Namespace(namespace).Watch(ctx, metav1.ListOptions{ watcher, err := c.Dynamic().Resource(gvr).Namespace(namespace).Watch(ctx, metav1.ListOptions{
FieldSelector: fmt.Sprintf("metadata.name=%s", name), FieldSelector: fmt.Sprintf("metadata.name=%s", name),
}) })
if err != nil { if err != nil {
return fmt.Errorf("watching %s %s/%s: %w", resource, namespace, name, err) return fmt.Errorf("watching %s %s/%s: %w", gvr.Resource, namespace, name, err)
} }
defer watcher.Stop() defer watcher.Stop()
for { for {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return fmt.Errorf("timed out waiting for %s %s/%s to become ready", resource, namespace, name) return fmt.Errorf("timed out waiting for %s %s/%s to become ready", gvr.Resource, namespace, name)
case event, ok := <-watcher.ResultChan(): case event, ok := <-watcher.ResultChan():
if !ok { if !ok {
return fmt.Errorf("watch channel closed for %s %s/%s", resource, namespace, name) return fmt.Errorf("watch channel closed for %s %s/%s", gvr.Resource, namespace, name)
} }
if event.Type == watch.Error { if event.Type == watch.Error {
return fmt.Errorf("watch error for %s %s/%s", resource, namespace, name) return fmt.Errorf("watch error for %s %s/%s", gvr.Resource, namespace, name)
} }
obj, ok := event.Object.(*unstructured.Unstructured) obj, ok := event.Object.(*unstructured.Unstructured)

View file

@ -1,4 +1,4 @@
apiVersion: agentsandbox.dev/v1 apiVersion: extensions.agents.x-k8s.io/v1alpha1
kind: SandboxTemplate kind: SandboxTemplate
metadata: metadata:
name: sandbox-template name: sandbox-template

View file

@ -1,4 +1,4 @@
apiVersion: agentsandbox.dev/v1 apiVersion: extensions.agents.x-k8s.io/v1alpha1
kind: SandboxWarmPool kind: SandboxWarmPool
metadata: metadata:
name: sandbox-warm-pool name: sandbox-warm-pool