From efe88a8cc4845f5e0ba721a0d6df0db2bf385b1c Mon Sep 17 00:00:00 2001 From: mesutoezdil Date: Mon, 8 Jun 2026 19:35:28 +0200 Subject: [PATCH] fix(agentharness): fall back to status.conditions when phase is UNSPECIFIED When the OpenShell gateway omits the phase field (returns UNSPECIFIED), the controller was setting Ready=Unknown permanently. If status.conditions contains Ready=True, use that instead. Fixes #1958 Signed-off-by: mesutoezdil --- .../pkg/sandboxbackend/openshell/translate.go | 5 ++ .../openshell/translate_test.go | 79 +++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/go/core/pkg/sandboxbackend/openshell/translate.go b/go/core/pkg/sandboxbackend/openshell/translate.go index d29c1fd8b1..8cd41f21d9 100644 --- a/go/core/pkg/sandboxbackend/openshell/translate.go +++ b/go/core/pkg/sandboxbackend/openshell/translate.go @@ -78,6 +78,11 @@ func phaseToCondition(sb *openshellv1.Sandbox) (metav1.ConditionStatus, string, case openshellv1.SandboxPhase_SANDBOX_PHASE_DELETING: return metav1.ConditionFalse, "SandboxDeleting", msg case openshellv1.SandboxPhase_SANDBOX_PHASE_UNKNOWN, openshellv1.SandboxPhase_SANDBOX_PHASE_UNSPECIFIED: + for _, c := range sb.GetStatus().GetConditions() { + if c.GetType() == "Ready" && c.GetStatus() == "True" { + return metav1.ConditionTrue, "SandboxReady", msg + } + } return metav1.ConditionUnknown, "SandboxPhaseUnknown", msg default: return metav1.ConditionUnknown, "SandboxPhaseUnrecognized", fmt.Sprintf("unrecognized phase %s", sb.GetPhase()) diff --git a/go/core/pkg/sandboxbackend/openshell/translate_test.go b/go/core/pkg/sandboxbackend/openshell/translate_test.go index 88f7124f42..571b3e3531 100644 --- a/go/core/pkg/sandboxbackend/openshell/translate_test.go +++ b/go/core/pkg/sandboxbackend/openshell/translate_test.go @@ -3,6 +3,7 @@ package openshell import ( "testing" + openshellv1 "github.com/kagent-dev/kagent/go/api/openshell/gen/openshellv1" "github.com/kagent-dev/kagent/go/api/v1alpha2" "github.com/kagent-dev/kagent/go/core/pkg/sandboxbackend/openclaw" "github.com/kagent-dev/kagent/go/core/pkg/sandboxbackend/openshell/hermes" @@ -10,6 +11,84 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +func TestPhaseToCondition(t *testing.T) { + ready := []*openshellv1.SandboxCondition{{Type: "Ready", Status: "True"}} + notReady := []*openshellv1.SandboxCondition{{Type: "Ready", Status: "False"}} + + tests := []struct { + name string + sb *openshellv1.Sandbox + wantStatus metav1.ConditionStatus + wantReason string + }{ + { + name: "nil sandbox", + sb: nil, + wantStatus: metav1.ConditionUnknown, + wantReason: "SandboxNotFound", + }, + { + name: "ready phase", + sb: &openshellv1.Sandbox{Phase: openshellv1.SandboxPhase_SANDBOX_PHASE_READY}, + wantStatus: metav1.ConditionTrue, + wantReason: "SandboxReady", + }, + { + name: "provisioning phase", + sb: &openshellv1.Sandbox{Phase: openshellv1.SandboxPhase_SANDBOX_PHASE_PROVISIONING}, + wantStatus: metav1.ConditionFalse, + wantReason: "SandboxProvisioning", + }, + { + name: "error phase", + sb: &openshellv1.Sandbox{Phase: openshellv1.SandboxPhase_SANDBOX_PHASE_ERROR}, + wantStatus: metav1.ConditionFalse, + wantReason: "SandboxError", + }, + { + name: "unspecified phase no conditions", + sb: &openshellv1.Sandbox{Phase: openshellv1.SandboxPhase_SANDBOX_PHASE_UNSPECIFIED}, + wantStatus: metav1.ConditionUnknown, + wantReason: "SandboxPhaseUnknown", + }, + { + name: "unspecified phase with Ready=True falls back to ready", + sb: &openshellv1.Sandbox{ + Phase: openshellv1.SandboxPhase_SANDBOX_PHASE_UNSPECIFIED, + Status: &openshellv1.SandboxStatus{Conditions: ready}, + }, + wantStatus: metav1.ConditionTrue, + wantReason: "SandboxReady", + }, + { + name: "unknown phase with Ready=True falls back to ready", + sb: &openshellv1.Sandbox{ + Phase: openshellv1.SandboxPhase_SANDBOX_PHASE_UNKNOWN, + Status: &openshellv1.SandboxStatus{Conditions: ready}, + }, + wantStatus: metav1.ConditionTrue, + wantReason: "SandboxReady", + }, + { + name: "unspecified phase with Ready=False stays unknown", + sb: &openshellv1.Sandbox{ + Phase: openshellv1.SandboxPhase_SANDBOX_PHASE_UNSPECIFIED, + Status: &openshellv1.SandboxStatus{Conditions: notReady}, + }, + wantStatus: metav1.ConditionUnknown, + wantReason: "SandboxPhaseUnknown", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + status, reason, _ := phaseToCondition(tt.sb) + require.Equal(t, tt.wantStatus, status) + require.Equal(t, tt.wantReason, reason) + }) + } +} + func TestBuildOpenshellCreateRequest_AllowedDomainsPolicy(t *testing.T) { sbx := &v1alpha2.AgentHarness{ ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: "ns"},