diff --git a/cmd/upload.go b/cmd/upload.go index abc15c7..0c06177 100644 --- a/cmd/upload.go +++ b/cmd/upload.go @@ -17,6 +17,7 @@ const ( uploadFlagImagePath = "image-path" uploadFlagCompression = "compression" uploadFlagArchitecture = "architecture" + uploadFlagServerType = "server-type" uploadFlagDescription = "description" uploadFlagLabels = "labels" ) @@ -43,12 +44,12 @@ This does cost a bit of money for the server.`, imagePathString, _ := cmd.Flags().GetString(uploadFlagImagePath) imageCompression, _ := cmd.Flags().GetString(uploadFlagCompression) architecture, _ := cmd.Flags().GetString(uploadFlagArchitecture) + serverType, _ := cmd.Flags().GetString(uploadFlagServerType) description, _ := cmd.Flags().GetString(uploadFlagDescription) labels, _ := cmd.Flags().GetStringToString(uploadFlagLabels) options := hcloudimages.UploadOptions{ ImageCompression: hcloudimages.Compression(imageCompression), - Architecture: hcloud.Architecture(architecture), Description: hcloud.Ptr(description), Labels: labels, } @@ -69,6 +70,12 @@ This does cost a bit of money for the server.`, options.ImageReader = imageFile } + if architecture != "" { + options.Architecture = hcloud.Architecture(architecture) + } else if serverType != "" { + options.ServerType = &hcloud.ServerType{Name: serverType} + } + image, err := client.Upload(ctx, options) if err != nil { return fmt.Errorf("failed to upload the image: %w", err) @@ -99,7 +106,12 @@ func init() { uploadFlagArchitecture, cobra.FixedCompletions([]string{string(hcloud.ArchitectureX86), string(hcloud.ArchitectureARM)}, cobra.ShellCompDirectiveNoFileComp), ) - _ = uploadCmd.MarkFlagRequired(uploadFlagArchitecture) + + uploadCmd.Flags().String(uploadFlagServerType, "", "Explicitly use this server type to generate the image. Mutually exclusive with --architecture.") + + // Only one of them needs to be set + uploadCmd.MarkFlagsOneRequired(uploadFlagArchitecture, uploadFlagServerType) + uploadCmd.MarkFlagsMutuallyExclusive(uploadFlagArchitecture, uploadFlagServerType) uploadCmd.Flags().String(uploadFlagDescription, "", "Description for the resulting image") diff --git a/hcloudimages/client.go b/hcloudimages/client.go index abeb24e..d42bbc8 100644 --- a/hcloudimages/client.go +++ b/hcloudimages/client.go @@ -65,8 +65,17 @@ type UploadOptions struct { // used with [hcloud.ArchitectureX86] or [hcloud.ArchitectureARM] servers. // // Internally this decides what server type is used for the temporary server. + // + // Optional if [UploadOptions.ServerType] is set. Architecture hcloud.Architecture + // ServerType can be optionally set to override the default server type for the architecture. + // Situations where this makes sense: + // + // - Your image is larger than the root disk of the default server types. + // - The default server type is no longer available, or not temporarily out of stock. + ServerType *hcloud.ServerType + // Description is an optional description that the resulting image (snapshot) will have. There is no way to // select images by its description, you should use Labels if you need to identify your image later. Description *string @@ -159,9 +168,15 @@ func (s *Client) Upload(ctx context.Context, options UploadOptions) (*hcloud.Ima // 2. Create Server logger.InfoContext(ctx, "# Step 2: Creating Server") - serverType, ok := serverTypePerArchitecture[options.Architecture] - if !ok { - return nil, fmt.Errorf("unknown architecture %q, valid options: %q, %q", options.Architecture, hcloud.ArchitectureX86, hcloud.ArchitectureARM) + var serverType *hcloud.ServerType + if options.ServerType != nil { + serverType = options.ServerType + } else { + var ok bool + serverType, ok = serverTypePerArchitecture[options.Architecture] + if !ok { + return nil, fmt.Errorf("unknown architecture %q, valid options: %q, %q", options.Architecture, hcloud.ArchitectureX86, hcloud.ArchitectureARM) + } } logger.DebugContext(ctx, "creating server with config",