volume

package
v1.48.0 Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2024 License: MIT Imports: 17 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")

		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{
	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)")

		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) (any, 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
		}

		return result.Volume, util.Wrap("volume", hcloud.SchemaFromVolume(result.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{
	ResourceNameSingular: "volume",
	ShortDescription:     "Describe an Volume",
	JSONKeyGetByID:       "volume",
	JSONKeyGetByName:     "volumes",
	NameSuggestions:      func(c hcapi2.Client) func() []string { return c.Volume().Names },
	Fetch: func(s state.State, _ *cobra.Command, idOrName string) (interface{}, interface{}, 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, cmd *cobra.Command, resource interface{}) error {
		volume := resource.(*hcloud.Volume)

		cmd.Printf("ID:\t\t%d\n", volume.ID)
		cmd.Printf("Name:\t\t%s\n", volume.Name)
		cmd.Printf("Created:\t%s (%s)\n", util.Datetime(volume.Created), humanize.Time(volume.Created))
		cmd.Printf("Size:\t\t%s\n", humanize.Bytes(uint64(volume.Size)*humanize.GByte))
		cmd.Printf("Linux Device:\t%s\n", volume.LinuxDevice)
		cmd.Printf("Location:\n")
		cmd.Printf("  Name:\t\t%s\n", volume.Location.Name)
		cmd.Printf("  Description:\t%s\n", volume.Location.Description)
		cmd.Printf("  Country:\t%s\n", volume.Location.Country)
		cmd.Printf("  City:\t\t%s\n", volume.Location.City)
		cmd.Printf("  Latitude:\t%f\n", volume.Location.Latitude)
		cmd.Printf("  Longitude:\t%f\n", volume.Location.Longitude)
		if volume.Server != nil {
			cmd.Printf("Server:\n")
			cmd.Printf("  ID:\t\t%d\n", volume.Server.ID)
			cmd.Printf("  Name:\t\t%s\n", s.Client().Server().ServerName(volume.Server.ID))
		} else {
			cmd.Print("Server:\n  Not attached\n")
		}
		cmd.Printf("Protection:\n")
		cmd.Printf("  Delete:\t%s\n", util.YesNo(volume.Protection.Delete))

		cmd.Print("Labels:\n")
		if len(volume.Labels) == 0 {
			cmd.Print("  No labels\n")
		} else {
			for key, value := range volume.Labels {
				cmd.Printf("  %s: %s\n", key, value)
			}
		}

		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> <protection-level>...",
			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> <protection-level>...",
			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{
	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 },
	FetchLabels: func(s state.State, idOrName string) (map[string]string, int64, error) {
		volume, _, err := s.Client().Volume().Get(s, idOrName)
		if err != nil {
			return nil, 0, err
		}
		if volume == nil {
			return nil, 0, fmt.Errorf("volume not found: %s", idOrName)
		}
		return volume.Labels, volume.ID, nil
	},
	SetLabels: func(s state.State, id int64, labels map[string]string) error {
		opts := hcloud.VolumeUpdateOpts{
			Labels: labels,
		}
		_, _, err := s.Client().Volume().Update(s, &hcloud.Volume{ID: id}, opts)
		return err
	},
}
View Source
var ListCmd = base.ListCmd{
	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) ([]interface{}, error) {
		opts := hcloud.VolumeListOpts{ListOpts: listOpts}
		if len(sorts) > 0 {
			opts.Sort = sorts
		}
		volumes, err := s.Client().Volume().AllWithOpts(s, opts)

		var resources []interface{}
		for _, n := range volumes {
			resources = append(resources, n)
		}
		return resources, err
	},

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

	Schema: func(resources []interface{}) interface{} {
		volumesSchema := make([]schema.Volume, 0, len(resources))
		for _, resource := range resources {
			volume := resource.(*hcloud.Volume)
			volumesSchema = append(volumesSchema, hcloud.SchemaFromVolume(volume))
		}
		return volumesSchema
	},
}
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