Merge pull request #91505 from jpbetz/rv-semantics
Consistent Resource Version Semantics for List
This commit is contained in:
commit
27aca3f7c2
3465
api/openapi-spec/swagger.json
generated
3465
api/openapi-spec/swagger.json
generated
File diff suppressed because it is too large
Load Diff
@ -64,8 +64,9 @@ var _ Leases = &storageLeases{}
|
||||
func (s *storageLeases) ListLeases() ([]string, error) {
|
||||
ipInfoList := &corev1.EndpointsList{}
|
||||
storageOpts := storage.ListOptions{
|
||||
ResourceVersion: "0",
|
||||
Predicate: storage.Everything,
|
||||
ResourceVersion: "0",
|
||||
ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
|
||||
Predicate: storage.Everything,
|
||||
}
|
||||
if err := s.storage.List(apirequest.NewDefaultContext(), s.baseKey, storageOpts, ipInfoList); err != nil {
|
||||
return nil, err
|
||||
|
@ -5,7 +5,8 @@
|
||||
"fieldSelector": "3",
|
||||
"watch": true,
|
||||
"resourceVersion": "4",
|
||||
"timeoutSeconds": 1002466899136229878,
|
||||
"limit": 5339971464584210463,
|
||||
"resourceVersionMatch": "Exact",
|
||||
"timeoutSeconds": 6780787122834727873,
|
||||
"limit": 3549865785210165515,
|
||||
"continue": "5"
|
||||
}
|
Binary file not shown.
@ -3,7 +3,8 @@ continue: "5"
|
||||
fieldSelector: "3"
|
||||
kind: ListOptions
|
||||
labelSelector: "2"
|
||||
limit: 5339971464584210463
|
||||
limit: 3549865785210165515
|
||||
resourceVersion: "4"
|
||||
timeoutSeconds: 1002466899136229878
|
||||
resourceVersionMatch: Exact
|
||||
timeoutSeconds: 6780787122834727873
|
||||
watch: true
|
||||
|
BIN
staging/src/k8s.io/api/testdata/v1.17.0/core.v1.ListOptions.after_roundtrip.pb
vendored
Normal file
BIN
staging/src/k8s.io/api/testdata/v1.17.0/core.v1.ListOptions.after_roundtrip.pb
vendored
Normal file
Binary file not shown.
BIN
staging/src/k8s.io/api/testdata/v1.18.0/core.v1.ListOptions.after_roundtrip.pb
vendored
Normal file
BIN
staging/src/k8s.io/api/testdata/v1.18.0/core.v1.ListOptions.after_roundtrip.pb
vendored
Normal file
Binary file not shown.
@ -1414,7 +1414,7 @@ func schema_pkg_apis_meta_v1_GetOptions(ref common.ReferenceCallback) common.Ope
|
||||
},
|
||||
"resourceVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "When specified: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
Description: "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
@ -1855,7 +1855,14 @@ func schema_pkg_apis_meta_v1_ListOptions(ref common.ReferenceCallback) common.Op
|
||||
},
|
||||
"resourceVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
Description: "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"resourceVersionMatch": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
|
@ -215,6 +215,10 @@ func v1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
j.Finalizers = nil
|
||||
}
|
||||
},
|
||||
func(j *metav1.ResourceVersionMatch, c fuzz.Continue) {
|
||||
matches := []metav1.ResourceVersionMatch{"", metav1.ResourceVersionMatchExact, metav1.ResourceVersionMatchNotOlderThan}
|
||||
*j = matches[c.Rand.Intn(len(matches))]
|
||||
},
|
||||
func(j *metav1.ListMeta, c fuzz.Continue) {
|
||||
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
|
||||
j.SelfLink = c.RandString()
|
||||
|
@ -36,6 +36,7 @@ filegroup(
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme:all-srcs",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/validation:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
@ -44,13 +44,17 @@ type ListOptions struct {
|
||||
// If the feature gate WatchBookmarks is not enabled in apiserver,
|
||||
// this field is ignored.
|
||||
AllowWatchBookmarks bool
|
||||
// When specified with a watch call, shows changes that occur after that particular version of a resource.
|
||||
// Defaults to changes from the beginning of history.
|
||||
// When specified for list:
|
||||
// - if unset, then the result is returned from remote storage based on quorum-read flag;
|
||||
// - if it's 0, then we simply return what we currently have in cache, no guarantee;
|
||||
// - if set to non zero, then the result is at least as fresh as given rv.
|
||||
// resourceVersion sets a constraint on what resource versions a request may be served from.
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for
|
||||
// details.
|
||||
ResourceVersion string
|
||||
// resourceVersionMatch determines how resourceVersion is applied to list calls.
|
||||
// It is highly recommended that resourceVersionMatch be set for list calls where
|
||||
// resourceVersion is set.
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for
|
||||
// details.
|
||||
ResourceVersionMatch metav1.ResourceVersionMatch
|
||||
|
||||
// Timeout for the list/watch call.
|
||||
TimeoutSeconds *int64
|
||||
// Limit specifies the maximum number of results to return from the server. The server may
|
||||
|
@ -0,0 +1,38 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["validation.go"],
|
||||
importmap = "k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion/validation",
|
||||
importpath = "k8s.io/apimachinery/pkg/apis/meta/internalversion/validation",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["validation_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright 2020 The Kubernetes 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 validation
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
// ValidateListOptions returns all validation errors found while validating the ListOptions.
|
||||
func ValidateListOptions(options *internalversion.ListOptions) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if match := options.ResourceVersionMatch; len(match) > 0 {
|
||||
if options.Watch {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("resourceVersionMatch"), "resourceVersionMatch is forbidden for watch"))
|
||||
}
|
||||
if len(options.ResourceVersion) == 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("resourceVersionMatch"), "resourceVersionMatch is forbidden unless resourceVersion is provided"))
|
||||
}
|
||||
if len(options.Continue) > 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("resourceVersionMatch"), "resourceVersionMatch is forbidden when continue is provided"))
|
||||
}
|
||||
if match != metav1.ResourceVersionMatchExact && match != metav1.ResourceVersionMatchNotOlderThan {
|
||||
allErrs = append(allErrs, field.NotSupported(field.NewPath("resourceVersionMatch"), match, []string{string(metav1.ResourceVersionMatchExact), string(metav1.ResourceVersionMatchNotOlderThan), ""}))
|
||||
}
|
||||
if match == metav1.ResourceVersionMatchExact && options.ResourceVersion == "0" {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("resourceVersionMatch"), "resourceVersionMatch \"exact\" is forbidden for resourceVersion \"0\""))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright 2020 The Kubernetes 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 validation
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestValidateListOptions(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
opts internalversion.ListOptions
|
||||
expectError string
|
||||
}{
|
||||
{
|
||||
name: "valid-default",
|
||||
opts: internalversion.ListOptions{},
|
||||
},
|
||||
{
|
||||
name: "valid-resourceversionmatch-exact",
|
||||
opts: internalversion.ListOptions{
|
||||
ResourceVersion: "1",
|
||||
ResourceVersionMatch: metav1.ResourceVersionMatchExact,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid-resourceversionmatch-exact",
|
||||
opts: internalversion.ListOptions{
|
||||
ResourceVersion: "0",
|
||||
ResourceVersionMatch: metav1.ResourceVersionMatchExact,
|
||||
},
|
||||
expectError: "resourceVersionMatch: Forbidden: resourceVersionMatch \"exact\" is forbidden for resourceVersion \"0\"",
|
||||
},
|
||||
{
|
||||
name: "valid-resourceversionmatch-notolderthan",
|
||||
opts: internalversion.ListOptions{
|
||||
ResourceVersion: "0",
|
||||
ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid-resourceversionmatch",
|
||||
opts: internalversion.ListOptions{
|
||||
ResourceVersion: "0",
|
||||
ResourceVersionMatch: "foo",
|
||||
},
|
||||
expectError: "resourceVersionMatch: Unsupported value: \"foo\": supported values: \"Exact\", \"NotOlderThan\", \"\"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
errs := ValidateListOptions(&tc.opts)
|
||||
if tc.expectError != "" {
|
||||
if len(errs) != 1 {
|
||||
t.Errorf("expected an error but got %d errors", len(errs))
|
||||
} else if errs[0].Error() != tc.expectError {
|
||||
t.Errorf("expected error '%s' but got '%s'", tc.expectError, errs[0].Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
if len(errs) != 0 {
|
||||
t.Errorf("expected no errors, but got: %v", errs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -110,6 +110,7 @@ func autoConvert_internalversion_ListOptions_To_v1_ListOptions(in *ListOptions,
|
||||
out.Watch = in.Watch
|
||||
out.AllowWatchBookmarks = in.AllowWatchBookmarks
|
||||
out.ResourceVersion = in.ResourceVersion
|
||||
out.ResourceVersionMatch = v1.ResourceVersionMatch(in.ResourceVersionMatch)
|
||||
out.TimeoutSeconds = (*int64)(unsafe.Pointer(in.TimeoutSeconds))
|
||||
out.Limit = in.Limit
|
||||
out.Continue = in.Continue
|
||||
@ -131,6 +132,7 @@ func autoConvert_v1_ListOptions_To_internalversion_ListOptions(in *v1.ListOption
|
||||
out.Watch = in.Watch
|
||||
out.AllowWatchBookmarks = in.AllowWatchBookmarks
|
||||
out.ResourceVersion = in.ResourceVersion
|
||||
out.ResourceVersionMatch = v1.ResourceVersionMatch(in.ResourceVersionMatch)
|
||||
out.TimeoutSeconds = (*int64)(unsafe.Pointer(in.TimeoutSeconds))
|
||||
out.Limit = in.Limit
|
||||
out.Continue = in.Continue
|
||||
|
@ -345,3 +345,11 @@ func Convert_url_Values_To_v1_DeleteOptions(in *url.Values, out *DeleteOptions,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_Slice_string_To_v1_ResourceVersionMatch allows converting a URL query parameter to ResourceVersionMatch
|
||||
func Convert_Slice_string_To_v1_ResourceVersionMatch(in *[]string, out *ResourceVersionMatch, s conversion.Scope) error {
|
||||
if len(*in) > 0 {
|
||||
*out = ResourceVersionMatch((*in)[0])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1297,177 +1297,179 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_cf52fa777ced5367 = []byte{
|
||||
// 2714 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x19, 0xcd, 0x6f, 0x1b, 0x59,
|
||||
0x3d, 0x63, 0xc7, 0x8e, 0xfd, 0x73, 0x9c, 0x8f, 0x97, 0x16, 0xdc, 0x20, 0xe2, 0xec, 0x2c, 0xaa,
|
||||
0x52, 0xe8, 0x3a, 0x9b, 0x02, 0xab, 0xd2, 0x65, 0x0b, 0x71, 0x9c, 0x74, 0xc3, 0x36, 0x4d, 0xf4,
|
||||
0xd2, 0x16, 0x28, 0x15, 0xea, 0x64, 0xe6, 0xc5, 0x19, 0x32, 0x9e, 0xf1, 0xbe, 0x19, 0x27, 0x35,
|
||||
0x1c, 0xd8, 0x03, 0x08, 0x90, 0x60, 0xd5, 0x23, 0xe2, 0x80, 0xb6, 0x82, 0xbf, 0x80, 0x13, 0x7f,
|
||||
0x00, 0x12, 0xbd, 0x20, 0xad, 0xc4, 0x65, 0x25, 0x90, 0xb5, 0x0d, 0x07, 0x8e, 0x88, 0x6b, 0x4e,
|
||||
0xe8, 0x7d, 0xcd, 0x87, 0x1d, 0x37, 0x63, 0xba, 0xac, 0xb8, 0x79, 0x7e, 0xdf, 0xbf, 0xf7, 0x7e,
|
||||
0xef, 0xf7, 0x65, 0xd8, 0x3a, 0xbc, 0xee, 0xd7, 0x6c, 0x6f, 0xf9, 0xb0, 0xb3, 0x47, 0xa8, 0x4b,
|
||||
0x02, 0xe2, 0x2f, 0x1f, 0x11, 0xd7, 0xf2, 0xe8, 0xb2, 0x44, 0x18, 0x6d, 0xbb, 0x65, 0x98, 0x07,
|
||||
0xb6, 0x4b, 0x68, 0x77, 0xb9, 0x7d, 0xd8, 0x64, 0x00, 0x7f, 0xb9, 0x45, 0x02, 0x63, 0xf9, 0x68,
|
||||
0x65, 0xb9, 0x49, 0x5c, 0x42, 0x8d, 0x80, 0x58, 0xb5, 0x36, 0xf5, 0x02, 0x0f, 0x7d, 0x41, 0x70,
|
||||
0xd5, 0xe2, 0x5c, 0xb5, 0xf6, 0x61, 0x93, 0x01, 0xfc, 0x1a, 0xe3, 0xaa, 0x1d, 0xad, 0xcc, 0xbf,
|
||||
0xd6, 0xb4, 0x83, 0x83, 0xce, 0x5e, 0xcd, 0xf4, 0x5a, 0xcb, 0x4d, 0xaf, 0xe9, 0x2d, 0x73, 0xe6,
|
||||
0xbd, 0xce, 0x3e, 0xff, 0xe2, 0x1f, 0xfc, 0x97, 0x10, 0x3a, 0x3f, 0xd4, 0x14, 0xda, 0x71, 0x03,
|
||||
0xbb, 0x45, 0xfa, 0xad, 0x98, 0x7f, 0xe3, 0x3c, 0x06, 0xdf, 0x3c, 0x20, 0x2d, 0xa3, 0x9f, 0x4f,
|
||||
0xff, 0x73, 0x16, 0x0a, 0xab, 0x3b, 0x9b, 0xb7, 0xa8, 0xd7, 0x69, 0xa3, 0x45, 0x18, 0x77, 0x8d,
|
||||
0x16, 0xa9, 0x68, 0x8b, 0xda, 0x52, 0xb1, 0x3e, 0xf9, 0xac, 0x57, 0x1d, 0x3b, 0xe9, 0x55, 0xc7,
|
||||
0xef, 0x18, 0x2d, 0x82, 0x39, 0x06, 0x39, 0x50, 0x38, 0x22, 0xd4, 0xb7, 0x3d, 0xd7, 0xaf, 0x64,
|
||||
0x16, 0xb3, 0x4b, 0xa5, 0x6b, 0x37, 0x6b, 0x69, 0xfc, 0xaf, 0x71, 0x05, 0xf7, 0x05, 0xeb, 0x86,
|
||||
0x47, 0x1b, 0xb6, 0x6f, 0x7a, 0x47, 0x84, 0x76, 0xeb, 0x33, 0x52, 0x4b, 0x41, 0x22, 0x7d, 0x1c,
|
||||
0x6a, 0x40, 0x3f, 0xd1, 0x60, 0xa6, 0x4d, 0xc9, 0x3e, 0xa1, 0x94, 0x58, 0x12, 0x5f, 0xc9, 0x2e,
|
||||
0x6a, 0x9f, 0x80, 0xda, 0x8a, 0x54, 0x3b, 0xb3, 0xd3, 0x27, 0x1f, 0x0f, 0x68, 0x44, 0xbf, 0xd3,
|
||||
0x60, 0xde, 0x27, 0xf4, 0x88, 0xd0, 0x55, 0xcb, 0xa2, 0xc4, 0xf7, 0xeb, 0xdd, 0x35, 0xc7, 0x26,
|
||||
0x6e, 0xb0, 0xb6, 0xd9, 0xc0, 0x7e, 0x65, 0x9c, 0x9f, 0xc3, 0x37, 0xd2, 0x19, 0xb4, 0x3b, 0x4c,
|
||||
0x4e, 0x5d, 0x97, 0x16, 0xcd, 0x0f, 0x25, 0xf1, 0xf1, 0x0b, 0xcc, 0xd0, 0xf7, 0x61, 0x52, 0x5d,
|
||||
0xe4, 0x6d, 0xdb, 0x0f, 0xd0, 0x7d, 0xc8, 0x37, 0xd9, 0x87, 0x5f, 0xd1, 0xb8, 0x81, 0xb5, 0x74,
|
||||
0x06, 0x2a, 0x19, 0xf5, 0x29, 0x69, 0x4f, 0x9e, 0x7f, 0xfa, 0x58, 0x4a, 0xd3, 0x7f, 0x31, 0x0e,
|
||||
0xa5, 0xd5, 0x9d, 0x4d, 0x4c, 0x7c, 0xaf, 0x43, 0x4d, 0x92, 0x22, 0x68, 0xae, 0xc3, 0xa4, 0x6f,
|
||||
0xbb, 0xcd, 0x8e, 0x63, 0x50, 0x06, 0xad, 0xe4, 0x39, 0xe5, 0x05, 0x49, 0x39, 0xb9, 0x1b, 0xc3,
|
||||
0xe1, 0x04, 0x25, 0xba, 0x06, 0xc0, 0x24, 0xf8, 0x6d, 0xc3, 0x24, 0x56, 0x25, 0xb3, 0xa8, 0x2d,
|
||||
0x15, 0xea, 0x48, 0xf2, 0xc1, 0x9d, 0x10, 0x83, 0x63, 0x54, 0xe8, 0x55, 0xc8, 0x71, 0x4b, 0x2b,
|
||||
0x05, 0xae, 0xa6, 0x2c, 0xc9, 0x73, 0xdc, 0x0d, 0x2c, 0x70, 0xe8, 0x0a, 0x4c, 0xc8, 0x28, 0xab,
|
||||
0x14, 0x39, 0xd9, 0xb4, 0x24, 0x9b, 0x50, 0x61, 0xa0, 0xf0, 0xcc, 0xbf, 0x43, 0xdb, 0xb5, 0x78,
|
||||
0xdc, 0xc5, 0xfc, 0x7b, 0xc7, 0x76, 0x2d, 0xcc, 0x31, 0xe8, 0x36, 0xe4, 0x8e, 0x08, 0xdd, 0x63,
|
||||
0x91, 0xc0, 0x42, 0xf3, 0x4b, 0xe9, 0x0e, 0xfa, 0x3e, 0x63, 0xa9, 0x17, 0x99, 0x69, 0xfc, 0x27,
|
||||
0x16, 0x42, 0x50, 0x0d, 0xc0, 0x3f, 0xf0, 0x68, 0xc0, 0xdd, 0xab, 0xe4, 0x16, 0xb3, 0x4b, 0xc5,
|
||||
0xfa, 0x14, 0xf3, 0x77, 0x37, 0x84, 0xe2, 0x18, 0x05, 0xa3, 0x37, 0x8d, 0x80, 0x34, 0x3d, 0x6a,
|
||||
0x13, 0xbf, 0x32, 0x11, 0xd1, 0xaf, 0x85, 0x50, 0x1c, 0xa3, 0x40, 0xdf, 0x02, 0xe4, 0x07, 0x1e,
|
||||
0x35, 0x9a, 0x44, 0xba, 0xfa, 0xb6, 0xe1, 0x1f, 0x54, 0x80, 0x7b, 0x37, 0x2f, 0xbd, 0x43, 0xbb,
|
||||
0x03, 0x14, 0xf8, 0x0c, 0x2e, 0xfd, 0x0f, 0x1a, 0x4c, 0xc7, 0x62, 0x81, 0xc7, 0xdd, 0x75, 0x98,
|
||||
0x6c, 0xc6, 0x5e, 0x9d, 0x8c, 0x8b, 0xf0, 0xb6, 0xe3, 0x2f, 0x12, 0x27, 0x28, 0x11, 0x81, 0x22,
|
||||
0x95, 0x92, 0x54, 0x76, 0x59, 0x49, 0x1d, 0xb4, 0xca, 0x86, 0x48, 0x53, 0x0c, 0xe8, 0xe3, 0x48,
|
||||
0xb2, 0xfe, 0x4f, 0x8d, 0x07, 0xb0, 0xca, 0x37, 0x68, 0x29, 0x96, 0xd3, 0x34, 0x7e, 0x7c, 0x93,
|
||||
0x43, 0xf2, 0xd1, 0x39, 0x89, 0x20, 0xf3, 0x7f, 0x91, 0x08, 0x6e, 0x14, 0x7e, 0xfd, 0x41, 0x75,
|
||||
0xec, 0xbd, 0xbf, 0x2f, 0x8e, 0xe9, 0x2d, 0x28, 0xaf, 0x51, 0x62, 0x04, 0x64, 0xbb, 0x1d, 0x70,
|
||||
0x07, 0x74, 0xc8, 0x5b, 0xb4, 0x8b, 0x3b, 0xae, 0x74, 0x14, 0xd8, 0xfb, 0x6e, 0x70, 0x08, 0x96,
|
||||
0x18, 0x76, 0x7f, 0xfb, 0x36, 0x71, 0xac, 0x2d, 0xc3, 0x35, 0x9a, 0x84, 0xca, 0xb8, 0x0f, 0x4f,
|
||||
0x75, 0x23, 0x86, 0xc3, 0x09, 0x4a, 0xfd, 0x67, 0x59, 0x28, 0x37, 0x88, 0x43, 0x22, 0x7d, 0x1b,
|
||||
0x80, 0x9a, 0xd4, 0x30, 0xc9, 0x0e, 0xa1, 0xb6, 0x67, 0xed, 0x12, 0xd3, 0x73, 0x2d, 0x9f, 0x47,
|
||||
0x44, 0xb6, 0xfe, 0x19, 0x16, 0x67, 0xb7, 0x06, 0xb0, 0xf8, 0x0c, 0x0e, 0xe4, 0x40, 0xb9, 0x4d,
|
||||
0xf9, 0x6f, 0x3b, 0x90, 0xb5, 0x87, 0xbd, 0xb4, 0x2f, 0xa7, 0x3b, 0xea, 0x9d, 0x38, 0x6b, 0x7d,
|
||||
0xf6, 0xa4, 0x57, 0x2d, 0x27, 0x40, 0x38, 0x29, 0x1c, 0x7d, 0x13, 0x66, 0x3c, 0xda, 0x3e, 0x30,
|
||||
0xdc, 0x06, 0x69, 0x13, 0xd7, 0x22, 0x6e, 0xe0, 0xf3, 0x53, 0x28, 0xd4, 0x2f, 0xb0, 0x8a, 0xb1,
|
||||
0xdd, 0x87, 0xc3, 0x03, 0xd4, 0xe8, 0x01, 0xcc, 0xb6, 0xa9, 0xd7, 0x36, 0x9a, 0x06, 0x93, 0xb8,
|
||||
0xe3, 0x39, 0xb6, 0xd9, 0xe5, 0xd9, 0xa1, 0x58, 0xbf, 0x7a, 0xd2, 0xab, 0xce, 0xee, 0xf4, 0x23,
|
||||
0x4f, 0x7b, 0xd5, 0x39, 0x7e, 0x74, 0x0c, 0x12, 0x21, 0xf1, 0xa0, 0x98, 0xd8, 0x1d, 0xe6, 0x86,
|
||||
0xdd, 0xa1, 0xbe, 0x09, 0x85, 0x46, 0x87, 0x72, 0x2e, 0xf4, 0x16, 0x14, 0x2c, 0xf9, 0x5b, 0x9e,
|
||||
0xfc, 0x2b, 0xaa, 0xe4, 0x2a, 0x9a, 0xd3, 0x5e, 0xb5, 0xcc, 0x9a, 0x84, 0x9a, 0x02, 0xe0, 0x90,
|
||||
0x45, 0x7f, 0x08, 0xe5, 0xf5, 0xc7, 0x6d, 0x8f, 0x06, 0xea, 0x4e, 0x2f, 0x43, 0x9e, 0x70, 0x00,
|
||||
0x97, 0x56, 0x88, 0xea, 0x84, 0x20, 0xc3, 0x12, 0xcb, 0xf2, 0x30, 0x79, 0x6c, 0x98, 0x81, 0x4c,
|
||||
0xdb, 0x61, 0x1e, 0x5e, 0x67, 0x40, 0x2c, 0x70, 0xfa, 0x65, 0x28, 0xf0, 0x80, 0xf2, 0xef, 0xaf,
|
||||
0xa0, 0x19, 0xc8, 0x62, 0xe3, 0x98, 0x4b, 0x9d, 0xc4, 0x59, 0x6a, 0x1c, 0xc7, 0x22, 0x79, 0x1b,
|
||||
0xe0, 0x16, 0x09, 0x4d, 0x58, 0x85, 0x69, 0xf5, 0x9c, 0x93, 0x59, 0xe6, 0xb3, 0x52, 0xc9, 0x34,
|
||||
0x4e, 0xa2, 0x71, 0x3f, 0xbd, 0xfe, 0x10, 0x8a, 0x3c, 0x13, 0xb1, 0x34, 0x1e, 0x95, 0x0c, 0xed,
|
||||
0x05, 0x25, 0x43, 0xd5, 0x81, 0xcc, 0xb0, 0x3a, 0x10, 0x33, 0xd7, 0x81, 0xb2, 0xe0, 0x55, 0x45,
|
||||
0x32, 0x95, 0x86, 0xab, 0x50, 0x50, 0x66, 0x4a, 0x2d, 0x61, 0x73, 0xa4, 0x04, 0xe1, 0x90, 0x22,
|
||||
0xa6, 0xed, 0x00, 0x12, 0x59, 0x35, 0x9d, 0xb2, 0x58, 0x05, 0xcc, 0xbc, 0xb8, 0x02, 0xc6, 0x34,
|
||||
0xfd, 0x18, 0x2a, 0xc3, 0x3a, 0xaa, 0x97, 0xc8, 0xfb, 0xe9, 0x4d, 0xd1, 0xdf, 0xd7, 0x60, 0x26,
|
||||
0x2e, 0x29, 0xfd, 0xf5, 0xa5, 0x57, 0x72, 0x7e, 0xc5, 0x8f, 0x9d, 0xc8, 0x6f, 0x35, 0xb8, 0x90,
|
||||
0x70, 0x6d, 0xa4, 0x1b, 0x1f, 0xc1, 0xa8, 0x78, 0x70, 0x64, 0x47, 0x08, 0x8e, 0xbf, 0x66, 0xa0,
|
||||
0x7c, 0xdb, 0xd8, 0x23, 0xce, 0x2e, 0x71, 0x88, 0x19, 0x78, 0x14, 0xfd, 0x08, 0x4a, 0x2d, 0x23,
|
||||
0x30, 0x0f, 0x38, 0x54, 0x75, 0x87, 0x8d, 0x74, 0xa9, 0x34, 0x21, 0xa9, 0xb6, 0x15, 0x89, 0x59,
|
||||
0x77, 0x03, 0xda, 0xad, 0xcf, 0x49, 0x93, 0x4a, 0x31, 0x0c, 0x8e, 0x6b, 0xe3, 0x2d, 0x3d, 0xff,
|
||||
0x5e, 0x7f, 0xdc, 0x66, 0xa5, 0x6b, 0xf4, 0x49, 0x22, 0x61, 0x02, 0x26, 0xef, 0x76, 0x6c, 0x4a,
|
||||
0x5a, 0xc4, 0x0d, 0xa2, 0x96, 0x7e, 0xab, 0x4f, 0x3e, 0x1e, 0xd0, 0x38, 0x7f, 0x13, 0x66, 0xfa,
|
||||
0x8d, 0x67, 0xf9, 0xe7, 0x90, 0x74, 0xc5, 0x7d, 0x61, 0xf6, 0x13, 0x5d, 0x80, 0xdc, 0x91, 0xe1,
|
||||
0x74, 0xe4, 0x6b, 0xc4, 0xe2, 0xe3, 0x46, 0xe6, 0xba, 0xa6, 0xff, 0x5e, 0x83, 0xca, 0x30, 0x43,
|
||||
0xd0, 0xe7, 0x63, 0x82, 0xea, 0x25, 0x69, 0x55, 0xf6, 0x1d, 0xd2, 0x15, 0x52, 0xd7, 0xa1, 0xe0,
|
||||
0xb5, 0xd9, 0x10, 0xe6, 0x51, 0x79, 0xeb, 0x57, 0xd4, 0x4d, 0x6e, 0x4b, 0xf8, 0x69, 0xaf, 0x7a,
|
||||
0x31, 0x21, 0x5e, 0x21, 0x70, 0xc8, 0xca, 0xea, 0x00, 0xb7, 0x87, 0xd5, 0xa6, 0xb0, 0x0e, 0xdc,
|
||||
0xe7, 0x10, 0x2c, 0x31, 0xfa, 0x1f, 0x35, 0x18, 0xe7, 0x4d, 0xd9, 0x43, 0x28, 0xb0, 0xf3, 0xb3,
|
||||
0x8c, 0xc0, 0xe0, 0x76, 0xa5, 0x1e, 0x07, 0x18, 0xf7, 0x16, 0x09, 0x8c, 0x28, 0xda, 0x14, 0x04,
|
||||
0x87, 0x12, 0x11, 0x86, 0x9c, 0x1d, 0x90, 0x96, 0xba, 0xc8, 0xd7, 0x86, 0x8a, 0x96, 0xc3, 0x68,
|
||||
0x0d, 0x1b, 0xc7, 0xeb, 0x8f, 0x03, 0xe2, 0xb2, 0xcb, 0x88, 0x9e, 0xc6, 0x26, 0x93, 0x81, 0x85,
|
||||
0x28, 0xfd, 0xdf, 0x1a, 0x84, 0xaa, 0x58, 0xf0, 0xfb, 0xc4, 0xd9, 0xbf, 0x6d, 0xbb, 0x87, 0xf2,
|
||||
0x58, 0x43, 0x73, 0x76, 0x25, 0x1c, 0x87, 0x14, 0x67, 0x95, 0x87, 0xcc, 0x68, 0xe5, 0x81, 0x29,
|
||||
0x34, 0x3d, 0x37, 0xb0, 0xdd, 0xce, 0xc0, 0x6b, 0x5b, 0x93, 0x70, 0x1c, 0x52, 0xb0, 0x36, 0x87,
|
||||
0x92, 0x96, 0x61, 0xbb, 0xb6, 0xdb, 0x64, 0x4e, 0xac, 0x79, 0x1d, 0x37, 0xe0, 0xf5, 0x5e, 0xb6,
|
||||
0x39, 0x78, 0x00, 0x8b, 0xcf, 0xe0, 0xd0, 0xff, 0x92, 0x85, 0x12, 0xf3, 0x59, 0xd5, 0xb9, 0x37,
|
||||
0xa1, 0xec, 0xc4, 0xa3, 0x40, 0xfa, 0x7e, 0x51, 0x9a, 0x92, 0x7c, 0xd7, 0x38, 0x49, 0xcb, 0x98,
|
||||
0x79, 0x77, 0x16, 0x32, 0x67, 0x92, 0xcc, 0x1b, 0x71, 0x24, 0x4e, 0xd2, 0xb2, 0xec, 0x75, 0xcc,
|
||||
0xde, 0x87, 0xec, 0x7b, 0xc2, 0x2b, 0xfa, 0x36, 0x03, 0x62, 0x81, 0x43, 0x5b, 0x30, 0x67, 0x38,
|
||||
0x8e, 0x77, 0xcc, 0x81, 0x75, 0xcf, 0x3b, 0x6c, 0x19, 0xf4, 0xd0, 0xe7, 0x03, 0x55, 0xa1, 0xfe,
|
||||
0x39, 0xc9, 0x32, 0xb7, 0x3a, 0x48, 0x82, 0xcf, 0xe2, 0x3b, 0xeb, 0xda, 0xc6, 0x47, 0xbc, 0xb6,
|
||||
0x1b, 0x30, 0xc5, 0xe2, 0xcb, 0xeb, 0x04, 0xaa, 0xd7, 0xcc, 0xf1, 0x4b, 0x40, 0x27, 0xbd, 0xea,
|
||||
0xd4, 0xdd, 0x04, 0x06, 0xf7, 0x51, 0x32, 0x97, 0x1d, 0xbb, 0x65, 0x07, 0x95, 0x09, 0xce, 0x12,
|
||||
0xba, 0x7c, 0x9b, 0x01, 0xb1, 0xc0, 0x25, 0xe2, 0xa2, 0x70, 0x5e, 0x5c, 0xe8, 0xbf, 0xc9, 0x02,
|
||||
0x12, 0xcd, 0xb1, 0x25, 0xba, 0x1c, 0x91, 0x68, 0xae, 0xc0, 0x44, 0x4b, 0x36, 0xd7, 0x5a, 0x32,
|
||||
0xeb, 0xab, 0xbe, 0x5a, 0xe1, 0xd1, 0x16, 0x14, 0xc5, 0x83, 0x8f, 0x82, 0x78, 0x59, 0x12, 0x17,
|
||||
0xb7, 0x15, 0xe2, 0xb4, 0x57, 0x9d, 0x4f, 0xa8, 0x09, 0x31, 0x77, 0xbb, 0x6d, 0x82, 0x23, 0x09,
|
||||
0x6c, 0x9e, 0x36, 0xda, 0x76, 0x7c, 0x93, 0x52, 0x8c, 0xe6, 0xe9, 0x68, 0x26, 0xc2, 0x31, 0x2a,
|
||||
0xf4, 0x36, 0x8c, 0xb3, 0x93, 0x92, 0xc3, 0xed, 0x17, 0xd3, 0xa5, 0x0d, 0x76, 0xd6, 0xf5, 0x02,
|
||||
0xab, 0x9a, 0xec, 0x17, 0xe6, 0x12, 0x98, 0x76, 0x1e, 0x65, 0x3e, 0x33, 0x4b, 0x6e, 0x01, 0x42,
|
||||
0xed, 0x1b, 0x21, 0x06, 0xc7, 0xa8, 0xd0, 0x77, 0xa0, 0xb0, 0x2f, 0x1b, 0x44, 0x7e, 0x31, 0xa9,
|
||||
0x13, 0x97, 0x6a, 0x2b, 0xc5, 0x30, 0xa7, 0xbe, 0x70, 0x28, 0x4d, 0x7f, 0x17, 0x8a, 0x5b, 0xb6,
|
||||
0x49, 0x3d, 0x66, 0x20, 0xbb, 0x12, 0x3f, 0x31, 0x9d, 0x84, 0x57, 0xa2, 0xc2, 0x45, 0xe1, 0x59,
|
||||
0x9c, 0xb8, 0x86, 0xeb, 0x89, 0x19, 0x24, 0x17, 0xc5, 0xc9, 0x1d, 0x06, 0xc4, 0x02, 0x77, 0xe3,
|
||||
0x02, 0xab, 0xbf, 0x3f, 0x7f, 0x5a, 0x1d, 0x7b, 0xf2, 0xb4, 0x3a, 0xf6, 0xc1, 0x53, 0x59, 0x8b,
|
||||
0x4f, 0x01, 0x60, 0x7b, 0xef, 0x07, 0xc4, 0x14, 0x59, 0x2d, 0xd5, 0xe6, 0x44, 0x2d, 0xec, 0xf8,
|
||||
0xe6, 0x24, 0xd3, 0xd7, 0x53, 0xc5, 0x70, 0x38, 0x41, 0x89, 0x96, 0xa1, 0x18, 0xee, 0x44, 0xe4,
|
||||
0x45, 0xcf, 0xaa, 0xc0, 0x09, 0x17, 0x27, 0x38, 0xa2, 0x49, 0xa4, 0xd8, 0xf1, 0x73, 0x53, 0x6c,
|
||||
0x1d, 0xb2, 0x1d, 0xdb, 0xe2, 0xaf, 0xab, 0x58, 0x7f, 0x5d, 0x95, 0xb8, 0x7b, 0x9b, 0x8d, 0xd3,
|
||||
0x5e, 0xf5, 0x95, 0x61, 0xab, 0xc8, 0xa0, 0xdb, 0x26, 0x7e, 0xed, 0xde, 0x66, 0x03, 0x33, 0xe6,
|
||||
0xb3, 0xde, 0x7b, 0x7e, 0xc4, 0xf7, 0x7e, 0x0d, 0x40, 0x7a, 0xcd, 0xb8, 0xc5, 0xc3, 0x0d, 0x23,
|
||||
0xea, 0x56, 0x88, 0xc1, 0x31, 0x2a, 0xe4, 0xc3, 0xac, 0xc9, 0x86, 0x62, 0xf6, 0x3c, 0xec, 0x16,
|
||||
0xf1, 0x03, 0xa3, 0x25, 0x76, 0x45, 0xa3, 0x05, 0xf7, 0x25, 0xa9, 0x66, 0x76, 0xad, 0x5f, 0x18,
|
||||
0x1e, 0x94, 0x8f, 0x3c, 0x98, 0xb5, 0xe4, 0x78, 0x17, 0x29, 0x2d, 0x8e, 0xac, 0xf4, 0x22, 0x53,
|
||||
0xd8, 0xe8, 0x17, 0x84, 0x07, 0x65, 0xa3, 0xef, 0xc3, 0xbc, 0x02, 0x0e, 0xce, 0xd8, 0x7c, 0xdb,
|
||||
0x93, 0xad, 0x2f, 0x9c, 0xf4, 0xaa, 0xf3, 0x8d, 0xa1, 0x54, 0xf8, 0x05, 0x12, 0x90, 0x05, 0x79,
|
||||
0x47, 0xf4, 0x8f, 0x25, 0x5e, 0xf3, 0xbf, 0x9e, 0xce, 0x8b, 0x28, 0xfa, 0x6b, 0xf1, 0xbe, 0x31,
|
||||
0x9c, 0x21, 0x65, 0xcb, 0x28, 0x65, 0xa3, 0xc7, 0x50, 0x32, 0x5c, 0xd7, 0x0b, 0x0c, 0x31, 0xf5,
|
||||
0x4f, 0x72, 0x55, 0xab, 0x23, 0xab, 0x5a, 0x8d, 0x64, 0xf4, 0xf5, 0xa9, 0x31, 0x0c, 0x8e, 0xab,
|
||||
0x42, 0xc7, 0x30, 0xed, 0x1d, 0xbb, 0x84, 0x62, 0xb2, 0x4f, 0x28, 0x71, 0x4d, 0xe2, 0x57, 0xca,
|
||||
0x5c, 0xfb, 0x57, 0x52, 0x6a, 0x4f, 0x30, 0x47, 0x21, 0x9d, 0x84, 0xfb, 0xb8, 0x5f, 0x0b, 0xaa,
|
||||
0xb1, 0x24, 0xe9, 0x1a, 0x8e, 0xfd, 0x43, 0x42, 0xfd, 0xca, 0x54, 0xb4, 0xce, 0xdb, 0x08, 0xa1,
|
||||
0x38, 0x46, 0x81, 0xbe, 0x0a, 0x25, 0xd3, 0xe9, 0xf8, 0x01, 0x11, 0xbb, 0xd5, 0x69, 0xfe, 0x82,
|
||||
0x42, 0xff, 0xd6, 0x22, 0x14, 0x8e, 0xd3, 0xa1, 0x0e, 0x94, 0x5b, 0xf1, 0x92, 0x51, 0x99, 0xe5,
|
||||
0xde, 0x5d, 0x4f, 0xe7, 0xdd, 0x60, 0x51, 0x8b, 0xfa, 0x8a, 0x04, 0x0e, 0x27, 0xb5, 0xcc, 0x7f,
|
||||
0x0d, 0x4a, 0xff, 0x65, 0xcb, 0xcd, 0x5a, 0xf6, 0xfe, 0x7b, 0x1c, 0xa9, 0x65, 0xff, 0x53, 0x06,
|
||||
0xa6, 0x92, 0xa7, 0xdf, 0x57, 0x0e, 0x73, 0xa9, 0xca, 0xa1, 0x1a, 0x0e, 0xb5, 0xa1, 0xeb, 0x60,
|
||||
0x95, 0xd6, 0xb3, 0x43, 0xd3, 0xba, 0xcc, 0x9e, 0xe3, 0x2f, 0x93, 0x3d, 0x6b, 0x00, 0xac, 0xcf,
|
||||
0xa0, 0x9e, 0xe3, 0x10, 0xca, 0x13, 0x67, 0x41, 0xae, 0x7d, 0x43, 0x28, 0x8e, 0x51, 0xb0, 0x1e,
|
||||
0x75, 0xcf, 0xf1, 0xcc, 0x43, 0x7e, 0x04, 0xea, 0xd1, 0xf3, 0x94, 0x59, 0x10, 0x3d, 0x6a, 0x7d,
|
||||
0x00, 0x8b, 0xcf, 0xe0, 0xd0, 0xbb, 0x70, 0x71, 0xc7, 0xa0, 0x81, 0x6d, 0x38, 0xd1, 0x03, 0xe3,
|
||||
0x43, 0xc0, 0xa3, 0x81, 0x11, 0xe3, 0xf5, 0x51, 0x1f, 0x6a, 0x74, 0xf8, 0x11, 0x2c, 0x1a, 0x33,
|
||||
0xf4, 0xbf, 0x69, 0x70, 0xe9, 0x4c, 0xdd, 0x9f, 0xc2, 0x88, 0xf3, 0x28, 0x39, 0xe2, 0xbc, 0x99,
|
||||
0x72, 0xf3, 0x78, 0x96, 0xb5, 0x43, 0x06, 0x9e, 0x09, 0xc8, 0xed, 0xb0, 0x86, 0x58, 0xff, 0x95,
|
||||
0x06, 0x93, 0xfc, 0xd7, 0x28, 0x5b, 0xdb, 0x2a, 0xe4, 0xf6, 0x3d, 0xb5, 0x38, 0x2a, 0x88, 0xbf,
|
||||
0x15, 0x36, 0x18, 0x00, 0x0b, 0xf8, 0x4b, 0xac, 0x75, 0xdf, 0xd7, 0x20, 0xb9, 0x2f, 0x45, 0x37,
|
||||
0x45, 0xfc, 0x6a, 0xe1, 0x42, 0x73, 0xc4, 0xd8, 0x7d, 0x6b, 0xd8, 0x80, 0x36, 0x97, 0x6a, 0x77,
|
||||
0x77, 0x15, 0x8a, 0xd8, 0xf3, 0x82, 0x1d, 0x23, 0x38, 0xf0, 0x99, 0xe3, 0x6d, 0xf6, 0x43, 0x9e,
|
||||
0x0d, 0x77, 0x9c, 0x63, 0xb0, 0x80, 0xeb, 0xbf, 0xd4, 0xe0, 0xd2, 0xd0, 0x4d, 0x3a, 0x4b, 0x01,
|
||||
0x66, 0xf8, 0x25, 0x3d, 0x0a, 0xa3, 0x30, 0xa2, 0xc3, 0x31, 0x2a, 0x36, 0x59, 0x25, 0xd6, 0xef,
|
||||
0xfd, 0x93, 0x55, 0x42, 0x1b, 0x4e, 0xd2, 0xea, 0xff, 0xca, 0x40, 0x7e, 0x37, 0x30, 0x82, 0x8e,
|
||||
0xff, 0x3f, 0x8e, 0xd8, 0xcb, 0x90, 0xf7, 0xb9, 0x1e, 0x69, 0x5e, 0x58, 0x63, 0x85, 0x76, 0x2c,
|
||||
0xb1, 0x7c, 0x1a, 0x21, 0xbe, 0x6f, 0x34, 0x55, 0xc6, 0x8a, 0xa6, 0x11, 0x01, 0xc6, 0x0a, 0x8f,
|
||||
0xde, 0x80, 0x3c, 0x25, 0x86, 0x1f, 0x0e, 0x66, 0x0b, 0x4a, 0x24, 0xe6, 0xd0, 0xd3, 0x5e, 0x75,
|
||||
0x52, 0x0a, 0xe7, 0xdf, 0x58, 0x52, 0xa3, 0x07, 0x30, 0x61, 0x91, 0xc0, 0xb0, 0x1d, 0x31, 0x8f,
|
||||
0xa5, 0x5e, 0xdc, 0x0b, 0x61, 0x0d, 0xc1, 0x5a, 0x2f, 0x31, 0x9b, 0xe4, 0x07, 0x56, 0x02, 0x59,
|
||||
0xb6, 0x35, 0x3d, 0x4b, 0x8c, 0x13, 0xb9, 0x28, 0xdb, 0xae, 0x79, 0x16, 0xc1, 0x1c, 0xa3, 0x3f,
|
||||
0xd1, 0xa0, 0x24, 0x24, 0xad, 0x19, 0x1d, 0x9f, 0xa0, 0x95, 0xd0, 0x0b, 0x71, 0xdd, 0xaa, 0x93,
|
||||
0x1b, 0x67, 0x03, 0xc7, 0x69, 0xaf, 0x5a, 0xe4, 0x64, 0x7c, 0x12, 0x51, 0x0e, 0xc4, 0xce, 0x28,
|
||||
0x73, 0xce, 0x19, 0xbd, 0x0a, 0x39, 0xfe, 0x7a, 0xe4, 0x61, 0x86, 0x6f, 0x9d, 0x3f, 0x30, 0x2c,
|
||||
0x70, 0xfa, 0xc7, 0x19, 0x28, 0x27, 0x9c, 0x4b, 0x31, 0x0b, 0x84, 0x0b, 0xc5, 0x4c, 0x8a, 0x25,
|
||||
0xf5, 0xf0, 0x3f, 0x2b, 0x65, 0xed, 0xc9, 0xbf, 0x4c, 0xed, 0xf9, 0x2e, 0xe4, 0x4d, 0x76, 0x46,
|
||||
0xea, 0xbf, 0xef, 0x95, 0x51, 0xae, 0x93, 0x9f, 0x6e, 0x14, 0x8d, 0xfc, 0xd3, 0xc7, 0x52, 0x20,
|
||||
0xba, 0x05, 0xb3, 0x94, 0x04, 0xb4, 0xbb, 0xba, 0x1f, 0x10, 0x1a, 0x1f, 0xe2, 0x73, 0x51, 0xc7,
|
||||
0x8d, 0xfb, 0x09, 0xf0, 0x20, 0x8f, 0xbe, 0x07, 0x93, 0x77, 0x8d, 0x3d, 0x27, 0xfc, 0x2b, 0x0a,
|
||||
0x43, 0xd9, 0x76, 0x4d, 0xa7, 0x63, 0x11, 0x91, 0x8d, 0x55, 0xf6, 0x52, 0x8f, 0x76, 0x33, 0x8e,
|
||||
0x3c, 0xed, 0x55, 0xe7, 0x12, 0x00, 0xf1, 0xdf, 0x0b, 0x4e, 0x8a, 0xd0, 0x1d, 0x18, 0xff, 0x14,
|
||||
0xa7, 0xc7, 0xef, 0x41, 0x31, 0xea, 0xef, 0x3f, 0x61, 0x95, 0xfa, 0x23, 0x28, 0xb0, 0x88, 0x57,
|
||||
0x73, 0xe9, 0x39, 0x2d, 0x4e, 0xb2, 0x71, 0xca, 0xa4, 0x69, 0x9c, 0xf4, 0x16, 0x94, 0xef, 0xb5,
|
||||
0xad, 0x97, 0xfc, 0x33, 0x32, 0x93, 0xba, 0x6a, 0x5d, 0x03, 0xf1, 0xb7, 0x3a, 0x2b, 0x10, 0xa2,
|
||||
0x72, 0xc7, 0x0a, 0x44, 0xbc, 0xf0, 0xc6, 0x76, 0xe5, 0x3f, 0xd5, 0x00, 0xf8, 0x52, 0x6a, 0xfd,
|
||||
0x88, 0xb8, 0x01, 0x3b, 0x07, 0x16, 0xf8, 0xfd, 0xe7, 0xc0, 0x33, 0x03, 0xc7, 0xa0, 0x7b, 0x90,
|
||||
0xf7, 0x44, 0x34, 0x89, 0x3f, 0x24, 0x47, 0xdc, 0x7c, 0x86, 0x8f, 0x40, 0xc4, 0x13, 0x96, 0xc2,
|
||||
0xea, 0x4b, 0xcf, 0x9e, 0x2f, 0x8c, 0x7d, 0xf8, 0x7c, 0x61, 0xec, 0xa3, 0xe7, 0x0b, 0x63, 0xef,
|
||||
0x9d, 0x2c, 0x68, 0xcf, 0x4e, 0x16, 0xb4, 0x0f, 0x4f, 0x16, 0xb4, 0x8f, 0x4e, 0x16, 0xb4, 0x8f,
|
||||
0x4f, 0x16, 0xb4, 0x27, 0xff, 0x58, 0x18, 0x7b, 0x90, 0x39, 0x5a, 0xf9, 0x4f, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0x89, 0x39, 0x24, 0x64, 0xcc, 0x24, 0x00, 0x00,
|
||||
// 2737 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x39, 0xcb, 0x6f, 0x24, 0x47,
|
||||
0xf9, 0xee, 0x79, 0x79, 0xe6, 0x1b, 0x8f, 0x1f, 0x65, 0xef, 0xef, 0x37, 0x31, 0xc2, 0xe3, 0x74,
|
||||
0x50, 0xe4, 0x40, 0x32, 0x8e, 0x97, 0x10, 0x2d, 0x1b, 0x12, 0xf0, 0x78, 0xec, 0x8d, 0xc9, 0x3a,
|
||||
0xb6, 0xca, 0xd9, 0x05, 0x42, 0x84, 0xd2, 0xee, 0x2e, 0x8f, 0x1b, 0xf7, 0x74, 0x4f, 0xaa, 0x7b,
|
||||
0xec, 0x1d, 0x38, 0x90, 0x03, 0x08, 0x90, 0x20, 0xda, 0x23, 0xe2, 0x80, 0xb2, 0x82, 0xbf, 0x80,
|
||||
0x0b, 0xfc, 0x01, 0x48, 0xec, 0x31, 0x12, 0x97, 0x48, 0xa0, 0x51, 0xd6, 0x1c, 0x38, 0x22, 0xae,
|
||||
0x3e, 0xa1, 0x7a, 0xf5, 0x63, 0x1e, 0xeb, 0x1e, 0x36, 0x44, 0xdc, 0xba, 0xbe, 0x77, 0x55, 0x7d,
|
||||
0xf5, 0xbd, 0x1a, 0xf6, 0x4e, 0x6f, 0xf8, 0x75, 0xdb, 0x5b, 0x3f, 0xed, 0x1e, 0x11, 0xea, 0x92,
|
||||
0x80, 0xf8, 0xeb, 0x67, 0xc4, 0xb5, 0x3c, 0xba, 0x2e, 0x11, 0x46, 0xc7, 0x6e, 0x1b, 0xe6, 0x89,
|
||||
0xed, 0x12, 0xda, 0x5b, 0xef, 0x9c, 0xb6, 0x18, 0xc0, 0x5f, 0x6f, 0x93, 0xc0, 0x58, 0x3f, 0xdb,
|
||||
0x58, 0x6f, 0x11, 0x97, 0x50, 0x23, 0x20, 0x56, 0xbd, 0x43, 0xbd, 0xc0, 0x43, 0x5f, 0x10, 0x5c,
|
||||
0xf5, 0x38, 0x57, 0xbd, 0x73, 0xda, 0x62, 0x00, 0xbf, 0xce, 0xb8, 0xea, 0x67, 0x1b, 0xcb, 0x2f,
|
||||
0xb4, 0xec, 0xe0, 0xa4, 0x7b, 0x54, 0x37, 0xbd, 0xf6, 0x7a, 0xcb, 0x6b, 0x79, 0xeb, 0x9c, 0xf9,
|
||||
0xa8, 0x7b, 0xcc, 0x57, 0x7c, 0xc1, 0xbf, 0x84, 0xd0, 0xe5, 0xb1, 0xa6, 0xd0, 0xae, 0x1b, 0xd8,
|
||||
0x6d, 0x32, 0x68, 0xc5, 0xf2, 0xcb, 0x57, 0x31, 0xf8, 0xe6, 0x09, 0x69, 0x1b, 0x83, 0x7c, 0xfa,
|
||||
0x9f, 0xb3, 0x50, 0xdc, 0x3c, 0xd8, 0xbd, 0x45, 0xbd, 0x6e, 0x07, 0xad, 0x42, 0xce, 0x35, 0xda,
|
||||
0xa4, 0xaa, 0xad, 0x6a, 0x6b, 0xa5, 0xc6, 0xcc, 0xc3, 0x7e, 0x6d, 0xea, 0xa2, 0x5f, 0xcb, 0xbd,
|
||||
0x69, 0xb4, 0x09, 0xe6, 0x18, 0xe4, 0x40, 0xf1, 0x8c, 0x50, 0xdf, 0xf6, 0x5c, 0xbf, 0x9a, 0x59,
|
||||
0xcd, 0xae, 0x95, 0xaf, 0xbf, 0x56, 0x4f, 0xb3, 0xff, 0x3a, 0x57, 0x70, 0x57, 0xb0, 0xee, 0x78,
|
||||
0xb4, 0x69, 0xfb, 0xa6, 0x77, 0x46, 0x68, 0xaf, 0x31, 0x2f, 0xb5, 0x14, 0x25, 0xd2, 0xc7, 0xa1,
|
||||
0x06, 0xf4, 0x63, 0x0d, 0xe6, 0x3b, 0x94, 0x1c, 0x13, 0x4a, 0x89, 0x25, 0xf1, 0xd5, 0xec, 0xaa,
|
||||
0xf6, 0x29, 0xa8, 0xad, 0x4a, 0xb5, 0xf3, 0x07, 0x03, 0xf2, 0xf1, 0x90, 0x46, 0xf4, 0x5b, 0x0d,
|
||||
0x96, 0x7d, 0x42, 0xcf, 0x08, 0xdd, 0xb4, 0x2c, 0x4a, 0x7c, 0xbf, 0xd1, 0xdb, 0x72, 0x6c, 0xe2,
|
||||
0x06, 0x5b, 0xbb, 0x4d, 0xec, 0x57, 0x73, 0xfc, 0x1c, 0xbe, 0x9e, 0xce, 0xa0, 0xc3, 0x71, 0x72,
|
||||
0x1a, 0xba, 0xb4, 0x68, 0x79, 0x2c, 0x89, 0x8f, 0x1f, 0x63, 0x86, 0x7e, 0x0c, 0x33, 0xea, 0x22,
|
||||
0x6f, 0xdb, 0x7e, 0x80, 0xee, 0x42, 0xa1, 0xc5, 0x16, 0x7e, 0x55, 0xe3, 0x06, 0xd6, 0xd3, 0x19,
|
||||
0xa8, 0x64, 0x34, 0x66, 0xa5, 0x3d, 0x05, 0xbe, 0xf4, 0xb1, 0x94, 0xa6, 0xff, 0x3c, 0x07, 0xe5,
|
||||
0xcd, 0x83, 0x5d, 0x4c, 0x7c, 0xaf, 0x4b, 0x4d, 0x92, 0xc2, 0x69, 0x6e, 0xc0, 0x8c, 0x6f, 0xbb,
|
||||
0xad, 0xae, 0x63, 0x50, 0x06, 0xad, 0x16, 0x38, 0xe5, 0x92, 0xa4, 0x9c, 0x39, 0x8c, 0xe1, 0x70,
|
||||
0x82, 0x12, 0x5d, 0x07, 0x60, 0x12, 0xfc, 0x8e, 0x61, 0x12, 0xab, 0x9a, 0x59, 0xd5, 0xd6, 0x8a,
|
||||
0x0d, 0x24, 0xf9, 0xe0, 0xcd, 0x10, 0x83, 0x63, 0x54, 0xe8, 0x19, 0xc8, 0x73, 0x4b, 0xab, 0x45,
|
||||
0xae, 0xa6, 0x22, 0xc9, 0xf3, 0x7c, 0x1b, 0x58, 0xe0, 0xd0, 0x73, 0x30, 0x2d, 0xbd, 0xac, 0x5a,
|
||||
0xe2, 0x64, 0x73, 0x92, 0x6c, 0x5a, 0xb9, 0x81, 0xc2, 0xb3, 0xfd, 0x9d, 0xda, 0xae, 0xc5, 0xfd,
|
||||
0x2e, 0xb6, 0xbf, 0x37, 0x6c, 0xd7, 0xc2, 0x1c, 0x83, 0x6e, 0x43, 0xfe, 0x8c, 0xd0, 0x23, 0xe6,
|
||||
0x09, 0xcc, 0x35, 0xbf, 0x94, 0xee, 0xa0, 0xef, 0x32, 0x96, 0x46, 0x89, 0x99, 0xc6, 0x3f, 0xb1,
|
||||
0x10, 0x82, 0xea, 0x00, 0xfe, 0x89, 0x47, 0x03, 0xbe, 0xbd, 0x6a, 0x7e, 0x35, 0xbb, 0x56, 0x6a,
|
||||
0xcc, 0xb2, 0xfd, 0x1e, 0x86, 0x50, 0x1c, 0xa3, 0x60, 0xf4, 0xa6, 0x11, 0x90, 0x96, 0x47, 0x6d,
|
||||
0xe2, 0x57, 0xa7, 0x23, 0xfa, 0xad, 0x10, 0x8a, 0x63, 0x14, 0xe8, 0x9b, 0x80, 0xfc, 0xc0, 0xa3,
|
||||
0x46, 0x8b, 0xc8, 0xad, 0xbe, 0x6e, 0xf8, 0x27, 0x55, 0xe0, 0xbb, 0x5b, 0x96, 0xbb, 0x43, 0x87,
|
||||
0x43, 0x14, 0x78, 0x04, 0x97, 0xfe, 0x7b, 0x0d, 0xe6, 0x62, 0xbe, 0xc0, 0xfd, 0xee, 0x06, 0xcc,
|
||||
0xb4, 0x62, 0xaf, 0x4e, 0xfa, 0x45, 0x78, 0xdb, 0xf1, 0x17, 0x89, 0x13, 0x94, 0x88, 0x40, 0x89,
|
||||
0x4a, 0x49, 0x2a, 0xba, 0x6c, 0xa4, 0x76, 0x5a, 0x65, 0x43, 0xa4, 0x29, 0x06, 0xf4, 0x71, 0x24,
|
||||
0x59, 0xff, 0x87, 0xc6, 0x1d, 0x58, 0xc5, 0x1b, 0xb4, 0x16, 0x8b, 0x69, 0x1a, 0x3f, 0xbe, 0x99,
|
||||
0x31, 0xf1, 0xe8, 0x8a, 0x40, 0x90, 0xf9, 0x9f, 0x08, 0x04, 0x37, 0x8b, 0xbf, 0xfa, 0xb0, 0x36,
|
||||
0xf5, 0xfe, 0xdf, 0x56, 0xa7, 0xf4, 0x36, 0x54, 0xb6, 0x28, 0x31, 0x02, 0xb2, 0xdf, 0x09, 0xf8,
|
||||
0x06, 0x74, 0x28, 0x58, 0xb4, 0x87, 0xbb, 0xae, 0xdc, 0x28, 0xb0, 0xf7, 0xdd, 0xe4, 0x10, 0x2c,
|
||||
0x31, 0xec, 0xfe, 0x8e, 0x6d, 0xe2, 0x58, 0x7b, 0x86, 0x6b, 0xb4, 0x08, 0x95, 0x7e, 0x1f, 0x9e,
|
||||
0xea, 0x4e, 0x0c, 0x87, 0x13, 0x94, 0xfa, 0x4f, 0xb3, 0x50, 0x69, 0x12, 0x87, 0x44, 0xfa, 0x76,
|
||||
0x00, 0xb5, 0xa8, 0x61, 0x92, 0x03, 0x42, 0x6d, 0xcf, 0x3a, 0x24, 0xa6, 0xe7, 0x5a, 0x3e, 0xf7,
|
||||
0x88, 0x6c, 0xe3, 0xff, 0x98, 0x9f, 0xdd, 0x1a, 0xc2, 0xe2, 0x11, 0x1c, 0xc8, 0x81, 0x4a, 0x87,
|
||||
0xf2, 0x6f, 0x3b, 0x90, 0xb9, 0x87, 0xbd, 0xb4, 0x2f, 0xa7, 0x3b, 0xea, 0x83, 0x38, 0x6b, 0x63,
|
||||
0xe1, 0xa2, 0x5f, 0xab, 0x24, 0x40, 0x38, 0x29, 0x1c, 0x7d, 0x03, 0xe6, 0x3d, 0xda, 0x39, 0x31,
|
||||
0xdc, 0x26, 0xe9, 0x10, 0xd7, 0x22, 0x6e, 0xe0, 0xf3, 0x53, 0x28, 0x36, 0x96, 0x58, 0xc6, 0xd8,
|
||||
0x1f, 0xc0, 0xe1, 0x21, 0x6a, 0xf4, 0x36, 0x2c, 0x74, 0xa8, 0xd7, 0x31, 0x5a, 0x06, 0x93, 0x78,
|
||||
0xe0, 0x39, 0xb6, 0xd9, 0xe3, 0xd1, 0xa1, 0xd4, 0x78, 0xfe, 0xa2, 0x5f, 0x5b, 0x38, 0x18, 0x44,
|
||||
0x5e, 0xf6, 0x6b, 0x8b, 0xfc, 0xe8, 0x18, 0x24, 0x42, 0xe2, 0x61, 0x31, 0xb1, 0x3b, 0xcc, 0x8f,
|
||||
0xbb, 0x43, 0x7d, 0x17, 0x8a, 0xcd, 0x2e, 0xe5, 0x5c, 0xe8, 0x55, 0x28, 0x5a, 0xf2, 0x5b, 0x9e,
|
||||
0xfc, 0xd3, 0x2a, 0xe5, 0x2a, 0x9a, 0xcb, 0x7e, 0xad, 0xc2, 0x8a, 0x84, 0xba, 0x02, 0xe0, 0x90,
|
||||
0x45, 0x7f, 0x07, 0x2a, 0xdb, 0xf7, 0x3a, 0x1e, 0x0d, 0xd4, 0x9d, 0x3e, 0x0b, 0x05, 0xc2, 0x01,
|
||||
0x5c, 0x5a, 0x31, 0xca, 0x13, 0x82, 0x0c, 0x4b, 0x2c, 0x8b, 0xc3, 0xe4, 0x9e, 0x61, 0x06, 0x32,
|
||||
0x6c, 0x87, 0x71, 0x78, 0x9b, 0x01, 0xb1, 0xc0, 0xe9, 0xcf, 0x42, 0x91, 0x3b, 0x94, 0x7f, 0x77,
|
||||
0x03, 0xcd, 0x43, 0x16, 0x1b, 0xe7, 0x5c, 0xea, 0x0c, 0xce, 0x52, 0xe3, 0x3c, 0xe6, 0xc9, 0xfb,
|
||||
0x00, 0xb7, 0x48, 0x68, 0xc2, 0x26, 0xcc, 0xa9, 0xe7, 0x9c, 0x8c, 0x32, 0xff, 0x2f, 0x95, 0xcc,
|
||||
0xe1, 0x24, 0x1a, 0x0f, 0xd2, 0xeb, 0xef, 0x40, 0x89, 0x47, 0x22, 0x16, 0xc6, 0xa3, 0x94, 0xa1,
|
||||
0x3d, 0x26, 0x65, 0xa8, 0x3c, 0x90, 0x19, 0x97, 0x07, 0x62, 0xe6, 0x3a, 0x50, 0x11, 0xbc, 0x2a,
|
||||
0x49, 0xa6, 0xd2, 0xf0, 0x3c, 0x14, 0x95, 0x99, 0x52, 0x4b, 0x58, 0x1c, 0x29, 0x41, 0x38, 0xa4,
|
||||
0x88, 0x69, 0x3b, 0x81, 0x44, 0x54, 0x4d, 0xa7, 0x2c, 0x96, 0x01, 0x33, 0x8f, 0xcf, 0x80, 0x31,
|
||||
0x4d, 0x3f, 0x82, 0xea, 0xb8, 0x8a, 0xea, 0x09, 0xe2, 0x7e, 0x7a, 0x53, 0xf4, 0x0f, 0x34, 0x98,
|
||||
0x8f, 0x4b, 0x4a, 0x7f, 0x7d, 0xe9, 0x95, 0x5c, 0x9d, 0xf1, 0x63, 0x27, 0xf2, 0x1b, 0x0d, 0x96,
|
||||
0x12, 0x5b, 0x9b, 0xe8, 0xc6, 0x27, 0x30, 0x2a, 0xee, 0x1c, 0xd9, 0x09, 0x9c, 0xe3, 0x2f, 0x19,
|
||||
0xa8, 0xdc, 0x36, 0x8e, 0x88, 0x73, 0x48, 0x1c, 0x62, 0x06, 0x1e, 0x45, 0x3f, 0x84, 0x72, 0xdb,
|
||||
0x08, 0xcc, 0x13, 0x0e, 0x55, 0xd5, 0x61, 0x33, 0x5d, 0x28, 0x4d, 0x48, 0xaa, 0xef, 0x45, 0x62,
|
||||
0xb6, 0xdd, 0x80, 0xf6, 0x1a, 0x8b, 0xd2, 0xa4, 0x72, 0x0c, 0x83, 0xe3, 0xda, 0x78, 0x49, 0xcf,
|
||||
0xd7, 0xdb, 0xf7, 0x3a, 0x2c, 0x75, 0x4d, 0xde, 0x49, 0x24, 0x4c, 0xc0, 0xe4, 0xbd, 0xae, 0x4d,
|
||||
0x49, 0x9b, 0xb8, 0x41, 0x54, 0xd2, 0xef, 0x0d, 0xc8, 0xc7, 0x43, 0x1a, 0x97, 0x5f, 0x83, 0xf9,
|
||||
0x41, 0xe3, 0x59, 0xfc, 0x39, 0x25, 0x3d, 0x71, 0x5f, 0x98, 0x7d, 0xa2, 0x25, 0xc8, 0x9f, 0x19,
|
||||
0x4e, 0x57, 0xbe, 0x46, 0x2c, 0x16, 0x37, 0x33, 0x37, 0x34, 0xfd, 0x77, 0x1a, 0x54, 0xc7, 0x19,
|
||||
0x82, 0x3e, 0x1f, 0x13, 0xd4, 0x28, 0x4b, 0xab, 0xb2, 0x6f, 0x90, 0x9e, 0x90, 0xba, 0x0d, 0x45,
|
||||
0xaf, 0xc3, 0x9a, 0x30, 0x8f, 0xca, 0x5b, 0x7f, 0x4e, 0xdd, 0xe4, 0xbe, 0x84, 0x5f, 0xf6, 0x6b,
|
||||
0xd7, 0x12, 0xe2, 0x15, 0x02, 0x87, 0xac, 0x2c, 0x0f, 0x70, 0x7b, 0x58, 0x6e, 0x0a, 0xf3, 0xc0,
|
||||
0x5d, 0x0e, 0xc1, 0x12, 0xa3, 0xff, 0x51, 0x83, 0x1c, 0x2f, 0xca, 0xde, 0x81, 0x22, 0x3b, 0x3f,
|
||||
0xcb, 0x08, 0x0c, 0x6e, 0x57, 0xea, 0x76, 0x80, 0x71, 0xef, 0x91, 0xc0, 0x88, 0xbc, 0x4d, 0x41,
|
||||
0x70, 0x28, 0x11, 0x61, 0xc8, 0xdb, 0x01, 0x69, 0xab, 0x8b, 0x7c, 0x61, 0xac, 0x68, 0xd9, 0x8c,
|
||||
0xd6, 0xb1, 0x71, 0xbe, 0x7d, 0x2f, 0x20, 0x2e, 0xbb, 0x8c, 0xe8, 0x69, 0xec, 0x32, 0x19, 0x58,
|
||||
0x88, 0xd2, 0xff, 0xa5, 0x41, 0xa8, 0x8a, 0x39, 0xbf, 0x4f, 0x9c, 0xe3, 0xdb, 0xb6, 0x7b, 0x2a,
|
||||
0x8f, 0x35, 0x34, 0xe7, 0x50, 0xc2, 0x71, 0x48, 0x31, 0x2a, 0x3d, 0x64, 0x26, 0x4b, 0x0f, 0x4c,
|
||||
0xa1, 0xe9, 0xb9, 0x81, 0xed, 0x76, 0x87, 0x5e, 0xdb, 0x96, 0x84, 0xe3, 0x90, 0x82, 0x95, 0x39,
|
||||
0x94, 0xb4, 0x0d, 0xdb, 0xb5, 0xdd, 0x16, 0xdb, 0xc4, 0x96, 0xd7, 0x75, 0x03, 0x9e, 0xef, 0x65,
|
||||
0x99, 0x83, 0x87, 0xb0, 0x78, 0x04, 0x87, 0xfe, 0x87, 0x1c, 0x94, 0xd9, 0x9e, 0x55, 0x9e, 0x7b,
|
||||
0x05, 0x2a, 0x4e, 0xdc, 0x0b, 0xe4, 0xde, 0xaf, 0x49, 0x53, 0x92, 0xef, 0x1a, 0x27, 0x69, 0x19,
|
||||
0x33, 0xaf, 0xce, 0x42, 0xe6, 0x4c, 0x92, 0x79, 0x27, 0x8e, 0xc4, 0x49, 0x5a, 0x16, 0xbd, 0xce,
|
||||
0xd9, 0xfb, 0x90, 0x75, 0x4f, 0x78, 0x45, 0xdf, 0x62, 0x40, 0x2c, 0x70, 0x68, 0x0f, 0x16, 0x0d,
|
||||
0xc7, 0xf1, 0xce, 0x39, 0xb0, 0xe1, 0x79, 0xa7, 0x6d, 0x83, 0x9e, 0xfa, 0xbc, 0xa1, 0x2a, 0x36,
|
||||
0x3e, 0x27, 0x59, 0x16, 0x37, 0x87, 0x49, 0xf0, 0x28, 0xbe, 0x51, 0xd7, 0x96, 0x9b, 0xf0, 0xda,
|
||||
0x4e, 0x60, 0x69, 0x00, 0xc4, 0x5f, 0xb9, 0xec, 0x6e, 0x5e, 0x92, 0x72, 0x96, 0xf0, 0x08, 0x9a,
|
||||
0xcb, 0x31, 0x70, 0x3c, 0x52, 0x22, 0xba, 0x09, 0xb3, 0xcc, 0x93, 0xbd, 0x6e, 0xa0, 0xaa, 0xda,
|
||||
0x3c, 0xbf, 0x6e, 0x74, 0xd1, 0xaf, 0xcd, 0xbe, 0x95, 0xc0, 0xe0, 0x01, 0x4a, 0x76, 0xb8, 0x8e,
|
||||
0xdd, 0xb6, 0x83, 0xea, 0x34, 0x67, 0x09, 0x0f, 0xf7, 0x36, 0x03, 0x62, 0x81, 0x4b, 0x78, 0x60,
|
||||
0xf1, 0x2a, 0x0f, 0xd4, 0x7f, 0x9d, 0x05, 0x24, 0xca, 0x70, 0x4b, 0xd4, 0x53, 0x22, 0xa4, 0x3d,
|
||||
0x07, 0xd3, 0x6d, 0x59, 0xc6, 0x6b, 0xc9, 0xfc, 0xa2, 0x2a, 0x78, 0x85, 0x47, 0x7b, 0x50, 0x12,
|
||||
0xa1, 0x25, 0x7a, 0x2e, 0xeb, 0x92, 0xb8, 0xb4, 0xaf, 0x10, 0x97, 0xfd, 0xda, 0x72, 0x42, 0x4d,
|
||||
0x88, 0x79, 0xab, 0xd7, 0x21, 0x38, 0x92, 0xc0, 0x3a, 0x77, 0xa3, 0x63, 0xc7, 0x67, 0x36, 0xa5,
|
||||
0xa8, 0x73, 0x8f, 0xba, 0x2f, 0x1c, 0xa3, 0x42, 0xaf, 0x43, 0x8e, 0x9d, 0x94, 0x6c, 0xa3, 0xbf,
|
||||
0x98, 0x2e, 0x40, 0xb1, 0xb3, 0x6e, 0x14, 0x59, 0x7e, 0x66, 0x5f, 0x98, 0x4b, 0x60, 0xda, 0xb9,
|
||||
0x3f, 0xfb, 0xcc, 0x2c, 0x39, 0x6f, 0x08, 0xb5, 0xef, 0x84, 0x18, 0x1c, 0xa3, 0x42, 0xdf, 0x86,
|
||||
0xe2, 0xb1, 0x2c, 0x45, 0xf9, 0xc5, 0xa4, 0x0e, 0x91, 0xaa, 0x80, 0x15, 0x6d, 0xa3, 0x5a, 0xe1,
|
||||
0x50, 0x9a, 0xfe, 0x1e, 0x94, 0xf6, 0x6c, 0x93, 0x7a, 0xcc, 0x40, 0x76, 0x25, 0x7e, 0xa2, 0x0f,
|
||||
0x0a, 0xaf, 0x44, 0xb9, 0x8b, 0xc2, 0x33, 0x3f, 0x71, 0x0d, 0xd7, 0x13, 0xdd, 0x4e, 0x3e, 0xf2,
|
||||
0x93, 0x37, 0x19, 0x10, 0x0b, 0xdc, 0xcd, 0x25, 0x96, 0xe9, 0x7f, 0xf6, 0xa0, 0x36, 0x75, 0xff,
|
||||
0x41, 0x6d, 0xea, 0xc3, 0x07, 0x32, 0xeb, 0x5f, 0x02, 0xc0, 0xfe, 0xd1, 0xf7, 0x89, 0x29, 0xe2,
|
||||
0x67, 0xaa, 0x19, 0x8d, 0x1a, 0x0d, 0xf2, 0x19, 0x4d, 0x66, 0xa0, 0x7a, 0x8b, 0xe1, 0x70, 0x82,
|
||||
0x12, 0xad, 0x43, 0x29, 0x9c, 0xbe, 0xc8, 0x8b, 0x5e, 0x50, 0x8e, 0x13, 0x8e, 0x68, 0x70, 0x44,
|
||||
0x93, 0x08, 0xe6, 0xb9, 0x2b, 0x83, 0x79, 0x03, 0xb2, 0x5d, 0xdb, 0xe2, 0xaf, 0xab, 0xd4, 0x78,
|
||||
0x51, 0x25, 0xd3, 0x3b, 0xbb, 0xcd, 0xcb, 0x7e, 0xed, 0xe9, 0x71, 0x43, 0xcf, 0xa0, 0xd7, 0x21,
|
||||
0x7e, 0xfd, 0xce, 0x6e, 0x13, 0x33, 0xe6, 0x51, 0x91, 0xa5, 0x30, 0x61, 0x64, 0xb9, 0x0e, 0x20,
|
||||
0x77, 0xcd, 0xb8, 0xc5, 0xc3, 0x0d, 0x3d, 0xea, 0x56, 0x88, 0xc1, 0x31, 0x2a, 0xe4, 0xc3, 0x82,
|
||||
0xc9, 0xda, 0x6f, 0xf6, 0x3c, 0xec, 0x36, 0xf1, 0x03, 0xa3, 0x2d, 0xa6, 0x52, 0x93, 0x39, 0xf7,
|
||||
0x53, 0x52, 0xcd, 0xc2, 0xd6, 0xa0, 0x30, 0x3c, 0x2c, 0x1f, 0x79, 0xb0, 0x60, 0xc9, 0x46, 0x32,
|
||||
0x52, 0x5a, 0x9a, 0x58, 0xe9, 0x35, 0xa6, 0xb0, 0x39, 0x28, 0x08, 0x0f, 0xcb, 0x46, 0xdf, 0x83,
|
||||
0x65, 0x05, 0x1c, 0xee, 0xe6, 0x79, 0xe4, 0xcd, 0x36, 0x56, 0x2e, 0xfa, 0xb5, 0xe5, 0xe6, 0x58,
|
||||
0x2a, 0xfc, 0x18, 0x09, 0xc8, 0x82, 0x82, 0x23, 0x2a, 0xd5, 0x32, 0xaf, 0x2e, 0xbe, 0x96, 0x6e,
|
||||
0x17, 0x91, 0xf7, 0xd7, 0xe3, 0x15, 0x6a, 0xd8, 0xad, 0xca, 0xe2, 0x54, 0xca, 0x46, 0xf7, 0xa0,
|
||||
0x6c, 0xb8, 0xae, 0x17, 0x18, 0x62, 0xbe, 0x30, 0xc3, 0x55, 0x6d, 0x4e, 0xac, 0x6a, 0x33, 0x92,
|
||||
0x31, 0x50, 0x11, 0xc7, 0x30, 0x38, 0xae, 0x0a, 0x9d, 0xc3, 0x9c, 0x77, 0xee, 0x12, 0x8a, 0xc9,
|
||||
0x31, 0xa1, 0xc4, 0x35, 0x89, 0x5f, 0xad, 0x70, 0xed, 0x2f, 0xa5, 0xd4, 0x9e, 0x60, 0x8e, 0x5c,
|
||||
0x3a, 0x09, 0xf7, 0xf1, 0xa0, 0x16, 0x54, 0x67, 0x41, 0xd2, 0x35, 0x1c, 0xfb, 0x07, 0x84, 0xfa,
|
||||
0xd5, 0xd9, 0x68, 0x70, 0xb8, 0x13, 0x42, 0x71, 0x8c, 0x02, 0x7d, 0x05, 0xca, 0xa6, 0xd3, 0xf5,
|
||||
0x03, 0x22, 0xa6, 0xb8, 0x73, 0xfc, 0x05, 0x85, 0xfb, 0xdb, 0x8a, 0x50, 0x38, 0x4e, 0x87, 0xba,
|
||||
0x50, 0x69, 0xc7, 0x53, 0x46, 0x75, 0x81, 0xef, 0xee, 0x46, 0xba, 0xdd, 0x0d, 0x27, 0xb5, 0xa8,
|
||||
0x82, 0x49, 0xe0, 0x70, 0x52, 0xcb, 0xf2, 0x57, 0xa1, 0xfc, 0x1f, 0x16, 0xf7, 0xac, 0x39, 0x18,
|
||||
0xbc, 0xc7, 0x89, 0x9a, 0x83, 0x3f, 0x65, 0x60, 0x36, 0x79, 0xfa, 0x03, 0xe9, 0x30, 0x9f, 0x2a,
|
||||
0x1d, 0xaa, 0x36, 0x54, 0x1b, 0x3b, 0x78, 0x56, 0x61, 0x3d, 0x3b, 0x36, 0xac, 0xcb, 0xe8, 0x99,
|
||||
0x7b, 0x92, 0xe8, 0x59, 0x07, 0x60, 0x75, 0x06, 0xf5, 0x1c, 0x87, 0x50, 0x1e, 0x38, 0x8b, 0x72,
|
||||
0xc0, 0x1c, 0x42, 0x71, 0x8c, 0x82, 0x55, 0xc3, 0x47, 0x8e, 0x67, 0x9e, 0xf2, 0x23, 0x50, 0x8f,
|
||||
0x9e, 0x87, 0xcc, 0xa2, 0xa8, 0x86, 0x1b, 0x43, 0x58, 0x3c, 0x82, 0x43, 0xef, 0xc1, 0xb5, 0x03,
|
||||
0x83, 0x06, 0xb6, 0xe1, 0x44, 0x0f, 0x8c, 0xb7, 0x1b, 0xef, 0x0e, 0x35, 0x33, 0x2f, 0x4e, 0xfa,
|
||||
0x50, 0xa3, 0xc3, 0x8f, 0x60, 0x51, 0x43, 0xa3, 0xff, 0x55, 0x83, 0xa7, 0x46, 0xea, 0xfe, 0x0c,
|
||||
0x9a, 0xa9, 0x77, 0x93, 0xcd, 0xd4, 0x2b, 0x29, 0x67, 0x9c, 0xa3, 0xac, 0x1d, 0xd3, 0x5a, 0x4d,
|
||||
0x43, 0xfe, 0x80, 0x15, 0xb1, 0xfa, 0x2f, 0x35, 0x98, 0xe1, 0x5f, 0x93, 0xcc, 0x87, 0x6b, 0x90,
|
||||
0x3f, 0xf6, 0xd4, 0x88, 0xaa, 0x28, 0x7e, 0x60, 0xec, 0x30, 0x00, 0x16, 0xf0, 0x27, 0x18, 0x20,
|
||||
0x7f, 0xa0, 0x41, 0x72, 0x32, 0x8b, 0x5e, 0x13, 0xfe, 0xab, 0x85, 0xa3, 0xd3, 0x09, 0x7d, 0xf7,
|
||||
0xd5, 0x71, 0xad, 0xe0, 0x62, 0xaa, 0x29, 0xe1, 0xf3, 0x50, 0xc2, 0x9e, 0x17, 0x1c, 0x18, 0xc1,
|
||||
0x89, 0xcf, 0x36, 0xde, 0x61, 0x1f, 0xf2, 0x6c, 0xf8, 0xc6, 0x39, 0x06, 0x0b, 0xb8, 0xfe, 0x0b,
|
||||
0x0d, 0x9e, 0x1a, 0x3b, 0xb3, 0x67, 0x21, 0xc0, 0x0c, 0x57, 0x72, 0x47, 0xa1, 0x17, 0x46, 0x74,
|
||||
0x38, 0x46, 0xc5, 0x7a, 0xb8, 0xc4, 0xa0, 0x7f, 0xb0, 0x87, 0x4b, 0x68, 0xc3, 0x49, 0x5a, 0xfd,
|
||||
0x9f, 0x19, 0x28, 0x1c, 0x06, 0x46, 0xd0, 0xf5, 0xff, 0xcb, 0x1e, 0xfb, 0x2c, 0x14, 0x7c, 0xae,
|
||||
0x47, 0x9a, 0x17, 0xe6, 0x58, 0xa1, 0x1d, 0x4b, 0x2c, 0xef, 0x46, 0x88, 0xef, 0x1b, 0x2d, 0x15,
|
||||
0xb1, 0xa2, 0x6e, 0x44, 0x80, 0xb1, 0xc2, 0xa3, 0x97, 0xa1, 0x40, 0x89, 0xe1, 0x87, 0x2d, 0xe0,
|
||||
0x8a, 0x12, 0x89, 0x39, 0xf4, 0xb2, 0x5f, 0x9b, 0x91, 0xc2, 0xf9, 0x1a, 0x4b, 0x6a, 0xf4, 0x36,
|
||||
0x4c, 0x5b, 0x24, 0x30, 0x6c, 0x47, 0xf4, 0x63, 0xa9, 0x7f, 0x11, 0x08, 0x61, 0x4d, 0xc1, 0xda,
|
||||
0x28, 0x33, 0x9b, 0xe4, 0x02, 0x2b, 0x81, 0x2c, 0xda, 0x9a, 0x9e, 0x25, 0xda, 0x89, 0x7c, 0x14,
|
||||
0x6d, 0xb7, 0x3c, 0x8b, 0x60, 0x8e, 0xd1, 0xef, 0x6b, 0x50, 0x16, 0x92, 0xb6, 0x8c, 0xae, 0x4f,
|
||||
0xd0, 0x46, 0xb8, 0x0b, 0x71, 0xdd, 0xaa, 0x92, 0xcb, 0xb1, 0x86, 0xe3, 0xb2, 0x5f, 0x2b, 0x71,
|
||||
0x32, 0xde, 0x89, 0xa8, 0x0d, 0xc4, 0xce, 0x28, 0x73, 0xc5, 0x19, 0x3d, 0x03, 0x79, 0xfe, 0x7a,
|
||||
0xe4, 0x61, 0x86, 0x6f, 0x9d, 0x3f, 0x30, 0x2c, 0x70, 0xfa, 0x27, 0x19, 0xa8, 0x24, 0x36, 0x97,
|
||||
0xa2, 0x17, 0x08, 0x47, 0x97, 0x99, 0x14, 0xe3, 0xf0, 0xf1, 0xbf, 0x45, 0x65, 0xee, 0x29, 0x3c,
|
||||
0x49, 0xee, 0xf9, 0x0e, 0x14, 0x4c, 0x76, 0x46, 0xea, 0x2f, 0xfb, 0xc6, 0x24, 0xd7, 0xc9, 0x4f,
|
||||
0x37, 0xf2, 0x46, 0xbe, 0xf4, 0xb1, 0x14, 0x88, 0x6e, 0xc1, 0x02, 0x25, 0x01, 0xed, 0x6d, 0x1e,
|
||||
0x07, 0x84, 0xc6, 0x9b, 0xf8, 0x7c, 0x54, 0x71, 0xe3, 0x41, 0x02, 0x3c, 0xcc, 0xa3, 0x1f, 0xc1,
|
||||
0xcc, 0x5b, 0xc6, 0x91, 0x13, 0xfe, 0xf4, 0xc2, 0x50, 0xb1, 0x5d, 0xd3, 0xe9, 0x5a, 0x44, 0x44,
|
||||
0x63, 0x15, 0xbd, 0xd4, 0xa3, 0xdd, 0x8d, 0x23, 0x2f, 0xfb, 0xb5, 0xc5, 0x04, 0x40, 0xfc, 0xe5,
|
||||
0xc1, 0x49, 0x11, 0xba, 0x03, 0xb9, 0xcf, 0xb0, 0x7b, 0xfc, 0x2e, 0x94, 0xa2, 0xfa, 0xfe, 0x53,
|
||||
0x56, 0xa9, 0xbf, 0x0b, 0x45, 0xe6, 0xf1, 0xaa, 0x2f, 0xbd, 0xa2, 0xc4, 0x49, 0x16, 0x4e, 0x99,
|
||||
0x34, 0x85, 0x93, 0xde, 0x86, 0xca, 0x9d, 0x8e, 0xf5, 0x84, 0xbf, 0x3d, 0x33, 0xa9, 0xb3, 0xd6,
|
||||
0x75, 0x10, 0x3f, 0xf0, 0x59, 0x82, 0x10, 0x99, 0x3b, 0x96, 0x20, 0xe2, 0x89, 0x37, 0x36, 0x95,
|
||||
0xff, 0x89, 0x06, 0xc0, 0xc7, 0x5f, 0xdb, 0x67, 0xc4, 0x0d, 0xd8, 0x39, 0x30, 0xc7, 0x1f, 0x3c,
|
||||
0x07, 0x1e, 0x19, 0x38, 0x06, 0xdd, 0x81, 0x82, 0x27, 0xbc, 0x49, 0xfc, 0xfa, 0x9c, 0x70, 0xc6,
|
||||
0x1a, 0x3e, 0x02, 0xe1, 0x4f, 0x58, 0x0a, 0x6b, 0xac, 0x3d, 0x7c, 0xb4, 0x32, 0xf5, 0xd1, 0xa3,
|
||||
0x95, 0xa9, 0x8f, 0x1f, 0xad, 0x4c, 0xbd, 0x7f, 0xb1, 0xa2, 0x3d, 0xbc, 0x58, 0xd1, 0x3e, 0xba,
|
||||
0x58, 0xd1, 0x3e, 0xbe, 0x58, 0xd1, 0x3e, 0xb9, 0x58, 0xd1, 0xee, 0xff, 0x7d, 0x65, 0xea, 0xed,
|
||||
0xcc, 0xd9, 0xc6, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xa1, 0x16, 0x06, 0x49, 0x36, 0x25, 0x00,
|
||||
0x00,
|
||||
}
|
||||
|
||||
func (m *APIGroup) Marshal() (dAtA []byte, err error) {
|
||||
@ -2399,6 +2401,11 @@ func (m *ListOptions) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
i -= len(m.ResourceVersionMatch)
|
||||
copy(dAtA[i:], m.ResourceVersionMatch)
|
||||
i = encodeVarintGenerated(dAtA, i, uint64(len(m.ResourceVersionMatch)))
|
||||
i--
|
||||
dAtA[i] = 0x52
|
||||
i--
|
||||
if m.AllowWatchBookmarks {
|
||||
dAtA[i] = 1
|
||||
@ -3758,6 +3765,8 @@ func (m *ListOptions) Size() (n int) {
|
||||
l = len(m.Continue)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
n += 2
|
||||
l = len(m.ResourceVersionMatch)
|
||||
n += 1 + l + sovGenerated(uint64(l))
|
||||
return n
|
||||
}
|
||||
|
||||
@ -4345,6 +4354,7 @@ func (this *ListOptions) String() string {
|
||||
`Limit:` + fmt.Sprintf("%v", this.Limit) + `,`,
|
||||
`Continue:` + fmt.Sprintf("%v", this.Continue) + `,`,
|
||||
`AllowWatchBookmarks:` + fmt.Sprintf("%v", this.AllowWatchBookmarks) + `,`,
|
||||
`ResourceVersionMatch:` + fmt.Sprintf("%v", this.ResourceVersionMatch) + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
@ -7801,6 +7811,38 @@ func (m *ListOptions) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
}
|
||||
m.AllowWatchBookmarks = bool(v != 0)
|
||||
case 10:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ResourceVersionMatch", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenerated
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenerated
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.ResourceVersionMatch = ResourceVersionMatch(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenerated(dAtA[iNdEx:])
|
||||
|
@ -232,10 +232,12 @@ message FieldsV1 {
|
||||
|
||||
// GetOptions is the standard query options to the standard REST get call.
|
||||
message GetOptions {
|
||||
// When specified:
|
||||
// - if unset, then the result is returned from remote storage based on quorum-read flag;
|
||||
// - if it's 0, then we simply return what we currently have in cache, no guarantee;
|
||||
// - if set to non zero, then the result is at least as fresh as given rv.
|
||||
// resourceVersion sets a constraint on what resource versions a request may be served from.
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for
|
||||
// details.
|
||||
//
|
||||
// Defaults to unset
|
||||
// +optional
|
||||
optional string resourceVersion = 1;
|
||||
}
|
||||
|
||||
@ -421,15 +423,24 @@ message ListOptions {
|
||||
// +optional
|
||||
optional bool allowWatchBookmarks = 9;
|
||||
|
||||
// When specified with a watch call, shows changes that occur after that particular version of a resource.
|
||||
// Defaults to changes from the beginning of history.
|
||||
// When specified for list:
|
||||
// - if unset, then the result is returned from remote storage based on quorum-read flag;
|
||||
// - if it's 0, then we simply return what we currently have in cache, no guarantee;
|
||||
// - if set to non zero, then the result is at least as fresh as given rv.
|
||||
// resourceVersion sets a constraint on what resource versions a request may be served from.
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for
|
||||
// details.
|
||||
//
|
||||
// Defaults to unset
|
||||
// +optional
|
||||
optional string resourceVersion = 4;
|
||||
|
||||
// resourceVersionMatch determines how resourceVersion is applied to list calls.
|
||||
// It is highly recommended that resourceVersionMatch be set for list calls where
|
||||
// resourceVersion is set
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for
|
||||
// details.
|
||||
//
|
||||
// Defaults to unset
|
||||
// +optional
|
||||
optional string resourceVersionMatch = 10;
|
||||
|
||||
// Timeout for the list/watch call.
|
||||
// This limits the duration of the call, regardless of any activity or inactivity.
|
||||
// +optional
|
||||
|
@ -355,14 +355,23 @@ type ListOptions struct {
|
||||
// +optional
|
||||
AllowWatchBookmarks bool `json:"allowWatchBookmarks,omitempty" protobuf:"varint,9,opt,name=allowWatchBookmarks"`
|
||||
|
||||
// When specified with a watch call, shows changes that occur after that particular version of a resource.
|
||||
// Defaults to changes from the beginning of history.
|
||||
// When specified for list:
|
||||
// - if unset, then the result is returned from remote storage based on quorum-read flag;
|
||||
// - if it's 0, then we simply return what we currently have in cache, no guarantee;
|
||||
// - if set to non zero, then the result is at least as fresh as given rv.
|
||||
// resourceVersion sets a constraint on what resource versions a request may be served from.
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for
|
||||
// details.
|
||||
//
|
||||
// Defaults to unset
|
||||
// +optional
|
||||
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,4,opt,name=resourceVersion"`
|
||||
|
||||
// resourceVersionMatch determines how resourceVersion is applied to list calls.
|
||||
// It is highly recommended that resourceVersionMatch be set for list calls where
|
||||
// resourceVersion is set
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for
|
||||
// details.
|
||||
//
|
||||
// Defaults to unset
|
||||
// +optional
|
||||
ResourceVersionMatch ResourceVersionMatch `json:"resourceVersionMatch,omitempty" protobuf:"bytes,10,opt,name=resourceVersionMatch,casttype=ResourceVersionMatch"`
|
||||
// Timeout for the list/watch call.
|
||||
// This limits the duration of the call, regardless of any activity or inactivity.
|
||||
// +optional
|
||||
@ -402,6 +411,25 @@ type ListOptions struct {
|
||||
Continue string `json:"continue,omitempty" protobuf:"bytes,8,opt,name=continue"`
|
||||
}
|
||||
|
||||
// resourceVersionMatch specifies how the resourceVersion parameter is applied. resourceVersionMatch
|
||||
// may only be set if resourceVersion is also set.
|
||||
//
|
||||
// "NotOlderThan" matches data at least as new as the provided resourceVersion.
|
||||
// "Exact" matches data at the exact resourceVersion provided.
|
||||
//
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for
|
||||
// details.
|
||||
type ResourceVersionMatch string
|
||||
|
||||
const (
|
||||
// ResourceVersionMatchNotOlderThan matches data at least as new as the provided
|
||||
// resourceVersion.
|
||||
ResourceVersionMatchNotOlderThan ResourceVersionMatch = "NotOlderThan"
|
||||
// ResourceVersionMatchExact matches data at the exact resourceVersion
|
||||
// provided.
|
||||
ResourceVersionMatchExact ResourceVersionMatch = "Exact"
|
||||
)
|
||||
|
||||
// +k8s:conversion-gen:explicit-from=net/url.Values
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
@ -423,10 +451,12 @@ type ExportOptions struct {
|
||||
// GetOptions is the standard query options to the standard REST get call.
|
||||
type GetOptions struct {
|
||||
TypeMeta `json:",inline"`
|
||||
// When specified:
|
||||
// - if unset, then the result is returned from remote storage based on quorum-read flag;
|
||||
// - if it's 0, then we simply return what we currently have in cache, no guarantee;
|
||||
// - if set to non zero, then the result is at least as fresh as given rv.
|
||||
// resourceVersion sets a constraint on what resource versions a request may be served from.
|
||||
// See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for
|
||||
// details.
|
||||
//
|
||||
// Defaults to unset
|
||||
// +optional
|
||||
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,1,opt,name=resourceVersion"`
|
||||
// +k8s:deprecated=includeUninitialized,protobuf=2
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ func (FieldsV1) SwaggerDoc() map[string]string {
|
||||
|
||||
var map_GetOptions = map[string]string{
|
||||
"": "GetOptions is the standard query options to the standard REST get call.",
|
||||
"resourceVersion": "When specified: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
"resourceVersion": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
}
|
||||
|
||||
func (GetOptions) SwaggerDoc() map[string]string {
|
||||
@ -190,15 +190,16 @@ func (ListMeta) SwaggerDoc() map[string]string {
|
||||
}
|
||||
|
||||
var map_ListOptions = map[string]string{
|
||||
"": "ListOptions is the query options to a standard REST list call.",
|
||||
"labelSelector": "A selector to restrict the list of returned objects by their labels. Defaults to everything.",
|
||||
"fieldSelector": "A selector to restrict the list of returned objects by their fields. Defaults to everything.",
|
||||
"watch": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.",
|
||||
"allowWatchBookmarks": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored. If the feature gate WatchBookmarks is not enabled in apiserver, this field is ignored.",
|
||||
"resourceVersion": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
"timeoutSeconds": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.",
|
||||
"limit": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.",
|
||||
"continue": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.",
|
||||
"": "ListOptions is the query options to a standard REST list call.",
|
||||
"labelSelector": "A selector to restrict the list of returned objects by their labels. Defaults to everything.",
|
||||
"fieldSelector": "A selector to restrict the list of returned objects by their fields. Defaults to everything.",
|
||||
"watch": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.",
|
||||
"allowWatchBookmarks": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored. If the feature gate WatchBookmarks is not enabled in apiserver, this field is ignored.",
|
||||
"resourceVersion": "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
"resourceVersionMatch": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
"timeoutSeconds": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.",
|
||||
"limit": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.",
|
||||
"continue": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.",
|
||||
}
|
||||
|
||||
func (ListOptions) SwaggerDoc() map[string]string {
|
||||
|
@ -145,6 +145,11 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*[]string)(nil), (*ResourceVersionMatch)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_Slice_string_To_v1_ResourceVersionMatch(a.(*[]string), b.(*ResourceVersionMatch), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddConversionFunc((*[]string)(nil), (*Time)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_Slice_string_To_v1_Time(a.(*[]string), b.(*Time), scope)
|
||||
}); err != nil {
|
||||
@ -415,6 +420,13 @@ func autoConvert_url_Values_To_v1_ListOptions(in *url.Values, out *ListOptions,
|
||||
} else {
|
||||
out.ResourceVersion = ""
|
||||
}
|
||||
if values, ok := map[string][]string(*in)["resourceVersionMatch"]; ok && len(values) > 0 {
|
||||
if err := Convert_Slice_string_To_v1_ResourceVersionMatch(&values, &out.ResourceVersionMatch, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.ResourceVersionMatch = ""
|
||||
}
|
||||
if values, ok := map[string][]string(*in)["timeoutSeconds"]; ok && len(values) > 0 {
|
||||
if err := runtime.Convert_Slice_string_To_Pointer_int64(&values, &out.TimeoutSeconds, s); err != nil {
|
||||
return err
|
||||
|
@ -69,6 +69,7 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion/validation:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metainternalversionscheme "k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme"
|
||||
metainternalversionvalidation "k8s.io/apimachinery/pkg/apis/meta/internalversion/validation"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/validation"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@ -198,6 +199,12 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope *RequestSc
|
||||
return
|
||||
}
|
||||
|
||||
if errs := metainternalversionvalidation.ValidateListOptions(&listOptions); len(errs) > 0 {
|
||||
err := errors.NewInvalid(schema.GroupKind{Group: metav1.GroupName, Kind: "ListOptions"}, "", errs)
|
||||
scope.err(err, w, req)
|
||||
return
|
||||
}
|
||||
|
||||
// transform fields
|
||||
// TODO: DecodeParametersInto should do this.
|
||||
if listOptions.FieldSelector != nil {
|
||||
|
@ -19,6 +19,8 @@ package handlers
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
metainternalversionvalidation "k8s.io/apimachinery/pkg/apis/meta/internalversion/validation"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -198,6 +200,12 @@ func ListResource(r rest.Lister, rw rest.Watcher, scope *RequestScope, forceWatc
|
||||
return
|
||||
}
|
||||
|
||||
if errs := metainternalversionvalidation.ValidateListOptions(&opts); len(errs) > 0 {
|
||||
err := errors.NewInvalid(schema.GroupKind{Group: metav1.GroupName, Kind: "ListOptions"}, "", errs)
|
||||
scope.err(err, w, req)
|
||||
return
|
||||
}
|
||||
|
||||
// transform fields
|
||||
// TODO: DecodeParametersInto should do this.
|
||||
if opts.FieldSelector != nil {
|
||||
|
@ -1078,6 +1078,10 @@ func typeToJSON(typeName string) string {
|
||||
return "string"
|
||||
case "v1.DeletionPropagation", "*v1.DeletionPropagation":
|
||||
return "string"
|
||||
case "v1.ResourceVersionMatch", "*v1.ResourceVersionMatch":
|
||||
return "string"
|
||||
case "v1.IncludeObjectPolicy", "*v1.IncludeObjectPolicy":
|
||||
return "string"
|
||||
|
||||
// TODO: Fix these when go-restful supports a way to specify an array query param:
|
||||
// https://github.com/emicklei/go-restful/issues/225
|
||||
|
@ -322,7 +322,7 @@ func (e *Store) ListPredicate(ctx context.Context, p storage.SelectionPredicate,
|
||||
p.Continue = options.Continue
|
||||
list := e.NewListFunc()
|
||||
qualifiedResource := e.qualifiedResourceFromContext(ctx)
|
||||
storageOpts := storage.ListOptions{ResourceVersion: options.ResourceVersion, Predicate: p}
|
||||
storageOpts := storage.ListOptions{ResourceVersion: options.ResourceVersion, ResourceVersionMatch: options.ResourceVersionMatch, Predicate: p}
|
||||
if name, ok := p.MatchesSingle(); ok {
|
||||
if key, err := e.KeyFunc(ctx, name); err == nil {
|
||||
err := e.Storage.GetToList(ctx, key, storageOpts, list)
|
||||
|
@ -580,7 +580,7 @@ func (c *Cacher) GetToList(ctx context.Context, key string, opts storage.ListOpt
|
||||
pagingEnabled := utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking)
|
||||
hasContinuation := pagingEnabled && len(pred.Continue) > 0
|
||||
hasLimit := pagingEnabled && pred.Limit > 0 && resourceVersion != "0"
|
||||
if resourceVersion == "" || hasContinuation || hasLimit {
|
||||
if resourceVersion == "" || hasContinuation || hasLimit || opts.ResourceVersionMatch == metav1.ResourceVersionMatchExact {
|
||||
// If resourceVersion is not specified, serve it from underlying
|
||||
// storage (for backward compatibility). If a continuation is
|
||||
// requested, serve it from the underlying storage as well.
|
||||
@ -654,7 +654,7 @@ func (c *Cacher) List(ctx context.Context, key string, opts storage.ListOptions,
|
||||
pagingEnabled := utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking)
|
||||
hasContinuation := pagingEnabled && len(pred.Continue) > 0
|
||||
hasLimit := pagingEnabled && pred.Limit > 0 && resourceVersion != "0"
|
||||
if resourceVersion == "" || hasContinuation || hasLimit {
|
||||
if resourceVersion == "" || hasContinuation || hasLimit || opts.ResourceVersionMatch == metav1.ResourceVersionMatchExact {
|
||||
// If resourceVersion is not specified, serve it from underlying
|
||||
// storage (for backward compatibility). If a continuation is
|
||||
// requested, serve it from the underlying storage as well.
|
||||
@ -1090,7 +1090,7 @@ func (lw *cacherListerWatcher) List(options metav1.ListOptions) (runtime.Object,
|
||||
Continue: options.Continue,
|
||||
}
|
||||
|
||||
if err := lw.storage.List(context.TODO(), lw.resourcePrefix, storage.ListOptions{Predicate: pred}, list); err != nil {
|
||||
if err := lw.storage.List(context.TODO(), lw.resourcePrefix, storage.ListOptions{ResourceVersionMatch: options.ResourceVersionMatch, Predicate: pred}, list); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
|
@ -68,6 +68,7 @@ go_library(
|
||||
deps = [
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
|
@ -32,6 +32,8 @@ import (
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@ -62,10 +64,7 @@ func (d authenticatedDataString) AuthenticatedData() []byte {
|
||||
var _ value.Context = authenticatedDataString("")
|
||||
|
||||
type store struct {
|
||||
client *clientv3.Client
|
||||
// getOps contains additional options that should be passed
|
||||
// to all Get() calls.
|
||||
getOps []clientv3.OpOption
|
||||
client *clientv3.Client
|
||||
codec runtime.Codec
|
||||
versioner storage.Versioner
|
||||
transformer value.Transformer
|
||||
@ -115,13 +114,12 @@ func (s *store) Versioner() storage.Versioner {
|
||||
func (s *store) Get(ctx context.Context, key string, opts storage.GetOptions, out runtime.Object) error {
|
||||
key = path.Join(s.pathPrefix, key)
|
||||
startTime := time.Now()
|
||||
callOpts := s.getOps
|
||||
getResp, err := s.client.KV.Get(ctx, key, callOpts...)
|
||||
getResp, err := s.client.KV.Get(ctx, key)
|
||||
metrics.RecordEtcdRequestLatency("get", getTypeName(out), startTime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = s.ensureMinimumResourceVersion(opts.ResourceVersion, uint64(getResp.Header.Revision)); err != nil {
|
||||
if err = s.validateMinimumResourceVersion(opts.ResourceVersion, uint64(getResp.Header.Revision)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -252,7 +250,7 @@ func (s *store) GuaranteedUpdate(
|
||||
|
||||
getCurrentState := func() (*objState, error) {
|
||||
startTime := time.Now()
|
||||
getResp, err := s.client.KV.Get(ctx, key, s.getOps...)
|
||||
getResp, err := s.client.KV.Get(ctx, key)
|
||||
metrics.RecordEtcdRequestLatency("get", getTypeName(out), startTime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -382,10 +380,12 @@ func (s *store) GuaranteedUpdate(
|
||||
// GetToList implements storage.Interface.GetToList.
|
||||
func (s *store) GetToList(ctx context.Context, key string, listOpts storage.ListOptions, listObj runtime.Object) error {
|
||||
resourceVersion := listOpts.ResourceVersion
|
||||
match := listOpts.ResourceVersionMatch
|
||||
pred := listOpts.Predicate
|
||||
trace := utiltrace.New("GetToList etcd3",
|
||||
utiltrace.Field{"key", key},
|
||||
utiltrace.Field{"resourceVersion", resourceVersion},
|
||||
utiltrace.Field{"resourceVersionMatch", match},
|
||||
utiltrace.Field{"limit", pred.Limit},
|
||||
utiltrace.Field{"continue", pred.Continue})
|
||||
defer trace.LogIfLong(500 * time.Millisecond)
|
||||
@ -402,12 +402,21 @@ func (s *store) GetToList(ctx context.Context, key string, listOpts storage.List
|
||||
|
||||
key = path.Join(s.pathPrefix, key)
|
||||
startTime := time.Now()
|
||||
getResp, err := s.client.KV.Get(ctx, key, s.getOps...)
|
||||
var opts []clientv3.OpOption
|
||||
if len(resourceVersion) > 0 && match == metav1.ResourceVersionMatchExact {
|
||||
rv, err := s.versioner.ParseResourceVersion(resourceVersion)
|
||||
if err != nil {
|
||||
return apierrors.NewBadRequest(fmt.Sprintf("invalid resource version: %v", err))
|
||||
}
|
||||
opts = append(opts, clientv3.WithRev(int64(rv)))
|
||||
}
|
||||
|
||||
getResp, err := s.client.KV.Get(ctx, key, opts...)
|
||||
metrics.RecordEtcdRequestLatency("get", getTypeName(listPtr), startTime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = s.ensureMinimumResourceVersion(resourceVersion, uint64(getResp.Header.Revision)); err != nil {
|
||||
if err = s.validateMinimumResourceVersion(resourceVersion, uint64(getResp.Header.Revision)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -515,10 +524,12 @@ func encodeContinue(key, keyPrefix string, resourceVersion int64) (string, error
|
||||
// List implements storage.Interface.List.
|
||||
func (s *store) List(ctx context.Context, key string, opts storage.ListOptions, listObj runtime.Object) error {
|
||||
resourceVersion := opts.ResourceVersion
|
||||
match := opts.ResourceVersionMatch
|
||||
pred := opts.Predicate
|
||||
trace := utiltrace.New("List etcd3",
|
||||
utiltrace.Field{"key", key},
|
||||
utiltrace.Field{"resourceVersion", resourceVersion},
|
||||
utiltrace.Field{"resourceVersionMatch", match},
|
||||
utiltrace.Field{"limit", pred.Limit},
|
||||
utiltrace.Field{"continue", pred.Continue})
|
||||
defer trace.LogIfLong(500 * time.Millisecond)
|
||||
@ -552,6 +563,15 @@ func (s *store) List(ctx context.Context, key string, opts storage.ListOptions,
|
||||
|
||||
newItemFunc := getNewItemFunc(listObj, v)
|
||||
|
||||
var fromRV *uint64
|
||||
if len(resourceVersion) > 0 {
|
||||
parsedRV, err := s.versioner.ParseResourceVersion(resourceVersion)
|
||||
if err != nil {
|
||||
return apierrors.NewBadRequest(fmt.Sprintf("invalid resource version: %v", err))
|
||||
}
|
||||
fromRV = &parsedRV
|
||||
}
|
||||
|
||||
var returnedRV, continueRV int64
|
||||
var continueKey string
|
||||
switch {
|
||||
@ -577,20 +597,41 @@ func (s *store) List(ctx context.Context, key string, opts storage.ListOptions,
|
||||
returnedRV = continueRV
|
||||
}
|
||||
case s.pagingEnabled && pred.Limit > 0:
|
||||
if len(resourceVersion) > 0 {
|
||||
fromRV, err := s.versioner.ParseResourceVersion(resourceVersion)
|
||||
if err != nil {
|
||||
return apierrors.NewBadRequest(fmt.Sprintf("invalid resource version: %v", err))
|
||||
if fromRV != nil {
|
||||
switch match {
|
||||
case metav1.ResourceVersionMatchNotOlderThan:
|
||||
// The not older than constraint is checked after we get a response from etcd,
|
||||
// and returnedRV is then set to the revision we get from the etcd response.
|
||||
case metav1.ResourceVersionMatchExact:
|
||||
returnedRV = int64(*fromRV)
|
||||
options = append(options, clientv3.WithRev(returnedRV))
|
||||
case "": // legacy case
|
||||
if *fromRV > 0 {
|
||||
returnedRV = int64(*fromRV)
|
||||
options = append(options, clientv3.WithRev(returnedRV))
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown ResourceVersionMatch value: %v", match)
|
||||
}
|
||||
if fromRV > 0 {
|
||||
options = append(options, clientv3.WithRev(int64(fromRV)))
|
||||
}
|
||||
returnedRV = int64(fromRV)
|
||||
}
|
||||
|
||||
rangeEnd := clientv3.GetPrefixRangeEnd(keyPrefix)
|
||||
options = append(options, clientv3.WithRange(rangeEnd))
|
||||
default:
|
||||
if fromRV != nil {
|
||||
switch match {
|
||||
case metav1.ResourceVersionMatchNotOlderThan:
|
||||
// The not older than constraint is checked after we get a response from etcd,
|
||||
// and returnedRV is then set to the revision we get from the etcd response.
|
||||
case metav1.ResourceVersionMatchExact:
|
||||
returnedRV = int64(*fromRV)
|
||||
options = append(options, clientv3.WithRev(returnedRV))
|
||||
case "": // legacy case
|
||||
default:
|
||||
return fmt.Errorf("unknown ResourceVersionMatch value: %v", match)
|
||||
}
|
||||
}
|
||||
|
||||
options = append(options, clientv3.WithPrefix())
|
||||
}
|
||||
|
||||
@ -605,7 +646,7 @@ func (s *store) List(ctx context.Context, key string, opts storage.ListOptions,
|
||||
if err != nil {
|
||||
return interpretListError(err, len(pred.Continue) > 0, continueKey, keyPrefix)
|
||||
}
|
||||
if err = s.ensureMinimumResourceVersion(resourceVersion, uint64(getResp.Header.Revision)); err != nil {
|
||||
if err = s.validateMinimumResourceVersion(resourceVersion, uint64(getResp.Header.Revision)); err != nil {
|
||||
return err
|
||||
}
|
||||
hasMore = getResp.More
|
||||
@ -822,9 +863,9 @@ func (s *store) ttlOpts(ctx context.Context, ttl int64) ([]clientv3.OpOption, er
|
||||
return []clientv3.OpOption{clientv3.WithLease(id)}, nil
|
||||
}
|
||||
|
||||
// ensureMinimumResourceVersion returns a 'too large resource' version error when the provided minimumResourceVersion is
|
||||
// validateMinimumResourceVersion returns a 'too large resource' version error when the provided minimumResourceVersion is
|
||||
// greater than the most recent actualRevision available from storage.
|
||||
func (s *store) ensureMinimumResourceVersion(minimumResourceVersion string, actualRevision uint64) error {
|
||||
func (s *store) validateMinimumResourceVersion(minimumResourceVersion string, actualRevision uint64) error {
|
||||
if minimumResourceVersion == "" {
|
||||
return nil
|
||||
}
|
||||
|
@ -373,6 +373,10 @@ func TestConditionalDelete(t *testing.T) {
|
||||
func TestGetToList(t *testing.T) {
|
||||
ctx, store, cluster := testSetup(t)
|
||||
defer cluster.Terminate(t)
|
||||
prevKey, prevStoredObj := testPropogateStore(ctx, t, store, &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "prev"}})
|
||||
|
||||
prevRV, _ := strconv.Atoi(prevStoredObj.ResourceVersion)
|
||||
|
||||
key, storedObj := testPropogateStore(ctx, t, store, &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})
|
||||
|
||||
currentRV, _ := strconv.Atoi(storedObj.ResourceVersion)
|
||||
@ -382,6 +386,7 @@ func TestGetToList(t *testing.T) {
|
||||
pred storage.SelectionPredicate
|
||||
expectedOut []*example.Pod
|
||||
rv string
|
||||
rvMatch metav1.ResourceVersionMatch
|
||||
expectRVTooLarge bool
|
||||
}{{ // test GetToList on existing key
|
||||
key: key,
|
||||
@ -392,11 +397,41 @@ func TestGetToList(t *testing.T) {
|
||||
pred: storage.Everything,
|
||||
expectedOut: []*example.Pod{storedObj},
|
||||
rv: "0",
|
||||
}, { // test GetToList on existing key with minimum resource version set to 0, match=minimum
|
||||
key: key,
|
||||
pred: storage.Everything,
|
||||
expectedOut: []*example.Pod{storedObj},
|
||||
rv: "0",
|
||||
rvMatch: metav1.ResourceVersionMatchNotOlderThan,
|
||||
}, { // test GetToList on existing key with minimum resource version set to current resource version
|
||||
key: key,
|
||||
pred: storage.Everything,
|
||||
expectedOut: []*example.Pod{storedObj},
|
||||
rv: fmt.Sprintf("%d", currentRV),
|
||||
}, { // test GetToList on existing key with minimum resource version set to current resource version, match=minimum
|
||||
key: key,
|
||||
pred: storage.Everything,
|
||||
expectedOut: []*example.Pod{storedObj},
|
||||
rv: fmt.Sprintf("%d", currentRV),
|
||||
rvMatch: metav1.ResourceVersionMatchNotOlderThan,
|
||||
}, { // test GetToList on existing key with minimum resource version set to previous resource version, match=minimum
|
||||
key: key,
|
||||
pred: storage.Everything,
|
||||
expectedOut: []*example.Pod{storedObj},
|
||||
rv: fmt.Sprintf("%d", prevRV),
|
||||
rvMatch: metav1.ResourceVersionMatchNotOlderThan,
|
||||
}, { // test GetToList on existing key with resource version set to current resource version, match=exact
|
||||
key: key,
|
||||
pred: storage.Everything,
|
||||
expectedOut: []*example.Pod{storedObj},
|
||||
rv: fmt.Sprintf("%d", currentRV),
|
||||
rvMatch: metav1.ResourceVersionMatchExact,
|
||||
}, { // test GetToList on existing key with resource version set to previous resource version, match=exact
|
||||
key: prevKey,
|
||||
pred: storage.Everything,
|
||||
expectedOut: []*example.Pod{prevStoredObj},
|
||||
rv: fmt.Sprintf("%d", prevRV),
|
||||
rvMatch: metav1.ResourceVersionMatchExact,
|
||||
}, { // test GetToList on existing key with minimum resource version set too high
|
||||
key: key,
|
||||
pred: storage.Everything,
|
||||
@ -422,7 +457,7 @@ func TestGetToList(t *testing.T) {
|
||||
|
||||
for i, tt := range tests {
|
||||
out := &example.PodList{}
|
||||
err := store.GetToList(ctx, tt.key, storage.ListOptions{ResourceVersion: tt.rv, Predicate: tt.pred}, out)
|
||||
err := store.GetToList(ctx, tt.key, storage.ListOptions{ResourceVersion: tt.rv, ResourceVersionMatch: tt.rvMatch, Predicate: tt.pred}, out)
|
||||
|
||||
if tt.expectRVTooLarge {
|
||||
if err == nil || !storage.IsTooLargeResourceVersion(err) {
|
||||
@ -934,6 +969,7 @@ func TestList(t *testing.T) {
|
||||
name string
|
||||
disablePaging bool
|
||||
rv string
|
||||
rvMatch metav1.ResourceVersionMatch
|
||||
prefix string
|
||||
pred storage.SelectionPredicate
|
||||
expectedOut []*example.Pod
|
||||
@ -981,6 +1017,31 @@ func TestList(t *testing.T) {
|
||||
expectedOut: []*example.Pod{preset[0].storedObj},
|
||||
rv: "0",
|
||||
},
|
||||
{
|
||||
name: "test List on existing key with resource version set to 1, match=Exact",
|
||||
prefix: "/one-level/",
|
||||
pred: storage.Everything,
|
||||
expectedOut: []*example.Pod{},
|
||||
rv: "1",
|
||||
rvMatch: metav1.ResourceVersionMatchExact,
|
||||
expectRV: "1",
|
||||
},
|
||||
{
|
||||
name: "test List on existing key with resource version set to 1, match=NotOlderThan",
|
||||
prefix: "/one-level/",
|
||||
pred: storage.Everything,
|
||||
expectedOut: []*example.Pod{preset[0].storedObj},
|
||||
rv: "0",
|
||||
rvMatch: metav1.ResourceVersionMatchNotOlderThan,
|
||||
},
|
||||
{
|
||||
name: "test List on existing key with resource version set to 1, match=Invalid",
|
||||
prefix: "/one-level/",
|
||||
pred: storage.Everything,
|
||||
rv: "0",
|
||||
rvMatch: "Invalid",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "test List on existing key with resource version set to current resource version",
|
||||
prefix: "/one-level/",
|
||||
@ -988,6 +1049,23 @@ func TestList(t *testing.T) {
|
||||
expectedOut: []*example.Pod{preset[0].storedObj},
|
||||
rv: list.ResourceVersion,
|
||||
},
|
||||
{
|
||||
name: "test List on existing key with resource version set to current resource version, match=Exact",
|
||||
prefix: "/one-level/",
|
||||
pred: storage.Everything,
|
||||
expectedOut: []*example.Pod{preset[0].storedObj},
|
||||
rv: list.ResourceVersion,
|
||||
rvMatch: metav1.ResourceVersionMatchExact,
|
||||
expectRV: list.ResourceVersion,
|
||||
},
|
||||
{
|
||||
name: "test List on existing key with resource version set to current resource version, match=NotOlderThan",
|
||||
prefix: "/one-level/",
|
||||
pred: storage.Everything,
|
||||
expectedOut: []*example.Pod{preset[0].storedObj},
|
||||
rv: list.ResourceVersion,
|
||||
rvMatch: metav1.ResourceVersionMatchNotOlderThan,
|
||||
},
|
||||
{
|
||||
name: "test List on non-existing key",
|
||||
prefix: "/non-existing/",
|
||||
@ -1029,6 +1107,21 @@ func TestList(t *testing.T) {
|
||||
rv: list.ResourceVersion,
|
||||
expectRV: list.ResourceVersion,
|
||||
},
|
||||
{
|
||||
name: "test List with limit at current resource version and match=Exact",
|
||||
prefix: "/two-level/",
|
||||
pred: storage.SelectionPredicate{
|
||||
Label: labels.Everything(),
|
||||
Field: fields.Everything(),
|
||||
Limit: 1,
|
||||
},
|
||||
expectedOut: []*example.Pod{preset[1].storedObj},
|
||||
expectContinue: true,
|
||||
expectedRemainingItemCount: utilpointer.Int64Ptr(1),
|
||||
rv: list.ResourceVersion,
|
||||
rvMatch: metav1.ResourceVersionMatchExact,
|
||||
expectRV: list.ResourceVersion,
|
||||
},
|
||||
{
|
||||
name: "test List with limit at resource version 0",
|
||||
prefix: "/two-level/",
|
||||
@ -1043,6 +1136,49 @@ func TestList(t *testing.T) {
|
||||
rv: "0",
|
||||
expectRV: list.ResourceVersion,
|
||||
},
|
||||
{
|
||||
name: "test List with limit at resource version 0 match=NotOlderThan",
|
||||
prefix: "/two-level/",
|
||||
pred: storage.SelectionPredicate{
|
||||
Label: labels.Everything(),
|
||||
Field: fields.Everything(),
|
||||
Limit: 1,
|
||||
},
|
||||
expectedOut: []*example.Pod{preset[1].storedObj},
|
||||
expectContinue: true,
|
||||
expectedRemainingItemCount: utilpointer.Int64Ptr(1),
|
||||
rv: "0",
|
||||
rvMatch: metav1.ResourceVersionMatchNotOlderThan,
|
||||
expectRV: list.ResourceVersion,
|
||||
},
|
||||
{
|
||||
name: "test List with limit at resource version 1 and match=Exact",
|
||||
prefix: "/two-level/",
|
||||
pred: storage.SelectionPredicate{
|
||||
Label: labels.Everything(),
|
||||
Field: fields.Everything(),
|
||||
Limit: 1,
|
||||
},
|
||||
expectedOut: []*example.Pod{},
|
||||
expectContinue: false,
|
||||
rv: "1",
|
||||
rvMatch: metav1.ResourceVersionMatchExact,
|
||||
expectRV: "1",
|
||||
},
|
||||
{
|
||||
name: "test List with limit at old resource version and match=Exact",
|
||||
prefix: "/two-level/",
|
||||
pred: storage.SelectionPredicate{
|
||||
Label: labels.Everything(),
|
||||
Field: fields.Everything(),
|
||||
Limit: 1,
|
||||
},
|
||||
expectedOut: []*example.Pod{},
|
||||
expectContinue: false,
|
||||
rv: "1",
|
||||
rvMatch: metav1.ResourceVersionMatchExact,
|
||||
expectRV: "1",
|
||||
},
|
||||
{
|
||||
name: "test List with limit when paging disabled",
|
||||
disablePaging: true,
|
||||
@ -1201,7 +1337,7 @@ func TestList(t *testing.T) {
|
||||
}
|
||||
|
||||
out := &example.PodList{}
|
||||
storageOpts := storage.ListOptions{ResourceVersion: tt.rv, Predicate: tt.pred}
|
||||
storageOpts := storage.ListOptions{ResourceVersion: tt.rv, ResourceVersionMatch: tt.rvMatch, Predicate: tt.pred}
|
||||
var err error
|
||||
if tt.disablePaging {
|
||||
err = disablePagingStore.List(ctx, tt.prefix, storageOpts, out)
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@ -189,17 +190,20 @@ type Interface interface {
|
||||
// Get unmarshals json found at key into objPtr. On a not found error, will either
|
||||
// return a zero object of the requested type, or an error, depending on 'opts.ignoreNotFound'.
|
||||
// Treats empty responses and nil response nodes exactly like a not found error.
|
||||
// The returned contents may be delayed according to the semantics of GetOptions.ResourceVersion.
|
||||
// The returned contents may be delayed, but it is guaranteed that they will
|
||||
// match 'opts.ResourceVersion' according 'opts.ResourceVersionMatch'.
|
||||
Get(ctx context.Context, key string, opts GetOptions, objPtr runtime.Object) error
|
||||
|
||||
// GetToList unmarshals json found at key and opaque it into *List api object
|
||||
// (an object that satisfies the runtime.IsList definition).
|
||||
// The returned contents may be delayed according to the semantics of ListOptions.ResourceVersion.
|
||||
// The returned contents may be delayed, but it is guaranteed that they will
|
||||
// match 'opts.ResourceVersion' according 'opts.ResourceVersionMatch'.
|
||||
GetToList(ctx context.Context, key string, opts ListOptions, listObj runtime.Object) error
|
||||
|
||||
// List unmarshalls jsons found at directory defined by key and opaque them
|
||||
// into *List api object (an object that satisfies runtime.IsList definition).
|
||||
// The returned contents may be delayed according to the semantics of ListOptions.ResourceVersion.
|
||||
// The returned contents may be delayed, but it is guaranteed that they will
|
||||
// match 'opts.ResourceVersion' according 'opts.ResourceVersionMatch'.
|
||||
List(ctx context.Context, key string, opts ListOptions, listObj runtime.Object) error
|
||||
|
||||
// GuaranteedUpdate keeps calling 'tryUpdate()' to update key 'key' (of type 'ptrToType')
|
||||
@ -260,6 +264,9 @@ type ListOptions struct {
|
||||
// ResourceVersion. The newest available data is preferred, but any data not older than this
|
||||
// ResourceVersion may be served.
|
||||
ResourceVersion string
|
||||
// ResourceVersionMatch provides the rule for how the resource version constraint applies. If set
|
||||
// to the default value "" the legacy resource version semantic apply.
|
||||
ResourceVersionMatch metav1.ResourceVersionMatch
|
||||
// Predicate provides the selection rules for the list operation.
|
||||
Predicate SelectionPredicate
|
||||
}
|
||||
|
@ -623,7 +623,7 @@ func schema_pkg_apis_meta_v1_GetOptions(ref common.ReferenceCallback) common.Ope
|
||||
},
|
||||
"resourceVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "When specified: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
Description: "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
@ -1064,7 +1064,14 @@ func schema_pkg_apis_meta_v1_ListOptions(ref common.ReferenceCallback) common.Op
|
||||
},
|
||||
"resourceVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
Description: "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"resourceVersionMatch": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
|
@ -626,7 +626,7 @@ func schema_pkg_apis_meta_v1_GetOptions(ref common.ReferenceCallback) common.Ope
|
||||
},
|
||||
"resourceVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "When specified: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
Description: "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
@ -1067,7 +1067,14 @@ func schema_pkg_apis_meta_v1_ListOptions(ref common.ReferenceCallback) common.Op
|
||||
},
|
||||
"resourceVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
Description: "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"resourceVersionMatch": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
|
@ -624,7 +624,7 @@ func schema_pkg_apis_meta_v1_GetOptions(ref common.ReferenceCallback) common.Ope
|
||||
},
|
||||
"resourceVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "When specified: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
Description: "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
@ -1065,7 +1065,14 @@ func schema_pkg_apis_meta_v1_ListOptions(ref common.ReferenceCallback) common.Op
|
||||
},
|
||||
"resourceVersion": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
Description: "resourceVersion sets a constraint on what resource versions a request may be served from. See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"resourceVersionMatch": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
|
@ -61,6 +61,7 @@ go_test(
|
||||
"//staging/src/k8s.io/client-go/discovery/cached/disk:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/dynamic:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/typed/apps/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/metadata:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
@ -68,6 +69,7 @@ go_test(
|
||||
"//staging/src/k8s.io/client-go/tools/pager:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||
"//staging/src/k8s.io/kubectl/pkg/cmd/util:go_default_library",
|
||||
"//test/integration:go_default_library",
|
||||
"//test/integration/framework:go_default_library",
|
||||
"//vendor/github.com/google/uuid:go_default_library",
|
||||
"//vendor/k8s.io/gengo/examples/set-gen/sets:go_default_library",
|
||||
|
@ -54,12 +54,15 @@ import (
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/dynamic"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
|
||||
"k8s.io/client-go/metadata"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/pager"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/kubernetes/pkg/master"
|
||||
"k8s.io/kubernetes/test/integration"
|
||||
"k8s.io/kubernetes/test/integration/framework"
|
||||
)
|
||||
|
||||
@ -86,7 +89,7 @@ func setupWithResourcesWithOptions(t *testing.T, opts *framework.MasterConfigOpt
|
||||
masterConfig.GenericConfig.OpenAPIConfig = framework.DefaultOpenAPIConfig()
|
||||
_, s, closeFn := framework.RunAMaster(masterConfig)
|
||||
|
||||
clientSet, err := clientset.NewForConfig(&restclient.Config{Host: s.URL})
|
||||
clientSet, err := clientset.NewForConfig(&restclient.Config{Host: s.URL, QPS: -1})
|
||||
if err != nil {
|
||||
t.Fatalf("Error in create clientset: %v", err)
|
||||
}
|
||||
@ -309,6 +312,207 @@ func Test202StatusCode(t *testing.T) {
|
||||
verifyStatusCode(t, "DELETE", s.URL+path.Join("/apis/apps/v1/namespaces", ns.Name, "replicasets", rs.Name), cascDel, 202)
|
||||
}
|
||||
|
||||
var (
|
||||
invalidContinueToken = "invalidContinueToken"
|
||||
invalidResourceVersion = "invalid"
|
||||
invalidResourceVersionMatch = metav1.ResourceVersionMatch("InvalidMatch")
|
||||
)
|
||||
|
||||
// TestListOptions ensures that list works as expected for valid and invalid combinations of limit, continue,
|
||||
// resourceVersion and resourceVersionMatch.
|
||||
func TestListOptions(t *testing.T) {
|
||||
for _, watchCacheEnabled := range []bool{true, false} {
|
||||
t.Run(fmt.Sprintf("watchCacheEnabled=%t", watchCacheEnabled), func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.APIListChunking, true)()
|
||||
etcdOptions := framework.DefaultEtcdOptions()
|
||||
etcdOptions.EnableWatchCache = watchCacheEnabled
|
||||
s, clientSet, closeFn := setupWithOptions(t, &framework.MasterConfigOptions{EtcdOptions: etcdOptions})
|
||||
defer closeFn()
|
||||
|
||||
ns := framework.CreateTestingNamespace("list-options", s, t)
|
||||
defer framework.DeleteTestingNamespace(ns, s, t)
|
||||
|
||||
rsClient := clientSet.AppsV1().ReplicaSets(ns.Name)
|
||||
|
||||
var compactedRv, oldestUncompactedRv string
|
||||
for i := 0; i < 15; i++ {
|
||||
rs := newRS(ns.Name)
|
||||
rs.Name = fmt.Sprintf("test-%d", i)
|
||||
created, err := rsClient.Create(context.Background(), rs, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if i == 0 {
|
||||
compactedRv = created.ResourceVersion // We compact this first resource version below
|
||||
}
|
||||
// delete the first 5, and then compact them
|
||||
if i < 5 {
|
||||
var zero int64
|
||||
if err := rsClient.Delete(context.Background(), rs.Name, metav1.DeleteOptions{GracePeriodSeconds: &zero}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
oldestUncompactedRv = created.ResourceVersion
|
||||
}
|
||||
}
|
||||
|
||||
// compact some of the revision history in etcd so we can test "too old" resource versions
|
||||
_, kvClient, err := integration.GetEtcdClients(etcdOptions.StorageConfig.Transport)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
revision, err := strconv.Atoi(oldestUncompactedRv)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = kvClient.Compact(context.Background(), int64(revision))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
listObj, err := rsClient.List(context.Background(), metav1.ListOptions{
|
||||
Limit: 6,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
validContinueToken := listObj.Continue
|
||||
|
||||
// test all combinations of these, for both watch cache enabled and disabled:
|
||||
limits := []int64{0, 6}
|
||||
continueTokens := []string{"", validContinueToken, invalidContinueToken}
|
||||
rvs := []string{"", "0", compactedRv, invalidResourceVersion}
|
||||
rvMatches := []metav1.ResourceVersionMatch{
|
||||
"",
|
||||
metav1.ResourceVersionMatchNotOlderThan,
|
||||
metav1.ResourceVersionMatchExact,
|
||||
invalidResourceVersionMatch,
|
||||
}
|
||||
|
||||
for _, limit := range limits {
|
||||
for _, continueToken := range continueTokens {
|
||||
for _, rv := range rvs {
|
||||
for _, rvMatch := range rvMatches {
|
||||
name := fmt.Sprintf("limit=%d continue=%s rv=%s rvMatch=%s", limit, continueToken, rv, rvMatch)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
opts := metav1.ListOptions{
|
||||
ResourceVersion: rv,
|
||||
ResourceVersionMatch: rvMatch,
|
||||
Continue: continueToken,
|
||||
Limit: limit,
|
||||
}
|
||||
testListOptionsCase(t, rsClient, watchCacheEnabled, opts, compactedRv)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testListOptionsCase(t *testing.T, rsClient appsv1.ReplicaSetInterface, watchCacheEnabled bool, opts metav1.ListOptions, compactedRv string) {
|
||||
listObj, err := rsClient.List(context.Background(), opts)
|
||||
|
||||
// check for expected validation errors
|
||||
if opts.ResourceVersion == "" && opts.ResourceVersionMatch != "" {
|
||||
if err == nil || !strings.Contains(err.Error(), "resourceVersionMatch is forbidden unless resourceVersion is provided") {
|
||||
t.Fatalf("expected forbidden error, but got: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if opts.Continue != "" && opts.ResourceVersionMatch != "" {
|
||||
if err == nil || !strings.Contains(err.Error(), "resourceVersionMatch is forbidden when continue is provided") {
|
||||
t.Fatalf("expected forbidden error, but got: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if opts.ResourceVersionMatch == invalidResourceVersionMatch {
|
||||
if err == nil || !strings.Contains(err.Error(), "supported values") {
|
||||
t.Fatalf("expected not supported error, but got: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if opts.ResourceVersionMatch == metav1.ResourceVersionMatchExact && opts.ResourceVersion == "0" {
|
||||
if err == nil || !strings.Contains(err.Error(), "resourceVersionMatch \"exact\" is forbidden for resourceVersion \"0\"") {
|
||||
t.Fatalf("expected forbidden error, but got: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if opts.ResourceVersion == invalidResourceVersion {
|
||||
if err == nil || !strings.Contains(err.Error(), "Invalid value") {
|
||||
t.Fatalf("expecting invalid value error, but got: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if opts.Continue == invalidContinueToken {
|
||||
if err == nil || !strings.Contains(err.Error(), "continue key is not valid") {
|
||||
t.Fatalf("expected continue key not valid error, but got: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
// Should not be allowed for any resource version, but tightening the validation would be a breaking change
|
||||
if opts.Continue != "" && !(opts.ResourceVersion == "" || opts.ResourceVersion == "0") {
|
||||
if err == nil || !strings.Contains(err.Error(), "specifying resource version is not allowed when using continue") {
|
||||
t.Fatalf("expected not allowed error, but got: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Check for too old errors
|
||||
isExact := opts.ResourceVersionMatch == metav1.ResourceVersionMatchExact
|
||||
// Legacy corner cases that can be avoided by using an explicit resourceVersionMatch value
|
||||
// see https://kubernetes.io/docs/reference/using-api/api-concepts/#the-resourceversion-parameter
|
||||
isLegacyExact := opts.Limit > 0 && opts.ResourceVersionMatch == ""
|
||||
|
||||
if opts.ResourceVersion == compactedRv && (isExact || isLegacyExact) {
|
||||
if err == nil || !strings.Contains(err.Error(), "The resourceVersion for the provided list is too old") {
|
||||
t.Fatalf("expected too old error, but got: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// test successful responses
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
items, err := meta.ExtractList(listObj)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to extract list from %v", listObj)
|
||||
}
|
||||
count := int64(len(items))
|
||||
|
||||
// Cacher.GetToList defines this for logic to decide if the watch cache is skipped. We need to know it to know if
|
||||
// the limit is respected when testing here.
|
||||
pagingEnabled := utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking)
|
||||
hasContinuation := pagingEnabled && len(opts.Continue) > 0
|
||||
hasLimit := pagingEnabled && opts.Limit > 0 && opts.ResourceVersion != "0"
|
||||
skipWatchCache := opts.ResourceVersion == "" || hasContinuation || hasLimit || isExact
|
||||
usingWatchCache := watchCacheEnabled && !skipWatchCache
|
||||
|
||||
if usingWatchCache { // watch cache does not respect limit and is not used for continue
|
||||
if count != 10 {
|
||||
t.Errorf("Expected list size to be 10 but got %d", count) // limit is ignored if watch cache is hit
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if opts.Continue != "" {
|
||||
if count != 4 {
|
||||
t.Errorf("Expected list size of 4 but got %d", count)
|
||||
}
|
||||
return
|
||||
}
|
||||
if opts.Limit > 0 {
|
||||
if count != opts.Limit {
|
||||
t.Errorf("Expected list size to be limited to %d but got %d", opts.Limit, count)
|
||||
}
|
||||
return
|
||||
}
|
||||
if count != 10 {
|
||||
t.Errorf("Expected list size to be 10 but got %d", count)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListResourceVersion0(t *testing.T) {
|
||||
var testcases = []struct {
|
||||
name string
|
||||
|
1
vendor/modules.txt
vendored
1
vendor/modules.txt
vendored
@ -1642,6 +1642,7 @@ k8s.io/apimachinery/pkg/api/validation/path
|
||||
k8s.io/apimachinery/pkg/apis/meta/fuzzer
|
||||
k8s.io/apimachinery/pkg/apis/meta/internalversion
|
||||
k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme
|
||||
k8s.io/apimachinery/pkg/apis/meta/internalversion/validation
|
||||
k8s.io/apimachinery/pkg/apis/meta/v1
|
||||
k8s.io/apimachinery/pkg/apis/meta/v1/unstructured
|
||||
k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme
|
||||
|
Loading…
Reference in New Issue
Block a user