Skip to content

Commit 16c6676

Browse files
authored
Support creating addons as part of 'cluster create' command (#487)
* Refactor addon args into runnerArgs * Inherit cluster create args to satisfy addons, validate args Signed-off-by: Kyle Squizzato <[email protected]>
1 parent 82f48c4 commit 16c6676

File tree

3 files changed

+79
-28
lines changed

3 files changed

+79
-28
lines changed

cli/cmd/cluster_addon_create_objectstore.go

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,7 @@ import (
1313
"github.com/spf13/cobra"
1414
)
1515

16-
type clusterAddonCreateObjectStoreArgs struct {
17-
objectStoreBucket string
18-
clusterID string
19-
waitDuration time.Duration
20-
dryRun bool
21-
outputFormat string
22-
}
23-
2416
func (r *runners) InitClusterAddonCreateObjectStore(parent *cobra.Command) *cobra.Command {
25-
args := clusterAddonCreateObjectStoreArgs{}
26-
2717
cmd := &cobra.Command{
2818
Use: "object-store CLUSTER_ID --bucket-prefix BUCKET_PREFIX",
2919
Short: "Create an object store bucket for a cluster.",
@@ -48,40 +38,40 @@ Examples:
4838
05929b24 Object Store pending {"bucket_prefix":"mybucket"}`,
4939
Args: cobra.ExactArgs(1),
5040
RunE: func(_ *cobra.Command, cmdArgs []string) error {
51-
args.clusterID = cmdArgs[0]
52-
return r.clusterAddonCreateObjectStoreCreateRun(args)
41+
r.args.clusterAddonCreateObjectStoreClusterID = cmdArgs[0]
42+
return r.clusterAddonCreateObjectStoreCreateRun()
5343
},
5444
}
5545
parent.AddCommand(cmd)
5646

57-
err := clusterAddonCreateObjectStoreFlags(cmd, &args)
47+
err := r.clusterAddonCreateObjectStoreFlags(cmd)
5848
if err != nil {
5949
panic(err)
6050
}
6151

6252
return cmd
6353
}
6454

65-
func clusterAddonCreateObjectStoreFlags(cmd *cobra.Command, args *clusterAddonCreateObjectStoreArgs) error {
66-
cmd.Flags().StringVar(&args.objectStoreBucket, "bucket-prefix", "", "A prefix for the bucket name to be created (required)")
55+
func (r *runners) clusterAddonCreateObjectStoreFlags(cmd *cobra.Command) error {
56+
cmd.Flags().StringVar(&r.args.clusterAddonCreateObjectStoreBucket, "bucket-prefix", "", "A prefix for the bucket name to be created (required)")
6757
err := cmd.MarkFlagRequired("bucket-prefix")
6858
if err != nil {
6959
return err
7060
}
71-
cmd.Flags().DurationVar(&args.waitDuration, "wait", 0, "Wait duration for add-on to be ready before exiting (leave empty to not wait)")
72-
cmd.Flags().BoolVar(&args.dryRun, "dry-run", false, "Simulate creation to verify that your inputs are valid without actually creating an add-on")
73-
cmd.Flags().StringVar(&args.outputFormat, "output", "table", "The output format to use. One of: json|table|wide (default: table)")
61+
cmd.Flags().DurationVar(&r.args.clusterAddonCreateObjectStoreDuration, "wait", 0, "Wait duration for add-on to be ready before exiting (leave empty to not wait)")
62+
cmd.Flags().BoolVar(&r.args.clusterAddonCreateObjectStoreDryRun, "dry-run", false, "Simulate creation to verify that your inputs are valid without actually creating an add-on")
63+
cmd.Flags().StringVar(&r.args.clusterAddonCreateObjectStoreOutput, "output", "table", "The output format to use. One of: json|table|wide (default: table)")
7464
return nil
7565
}
7666

77-
func (r *runners) clusterAddonCreateObjectStoreCreateRun(args clusterAddonCreateObjectStoreArgs) error {
67+
func (r *runners) clusterAddonCreateObjectStoreCreateRun() error {
7868
opts := kotsclient.CreateClusterAddonObjectStoreOpts{
79-
ClusterID: args.clusterID,
80-
Bucket: args.objectStoreBucket,
81-
DryRun: args.dryRun,
69+
ClusterID: r.args.clusterAddonCreateObjectStoreClusterID,
70+
Bucket: r.args.clusterAddonCreateObjectStoreBucket,
71+
DryRun: r.args.clusterAddonCreateObjectStoreDryRun,
8272
}
8373

84-
addon, err := r.createAndWaitForClusterAddonCreateObjectStore(opts, args.waitDuration)
74+
addon, err := r.createAndWaitForClusterAddonCreateObjectStore(opts, r.args.clusterAddonCreateObjectStoreDuration)
8575
if err != nil {
8676
if errors.Cause(err) == ErrWaitDurationExceeded {
8777
defer func() {
@@ -93,11 +83,11 @@ func (r *runners) clusterAddonCreateObjectStoreCreateRun(args clusterAddonCreate
9383
}
9484

9585
if opts.DryRun {
96-
_, err := fmt.Fprintln(r.w, "Dry run succeeded.")
86+
_, err := fmt.Fprintln(r.w, "Dry run succeeded for addon object-store creation.")
9787
return err
9888
}
9989

100-
return print.Addon(args.outputFormat, r.w, addon)
90+
return print.Addon(r.args.clusterAddonCreateObjectStoreOutput, r.w, addon)
10191
}
10292

10393
func (r *runners) createAndWaitForClusterAddonCreateObjectStore(opts kotsclient.CreateClusterAddonObjectStoreOpts, waitDuration time.Duration) (*types.ClusterAddon, error) {

cli/cmd/cluster_create.go

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ Use the '--dry-run' flag to simulate the creation process and get an estimated c
4646
--ttl 24h
4747
4848
# Create a cluster with custom tags
49-
replicated cluster create --distribution eks --version 1.21 --nodes 3 --tag env=test --tag project=demo --ttl 24h`,
49+
replicated cluster create --distribution eks --version 1.21 --nodes 3 --tag env=test --tag project=demo --ttl 24h
50+
51+
# Create a cluster with addons
52+
replicated cluster create --distribution eks --version 1.21 --nodes 3 --addon object-store --ttl 24h`,
5053
SilenceUsage: true,
5154
RunE: r.createCluster,
5255
Args: cobra.NoArgs,
@@ -68,6 +71,9 @@ Use the '--dry-run' flag to simulate the creation process and get an estimated c
6871

6972
cmd.Flags().StringArrayVar(&r.args.createClusterTags, "tag", []string{}, "Tag to apply to the cluster (key=value format, can be specified multiple times)")
7073

74+
cmd.Flags().StringArrayVar(&r.args.createClusterAddons, "addon", []string{}, "Addons to install on the cluster (can be specified multiple times)")
75+
cmd.Flags().StringVar(&r.args.clusterAddonCreateObjectStoreBucket, "bucket-prefix", "", "A prefix for the bucket name to be created (required by '--addon object-store')")
76+
7177
cmd.Flags().BoolVar(&r.args.createClusterDryRun, "dry-run", false, "Dry run")
7278

7379
cmd.Flags().StringVar(&r.outputFormat, "output", "table", "The output format to use. One of: json|table|wide (default: table)")
@@ -77,7 +83,24 @@ Use the '--dry-run' flag to simulate the creation process and get an estimated c
7783
return cmd
7884
}
7985

80-
func (r *runners) createCluster(_ *cobra.Command, args []string) error {
86+
func (r *runners) validateAddonArgs(cmd *cobra.Command) error {
87+
for _, addon := range r.args.createClusterAddons {
88+
if addon == "object-store" {
89+
if r.args.clusterAddonCreateObjectStoreBucket == "" {
90+
if err := cmd.Help(); err != nil {
91+
return err
92+
}
93+
return errors.New("bucket-prefix is required for object-store addon")
94+
}
95+
} else {
96+
return errors.Errorf("unknown addon: %s", addon)
97+
}
98+
}
99+
100+
return nil
101+
}
102+
103+
func (r *runners) createCluster(cmd *cobra.Command, args []string) error {
81104
if r.args.createClusterName == "" {
82105
r.args.createClusterName = generateClusterName()
83106
}
@@ -92,6 +115,10 @@ func (r *runners) createCluster(_ *cobra.Command, args []string) error {
92115
return errors.Wrap(err, "parse node groups")
93116
}
94117

118+
if err := r.validateAddonArgs(cmd); err != nil {
119+
return errors.Wrap(err, "validate addon args")
120+
}
121+
95122
opts := kotsclient.CreateClusterOpts{
96123
Name: r.args.createClusterName,
97124
KubernetesDistribution: r.args.createClusterKubernetesDistribution,
@@ -137,19 +164,46 @@ func (r *runners) createCluster(_ *cobra.Command, args []string) error {
137164
}
138165
}
139166

167+
if r.args.createClusterAddons != nil {
168+
if err := r.createAndWaitForAddons(cl.ID); err != nil {
169+
return err
170+
}
171+
}
172+
140173
if opts.DryRun {
141174
estimatedCostMessage := fmt.Sprintf("Estimated cost: %s (if run to TTL of %s)", print.CreditsToDollarsDisplay(cl.EstimatedCost), cl.TTL)
142175
_, err := fmt.Fprintln(r.w, estimatedCostMessage)
143176
if err != nil {
144177
return err
145178
}
146-
_, err = fmt.Fprintln(r.w, "Dry run succeeded.")
179+
_, err = fmt.Fprintln(r.w, "Dry run succeeded for cluster create.")
147180
return err
148181
}
149182

150183
return print.Cluster(r.outputFormat, r.w, cl)
151184
}
152185

186+
func (r *runners) createAndWaitForAddons(clusterID string) error {
187+
for _, addon := range r.args.createClusterAddons {
188+
if addon == "object-store" {
189+
// ClusterID, DryRun, Duration and Output are common to all
190+
// addons and cluster create, so they are inherited from the
191+
// cluster create command.
192+
r.args.clusterAddonCreateObjectStoreClusterID = clusterID
193+
r.args.clusterAddonCreateObjectStoreDryRun = r.args.createClusterDryRun
194+
r.args.clusterAddonCreateObjectStoreDuration = r.args.createClusterWaitDuration
195+
r.args.clusterAddonCreateObjectStoreOutput = r.outputFormat
196+
197+
err := r.clusterAddonCreateObjectStoreCreateRun()
198+
if err != nil {
199+
return err
200+
}
201+
}
202+
}
203+
204+
return nil
205+
}
206+
153207
func (r *runners) createAndWaitForCluster(opts kotsclient.CreateClusterOpts) (*types.Cluster, error) {
154208
cl, ve, err := r.kotsAPI.CreateCluster(opts)
155209
if errors.Cause(err) == platformclient.ErrForbidden {

cli/cmd/runner.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ type runnerArgs struct {
129129
createClusterInstanceType string
130130
createClusterNodeGroups []string
131131
createClusterTags []string
132+
createClusterAddons []string
132133

133134
upgradeClusterKubernetesVersion string
134135
upgradeClusterDryRun bool
@@ -247,4 +248,10 @@ type runnerArgs struct {
247248
lsNetworkStartTime string
248249
lsNetworkEndTime string
249250
lsNetworkWatch bool
251+
252+
clusterAddonCreateObjectStoreBucket string
253+
clusterAddonCreateObjectStoreClusterID string
254+
clusterAddonCreateObjectStoreDuration time.Duration
255+
clusterAddonCreateObjectStoreDryRun bool
256+
clusterAddonCreateObjectStoreOutput string
250257
}

0 commit comments

Comments
 (0)