Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions cli/cmd/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,14 @@ Examples:
case output.FormatYAML:
return printer.PrintYAML(resp)
default:
headers := []string{"ID", "NAME", "DESCRIPTION", "OWNER", "CHARTS"}
headers := []string{"ID", "NAME", "DESCRIPTION", "OWNER"}
rows := make([][]string, len(resp.Data))
for i, d := range resp.Data {
rows[i] = []string{
d.ID,
d.Name,
d.Description,
d.Owner,
strconv.Itoa(len(d.Charts)),
}
}
return printer.PrintTable(headers, rows)
Expand Down Expand Up @@ -391,7 +390,7 @@ func printDefinition(def *types.StackDefinition) error {
for _, ch := range def.Charts {
fields = append(fields, output.KeyValue{
Key: "Chart",
Value: fmt.Sprintf("%s (%s@%s)", ch.Name, ch.RepoURL, ch.ChartVersion),
Value: fmt.Sprintf("%s (%s@%s)", ch.ChartName, ch.RepoURL, ch.ChartVersion),
})
}
return printer.PrintSingle(def, fields)
Expand Down
2 changes: 0 additions & 2 deletions cli/cmd/definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,10 @@ func TestDefinitionListCmd_TableOutput(t *testing.T) {
assert.Contains(t, out, "NAME")
assert.Contains(t, out, "DESCRIPTION")
assert.Contains(t, out, "OWNER")
assert.Contains(t, out, "CHARTS")
assert.Contains(t, out, "5")
assert.Contains(t, out, "api-service")
assert.Contains(t, out, "API microservice stack")
assert.Contains(t, out, "admin")
assert.Contains(t, out, "1")
}

func TestDefinitionListCmd_JSONOutput(t *testing.T) {
Expand Down
18 changes: 9 additions & 9 deletions cli/cmd/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,17 +203,17 @@ Examples:
return err
}

log, err := c.DeployStack(id)
resp, err := c.DeployStack(id)
if err != nil {
return err
}

if printer.Quiet {
fmt.Fprintln(printer.Writer, log.ID)
fmt.Fprintln(printer.Writer, resp.LogID)
return nil
}

printer.PrintMessage("Deploying stack %s... (log ID: %s)", id, log.ID)
printer.PrintMessage("Deploying stack %s... (log ID: %s)", id, resp.LogID)
return nil
},
}
Expand All @@ -238,17 +238,17 @@ Examples:
return err
}

log, err := c.StopStack(id)
resp, err := c.StopStack(id)
if err != nil {
return err
}

if printer.Quiet {
fmt.Fprintln(printer.Writer, log.ID)
fmt.Fprintln(printer.Writer, resp.LogID)
return nil
}

printer.PrintMessage("Stopping stack %s... (log ID: %s)", id, log.ID)
printer.PrintMessage("Stopping stack %s... (log ID: %s)", id, resp.LogID)
return nil
},
}
Expand Down Expand Up @@ -286,17 +286,17 @@ Examples:
return err
}

log, err := c.CleanStack(id)
resp, err := c.CleanStack(id)
if err != nil {
return err
}

if printer.Quiet {
fmt.Fprintln(printer.Writer, log.ID)
fmt.Fprintln(printer.Writer, resp.LogID)
return nil
}

printer.PrintMessage("Cleaning stack %s... (log ID: %s)", id, log.ID)
printer.PrintMessage("Cleaning stack %s... (log ID: %s)", id, resp.LogID)
return nil
},
}
Expand Down
26 changes: 13 additions & 13 deletions cli/cmd/stack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,8 @@ func TestStackDeployCmd_Success(t *testing.T) {
require.Equal(t, "/api/v1/stack-instances/42/deploy", r.URL.Path)
require.Equal(t, http.MethodPost, r.Method)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(types.DeploymentLog{ID: "100", InstanceID: "42", Action: "deploy", Status: "started"})
w.WriteHeader(http.StatusAccepted)
json.NewEncoder(w).Encode(types.DeployResponse{LogID: "100", Message: "Deployment started"})
}))
defer server.Close()

