...

Source file src/github.com/docker/cli/cli/command/service/generic_resource_opts.go

Documentation: github.com/docker/cli/cli/command/service

     1  package service
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/pkg/errors"
     8  
     9  	"github.com/docker/docker/api/types/swarm"
    10  	swarmapi "github.com/moby/swarmkit/v2/api"
    11  	"github.com/moby/swarmkit/v2/api/genericresource"
    12  )
    13  
    14  // GenericResource is a concept that a user can use to advertise user-defined
    15  // resources on a node and thus better place services based on these resources.
    16  // E.g: NVIDIA GPUs, Intel FPGAs, ...
    17  // See https://github.com/moby/swarmkit/blob/de950a7ed842c7b7e47e9451cde9bf8f96031894/design/generic_resources.md
    18  
    19  // ValidateSingleGenericResource validates that a single entry in the
    20  // generic resource list is valid.
    21  // i.e 'GPU=UID1' is valid however 'GPU:UID1' or 'UID1' isn't
    22  func ValidateSingleGenericResource(val string) (string, error) {
    23  	if strings.Count(val, "=") < 1 {
    24  		return "", fmt.Errorf("invalid generic-resource format `%s` expected `name=value`", val)
    25  	}
    26  
    27  	return val, nil
    28  }
    29  
    30  // ParseGenericResources parses an array of Generic resourceResources
    31  // Requesting Named Generic Resources for a service is not supported this
    32  // is filtered here.
    33  func ParseGenericResources(value []string) ([]swarm.GenericResource, error) {
    34  	if len(value) == 0 {
    35  		return nil, nil
    36  	}
    37  
    38  	resources, err := genericresource.Parse(value)
    39  	if err != nil {
    40  		return nil, errors.Wrapf(err, "invalid generic resource specification")
    41  	}
    42  
    43  	swarmResources := genericResourcesFromGRPC(resources)
    44  	for _, res := range swarmResources {
    45  		if res.NamedResourceSpec != nil {
    46  			return nil, fmt.Errorf("invalid generic-resource request `%s=%s`, Named Generic Resources is not supported for service create or update", res.NamedResourceSpec.Kind, res.NamedResourceSpec.Value)
    47  		}
    48  	}
    49  
    50  	return swarmResources, nil
    51  }
    52  
    53  // genericResourcesFromGRPC converts a GRPC GenericResource to a GenericResource
    54  func genericResourcesFromGRPC(genericRes []*swarmapi.GenericResource) []swarm.GenericResource {
    55  	generic := make([]swarm.GenericResource, 0, len(genericRes))
    56  	for _, res := range genericRes {
    57  		var current swarm.GenericResource
    58  
    59  		switch r := res.Resource.(type) {
    60  		case *swarmapi.GenericResource_DiscreteResourceSpec:
    61  			current.DiscreteResourceSpec = &swarm.DiscreteGenericResource{
    62  				Kind:  r.DiscreteResourceSpec.Kind,
    63  				Value: r.DiscreteResourceSpec.Value,
    64  			}
    65  		case *swarmapi.GenericResource_NamedResourceSpec:
    66  			current.NamedResourceSpec = &swarm.NamedGenericResource{
    67  				Kind:  r.NamedResourceSpec.Kind,
    68  				Value: r.NamedResourceSpec.Value,
    69  			}
    70  		}
    71  
    72  		generic = append(generic, current)
    73  	}
    74  
    75  	return generic
    76  }
    77  
    78  func buildGenericResourceMap(genericRes []swarm.GenericResource) (map[string]swarm.GenericResource, error) {
    79  	m := make(map[string]swarm.GenericResource)
    80  
    81  	for _, res := range genericRes {
    82  		if res.DiscreteResourceSpec == nil {
    83  			return nil, fmt.Errorf("invalid generic-resource `%+v` for service task", res)
    84  		}
    85  
    86  		_, ok := m[res.DiscreteResourceSpec.Kind]
    87  		if ok {
    88  			return nil, fmt.Errorf("duplicate generic-resource `%+v` for service task", res.DiscreteResourceSpec.Kind)
    89  		}
    90  
    91  		m[res.DiscreteResourceSpec.Kind] = res
    92  	}
    93  
    94  	return m, nil
    95  }
    96  
    97  func buildGenericResourceList(genericRes map[string]swarm.GenericResource) []swarm.GenericResource {
    98  	l := make([]swarm.GenericResource, 0, len(genericRes))
    99  
   100  	for _, res := range genericRes {
   101  		l = append(l, res)
   102  	}
   103  
   104  	return l
   105  }
   106  

View as plain text