mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 22:01:06 +00:00 
			
		
		
		
	Ran commands: hack/pin-dependency.sh github.com/GoogleCloudPlatform/k8s-cloud-provider 27a4ced34534a6c32b63159b100ac0efaa1d37b3 hack/update-vendor.sh hack/pin-dependency.sh google.golang.org/api 5213b809086156e6e2b262a41394993fcff97439 hack/update-vendor.sh hack/verify-vendor.sh merge conflicts
		
			
				
	
	
		
			148 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2018, OpenCensus Authors
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //     http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| // Package tracestate implements support for the Tracestate header of the
 | |
| // W3C TraceContext propagation format.
 | |
| package tracestate
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"regexp"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	keyMaxSize       = 256
 | |
| 	valueMaxSize     = 256
 | |
| 	maxKeyValuePairs = 32
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	keyWithoutVendorFormat = `[a-z][_0-9a-z\-\*\/]{0,255}`
 | |
| 	keyWithVendorFormat    = `[a-z][_0-9a-z\-\*\/]{0,240}@[a-z][_0-9a-z\-\*\/]{0,13}`
 | |
| 	keyFormat              = `(` + keyWithoutVendorFormat + `)|(` + keyWithVendorFormat + `)`
 | |
| 	valueFormat            = `[\x20-\x2b\x2d-\x3c\x3e-\x7e]{0,255}[\x21-\x2b\x2d-\x3c\x3e-\x7e]`
 | |
| )
 | |
| 
 | |
| var keyValidationRegExp = regexp.MustCompile(`^(` + keyFormat + `)$`)
 | |
| var valueValidationRegExp = regexp.MustCompile(`^(` + valueFormat + `)$`)
 | |
| 
 | |
| // Tracestate represents tracing-system specific context in a list of key-value pairs. Tracestate allows different
 | |
| // vendors propagate additional information and inter-operate with their legacy Id formats.
 | |
| type Tracestate struct {
 | |
| 	entries []Entry
 | |
| }
 | |
| 
 | |
| // Entry represents one key-value pair in a list of key-value pair of Tracestate.
 | |
| type Entry struct {
 | |
| 	// Key is an opaque string up to 256 characters printable. It MUST begin with a lowercase letter,
 | |
| 	// and can only contain lowercase letters a-z, digits 0-9, underscores _, dashes -, asterisks *, and
 | |
| 	// forward slashes /.
 | |
| 	Key string
 | |
| 
 | |
| 	// Value is an opaque string up to 256 characters printable ASCII RFC0020 characters (i.e., the
 | |
| 	// range 0x20 to 0x7E) except comma , and =.
 | |
| 	Value string
 | |
| }
 | |
| 
 | |
| // Entries returns a slice of Entry.
 | |
| func (ts *Tracestate) Entries() []Entry {
 | |
| 	if ts == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	return ts.entries
 | |
| }
 | |
| 
 | |
| func (ts *Tracestate) remove(key string) *Entry {
 | |
| 	for index, entry := range ts.entries {
 | |
| 		if entry.Key == key {
 | |
| 			ts.entries = append(ts.entries[:index], ts.entries[index+1:]...)
 | |
| 			return &entry
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (ts *Tracestate) add(entries []Entry) error {
 | |
| 	for _, entry := range entries {
 | |
| 		ts.remove(entry.Key)
 | |
| 	}
 | |
| 	if len(ts.entries)+len(entries) > maxKeyValuePairs {
 | |
| 		return fmt.Errorf("adding %d key-value pairs to current %d pairs exceeds the limit of %d",
 | |
| 			len(entries), len(ts.entries), maxKeyValuePairs)
 | |
| 	}
 | |
| 	ts.entries = append(entries, ts.entries...)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func isValid(entry Entry) bool {
 | |
| 	return keyValidationRegExp.MatchString(entry.Key) &&
 | |
| 		valueValidationRegExp.MatchString(entry.Value)
 | |
| }
 | |
| 
 | |
| func containsDuplicateKey(entries ...Entry) (string, bool) {
 | |
| 	keyMap := make(map[string]int)
 | |
| 	for _, entry := range entries {
 | |
| 		if _, ok := keyMap[entry.Key]; ok {
 | |
| 			return entry.Key, true
 | |
| 		}
 | |
| 		keyMap[entry.Key] = 1
 | |
| 	}
 | |
| 	return "", false
 | |
| }
 | |
| 
 | |
| func areEntriesValid(entries ...Entry) (*Entry, bool) {
 | |
| 	for _, entry := range entries {
 | |
| 		if !isValid(entry) {
 | |
| 			return &entry, false
 | |
| 		}
 | |
| 	}
 | |
| 	return nil, true
 | |
| }
 | |
| 
 | |
| // New creates a Tracestate object from a parent and/or entries (key-value pair).
 | |
| // Entries from the parent are copied if present. The entries passed to this function
 | |
| // are inserted in front of those copied from the parent. If an entry copied from the
 | |
| // parent contains the same key as one of the entry in entries then the entry copied
 | |
| // from the parent is removed. See add func.
 | |
| //
 | |
| // An error is returned with nil Tracestate if
 | |
| //  1. one or more entry in entries is invalid.
 | |
| //  2. two or more entries in the input entries have the same key.
 | |
| //  3. the number of entries combined from the parent and the input entries exceeds maxKeyValuePairs.
 | |
| //     (duplicate entry is counted only once).
 | |
| func New(parent *Tracestate, entries ...Entry) (*Tracestate, error) {
 | |
| 	if parent == nil && len(entries) == 0 {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 	if entry, ok := areEntriesValid(entries...); !ok {
 | |
| 		return nil, fmt.Errorf("key-value pair {%s, %s} is invalid", entry.Key, entry.Value)
 | |
| 	}
 | |
| 
 | |
| 	if key, duplicate := containsDuplicateKey(entries...); duplicate {
 | |
| 		return nil, fmt.Errorf("contains duplicate keys (%s)", key)
 | |
| 	}
 | |
| 
 | |
| 	tracestate := Tracestate{}
 | |
| 
 | |
| 	if parent != nil && len(parent.entries) > 0 {
 | |
| 		tracestate.entries = append([]Entry{}, parent.entries...)
 | |
| 	}
 | |
| 
 | |
| 	err := tracestate.add(entries)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return &tracestate, nil
 | |
| }
 |