Expand All @@ -381,8 +381,8 @@ func TestStackDeployCmd_Success(t *testing.T) {
func TestStackDeployCmd_QuietOutput(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(types.DeploymentLog{ID: "100"})
w.WriteHeader(http.StatusAccepted)
json.NewEncoder(w).Encode(types.DeployResponse{LogID: "100", Message: "Deployment started"})
}))
defer server.Close()

Expand All @@ -400,8 +400,8 @@ func TestStackStopCmd_Success(t *testing.T) {
require.Equal(t, "/api/v1/stack-instances/42/stop", r.URL.Path)
require.Equal(t, http.MethodPost, r.Method)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(types.DeploymentLog{ID: "101", InstanceID: "42", Action: "stop", Status: "started"})
w.WriteHeader(http.StatusAccepted)
json.NewEncoder(w).Encode(types.DeployResponse{LogID: "101", Message: "Stop started"})
}))
defer server.Close()

Expand All @@ -423,7 +423,7 @@ func TestStackCleanCmd_WithConfirmation(t *testing.T) {
require.Equal(t, "/api/v1/stack-instances/42/clean", r.URL.Path)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(types.DeploymentLog{ID: "102"})
json.NewEncoder(w).Encode(types.DeployResponse{LogID: "102", Message: "Clean started"})
}))
defer server.Close()

Expand Down Expand Up @@ -474,7 +474,7 @@ func TestStackCleanCmd_WithYesFlag(t *testing.T) {
called = true
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(types.DeploymentLog{ID: "103"})
json.NewEncoder(w).Encode(types.DeployResponse{LogID: "103", Message: "Clean started"})
}))
defer server.Close()

Expand Down Expand Up @@ -893,8 +893,8 @@ func TestStackDeleteCmd_QuietOutput(t *testing.T) {
func TestStackStopCmd_QuietOutput(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(types.DeploymentLog{ID: "101"})
w.WriteHeader(http.StatusAccepted)
json.NewEncoder(w).Encode(types.DeployResponse{LogID: "101", Message: "Stop started"})
}))
defer server.Close()

Expand Down Expand Up @@ -927,8 +927,8 @@ func TestStackExtendCmd_QuietOutput(t *testing.T) {
func TestStackCleanCmd_QuietOutput(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(types.DeploymentLog{ID: "102"})
w.WriteHeader(http.StatusAccepted)
json.NewEncoder(w).Encode(types.DeployResponse{LogID: "102", Message: "Clean started"})
}))
defer server.Close()

Expand Down Expand Up @@ -982,7 +982,7 @@ func TestStackGetCmd_YAMLOutput(t *testing.T) {

out := buf.String()
assert.Contains(t, out, "name: my-stack")
assert.Contains(t, out, "owner: admin")
assert.Contains(t, out, "owner_id: admin")
}

func TestStackStatusCmd_YAMLOutput(t *testing.T) {
Expand Down
16 changes: 8 additions & 8 deletions cli/cmd/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Examples:
case output.FormatYAML:
return printer.PrintYAML(resp)
default:
headers := []string{"ID", "NAME", "DESCRIPTION", "PUBLISHED", "CHARTS"}
headers := []string{"ID", "NAME", "DESCRIPTION", "PUBLISHED", "DEFINITIONS"}
rows := make([][]string, len(resp.Data))
for i, t := range resp.Data {
published := "false"
Expand All @@ -82,7 +82,7 @@ Examples:
t.Name,
t.Description,
published,
strconv.Itoa(len(t.Charts)),
strconv.Itoa(t.DefinitionCount),
}
}
return printer.PrintTable(headers, rows)
Expand Down Expand Up @@ -141,7 +141,7 @@ Examples:
for _, ch := range tmpl.Charts {
fields = append(fields, output.KeyValue{
Key: "Chart",
Value: fmt.Sprintf("%s (%s@%s)", ch.Name, ch.RepoURL, ch.ChartVersion),
Value: fmt.Sprintf("%s (%s@%s)", ch.ChartName, ch.RepoURL, ch.ChartVersion),
})
}
return printer.PrintSingle(tmpl, fields)
Expand All @@ -151,8 +151,8 @@ Examples:

