File: selector.go

package info (click to toggle)
golang-k8s-sigs-kustomize-api 0.19.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 3,732 kB
  • sloc: makefile: 206; sh: 67
file content (124 lines) | stat: -rw-r--r-- 3,365 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package types

import (
	"fmt"
	"regexp"

	"sigs.k8s.io/kustomize/kyaml/resid"
)

// Selector specifies a set of resources.
// Any resource that matches intersection of all conditions
// is included in this set.
type Selector struct {
	// ResId refers to a GVKN/Ns of a resource.
	resid.ResId `json:",inline,omitempty" yaml:",inline,omitempty"`

	// AnnotationSelector is a string that follows the label selection expression
	// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api
	// It matches with the resource annotations.
	AnnotationSelector string `json:"annotationSelector,omitempty" yaml:"annotationSelector,omitempty"`

	// LabelSelector is a string that follows the label selection expression
	// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api
	// It matches with the resource labels.
	LabelSelector string `json:"labelSelector,omitempty" yaml:"labelSelector,omitempty"`
}

func (s *Selector) Copy() Selector {
	return *s
}

func (s *Selector) String() string {
	return fmt.Sprintf(
		"%s:a=%s:l=%s", s.ResId, s.AnnotationSelector, s.LabelSelector)
}

// SelectorRegex is a Selector with regex in GVK
// Any resource that matches intersection of all conditions
// is included in this set.
type SelectorRegex struct {
	selector       *Selector
	groupRegex     *regexp.Regexp
	versionRegex   *regexp.Regexp
	kindRegex      *regexp.Regexp
	nameRegex      *regexp.Regexp
	namespaceRegex *regexp.Regexp
}

// NewSelectorRegex returns a pointer to a new SelectorRegex
// which uses the same condition as s.
func NewSelectorRegex(s *Selector) (*SelectorRegex, error) {
	sr := new(SelectorRegex)
	var err error
	sr.selector = s
	sr.groupRegex, err = regexp.Compile(anchorRegex(s.Gvk.Group))
	if err != nil {
		return nil, err
	}
	sr.versionRegex, err = regexp.Compile(anchorRegex(s.Gvk.Version))
	if err != nil {
		return nil, err
	}
	sr.kindRegex, err = regexp.Compile(anchorRegex(s.Gvk.Kind))
	if err != nil {
		return nil, err
	}
	sr.nameRegex, err = regexp.Compile(anchorRegex(s.Name))
	if err != nil {
		return nil, err
	}
	sr.namespaceRegex, err = regexp.Compile(anchorRegex(s.Namespace))
	if err != nil {
		return nil, err
	}
	return sr, nil
}

func anchorRegex(pattern string) string {
	if pattern == "" {
		return pattern
	}
	return "^(?:" + pattern + ")$"
}

// MatchGvk return true if gvk can be matched by s.
func (s *SelectorRegex) MatchGvk(gvk resid.Gvk) bool {
	if len(s.selector.Gvk.Group) > 0 {
		if !s.groupRegex.MatchString(gvk.Group) {
			return false
		}
	}
	if len(s.selector.Gvk.Version) > 0 {
		if !s.versionRegex.MatchString(gvk.Version) {
			return false
		}
	}
	if len(s.selector.Gvk.Kind) > 0 {
		if !s.kindRegex.MatchString(gvk.Kind) {
			return false
		}
	}
	return true
}

// MatchName returns true if the name in selector is
// empty or the n can be matches by the name in selector
func (s *SelectorRegex) MatchName(n string) bool {
	if s.selector.Name == "" {
		return true
	}
	return s.nameRegex.MatchString(n)
}

// MatchNamespace returns true if the namespace in selector is
// empty or the ns can be matches by the namespace in selector
func (s *SelectorRegex) MatchNamespace(ns string) bool {
	if s.selector.Namespace == "" {
		return true
	}
	return s.namespaceRegex.MatchString(ns)
}