fix: complete P2 host workspace contract

This commit is contained in:
2026-08-11 00:39:44 +02:00
parent ccaf8c1be0
commit 9df7c38069
13 changed files with 849 additions and 252 deletions
+55 -4
View File
@@ -90,11 +90,48 @@ func run(ctx context.Context, args []string, stdout, stderr io.Writer) int {
runner := compose.NewRunner("")
if command == "workspace" {
workspaceCommand, parseErr := workspaceops.ParseWorkspaceCommand(append([]string{"workspace"}, commandArgs...))
if parseErr != nil { return commandUsageError(stderr, parseErr.Error()) }
if parseErr != nil {
return commandUsageError(stderr, parseErr.Error())
}
result, operationErr := workspaceops.Run(ctx, installation, runner, workspaceCommand, nil)
if operationErr != nil { if errors.Is(operationErr, compose.ErrOutputLimit) || strings.Contains(operationErr.Error(), "unsafe") || strings.Contains(operationErr.Error(), "exceeds") { return commandUsageError(stderr, operationErr.Error()) }; fmt.Fprintf(stderr, "thothctl: %s\n", output.Sanitize(operationErr.Error(), secretValues)); return 1 }
if err := json.NewEncoder(stdout).Encode(result); err != nil { return 1 }
if result.Status == "blocked" { return 3 }; if result.Status == "failed" { return 1 }; return 0
if operationErr != nil {
if errors.Is(operationErr, compose.ErrOutputLimit) || strings.Contains(operationErr.Error(), "unsafe") || strings.Contains(operationErr.Error(), "exceeds") || strings.Contains(operationErr.Error(), "invalid workspace") {
return commandUsageError(stderr, operationErr.Error())
}
fmt.Fprintf(stderr, "thothctl: %s\n", output.Sanitize(operationErr.Error(), secretValues))
return 1
}
jsonMode := true
switch c := workspaceCommand.(type) {
case workspaceops.InspectCommand:
jsonMode = c.JSON
case workspaceops.DwhRequest:
jsonMode = c.JSON
case workspaceops.SuggestFksRequest:
jsonMode = c.JSON
case workspaceops.CheckSchemaRequest:
jsonMode = c.JSON
case workspaceops.IndexSchemaRequest:
jsonMode = c.JSON
case workspaceops.EvidenceRequest:
jsonMode = c.JSON
case workspaceops.RunRequest:
jsonMode = c.JSON
}
if jsonMode {
if err := json.NewEncoder(stdout).Encode(result); err != nil {
return 1
}
} else {
renderWorkspaceHuman(stdout, result)
}
if result.Status == "blocked" {
return 3
}
if result.Status == "failed" {
return 1
}
return 0
}
var result compose.Result
switch command {
@@ -173,6 +210,20 @@ func run(ctx context.Context, args []string, stdout, stderr io.Writer) int {
return writeResult(result, err, secretValues, stdout, stderr)
}
func renderWorkspaceHuman(w io.Writer, result workspaceops.Result) {
if result.Code == workspaceops.CodeRegistryBootstrapRecoveryConflict {
fmt.Fprintln(w, "Bootstrap recovery is ambiguous or corrupt; inspect the installation registry jobs.")
return
}
fmt.Fprintf(w, "Workspace %s: %s (%s)\n", result.WorkspaceID, result.Status, result.Code)
if result.RunID != "" {
fmt.Fprintf(w, "Run: %s\n", result.RunID)
}
if len(result.CompletedStages) > 0 {
fmt.Fprintf(w, "Completed stages: %s\n", strings.Join(result.CompletedStages, ", "))
}
}
func writeRemovalTargets(outputWriter io.Writer, project string, targets []serverops.Container) {
fmt.Fprintf(outputWriter, "Removal targets for installation project %s:\n", project)
if len(targets) == 0 {
+9
View File
@@ -15,6 +15,7 @@ import (
"github.com/aritmolab/thothii/tools/thothctl/internal/config"
"github.com/aritmolab/thothii/tools/thothctl/internal/pi"
"github.com/aritmolab/thothii/tools/thothctl/internal/testsupport"
"github.com/aritmolab/thothii/tools/thothctl/internal/workspaceops"
)
func TestInstallationRunnerMapsProfileToSessionInventoryScope(t *testing.T) {
@@ -846,3 +847,11 @@ func assertInvocationContains(t *testing.T, invocations [][]string, want ...stri
}
t.Fatalf("invocations = %#v, want %#v", invocations, want)
}
func TestRenderWorkspaceHumanHidesRecoveryIdentity(t *testing.T) {
var out bytes.Buffer
renderWorkspaceHuman(&out, workspaceops.Result{WorkspaceID: "psd", Status: "blocked", Code: workspaceops.CodeRegistryBootstrapRecoveryConflict, RunID: "0123456789abcdef0123456789abcdef"})
if out.String() != "Bootstrap recovery is ambiguous or corrupt; inspect the installation registry jobs.\n" {
t.Fatalf("human output = %q", out.String())
}
}