blob: 32db4d96f69f8e4ca66ca7de9cda305df6c3ce18 [file] [log] [blame]
Zack Williamse940c7a2019-08-21 14:25:39 -07001/*
2Copyright 2014 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package labels
18
19import (
20 "fmt"
21 "sort"
22 "strings"
23)
24
25// Labels allows you to present labels independently from their storage.
26type Labels interface {
27 // Has returns whether the provided label exists.
28 Has(label string) (exists bool)
29
30 // Get returns the value for the provided label.
31 Get(label string) (value string)
32}
33
34// Set is a map of label:value. It implements Labels.
35type Set map[string]string
36
37// String returns all labels listed as a human readable string.
38// Conveniently, exactly the format that ParseSelector takes.
39func (ls Set) String() string {
40 selector := make([]string, 0, len(ls))
41 for key, value := range ls {
42 selector = append(selector, key+"="+value)
43 }
44 // Sort for determinism.
45 sort.StringSlice(selector).Sort()
46 return strings.Join(selector, ",")
47}
48
49// Has returns whether the provided label exists in the map.
50func (ls Set) Has(label string) bool {
51 _, exists := ls[label]
52 return exists
53}
54
55// Get returns the value in the map for the provided label.
56func (ls Set) Get(label string) string {
57 return ls[label]
58}
59
60// AsSelector converts labels into a selectors.
61func (ls Set) AsSelector() Selector {
62 return SelectorFromSet(ls)
63}
64
65// AsSelectorPreValidated converts labels into a selector, but
66// assumes that labels are already validated and thus don't
67// preform any validation.
68// According to our measurements this is significantly faster
69// in codepaths that matter at high scale.
70func (ls Set) AsSelectorPreValidated() Selector {
71 return SelectorFromValidatedSet(ls)
72}
73
74// FormatLabels convert label map into plain string
75func FormatLabels(labelMap map[string]string) string {
76 l := Set(labelMap).String()
77 if l == "" {
78 l = "<none>"
79 }
80 return l
81}
82
83// Conflicts takes 2 maps and returns true if there a key match between
84// the maps but the value doesn't match, and returns false in other cases
85func Conflicts(labels1, labels2 Set) bool {
86 small := labels1
87 big := labels2
88 if len(labels2) < len(labels1) {
89 small = labels2
90 big = labels1
91 }
92
93 for k, v := range small {
94 if val, match := big[k]; match {
95 if val != v {
96 return true
97 }
98 }
99 }
100
101 return false
102}
103
104// Merge combines given maps, and does not check for any conflicts
105// between the maps. In case of conflicts, second map (labels2) wins
106func Merge(labels1, labels2 Set) Set {
107 mergedMap := Set{}
108
109 for k, v := range labels1 {
110 mergedMap[k] = v
111 }
112 for k, v := range labels2 {
113 mergedMap[k] = v
114 }
115 return mergedMap
116}
117
118// Equals returns true if the given maps are equal
119func Equals(labels1, labels2 Set) bool {
120 if len(labels1) != len(labels2) {
121 return false
122 }
123
124 for k, v := range labels1 {
125 value, ok := labels2[k]
126 if !ok {
127 return false
128 }
129 if value != v {
130 return false
131 }
132 }
133 return true
134}
135
136// AreLabelsInWhiteList verifies if the provided label list
137// is in the provided whitelist and returns true, otherwise false.
138func AreLabelsInWhiteList(labels, whitelist Set) bool {
139 if len(whitelist) == 0 {
140 return true
141 }
142
143 for k, v := range labels {
144 value, ok := whitelist[k]
145 if !ok {
146 return false
147 }
148 if value != v {
149 return false
150 }
151 }
152 return true
153}
154
155// ConvertSelectorToLabelsMap converts selector string to labels map
156// and validates keys and values
157func ConvertSelectorToLabelsMap(selector string) (Set, error) {
158 labelsMap := Set{}
159
160 if len(selector) == 0 {
161 return labelsMap, nil
162 }
163
164 labels := strings.Split(selector, ",")
165 for _, label := range labels {
166 l := strings.Split(label, "=")
167 if len(l) != 2 {
168 return labelsMap, fmt.Errorf("invalid selector: %s", l)
169 }
170 key := strings.TrimSpace(l[0])
171 if err := validateLabelKey(key); err != nil {
172 return labelsMap, err
173 }
174 value := strings.TrimSpace(l[1])
175 if err := validateLabelValue(value); err != nil {
176 return labelsMap, err
177 }
178 labelsMap[key] = value
179 }
180 return labelsMap, nil
181}