volume

package
v1.56.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2025 License: MIT Imports: 19 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var AttachCmd = base.Cmd{
	BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
		cmd := &cobra.Command{
			Use:                   "attach [--automount] --server <server> <volume>",
			Short:                 "Attach a Volume to a Server",
			ValidArgsFunction:     cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Volume().Names)),
			TraverseChildren:      true,
			DisableFlagsInUseLine: true,
		}
		cmd.Flags().String("server", "", "Server (ID or name) (required)")
		_ = cmd.RegisterFlagCompletionFunc("server", cmpl.SuggestCandidatesF(client.Server().Names))
		_ = cmd.MarkFlagRequired("server")
		cmd.Flags().Bool("automount", false, "Automount Volume after attach (true, false)")

		return cmd
	},
	Run: func(s state.State, cmd *cobra.Command, args []string) error {
		volume, _, err := s.Client().Volume().Get(s, args[0])
		if err != nil {
			return err
		}
		if volume == nil {
			return fmt.Errorf("volume not found: %s", args[0])
		}

		serverIDOrName, _ := cmd.Flags().GetString("server")
		server, _, err := s.Client().Server().Get(s, serverIDOrName)
		if err != nil {
			return err
		}
		if server == nil {
			return fmt.Errorf("Server not found: %s", serverIDOrName)
		}
		automount, _ := cmd.Flags().GetBool("automount")
		action, _, err := s.Client().Volume().AttachWithOpts(s, volume, hcloud.VolumeAttachOpts{
			Server:    server,
			Automount: &automount,
		})

		if err != nil {
			return err
		}

		if err := s.WaitForActions(s, cmd, action); err != nil {
			return err
		}

		cmd.Printf("Volume %d attached to Server %s\n", volume.ID, server.Name)
		return nil
	},
}
View Source
var CreateCmd = base.CreateCmd[*hcloud.Volume]{
	BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
		cmd := &cobra.Command{
			Use:                   "create [options] --name <name> --size <size>",
			Short:                 "Create a Volume",
			TraverseChildren:      true,
			DisableFlagsInUseLine: true,
		}
		cmd.Flags().String("name", "", "Volume name (required)")
		_ = cmd.MarkFlagRequired("name")

		cmd.Flags().String("server", "", "Server (ID or name)")
		_ = cmd.RegisterFlagCompletionFunc("server", cmpl.SuggestCandidatesF(client.Server().Names))

		cmd.Flags().String("location", "", "Location (ID or name)")
		_ = cmd.RegisterFlagCompletionFunc("location", cmpl.SuggestCandidatesF(client.Location().Names))

		cmd.Flags().Int("size", 0, "Size (GB) (required)")
		_ = cmd.MarkFlagRequired("size")

		cmd.Flags().Bool("automount", false, "Automount Volume after attach (Server must be provided) (true, false)")

		cmd.Flags().String("format", "", "Format Volume after creation (ext4 or xfs)")
		_ = cmd.RegisterFlagCompletionFunc("format", cmpl.SuggestCandidates("ext4", "xfs"))

		cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)")

		cmd.Flags().StringSlice("enable-protection", []string{}, "Enable protection (delete) (default: none)")
		_ = cmd.RegisterFlagCompletionFunc("enable-protection", cmpl.SuggestCandidates("delete"))

		return cmd
	},
	Run: func(s state.State, cmd *cobra.Command, _ []string) (*hcloud.Volume, any, error) {
		name, _ := cmd.Flags().GetString("name")
		serverIDOrName, _ := cmd.Flags().GetString("server")
		size, _ := cmd.Flags().GetInt("size")
		location, _ := cmd.Flags().GetString("location")
		automount, _ := cmd.Flags().GetBool("automount")
		format, _ := cmd.Flags().GetString("format")
		labels, _ := cmd.Flags().GetStringToString("label")
		protection, _ := cmd.Flags().GetStringSlice("enable-protection")

		protectionOpts, err := getChangeProtectionOpts(true, protection)
		if err != nil {
			return nil, nil, err
		}

		createOpts := hcloud.VolumeCreateOpts{
			Name:   name,
			Size:   size,
			Labels: labels,
		}

		if location != "" {
			id, err := strconv.ParseInt(location, 10, 64)
			if err == nil {
				createOpts.Location = &hcloud.Location{ID: id}
			} else {
				createOpts.Location = &hcloud.Location{Name: location}
			}
		}
		if serverIDOrName != "" {
			server, _, err := s.Client().Server().Get(s, serverIDOrName)
			if err != nil {
				return nil, nil, err
			}
			if server == nil {
				return nil, nil, fmt.Errorf("Server not found: %s", serverIDOrName)
			}
			createOpts.Server = server
		}
		if automount {
			createOpts.Automount = &automount
		}
		if format != "" {
			createOpts.Format = &format
		}

		result, _, err := s.Client().Volume().Create(s, createOpts)
		if err != nil {
			return nil, nil, err
		}

		if err := s.WaitForActions(s, cmd, actionutil.AppendNext(result.Action, result.NextActions)...); err != nil {
			return nil, nil, err
		}
		cmd.Printf("Volume %d created\n", result.Volume.ID)

		if err := changeProtection(s, cmd, result.Volume, true, protectionOpts); err != nil {
			return nil, nil, err
		}

		volume, _, err := s.Client().Volume().GetByID(s, result.Volume.ID)
		if err != nil {
			return nil, nil, err
		}
		if volume == nil {
			return nil, nil, fmt.Errorf("Volume not found: %d", result.Volume.ID)
		}

		return volume, util.Wrap("volume", hcloud.SchemaFromVolume(volume)), nil
	},
}
View Source
var DeleteCmd = base.DeleteCmd{
	ResourceNameSingular: "Volume",
	ResourceNamePlural:   "Volumes",
	ShortDescription:     "Delete a Volume",
	NameSuggestions:      func(c hcapi2.Client) func() []string { return c.Volume().Names },
	Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) {
		return s.Client().Volume().Get(s, idOrName)
	},
	Delete: func(s state.State, _ *cobra.Command, resource interface{}) (*hcloud.Action, error) {
		volume := resource.(*hcloud.Volume)
		_, err := s.Client().Volume().Delete(s, volume)
		return nil, err
	},
}
View Source
var DescribeCmd = base.DescribeCmd[*hcloud.Volume]{
	ResourceNameSingular: "Volume",
	ShortDescription:     "Describe a Volume",
	NameSuggestions:      func(c hcapi2.Client) func() []string { return c.Volume().Names },
	Fetch: func(s state.State, _ *cobra.Command, idOrName string) (*hcloud.Volume, any, error) {
		v, _, err := s.Client().Volume().Get(s, idOrName)
		if err != nil {
			return nil, nil, err
		}
		return v, hcloud.SchemaFromVolume(v), nil
	},
	PrintText: func(s state.State, _ *cobra.Command, out io.Writer, volume *hcloud.Volume) error {

		fmt.Fprintf(out, "ID:\t%d\n", volume.ID)
		fmt.Fprintf(out, "Name:\t%s\n", volume.Name)
		fmt.Fprintf(out, "Created:\t%s (%s)\n", util.Datetime(volume.Created), humanize.Time(volume.Created))
		fmt.Fprintf(out, "Size:\t%s\n", humanize.Bytes(uint64(volume.Size)*humanize.GByte))
		fmt.Fprintf(out, "Linux Device:\t%s\n", volume.LinuxDevice)

		fmt.Fprintln(out)
		fmt.Fprintf(out, "Location:\n")
		fmt.Fprintf(out, "%s", util.PrefixLines(location.DescribeLocation(volume.Location), "  "))

		fmt.Fprintln(out)
		fmt.Fprintf(out, "Server:\n")
		if volume.Server != nil {
			fmt.Fprintf(out, "  ID:\t%d\n", volume.Server.ID)
			fmt.Fprintf(out, "  Name:\t%s\n", s.Client().Server().ServerName(volume.Server.ID))
		} else {
			fmt.Fprintf(out, "  Not attached\n")
		}

		fmt.Fprintln(out)
		fmt.Fprintf(out, "Protection:\n")
		fmt.Fprintf(out, "  Delete:\t%s\n", util.YesNo(volume.Protection.Delete))

		fmt.Fprintln(out)
		util.DescribeLabels(out, volume.Labels, "")

		return nil
	},
}
View Source
var DetachCmd = base.Cmd{
	BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
		return &cobra.Command{
			Use:                   "detach <volume>",
			Short:                 "Detach a Volume",
			ValidArgsFunction:     cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Volume().Names)),
			TraverseChildren:      true,
			DisableFlagsInUseLine: true,
		}
	},
	Run: func(s state.State, cmd *cobra.Command, args []string) error {
		volume, _, err := s.Client().Volume().Get(s, args[0])
		if err != nil {
			return err
		}
		if volume == nil {
			return fmt.Errorf("Volume not found: %s", args[0])
		}

		action, _, err := s.Client().Volume().Detach(s, volume)
		if err != nil {
			return err
		}

		if err := s.WaitForActions(s, cmd, action); err != nil {
			return err
		}

		cmd.Printf("Volume %d detached\n", volume.ID)
		return nil
	},
}
View Source
var DisableProtectionCmd = base.Cmd{
	BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
		return &cobra.Command{
			Use:   "disable-protection <volume> delete",
			Args:  util.ValidateLenient,
			Short: "Disable resource protection for a volume",
			ValidArgsFunction: cmpl.SuggestArgs(
				cmpl.SuggestCandidatesF(client.Volume().Names),
				cmpl.SuggestCandidates("delete"),
			),
			TraverseChildren:      true,
			DisableFlagsInUseLine: true,
		}
	},
	Run: func(s state.State, cmd *cobra.Command, args []string) error {
		volume, _, err := s.Client().Volume().Get(s, args[0])
		if err != nil {
			return err
		}
		if volume == nil {
			return fmt.Errorf("volume not found: %s", args[0])
		}

		opts, err := getChangeProtectionOpts(false, args[1:])
		if err != nil {
			return err
		}

		return changeProtection(s, cmd, volume, false, opts)
	},
}
View Source
var EnableProtectionCmd = base.Cmd{
	BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
		return &cobra.Command{
			Use:   "enable-protection <volume> delete",
			Args:  util.ValidateLenient,
			Short: "Enable resource protection for a volume",
			ValidArgsFunction: cmpl.SuggestArgs(
				cmpl.SuggestCandidatesF(client.Volume().Names),
				cmpl.SuggestCandidates("delete"),
			),
			TraverseChildren:      true,
			DisableFlagsInUseLine: true,
		}
	},
	Run: func(s state.State, cmd *cobra.Command, args []string) error {
		volume, _, err := s.Client().Volume().Get(s, args[0])
		if err != nil {
			return err
		}
		if volume == nil {
			return fmt.Errorf("volume not found: %s", args[0])
		}

		opts, err := getChangeProtectionOpts(true, args[1:])
		if err != nil {
			return err
		}

		return changeProtection(s, cmd, volume, true, opts)
	},
}
View Source
var LabelCmds = base.LabelCmds[*hcloud.Volume]{
	ResourceNameSingular:   "Volume",
	ShortDescriptionAdd:    "Add a label to a Volume",
	ShortDescriptionRemove: "Remove a label from a Volume",
	NameSuggestions:        func(c hcapi2.Client) func() []string { return c.Volume().Names },
	LabelKeySuggestions:    func(c hcapi2.Client) func(idOrName string) []string { return c.Volume().LabelKeys },
	Fetch: func(s state.State, idOrName string) (*hcloud.Volume, error) {
		volume, _, err := s.Client().Volume().Get(s, idOrName)
		if err != nil {
			return nil, err
		}
		if volume == nil {
			return nil, fmt.Errorf("Volume not found: %s", idOrName)
		}
		return volume, nil
	},
	SetLabels: func(s state.State, volume *hcloud.Volume, labels map[string]string) error {
		opts := hcloud.VolumeUpdateOpts{
			Labels: labels,
		}
		_, _, err := s.Client().Volume().Update(s, volume, opts)
		return err
	},
	GetLabels: func(volume *hcloud.Volume) map[string]string {
		return volume.Labels
	},
	GetIDOrName: func(volume *hcloud.Volume) string {
		return strconv.FormatInt(volume.ID, 10)
	},
}
View Source
var ListCmd = &base.ListCmd[*hcloud.Volume, schema.Volume]{
	ResourceNamePlural: "Volumes",
	JSONKeyGetByName:   "volumes",
	DefaultColumns:     []string{"id", "name", "size", "server", "location", "age"},
	SortOption:         config.OptionSortVolume,

	Fetch: func(s state.State, _ *pflag.FlagSet, listOpts hcloud.ListOpts, sorts []string) ([]*hcloud.Volume, error) {
		opts := hcloud.VolumeListOpts{ListOpts: listOpts}
		if len(sorts) > 0 {
			opts.Sort = sorts
		}
		return s.Client().Volume().AllWithOpts(s, opts)
	},

	OutputTable: func(t *output.Table[*hcloud.Volume], client hcapi2.Client) {
		t.
			AddAllowedFields(&hcloud.Volume{}).
			AddFieldFn("server", func(volume *hcloud.Volume) string {
				var server string
				if volume.Server != nil {
					return client.Server().ServerName(volume.Server.ID)
				}
				return util.NA(server)
			}).
			AddFieldFn("size", func(volume *hcloud.Volume) string {
				return humanize.Bytes(uint64(volume.Size) * humanize.GByte)
			}).
			AddFieldFn("location", func(volume *hcloud.Volume) string {
				return volume.Location.Name
			}).
			AddFieldFn("protection", func(volume *hcloud.Volume) string {
				var protection []string
				if volume.Protection.Delete {
					protection = append(protection, "delete")
				}
				return strings.Join(protection, ", ")
			}).
			AddFieldFn("labels", func(volume *hcloud.Volume) string {
				return util.LabelsToString(volume.Labels)
			}).
			AddFieldFn("created", func(volume *hcloud.Volume) string {
				return util.Datetime(volume.Created)
			}).
			AddFieldFn("age", func(volume *hcloud.Volume) string {
				return util.Age(volume.Created, time.Now())
			})
	},

	Schema: hcloud.SchemaFromVolume,
}
View Source
var ResizeCmd = base.Cmd{
	BaseCobraCommand: func(client hcapi2.Client) *cobra.Command {
		cmd := &cobra.Command{
			Use:                   "resize --size <size> <volume>",
			Short:                 "Resize a volume",
			ValidArgsFunction:     cmpl.SuggestArgs(cmpl.SuggestCandidatesF(client.Volume().Names)),
			TraverseChildren:      true,
			DisableFlagsInUseLine: true,
		}
		cmd.Flags().Int("size", 0, "New size (GB) of the Volume (required)")
		_ = cmd.MarkFlagRequired("size")
		return cmd
	},
	Run: func(s state.State, cmd *cobra.Command, args []string) error {
		volume, _, err := s.Client().Volume().Get(s, args[0])
		if err != nil {
			return err
		}
		if volume == nil {
			return fmt.Errorf("volume not found: %s", args[0])
		}

		size, _ := cmd.Flags().GetInt("size")
		action, _, err := s.Client().Volume().Resize(s, volume, size)
		if err != nil {
			return err
		}

		if err := s.WaitForActions(s, cmd, action); err != nil {
			return err
		}

		cmd.Printf("Volume %d resized\n", volume.ID)
		cmd.Printf("You might need to adjust the filesystem size on the Server too\n")
		return nil
	},
}
View Source
var UpdateCmd = base.UpdateCmd{
	ResourceNameSingular: "Volume",
	ShortDescription:     "Update a Volume",
	NameSuggestions:      func(c hcapi2.Client) func() []string { return c.Volume().Names },
	Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) {
		return s.Client().Volume().Get(s, idOrName)
	},
	DefineFlags: func(cmd *cobra.Command) {
		cmd.Flags().String("name", "", "Volume name")
	},
	Update: func(s state.State, _ *cobra.Command, resource interface{}, flags map[string]pflag.Value) error {
		floatingIP := resource.(*hcloud.Volume)
		updOpts := hcloud.VolumeUpdateOpts{
			Name: flags["name"].String(),
		}
		_, _, err := s.Client().Volume().Update(s, floatingIP, updOpts)
		if err != nil {
			return err
		}
		return nil
	},
}

Functions

func NewCommand

func NewCommand(s state.State) *cobra.Command

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL