vitess.io/vitess@v0.16.2/go/vt/vtorc/inst/tag.go (about)

     1  /*
     2     Copyright 2015 Shlomi Noach, courtesy Booking.com
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package inst
    18  
    19  import (
    20  	"fmt"
    21  	"regexp"
    22  	"strings"
    23  )
    24  
    25  type Tag struct {
    26  	TagName  string
    27  	TagValue string
    28  	HasValue bool
    29  	Negate   bool
    30  }
    31  
    32  var (
    33  	negateTagEqualsRegexp = regexp.MustCompile("^~([^=]+)=(.*)$")
    34  	TagEqualsRegexp       = regexp.MustCompile("^([^=]+)=(.*)$")
    35  	negateTagExistsRegexp = regexp.MustCompile("^~([^=]+)$")
    36  	tagExistsRegexp       = regexp.MustCompile("^([^=]+)$")
    37  )
    38  
    39  func NewTag(tagName string, tagValue string) (*Tag, error) {
    40  	tagName = strings.TrimSpace(tagName)
    41  	if tagName == "" {
    42  		return nil, fmt.Errorf("NewTag: empty tag name")
    43  	}
    44  	return &Tag{TagName: tagName, TagValue: tagValue}, nil
    45  }
    46  
    47  func ParseTag(tagString string) (*Tag, error) {
    48  	tagString = strings.Replace(tagString, "!", "~", -1)
    49  	tagString = strings.TrimSpace(tagString)
    50  
    51  	if submatch := negateTagEqualsRegexp.FindStringSubmatch(tagString); len(submatch) > 0 {
    52  		return &Tag{
    53  			TagName:  submatch[1],
    54  			TagValue: submatch[2],
    55  			HasValue: true,
    56  			Negate:   true,
    57  		}, nil
    58  	} else if submatch := TagEqualsRegexp.FindStringSubmatch(tagString); len(submatch) > 0 {
    59  		return &Tag{
    60  			TagName:  submatch[1],
    61  			TagValue: submatch[2],
    62  			HasValue: true,
    63  		}, nil
    64  	} else if submatch := negateTagExistsRegexp.FindStringSubmatch(tagString); len(submatch) > 0 {
    65  		return &Tag{
    66  			TagName: submatch[1],
    67  			Negate:  true,
    68  		}, nil
    69  	} else if submatch := tagExistsRegexp.FindStringSubmatch(tagString); len(submatch) > 0 {
    70  		return &Tag{
    71  			TagName: submatch[1],
    72  		}, nil
    73  	}
    74  	return nil, fmt.Errorf("Unable to parse tag: %s", tagString)
    75  }
    76  
    77  func (tag *Tag) String() string {
    78  	return fmt.Sprintf("%s=%s", tag.TagName, tag.TagValue)
    79  }
    80  
    81  func (tag *Tag) Display() string {
    82  	if tag.TagValue == "" {
    83  		return tag.TagName
    84  	}
    85  	return fmt.Sprintf("%s=%s", tag.TagName, tag.TagValue)
    86  }
    87  
    88  func ParseIntersectTags(tagsString string) (tags [](*Tag), err error) {
    89  	for _, tagString := range strings.Split(tagsString, ",") {
    90  		tag, err := ParseTag(tagString)
    91  		if err != nil {
    92  			return tags, err
    93  		}
    94  		tags = append(tags, tag)
    95  	}
    96  	return tags, nil
    97  }
    98  
    99  type InstanceTag struct {
   100  	Key InstanceKey
   101  	T   Tag
   102  }
   103  
   104  func GetInstanceKeysByTags(tagsString string) (tagged *InstanceKeyMap, err error) {
   105  	tags, err := ParseIntersectTags(tagsString)
   106  	if err != nil {
   107  		return tagged, err
   108  	}
   109  	for i, tag := range tags {
   110  		taggedByTag, err := GetInstanceKeysByTag(tag)
   111  		if err != nil {
   112  			return tagged, err
   113  		}
   114  		if i == 0 {
   115  			tagged = taggedByTag
   116  		} else {
   117  			tagged = tagged.Intersect(taggedByTag)
   118  		}
   119  	}
   120  	return tagged, nil
   121  }