Skip to content

Commit 37c2389

Browse files
committed
feat: --password flag on droplet create and campaign deploy
1 parent 612439f commit 37c2389

2 files changed

Lines changed: 36 additions & 0 deletions

File tree

cmd/campaign.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ var (
115115
campOperatorIP string
116116
campVPCAuto bool
117117
campTemplateVar []string
118+
campPassword string
118119
)
119120

120121
func init() {
@@ -136,6 +137,7 @@ func init() {
136137
campaignDeployCmd.Flags().StringVar(&campOperatorIP, "operator-ip", "", "Operator IP used by firewall presets to restrict SSH (required when using --role with a preset)")
137138
campaignDeployCmd.Flags().BoolVar(&campVPCAuto, "vpc-auto", false, "Automatically create a VPC in the campaign region and attach all Droplets")
138139
campaignDeployCmd.Flags().StringArrayVar(&campTemplateVar, "template-var", nil, "Template variable: KEY=VALUE (repeatable, applies to all --template or role template=)")
140+
campaignDeployCmd.Flags().StringVar(&campPassword, "password", "", "Set root password via cloud-init on all Droplets (injected into any template or user-data)")
139141
campaignDeployCmd.MarkFlagRequired("name") //nolint:errcheck
140142

141143
// status & destroy
@@ -269,6 +271,9 @@ func runCampaignDeploySimple() error {
269271
if err != nil {
270272
return err
271273
}
274+
if campPassword != "" {
275+
ud = injectPassword(ud, campPassword)
276+
}
272277

273278
dropSvc, fwSvc, ripSvc, err := newCampaignClients()
274279
if err != nil {
@@ -499,6 +504,9 @@ func runCampaignDeployRoles() error {
499504
return err
500505
}
501506
}
507+
if campPassword != "" {
508+
ud = injectPassword(ud, campPassword)
509+
}
502510

503511
step(fmt.Sprintf("[%s] Creating %d Droplet(s) image=%s size=%s",
504512
color.CyanString(role.Name), role.Count, image, size))

cmd/droplet.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ var (
190190
sshPort int
191191
createTemplate string
192192
createTemplateVar []string
193+
createPassword string
193194
)
194195

195196
func init() {
@@ -209,6 +210,7 @@ func init() {
209210
dropletCreateCmd.Flags().BoolVar(&createBackups, "backups", false, "Enable automatic backups")
210211
dropletCreateCmd.Flags().BoolVarP(&createWait, "wait", "w", false, "Wait until the Droplet is active and print its IP")
211212
dropletCreateCmd.Flags().IntVarP(&createCount, "count", "c", 1, "Number of Droplets to provision in parallel (names become name-01, name-02, ...)")
213+
dropletCreateCmd.Flags().StringVar(&createPassword, "password", "", "Set root password via cloud-init (injected into any --template or --user-data-file)")
212214
dropletCreateCmd.MarkFlagRequired("name") //nolint:errcheck
213215

214216
// delete flags
@@ -457,6 +459,29 @@ func runDropletGet(cmd *cobra.Command, args []string) error {
457459
return nil
458460
}
459461

462+
// injectPassword inserts root password setup lines into a cloud-init script.
463+
// If script is empty a minimal shebang is generated. The block is always
464+
// inserted right after the shebang line so it runs before any other logic.
465+
func injectPassword(script, password string) string {
466+
block := fmt.Sprintf(
467+
"echo %q | chpasswd\n"+
468+
"sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config\n"+
469+
"sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config\n"+
470+
"systemctl restart ssh\n",
471+
"root:"+password,
472+
)
473+
if script == "" {
474+
return "#!/bin/bash\n" + block
475+
}
476+
if strings.HasPrefix(script, "#!") {
477+
idx := strings.Index(script, "\n")
478+
if idx >= 0 {
479+
return script[:idx+1] + block + script[idx+1:]
480+
}
481+
}
482+
return block + script
483+
}
484+
460485
func runDropletCreate(cmd *cobra.Command, args []string) error {
461486
if createCount < 1 {
462487
return fmt.Errorf("--count must be >= 1")
@@ -466,6 +491,9 @@ func runDropletCreate(cmd *cobra.Command, args []string) error {
466491
if err != nil {
467492
return err
468493
}
494+
if createPassword != "" {
495+
ud = injectPassword(ud, createPassword)
496+
}
469497

470498
svc, err := newDropletService()
471499
if err != nil {

0 commit comments

Comments
 (0)