var templateInstantiateCmd = &cobra.Command{
Use: "instantiate <id>",
Short: "Create a stack instance from a template",
Long: `Create a new stack instance from a template.
Short: "Create a stack definition from a template",
Long: `Create a new stack definition from a template.

Examples:
stackctl template instantiate 1 --name my-stack
Expand Down Expand Up @@ -180,12 +180,12 @@ Examples:
return err
}

instance, err := c.InstantiateTemplate(id, req)
def, err := c.InstantiateTemplate(id, req)
if err != nil {
return err
}

return printInstance(instance)
return printDefinition(def)
},
}

Expand Down Expand Up @@ -236,7 +236,7 @@ func init() {
templateListCmd.Flags().Int(flagPageSize, 0, "Page size")

// template instantiate flags
templateInstantiateCmd.Flags().String("name", "", "Stack instance name (required)")
templateInstantiateCmd.Flags().String("name", "", "Stack definition name (required)")
templateInstantiateCmd.Flags().String("branch", "", "Git branch")
templateInstantiateCmd.Flags().String("cluster", "", "Target cluster ID")
_ = templateInstantiateCmd.MarkFlagRequired("name")
Expand Down
31 changes: 18 additions & 13 deletions cli/cmd/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ import (
func sampleTemplate() types.StackTemplate {
now := time.Date(2025, 6, 15, 10, 0, 0, 0, time.UTC)
return types.StackTemplate{
Base: types.Base{ID: "10", CreatedAt: now, UpdatedAt: now, Version: "1"},
Name: "web-app-template",
Description: "Full web app stack",
Published: true,
Owner: "admin",
Base: types.Base{ID: "10", CreatedAt: now, UpdatedAt: now, Version: "1"},
Name: "web-app-template",
Description: "Full web app stack",
Published: true,
Owner: "admin",
DefinitionCount: 2,
Charts: []types.ChartConfig{
{
Base: types.Base{ID: "1"},
Expand Down Expand Up @@ -70,7 +71,7 @@ func TestTemplateListCmd_TableOutput(t *testing.T) {
assert.Contains(t, out, "NAME")
assert.Contains(t, out, "DESCRIPTION")
assert.Contains(t, out, "PUBLISHED")
assert.Contains(t, out, "CHARTS")
assert.Contains(t, out, "DEFINITIONS")
assert.Contains(t, out, "10")
assert.Contains(t, out, "web-app-template")
assert.Contains(t, out, "Full web app stack")
Expand Down Expand Up @@ -217,8 +218,8 @@ func TestTemplateGetCmd_TableOutput(t *testing.T) {
assert.Contains(t, out, "Full web app stack")
assert.Contains(t, out, "true")
assert.Contains(t, out, "admin")
assert.Contains(t, out, "frontend")
assert.Contains(t, out, "backend")
assert.Contains(t, out, "react-app")
assert.Contains(t, out, "api-server")
}

func TestTemplateGetCmd_JSONOutput(t *testing.T) {
Expand Down Expand Up @@ -275,7 +276,11 @@ func TestTemplateGetCmd_NotFound(t *testing.T) {
// ---------- template instantiate ----------

func TestTemplateInstantiateCmd_Success(t *testing.T) {
instance := sampleStack()
def := types.StackDefinition{
Base: types.Base{ID: "42"},
Name: "my-def",
Owner: "uid-1",
}
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, "/api/v1/templates/10/instantiate", r.URL.Path)
require.Equal(t, http.MethodPost, r.Method)
Expand All @@ -286,7 +291,7 @@ func TestTemplateInstantiateCmd_Success(t *testing.T) {

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(instance)
json.NewEncoder(w).Encode(def)
}))
defer server.Close()

Expand All @@ -304,7 +309,7 @@ func TestTemplateInstantiateCmd_Success(t *testing.T) {

out := buf.String()
assert.Contains(t, out, "42")
assert.Contains(t, out, "my-stack")
assert.Contains(t, out, "my-def")
}

func TestTemplateInstantiateCmd_WithBranchAndCluster(t *testing.T) {
Expand All @@ -317,7 +322,7 @@ func TestTemplateInstantiateCmd_WithBranchAndCluster(t *testing.T) {

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(types.StackInstance{Base: types.Base{ID: "50"}, Name: "my-instance"})
json.NewEncoder(w).Encode(types.StackDefinition{Base: types.Base{ID: "50"}, Name: "my-instance"})
}))
defer server.Close()

Expand Down Expand Up @@ -371,7 +376,7 @@ func TestTemplateInstantiateCmd_QuietOutput(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(types.StackInstance{Base: types.Base{ID: "50"}})
json.NewEncoder(w).Encode(types.StackDefinition{Base: types.Base{ID: "50"}})
}))
defer server.Close()

Expand Down
34 changes: 17 additions & 17 deletions cli/pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,33 +301,33 @@ func (c *Client) DeleteStack(id string) error {
}

// DeployStack triggers a deployment for a stack instance.
func (c *Client) DeployStack(id string) (*types.DeploymentLog, error) {
var log types.DeploymentLog
err := c.Post(fmt.Sprintf("/api/v1/stack-instances/%s/deploy", id), nil, &log)
func (c *Client) DeployStack(id string) (*types.DeployResponse, error) {
var resp types.DeployResponse
err := c.Post(fmt.Sprintf("/api/v1/stack-instances/%s/deploy", id), nil, &resp)
if err != nil {
return nil, err
}
return &log, nil
return &resp, nil
}

// StopStack triggers a stop for a stack instance.
func (c *Client) StopStack(id string) (*types.DeploymentLog, error) {
var log types.DeploymentLog
err := c.Post(fmt.Sprintf("/api/v1/stack-instances/%s/stop", id), nil, &log)
func (c *Client) StopStack(id string) (*types.DeployResponse, error) {
var resp types.DeployResponse
err := c.Post(fmt.Sprintf("/api/v1/stack-instances/%s/stop", id), nil, &resp)
if err != nil {
return nil, err
}
return &log, nil
return &resp, nil
}

// CleanStack triggers an undeploy and namespace removal for a stack instance.
func (c *Client) CleanStack(id string) (*types.DeploymentLog, error) {
var log types.DeploymentLog
err := c.Post(fmt.Sprintf("/api/v1/stack-instances/%s/clean", id), nil, &log)
func (c *Client) CleanStack(id string) (*types.DeployResponse, error) {
var resp types.DeployResponse
err := c.Post(fmt.Sprintf("/api/v1/stack-instances/%s/clean", id), nil, &resp)
if err != nil {
return nil, err
}
return &log, nil
return &resp, nil
}

// GetStackStatus returns the current status and pod states for a stack instance.
Expand Down Expand Up @@ -424,14 +424,14 @@ func (c *Client) GetTemplate(id string) (*types.StackTemplate, error) {
return &tmpl, nil
}

// InstantiateTemplate creates a new stack instance from a template.
func (c *Client) InstantiateTemplate(id string, req *types.InstantiateTemplateRequest) (*types.StackInstance, error) {
var instance types.StackInstance
err := c.Post(fmt.Sprintf("/api/v1/templates/%s/instantiate", id), req, &instance)
// InstantiateTemplate creates a new stack definition from a template.
func (c *Client) InstantiateTemplate(id string, req *types.InstantiateTemplateRequest) (*types.StackDefinition, error) {
var def types.StackDefinition
err := c.Post(fmt.Sprintf("/api/v1/templates/%s/instantiate", id), req, &def)
if err != nil {
return nil, err
}
return &instance, nil
return &def, nil
}

// QuickDeployTemplate creates and deploys a stack instance from a template in one step.
Expand Down
Loading
Loading