Skip to content

Commit 983d2f9

Browse files
committed
Stacks: Add create-from-blueprint command
1 parent cb08246 commit 983d2f9

File tree

4 files changed

+150
-0
lines changed

4 files changed

+150
-0
lines changed

cmd/cycloid/middleware/middleware.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ type Middleware interface {
3535
UpdateStack(org, ref, teamCanonical string, visibility *string) (*models.ServiceCatalog, error)
3636
ListStacks(org string) ([]*models.ServiceCatalog, error)
3737
ListBlueprints(org string) ([]*models.ServiceCatalog, error)
38+
CreateStackFromBlueprint(org, blueprintRef, name, canonical, serviceCatalogSourceCanonical, useCase string) (*models.ServiceCatalog, error)
3839
GetStackConfig(org, ref string) (models.ServiceCatalogConfigs, error)
3940

4041
// organization_credentials

cmd/cycloid/middleware/stacks.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/cycloidio/cycloid-cli/client/client/service_catalogs"
1313
"github.com/cycloidio/cycloid-cli/client/models"
14+
"github.com/cycloidio/cycloid-cli/internal/ptr"
1415
)
1516

1617
func (m *middleware) GetStack(org, ref string) (*models.ServiceCatalog, error) {
@@ -108,6 +109,39 @@ func (m *middleware) ListBlueprints(org string) ([]*models.ServiceCatalog, error
108109
return validBlueprints, nil
109110
}
110111

112+
func (m *middleware) CreateStackFromBlueprint(org, blueprintRef, name, canonical, serviceCatalogSourceCanonical, useCase string) (*models.ServiceCatalog, error) {
113+
params := service_catalogs.NewCreateServiceCatalogFromTemplateParams()
114+
params.SetOrganizationCanonical(org)
115+
params.SetServiceCatalogRef(blueprintRef)
116+
117+
body := &models.NewServiceCatalogFromTemplate{
118+
Name: ptr.Ptr(name),
119+
Canonical: ptr.Ptr(canonical),
120+
ServiceCatalogSourceCanonical: ptr.Ptr(serviceCatalogSourceCanonical),
121+
UseCase: ptr.Ptr(useCase),
122+
}
123+
124+
err := body.Validate(strfmt.Default)
125+
if err != nil {
126+
return nil, errors.Wrap(err, "validation failed for createServiceCatalogFromTemplate input")
127+
}
128+
129+
params.WithBody(body)
130+
131+
resp, err := m.api.ServiceCatalogs.CreateServiceCatalogFromTemplate(params, m.api.Credentials(&org))
132+
if err != nil {
133+
return nil, NewApiError(err)
134+
}
135+
136+
payload := resp.GetPayload()
137+
err = payload.Validate(strfmt.Default)
138+
if err != nil {
139+
return payload.Data, fmt.Errorf("invalid response from the API: %v", err)
140+
}
141+
142+
return payload.Data, nil
143+
}
144+
111145

112146

113147
func (m *middleware) UpdateStack(

cmd/cycloid/stacks/cmd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ func NewCommands() *cobra.Command {
1919
NewGetCommand(),
2020
NewUpdateCommand(),
2121
NewConfigGetCommand(),
22+
NewCreateFromBlueprintCommand(),
2223
NewFormsCommands(),
2324
NewConfigCommands(),
2425
)
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package stacks
2+
3+
import (
4+
"github.com/pkg/errors"
5+
"github.com/spf13/cobra"
6+
7+
"github.com/cycloidio/cycloid-cli/cmd/cycloid/common"
8+
"github.com/cycloidio/cycloid-cli/cmd/cycloid/middleware"
9+
"github.com/cycloidio/cycloid-cli/internal/cyargs"
10+
"github.com/cycloidio/cycloid-cli/printer"
11+
"github.com/cycloidio/cycloid-cli/printer/factory"
12+
)
13+
14+
// CreateFromBlueprintOutput represents the formatted output for create-from-blueprint command
15+
type CreateFromBlueprintOutput struct {
16+
Canonical string `json:"canonical"`
17+
Name string `json:"name"`
18+
Ref string `json:"ref"`
19+
Description string `json:"description"`
20+
}
21+
22+
func NewCreateFromBlueprintCommand() *cobra.Command {
23+
var cmd = &cobra.Command{
24+
Use: "create-from-blueprint",
25+
Short: "create a new stack from a blueprint",
26+
Example: `cy --org my-org stack create-from-blueprint --blueprint-ref repo:blueprint-canonical --name "My Stack" --canonical my-stack --service-catalog-source-canonical my-catalog --use-case production`,
27+
RunE: createFromBlueprint,
28+
}
29+
30+
cmd.Flags().String("blueprint-ref", "", "Blueprint reference to use as template (required)")
31+
cmd.MarkFlagRequired("blueprint-ref")
32+
33+
cmd.Flags().String("name", "", "Name of the new stack (required)")
34+
cmd.MarkFlagRequired("name")
35+
36+
cmd.Flags().String("canonical", "", "Canonical name (slug) of the new stack (required)")
37+
cmd.MarkFlagRequired("canonical")
38+
39+
cmd.Flags().String("service-catalog-source-canonical", "", "Service catalog source canonical (required)")
40+
cmd.MarkFlagRequired("service-catalog-source-canonical")
41+
42+
cmd.Flags().String("use-case", "", "Use case canonical to apply from the blueprint (required)")
43+
cmd.MarkFlagRequired("use-case")
44+
45+
return cmd
46+
}
47+
48+
func createFromBlueprint(cmd *cobra.Command, args []string) error {
49+
api := common.NewAPI()
50+
m := middleware.NewMiddleware(api)
51+
52+
org, err := cyargs.GetOrg(cmd)
53+
if err != nil {
54+
return err
55+
}
56+
57+
output, err := cyargs.GetOutput(cmd)
58+
if err != nil {
59+
return err
60+
}
61+
62+
// Get required flags
63+
blueprintRef, err := cmd.Flags().GetString("blueprint-ref")
64+
if err != nil {
65+
return err
66+
}
67+
68+
name, err := cmd.Flags().GetString("name")
69+
if err != nil {
70+
return err
71+
}
72+
73+
canonical, err := cmd.Flags().GetString("canonical")
74+
if err != nil {
75+
return err
76+
}
77+
78+
serviceCatalogSourceCanonical, err := cmd.Flags().GetString("service-catalog-source-canonical")
79+
if err != nil {
80+
return err
81+
}
82+
83+
useCase, err := cmd.Flags().GetString("use-case")
84+
if err != nil {
85+
return err
86+
}
87+
88+
// fetch the printer from the factory
89+
p, err := factory.GetPrinter(output)
90+
if err != nil {
91+
return errors.Wrap(err, "unable to get printer")
92+
}
93+
94+
// Create the stack from blueprint
95+
stack, err := m.CreateStackFromBlueprint(org, blueprintRef, name, canonical, serviceCatalogSourceCanonical, useCase)
96+
if err != nil {
97+
return printer.SmartPrint(p, nil, err, "failed to create stack from blueprint", printer.Options{}, cmd.OutOrStdout())
98+
}
99+
100+
// For JSON output, return all fields; for table output, return only specific fields
101+
if output == "json" {
102+
return printer.SmartPrint(p, stack, nil, "", printer.Options{}, cmd.OutOrStdout())
103+
}
104+
105+
// For table output, format to show only the requested fields
106+
formattedOutput := &CreateFromBlueprintOutput{
107+
Canonical: getStringValue(stack.Canonical),
108+
Name: getStringValue(stack.Name),
109+
Ref: getStringValue(stack.Ref),
110+
Description: stack.Description,
111+
}
112+
113+
return printer.SmartPrint(p, formattedOutput, nil, "", printer.Options{}, cmd.OutOrStdout())
114+
}

0 commit comments

Comments
 (0)