github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/controlapi/common.go (about)

     1  package controlapi
     2  
     3  import (
     4  	"regexp"
     5  	"strings"
     6  
     7  	"github.com/docker/docker/pkg/plugingetter"
     8  	"github.com/docker/libnetwork/driverapi"
     9  	"github.com/docker/libnetwork/ipamapi"
    10  	"github.com/docker/swarmkit/api"
    11  	"github.com/docker/swarmkit/manager/allocator"
    12  	"github.com/docker/swarmkit/manager/state/store"
    13  	"google.golang.org/grpc/codes"
    14  	"google.golang.org/grpc/status"
    15  )
    16  
    17  var isValidDNSName = regexp.MustCompile(`^[a-zA-Z0-9](?:[-_]*[A-Za-z0-9]+)*$`)
    18  
    19  // configs and secrets have different naming requirements from tasks and services
    20  var isValidConfigOrSecretName = regexp.MustCompile(`^[a-zA-Z0-9]+(?:[a-zA-Z0-9-_.]*[a-zA-Z0-9])?$`)
    21  
    22  func buildFilters(by func(string) store.By, values []string) store.By {
    23  	filters := make([]store.By, 0, len(values))
    24  	for _, v := range values {
    25  		filters = append(filters, by(v))
    26  	}
    27  	return store.Or(filters...)
    28  }
    29  
    30  func filterContains(match string, candidates []string) bool {
    31  	if len(candidates) == 0 {
    32  		return true
    33  	}
    34  	for _, c := range candidates {
    35  		if c == match {
    36  			return true
    37  		}
    38  	}
    39  	return false
    40  }
    41  
    42  func filterContainsPrefix(match string, candidates []string) bool {
    43  	if len(candidates) == 0 {
    44  		return true
    45  	}
    46  	for _, c := range candidates {
    47  		if strings.HasPrefix(match, c) {
    48  			return true
    49  		}
    50  	}
    51  	return false
    52  }
    53  
    54  func filterMatchLabels(match map[string]string, candidates map[string]string) bool {
    55  	if len(candidates) == 0 {
    56  		return true
    57  	}
    58  
    59  	for k, v := range candidates {
    60  		c, ok := match[k]
    61  		if !ok {
    62  			return false
    63  		}
    64  		if v != "" && v != c {
    65  			return false
    66  		}
    67  	}
    68  	return true
    69  }
    70  
    71  func validateAnnotations(m api.Annotations) error {
    72  	if m.Name == "" {
    73  		return status.Errorf(codes.InvalidArgument, "meta: name must be provided")
    74  	}
    75  	if !isValidDNSName.MatchString(m.Name) {
    76  		// if the name doesn't match the regex
    77  		return status.Errorf(codes.InvalidArgument, "name must be valid as a DNS name component")
    78  	}
    79  	if len(m.Name) > 63 {
    80  		// DNS labels are limited to 63 characters
    81  		return status.Errorf(codes.InvalidArgument, "name must be 63 characters or fewer")
    82  	}
    83  	return nil
    84  }
    85  
    86  func validateConfigOrSecretAnnotations(m api.Annotations) error {
    87  	if m.Name == "" {
    88  		return status.Errorf(codes.InvalidArgument, "name must be provided")
    89  	} else if len(m.Name) > 64 || !isValidConfigOrSecretName.MatchString(m.Name) {
    90  		// if the name doesn't match the regex
    91  		return status.Errorf(codes.InvalidArgument,
    92  			"invalid name, only 64 [a-zA-Z0-9-_.] characters allowed, and the start and end character must be [a-zA-Z0-9]")
    93  	}
    94  	return nil
    95  }
    96  
    97  func validateDriver(driver *api.Driver, pg plugingetter.PluginGetter, pluginType string) error {
    98  	if driver == nil {
    99  		// It is ok to not specify the driver. We will choose
   100  		// a default driver.
   101  		return nil
   102  	}
   103  
   104  	if driver.Name == "" {
   105  		return status.Errorf(codes.InvalidArgument, "driver name: if driver is specified name is required")
   106  	}
   107  
   108  	// First check against the known drivers
   109  	switch pluginType {
   110  	case ipamapi.PluginEndpointType:
   111  		if strings.ToLower(driver.Name) == ipamapi.DefaultIPAM {
   112  			return nil
   113  		}
   114  	case driverapi.NetworkPluginEndpointType:
   115  		if allocator.IsBuiltInNetworkDriver(driver.Name) {
   116  			return nil
   117  		}
   118  	default:
   119  	}
   120  
   121  	if pg == nil {
   122  		return status.Errorf(codes.InvalidArgument, "plugin %s not supported", driver.Name)
   123  	}
   124  
   125  	p, err := pg.Get(driver.Name, pluginType, plugingetter.Lookup)
   126  	if err != nil {
   127  		return status.Errorf(codes.InvalidArgument, "error during lookup of plugin %s", driver.Name)
   128  	}
   129  
   130  	if p.IsV1() {
   131  		return status.Errorf(codes.InvalidArgument, "legacy plugin %s of type %s is not supported in swarm mode", driver.Name, pluginType)
   132  	}
   133  
   134  	return nil
   135  }