github.com/khulnasoft/cli@v0.0.0-20240402070845-01bcad7beefa/opts/throttledevice.go (about)

     1  package opts
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/docker/docker/api/types/blkiodev"
     9  	"github.com/khulnasoft-lab/go-units"
    10  )
    11  
    12  // ValidatorThrottleFctType defines a validator function that returns a validated struct and/or an error.
    13  type ValidatorThrottleFctType func(val string) (*blkiodev.ThrottleDevice, error)
    14  
    15  // ValidateThrottleBpsDevice validates that the specified string has a valid device-rate format.
    16  func ValidateThrottleBpsDevice(val string) (*blkiodev.ThrottleDevice, error) {
    17  	k, v, ok := strings.Cut(val, ":")
    18  	if !ok || k == "" {
    19  		return nil, fmt.Errorf("bad format: %s", val)
    20  	}
    21  	// TODO(thaJeztah): should we really validate this on the client?
    22  	if !strings.HasPrefix(k, "/dev/") {
    23  		return nil, fmt.Errorf("bad format for device path: %s", val)
    24  	}
    25  	rate, err := units.RAMInBytes(v)
    26  	if err != nil {
    27  		return nil, fmt.Errorf("invalid rate for device: %s. The correct format is <device-path>:<number>[<unit>]. Number must be a positive integer. Unit is optional and can be kb, mb, or gb", val)
    28  	}
    29  	if rate < 0 {
    30  		return nil, fmt.Errorf("invalid rate for device: %s. The correct format is <device-path>:<number>[<unit>]. Number must be a positive integer. Unit is optional and can be kb, mb, or gb", val)
    31  	}
    32  
    33  	return &blkiodev.ThrottleDevice{
    34  		Path: k,
    35  		Rate: uint64(rate),
    36  	}, nil
    37  }
    38  
    39  // ValidateThrottleIOpsDevice validates that the specified string has a valid device-rate format.
    40  func ValidateThrottleIOpsDevice(val string) (*blkiodev.ThrottleDevice, error) {
    41  	k, v, ok := strings.Cut(val, ":")
    42  	if !ok || k == "" {
    43  		return nil, fmt.Errorf("bad format: %s", val)
    44  	}
    45  	// TODO(thaJeztah): should we really validate this on the client?
    46  	if !strings.HasPrefix(k, "/dev/") {
    47  		return nil, fmt.Errorf("bad format for device path: %s", val)
    48  	}
    49  	rate, err := strconv.ParseUint(v, 10, 64)
    50  	if err != nil {
    51  		return nil, fmt.Errorf("invalid rate for device: %s. The correct format is <device-path>:<number>. Number must be a positive integer", val)
    52  	}
    53  
    54  	return &blkiodev.ThrottleDevice{Path: k, Rate: rate}, nil
    55  }
    56  
    57  // ThrottledeviceOpt defines a map of ThrottleDevices
    58  type ThrottledeviceOpt struct {
    59  	values    []*blkiodev.ThrottleDevice
    60  	validator ValidatorThrottleFctType
    61  }
    62  
    63  // NewThrottledeviceOpt creates a new ThrottledeviceOpt
    64  func NewThrottledeviceOpt(validator ValidatorThrottleFctType) ThrottledeviceOpt {
    65  	return ThrottledeviceOpt{
    66  		values:    []*blkiodev.ThrottleDevice{},
    67  		validator: validator,
    68  	}
    69  }
    70  
    71  // Set validates a ThrottleDevice and sets its name as a key in ThrottledeviceOpt
    72  func (opt *ThrottledeviceOpt) Set(val string) error {
    73  	var value *blkiodev.ThrottleDevice
    74  	if opt.validator != nil {
    75  		v, err := opt.validator(val)
    76  		if err != nil {
    77  			return err
    78  		}
    79  		value = v
    80  	}
    81  	opt.values = append(opt.values, value)
    82  	return nil
    83  }
    84  
    85  // String returns ThrottledeviceOpt values as a string.
    86  func (opt *ThrottledeviceOpt) String() string {
    87  	out := make([]string, 0, len(opt.values))
    88  	for _, v := range opt.values {
    89  		out = append(out, v.String())
    90  	}
    91  
    92  	return fmt.Sprintf("%v", out)
    93  }
    94  
    95  // GetList returns a slice of pointers to ThrottleDevices.
    96  func (opt *ThrottledeviceOpt) GetList() []*blkiodev.ThrottleDevice {
    97  	out := make([]*blkiodev.ThrottleDevice, 0, len(opt.values))
    98  	copy(out, opt.values)
    99  	return out
   100  }
   101  
   102  // Type returns the option type
   103  func (opt *ThrottledeviceOpt) Type() string {
   104  	return "list"
   105  }