<commit_before>package filter

import (
	"fmt"
	"strings"

	"github.com/docker/swarm/cluster"
	"github.com/samalba/dockerclient"
)

// LabelFilter selects only nodes that match certain labels.
type LabelFilter struct {
}

func (f *LabelFilter) extractConstraints(env []string) map[string]string {
	constraints := make(map[string]string)
	for _, e := range env {
		if strings.HasPrefix(e, "constraint:") {
			constraint := strings.TrimPrefix(e, "constraint:")
			parts := strings.SplitN(constraint, "=", 2)
			constraints[strings.ToLower(parts[0])] = strings.ToLower(parts[1])
		}
	}
	return constraints
}

func (f *LabelFilter) Filter(config *dockerclient.ContainerConfig, nodes []*cluster.Node) ([]*cluster.Node, error) {
	constraints := f.extractConstraints(config.Env)
	for k, v := range constraints {
		candidates := []*cluster.Node{}
		for _, node := range nodes {
			switch k {
			case "node":
				// "node" label is a special case pinning a container to a specific node.
				if strings.ToLower(node.ID) == v || strings.ToLower(node.Name) == v {
					candidates = append(candidates, node)
				}
			default:
				// By default match the node labels.
				if label, ok := node.Labels[k]; ok {
					if strings.Contains(strings.ToLower(label), v) {
						candidates = append(candidates, node)
					}
				}
			}
		}
		if len(candidates) == 0 {
			return nil, fmt.Errorf("unable to find a node that satisfies %s == %s", k, v)
		}
		nodes = candidates
	}
	return nodes, nil
}<commit_msg>add matching to constraints<commit_after>package filter

import (
	"fmt"
	"regexp"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/swarm/cluster"
	"github.com/samalba/dockerclient"
)

// LabelFilter selects only nodes that match certain labels.
type LabelFilter struct {
}

func (f *LabelFilter) extractConstraints(env []string) map[string]string {
	constraints := make(map[string]string)
	for _, e := range env {
		if strings.HasPrefix(e, "constraint:") {
			constraint := strings.TrimPrefix(e, "constraint:")
			parts := strings.SplitN(constraint, "=", 2)
			constraints[strings.ToLower(parts[0])] = strings.ToLower(parts[1])
		}
	}
	return constraints
}

func (f *LabelFilter) Filter(config *dockerclient.ContainerConfig, nodes []*cluster.Node) ([]*cluster.Node, error) {
	constraints := f.extractConstraints(config.Env)
	for k, v := range constraints {
		regex := "^" + strings.Replace(v, "*", ".*", -1) + "$"
		log.Debugf("matching constraint: %s=%s", k, regex)
		candidates := []*cluster.Node{}
		for _, node := range nodes {
			switch k {
			case "node":
				// "node" label is a special case pinning a container to a specific node.
				matchedID, err := regexp.MatchString(regex, strings.ToLower(node.ID))
				if err != nil {
					log.Error(err)
				}
				matchedName, err := regexp.MatchString(regex, strings.ToLower(node.Name))
				if err != nil {
					log.Error(err)
				}
				if matchedID || matchedName {
					candidates = append(candidates, node)
				}
			default:
				// By default match the node labels.
				if label, ok := node.Labels[k]; ok {
					matched, err := regexp.MatchString(regex, strings.ToLower(label))
					if err != nil {
						log.Error(err)
					}
					if matched {
						candidates = append(candidates, node)
					}
				}
			}
		}
		if len(candidates) == 0 {
			return nil, fmt.Errorf("unable to find a node that satisfies %s == %s", k, v)
		}
		nodes = candidates
	}
	return nodes, nil
}
{'fraction_non_alphanumeric': 0.14427570093457945, 'fraction_numerical': 0.002628504672897196, 'mean_word_length': 3.5304232804232805, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1520494', 'n_tokens_mistral': 1318, 'n_tokens_neox': 1117, 'n_words': 293}