github.com/docker/compose-on-kubernetes@v0.5.0/internal/convert/placement.go (about)

     1  package convert
     2  
     3  import (
     4  	"github.com/docker/compose-on-kubernetes/api/compose/latest"
     5  	"github.com/pkg/errors"
     6  	apiv1 "k8s.io/api/core/v1"
     7  )
     8  
     9  const (
    10  	kubernetesOs       = "beta.kubernetes.io/os"
    11  	kubernetesArch     = "beta.kubernetes.io/arch"
    12  	kubernetesHostname = "kubernetes.io/hostname"
    13  )
    14  
    15  // node.id	Node ID	node.id == 2ivku8v2gvtg4
    16  // node.hostname	Node hostname	node.hostname != node-2
    17  // node.role	Node role	node.role == manager
    18  // node.labels	user defined node labels	node.labels.security == high
    19  // engine.labels	Docker Engine's labels	engine.labels.operatingsystem == ubuntu 14.04
    20  func toNodeAffinity(constraints *latest.Constraints) (*apiv1.Affinity, error) {
    21  	if constraints == nil {
    22  		constraints = &latest.Constraints{}
    23  	}
    24  	requirements := []apiv1.NodeSelectorRequirement{}
    25  	if constraints.OperatingSystem != nil {
    26  		operator, err := toRequirementOperator(constraints.OperatingSystem.Operator)
    27  		if err != nil {
    28  			return nil, err
    29  		}
    30  		requirements = append(requirements, apiv1.NodeSelectorRequirement{
    31  			Key:      kubernetesOs,
    32  			Operator: operator,
    33  			Values:   []string{constraints.OperatingSystem.Value},
    34  		})
    35  	}
    36  	if constraints.Architecture != nil {
    37  		operator, err := toRequirementOperator(constraints.Architecture.Operator)
    38  		if err != nil {
    39  			return nil, err
    40  		}
    41  		requirements = append(requirements, apiv1.NodeSelectorRequirement{
    42  			Key:      kubernetesArch,
    43  			Operator: operator,
    44  			Values:   []string{constraints.Architecture.Value},
    45  		})
    46  	}
    47  	if constraints.Hostname != nil {
    48  		operator, err := toRequirementOperator(constraints.Hostname.Operator)
    49  		if err != nil {
    50  			return nil, err
    51  		}
    52  		requirements = append(requirements, apiv1.NodeSelectorRequirement{
    53  			Key:      kubernetesHostname,
    54  			Operator: operator,
    55  			Values:   []string{constraints.Hostname.Value},
    56  		})
    57  	}
    58  	if constraints.MatchLabels != nil {
    59  		for key, constraint := range constraints.MatchLabels {
    60  			operator, err := toRequirementOperator(constraint.Operator)
    61  			if err != nil {
    62  				return nil, err
    63  			}
    64  			requirements = append(requirements, apiv1.NodeSelectorRequirement{
    65  				Key:      key,
    66  				Operator: operator,
    67  				Values:   []string{constraint.Value},
    68  			})
    69  		}
    70  	}
    71  	if !hasRequirement(requirements, kubernetesOs) {
    72  		requirements = append(requirements, apiv1.NodeSelectorRequirement{
    73  			Key:      kubernetesOs,
    74  			Operator: apiv1.NodeSelectorOpIn,
    75  			Values:   []string{"linux"},
    76  		})
    77  	}
    78  	if !hasRequirement(requirements, kubernetesArch) {
    79  		requirements = append(requirements, apiv1.NodeSelectorRequirement{
    80  			Key:      kubernetesArch,
    81  			Operator: apiv1.NodeSelectorOpIn,
    82  			Values:   []string{"amd64"},
    83  		})
    84  	}
    85  	return &apiv1.Affinity{
    86  		NodeAffinity: &apiv1.NodeAffinity{
    87  			RequiredDuringSchedulingIgnoredDuringExecution: &apiv1.NodeSelector{
    88  				NodeSelectorTerms: []apiv1.NodeSelectorTerm{
    89  					{
    90  						MatchExpressions: requirements,
    91  					},
    92  				},
    93  			},
    94  		},
    95  	}, nil
    96  }
    97  
    98  func hasRequirement(requirements []apiv1.NodeSelectorRequirement, key string) bool {
    99  	for _, r := range requirements {
   100  		if r.Key == key {
   101  			return true
   102  		}
   103  	}
   104  	return false
   105  }
   106  
   107  func toRequirementOperator(sign string) (apiv1.NodeSelectorOperator, error) {
   108  	switch sign {
   109  	case "==":
   110  		return apiv1.NodeSelectorOpIn, nil
   111  	case "!=":
   112  		return apiv1.NodeSelectorOpNotIn, nil
   113  	case ">":
   114  		return apiv1.NodeSelectorOpGt, nil
   115  	case "<":
   116  		return apiv1.NodeSelectorOpLt, nil
   117  	default:
   118  		return "", errors.Errorf("operator %s not supported", sign)
   119  	}
   120  }