volume

package
v1.43.1 Latest Latest
Warning

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

Go to latest
Published: Apr 22, 2024 License: MIT Imports: 15 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.ActionProgress(cmd, s, 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, args []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.ActionProgress(cmd, s, result.Action); err != nil {
			return nil, nil, err
		}
		if err := s.WaitForActions(cmd, s, 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",
	ShortDescription:     "Delete a Volume",
	NameSuggestions:      func(c hcapi2.Client) func() []string { return c.Volume().Names },
	Fetch: func(s state.State, cmd *cobra.Command, idOrName string) (interface{}, *hcloud.Response, error) {
		return s.Client().Volume().Get(s, idOrName)
	},
	Delete: func(s state.State, cmd *cobra.Command, resource interface{}) error {
		volume := resource.(*hcloud.Volume)
		if _, err := s.Client().Volume().Delete(s, volume); err != nil {
			return err
		}
		return nil
	},
}
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, cmd *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.ActionProgress(cmd, s, 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"},

	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(client hcapi2.Client) *output.Table {
		return output.NewTable().
			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.ActionProgress(cmd, s, 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, cmd *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, cmd *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