util.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package storage
  14. import (
  15. "fmt"
  16. "strconv"
  17. "strings"
  18. "k8s.io/kubernetes/pkg/api/meta"
  19. "k8s.io/kubernetes/pkg/api/validation"
  20. "k8s.io/kubernetes/pkg/runtime"
  21. "k8s.io/kubernetes/pkg/util/validation/field"
  22. )
  23. type SimpleUpdateFunc func(runtime.Object) (runtime.Object, error)
  24. // SimpleUpdateFunc converts SimpleUpdateFunc into UpdateFunc
  25. func SimpleUpdate(fn SimpleUpdateFunc) UpdateFunc {
  26. return func(input runtime.Object, _ ResponseMeta) (runtime.Object, *uint64, error) {
  27. out, err := fn(input)
  28. return out, nil, err
  29. }
  30. }
  31. // SimpleFilter implements Filter interface.
  32. type SimpleFilter struct {
  33. filterFunc func(runtime.Object) bool
  34. triggerFunc func() []MatchValue
  35. }
  36. func (s *SimpleFilter) Filter(obj runtime.Object) bool {
  37. return s.filterFunc(obj)
  38. }
  39. func (s *SimpleFilter) Trigger() []MatchValue {
  40. return s.triggerFunc()
  41. }
  42. func NewSimpleFilter(
  43. filterFunc func(runtime.Object) bool,
  44. triggerFunc func() []MatchValue) Filter {
  45. return &SimpleFilter{
  46. filterFunc: filterFunc,
  47. triggerFunc: triggerFunc,
  48. }
  49. }
  50. func EverythingFunc(runtime.Object) bool {
  51. return true
  52. }
  53. func NoTriggerFunc() []MatchValue {
  54. return nil
  55. }
  56. func NoTriggerPublisher(runtime.Object) []MatchValue {
  57. return nil
  58. }
  59. // ParseWatchResourceVersion takes a resource version argument and converts it to
  60. // the etcd version we should pass to helper.Watch(). Because resourceVersion is
  61. // an opaque value, the default watch behavior for non-zero watch is to watch
  62. // the next value (if you pass "1", you will see updates from "2" onwards).
  63. func ParseWatchResourceVersion(resourceVersion string) (uint64, error) {
  64. if resourceVersion == "" || resourceVersion == "0" {
  65. return 0, nil
  66. }
  67. version, err := strconv.ParseUint(resourceVersion, 10, 64)
  68. if err != nil {
  69. return 0, NewInvalidError(field.ErrorList{
  70. // Validation errors are supposed to return version-specific field
  71. // paths, but this is probably close enough.
  72. field.Invalid(field.NewPath("resourceVersion"), resourceVersion, err.Error()),
  73. })
  74. }
  75. return version, nil
  76. }
  77. // ParseListResourceVersion takes a resource version argument and converts it to
  78. // the etcd version.
  79. func ParseListResourceVersion(resourceVersion string) (uint64, error) {
  80. if resourceVersion == "" {
  81. return 0, nil
  82. }
  83. version, err := strconv.ParseUint(resourceVersion, 10, 64)
  84. return version, err
  85. }
  86. func NamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) {
  87. meta, err := meta.Accessor(obj)
  88. if err != nil {
  89. return "", err
  90. }
  91. name := meta.GetName()
  92. if msgs := validation.IsValidPathSegmentName(name); len(msgs) != 0 {
  93. return "", fmt.Errorf("invalid name: %v", msgs)
  94. }
  95. return prefix + "/" + meta.GetNamespace() + "/" + name, nil
  96. }
  97. func NoNamespaceKeyFunc(prefix string, obj runtime.Object) (string, error) {
  98. meta, err := meta.Accessor(obj)
  99. if err != nil {
  100. return "", err
  101. }
  102. name := meta.GetName()
  103. if msgs := validation.IsValidPathSegmentName(name); len(msgs) != 0 {
  104. return "", fmt.Errorf("invalid name: %v", msgs)
  105. }
  106. return prefix + "/" + name, nil
  107. }
  108. // hasPathPrefix returns true if the string matches pathPrefix exactly, or if is prefixed with pathPrefix at a path segment boundary
  109. func hasPathPrefix(s, pathPrefix string) bool {
  110. // Short circuit if s doesn't contain the prefix at all
  111. if !strings.HasPrefix(s, pathPrefix) {
  112. return false
  113. }
  114. pathPrefixLength := len(pathPrefix)
  115. if len(s) == pathPrefixLength {
  116. // Exact match
  117. return true
  118. }
  119. if strings.HasSuffix(pathPrefix, "/") {
  120. // pathPrefix already ensured a path segment boundary
  121. return true
  122. }
  123. if s[pathPrefixLength:pathPrefixLength+1] == "/" {
  124. // The next character in s is a path segment boundary
  125. // Check this instead of normalizing pathPrefix to avoid allocating on every call
  126. return true
  127. }
  128. return false
  129. }