github.com/docker/libcompose@v0.4.1-0.20210616120443-2a046c0bdbf2/yaml/ulimit.go (about)

     1  package yaml
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"sort"
     7  )
     8  
     9  // Ulimits represents a list of Ulimit.
    10  // It is, however, represented in yaml as keys (and thus map in Go)
    11  type Ulimits struct {
    12  	Elements []Ulimit
    13  }
    14  
    15  // MarshalYAML implements the Marshaller interface.
    16  func (u Ulimits) MarshalYAML() (interface{}, error) {
    17  	ulimitMap := make(map[string]Ulimit)
    18  	for _, ulimit := range u.Elements {
    19  		ulimitMap[ulimit.Name] = ulimit
    20  	}
    21  	return ulimitMap, nil
    22  }
    23  
    24  // UnmarshalYAML implements the Unmarshaller interface.
    25  func (u *Ulimits) UnmarshalYAML(unmarshal func(interface{}) error) error {
    26  	ulimits := make(map[string]Ulimit)
    27  
    28  	var mapType map[interface{}]interface{}
    29  	if err := unmarshal(&mapType); err == nil {
    30  		for mapKey, mapValue := range mapType {
    31  			name, ok := mapKey.(string)
    32  			if !ok {
    33  				return fmt.Errorf("Cannot unmarshal '%v' to type %T into a string value", name, name)
    34  			}
    35  			var soft, hard int64
    36  			switch mv := mapValue.(type) {
    37  			case int:
    38  				soft = int64(mv)
    39  				hard = int64(mv)
    40  			case map[interface{}]interface{}:
    41  				if len(mv) != 2 {
    42  					return fmt.Errorf("Failed to unmarshal Ulimit: %#v", mapValue)
    43  				}
    44  				for mkey, mvalue := range mv {
    45  					switch mkey {
    46  					case "soft":
    47  						soft = int64(mvalue.(int))
    48  					case "hard":
    49  						hard = int64(mvalue.(int))
    50  					default:
    51  						// FIXME(vdemeester) Should we ignore or fail ?
    52  						continue
    53  					}
    54  				}
    55  			default:
    56  				return fmt.Errorf("Failed to unmarshal Ulimit: %v, %T", mapValue, mapValue)
    57  			}
    58  			ulimits[name] = Ulimit{
    59  				Name: name,
    60  				ulimitValues: ulimitValues{
    61  					Soft: soft,
    62  					Hard: hard,
    63  				},
    64  			}
    65  		}
    66  		keys := make([]string, 0, len(ulimits))
    67  		for key := range ulimits {
    68  			keys = append(keys, key)
    69  		}
    70  		sort.Strings(keys)
    71  		for _, key := range keys {
    72  			u.Elements = append(u.Elements, ulimits[key])
    73  		}
    74  		return nil
    75  	}
    76  
    77  	return errors.New("Failed to unmarshal Ulimit")
    78  }
    79  
    80  // Ulimit represents ulimit information.
    81  type Ulimit struct {
    82  	ulimitValues
    83  	Name string
    84  }
    85  
    86  type ulimitValues struct {
    87  	Soft int64 `yaml:"soft"`
    88  	Hard int64 `yaml:"hard"`
    89  }
    90  
    91  // MarshalYAML implements the Marshaller interface.
    92  func (u Ulimit) MarshalYAML() (interface{}, error) {
    93  	if u.Soft == u.Hard {
    94  		return u.Soft, nil
    95  	}
    96  	return u.ulimitValues, nil
    97  }
    98  
    99  // NewUlimit creates a Ulimit based on the specified parts.
   100  func NewUlimit(name string, soft int64, hard int64) Ulimit {
   101  	return Ulimit{
   102  		Name: name,
   103  		ulimitValues: ulimitValues{
   104  			Soft: soft,
   105  			Hard: hard,
   106  		},
   107  	}
   108  }