github.com/influxdata/influxdb/v2@v2.7.6/tag.go (about)

     1  package influxdb
     2  
     3  import (
     4  	"encoding/json"
     5  	"regexp"
     6  	"strings"
     7  
     8  	"github.com/influxdata/influxdb/v2/kit/platform/errors"
     9  )
    10  
    11  // Operator is an Enum value of operators.
    12  type Operator int
    13  
    14  // Valid returns invalid error if the operator is invalid.
    15  func (op Operator) Valid() error {
    16  	if op < Equal || op > NotRegexEqual {
    17  		return &errors.Error{
    18  			Code: errors.EInvalid,
    19  			Msg:  "Operator is invalid",
    20  		}
    21  	}
    22  	return nil
    23  }
    24  
    25  // operators
    26  const (
    27  	Equal Operator = iota
    28  	NotEqual
    29  	RegexEqual
    30  	NotRegexEqual
    31  )
    32  
    33  var opStr = []string{
    34  	"equal",
    35  	"notequal",
    36  	"equalregex",
    37  	"notequalregex",
    38  }
    39  
    40  var opStrMap = map[string]Operator{
    41  	"equal":         Equal,
    42  	"notequal":      NotEqual,
    43  	"equalregex":    RegexEqual,
    44  	"notequalregex": NotRegexEqual,
    45  }
    46  
    47  // ToOperator converts a string into its equivalent Operator.
    48  func ToOperator(s string) (Operator, bool) {
    49  	s = strings.ToLower(s)
    50  	if op, ok := opStrMap[s]; ok {
    51  		return op, true
    52  	}
    53  	return -1, false
    54  }
    55  
    56  // String returns the string value of the operator.
    57  func (op Operator) String() string {
    58  	if err := op.Valid(); err != nil {
    59  		return ""
    60  	}
    61  	return opStr[op]
    62  }
    63  
    64  // MarshalJSON implements json.Marshal interface.
    65  func (op Operator) MarshalJSON() ([]byte, error) {
    66  	return json.Marshal(op.String())
    67  }
    68  
    69  // UnmarshalJSON implements json.Unmarshaler interface.
    70  func (op *Operator) UnmarshalJSON(b []byte) error {
    71  	var s string
    72  	if err := json.Unmarshal(b, &s); err != nil {
    73  		return &errors.Error{
    74  			Code: errors.EInvalid,
    75  			Err:  err,
    76  		}
    77  	}
    78  	var ok bool
    79  	if *op, ok = opStrMap[s]; !ok {
    80  		return &errors.Error{
    81  			Code: errors.EInvalid,
    82  			Msg:  "unrecognized operator",
    83  		}
    84  	}
    85  	return nil
    86  }
    87  
    88  // Tag is a tag key-value pair.
    89  type Tag struct {
    90  	Key   string `json:"key"`
    91  	Value string `json:"value"`
    92  }
    93  
    94  // NewTag generates a tag pair from a string in the format key:value.
    95  func NewTag(s string) (Tag, error) {
    96  	var tagPair Tag
    97  
    98  	matched, err := regexp.MatchString(`^[a-zA-Z0-9_]+:[a-zA-Z0-9_]+$`, s)
    99  	if !matched || err != nil {
   100  		return tagPair, &errors.Error{
   101  			Code: errors.EInvalid,
   102  			Msg:  `tag must be in form key:value`,
   103  		}
   104  	}
   105  
   106  	tagPair.Key, tagPair.Value, _ = strings.Cut(s, ":")
   107  	return tagPair, nil
   108  }
   109  
   110  // Valid returns an error if the tagpair is missing fields
   111  func (t Tag) Valid() error {
   112  	if t.Key == "" || t.Value == "" {
   113  		return &errors.Error{
   114  			Code: errors.EInvalid,
   115  			Msg:  "tag must contain a key and a value",
   116  		}
   117  	}
   118  	return nil
   119  }
   120  
   121  // QueryParam converts a Tag to a string query parameter
   122  func (t *Tag) QueryParam() string {
   123  	return strings.Join([]string{t.Key, t.Value}, ":")
   124  }
   125  
   126  // TagRule is the struct of tag rule.
   127  type TagRule struct {
   128  	Tag
   129  	Operator Operator `json:"operator"`
   130  }
   131  
   132  // Valid returns error for invalid operators.
   133  func (tr TagRule) Valid() error {
   134  	if err := tr.Tag.Valid(); err != nil {
   135  		return err
   136  	}
   137  
   138  	return tr.Operator.Valid()
   139  }