Skip to content

Commit eb81121

Browse files
authored
feat(server): allow specifying user-data for rebuild (#1319)
See https://docs.hetzner.cloud/changelog#2026-01-16-server-rebuild-with-user-data
1 parent 7c64c0f commit eb81121

3 files changed

Lines changed: 41 additions & 25 deletions

File tree

docs/reference/manual/hcloud_server_rebuild.md

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/cmd/server/create.go

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,23 @@ func detectContentType(data string) string {
206206
}
207207

208208
func buildUserData(files []string) (string, error) {
209+
if len(files) == 0 {
210+
return "", nil
211+
}
212+
213+
var (
214+
data []byte
215+
err error
216+
)
217+
if len(files) == 1 {
218+
if file := files[0]; file == "-" {
219+
data, err = io.ReadAll(os.Stdin)
220+
} else {
221+
data, err = os.ReadFile(file)
222+
}
223+
return string(data), err
224+
}
225+
209226
var (
210227
buf = new(bytes.Buffer)
211228
mp = multipart.NewWriter(buf)
@@ -215,10 +232,6 @@ func buildUserData(files []string) (string, error) {
215232
fmt.Fprint(buf, "Content-Type: multipart/mixed; boundary="+mp.Boundary()+"\r\n\r\n")
216233

217234
for _, file := range files {
218-
var (
219-
data []byte
220-
err error
221-
)
222235
if file == "-" {
223236
data, err = io.ReadAll(os.Stdin)
224237
} else {
@@ -352,22 +365,10 @@ func createOptsFromFlags(
352365
publicNetConfiguration.IPv6 = primaryIPv6
353366
}
354367
createOpts.PublicNet = publicNetConfiguration
355-
if len(userDataFiles) == 1 {
356-
var data []byte
357-
if userDataFiles[0] == "-" {
358-
data, err = io.ReadAll(os.Stdin)
359-
} else {
360-
data, err = os.ReadFile(userDataFiles[0])
361-
}
362-
if err != nil {
363-
return
364-
}
365-
createOpts.UserData = string(data)
366-
} else if len(userDataFiles) > 1 {
367-
createOpts.UserData, err = buildUserData(userDataFiles)
368-
if err != nil {
369-
return
370-
}
368+
369+
createOpts.UserData, err = buildUserData(userDataFiles)
370+
if err != nil {
371+
return
371372
}
372373

373374
if !flags.Changed("ssh-key") && config.OptionDefaultSSHKeys.Changed(s.Config()) {

internal/cmd/server/rebuild.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
var RebuildCmd = base.Cmd{
1717
BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
1818
cmd := &cobra.Command{
19-
Use: "rebuild [--allow-deprecated-image] --image <image> <server>",
19+
Use: "rebuild [options] --image <image> <server>",
2020
Short: "Rebuild a server",
2121
ValidArgsFunction: cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Server().Names)),
2222
TraverseChildren: true,
@@ -26,8 +26,11 @@ var RebuildCmd = base.Cmd{
2626
cmd.Flags().String("image", "", "ID or name of Image to rebuild from (required)")
2727
_ = cmd.RegisterFlagCompletionFunc("image", cmpl.SuggestCandidatesF(client.Image().Names))
2828
_ = cmd.MarkFlagRequired("image")
29+
2930
cmd.Flags().Bool("allow-deprecated-image", false, "Enable the use of deprecated images (default: false) (true, false)")
3031

32+
cmd.Flags().StringArray("user-data-from-file", []string{}, "Read user data from specified file (use - to read from stdin)")
33+
3134
return cmd
3235
},
3336
Run: func(s state.State, cmd *cobra.Command, args []string) error {
@@ -41,6 +44,8 @@ var RebuildCmd = base.Cmd{
4144
}
4245

4346
imageIDOrName, _ := cmd.Flags().GetString("image")
47+
userDataFiles, _ := cmd.Flags().GetStringArray("user-data-from-file")
48+
4449
// Select correct image based on Server Type architecture
4550
image, _, err := s.Client().Image().GetForArchitecture(s, imageIDOrName, server.ServerType.Architecture)
4651
if err != nil {
@@ -63,6 +68,15 @@ var RebuildCmd = base.Cmd{
6368
opts := hcloud.ServerRebuildOpts{
6469
Image: image,
6570
}
71+
72+
if len(userDataFiles) > 0 {
73+
userData, err := buildUserData(userDataFiles)
74+
if err != nil {
75+
return err
76+
}
77+
opts.UserData = &userData
78+
}
79+
6680
result, _, err := s.Client().Server().RebuildWithResult(s, server, opts)
6781
if err != nil {
6882
return err

0 commit comments

Comments
 (0)