Skip to content

Commit c7041e7

Browse files
authored
deployment command: Remove flag based create (#460)
Removes the flags to change the deployment create request properties and instead adds the ability to use the deployment template defaults and document a workflow that can be used to easily tweak those settings and create a deployment with the file declaration instead. Signed-off-by: Marc Lopez <marc5.12@outlook.com>
1 parent 54cd667 commit c7041e7

File tree

8 files changed

+596
-694
lines changed

8 files changed

+596
-694
lines changed

cmd/deployment/create.go

Lines changed: 42 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,12 @@
1818
package cmddeployment
1919

2020
import (
21-
"encoding/json"
2221
"errors"
2322
"fmt"
2423
"strings"
2524

2625
"github.com/elastic/cloud-sdk-go/pkg/api/deploymentapi"
27-
"github.com/elastic/cloud-sdk-go/pkg/api/deploymentapi/deploymentsize"
28-
"github.com/elastic/cloud-sdk-go/pkg/api/deploymentapi/depresourceapi"
26+
"github.com/elastic/cloud-sdk-go/pkg/api/deploymentapi/deptemplateapi"
2927
"github.com/elastic/cloud-sdk-go/pkg/models"
3028
"github.com/elastic/cloud-sdk-go/pkg/multierror"
3129
sdkcmdutil "github.com/elastic/cloud-sdk-go/pkg/util/cmdutil"
@@ -42,141 +40,37 @@ var createCmd = &cobra.Command{
4240
Long: createLong,
4341
Example: createExample,
4442
RunE: func(cmd *cobra.Command, args []string) error {
45-
var file, _ = cmd.Flags().GetString("file")
46-
var track, _ = cmd.Flags().GetBool("track")
47-
var generatePayload, _ = cmd.Flags().GetBool("generate-payload")
48-
var name, _ = cmd.Flags().GetString("name")
49-
var version, _ = cmd.Flags().GetString("version")
50-
var dt, _ = cmd.Flags().GetString("deployment-template")
51-
var region = ecctl.Get().Config.Region
43+
track, _ := cmd.Flags().GetBool("track")
44+
generatePayload, _ := cmd.Flags().GetBool("generate-payload")
45+
name, _ := cmd.Flags().GetString("name")
46+
version, _ := cmd.Flags().GetString("version")
47+
region := ecctl.Get().Config.Region
5248

53-
var esZoneCount, _ = cmd.Flags().GetInt32("es-zones")
54-
var esSize, _ = cmd.Flags().GetString("es-size")
55-
var esRefID, _ = cmd.Flags().GetString("es-ref-id")
56-
var topologyElements, _ = cmd.Flags().GetStringArray("es-node-topology")
57-
var plugin, _ = cmd.Flags().GetStringSlice("plugin")
58-
59-
var kibanaZoneCount, _ = cmd.Flags().GetInt32("kibana-zones")
60-
var kibanaSize, _ = cmd.Flags().GetString("kibana-size")
61-
var kibanaRefID, _ = cmd.Flags().GetString("kibana-ref-id")
62-
63-
var apmEnable, _ = cmd.Flags().GetBool("apm")
64-
var apmZoneCount, _ = cmd.Flags().GetInt32("apm-zones")
65-
var apmSize, _ = cmd.Flags().GetString("apm-size")
66-
var apmRefID, _ = cmd.Flags().GetString("apm-ref-id")
67-
68-
var appsearchEnable, _ = cmd.Flags().GetBool("appsearch")
69-
var appsearchZoneCount, _ = cmd.Flags().GetInt32("appsearch-zones")
70-
var appsearchSize, _ = cmd.Flags().GetString("appsearch-size")
71-
var appsearchRefID, _ = cmd.Flags().GetString("appsearch-ref-id")
72-
73-
var enterpriseSearchEnable, _ = cmd.Flags().GetBool("enterprise_search")
74-
var enterpriseSearchZoneCount, _ = cmd.Flags().GetInt32("enterprise_search-zones")
75-
var enterpriseSearchSize, _ = cmd.Flags().GetString("enterprise_search-size")
76-
var enterpriseSearchRefID, _ = cmd.Flags().GetString("enterprise_search-ref-id")
77-
78-
var payload *models.DeploymentCreateRequest
79-
80-
if file != "" {
81-
err := sdkcmdutil.DecodeDefinition(cmd, "file", &payload)
82-
if err != nil {
83-
merr := multierror.NewPrefixed("failed reading the file definition")
84-
return merr.Append(err,
85-
errors.New("could not read the specified file, please make sure it exists"),
86-
)
87-
}
88-
}
89-
90-
if dt == "" {
91-
dt = setDefaultTemplate(region)
92-
}
93-
94-
apmSizeMB, err := deploymentsize.ParseGb(apmSize)
95-
if err != nil {
96-
return err
97-
}
98-
99-
appsearchSizeMB, err := deploymentsize.ParseGb(appsearchSize)
100-
if err != nil {
101-
return err
102-
}
103-
104-
esSizeMB, err := deploymentsize.ParseGb(esSize)
49+
payload, err := newCreatePayload(cmd, version, region)
10550
if err != nil {
10651
return err
10752
}
10853

109-
enterpriseSearchSizeMB, err := deploymentsize.ParseGb(enterpriseSearchSize)
110-
if err != nil {
111-
return err
112-
}
113-
114-
kibanaSizeMB, err := deploymentsize.ParseGb(kibanaSize)
115-
if err != nil {
54+
if err := deploymentapi.OverrideCreateOrUpdateRequest(payload,
55+
&deploymentapi.PayloadOverrides{
56+
Name: name,
57+
Version: version,
58+
Region: region,
59+
ElasticsearchRefID: "main-elasticsearch",
60+
OverrideRefIDs: true,
61+
},
62+
); err != nil {
11663
return err
11764
}
11865

119-
if topologyElements != nil {
120-
topologyElements, err = esTopologyParseGB(topologyElements)
121-
if err != nil {
122-
return err
123-
}
124-
}
125-
126-
if payload == nil {
127-
var err error
128-
payload, err = depresourceapi.NewPayload(depresourceapi.NewPayloadParams{
129-
API: ecctl.Get().API,
130-
Name: name,
131-
DeploymentTemplateID: dt,
132-
Version: version,
133-
Region: region,
134-
Writer: ecctl.Get().Config.ErrorDevice,
135-
Plugins: plugin,
136-
TopologyElements: topologyElements,
137-
ApmEnable: apmEnable,
138-
AppsearchEnable: appsearchEnable,
139-
EnterpriseSearchEnable: enterpriseSearchEnable,
140-
ElasticsearchInstance: depresourceapi.InstanceParams{
141-
RefID: esRefID,
142-
Size: esSizeMB,
143-
ZoneCount: esZoneCount,
144-
},
145-
KibanaInstance: depresourceapi.InstanceParams{
146-
RefID: kibanaRefID,
147-
Size: kibanaSizeMB,
148-
ZoneCount: kibanaZoneCount,
149-
},
150-
ApmInstance: depresourceapi.InstanceParams{
151-
RefID: apmRefID,
152-
Size: apmSizeMB,
153-
ZoneCount: apmZoneCount,
154-
},
155-
AppsearchInstance: depresourceapi.InstanceParams{
156-
RefID: appsearchRefID,
157-
Size: appsearchSizeMB,
158-
ZoneCount: appsearchZoneCount,
159-
},
160-
EnterpriseSearchInstance: depresourceapi.InstanceParams{
161-
RefID: enterpriseSearchRefID,
162-
Size: enterpriseSearchSizeMB,
163-
ZoneCount: enterpriseSearchZoneCount,
164-
},
165-
})
166-
if err != nil {
167-
return err
168-
}
169-
}
170-
17166
// Returns the DeploymentCreateRequest skipping the creation of the resources.
17267
if generatePayload {
17368
return ecctl.Get().Formatter.Format("", payload)
17469
}
17570

17671
reqID, _ := cmd.Flags().GetString("request-id")
17772
reqID = deploymentapi.RequestID(reqID)
178-
179-
var createParams = deploymentapi.CreateParams{
73+
createParams := deploymentapi.CreateParams{
18074
API: ecctl.Get().API,
18175
RequestID: reqID,
18276
Request: payload,
@@ -213,31 +107,6 @@ func initFlags() {
213107
createCmd.Flags().BoolP("track", "t", false, cmdutil.TrackFlagMessage)
214108
createCmd.Flags().Bool("generate-payload", false, "Returns the deployment payload without actually creating the deployment resources")
215109
createCmd.Flags().String("request-id", "", "Optional request ID - Can be found in the Stderr device when a previous deployment creation failed. For more information see the examples in the help command page")
216-
217-
createCmd.Flags().String("es-ref-id", "main-elasticsearch", "Optional RefId for the Elasticsearch deployment")
218-
createCmd.Flags().Int32("es-zones", 1, "Number of zones the Elasticsearch instances will span")
219-
createCmd.Flags().String("es-size", "4g", "Memory (RAM) in GB that each of the Elasticsearch instances will have")
220-
createCmd.Flags().StringArrayP("es-node-topology", "e", nil, "Optional Elasticsearch node topology element definition. See help for more information")
221-
createCmd.Flags().StringSlice("plugin", nil, "Additional plugins to add to the Elasticsearch deployment")
222-
223-
createCmd.Flags().String("kibana-ref-id", "main-kibana", "Optional RefId for the Kibana deployment")
224-
createCmd.Flags().Int32("kibana-zones", 1, "Number of zones the Kibana instances will span")
225-
createCmd.Flags().String("kibana-size", "1g", "Memory (RAM) in GB that each of the Kibana instances will have")
226-
227-
createCmd.Flags().Bool("apm", false, "Enables APM for the deployment")
228-
createCmd.Flags().String("apm-ref-id", "main-apm", "Optional RefId for the APM deployment")
229-
createCmd.Flags().Int32("apm-zones", 1, "Number of zones the APM instances will span")
230-
createCmd.Flags().String("apm-size", "0.5g", "Memory (RAM) in GB that each of the APM instances will have")
231-
232-
createCmd.Flags().Bool("appsearch", false, "Enables App Search for the deployment")
233-
createCmd.Flags().String("appsearch-ref-id", "main-appsearch", "Optional RefId for the App Search deployment")
234-
createCmd.Flags().Int32("appsearch-zones", 1, "Number of zones the App Search instances will span")
235-
createCmd.Flags().String("appsearch-size", "2g", "Memory (RAM) in GB that each of the App Search instances will have")
236-
237-
createCmd.Flags().Bool("enterprise_search", false, "Enables Enterprise Search for the deployment")
238-
createCmd.Flags().String("enterprise_search-ref-id", "main-enterprise_search", "Optional RefId for the Enterprise Search deployment")
239-
createCmd.Flags().Int32("enterprise_search-zones", 1, "Number of zones the Enterprise Search instances will span")
240-
createCmd.Flags().String("enterprise_search-size", "4g", "Memory (RAM) in GB that each of the Enterprise Search instances will have")
241110
}
242111

243112
func setDefaultTemplate(region string) string {
@@ -261,43 +130,33 @@ func setDefaultTemplate(region string) string {
261130
}
262131
}
263132

264-
type elasticsearchTopologyElement struct {
265-
NodeType string `json:"node_type"`
266-
Size string `json:"size"`
267-
ZoneCount int32 `json:"zone_count,omitempty"`
268-
}
269-
270-
func esTopologyParseGB(topology []string) ([]string, error) {
271-
var t = make([]string, 0, len(topology))
272-
for _, rawElement := range topology {
273-
var element elasticsearchTopologyElement
274-
if err := json.Unmarshal([]byte(rawElement), &element); err != nil {
275-
return nil, fmt.Errorf("failed unpacking raw elasticsearch node topology: %s", err)
276-
}
277-
278-
if element.Size == "" {
279-
return nil, errors.New("elasticsearch node topology: memory size cannot be empty")
280-
}
281-
282-
elementSizeMB, err := deploymentsize.ParseGb(element.Size)
283-
if err != nil {
284-
return nil, err
285-
}
286-
287-
esTopologyElement := depresourceapi.ElasticsearchTopologyElement{
288-
NodeType: element.NodeType,
289-
ZoneCount: element.ZoneCount,
290-
Size: elementSizeMB,
291-
}
292-
293-
b, err := json.Marshal(esTopologyElement)
294-
if err != nil {
295-
return nil, fmt.Errorf("failed unpacking elasticsearch node topology: %s", err)
133+
func newCreatePayload(cmd *cobra.Command, version, region string) (*models.DeploymentCreateRequest, error) {
134+
file, _ := cmd.Flags().GetString("file")
135+
dt, _ := cmd.Flags().GetString("deployment-template")
136+
var payload models.DeploymentCreateRequest
137+
if file != "" {
138+
if err := sdkcmdutil.DecodeDefinition(cmd, "file", &payload); err != nil {
139+
merr := multierror.NewPrefixed("failed reading the file definition")
140+
return nil, merr.Append(err,
141+
errors.New("could not read the specified file, please make sure it exists"),
142+
)
296143
}
297-
parsedElement := string(b)
144+
return &payload, nil
145+
}
298146

299-
t = append(t, parsedElement)
147+
if dt == "" {
148+
dt = setDefaultTemplate(region)
149+
fmt.Fprintf(cmd.ErrOrStderr(), "--deployment-template not set, using %s", dt)
150+
}
151+
tpl, err := deptemplateapi.Get(deptemplateapi.GetParams{
152+
API: ecctl.Get().API,
153+
TemplateID: dt,
154+
Region: region,
155+
StackVersion: version,
156+
})
157+
if err != nil {
158+
return nil, err
300159
}
301160

302-
return t, nil
161+
return tpl.DeploymentTemplate, nil
303162
}

cmd/deployment/create_help.go

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,51 +19,38 @@ package cmddeployment
1919

2020
const (
2121
// nolint
22-
createLong = `Creates a deployment which can be defined through flags or from a file definition.
23-
Sane default values are provided, making the command work out of the box even when no parameters are set.
24-
When version is not specified, the latest available stack version will automatically be used.
22+
createLong = `Creates a deployment from a file definition or using the defaults from the deployment template.
23+
Default values are provided by the deployment template, simplifying the getting started experience.
24+
When version is not specified, the latest available stack version will automatically be used.
2525
These are the available options:
2626
27-
* Simplified flags to set size and zone count for each instance type (Elasticsearch, Kibana, APM, Enterprise Search and App Search).
28-
* Advanced flag for different Elasticsearch node types: --es-node-topology <json obj> (shorthand: -e).
29-
Note that the flag can be specified multiple times for complex topologies.
30-
The JSON object has the following format:
31-
{
32-
"node_type": "["data", "master", "ml"]" # type string
33-
"size": "1g" # type string
34-
"zone_count": 1 # type int32
35-
}
27+
* Using the deployment template defaults with --deployment-template=<deployment template id>
28+
* Using the deployment template defaults with --deployment-template=<deployment template id> and
29+
--generate-payload to use the deployment template, modify certain fields of the definition and
30+
use the --file flag to create the deployment.
3631
* File definition: --file=<file path> (shorthand: -f). You can create a definition by using the sample JSON seen here:
3732
https://elastic.co/guide/en/cloud/current/ec-api-deployment-crud.html#ec_create_a_deployment
3833
3934
As an option "--generate-payload" can be used in order to obtain the generated payload that would be sent as a request.
4035
Save it, update or extend the topology and create a deployment using the saved payload with the "--file" flag.`
4136

4237
// nolint
43-
createExample = `## Create a deployment with the default values for Elasticsearch, a Kibana instance with a modified size,
44-
and a default APM instance. While Elasticsearch and Kibana come enabled by default, APM, Enterprise Search and App Search need to be
45-
enabled by using the "--apm", "--enterprise_search" and "--appsearch" flags. The command will exit after the API response has been returned, without
46-
waiting until the deployment resources have been created.
47-
$ ecctl deployment create --name my-deployment --zones 2 --kibana-size 2g --apm --apm-size 0.5g
38+
createExample = `## Create a deployment with the default values
39+
$ ecctl deployment create --name my-deployment --deployment-template=aws-io-optimized-v2 --region=us-east-1
4840
4941
## To make the command wait until the resources have been created use the "--track" flag, which will output
5042
the current stage on which the deployment resources are in.
51-
$ deployment create --name my-deployment --track
43+
$ ecctl deployment create --name my-deployment --deployment-template=aws-io-optimized-v2 --region=us-east-1 --track
5244
[...]
5345
Deployment [b6ecbea3d5c84124b7dca457f2892086] - [Elasticsearch][b6ecbea3d5c84124b7dca457f2892086]: finished running all the plan steps (Total plan duration: 5m11.s)
5446
Deployment [91c4d60acb804ba0a27651fac02780ec] - [Kibana][8a9d9916cd6e46a7bb0912211d76e2af]: finished running all the plan steps (Total plan duration: 4m29.58s)
5547
56-
## Additionally, a more advanced topology for Elasticsearch can be created through "--es-node-topology" or shorthand "-e".
57-
The following command will create a deployment with two 1GB Elasticsearch instances of the type "data" and
58-
one 1GB Elasticsearch instance of the type "ml".
59-
$ ecctl deployment create --name my-deployment --es-node-topology '{"size": "1g", "zone_count": 2, "node_type": "data"}' --es-node-topology '{"size": "1g", "zone_count": 1, "node_type": "ml"}'
60-
6148
## In order to use the "--deployment-template" flag, you'll need to know which deployment templates ara available to you.
6249
You'll need to run the following command to view your deployment templates:
6350
$ ecctl platform deployment-template list
6451
6552
## Use the "--generate-payload" flag to save the definition to a file for later use.
66-
$ ecctl deployment create --name my-deployment --size 1g --track --generate-payload --zones 2 > create_example.json
53+
$ ecctl deployment create --name my-deployment --version=7.11.2 --generate-payload > create_example.json
6754
6855
## Create a deployment through the file definition.
6956
$ ecctl deployment create --file create_example.json --track

0 commit comments

Comments
 (0)