mirror of
https://github.com/kubernetes/client-go.git
synced 2026-05-16 12:22:43 +00:00
Compare commits
140 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7226b15af0 | ||
|
|
166ab05d11 | ||
|
|
4b5a63801d | ||
|
|
1904631ef0 | ||
|
|
8f4eb75bce | ||
|
|
e278668ebe | ||
|
|
1874bc6496 | ||
|
|
db7e2d829e | ||
|
|
c9008f3abb | ||
|
|
1a46dfdf57 | ||
|
|
b3e4a4065a | ||
|
|
c2f61ae20a | ||
|
|
54e42ab6f2 | ||
|
|
ef26118838 | ||
|
|
a890e7bc14 | ||
|
|
f10f16e029 | ||
|
|
3300752b61 | ||
|
|
ce9ac379ec | ||
|
|
4100519c43 | ||
|
|
c439b2507d | ||
|
|
76884cd2d8 | ||
|
|
a00e9abf6c | ||
|
|
55b6f70f83 | ||
|
|
606e4a8099 | ||
|
|
fe9020e749 | ||
|
|
e803ec6bfc | ||
|
|
07171f82e7 | ||
|
|
b5feb253b6 | ||
|
|
c5a511a525 | ||
|
|
bebf21907c | ||
|
|
68639ba114 | ||
|
|
b0d4101b8e | ||
|
|
1631be4c27 | ||
|
|
912b04a8ad | ||
|
|
3dfaef50d7 | ||
|
|
3e9c4b4f17 | ||
|
|
2037cc6a9a | ||
|
|
07735eaa93 | ||
|
|
2190b2f23b | ||
|
|
95367f2044 | ||
|
|
ec0f33729d | ||
|
|
c2d2c47718 | ||
|
|
fe12e65afd | ||
|
|
761f55c9e0 | ||
|
|
7a55c3b96b | ||
|
|
cc879cd5b6 | ||
|
|
b5c7588f8a | ||
|
|
ff6bf679aa | ||
|
|
b2097e607c | ||
|
|
4db4856058 | ||
|
|
95a40e254c | ||
|
|
267b6570f5 | ||
|
|
0cfc9635b9 | ||
|
|
2a6c116e40 | ||
|
|
ca60e0ea14 | ||
|
|
9dde02d660 | ||
|
|
65b1e7d3c0 | ||
|
|
c6bd30b9ec | ||
|
|
441e2c8c97 | ||
|
|
735524f850 | ||
|
|
4aac6a7c9c | ||
|
|
b4c3510afd | ||
|
|
828c3cb11b | ||
|
|
1ea239faa5 | ||
|
|
76fccca0ea | ||
|
|
04f67d5d4f | ||
|
|
4e28921c86 | ||
|
|
163ee0b6d7 | ||
|
|
743e29dc1f | ||
|
|
79a582f2eb | ||
|
|
eabd4289b0 | ||
|
|
7c3fa18b11 | ||
|
|
59fda2e669 | ||
|
|
2f582c2a40 | ||
|
|
84e1219642 | ||
|
|
3b969f9680 | ||
|
|
7f7dbbc80a | ||
|
|
f295032991 | ||
|
|
26b506437f | ||
|
|
506ef8944c | ||
|
|
123d4e7e38 | ||
|
|
e2ef40870b | ||
|
|
ed7d154cc2 | ||
|
|
61a7d9d6e1 | ||
|
|
a16e76eb69 | ||
|
|
6a58c3a5c7 | ||
|
|
f5b6af4563 | ||
|
|
1b23c1577a | ||
|
|
8dfe88aeff | ||
|
|
899bcd7409 | ||
|
|
0647d43372 | ||
|
|
9ac8bfecbb | ||
|
|
cb4a10df41 | ||
|
|
64585cf823 | ||
|
|
acab036eff | ||
|
|
830d4c4624 | ||
|
|
e0fa50410b | ||
|
|
2a9f955190 | ||
|
|
d4fc9af2df | ||
|
|
08b4bbc4f6 | ||
|
|
7e1edab3f7 | ||
|
|
87a5b7b3b7 | ||
|
|
5ce7078061 | ||
|
|
cf0ba13096 | ||
|
|
f88de91ae5 | ||
|
|
e2598a43a3 | ||
|
|
cf13620092 | ||
|
|
33115b49ac | ||
|
|
71b8c174e4 | ||
|
|
0bc005e72f | ||
|
|
876406445a | ||
|
|
ef63e495ba | ||
|
|
1f7dc8805f | ||
|
|
77f63643f9 | ||
|
|
b4b8e5e1e5 | ||
|
|
5bb1a76702 | ||
|
|
24209264f7 | ||
|
|
7c5b74295f | ||
|
|
5a9c3acf9d | ||
|
|
c0ab12afa7 | ||
|
|
bb66d8065b | ||
|
|
f4c553f30d | ||
|
|
631da0c65f | ||
|
|
28feddd66c | ||
|
|
a8fbc496ab | ||
|
|
ac3e4baf0f | ||
|
|
ccff9638f3 | ||
|
|
671a40c59f | ||
|
|
211d8a7adf | ||
|
|
2cf1a8ffd6 | ||
|
|
748150502e | ||
|
|
28c4a4d40f | ||
|
|
152e68ff13 | ||
|
|
28ccde769f | ||
|
|
4eab6be14c | ||
|
|
f9fdccdfc3 | ||
|
|
1f8debfcd2 | ||
|
|
c301d448ce | ||
|
|
f19a514ff5 | ||
|
|
21f4308ca2 |
@@ -21,7 +21,7 @@ package v1
|
||||
import (
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
corev1 "k8s.io/client-go/applyconfigurations/core/v1"
|
||||
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
|
||||
metav1 "k8s.io/client-go/applyconfigurations/meta/v1"
|
||||
)
|
||||
|
||||
// JobSpecApplyConfiguration represents an declarative configuration of the JobSpec type for use
|
||||
@@ -30,8 +30,9 @@ type JobSpecApplyConfiguration struct {
|
||||
Parallelism *int32 `json:"parallelism,omitempty"`
|
||||
Completions *int32 `json:"completions,omitempty"`
|
||||
ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty"`
|
||||
PodFailurePolicy *PodFailurePolicyApplyConfiguration `json:"podFailurePolicy,omitempty"`
|
||||
BackoffLimit *int32 `json:"backoffLimit,omitempty"`
|
||||
Selector *v1.LabelSelectorApplyConfiguration `json:"selector,omitempty"`
|
||||
Selector *metav1.LabelSelectorApplyConfiguration `json:"selector,omitempty"`
|
||||
ManualSelector *bool `json:"manualSelector,omitempty"`
|
||||
Template *corev1.PodTemplateSpecApplyConfiguration `json:"template,omitempty"`
|
||||
TTLSecondsAfterFinished *int32 `json:"ttlSecondsAfterFinished,omitempty"`
|
||||
@@ -69,6 +70,14 @@ func (b *JobSpecApplyConfiguration) WithActiveDeadlineSeconds(value int64) *JobS
|
||||
return b
|
||||
}
|
||||
|
||||
// WithPodFailurePolicy sets the PodFailurePolicy field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the PodFailurePolicy field is set to the value of the last call.
|
||||
func (b *JobSpecApplyConfiguration) WithPodFailurePolicy(value *PodFailurePolicyApplyConfiguration) *JobSpecApplyConfiguration {
|
||||
b.PodFailurePolicy = value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithBackoffLimit sets the BackoffLimit field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the BackoffLimit field is set to the value of the last call.
|
||||
@@ -80,7 +89,7 @@ func (b *JobSpecApplyConfiguration) WithBackoffLimit(value int32) *JobSpecApplyC
|
||||
// WithSelector sets the Selector field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Selector field is set to the value of the last call.
|
||||
func (b *JobSpecApplyConfiguration) WithSelector(value *v1.LabelSelectorApplyConfiguration) *JobSpecApplyConfiguration {
|
||||
func (b *JobSpecApplyConfiguration) WithSelector(value *metav1.LabelSelectorApplyConfiguration) *JobSpecApplyConfiguration {
|
||||
b.Selector = value
|
||||
return b
|
||||
}
|
||||
|
||||
44
applyconfigurations/batch/v1/podfailurepolicy.go
Normal file
44
applyconfigurations/batch/v1/podfailurepolicy.go
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
// PodFailurePolicyApplyConfiguration represents an declarative configuration of the PodFailurePolicy type for use
|
||||
// with apply.
|
||||
type PodFailurePolicyApplyConfiguration struct {
|
||||
Rules []PodFailurePolicyRuleApplyConfiguration `json:"rules,omitempty"`
|
||||
}
|
||||
|
||||
// PodFailurePolicyApplyConfiguration constructs an declarative configuration of the PodFailurePolicy type for use with
|
||||
// apply.
|
||||
func PodFailurePolicy() *PodFailurePolicyApplyConfiguration {
|
||||
return &PodFailurePolicyApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithRules adds the given value to the Rules field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, values provided by each call will be appended to the Rules field.
|
||||
func (b *PodFailurePolicyApplyConfiguration) WithRules(values ...*PodFailurePolicyRuleApplyConfiguration) *PodFailurePolicyApplyConfiguration {
|
||||
for i := range values {
|
||||
if values[i] == nil {
|
||||
panic("nil value passed to WithRules")
|
||||
}
|
||||
b.Rules = append(b.Rules, *values[i])
|
||||
}
|
||||
return b
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/batch/v1"
|
||||
)
|
||||
|
||||
// PodFailurePolicyOnExitCodesRequirementApplyConfiguration represents an declarative configuration of the PodFailurePolicyOnExitCodesRequirement type for use
|
||||
// with apply.
|
||||
type PodFailurePolicyOnExitCodesRequirementApplyConfiguration struct {
|
||||
ContainerName *string `json:"containerName,omitempty"`
|
||||
Operator *v1.PodFailurePolicyOnExitCodesOperator `json:"operator,omitempty"`
|
||||
Values []int32 `json:"values,omitempty"`
|
||||
}
|
||||
|
||||
// PodFailurePolicyOnExitCodesRequirementApplyConfiguration constructs an declarative configuration of the PodFailurePolicyOnExitCodesRequirement type for use with
|
||||
// apply.
|
||||
func PodFailurePolicyOnExitCodesRequirement() *PodFailurePolicyOnExitCodesRequirementApplyConfiguration {
|
||||
return &PodFailurePolicyOnExitCodesRequirementApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithContainerName sets the ContainerName field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the ContainerName field is set to the value of the last call.
|
||||
func (b *PodFailurePolicyOnExitCodesRequirementApplyConfiguration) WithContainerName(value string) *PodFailurePolicyOnExitCodesRequirementApplyConfiguration {
|
||||
b.ContainerName = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithOperator sets the Operator field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Operator field is set to the value of the last call.
|
||||
func (b *PodFailurePolicyOnExitCodesRequirementApplyConfiguration) WithOperator(value v1.PodFailurePolicyOnExitCodesOperator) *PodFailurePolicyOnExitCodesRequirementApplyConfiguration {
|
||||
b.Operator = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithValues adds the given value to the Values field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, values provided by each call will be appended to the Values field.
|
||||
func (b *PodFailurePolicyOnExitCodesRequirementApplyConfiguration) WithValues(values ...int32) *PodFailurePolicyOnExitCodesRequirementApplyConfiguration {
|
||||
for i := range values {
|
||||
b.Values = append(b.Values, values[i])
|
||||
}
|
||||
return b
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// PodFailurePolicyOnPodConditionsPatternApplyConfiguration represents an declarative configuration of the PodFailurePolicyOnPodConditionsPattern type for use
|
||||
// with apply.
|
||||
type PodFailurePolicyOnPodConditionsPatternApplyConfiguration struct {
|
||||
Type *v1.PodConditionType `json:"type,omitempty"`
|
||||
Status *v1.ConditionStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// PodFailurePolicyOnPodConditionsPatternApplyConfiguration constructs an declarative configuration of the PodFailurePolicyOnPodConditionsPattern type for use with
|
||||
// apply.
|
||||
func PodFailurePolicyOnPodConditionsPattern() *PodFailurePolicyOnPodConditionsPatternApplyConfiguration {
|
||||
return &PodFailurePolicyOnPodConditionsPatternApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithType sets the Type field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Type field is set to the value of the last call.
|
||||
func (b *PodFailurePolicyOnPodConditionsPatternApplyConfiguration) WithType(value v1.PodConditionType) *PodFailurePolicyOnPodConditionsPatternApplyConfiguration {
|
||||
b.Type = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithStatus sets the Status field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Status field is set to the value of the last call.
|
||||
func (b *PodFailurePolicyOnPodConditionsPatternApplyConfiguration) WithStatus(value v1.ConditionStatus) *PodFailurePolicyOnPodConditionsPatternApplyConfiguration {
|
||||
b.Status = &value
|
||||
return b
|
||||
}
|
||||
66
applyconfigurations/batch/v1/podfailurepolicyrule.go
Normal file
66
applyconfigurations/batch/v1/podfailurepolicyrule.go
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/batch/v1"
|
||||
)
|
||||
|
||||
// PodFailurePolicyRuleApplyConfiguration represents an declarative configuration of the PodFailurePolicyRule type for use
|
||||
// with apply.
|
||||
type PodFailurePolicyRuleApplyConfiguration struct {
|
||||
Action *v1.PodFailurePolicyAction `json:"action,omitempty"`
|
||||
OnExitCodes *PodFailurePolicyOnExitCodesRequirementApplyConfiguration `json:"onExitCodes,omitempty"`
|
||||
OnPodConditions []PodFailurePolicyOnPodConditionsPatternApplyConfiguration `json:"onPodConditions,omitempty"`
|
||||
}
|
||||
|
||||
// PodFailurePolicyRuleApplyConfiguration constructs an declarative configuration of the PodFailurePolicyRule type for use with
|
||||
// apply.
|
||||
func PodFailurePolicyRule() *PodFailurePolicyRuleApplyConfiguration {
|
||||
return &PodFailurePolicyRuleApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithAction sets the Action field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Action field is set to the value of the last call.
|
||||
func (b *PodFailurePolicyRuleApplyConfiguration) WithAction(value v1.PodFailurePolicyAction) *PodFailurePolicyRuleApplyConfiguration {
|
||||
b.Action = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithOnExitCodes sets the OnExitCodes field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the OnExitCodes field is set to the value of the last call.
|
||||
func (b *PodFailurePolicyRuleApplyConfiguration) WithOnExitCodes(value *PodFailurePolicyOnExitCodesRequirementApplyConfiguration) *PodFailurePolicyRuleApplyConfiguration {
|
||||
b.OnExitCodes = value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithOnPodConditions adds the given value to the OnPodConditions field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, values provided by each call will be appended to the OnPodConditions field.
|
||||
func (b *PodFailurePolicyRuleApplyConfiguration) WithOnPodConditions(values ...*PodFailurePolicyOnPodConditionsPatternApplyConfiguration) *PodFailurePolicyRuleApplyConfiguration {
|
||||
for i := range values {
|
||||
if values[i] == nil {
|
||||
panic("nil value passed to WithOnPodConditions")
|
||||
}
|
||||
b.OnPodConditions = append(b.OnPodConditions, *values[i])
|
||||
}
|
||||
return b
|
||||
}
|
||||
@@ -30,6 +30,7 @@ type CSIPersistentVolumeSourceApplyConfiguration struct {
|
||||
NodeStageSecretRef *SecretReferenceApplyConfiguration `json:"nodeStageSecretRef,omitempty"`
|
||||
NodePublishSecretRef *SecretReferenceApplyConfiguration `json:"nodePublishSecretRef,omitempty"`
|
||||
ControllerExpandSecretRef *SecretReferenceApplyConfiguration `json:"controllerExpandSecretRef,omitempty"`
|
||||
NodeExpandSecretRef *SecretReferenceApplyConfiguration `json:"nodeExpandSecretRef,omitempty"`
|
||||
}
|
||||
|
||||
// CSIPersistentVolumeSourceApplyConfiguration constructs an declarative configuration of the CSIPersistentVolumeSource type for use with
|
||||
@@ -115,3 +116,11 @@ func (b *CSIPersistentVolumeSourceApplyConfiguration) WithControllerExpandSecret
|
||||
b.ControllerExpandSecretRef = value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithNodeExpandSecretRef sets the NodeExpandSecretRef field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the NodeExpandSecretRef field is set to the value of the last call.
|
||||
func (b *CSIPersistentVolumeSourceApplyConfiguration) WithNodeExpandSecretRef(value *SecretReferenceApplyConfiguration) *CSIPersistentVolumeSourceApplyConfiguration {
|
||||
b.NodeExpandSecretRef = value
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ type PodSpecApplyConfiguration struct {
|
||||
TopologySpreadConstraints []TopologySpreadConstraintApplyConfiguration `json:"topologySpreadConstraints,omitempty"`
|
||||
SetHostnameAsFQDN *bool `json:"setHostnameAsFQDN,omitempty"`
|
||||
OS *PodOSApplyConfiguration `json:"os,omitempty"`
|
||||
HostUsers *bool `json:"hostUsers,omitempty"`
|
||||
}
|
||||
|
||||
// PodSpecApplyConfiguration constructs an declarative configuration of the PodSpec type for use with
|
||||
@@ -407,3 +408,11 @@ func (b *PodSpecApplyConfiguration) WithOS(value *PodOSApplyConfiguration) *PodS
|
||||
b.OS = value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithHostUsers sets the HostUsers field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the HostUsers field is set to the value of the last call.
|
||||
func (b *PodSpecApplyConfiguration) WithHostUsers(value bool) *PodSpecApplyConfiguration {
|
||||
b.HostUsers = &value
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ type ServiceSpecApplyConfiguration struct {
|
||||
PublishNotReadyAddresses *bool `json:"publishNotReadyAddresses,omitempty"`
|
||||
SessionAffinityConfig *SessionAffinityConfigApplyConfiguration `json:"sessionAffinityConfig,omitempty"`
|
||||
IPFamilies []corev1.IPFamily `json:"ipFamilies,omitempty"`
|
||||
IPFamilyPolicy *corev1.IPFamilyPolicyType `json:"ipFamilyPolicy,omitempty"`
|
||||
IPFamilyPolicy *corev1.IPFamilyPolicy `json:"ipFamilyPolicy,omitempty"`
|
||||
AllocateLoadBalancerNodePorts *bool `json:"allocateLoadBalancerNodePorts,omitempty"`
|
||||
LoadBalancerClass *string `json:"loadBalancerClass,omitempty"`
|
||||
InternalTrafficPolicy *corev1.ServiceInternalTrafficPolicyType `json:"internalTrafficPolicy,omitempty"`
|
||||
@@ -194,7 +194,7 @@ func (b *ServiceSpecApplyConfiguration) WithIPFamilies(values ...corev1.IPFamily
|
||||
// WithIPFamilyPolicy sets the IPFamilyPolicy field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the IPFamilyPolicy field is set to the value of the last call.
|
||||
func (b *ServiceSpecApplyConfiguration) WithIPFamilyPolicy(value corev1.IPFamilyPolicyType) *ServiceSpecApplyConfiguration {
|
||||
func (b *ServiceSpecApplyConfiguration) WithIPFamilyPolicy(value corev1.IPFamilyPolicy) *ServiceSpecApplyConfiguration {
|
||||
b.IPFamilyPolicy = &value
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -26,11 +26,14 @@ import (
|
||||
// TopologySpreadConstraintApplyConfiguration represents an declarative configuration of the TopologySpreadConstraint type for use
|
||||
// with apply.
|
||||
type TopologySpreadConstraintApplyConfiguration struct {
|
||||
MaxSkew *int32 `json:"maxSkew,omitempty"`
|
||||
TopologyKey *string `json:"topologyKey,omitempty"`
|
||||
WhenUnsatisfiable *v1.UnsatisfiableConstraintAction `json:"whenUnsatisfiable,omitempty"`
|
||||
LabelSelector *metav1.LabelSelectorApplyConfiguration `json:"labelSelector,omitempty"`
|
||||
MinDomains *int32 `json:"minDomains,omitempty"`
|
||||
MaxSkew *int32 `json:"maxSkew,omitempty"`
|
||||
TopologyKey *string `json:"topologyKey,omitempty"`
|
||||
WhenUnsatisfiable *v1.UnsatisfiableConstraintAction `json:"whenUnsatisfiable,omitempty"`
|
||||
LabelSelector *metav1.LabelSelectorApplyConfiguration `json:"labelSelector,omitempty"`
|
||||
MinDomains *int32 `json:"minDomains,omitempty"`
|
||||
NodeAffinityPolicy *v1.NodeInclusionPolicy `json:"nodeAffinityPolicy,omitempty"`
|
||||
NodeTaintsPolicy *v1.NodeInclusionPolicy `json:"nodeTaintsPolicy,omitempty"`
|
||||
MatchLabelKeys []string `json:"matchLabelKeys,omitempty"`
|
||||
}
|
||||
|
||||
// TopologySpreadConstraintApplyConfiguration constructs an declarative configuration of the TopologySpreadConstraint type for use with
|
||||
@@ -78,3 +81,29 @@ func (b *TopologySpreadConstraintApplyConfiguration) WithMinDomains(value int32)
|
||||
b.MinDomains = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithNodeAffinityPolicy sets the NodeAffinityPolicy field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the NodeAffinityPolicy field is set to the value of the last call.
|
||||
func (b *TopologySpreadConstraintApplyConfiguration) WithNodeAffinityPolicy(value v1.NodeInclusionPolicy) *TopologySpreadConstraintApplyConfiguration {
|
||||
b.NodeAffinityPolicy = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithNodeTaintsPolicy sets the NodeTaintsPolicy field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the NodeTaintsPolicy field is set to the value of the last call.
|
||||
func (b *TopologySpreadConstraintApplyConfiguration) WithNodeTaintsPolicy(value v1.NodeInclusionPolicy) *TopologySpreadConstraintApplyConfiguration {
|
||||
b.NodeTaintsPolicy = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithMatchLabelKeys adds the given value to the MatchLabelKeys field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, values provided by each call will be appended to the MatchLabelKeys field.
|
||||
func (b *TopologySpreadConstraintApplyConfiguration) WithMatchLabelKeys(values ...string) *TopologySpreadConstraintApplyConfiguration {
|
||||
for i := range values {
|
||||
b.MatchLabelKeys = append(b.MatchLabelKeys, values[i])
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -20,22 +20,22 @@ limitations under the License.
|
||||
Package applyconfigurations provides typesafe go representations of the apply
|
||||
configurations that are used to constructs Server-side Apply requests.
|
||||
|
||||
Basics
|
||||
# Basics
|
||||
|
||||
The Apply functions in the typed client (see the k8s.io/client-go/kubernetes/typed packages) offer
|
||||
a direct and typesafe way of calling Server-side Apply. Each Apply function takes an "apply
|
||||
configuration" type as an argument, which is a structured representation of an Apply request. For
|
||||
example:
|
||||
|
||||
import (
|
||||
...
|
||||
v1ac "k8s.io/client-go/applyconfigurations/autoscaling/v1"
|
||||
)
|
||||
hpaApplyConfig := v1ac.HorizontalPodAutoscaler(autoscalerName, ns).
|
||||
WithSpec(v1ac.HorizontalPodAutoscalerSpec().
|
||||
WithMinReplicas(0)
|
||||
)
|
||||
return hpav1client.Apply(ctx, hpaApplyConfig, metav1.ApplyOptions{FieldManager: "mycontroller", Force: true})
|
||||
import (
|
||||
...
|
||||
v1ac "k8s.io/client-go/applyconfigurations/autoscaling/v1"
|
||||
)
|
||||
hpaApplyConfig := v1ac.HorizontalPodAutoscaler(autoscalerName, ns).
|
||||
WithSpec(v1ac.HorizontalPodAutoscalerSpec().
|
||||
WithMinReplicas(0)
|
||||
)
|
||||
return hpav1client.Apply(ctx, hpaApplyConfig, metav1.ApplyOptions{FieldManager: "mycontroller", Force: true})
|
||||
|
||||
Note in this example that HorizontalPodAutoscaler is imported from an "applyconfigurations"
|
||||
package. Each "apply configuration" type represents the same Kubernetes object kind as the
|
||||
@@ -43,46 +43,46 @@ corresponding go struct, but where all fields are pointers to make them optional
|
||||
requests to be accurately represented. For example, this when the apply configuration in the above
|
||||
example is marshalled to YAML, it produces:
|
||||
|
||||
apiVersion: autoscaling/v1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: myHPA
|
||||
namespace: myNamespace
|
||||
spec:
|
||||
minReplicas: 0
|
||||
apiVersion: autoscaling/v1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: myHPA
|
||||
namespace: myNamespace
|
||||
spec:
|
||||
minReplicas: 0
|
||||
|
||||
To understand why this is needed, the above YAML cannot be produced by the
|
||||
v1.HorizontalPodAutoscaler go struct. Take for example:
|
||||
|
||||
hpa := v1.HorizontalPodAutoscaler{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "autoscaling/v1",
|
||||
Kind: "HorizontalPodAutoscaler",
|
||||
},
|
||||
ObjectMeta: ObjectMeta{
|
||||
Namespace: ns,
|
||||
Name: autoscalerName,
|
||||
},
|
||||
Spec: v1.HorizontalPodAutoscalerSpec{
|
||||
MinReplicas: pointer.Int32Ptr(0),
|
||||
},
|
||||
}
|
||||
hpa := v1.HorizontalPodAutoscaler{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "autoscaling/v1",
|
||||
Kind: "HorizontalPodAutoscaler",
|
||||
},
|
||||
ObjectMeta: ObjectMeta{
|
||||
Namespace: ns,
|
||||
Name: autoscalerName,
|
||||
},
|
||||
Spec: v1.HorizontalPodAutoscalerSpec{
|
||||
MinReplicas: pointer.Int32Ptr(0),
|
||||
},
|
||||
}
|
||||
|
||||
The above code attempts to declare the same apply configuration as shown in the previous examples,
|
||||
but when marshalled to YAML, produces:
|
||||
|
||||
kind: HorizontalPodAutoscaler
|
||||
apiVersion: autoscaling/v1
|
||||
metadata:
|
||||
name: myHPA
|
||||
namespace: myNamespace
|
||||
creationTimestamp: null
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
kind: ""
|
||||
name: ""
|
||||
minReplicas: 0
|
||||
maxReplicas: 0
|
||||
kind: HorizontalPodAutoscaler
|
||||
apiVersion: autoscaling/v1
|
||||
metadata:
|
||||
name: myHPA
|
||||
namespace: myNamespace
|
||||
creationTimestamp: null
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
kind: ""
|
||||
name: ""
|
||||
minReplicas: 0
|
||||
maxReplicas: 0
|
||||
|
||||
Which, among other things, contains spec.maxReplicas set to 0. This is almost certainly not what
|
||||
the caller intended (the intended apply configuration says nothing about the maxReplicas field),
|
||||
@@ -102,7 +102,7 @@ general purpose library. In addition to the convenience, the With functions also
|
||||
developers from the underlying representation, which makes it safer for the underlying
|
||||
representation to be changed to support additional features in the future.
|
||||
|
||||
Controller Support
|
||||
# Controller Support
|
||||
|
||||
The new client-go support makes it much easier to use Server-side Apply in controllers, by either of
|
||||
two mechanisms.
|
||||
@@ -130,24 +130,24 @@ accidentally deleted. For such cases, an alternative to mechanism 1 is to replac
|
||||
reconciliation code that performs a "read/modify-in-place/update" (or patch) workflow with a
|
||||
"extract/modify-in-place/apply" workflow. Here's an example of the new workflow:
|
||||
|
||||
fieldMgr := "my-field-manager"
|
||||
deploymentClient := clientset.AppsV1().Deployments("default")
|
||||
// read, could also be read from a shared informer
|
||||
deployment, err := deploymentClient.Get(ctx, "example-deployment", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
// extract
|
||||
deploymentApplyConfig, err := appsv1ac.ExtractDeployment(deployment, fieldMgr)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
// modify-in-place
|
||||
deploymentApplyConfig.Spec.Template.Spec.WithContainers(corev1ac.Container().
|
||||
WithName("modify-slice").
|
||||
WithImage("nginx:1.14.2"),
|
||||
)
|
||||
// apply
|
||||
applied, err := deploymentClient.Apply(ctx, extractedDeployment, metav1.ApplyOptions{FieldManager: fieldMgr})
|
||||
fieldMgr := "my-field-manager"
|
||||
deploymentClient := clientset.AppsV1().Deployments("default")
|
||||
// read, could also be read from a shared informer
|
||||
deployment, err := deploymentClient.Get(ctx, "example-deployment", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
// extract
|
||||
deploymentApplyConfig, err := appsv1ac.ExtractDeployment(deployment, fieldMgr)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
// modify-in-place
|
||||
deploymentApplyConfig.Spec.Template.Spec.WithContainers(corev1ac.Container().
|
||||
WithName("modify-slice").
|
||||
WithImage("nginx:1.14.2"),
|
||||
)
|
||||
// apply
|
||||
applied, err := deploymentClient.Apply(ctx, extractedDeployment, metav1.ApplyOptions{FieldManager: fieldMgr})
|
||||
*/
|
||||
package applyconfigurations
|
||||
|
||||
@@ -3041,6 +3041,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: parallelism
|
||||
type:
|
||||
scalar: numeric
|
||||
- name: podFailurePolicy
|
||||
type:
|
||||
namedType: io.k8s.api.batch.v1.PodFailurePolicy
|
||||
- name: selector
|
||||
type:
|
||||
namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector
|
||||
@@ -3098,6 +3101,58 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
type:
|
||||
namedType: io.k8s.api.batch.v1.JobSpec
|
||||
default: {}
|
||||
- name: io.k8s.api.batch.v1.PodFailurePolicy
|
||||
map:
|
||||
fields:
|
||||
- name: rules
|
||||
type:
|
||||
list:
|
||||
elementType:
|
||||
namedType: io.k8s.api.batch.v1.PodFailurePolicyRule
|
||||
elementRelationship: atomic
|
||||
- name: io.k8s.api.batch.v1.PodFailurePolicyOnExitCodesRequirement
|
||||
map:
|
||||
fields:
|
||||
- name: containerName
|
||||
type:
|
||||
scalar: string
|
||||
- name: operator
|
||||
type:
|
||||
scalar: string
|
||||
default: ""
|
||||
- name: values
|
||||
type:
|
||||
list:
|
||||
elementType:
|
||||
scalar: numeric
|
||||
elementRelationship: associative
|
||||
- name: io.k8s.api.batch.v1.PodFailurePolicyOnPodConditionsPattern
|
||||
map:
|
||||
fields:
|
||||
- name: status
|
||||
type:
|
||||
scalar: string
|
||||
default: ""
|
||||
- name: type
|
||||
type:
|
||||
scalar: string
|
||||
default: ""
|
||||
- name: io.k8s.api.batch.v1.PodFailurePolicyRule
|
||||
map:
|
||||
fields:
|
||||
- name: action
|
||||
type:
|
||||
scalar: string
|
||||
default: ""
|
||||
- name: onExitCodes
|
||||
type:
|
||||
namedType: io.k8s.api.batch.v1.PodFailurePolicyOnExitCodesRequirement
|
||||
- name: onPodConditions
|
||||
type:
|
||||
list:
|
||||
elementType:
|
||||
namedType: io.k8s.api.batch.v1.PodFailurePolicyOnPodConditionsPattern
|
||||
elementRelationship: atomic
|
||||
- name: io.k8s.api.batch.v1.UncountedTerminatedPods
|
||||
map:
|
||||
fields:
|
||||
@@ -3565,6 +3620,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: fsType
|
||||
type:
|
||||
scalar: string
|
||||
- name: nodeExpandSecretRef
|
||||
type:
|
||||
namedType: io.k8s.api.core.v1.SecretReference
|
||||
- name: nodePublishSecretRef
|
||||
type:
|
||||
namedType: io.k8s.api.core.v1.SecretReference
|
||||
@@ -5430,6 +5488,7 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: claimRef
|
||||
type:
|
||||
namedType: io.k8s.api.core.v1.ObjectReference
|
||||
elementRelationship: separable
|
||||
- name: csi
|
||||
type:
|
||||
namedType: io.k8s.api.core.v1.CSIPersistentVolumeSource
|
||||
@@ -5759,6 +5818,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: hostPID
|
||||
type:
|
||||
scalar: boolean
|
||||
- name: hostUsers
|
||||
type:
|
||||
scalar: boolean
|
||||
- name: hostname
|
||||
type:
|
||||
scalar: string
|
||||
@@ -6855,6 +6917,12 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: labelSelector
|
||||
type:
|
||||
namedType: io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector
|
||||
- name: matchLabelKeys
|
||||
type:
|
||||
list:
|
||||
elementType:
|
||||
scalar: string
|
||||
elementRelationship: atomic
|
||||
- name: maxSkew
|
||||
type:
|
||||
scalar: numeric
|
||||
@@ -6862,6 +6930,12 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: minDomains
|
||||
type:
|
||||
scalar: numeric
|
||||
- name: nodeAffinityPolicy
|
||||
type:
|
||||
scalar: string
|
||||
- name: nodeTaintsPolicy
|
||||
type:
|
||||
scalar: string
|
||||
- name: topologyKey
|
||||
type:
|
||||
scalar: string
|
||||
@@ -9519,7 +9593,7 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: number
|
||||
type:
|
||||
scalar: numeric
|
||||
- name: io.k8s.api.networking.v1alpha1.ClusterCIDRConfig
|
||||
- name: io.k8s.api.networking.v1alpha1.ClusterCIDR
|
||||
map:
|
||||
fields:
|
||||
- name: apiVersion
|
||||
@@ -9534,20 +9608,16 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
default: {}
|
||||
- name: spec
|
||||
type:
|
||||
namedType: io.k8s.api.networking.v1alpha1.ClusterCIDRConfigSpec
|
||||
namedType: io.k8s.api.networking.v1alpha1.ClusterCIDRSpec
|
||||
default: {}
|
||||
- name: status
|
||||
type:
|
||||
namedType: io.k8s.api.networking.v1alpha1.ClusterCIDRConfigStatus
|
||||
default: {}
|
||||
- name: io.k8s.api.networking.v1alpha1.ClusterCIDRConfigSpec
|
||||
- name: io.k8s.api.networking.v1alpha1.ClusterCIDRSpec
|
||||
map:
|
||||
fields:
|
||||
- name: ipv4CIDR
|
||||
- name: ipv4
|
||||
type:
|
||||
scalar: string
|
||||
default: ""
|
||||
- name: ipv6CIDR
|
||||
- name: ipv6
|
||||
type:
|
||||
scalar: string
|
||||
default: ""
|
||||
@@ -9558,18 +9628,6 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
type:
|
||||
scalar: numeric
|
||||
default: 0
|
||||
- name: io.k8s.api.networking.v1alpha1.ClusterCIDRConfigStatus
|
||||
map:
|
||||
elementType:
|
||||
scalar: untyped
|
||||
list:
|
||||
elementType:
|
||||
namedType: __untyped_atomic_
|
||||
elementRelationship: atomic
|
||||
map:
|
||||
elementType:
|
||||
namedType: __untyped_deduced_
|
||||
elementRelationship: separable
|
||||
- name: io.k8s.api.networking.v1beta1.HTTPIngressPath
|
||||
map:
|
||||
fields:
|
||||
@@ -10875,6 +10933,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: requiresRepublish
|
||||
type:
|
||||
scalar: boolean
|
||||
- name: seLinuxMount
|
||||
type:
|
||||
scalar: boolean
|
||||
- name: storageCapacity
|
||||
type:
|
||||
scalar: boolean
|
||||
@@ -11227,6 +11288,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: requiresRepublish
|
||||
type:
|
||||
scalar: boolean
|
||||
- name: seLinuxMount
|
||||
type:
|
||||
scalar: boolean
|
||||
- name: storageCapacity
|
||||
type:
|
||||
scalar: boolean
|
||||
@@ -11581,9 +11645,6 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
map:
|
||||
elementType:
|
||||
scalar: string
|
||||
- name: clusterName
|
||||
type:
|
||||
scalar: string
|
||||
- name: creationTimestamp
|
||||
type:
|
||||
namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
// CIDRConfigApplyConfiguration represents an declarative configuration of the CIDRConfig type for use
|
||||
// with apply.
|
||||
type CIDRConfigApplyConfiguration struct {
|
||||
CIDR *string `json:"cidr,omitempty"`
|
||||
PerNodeMaskSize *int32 `json:"perNodeMaskSize,omitempty"`
|
||||
}
|
||||
|
||||
// CIDRConfigApplyConfiguration constructs an declarative configuration of the CIDRConfig type for use with
|
||||
// apply.
|
||||
func CIDRConfig() *CIDRConfigApplyConfiguration {
|
||||
return &CIDRConfigApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithCIDR sets the CIDR field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the CIDR field is set to the value of the last call.
|
||||
func (b *CIDRConfigApplyConfiguration) WithCIDR(value string) *CIDRConfigApplyConfiguration {
|
||||
b.CIDR = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithPerNodeMaskSize sets the PerNodeMaskSize field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the PerNodeMaskSize field is set to the value of the last call.
|
||||
func (b *CIDRConfigApplyConfiguration) WithPerNodeMaskSize(value int32) *CIDRConfigApplyConfiguration {
|
||||
b.PerNodeMaskSize = &value
|
||||
return b
|
||||
}
|
||||
@@ -27,56 +27,55 @@ import (
|
||||
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
|
||||
)
|
||||
|
||||
// ClusterCIDRConfigApplyConfiguration represents an declarative configuration of the ClusterCIDRConfig type for use
|
||||
// ClusterCIDRApplyConfiguration represents an declarative configuration of the ClusterCIDR type for use
|
||||
// with apply.
|
||||
type ClusterCIDRConfigApplyConfiguration struct {
|
||||
type ClusterCIDRApplyConfiguration struct {
|
||||
v1.TypeMetaApplyConfiguration `json:",inline"`
|
||||
*v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"`
|
||||
Spec *ClusterCIDRConfigSpecApplyConfiguration `json:"spec,omitempty"`
|
||||
Status *networkingv1alpha1.ClusterCIDRConfigStatus `json:"status,omitempty"`
|
||||
Spec *ClusterCIDRSpecApplyConfiguration `json:"spec,omitempty"`
|
||||
}
|
||||
|
||||
// ClusterCIDRConfig constructs an declarative configuration of the ClusterCIDRConfig type for use with
|
||||
// ClusterCIDR constructs an declarative configuration of the ClusterCIDR type for use with
|
||||
// apply.
|
||||
func ClusterCIDRConfig(name string) *ClusterCIDRConfigApplyConfiguration {
|
||||
b := &ClusterCIDRConfigApplyConfiguration{}
|
||||
func ClusterCIDR(name string) *ClusterCIDRApplyConfiguration {
|
||||
b := &ClusterCIDRApplyConfiguration{}
|
||||
b.WithName(name)
|
||||
b.WithKind("ClusterCIDRConfig")
|
||||
b.WithKind("ClusterCIDR")
|
||||
b.WithAPIVersion("networking.k8s.io/v1alpha1")
|
||||
return b
|
||||
}
|
||||
|
||||
// ExtractClusterCIDRConfig extracts the applied configuration owned by fieldManager from
|
||||
// clusterCIDRConfig. If no managedFields are found in clusterCIDRConfig for fieldManager, a
|
||||
// ClusterCIDRConfigApplyConfiguration is returned with only the Name, Namespace (if applicable),
|
||||
// ExtractClusterCIDR extracts the applied configuration owned by fieldManager from
|
||||
// clusterCIDR. If no managedFields are found in clusterCIDR for fieldManager, a
|
||||
// ClusterCIDRApplyConfiguration is returned with only the Name, Namespace (if applicable),
|
||||
// APIVersion and Kind populated. It is possible that no managed fields were found for because other
|
||||
// field managers have taken ownership of all the fields previously owned by fieldManager, or because
|
||||
// the fieldManager never owned fields any fields.
|
||||
// clusterCIDRConfig must be a unmodified ClusterCIDRConfig API object that was retrieved from the Kubernetes API.
|
||||
// ExtractClusterCIDRConfig provides a way to perform a extract/modify-in-place/apply workflow.
|
||||
// clusterCIDR must be a unmodified ClusterCIDR API object that was retrieved from the Kubernetes API.
|
||||
// ExtractClusterCIDR provides a way to perform a extract/modify-in-place/apply workflow.
|
||||
// Note that an extracted apply configuration will contain fewer fields than what the fieldManager previously
|
||||
// applied if another fieldManager has updated or force applied any of the previously applied fields.
|
||||
// Experimental!
|
||||
func ExtractClusterCIDRConfig(clusterCIDRConfig *networkingv1alpha1.ClusterCIDRConfig, fieldManager string) (*ClusterCIDRConfigApplyConfiguration, error) {
|
||||
return extractClusterCIDRConfig(clusterCIDRConfig, fieldManager, "")
|
||||
func ExtractClusterCIDR(clusterCIDR *networkingv1alpha1.ClusterCIDR, fieldManager string) (*ClusterCIDRApplyConfiguration, error) {
|
||||
return extractClusterCIDR(clusterCIDR, fieldManager, "")
|
||||
}
|
||||
|
||||
// ExtractClusterCIDRConfigStatus is the same as ExtractClusterCIDRConfig except
|
||||
// ExtractClusterCIDRStatus is the same as ExtractClusterCIDR except
|
||||
// that it extracts the status subresource applied configuration.
|
||||
// Experimental!
|
||||
func ExtractClusterCIDRConfigStatus(clusterCIDRConfig *networkingv1alpha1.ClusterCIDRConfig, fieldManager string) (*ClusterCIDRConfigApplyConfiguration, error) {
|
||||
return extractClusterCIDRConfig(clusterCIDRConfig, fieldManager, "status")
|
||||
func ExtractClusterCIDRStatus(clusterCIDR *networkingv1alpha1.ClusterCIDR, fieldManager string) (*ClusterCIDRApplyConfiguration, error) {
|
||||
return extractClusterCIDR(clusterCIDR, fieldManager, "status")
|
||||
}
|
||||
|
||||
func extractClusterCIDRConfig(clusterCIDRConfig *networkingv1alpha1.ClusterCIDRConfig, fieldManager string, subresource string) (*ClusterCIDRConfigApplyConfiguration, error) {
|
||||
b := &ClusterCIDRConfigApplyConfiguration{}
|
||||
err := managedfields.ExtractInto(clusterCIDRConfig, internal.Parser().Type("io.k8s.api.networking.v1alpha1.ClusterCIDRConfig"), fieldManager, b, subresource)
|
||||
func extractClusterCIDR(clusterCIDR *networkingv1alpha1.ClusterCIDR, fieldManager string, subresource string) (*ClusterCIDRApplyConfiguration, error) {
|
||||
b := &ClusterCIDRApplyConfiguration{}
|
||||
err := managedfields.ExtractInto(clusterCIDR, internal.Parser().Type("io.k8s.api.networking.v1alpha1.ClusterCIDR"), fieldManager, b, subresource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.WithName(clusterCIDRConfig.Name)
|
||||
b.WithName(clusterCIDR.Name)
|
||||
|
||||
b.WithKind("ClusterCIDRConfig")
|
||||
b.WithKind("ClusterCIDR")
|
||||
b.WithAPIVersion("networking.k8s.io/v1alpha1")
|
||||
return b, nil
|
||||
}
|
||||
@@ -84,7 +83,7 @@ func extractClusterCIDRConfig(clusterCIDRConfig *networkingv1alpha1.ClusterCIDRC
|
||||
// WithKind sets the Kind field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Kind field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithKind(value string) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithKind(value string) *ClusterCIDRApplyConfiguration {
|
||||
b.Kind = &value
|
||||
return b
|
||||
}
|
||||
@@ -92,7 +91,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithKind(value string) *ClusterCID
|
||||
// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the APIVersion field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithAPIVersion(value string) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithAPIVersion(value string) *ClusterCIDRApplyConfiguration {
|
||||
b.APIVersion = &value
|
||||
return b
|
||||
}
|
||||
@@ -100,7 +99,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithAPIVersion(value string) *Clus
|
||||
// WithName sets the Name field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Name field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithName(value string) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithName(value string) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
b.Name = &value
|
||||
return b
|
||||
@@ -109,7 +108,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithName(value string) *ClusterCID
|
||||
// WithGenerateName sets the GenerateName field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the GenerateName field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithGenerateName(value string) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithGenerateName(value string) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
b.GenerateName = &value
|
||||
return b
|
||||
@@ -118,7 +117,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithGenerateName(value string) *Cl
|
||||
// WithNamespace sets the Namespace field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Namespace field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithNamespace(value string) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithNamespace(value string) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
b.Namespace = &value
|
||||
return b
|
||||
@@ -127,7 +126,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithNamespace(value string) *Clust
|
||||
// WithUID sets the UID field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the UID field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithUID(value types.UID) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithUID(value types.UID) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
b.UID = &value
|
||||
return b
|
||||
@@ -136,7 +135,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithUID(value types.UID) *ClusterC
|
||||
// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the ResourceVersion field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithResourceVersion(value string) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithResourceVersion(value string) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
b.ResourceVersion = &value
|
||||
return b
|
||||
@@ -145,7 +144,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithResourceVersion(value string)
|
||||
// WithGeneration sets the Generation field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Generation field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithGeneration(value int64) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithGeneration(value int64) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
b.Generation = &value
|
||||
return b
|
||||
@@ -154,7 +153,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithGeneration(value int64) *Clust
|
||||
// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the CreationTimestamp field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
b.CreationTimestamp = &value
|
||||
return b
|
||||
@@ -163,7 +162,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithCreationTimestamp(value metav1
|
||||
// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the DeletionTimestamp field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
b.DeletionTimestamp = &value
|
||||
return b
|
||||
@@ -172,7 +171,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithDeletionTimestamp(value metav1
|
||||
// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
b.DeletionGracePeriodSeconds = &value
|
||||
return b
|
||||
@@ -182,7 +181,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithDeletionGracePeriodSeconds(val
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, the entries provided by each call will be put on the Labels field,
|
||||
// overwriting an existing map entries in Labels field with the same key.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithLabels(entries map[string]string) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithLabels(entries map[string]string) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
if b.Labels == nil && len(entries) > 0 {
|
||||
b.Labels = make(map[string]string, len(entries))
|
||||
@@ -197,7 +196,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithLabels(entries map[string]stri
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, the entries provided by each call will be put on the Annotations field,
|
||||
// overwriting an existing map entries in Annotations field with the same key.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithAnnotations(entries map[string]string) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithAnnotations(entries map[string]string) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
if b.Annotations == nil && len(entries) > 0 {
|
||||
b.Annotations = make(map[string]string, len(entries))
|
||||
@@ -211,7 +210,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithAnnotations(entries map[string
|
||||
// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, values provided by each call will be appended to the OwnerReferences field.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
for i := range values {
|
||||
if values[i] == nil {
|
||||
@@ -225,7 +224,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithOwnerReferences(values ...*v1.
|
||||
// WithFinalizers adds the given value to the Finalizers field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, values provided by each call will be appended to the Finalizers field.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithFinalizers(values ...string) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithFinalizers(values ...string) *ClusterCIDRApplyConfiguration {
|
||||
b.ensureObjectMetaApplyConfigurationExists()
|
||||
for i := range values {
|
||||
b.Finalizers = append(b.Finalizers, values[i])
|
||||
@@ -233,7 +232,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) WithFinalizers(values ...string) *
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
|
||||
func (b *ClusterCIDRApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
|
||||
if b.ObjectMetaApplyConfiguration == nil {
|
||||
b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{}
|
||||
}
|
||||
@@ -242,15 +241,7 @@ func (b *ClusterCIDRConfigApplyConfiguration) ensureObjectMetaApplyConfiguration
|
||||
// WithSpec sets the Spec field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Spec field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithSpec(value *ClusterCIDRConfigSpecApplyConfiguration) *ClusterCIDRConfigApplyConfiguration {
|
||||
func (b *ClusterCIDRApplyConfiguration) WithSpec(value *ClusterCIDRSpecApplyConfiguration) *ClusterCIDRApplyConfiguration {
|
||||
b.Spec = value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithStatus sets the Status field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Status field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigApplyConfiguration) WithStatus(value networkingv1alpha1.ClusterCIDRConfigStatus) *ClusterCIDRConfigApplyConfiguration {
|
||||
b.Status = &value
|
||||
return b
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
|
||||
)
|
||||
|
||||
// ClusterCIDRConfigStatusApplyConfiguration represents an declarative configuration of the ClusterCIDRConfigStatus type for use
|
||||
// with apply.
|
||||
type ClusterCIDRConfigStatusApplyConfiguration struct {
|
||||
Conditions []v1.ConditionApplyConfiguration `json:"conditions,omitempty"`
|
||||
}
|
||||
|
||||
// ClusterCIDRConfigStatusApplyConfiguration constructs an declarative configuration of the ClusterCIDRConfigStatus type for use with
|
||||
// apply.
|
||||
func ClusterCIDRConfigStatus() *ClusterCIDRConfigStatusApplyConfiguration {
|
||||
return &ClusterCIDRConfigStatusApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithConditions adds the given value to the Conditions field in the declarative configuration
|
||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
||||
// If called multiple times, values provided by each call will be appended to the Conditions field.
|
||||
func (b *ClusterCIDRConfigStatusApplyConfiguration) WithConditions(values ...*v1.ConditionApplyConfiguration) *ClusterCIDRConfigStatusApplyConfiguration {
|
||||
for i := range values {
|
||||
if values[i] == nil {
|
||||
panic("nil value passed to WithConditions")
|
||||
}
|
||||
b.Conditions = append(b.Conditions, *values[i])
|
||||
}
|
||||
return b
|
||||
}
|
||||
@@ -22,25 +22,25 @@ import (
|
||||
v1 "k8s.io/client-go/applyconfigurations/core/v1"
|
||||
)
|
||||
|
||||
// ClusterCIDRConfigSpecApplyConfiguration represents an declarative configuration of the ClusterCIDRConfigSpec type for use
|
||||
// ClusterCIDRSpecApplyConfiguration represents an declarative configuration of the ClusterCIDRSpec type for use
|
||||
// with apply.
|
||||
type ClusterCIDRConfigSpecApplyConfiguration struct {
|
||||
type ClusterCIDRSpecApplyConfiguration struct {
|
||||
NodeSelector *v1.NodeSelectorApplyConfiguration `json:"nodeSelector,omitempty"`
|
||||
PerNodeHostBits *int32 `json:"perNodeHostBits,omitempty"`
|
||||
IPv4CIDR *string `json:"ipv4CIDR,omitempty"`
|
||||
IPv6CIDR *string `json:"ipv6CIDR,omitempty"`
|
||||
IPv4 *string `json:"ipv4,omitempty"`
|
||||
IPv6 *string `json:"ipv6,omitempty"`
|
||||
}
|
||||
|
||||
// ClusterCIDRConfigSpecApplyConfiguration constructs an declarative configuration of the ClusterCIDRConfigSpec type for use with
|
||||
// ClusterCIDRSpecApplyConfiguration constructs an declarative configuration of the ClusterCIDRSpec type for use with
|
||||
// apply.
|
||||
func ClusterCIDRConfigSpec() *ClusterCIDRConfigSpecApplyConfiguration {
|
||||
return &ClusterCIDRConfigSpecApplyConfiguration{}
|
||||
func ClusterCIDRSpec() *ClusterCIDRSpecApplyConfiguration {
|
||||
return &ClusterCIDRSpecApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithNodeSelector sets the NodeSelector field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the NodeSelector field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigSpecApplyConfiguration) WithNodeSelector(value *v1.NodeSelectorApplyConfiguration) *ClusterCIDRConfigSpecApplyConfiguration {
|
||||
func (b *ClusterCIDRSpecApplyConfiguration) WithNodeSelector(value *v1.NodeSelectorApplyConfiguration) *ClusterCIDRSpecApplyConfiguration {
|
||||
b.NodeSelector = value
|
||||
return b
|
||||
}
|
||||
@@ -48,23 +48,23 @@ func (b *ClusterCIDRConfigSpecApplyConfiguration) WithNodeSelector(value *v1.Nod
|
||||
// WithPerNodeHostBits sets the PerNodeHostBits field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the PerNodeHostBits field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigSpecApplyConfiguration) WithPerNodeHostBits(value int32) *ClusterCIDRConfigSpecApplyConfiguration {
|
||||
func (b *ClusterCIDRSpecApplyConfiguration) WithPerNodeHostBits(value int32) *ClusterCIDRSpecApplyConfiguration {
|
||||
b.PerNodeHostBits = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithIPv4CIDR sets the IPv4CIDR field in the declarative configuration to the given value
|
||||
// WithIPv4 sets the IPv4 field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the IPv4CIDR field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigSpecApplyConfiguration) WithIPv4CIDR(value string) *ClusterCIDRConfigSpecApplyConfiguration {
|
||||
b.IPv4CIDR = &value
|
||||
// If called multiple times, the IPv4 field is set to the value of the last call.
|
||||
func (b *ClusterCIDRSpecApplyConfiguration) WithIPv4(value string) *ClusterCIDRSpecApplyConfiguration {
|
||||
b.IPv4 = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithIPv6CIDR sets the IPv6CIDR field in the declarative configuration to the given value
|
||||
// WithIPv6 sets the IPv6 field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the IPv6CIDR field is set to the value of the last call.
|
||||
func (b *ClusterCIDRConfigSpecApplyConfiguration) WithIPv6CIDR(value string) *ClusterCIDRConfigSpecApplyConfiguration {
|
||||
b.IPv6CIDR = &value
|
||||
// If called multiple times, the IPv6 field is set to the value of the last call.
|
||||
func (b *ClusterCIDRSpecApplyConfiguration) WithIPv6(value string) *ClusterCIDRSpecApplyConfiguration {
|
||||
b.IPv6 = &value
|
||||
return b
|
||||
}
|
||||
@@ -32,6 +32,7 @@ type CSIDriverSpecApplyConfiguration struct {
|
||||
FSGroupPolicy *v1.FSGroupPolicy `json:"fsGroupPolicy,omitempty"`
|
||||
TokenRequests []TokenRequestApplyConfiguration `json:"tokenRequests,omitempty"`
|
||||
RequiresRepublish *bool `json:"requiresRepublish,omitempty"`
|
||||
SELinuxMount *bool `json:"seLinuxMount,omitempty"`
|
||||
}
|
||||
|
||||
// CSIDriverSpecApplyConfiguration constructs an declarative configuration of the CSIDriverSpec type for use with
|
||||
@@ -102,3 +103,11 @@ func (b *CSIDriverSpecApplyConfiguration) WithRequiresRepublish(value bool) *CSI
|
||||
b.RequiresRepublish = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithSELinuxMount sets the SELinuxMount field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the SELinuxMount field is set to the value of the last call.
|
||||
func (b *CSIDriverSpecApplyConfiguration) WithSELinuxMount(value bool) *CSIDriverSpecApplyConfiguration {
|
||||
b.SELinuxMount = &value
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ type CSIDriverSpecApplyConfiguration struct {
|
||||
FSGroupPolicy *v1beta1.FSGroupPolicy `json:"fsGroupPolicy,omitempty"`
|
||||
TokenRequests []TokenRequestApplyConfiguration `json:"tokenRequests,omitempty"`
|
||||
RequiresRepublish *bool `json:"requiresRepublish,omitempty"`
|
||||
SELinuxMount *bool `json:"seLinuxMount,omitempty"`
|
||||
}
|
||||
|
||||
// CSIDriverSpecApplyConfiguration constructs an declarative configuration of the CSIDriverSpec type for use with
|
||||
@@ -102,3 +103,11 @@ func (b *CSIDriverSpecApplyConfiguration) WithRequiresRepublish(value bool) *CSI
|
||||
b.RequiresRepublish = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithSELinuxMount sets the SELinuxMount field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the SELinuxMount field is set to the value of the last call.
|
||||
func (b *CSIDriverSpecApplyConfiguration) WithSELinuxMount(value bool) *CSIDriverSpecApplyConfiguration {
|
||||
b.SELinuxMount = &value
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -449,6 +449,14 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
|
||||
return &applyconfigurationsbatchv1.JobStatusApplyConfiguration{}
|
||||
case batchv1.SchemeGroupVersion.WithKind("JobTemplateSpec"):
|
||||
return &applyconfigurationsbatchv1.JobTemplateSpecApplyConfiguration{}
|
||||
case batchv1.SchemeGroupVersion.WithKind("PodFailurePolicy"):
|
||||
return &applyconfigurationsbatchv1.PodFailurePolicyApplyConfiguration{}
|
||||
case batchv1.SchemeGroupVersion.WithKind("PodFailurePolicyOnExitCodesRequirement"):
|
||||
return &applyconfigurationsbatchv1.PodFailurePolicyOnExitCodesRequirementApplyConfiguration{}
|
||||
case batchv1.SchemeGroupVersion.WithKind("PodFailurePolicyOnPodConditionsPattern"):
|
||||
return &applyconfigurationsbatchv1.PodFailurePolicyOnPodConditionsPatternApplyConfiguration{}
|
||||
case batchv1.SchemeGroupVersion.WithKind("PodFailurePolicyRule"):
|
||||
return &applyconfigurationsbatchv1.PodFailurePolicyRuleApplyConfiguration{}
|
||||
case batchv1.SchemeGroupVersion.WithKind("UncountedTerminatedPods"):
|
||||
return &applyconfigurationsbatchv1.UncountedTerminatedPodsApplyConfiguration{}
|
||||
|
||||
@@ -1201,10 +1209,10 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
|
||||
return &applyconfigurationsnetworkingv1.ServiceBackendPortApplyConfiguration{}
|
||||
|
||||
// Group=networking.k8s.io, Version=v1alpha1
|
||||
case networkingv1alpha1.SchemeGroupVersion.WithKind("ClusterCIDRConfig"):
|
||||
return &applyconfigurationsnetworkingv1alpha1.ClusterCIDRConfigApplyConfiguration{}
|
||||
case networkingv1alpha1.SchemeGroupVersion.WithKind("ClusterCIDRConfigSpec"):
|
||||
return &applyconfigurationsnetworkingv1alpha1.ClusterCIDRConfigSpecApplyConfiguration{}
|
||||
case networkingv1alpha1.SchemeGroupVersion.WithKind("ClusterCIDR"):
|
||||
return &applyconfigurationsnetworkingv1alpha1.ClusterCIDRApplyConfiguration{}
|
||||
case networkingv1alpha1.SchemeGroupVersion.WithKind("ClusterCIDRSpec"):
|
||||
return &applyconfigurationsnetworkingv1alpha1.ClusterCIDRSpecApplyConfiguration{}
|
||||
|
||||
// Group=networking.k8s.io, Version=v1beta1
|
||||
case networkingv1beta1.SchemeGroupVersion.WithKind("HTTPIngressPath"):
|
||||
|
||||
@@ -34,7 +34,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/openapi"
|
||||
"k8s.io/client-go/rest"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/rest/fake"
|
||||
testutil "k8s.io/client-go/util/testing"
|
||||
@@ -151,7 +150,7 @@ func TestOpenAPIDiskCache(t *testing.T) {
|
||||
require.Greater(t, len(fakeServer.ServedDocuments), 0)
|
||||
|
||||
client, err := NewCachedDiscoveryClientForConfig(
|
||||
&rest.Config{Host: fakeServer.HttpServer.URL},
|
||||
&restclient.Config{Host: fakeServer.HttpServer.URL},
|
||||
discoCache,
|
||||
httpCache,
|
||||
1*time.Nanosecond,
|
||||
|
||||
@@ -17,12 +17,14 @@ limitations under the License.
|
||||
package disk
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gregjones/httpcache"
|
||||
"github.com/gregjones/httpcache/diskcache"
|
||||
"github.com/peterbourgon/diskv"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
@@ -41,7 +43,7 @@ func newCacheRoundTripper(cacheDir string, rt http.RoundTripper) http.RoundTripp
|
||||
BasePath: cacheDir,
|
||||
TempDir: filepath.Join(cacheDir, ".diskv-temp"),
|
||||
})
|
||||
t := httpcache.NewTransport(diskcache.NewWithDiskv(d))
|
||||
t := httpcache.NewTransport(&sumDiskCache{disk: d})
|
||||
t.Transport = rt
|
||||
|
||||
return &cacheRoundTripper{rt: t}
|
||||
@@ -63,3 +65,56 @@ func (rt *cacheRoundTripper) CancelRequest(req *http.Request) {
|
||||
}
|
||||
|
||||
func (rt *cacheRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt.Transport }
|
||||
|
||||
// A sumDiskCache is a cache backend for github.com/gregjones/httpcache. It is
|
||||
// similar to httpcache's diskcache package, but uses SHA256 sums to ensure
|
||||
// cache integrity at read time rather than fsyncing each cache entry to
|
||||
// increase the likelihood they will be persisted at write time. This avoids
|
||||
// significant performance degradation on MacOS.
|
||||
//
|
||||
// See https://github.com/kubernetes/kubernetes/issues/110753 for more.
|
||||
type sumDiskCache struct {
|
||||
disk *diskv.Diskv
|
||||
}
|
||||
|
||||
// Get the requested key from the cache on disk. If Get encounters an error, or
|
||||
// the returned value is not a SHA256 sum followed by bytes with a matching
|
||||
// checksum it will return false to indicate a cache miss.
|
||||
func (c *sumDiskCache) Get(key string) ([]byte, bool) {
|
||||
b, err := c.disk.Read(sanitize(key))
|
||||
if err != nil || len(b) < sha256.Size {
|
||||
return []byte{}, false
|
||||
}
|
||||
|
||||
response := b[sha256.Size:]
|
||||
want := b[:sha256.Size] // The first 32 bytes of the file should be the SHA256 sum.
|
||||
got := sha256.Sum256(response)
|
||||
if !bytes.Equal(want, got[:]) {
|
||||
return []byte{}, false
|
||||
}
|
||||
|
||||
return response, true
|
||||
}
|
||||
|
||||
// Set writes the response to a file on disk. The filename will be the SHA256
|
||||
// sum of the key. The file will contain a SHA256 sum of the response bytes,
|
||||
// followed by said response bytes.
|
||||
func (c *sumDiskCache) Set(key string, response []byte) {
|
||||
s := sha256.Sum256(response)
|
||||
_ = c.disk.Write(sanitize(key), append(s[:], response...)) // Nothing we can do with this error.
|
||||
}
|
||||
|
||||
func (c *sumDiskCache) Delete(key string) {
|
||||
_ = c.disk.Erase(sanitize(key)) // Nothing we can do with this error.
|
||||
}
|
||||
|
||||
// Sanitize an httpcache key such that it can be used as a diskv key, which must
|
||||
// be a valid filename. The httpcache key will either be the requested URL (if
|
||||
// the request method was GET) or "<method> <url>" for other methods, per the
|
||||
// httpcache.cacheKey function.
|
||||
func sanitize(key string) string {
|
||||
// These keys are not sensitive. We use sha256 to avoid a (potentially
|
||||
// malicious) collision causing the wrong cache data to be written or
|
||||
// accessed.
|
||||
return fmt.Sprintf("%x", sha256.Sum256([]byte(key)))
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package disk
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -25,6 +26,7 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/peterbourgon/diskv"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -40,6 +42,35 @@ func (rt *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error)
|
||||
return rt.Response, rt.Err
|
||||
}
|
||||
|
||||
func BenchmarkDiskCache(b *testing.B) {
|
||||
cacheDir, err := ioutil.TempDir("", "cache-rt")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(cacheDir)
|
||||
|
||||
d := diskv.New(diskv.Options{
|
||||
PathPerm: os.FileMode(0750),
|
||||
FilePerm: os.FileMode(0660),
|
||||
BasePath: cacheDir,
|
||||
TempDir: filepath.Join(cacheDir, ".diskv-temp"),
|
||||
})
|
||||
|
||||
k := "localhost:8080/apis/batch/v1.json"
|
||||
v, err := ioutil.ReadFile("../../testdata/apis/batch/v1.json")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
c := sumDiskCache{disk: d}
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
c.Set(k, v)
|
||||
c.Get(k)
|
||||
c.Delete(k)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheRoundTripper(t *testing.T) {
|
||||
rt := &testRoundTripper{}
|
||||
cacheDir, err := ioutil.TempDir("", "cache-rt")
|
||||
@@ -145,3 +176,146 @@ func TestCacheRoundTripperPathPerm(t *testing.T) {
|
||||
})
|
||||
assert.NoError(err)
|
||||
}
|
||||
|
||||
func TestSumDiskCache(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// Ensure that we'll return a cache miss if the backing file doesn't exist.
|
||||
t.Run("NoSuchKey", func(t *testing.T) {
|
||||
cacheDir, err := ioutil.TempDir("", "cache-test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(cacheDir)
|
||||
d := diskv.New(diskv.Options{BasePath: cacheDir, TempDir: filepath.Join(cacheDir, ".diskv-temp")})
|
||||
c := &sumDiskCache{disk: d}
|
||||
|
||||
key := "testing"
|
||||
|
||||
got, ok := c.Get(key)
|
||||
assert.False(ok)
|
||||
assert.Equal([]byte{}, got)
|
||||
})
|
||||
|
||||
// Ensure that we'll return a cache miss if the backing file is empty.
|
||||
t.Run("EmptyFile", func(t *testing.T) {
|
||||
cacheDir, err := ioutil.TempDir("", "cache-test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(cacheDir)
|
||||
d := diskv.New(diskv.Options{BasePath: cacheDir, TempDir: filepath.Join(cacheDir, ".diskv-temp")})
|
||||
c := &sumDiskCache{disk: d}
|
||||
|
||||
key := "testing"
|
||||
|
||||
f, err := os.Create(filepath.Join(cacheDir, sanitize(key)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Close()
|
||||
|
||||
got, ok := c.Get(key)
|
||||
assert.False(ok)
|
||||
assert.Equal([]byte{}, got)
|
||||
})
|
||||
|
||||
// Ensure that we'll return a cache miss if the backing has an invalid
|
||||
// checksum.
|
||||
t.Run("InvalidChecksum", func(t *testing.T) {
|
||||
cacheDir, err := ioutil.TempDir("", "cache-test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(cacheDir)
|
||||
d := diskv.New(diskv.Options{BasePath: cacheDir, TempDir: filepath.Join(cacheDir, ".diskv-temp")})
|
||||
c := &sumDiskCache{disk: d}
|
||||
|
||||
key := "testing"
|
||||
value := []byte("testing")
|
||||
mismatchedValue := []byte("testink")
|
||||
sum := sha256.Sum256(value)
|
||||
|
||||
// Create a file with the sum of 'value' followed by the bytes of
|
||||
// 'mismatchedValue'.
|
||||
f, err := os.Create(filepath.Join(cacheDir, sanitize(key)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Write(sum[:])
|
||||
f.Write(mismatchedValue)
|
||||
f.Close()
|
||||
|
||||
// The mismatched checksum should result in a cache miss.
|
||||
got, ok := c.Get(key)
|
||||
assert.False(ok)
|
||||
assert.Equal([]byte{}, got)
|
||||
})
|
||||
|
||||
// Ensure that our disk cache will happily cache over the top of an existing
|
||||
// value. We depend on this behaviour to recover from corrupted cache
|
||||
// entries. When Get detects a bad checksum it will return a cache miss.
|
||||
// This should cause httpcache to fall back to its underlying transport and
|
||||
// to subsequently cache the new value, overwriting the corrupt one.
|
||||
t.Run("OverwriteExistingKey", func(t *testing.T) {
|
||||
cacheDir, err := ioutil.TempDir("", "cache-test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(cacheDir)
|
||||
d := diskv.New(diskv.Options{BasePath: cacheDir, TempDir: filepath.Join(cacheDir, ".diskv-temp")})
|
||||
c := &sumDiskCache{disk: d}
|
||||
|
||||
key := "testing"
|
||||
value := []byte("cool value!")
|
||||
|
||||
// Write a value.
|
||||
c.Set(key, value)
|
||||
got, ok := c.Get(key)
|
||||
|
||||
// Ensure we can read back what we wrote.
|
||||
assert.True(ok)
|
||||
assert.Equal(value, got)
|
||||
|
||||
differentValue := []byte("I'm different!")
|
||||
|
||||
// Write a different value.
|
||||
c.Set(key, differentValue)
|
||||
got, ok = c.Get(key)
|
||||
|
||||
// Ensure we can read back the different value.
|
||||
assert.True(ok)
|
||||
assert.Equal(differentValue, got)
|
||||
})
|
||||
|
||||
// Ensure that deleting a key does in fact delete it.
|
||||
t.Run("DeleteKey", func(t *testing.T) {
|
||||
cacheDir, err := ioutil.TempDir("", "cache-test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(cacheDir)
|
||||
d := diskv.New(diskv.Options{BasePath: cacheDir, TempDir: filepath.Join(cacheDir, ".diskv-temp")})
|
||||
c := &sumDiskCache{disk: d}
|
||||
|
||||
key := "testing"
|
||||
value := []byte("coolValue")
|
||||
|
||||
c.Set(key, value)
|
||||
|
||||
// Ensure we successfully set the value.
|
||||
got, ok := c.Get(key)
|
||||
assert.True(ok)
|
||||
assert.Equal(value, got)
|
||||
|
||||
c.Delete(key)
|
||||
|
||||
// Ensure the value is gone.
|
||||
got, ok = c.Get(key)
|
||||
assert.False(ok)
|
||||
assert.Equal([]byte{}, got)
|
||||
|
||||
// Ensure that deleting a non-existent value is a no-op.
|
||||
c.Delete(key)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -52,6 +52,9 @@ const (
|
||||
// defaultTimeout is the maximum amount of time per request when no timeout has been set on a RESTClient.
|
||||
// Defaults to 32s in order to have a distinguishable length of time, relative to other timeouts that exist.
|
||||
defaultTimeout = 32 * time.Second
|
||||
|
||||
// defaultBurst is the default burst to be used with the discovery client's token bucket rate limiter
|
||||
defaultBurst = 300
|
||||
)
|
||||
|
||||
// DiscoveryInterface holds the methods that discover server-supported API groups,
|
||||
@@ -456,12 +459,13 @@ func setDiscoveryDefaults(config *restclient.Config) error {
|
||||
if config.Timeout == 0 {
|
||||
config.Timeout = defaultTimeout
|
||||
}
|
||||
if config.Burst == 0 && config.QPS < 100 {
|
||||
// if a burst limit is not already configured
|
||||
if config.Burst == 0 {
|
||||
// discovery is expected to be bursty, increase the default burst
|
||||
// to accommodate looking up resource info for many API groups.
|
||||
// matches burst set by ConfigFlags#ToDiscoveryClient().
|
||||
// see https://issue.k8s.io/86149
|
||||
config.Burst = 100
|
||||
config.Burst = defaultBurst
|
||||
}
|
||||
codec := runtime.NoopEncoder{Decoder: scheme.Codecs.UniversalDecoder()}
|
||||
config.NegotiatedSerializer = serializer.NegotiatedSerializerWrapper(runtime.SerializerInfo{Serializer: codec})
|
||||
|
||||
@@ -454,6 +454,50 @@ func (c *dynamicResourceClient) Patch(ctx context.Context, name string, pt types
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// TODO: opts are currently ignored.
|
||||
func (c *dynamicResourceClient) Apply(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var uncastRet runtime.Object
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootPatchAction(c.resource, name, types.ApplyPatchType, outBytes), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(c.resource, name, types.ApplyPatchType, outBytes, subresources...), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewPatchAction(c.resource, c.namespace, name, types.ApplyPatchType, outBytes), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, types.ApplyPatchType, outBytes, subresources...), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &unstructured.Unstructured{}
|
||||
if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) ApplyStatus(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions) (*unstructured.Unstructured, error) {
|
||||
return c.Apply(ctx, name, obj, options, "status")
|
||||
}
|
||||
|
||||
func convertObjectsToUnstructured(s *runtime.Scheme, objs []runtime.Object) ([]runtime.Object, error) {
|
||||
ul := make([]runtime.Object, 0, len(objs))
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ type ResourceInterface interface {
|
||||
List(ctx context.Context, opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
|
||||
Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, options metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error)
|
||||
Apply(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions, subresources ...string) (*unstructured.Unstructured, error)
|
||||
ApplyStatus(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions) (*unstructured.Unstructured, error)
|
||||
}
|
||||
|
||||
type NamespaceableResourceInterface interface {
|
||||
|
||||
@@ -324,6 +324,48 @@ func (c *dynamicResourceClient) Patch(ctx context.Context, name string, pt types
|
||||
return uncastObj.(*unstructured.Unstructured), nil
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Apply(ctx context.Context, name string, obj *unstructured.Unstructured, opts metav1.ApplyOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, fmt.Errorf("name is required")
|
||||
}
|
||||
outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accessor, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
managedFields := accessor.GetManagedFields()
|
||||
if len(managedFields) > 0 {
|
||||
return nil, fmt.Errorf(`cannot apply an object with managed fields already set.
|
||||
Use the client-go/applyconfigurations "UnstructructuredExtractor" to obtain the unstructured ApplyConfiguration for the given field manager that you can use/modify here to apply`)
|
||||
}
|
||||
patchOpts := opts.ToPatchOptions()
|
||||
|
||||
result := c.client.client.
|
||||
Patch(types.ApplyPatchType).
|
||||
AbsPath(append(c.makeURLSegments(name), subresources...)...).
|
||||
Body(outBytes).
|
||||
SpecificallyVersionedParams(&patchOpts, dynamicParameterCodec, versionV1).
|
||||
Do(ctx)
|
||||
if err := result.Error(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
retBytes, err := result.Raw()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uncastObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, retBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return uncastObj.(*unstructured.Unstructured), nil
|
||||
}
|
||||
func (c *dynamicResourceClient) ApplyStatus(ctx context.Context, name string, obj *unstructured.Unstructured, opts metav1.ApplyOptions) (*unstructured.Unstructured, error) {
|
||||
return c.Apply(ctx, name, obj, opts, "status")
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) makeURLSegments(name string) []string {
|
||||
url := []string{}
|
||||
if len(c.resource.Group) == 0 {
|
||||
|
||||
76
go.mod
76
go.mod
@@ -2,48 +2,74 @@
|
||||
|
||||
module k8s.io/client-go
|
||||
|
||||
go 1.16
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.81.0 // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.18
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13
|
||||
github.com/Azure/go-autorest/autorest v0.11.27
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.20
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
||||
github.com/go-openapi/swag v0.19.14 // indirect
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/gnostic v0.5.7-v3refs
|
||||
github.com/google/go-cmp v0.5.5
|
||||
github.com/google/go-cmp v0.5.8
|
||||
github.com/google/gofuzz v1.1.0
|
||||
github.com/google/uuid v1.1.2
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7
|
||||
github.com/imdario/mergo v0.3.5
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/imdario/mergo v0.3.6
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.7.0
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
|
||||
github.com/stretchr/testify v1.8.0
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8
|
||||
google.golang.org/protobuf v1.27.1
|
||||
k8s.io/api v0.0.0-20220402025220-2de699698342
|
||||
k8s.io/apimachinery v0.0.0-20220330050810-6550efdb7444
|
||||
k8s.io/klog/v2 v2.60.1
|
||||
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42
|
||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1
|
||||
google.golang.org/protobuf v1.28.0
|
||||
k8s.io/api v0.25.4
|
||||
k8s.io/apimachinery v0.25.4
|
||||
k8s.io/klog/v2 v2.70.1
|
||||
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
)
|
||||
|
||||
replace (
|
||||
k8s.io/api => k8s.io/api v0.0.0-20220402025220-2de699698342
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20220330050810-6550efdb7444
|
||||
require (
|
||||
cloud.google.com/go v0.97.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
||||
github.com/go-openapi/swag v0.19.14 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
k8s.io/api => k8s.io/api v0.25.4
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.25.4
|
||||
)
|
||||
|
||||
215
go.sum
215
go.sum
@@ -17,8 +17,15 @@ cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKP
|
||||
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
|
||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||
cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8=
|
||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
|
||||
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
|
||||
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
|
||||
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
|
||||
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
|
||||
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
|
||||
cloud.google.com/go v0.97.0 h1:3DXvAyifywvq64LfkKaMOmkWPS1CikIQdMe2lY9vxU8=
|
||||
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
@@ -39,29 +46,31 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM=
|
||||
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
|
||||
github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A=
|
||||
github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=
|
||||
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
|
||||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
@@ -69,43 +78,36 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=
|
||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw=
|
||||
github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c=
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE=
|
||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||
github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM=
|
||||
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
@@ -113,6 +115,9 @@ github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5F
|
||||
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@@ -127,6 +132,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@@ -145,6 +151,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
|
||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
@@ -161,14 +168,17 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
@@ -180,25 +190,27 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
@@ -215,32 +227,19 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
|
||||
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU=
|
||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@@ -248,18 +247,22 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -272,14 +275,16 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
|
||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -303,6 +308,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
@@ -316,7 +322,6 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -338,7 +343,6 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
@@ -351,9 +355,10 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -365,6 +370,10 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -379,7 +388,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -388,10 +396,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -405,7 +410,6 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -421,10 +425,16 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -477,7 +487,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
@@ -492,11 +501,14 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
@@ -519,6 +531,13 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
|
||||
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
|
||||
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
|
||||
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
|
||||
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
|
||||
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
|
||||
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@@ -550,6 +569,7 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||
@@ -567,6 +587,21 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D
|
||||
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
|
||||
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
|
||||
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
|
||||
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -580,11 +615,19 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -597,30 +640,26 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
@@ -628,27 +667,23 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.0.0-20220402025220-2de699698342 h1:xFpsdy7RmF2niTyB76yUyPubqMa5m9/L9sswkdyhONo=
|
||||
k8s.io/api v0.0.0-20220402025220-2de699698342/go.mod h1:69QWTzqWVlGn0rU+x3dmk3WAsUQHmeQwIBWMbK1ZEyE=
|
||||
k8s.io/apimachinery v0.0.0-20220330050810-6550efdb7444 h1:whQmS3GtF822OUer+LPJnMFKn6kPfuJOCM/3xUuATIY=
|
||||
k8s.io/apimachinery v0.0.0-20220330050810-6550efdb7444/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
|
||||
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||
k8s.io/api v0.25.4 h1:3YO8J4RtmG7elEgaWMb4HgmpS2CfY1QlaOz9nwB+ZSs=
|
||||
k8s.io/api v0.25.4/go.mod h1:IG2+RzyPQLllQxnhzD8KQNEu4c4YvyDTpSMztf4A0OQ=
|
||||
k8s.io/apimachinery v0.25.4 h1:CtXsuaitMESSu339tfhVXhQrPET+EiWnIY1rcurKnAc=
|
||||
k8s.io/apimachinery v0.25.4/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc=
|
||||
k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU=
|
||||
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk=
|
||||
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
|
||||
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
|
||||
k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
|
||||
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
|
||||
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y=
|
||||
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
|
||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
|
||||
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
|
||||
@@ -274,8 +274,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1().NetworkPolicies().Informer()}, nil
|
||||
|
||||
// Group=networking.k8s.io, Version=v1alpha1
|
||||
case networkingv1alpha1.SchemeGroupVersion.WithResource("clustercidrconfigs"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1alpha1().ClusterCIDRConfigs().Informer()}, nil
|
||||
case networkingv1alpha1.SchemeGroupVersion.WithResource("clustercidrs"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Networking().V1alpha1().ClusterCIDRs().Informer()}, nil
|
||||
|
||||
// Group=networking.k8s.io, Version=v1beta1
|
||||
case networkingv1beta1.SchemeGroupVersion.WithResource("ingresses"):
|
||||
|
||||
@@ -32,58 +32,58 @@ import (
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// ClusterCIDRConfigInformer provides access to a shared informer and lister for
|
||||
// ClusterCIDRConfigs.
|
||||
type ClusterCIDRConfigInformer interface {
|
||||
// ClusterCIDRInformer provides access to a shared informer and lister for
|
||||
// ClusterCIDRs.
|
||||
type ClusterCIDRInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1alpha1.ClusterCIDRConfigLister
|
||||
Lister() v1alpha1.ClusterCIDRLister
|
||||
}
|
||||
|
||||
type clusterCIDRConfigInformer struct {
|
||||
type clusterCIDRInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// NewClusterCIDRConfigInformer constructs a new informer for ClusterCIDRConfig type.
|
||||
// NewClusterCIDRInformer constructs a new informer for ClusterCIDR type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewClusterCIDRConfigInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredClusterCIDRConfigInformer(client, resyncPeriod, indexers, nil)
|
||||
func NewClusterCIDRInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredClusterCIDRInformer(client, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredClusterCIDRConfigInformer constructs a new informer for ClusterCIDRConfig type.
|
||||
// NewFilteredClusterCIDRInformer constructs a new informer for ClusterCIDR type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredClusterCIDRConfigInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
func NewFilteredClusterCIDRInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.NetworkingV1alpha1().ClusterCIDRConfigs().List(context.TODO(), options)
|
||||
return client.NetworkingV1alpha1().ClusterCIDRs().List(context.TODO(), options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.NetworkingV1alpha1().ClusterCIDRConfigs().Watch(context.TODO(), options)
|
||||
return client.NetworkingV1alpha1().ClusterCIDRs().Watch(context.TODO(), options)
|
||||
},
|
||||
},
|
||||
&networkingv1alpha1.ClusterCIDRConfig{},
|
||||
&networkingv1alpha1.ClusterCIDR{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *clusterCIDRConfigInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredClusterCIDRConfigInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
func (f *clusterCIDRInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredClusterCIDRInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *clusterCIDRConfigInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&networkingv1alpha1.ClusterCIDRConfig{}, f.defaultInformer)
|
||||
func (f *clusterCIDRInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&networkingv1alpha1.ClusterCIDR{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *clusterCIDRConfigInformer) Lister() v1alpha1.ClusterCIDRConfigLister {
|
||||
return v1alpha1.NewClusterCIDRConfigLister(f.Informer().GetIndexer())
|
||||
func (f *clusterCIDRInformer) Lister() v1alpha1.ClusterCIDRLister {
|
||||
return v1alpha1.NewClusterCIDRLister(f.Informer().GetIndexer())
|
||||
}
|
||||
@@ -24,8 +24,8 @@ import (
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// ClusterCIDRConfigs returns a ClusterCIDRConfigInformer.
|
||||
ClusterCIDRConfigs() ClusterCIDRConfigInformer
|
||||
// ClusterCIDRs returns a ClusterCIDRInformer.
|
||||
ClusterCIDRs() ClusterCIDRInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
@@ -39,7 +39,7 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// ClusterCIDRConfigs returns a ClusterCIDRConfigInformer.
|
||||
func (v *version) ClusterCIDRConfigs() ClusterCIDRConfigInformer {
|
||||
return &clusterCIDRConfigInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
|
||||
// ClusterCIDRs returns a ClusterCIDRInformer.
|
||||
func (v *version) ClusterCIDRs() ClusterCIDRInformer {
|
||||
return &clusterCIDRInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
|
||||
58
kubernetes/fake/clientset_generated_test.go
Normal file
58
kubernetes/fake/clientset_generated_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright 2022 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 fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
policy "k8s.io/api/policy/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewSimpleClientset(t *testing.T) {
|
||||
client := NewSimpleClientset()
|
||||
client.CoreV1().Pods("default").Create(context.Background(), &v1.Pod{
|
||||
ObjectMeta: meta_v1.ObjectMeta{
|
||||
Name: "pod-1",
|
||||
Namespace: "default",
|
||||
},
|
||||
}, meta_v1.CreateOptions{})
|
||||
client.CoreV1().Pods("default").Create(context.Background(), &v1.Pod{
|
||||
ObjectMeta: meta_v1.ObjectMeta{
|
||||
Name: "pod-2",
|
||||
Namespace: "default",
|
||||
},
|
||||
}, meta_v1.CreateOptions{})
|
||||
err := client.CoreV1().Pods("default").EvictV1(context.Background(), &policy.Eviction{
|
||||
ObjectMeta: meta_v1.ObjectMeta{
|
||||
Name: "pod-2",
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("TestNewSimpleClientset() res = %v", err.Error())
|
||||
}
|
||||
|
||||
pods, err := client.CoreV1().Pods("default").List(context.Background(), meta_v1.ListOptions{})
|
||||
// err: item[0]: can't assign or convert v1beta1.Eviction into v1.Pod
|
||||
if err != nil {
|
||||
t.Errorf("TestNewSimpleClientset() res = %v", err.Error())
|
||||
} else {
|
||||
t.Logf("TestNewSimpleClientset() res = %v", pods)
|
||||
}
|
||||
}
|
||||
@@ -127,14 +127,14 @@ var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
|
||||
@@ -127,14 +127,14 @@ var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
|
||||
@@ -17,7 +17,7 @@ limitations under the License.
|
||||
package fake
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -26,9 +26,11 @@ import (
|
||||
)
|
||||
|
||||
func (c *FakeEvents) CreateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
|
||||
action := core.NewRootCreateAction(eventsResource, event)
|
||||
var action core.CreateActionImpl
|
||||
if c.ns != "" {
|
||||
action = core.NewCreateAction(eventsResource, c.ns, event)
|
||||
} else {
|
||||
action = core.NewCreateAction(eventsResource, event.GetNamespace(), event)
|
||||
}
|
||||
obj, err := c.Fake.Invokes(action, event)
|
||||
if obj == nil {
|
||||
@@ -40,9 +42,11 @@ func (c *FakeEvents) CreateWithEventNamespace(event *v1.Event) (*v1.Event, error
|
||||
|
||||
// Update replaces an existing event. Returns the copy of the event the server returns, or an error.
|
||||
func (c *FakeEvents) UpdateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
|
||||
action := core.NewRootUpdateAction(eventsResource, event)
|
||||
var action core.UpdateActionImpl
|
||||
if c.ns != "" {
|
||||
action = core.NewUpdateAction(eventsResource, c.ns, event)
|
||||
} else {
|
||||
action = core.NewUpdateAction(eventsResource, event.GetNamespace(), event)
|
||||
}
|
||||
obj, err := c.Fake.Invokes(action, event)
|
||||
if obj == nil {
|
||||
@@ -57,9 +61,11 @@ func (c *FakeEvents) UpdateWithEventNamespace(event *v1.Event) (*v1.Event, error
|
||||
func (c *FakeEvents) PatchWithEventNamespace(event *v1.Event, data []byte) (*v1.Event, error) {
|
||||
// TODO: Should be configurable to support additional patch strategies.
|
||||
pt := types.StrategicMergePatchType
|
||||
action := core.NewRootPatchAction(eventsResource, event.Name, pt, data)
|
||||
var action core.PatchActionImpl
|
||||
if c.ns != "" {
|
||||
action = core.NewPatchAction(eventsResource, c.ns, event.Name, pt, data)
|
||||
} else {
|
||||
action = core.NewPatchAction(eventsResource, event.GetNamespace(), event.Name, pt, data)
|
||||
}
|
||||
obj, err := c.Fake.Invokes(action, event)
|
||||
if obj == nil {
|
||||
@@ -71,9 +77,11 @@ func (c *FakeEvents) PatchWithEventNamespace(event *v1.Event, data []byte) (*v1.
|
||||
|
||||
// Search returns a list of events matching the specified object.
|
||||
func (c *FakeEvents) Search(scheme *runtime.Scheme, objOrRef runtime.Object) (*v1.EventList, error) {
|
||||
action := core.NewRootListAction(eventsResource, eventsKind, metav1.ListOptions{})
|
||||
var action core.ListActionImpl
|
||||
if c.ns != "" {
|
||||
action = core.NewListAction(eventsResource, eventsKind, c.ns, metav1.ListOptions{})
|
||||
} else {
|
||||
action = core.NewListAction(eventsResource, eventsKind, v1.NamespaceDefault, metav1.ListOptions{})
|
||||
}
|
||||
obj, err := c.Fake.Invokes(action, &v1.EventList{})
|
||||
if obj == nil {
|
||||
|
||||
@@ -82,7 +82,8 @@ func (e *events) UpdateWithEventNamespace(event *v1beta1.Event) (*v1beta1.Event,
|
||||
// It returns the copy of the event that the server returns, or an error.
|
||||
// The namespace and name of the target event is deduced from the event.
|
||||
// The namespace must either match this event client's namespace, or this event client must
|
||||
// have been created with the "" namespace.
|
||||
//
|
||||
// have been created with the "" namespace.
|
||||
func (e *events) PatchWithEventNamespace(event *v1beta1.Event, data []byte) (*v1beta1.Event, error) {
|
||||
if e.ns != "" && event.Namespace != e.ns {
|
||||
return nil, fmt.Errorf("can't patch an event with namespace '%v' in namespace '%v'", event.Namespace, e.ns)
|
||||
|
||||
197
kubernetes/typed/networking/v1alpha1/clustercidr.go
Normal file
197
kubernetes/typed/networking/v1alpha1/clustercidr.go
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
json "encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
v1alpha1 "k8s.io/api/networking/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
networkingv1alpha1 "k8s.io/client-go/applyconfigurations/networking/v1alpha1"
|
||||
scheme "k8s.io/client-go/kubernetes/scheme"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// ClusterCIDRsGetter has a method to return a ClusterCIDRInterface.
|
||||
// A group's client should implement this interface.
|
||||
type ClusterCIDRsGetter interface {
|
||||
ClusterCIDRs() ClusterCIDRInterface
|
||||
}
|
||||
|
||||
// ClusterCIDRInterface has methods to work with ClusterCIDR resources.
|
||||
type ClusterCIDRInterface interface {
|
||||
Create(ctx context.Context, clusterCIDR *v1alpha1.ClusterCIDR, opts v1.CreateOptions) (*v1alpha1.ClusterCIDR, error)
|
||||
Update(ctx context.Context, clusterCIDR *v1alpha1.ClusterCIDR, opts v1.UpdateOptions) (*v1alpha1.ClusterCIDR, error)
|
||||
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ClusterCIDR, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ClusterCIDRList, error)
|
||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterCIDR, err error)
|
||||
Apply(ctx context.Context, clusterCIDR *networkingv1alpha1.ClusterCIDRApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ClusterCIDR, err error)
|
||||
ClusterCIDRExpansion
|
||||
}
|
||||
|
||||
// clusterCIDRs implements ClusterCIDRInterface
|
||||
type clusterCIDRs struct {
|
||||
client rest.Interface
|
||||
}
|
||||
|
||||
// newClusterCIDRs returns a ClusterCIDRs
|
||||
func newClusterCIDRs(c *NetworkingV1alpha1Client) *clusterCIDRs {
|
||||
return &clusterCIDRs{
|
||||
client: c.RESTClient(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the clusterCIDR, and returns the corresponding clusterCIDR object, and an error if there is any.
|
||||
func (c *clusterCIDRs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterCIDR, err error) {
|
||||
result = &v1alpha1.ClusterCIDR{}
|
||||
err = c.client.Get().
|
||||
Resource("clustercidrs").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of ClusterCIDRs that match those selectors.
|
||||
func (c *clusterCIDRs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterCIDRList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1alpha1.ClusterCIDRList{}
|
||||
err = c.client.Get().
|
||||
Resource("clustercidrs").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested clusterCIDRs.
|
||||
func (c *clusterCIDRs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Resource("clustercidrs").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch(ctx)
|
||||
}
|
||||
|
||||
// Create takes the representation of a clusterCIDR and creates it. Returns the server's representation of the clusterCIDR, and an error, if there is any.
|
||||
func (c *clusterCIDRs) Create(ctx context.Context, clusterCIDR *v1alpha1.ClusterCIDR, opts v1.CreateOptions) (result *v1alpha1.ClusterCIDR, err error) {
|
||||
result = &v1alpha1.ClusterCIDR{}
|
||||
err = c.client.Post().
|
||||
Resource("clustercidrs").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(clusterCIDR).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a clusterCIDR and updates it. Returns the server's representation of the clusterCIDR, and an error, if there is any.
|
||||
func (c *clusterCIDRs) Update(ctx context.Context, clusterCIDR *v1alpha1.ClusterCIDR, opts v1.UpdateOptions) (result *v1alpha1.ClusterCIDR, err error) {
|
||||
result = &v1alpha1.ClusterCIDR{}
|
||||
err = c.client.Put().
|
||||
Resource("clustercidrs").
|
||||
Name(clusterCIDR.Name).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(clusterCIDR).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the clusterCIDR and deletes it. Returns an error if one occurs.
|
||||
func (c *clusterCIDRs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Resource("clustercidrs").
|
||||
Name(name).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *clusterCIDRs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOpts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Resource("clustercidrs").
|
||||
VersionedParams(&listOpts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched clusterCIDR.
|
||||
func (c *clusterCIDRs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterCIDR, err error) {
|
||||
result = &v1alpha1.ClusterCIDR{}
|
||||
err = c.client.Patch(pt).
|
||||
Resource("clustercidrs").
|
||||
Name(name).
|
||||
SubResource(subresources...).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(data).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Apply takes the given apply declarative configuration, applies it and returns the applied clusterCIDR.
|
||||
func (c *clusterCIDRs) Apply(ctx context.Context, clusterCIDR *networkingv1alpha1.ClusterCIDRApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ClusterCIDR, err error) {
|
||||
if clusterCIDR == nil {
|
||||
return nil, fmt.Errorf("clusterCIDR provided to Apply must not be nil")
|
||||
}
|
||||
patchOpts := opts.ToPatchOptions()
|
||||
data, err := json.Marshal(clusterCIDR)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := clusterCIDR.Name
|
||||
if name == nil {
|
||||
return nil, fmt.Errorf("clusterCIDR.Name must be provided to Apply")
|
||||
}
|
||||
result = &v1alpha1.ClusterCIDR{}
|
||||
err = c.client.Patch(types.ApplyPatchType).
|
||||
Resource("clustercidrs").
|
||||
Name(*name).
|
||||
VersionedParams(&patchOpts, scheme.ParameterCodec).
|
||||
Body(data).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"context"
|
||||
json "encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
v1alpha1 "k8s.io/api/networking/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
networkingv1alpha1 "k8s.io/client-go/applyconfigurations/networking/v1alpha1"
|
||||
scheme "k8s.io/client-go/kubernetes/scheme"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// ClusterCIDRConfigsGetter has a method to return a ClusterCIDRConfigInterface.
|
||||
// A group's client should implement this interface.
|
||||
type ClusterCIDRConfigsGetter interface {
|
||||
ClusterCIDRConfigs() ClusterCIDRConfigInterface
|
||||
}
|
||||
|
||||
// ClusterCIDRConfigInterface has methods to work with ClusterCIDRConfig resources.
|
||||
type ClusterCIDRConfigInterface interface {
|
||||
Create(ctx context.Context, clusterCIDRConfig *v1alpha1.ClusterCIDRConfig, opts v1.CreateOptions) (*v1alpha1.ClusterCIDRConfig, error)
|
||||
Update(ctx context.Context, clusterCIDRConfig *v1alpha1.ClusterCIDRConfig, opts v1.UpdateOptions) (*v1alpha1.ClusterCIDRConfig, error)
|
||||
UpdateStatus(ctx context.Context, clusterCIDRConfig *v1alpha1.ClusterCIDRConfig, opts v1.UpdateOptions) (*v1alpha1.ClusterCIDRConfig, error)
|
||||
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ClusterCIDRConfig, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ClusterCIDRConfigList, error)
|
||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterCIDRConfig, err error)
|
||||
Apply(ctx context.Context, clusterCIDRConfig *networkingv1alpha1.ClusterCIDRConfigApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ClusterCIDRConfig, err error)
|
||||
ApplyStatus(ctx context.Context, clusterCIDRConfig *networkingv1alpha1.ClusterCIDRConfigApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ClusterCIDRConfig, err error)
|
||||
ClusterCIDRConfigExpansion
|
||||
}
|
||||
|
||||
// clusterCIDRConfigs implements ClusterCIDRConfigInterface
|
||||
type clusterCIDRConfigs struct {
|
||||
client rest.Interface
|
||||
}
|
||||
|
||||
// newClusterCIDRConfigs returns a ClusterCIDRConfigs
|
||||
func newClusterCIDRConfigs(c *NetworkingV1alpha1Client) *clusterCIDRConfigs {
|
||||
return &clusterCIDRConfigs{
|
||||
client: c.RESTClient(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the clusterCIDRConfig, and returns the corresponding clusterCIDRConfig object, and an error if there is any.
|
||||
func (c *clusterCIDRConfigs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
result = &v1alpha1.ClusterCIDRConfig{}
|
||||
err = c.client.Get().
|
||||
Resource("clustercidrconfigs").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of ClusterCIDRConfigs that match those selectors.
|
||||
func (c *clusterCIDRConfigs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterCIDRConfigList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1alpha1.ClusterCIDRConfigList{}
|
||||
err = c.client.Get().
|
||||
Resource("clustercidrconfigs").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested clusterCIDRConfigs.
|
||||
func (c *clusterCIDRConfigs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Resource("clustercidrconfigs").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch(ctx)
|
||||
}
|
||||
|
||||
// Create takes the representation of a clusterCIDRConfig and creates it. Returns the server's representation of the clusterCIDRConfig, and an error, if there is any.
|
||||
func (c *clusterCIDRConfigs) Create(ctx context.Context, clusterCIDRConfig *v1alpha1.ClusterCIDRConfig, opts v1.CreateOptions) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
result = &v1alpha1.ClusterCIDRConfig{}
|
||||
err = c.client.Post().
|
||||
Resource("clustercidrconfigs").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(clusterCIDRConfig).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a clusterCIDRConfig and updates it. Returns the server's representation of the clusterCIDRConfig, and an error, if there is any.
|
||||
func (c *clusterCIDRConfigs) Update(ctx context.Context, clusterCIDRConfig *v1alpha1.ClusterCIDRConfig, opts v1.UpdateOptions) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
result = &v1alpha1.ClusterCIDRConfig{}
|
||||
err = c.client.Put().
|
||||
Resource("clustercidrconfigs").
|
||||
Name(clusterCIDRConfig.Name).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(clusterCIDRConfig).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *clusterCIDRConfigs) UpdateStatus(ctx context.Context, clusterCIDRConfig *v1alpha1.ClusterCIDRConfig, opts v1.UpdateOptions) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
result = &v1alpha1.ClusterCIDRConfig{}
|
||||
err = c.client.Put().
|
||||
Resource("clustercidrconfigs").
|
||||
Name(clusterCIDRConfig.Name).
|
||||
SubResource("status").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(clusterCIDRConfig).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the clusterCIDRConfig and deletes it. Returns an error if one occurs.
|
||||
func (c *clusterCIDRConfigs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Resource("clustercidrconfigs").
|
||||
Name(name).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *clusterCIDRConfigs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOpts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Resource("clustercidrconfigs").
|
||||
VersionedParams(&listOpts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched clusterCIDRConfig.
|
||||
func (c *clusterCIDRConfigs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
result = &v1alpha1.ClusterCIDRConfig{}
|
||||
err = c.client.Patch(pt).
|
||||
Resource("clustercidrconfigs").
|
||||
Name(name).
|
||||
SubResource(subresources...).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(data).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Apply takes the given apply declarative configuration, applies it and returns the applied clusterCIDRConfig.
|
||||
func (c *clusterCIDRConfigs) Apply(ctx context.Context, clusterCIDRConfig *networkingv1alpha1.ClusterCIDRConfigApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
if clusterCIDRConfig == nil {
|
||||
return nil, fmt.Errorf("clusterCIDRConfig provided to Apply must not be nil")
|
||||
}
|
||||
patchOpts := opts.ToPatchOptions()
|
||||
data, err := json.Marshal(clusterCIDRConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := clusterCIDRConfig.Name
|
||||
if name == nil {
|
||||
return nil, fmt.Errorf("clusterCIDRConfig.Name must be provided to Apply")
|
||||
}
|
||||
result = &v1alpha1.ClusterCIDRConfig{}
|
||||
err = c.client.Patch(types.ApplyPatchType).
|
||||
Resource("clustercidrconfigs").
|
||||
Name(*name).
|
||||
VersionedParams(&patchOpts, scheme.ParameterCodec).
|
||||
Body(data).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// ApplyStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus().
|
||||
func (c *clusterCIDRConfigs) ApplyStatus(ctx context.Context, clusterCIDRConfig *networkingv1alpha1.ClusterCIDRConfigApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
if clusterCIDRConfig == nil {
|
||||
return nil, fmt.Errorf("clusterCIDRConfig provided to Apply must not be nil")
|
||||
}
|
||||
patchOpts := opts.ToPatchOptions()
|
||||
data, err := json.Marshal(clusterCIDRConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
name := clusterCIDRConfig.Name
|
||||
if name == nil {
|
||||
return nil, fmt.Errorf("clusterCIDRConfig.Name must be provided to Apply")
|
||||
}
|
||||
|
||||
result = &v1alpha1.ClusterCIDRConfig{}
|
||||
err = c.client.Patch(types.ApplyPatchType).
|
||||
Resource("clustercidrconfigs").
|
||||
Name(*name).
|
||||
SubResource("status").
|
||||
VersionedParams(&patchOpts, scheme.ParameterCodec).
|
||||
Body(data).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
146
kubernetes/typed/networking/v1alpha1/fake/fake_clustercidr.go
Normal file
146
kubernetes/typed/networking/v1alpha1/fake/fake_clustercidr.go
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
json "encoding/json"
|
||||
"fmt"
|
||||
|
||||
v1alpha1 "k8s.io/api/networking/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
networkingv1alpha1 "k8s.io/client-go/applyconfigurations/networking/v1alpha1"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeClusterCIDRs implements ClusterCIDRInterface
|
||||
type FakeClusterCIDRs struct {
|
||||
Fake *FakeNetworkingV1alpha1
|
||||
}
|
||||
|
||||
var clustercidrsResource = schema.GroupVersionResource{Group: "networking.k8s.io", Version: "v1alpha1", Resource: "clustercidrs"}
|
||||
|
||||
var clustercidrsKind = schema.GroupVersionKind{Group: "networking.k8s.io", Version: "v1alpha1", Kind: "ClusterCIDR"}
|
||||
|
||||
// Get takes name of the clusterCIDR, and returns the corresponding clusterCIDR object, and an error if there is any.
|
||||
func (c *FakeClusterCIDRs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterCIDR, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(clustercidrsResource, name), &v1alpha1.ClusterCIDR{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDR), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of ClusterCIDRs that match those selectors.
|
||||
func (c *FakeClusterCIDRs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterCIDRList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(clustercidrsResource, clustercidrsKind, opts), &v1alpha1.ClusterCIDRList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.ClusterCIDRList{ListMeta: obj.(*v1alpha1.ClusterCIDRList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.ClusterCIDRList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested clusterCIDRs.
|
||||
func (c *FakeClusterCIDRs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(clustercidrsResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a clusterCIDR and creates it. Returns the server's representation of the clusterCIDR, and an error, if there is any.
|
||||
func (c *FakeClusterCIDRs) Create(ctx context.Context, clusterCIDR *v1alpha1.ClusterCIDR, opts v1.CreateOptions) (result *v1alpha1.ClusterCIDR, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(clustercidrsResource, clusterCIDR), &v1alpha1.ClusterCIDR{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDR), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a clusterCIDR and updates it. Returns the server's representation of the clusterCIDR, and an error, if there is any.
|
||||
func (c *FakeClusterCIDRs) Update(ctx context.Context, clusterCIDR *v1alpha1.ClusterCIDR, opts v1.UpdateOptions) (result *v1alpha1.ClusterCIDR, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(clustercidrsResource, clusterCIDR), &v1alpha1.ClusterCIDR{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDR), err
|
||||
}
|
||||
|
||||
// Delete takes name of the clusterCIDR and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeClusterCIDRs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteActionWithOptions(clustercidrsResource, name, opts), &v1alpha1.ClusterCIDR{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeClusterCIDRs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(clustercidrsResource, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.ClusterCIDRList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched clusterCIDR.
|
||||
func (c *FakeClusterCIDRs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterCIDR, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(clustercidrsResource, name, pt, data, subresources...), &v1alpha1.ClusterCIDR{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDR), err
|
||||
}
|
||||
|
||||
// Apply takes the given apply declarative configuration, applies it and returns the applied clusterCIDR.
|
||||
func (c *FakeClusterCIDRs) Apply(ctx context.Context, clusterCIDR *networkingv1alpha1.ClusterCIDRApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ClusterCIDR, err error) {
|
||||
if clusterCIDR == nil {
|
||||
return nil, fmt.Errorf("clusterCIDR provided to Apply must not be nil")
|
||||
}
|
||||
data, err := json.Marshal(clusterCIDR)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := clusterCIDR.Name
|
||||
if name == nil {
|
||||
return nil, fmt.Errorf("clusterCIDR.Name must be provided to Apply")
|
||||
}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(clustercidrsResource, *name, types.ApplyPatchType, data), &v1alpha1.ClusterCIDR{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDR), err
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
json "encoding/json"
|
||||
"fmt"
|
||||
|
||||
v1alpha1 "k8s.io/api/networking/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
networkingv1alpha1 "k8s.io/client-go/applyconfigurations/networking/v1alpha1"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeClusterCIDRConfigs implements ClusterCIDRConfigInterface
|
||||
type FakeClusterCIDRConfigs struct {
|
||||
Fake *FakeNetworkingV1alpha1
|
||||
}
|
||||
|
||||
var clustercidrconfigsResource = schema.GroupVersionResource{Group: "networking.k8s.io", Version: "v1alpha1", Resource: "clustercidrconfigs"}
|
||||
|
||||
var clustercidrconfigsKind = schema.GroupVersionKind{Group: "networking.k8s.io", Version: "v1alpha1", Kind: "ClusterCIDRConfig"}
|
||||
|
||||
// Get takes name of the clusterCIDRConfig, and returns the corresponding clusterCIDRConfig object, and an error if there is any.
|
||||
func (c *FakeClusterCIDRConfigs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(clustercidrconfigsResource, name), &v1alpha1.ClusterCIDRConfig{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDRConfig), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of ClusterCIDRConfigs that match those selectors.
|
||||
func (c *FakeClusterCIDRConfigs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ClusterCIDRConfigList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(clustercidrconfigsResource, clustercidrconfigsKind, opts), &v1alpha1.ClusterCIDRConfigList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.ClusterCIDRConfigList{ListMeta: obj.(*v1alpha1.ClusterCIDRConfigList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.ClusterCIDRConfigList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested clusterCIDRConfigs.
|
||||
func (c *FakeClusterCIDRConfigs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(clustercidrconfigsResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a clusterCIDRConfig and creates it. Returns the server's representation of the clusterCIDRConfig, and an error, if there is any.
|
||||
func (c *FakeClusterCIDRConfigs) Create(ctx context.Context, clusterCIDRConfig *v1alpha1.ClusterCIDRConfig, opts v1.CreateOptions) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(clustercidrconfigsResource, clusterCIDRConfig), &v1alpha1.ClusterCIDRConfig{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDRConfig), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a clusterCIDRConfig and updates it. Returns the server's representation of the clusterCIDRConfig, and an error, if there is any.
|
||||
func (c *FakeClusterCIDRConfigs) Update(ctx context.Context, clusterCIDRConfig *v1alpha1.ClusterCIDRConfig, opts v1.UpdateOptions) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(clustercidrconfigsResource, clusterCIDRConfig), &v1alpha1.ClusterCIDRConfig{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDRConfig), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeClusterCIDRConfigs) UpdateStatus(ctx context.Context, clusterCIDRConfig *v1alpha1.ClusterCIDRConfig, opts v1.UpdateOptions) (*v1alpha1.ClusterCIDRConfig, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateSubresourceAction(clustercidrconfigsResource, "status", clusterCIDRConfig), &v1alpha1.ClusterCIDRConfig{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDRConfig), err
|
||||
}
|
||||
|
||||
// Delete takes name of the clusterCIDRConfig and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeClusterCIDRConfigs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteActionWithOptions(clustercidrconfigsResource, name, opts), &v1alpha1.ClusterCIDRConfig{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeClusterCIDRConfigs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(clustercidrconfigsResource, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.ClusterCIDRConfigList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched clusterCIDRConfig.
|
||||
func (c *FakeClusterCIDRConfigs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(clustercidrconfigsResource, name, pt, data, subresources...), &v1alpha1.ClusterCIDRConfig{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDRConfig), err
|
||||
}
|
||||
|
||||
// Apply takes the given apply declarative configuration, applies it and returns the applied clusterCIDRConfig.
|
||||
func (c *FakeClusterCIDRConfigs) Apply(ctx context.Context, clusterCIDRConfig *networkingv1alpha1.ClusterCIDRConfigApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
if clusterCIDRConfig == nil {
|
||||
return nil, fmt.Errorf("clusterCIDRConfig provided to Apply must not be nil")
|
||||
}
|
||||
data, err := json.Marshal(clusterCIDRConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := clusterCIDRConfig.Name
|
||||
if name == nil {
|
||||
return nil, fmt.Errorf("clusterCIDRConfig.Name must be provided to Apply")
|
||||
}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(clustercidrconfigsResource, *name, types.ApplyPatchType, data), &v1alpha1.ClusterCIDRConfig{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDRConfig), err
|
||||
}
|
||||
|
||||
// ApplyStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus().
|
||||
func (c *FakeClusterCIDRConfigs) ApplyStatus(ctx context.Context, clusterCIDRConfig *networkingv1alpha1.ClusterCIDRConfigApplyConfiguration, opts v1.ApplyOptions) (result *v1alpha1.ClusterCIDRConfig, err error) {
|
||||
if clusterCIDRConfig == nil {
|
||||
return nil, fmt.Errorf("clusterCIDRConfig provided to Apply must not be nil")
|
||||
}
|
||||
data, err := json.Marshal(clusterCIDRConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := clusterCIDRConfig.Name
|
||||
if name == nil {
|
||||
return nil, fmt.Errorf("clusterCIDRConfig.Name must be provided to Apply")
|
||||
}
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(clustercidrconfigsResource, *name, types.ApplyPatchType, data, "status"), &v1alpha1.ClusterCIDRConfig{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDRConfig), err
|
||||
}
|
||||
@@ -28,8 +28,8 @@ type FakeNetworkingV1alpha1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeNetworkingV1alpha1) ClusterCIDRConfigs() v1alpha1.ClusterCIDRConfigInterface {
|
||||
return &FakeClusterCIDRConfigs{c}
|
||||
func (c *FakeNetworkingV1alpha1) ClusterCIDRs() v1alpha1.ClusterCIDRInterface {
|
||||
return &FakeClusterCIDRs{c}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
|
||||
@@ -18,4 +18,4 @@ limitations under the License.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
type ClusterCIDRConfigExpansion interface{}
|
||||
type ClusterCIDRExpansion interface{}
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
|
||||
type NetworkingV1alpha1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
ClusterCIDRConfigsGetter
|
||||
ClusterCIDRsGetter
|
||||
}
|
||||
|
||||
// NetworkingV1alpha1Client is used to interact with features provided by the networking.k8s.io group.
|
||||
@@ -36,8 +36,8 @@ type NetworkingV1alpha1Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *NetworkingV1alpha1Client) ClusterCIDRConfigs() ClusterCIDRConfigInterface {
|
||||
return newClusterCIDRConfigs(c)
|
||||
func (c *NetworkingV1alpha1Client) ClusterCIDRs() ClusterCIDRInterface {
|
||||
return newClusterCIDRs(c)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new NetworkingV1alpha1Client for the given config.
|
||||
|
||||
68
listers/networking/v1alpha1/clustercidr.go
Normal file
68
listers/networking/v1alpha1/clustercidr.go
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1alpha1 "k8s.io/api/networking/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// ClusterCIDRLister helps list ClusterCIDRs.
|
||||
// All objects returned here must be treated as read-only.
|
||||
type ClusterCIDRLister interface {
|
||||
// List lists all ClusterCIDRs in the indexer.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.ClusterCIDR, err error)
|
||||
// Get retrieves the ClusterCIDR from the index for a given name.
|
||||
// Objects returned here must be treated as read-only.
|
||||
Get(name string) (*v1alpha1.ClusterCIDR, error)
|
||||
ClusterCIDRListerExpansion
|
||||
}
|
||||
|
||||
// clusterCIDRLister implements the ClusterCIDRLister interface.
|
||||
type clusterCIDRLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewClusterCIDRLister returns a new ClusterCIDRLister.
|
||||
func NewClusterCIDRLister(indexer cache.Indexer) ClusterCIDRLister {
|
||||
return &clusterCIDRLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all ClusterCIDRs in the indexer.
|
||||
func (s *clusterCIDRLister) List(selector labels.Selector) (ret []*v1alpha1.ClusterCIDR, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1alpha1.ClusterCIDR))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the ClusterCIDR from the index for a given name.
|
||||
func (s *clusterCIDRLister) Get(name string) (*v1alpha1.ClusterCIDR, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1alpha1.Resource("clustercidr"), name)
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDR), nil
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1alpha1 "k8s.io/api/networking/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// ClusterCIDRConfigLister helps list ClusterCIDRConfigs.
|
||||
// All objects returned here must be treated as read-only.
|
||||
type ClusterCIDRConfigLister interface {
|
||||
// List lists all ClusterCIDRConfigs in the indexer.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.ClusterCIDRConfig, err error)
|
||||
// Get retrieves the ClusterCIDRConfig from the index for a given name.
|
||||
// Objects returned here must be treated as read-only.
|
||||
Get(name string) (*v1alpha1.ClusterCIDRConfig, error)
|
||||
ClusterCIDRConfigListerExpansion
|
||||
}
|
||||
|
||||
// clusterCIDRConfigLister implements the ClusterCIDRConfigLister interface.
|
||||
type clusterCIDRConfigLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewClusterCIDRConfigLister returns a new ClusterCIDRConfigLister.
|
||||
func NewClusterCIDRConfigLister(indexer cache.Indexer) ClusterCIDRConfigLister {
|
||||
return &clusterCIDRConfigLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all ClusterCIDRConfigs in the indexer.
|
||||
func (s *clusterCIDRConfigLister) List(selector labels.Selector) (ret []*v1alpha1.ClusterCIDRConfig, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1alpha1.ClusterCIDRConfig))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the ClusterCIDRConfig from the index for a given name.
|
||||
func (s *clusterCIDRConfigLister) Get(name string) (*v1alpha1.ClusterCIDRConfig, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1alpha1.Resource("clustercidrconfig"), name)
|
||||
}
|
||||
return obj.(*v1alpha1.ClusterCIDRConfig), nil
|
||||
}
|
||||
@@ -18,6 +18,6 @@ limitations under the License.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
// ClusterCIDRConfigListerExpansion allows custom methods to be added to
|
||||
// ClusterCIDRConfigLister.
|
||||
type ClusterCIDRConfigListerExpansion interface{}
|
||||
// ClusterCIDRListerExpansion allows custom methods to be added to
|
||||
// ClusterCIDRLister.
|
||||
type ClusterCIDRListerExpansion interface{}
|
||||
|
||||
@@ -89,7 +89,7 @@ var warnOnce sync.Once
|
||||
func newAzureAuthProvider(_ string, cfg map[string]string, persister restclient.AuthProviderConfigPersister) (restclient.AuthProvider, error) {
|
||||
// deprecated in v1.22, remove in v1.25
|
||||
warnOnce.Do(func() {
|
||||
klog.Warningf(`WARNING: the azure auth plugin is deprecated in v1.22+, unavailable in v1.25+; use https://github.com/Azure/kubelogin instead.
|
||||
klog.Warningf(`WARNING: the azure auth plugin is deprecated in v1.22+, unavailable in v1.26+; use https://github.com/Azure/kubelogin instead.
|
||||
To learn more, consult https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins`)
|
||||
})
|
||||
|
||||
|
||||
@@ -199,14 +199,18 @@ func newAuthenticator(c *cache, isTerminalFunc func(int) bool, config *api.ExecC
|
||||
now: time.Now,
|
||||
environ: os.Environ,
|
||||
|
||||
defaultDialer: defaultDialer,
|
||||
connTracker: connTracker,
|
||||
connTracker: connTracker,
|
||||
}
|
||||
|
||||
for _, env := range config.Env {
|
||||
a.env = append(a.env, env.Name+"="+env.Value)
|
||||
}
|
||||
|
||||
// these functions are made comparable and stored in the cache so that repeated clientset
|
||||
// construction with the same rest.Config results in a single TLS cache and Authenticator
|
||||
a.getCert = &transport.GetCertHolder{GetCert: a.cert}
|
||||
a.dial = &transport.DialHolder{Dial: defaultDialer.DialContext}
|
||||
|
||||
return c.put(key, a), nil
|
||||
}
|
||||
|
||||
@@ -261,8 +265,6 @@ type Authenticator struct {
|
||||
now func() time.Time
|
||||
environ func() []string
|
||||
|
||||
// defaultDialer is used for clients which don't specify a custom dialer
|
||||
defaultDialer *connrotation.Dialer
|
||||
// connTracker tracks all connections opened that we need to close when rotating a client certificate
|
||||
connTracker *connrotation.ConnectionTracker
|
||||
|
||||
@@ -273,6 +275,12 @@ type Authenticator struct {
|
||||
mu sync.Mutex
|
||||
cachedCreds *credentials
|
||||
exp time.Time
|
||||
|
||||
// getCert makes Authenticator.cert comparable to support TLS config caching
|
||||
getCert *transport.GetCertHolder
|
||||
// dial is used for clients which do not specify a custom dialer
|
||||
// it is comparable to support TLS config caching
|
||||
dial *transport.DialHolder
|
||||
}
|
||||
|
||||
type credentials struct {
|
||||
@@ -300,18 +308,20 @@ func (a *Authenticator) UpdateTransportConfig(c *transport.Config) error {
|
||||
if c.HasCertCallback() {
|
||||
return errors.New("can't add TLS certificate callback: transport.Config.TLS.GetCert already set")
|
||||
}
|
||||
c.TLS.GetCert = a.cert
|
||||
c.TLS.GetCert = a.getCert.GetCert
|
||||
c.TLS.GetCertHolder = a.getCert // comparable for TLS config caching
|
||||
|
||||
var d *connrotation.Dialer
|
||||
if c.Dial != nil {
|
||||
// if c has a custom dialer, we have to wrap it
|
||||
d = connrotation.NewDialerWithTracker(c.Dial, a.connTracker)
|
||||
// TLS config caching is not supported for this config
|
||||
d := connrotation.NewDialerWithTracker(c.Dial, a.connTracker)
|
||||
c.Dial = d.DialContext
|
||||
c.DialHolder = nil
|
||||
} else {
|
||||
d = a.defaultDialer
|
||||
c.Dial = a.dial.Dial
|
||||
c.DialHolder = a.dial // comparable for TLS config caching
|
||||
}
|
||||
|
||||
c.Dial = d.DialContext
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
106
plugin/pkg/client/auth/exec/exec_cache_test.go
Normal file
106
plugin/pkg/client/auth/exec/exec_cache_test.go
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2022 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 exec_test // separate package to prevent circular import
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
)
|
||||
|
||||
// TestExecTLSCache asserts the semantics of the TLS cache when exec auth is used.
|
||||
//
|
||||
// In particular, when:
|
||||
// - multiple identical rest configs exist as distinct objects, and
|
||||
// - these rest configs use exec auth, and
|
||||
// - these rest configs are used to create distinct clientsets, then
|
||||
//
|
||||
// the underlying TLS config is shared between those clientsets.
|
||||
func TestExecTLSCache(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
config1 := &rest.Config{
|
||||
Host: "https://localhost",
|
||||
ExecProvider: &clientcmdapi.ExecConfig{
|
||||
Command: "./testdata/test-plugin.sh",
|
||||
APIVersion: "client.authentication.k8s.io/v1",
|
||||
InteractiveMode: clientcmdapi.IfAvailableExecInteractiveMode,
|
||||
},
|
||||
}
|
||||
client1 := clientset.NewForConfigOrDie(config1)
|
||||
|
||||
config2 := &rest.Config{
|
||||
Host: "https://localhost",
|
||||
ExecProvider: &clientcmdapi.ExecConfig{
|
||||
Command: "./testdata/test-plugin.sh",
|
||||
APIVersion: "client.authentication.k8s.io/v1",
|
||||
InteractiveMode: clientcmdapi.IfAvailableExecInteractiveMode,
|
||||
},
|
||||
}
|
||||
client2 := clientset.NewForConfigOrDie(config2)
|
||||
|
||||
config3 := &rest.Config{
|
||||
Host: "https://localhost",
|
||||
ExecProvider: &clientcmdapi.ExecConfig{
|
||||
Command: "./testdata/test-plugin.sh",
|
||||
Args: []string{"make this exec auth different"},
|
||||
APIVersion: "client.authentication.k8s.io/v1",
|
||||
InteractiveMode: clientcmdapi.IfAvailableExecInteractiveMode,
|
||||
},
|
||||
}
|
||||
client3 := clientset.NewForConfigOrDie(config3)
|
||||
|
||||
_, _ = client1.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
|
||||
_, _ = client2.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
|
||||
_, _ = client3.CoreV1().PersistentVolumes().List(ctx, metav1.ListOptions{})
|
||||
|
||||
rt1 := client1.RESTClient().(*rest.RESTClient).Client.Transport
|
||||
rt2 := client2.RESTClient().(*rest.RESTClient).Client.Transport
|
||||
rt3 := client3.RESTClient().(*rest.RESTClient).Client.Transport
|
||||
|
||||
tlsConfig1, err := utilnet.TLSClientConfig(rt1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tlsConfig2, err := utilnet.TLSClientConfig(rt2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tlsConfig3, err := utilnet.TLSClientConfig(rt3)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if tlsConfig1 == nil || tlsConfig2 == nil || tlsConfig3 == nil {
|
||||
t.Fatal("expected non-nil TLS configs")
|
||||
}
|
||||
|
||||
if tlsConfig1 != tlsConfig2 {
|
||||
t.Fatal("expected the same TLS config for matching exec config via rest config")
|
||||
}
|
||||
|
||||
if tlsConfig1 == tlsConfig3 {
|
||||
t.Fatal("expected different TLS config for non-matching exec config via rest config")
|
||||
}
|
||||
}
|
||||
@@ -59,55 +59,54 @@ var (
|
||||
// tokens for kubectl to authenticate itself to the apiserver. A sample json config
|
||||
// is provided below with all recognized options described.
|
||||
//
|
||||
// {
|
||||
// 'auth-provider': {
|
||||
// # Required
|
||||
// "name": "gcp",
|
||||
// {
|
||||
// 'auth-provider': {
|
||||
// # Required
|
||||
// "name": "gcp",
|
||||
//
|
||||
// 'config': {
|
||||
// # Authentication options
|
||||
// # These options are used while getting a token.
|
||||
// 'config': {
|
||||
// # Authentication options
|
||||
// # These options are used while getting a token.
|
||||
//
|
||||
// # comma-separated list of GCP API scopes. default value of this field
|
||||
// # is "https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/userinfo.email".
|
||||
// # to override the API scopes, specify this field explicitly.
|
||||
// "scopes": "https://www.googleapis.com/auth/cloud-platform"
|
||||
// # comma-separated list of GCP API scopes. default value of this field
|
||||
// # is "https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/userinfo.email".
|
||||
// # to override the API scopes, specify this field explicitly.
|
||||
// "scopes": "https://www.googleapis.com/auth/cloud-platform"
|
||||
//
|
||||
// # Caching options
|
||||
// # Caching options
|
||||
//
|
||||
// # Raw string data representing cached access token.
|
||||
// "access-token": "ya29.CjWdA4GiBPTt",
|
||||
// # RFC3339Nano expiration timestamp for cached access token.
|
||||
// "expiry": "2016-10-31 22:31:9.123",
|
||||
// # Raw string data representing cached access token.
|
||||
// "access-token": "ya29.CjWdA4GiBPTt",
|
||||
// # RFC3339Nano expiration timestamp for cached access token.
|
||||
// "expiry": "2016-10-31 22:31:9.123",
|
||||
//
|
||||
// # Command execution options
|
||||
// # These options direct the plugin to execute a specified command and parse
|
||||
// # token and expiry time from the output of the command.
|
||||
// # Command execution options
|
||||
// # These options direct the plugin to execute a specified command and parse
|
||||
// # token and expiry time from the output of the command.
|
||||
//
|
||||
// # Command to execute for access token. Command output will be parsed as JSON.
|
||||
// # If "cmd-args" is not present, this value will be split on whitespace, with
|
||||
// # the first element interpreted as the command, remaining elements as args.
|
||||
// "cmd-path": "/usr/bin/gcloud",
|
||||
// # Command to execute for access token. Command output will be parsed as JSON.
|
||||
// # If "cmd-args" is not present, this value will be split on whitespace, with
|
||||
// # the first element interpreted as the command, remaining elements as args.
|
||||
// "cmd-path": "/usr/bin/gcloud",
|
||||
//
|
||||
// # Arguments to pass to command to execute for access token.
|
||||
// "cmd-args": "config config-helper --output=json"
|
||||
// # Arguments to pass to command to execute for access token.
|
||||
// "cmd-args": "config config-helper --output=json"
|
||||
//
|
||||
// # JSONPath to the string field that represents the access token in
|
||||
// # command output. If omitted, defaults to "{.access_token}".
|
||||
// "token-key": "{.credential.access_token}",
|
||||
// # JSONPath to the string field that represents the access token in
|
||||
// # command output. If omitted, defaults to "{.access_token}".
|
||||
// "token-key": "{.credential.access_token}",
|
||||
//
|
||||
// # JSONPath to the string field that represents expiration timestamp
|
||||
// # of the access token in the command output. If omitted, defaults to
|
||||
// # "{.token_expiry}"
|
||||
// "expiry-key": ""{.credential.token_expiry}",
|
||||
//
|
||||
// # golang reference time in the format that the expiration timestamp uses.
|
||||
// # If omitted, defaults to time.RFC3339Nano
|
||||
// "time-fmt": "2006-01-02 15:04:05.999999999"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// # JSONPath to the string field that represents expiration timestamp
|
||||
// # of the access token in the command output. If omitted, defaults to
|
||||
// # "{.token_expiry}"
|
||||
// "expiry-key": ""{.credential.token_expiry}",
|
||||
//
|
||||
// # golang reference time in the format that the expiration timestamp uses.
|
||||
// # If omitted, defaults to time.RFC3339Nano
|
||||
// "time-fmt": "2006-01-02 15:04:05.999999999"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
type gcpAuthProvider struct {
|
||||
tokenSource oauth2.TokenSource
|
||||
persister restclient.AuthProviderConfigPersister
|
||||
@@ -117,7 +116,7 @@ var warnOnce sync.Once
|
||||
|
||||
func newGCPAuthProvider(_ string, gcpConfig map[string]string, persister restclient.AuthProviderConfigPersister) (restclient.AuthProvider, error) {
|
||||
warnOnce.Do(func() {
|
||||
klog.Warningf(`WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.25+; use gcloud instead.
|
||||
klog.Warningf(`WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.26+; use gcloud instead.
|
||||
To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke`)
|
||||
})
|
||||
|
||||
|
||||
@@ -52,7 +52,8 @@ type Interface interface {
|
||||
// ClientContentConfig controls how RESTClient communicates with the server.
|
||||
//
|
||||
// TODO: ContentConfig will be updated to accept a Negotiator instead of a
|
||||
// NegotiatedSerializer and NegotiatedSerializer will be removed.
|
||||
//
|
||||
// NegotiatedSerializer and NegotiatedSerializer will be removed.
|
||||
type ClientContentConfig struct {
|
||||
// AcceptContentTypes specifies the types the client will accept and is optional.
|
||||
// If not set, ContentType will be used to define the Accept header
|
||||
@@ -159,13 +160,14 @@ func readExpBackoffConfig() BackoffManager {
|
||||
// c, err := NewRESTClient(...)
|
||||
// if err != nil { ... }
|
||||
// resp, err := c.Verb("GET").
|
||||
// Path("pods").
|
||||
// SelectorParam("labels", "area=staging").
|
||||
// Timeout(10*time.Second).
|
||||
// Do()
|
||||
//
|
||||
// Path("pods").
|
||||
// SelectorParam("labels", "area=staging").
|
||||
// Timeout(10*time.Second).
|
||||
// Do()
|
||||
//
|
||||
// if err != nil { ... }
|
||||
// list, ok := resp.(*api.PodList)
|
||||
//
|
||||
func (c *RESTClient) Verb(verb string) *Request {
|
||||
return NewRequest(c).Verb(verb)
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ func TestReconnectBrokenTCP(t *testing.T) {
|
||||
// 2. the connection has keepalive enabled so it will be reused
|
||||
// 3. break the TCP connection stopping the proxy
|
||||
// 4. close the idle connection to force creating a new connection
|
||||
// 5. count that there are 2 connection to the server (we didn't reuse the original connection)
|
||||
// 5. count that there are 2 connections to the server (we didn't reuse the original connection)
|
||||
func TestReconnectBrokenTCP_HTTP1(t *testing.T) {
|
||||
ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Hello, %s", r.Proto)
|
||||
@@ -245,7 +245,7 @@ func TestReconnectBrokenTCP_HTTP1(t *testing.T) {
|
||||
// 1. connect to https server with http1.1 using a TCP proxy making the connection to timeout
|
||||
// 2. the connection has keepalive enabled so it will be reused
|
||||
// 3. close the in-flight connection to force creating a new connection
|
||||
// 4. count that there are 2 connection on the LB but only one succeeds
|
||||
// 4. count that there are 2 connections on the LB but only one succeeds
|
||||
func TestReconnectBrokenTCPInFlight_HTTP1(t *testing.T) {
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"k8s.io/client-go/pkg/apis/clientauthentication"
|
||||
clientauthenticationapi "k8s.io/client-go/pkg/apis/clientauthentication"
|
||||
)
|
||||
|
||||
@@ -50,7 +49,7 @@ func ConfigToExecCluster(config *Config) (*clientauthenticationapi.Cluster, erro
|
||||
}
|
||||
}
|
||||
|
||||
return &clientauthentication.Cluster{
|
||||
return &clientauthenticationapi.Cluster{
|
||||
Server: config.Host,
|
||||
TLSServerName: config.ServerName,
|
||||
InsecureSkipTLSVerify: config.Insecure,
|
||||
@@ -63,7 +62,7 @@ func ConfigToExecCluster(config *Config) (*clientauthenticationapi.Cluster, erro
|
||||
// ExecClusterToConfig creates a Config with the corresponding fields from the provided
|
||||
// clientauthenticationapi.Cluster. The returned Config will be anonymous (i.e., it will not have
|
||||
// any authentication-related fields set).
|
||||
func ExecClusterToConfig(cluster *clientauthentication.Cluster) (*Config, error) {
|
||||
func ExecClusterToConfig(cluster *clientauthenticationapi.Cluster) (*Config, error) {
|
||||
var proxy func(*http.Request) (*url.URL, error)
|
||||
if cluster.ProxyURL != "" {
|
||||
proxyURL, err := url.Parse(cluster.ProxyURL)
|
||||
|
||||
@@ -28,7 +28,6 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
fuzz "github.com/google/gofuzz"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/pkg/apis/clientauthentication"
|
||||
clientauthenticationapi "k8s.io/client-go/pkg/apis/clientauthentication"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/client-go/transport"
|
||||
@@ -353,7 +352,7 @@ func TestExecClusterToConfigRoundtrip(t *testing.T) {
|
||||
},
|
||||
)
|
||||
for i := 0; i < 100; i++ {
|
||||
expected := &clientauthentication.Cluster{}
|
||||
expected := &clientauthenticationapi.Cluster{}
|
||||
f.Fuzz(expected)
|
||||
|
||||
// Manually set URLs so we don't get an error when parsing these during the roundtrip.
|
||||
|
||||
@@ -36,9 +36,10 @@ type AuthProvider interface {
|
||||
}
|
||||
|
||||
// Factory generates an AuthProvider plugin.
|
||||
// clusterAddress is the address of the current cluster.
|
||||
// config is the initial configuration for this plugin.
|
||||
// persister allows the plugin to save updated configuration.
|
||||
//
|
||||
// clusterAddress is the address of the current cluster.
|
||||
// config is the initial configuration for this plugin.
|
||||
// persister allows the plugin to save updated configuration.
|
||||
type Factory func(clusterAddress string, config map[string]string, persister AuthProviderConfigPersister) (AuthProvider, error)
|
||||
|
||||
// AuthProviderConfigPersister allows a plugin to persist configuration info
|
||||
|
||||
113
rest/request.go
113
rest/request.go
@@ -508,6 +508,87 @@ func (r *Request) URL() *url.URL {
|
||||
return finalURL
|
||||
}
|
||||
|
||||
// finalURLTemplate is similar to URL(), but will make all specific parameter values equal
|
||||
// - instead of name or namespace, "{name}" and "{namespace}" will be used, and all query
|
||||
// parameters will be reset. This creates a copy of the url so as not to change the
|
||||
// underlying object.
|
||||
func (r Request) finalURLTemplate() url.URL {
|
||||
newParams := url.Values{}
|
||||
v := []string{"{value}"}
|
||||
for k := range r.params {
|
||||
newParams[k] = v
|
||||
}
|
||||
r.params = newParams
|
||||
u := r.URL()
|
||||
if u == nil {
|
||||
return url.URL{}
|
||||
}
|
||||
|
||||
segments := strings.Split(u.Path, "/")
|
||||
groupIndex := 0
|
||||
index := 0
|
||||
trimmedBasePath := ""
|
||||
if r.c.base != nil && strings.Contains(u.Path, r.c.base.Path) {
|
||||
p := strings.TrimPrefix(u.Path, r.c.base.Path)
|
||||
if !strings.HasPrefix(p, "/") {
|
||||
p = "/" + p
|
||||
}
|
||||
// store the base path that we have trimmed so we can append it
|
||||
// before returning the URL
|
||||
trimmedBasePath = r.c.base.Path
|
||||
segments = strings.Split(p, "/")
|
||||
groupIndex = 1
|
||||
}
|
||||
if len(segments) <= 2 {
|
||||
return *u
|
||||
}
|
||||
|
||||
const CoreGroupPrefix = "api"
|
||||
const NamedGroupPrefix = "apis"
|
||||
isCoreGroup := segments[groupIndex] == CoreGroupPrefix
|
||||
isNamedGroup := segments[groupIndex] == NamedGroupPrefix
|
||||
if isCoreGroup {
|
||||
// checking the case of core group with /api/v1/... format
|
||||
index = groupIndex + 2
|
||||
} else if isNamedGroup {
|
||||
// checking the case of named group with /apis/apps/v1/... format
|
||||
index = groupIndex + 3
|
||||
} else {
|
||||
// this should not happen that the only two possibilities are /api... and /apis..., just want to put an
|
||||
// outlet here in case more API groups are added in future if ever possible:
|
||||
// https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-groups
|
||||
// if a wrong API groups name is encountered, return the {prefix} for url.Path
|
||||
u.Path = "/{prefix}"
|
||||
u.RawQuery = ""
|
||||
return *u
|
||||
}
|
||||
// switch segLength := len(segments) - index; segLength {
|
||||
switch {
|
||||
// case len(segments) - index == 1:
|
||||
// resource (with no name) do nothing
|
||||
case len(segments)-index == 2:
|
||||
// /$RESOURCE/$NAME: replace $NAME with {name}
|
||||
segments[index+1] = "{name}"
|
||||
case len(segments)-index == 3:
|
||||
if segments[index+2] == "finalize" || segments[index+2] == "status" {
|
||||
// /$RESOURCE/$NAME/$SUBRESOURCE: replace $NAME with {name}
|
||||
segments[index+1] = "{name}"
|
||||
} else {
|
||||
// /namespace/$NAMESPACE/$RESOURCE: replace $NAMESPACE with {namespace}
|
||||
segments[index+1] = "{namespace}"
|
||||
}
|
||||
case len(segments)-index >= 4:
|
||||
segments[index+1] = "{namespace}"
|
||||
// /namespace/$NAMESPACE/$RESOURCE/$NAME: replace $NAMESPACE with {namespace}, $NAME with {name}
|
||||
if segments[index+3] != "finalize" && segments[index+3] != "status" {
|
||||
// /$RESOURCE/$NAME/$SUBRESOURCE: replace $NAME with {name}
|
||||
segments[index+3] = "{name}"
|
||||
}
|
||||
}
|
||||
u.Path = path.Join(trimmedBasePath, path.Join(segments...))
|
||||
return *u
|
||||
}
|
||||
|
||||
func (r *Request) tryThrottleWithInfo(ctx context.Context, retryInfo string) error {
|
||||
if r.rateLimiter == nil {
|
||||
return nil
|
||||
@@ -537,7 +618,7 @@ func (r *Request) tryThrottleWithInfo(ctx context.Context, retryInfo string) err
|
||||
// but we use a throttled logger to prevent spamming.
|
||||
globalThrottledLogger.Infof("%s", message)
|
||||
}
|
||||
metrics.RateLimiterLatency.Observe(ctx, r.verb, *r.URL(), latency)
|
||||
metrics.RateLimiterLatency.Observe(ctx, r.verb, r.finalURLTemplate(), latency)
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -710,7 +791,7 @@ func updateURLMetrics(ctx context.Context, req *Request, resp *http.Response, er
|
||||
if err != nil {
|
||||
metrics.RequestResult.Increment(ctx, "<error>", req.verb, url)
|
||||
} else {
|
||||
//Metrics for failure codes
|
||||
// Metrics for failure codes
|
||||
metrics.RequestResult.Increment(ctx, strconv.Itoa(resp.StatusCode), req.verb, url)
|
||||
}
|
||||
}
|
||||
@@ -823,10 +904,10 @@ func (r *Request) newHTTPRequest(ctx context.Context) (*http.Request, error) {
|
||||
// fn at most once. It will return an error if a problem occurred prior to connecting to the
|
||||
// server - the provided function is responsible for handling server errors.
|
||||
func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Response)) error {
|
||||
//Metrics for total request latency
|
||||
// Metrics for total request latency
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
metrics.RequestLatency.Observe(ctx, r.verb, *r.URL(), time.Since(start))
|
||||
metrics.RequestLatency.Observe(ctx, r.verb, r.finalURLTemplate(), time.Since(start))
|
||||
}()
|
||||
|
||||
if r.err != nil {
|
||||
@@ -892,7 +973,7 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp
|
||||
done := func() bool {
|
||||
defer readAndCloseResponseBody(resp)
|
||||
|
||||
// if the the server returns an error in err, the response will be nil.
|
||||
// if the server returns an error in err, the response will be nil.
|
||||
f := func(req *http.Request, resp *http.Response) {
|
||||
if resp == nil {
|
||||
return
|
||||
@@ -917,8 +998,8 @@ func (r *Request) request(ctx context.Context, fn func(*http.Request, *http.Resp
|
||||
// processing.
|
||||
//
|
||||
// Error type:
|
||||
// * If the server responds with a status: *errors.StatusError or *errors.UnexpectedObjectError
|
||||
// * http.Client.Do errors are returned directly.
|
||||
// - If the server responds with a status: *errors.StatusError or *errors.UnexpectedObjectError
|
||||
// - http.Client.Do errors are returned directly.
|
||||
func (r *Request) Do(ctx context.Context) Result {
|
||||
var result Result
|
||||
err := r.request(ctx, func(req *http.Request, resp *http.Response) {
|
||||
@@ -1085,15 +1166,15 @@ const maxUnstructuredResponseTextBytes = 2048
|
||||
// unexpected responses. The rough structure is:
|
||||
//
|
||||
// 1. Assume the server sends you something sane - JSON + well defined error objects + proper codes
|
||||
// - this is the happy path
|
||||
// - when you get this output, trust what the server sends
|
||||
// 2. Guard against empty fields / bodies in received JSON and attempt to cull sufficient info from them to
|
||||
// generate a reasonable facsimile of the original failure.
|
||||
// - Be sure to use a distinct error type or flag that allows a client to distinguish between this and error 1 above
|
||||
// 3. Handle true disconnect failures / completely malformed data by moving up to a more generic client error
|
||||
// 4. Distinguish between various connection failures like SSL certificates, timeouts, proxy errors, unexpected
|
||||
// initial contact, the presence of mismatched body contents from posted content types
|
||||
// - Give these a separate distinct error type and capture as much as possible of the original message
|
||||
// - this is the happy path
|
||||
// - when you get this output, trust what the server sends
|
||||
// 2. Guard against empty fields / bodies in received JSON and attempt to cull sufficient info from them to
|
||||
// generate a reasonable facsimile of the original failure.
|
||||
// - Be sure to use a distinct error type or flag that allows a client to distinguish between this and error 1 above
|
||||
// 3. Handle true disconnect failures / completely malformed data by moving up to a more generic client error
|
||||
// 4. Distinguish between various connection failures like SSL certificates, timeouts, proxy errors, unexpected
|
||||
// initial contact, the presence of mismatched body contents from posted content types
|
||||
// - Give these a separate distinct error type and capture as much as possible of the original message
|
||||
//
|
||||
// TODO: introduce transformation of generic http.Client.Do() errors that separates 4.
|
||||
func (r *Request) transformUnstructuredResponseError(resp *http.Response, req *http.Request, body []byte) error {
|
||||
|
||||
@@ -338,6 +338,206 @@ func TestResultIntoWithNoBodyReturnsErr(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestURLTemplate(t *testing.T) {
|
||||
uri, _ := url.Parse("http://localhost/some/base/url/path")
|
||||
uriSingleSlash, _ := url.Parse("http://localhost/")
|
||||
testCases := []struct {
|
||||
Request *Request
|
||||
ExpectedFullURL string
|
||||
ExpectedFinalURL string
|
||||
}{
|
||||
{
|
||||
// non dynamic client
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("POST").
|
||||
Prefix("api", "v1").Resource("r1").Namespace("ns").Name("nm").Param("p0", "v0"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/api/v1/namespaces/ns/r1/nm?p0=v0",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/api/v1/namespaces/%7Bnamespace%7D/r1/%7Bname%7D?p0=%7Bvalue%7D",
|
||||
},
|
||||
{
|
||||
// non dynamic client with wrong api group
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("POST").
|
||||
Prefix("pre1", "v1").Resource("r1").Namespace("ns").Name("nm").Param("p0", "v0"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/pre1/v1/namespaces/ns/r1/nm?p0=v0",
|
||||
ExpectedFinalURL: "http://localhost/%7Bprefix%7D",
|
||||
},
|
||||
{
|
||||
// dynamic client with core group + namespace + resourceResource (with name)
|
||||
// /api/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/api/v1/namespaces/ns/r1/name1"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/api/v1/namespaces/ns/r1/name1",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/api/v1/namespaces/%7Bnamespace%7D/r1/%7Bname%7D",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + namespace + resourceResource (with name)
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/g1/v1/namespaces/ns/r1/name1"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/g1/v1/namespaces/ns/r1/name1",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/g1/v1/namespaces/%7Bnamespace%7D/r1/%7Bname%7D",
|
||||
},
|
||||
{
|
||||
// dynamic client with core group + namespace + resourceResource (with NO name)
|
||||
// /api/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/api/v1/namespaces/ns/r1"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/api/v1/namespaces/ns/r1",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/api/v1/namespaces/%7Bnamespace%7D/r1",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + namespace + resourceResource (with NO name)
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/g1/v1/namespaces/ns/r1"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/g1/v1/namespaces/ns/r1",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/g1/v1/namespaces/%7Bnamespace%7D/r1",
|
||||
},
|
||||
{
|
||||
// dynamic client with core group + resourceResource (with name)
|
||||
// /api/$RESOURCEVERSION/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/api/v1/r1/name1"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/api/v1/r1/name1",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/api/v1/r1/%7Bname%7D",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + resourceResource (with name)
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/g1/v1/r1/name1"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/g1/v1/r1/name1",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/g1/v1/r1/%7Bname%7D",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + namespace + resourceResource (with name) + subresource
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME/$SUBRESOURCE
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces/finalize"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces/finalize",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bnamespace%7D/namespaces/%7Bname%7D/finalize",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + namespace + resourceResource (with name)
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bnamespace%7D/namespaces/%7Bname%7D",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + namespace + resourceResource (with NO name) + subresource
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%SUBRESOURCE
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/namespaces/finalize"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/namespaces/finalize",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bnamespace%7D/namespaces/finalize",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + namespace + resourceResource (with NO name) + subresource
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%SUBRESOURCE
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/namespaces/status"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/namespaces/status",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bnamespace%7D/namespaces/status",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + namespace + resourceResource (with no name)
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/namespaces"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/namespaces",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bnamespace%7D/namespaces",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + resourceResource (with name) + subresource
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/finalize"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/finalize",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bname%7D/finalize",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + resourceResource (with name) + subresource
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/status"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/status",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bname%7D/status",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + resourceResource (with name)
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/namespaces/namespaces/namespaces/namespaces"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bname%7D",
|
||||
},
|
||||
{
|
||||
// dynamic client with named group + resourceResource (with no name)
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/apis/namespaces/namespaces/namespaces"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces",
|
||||
},
|
||||
{
|
||||
// dynamic client with wrong api group + namespace + resourceResource (with name) + subresource
|
||||
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME/$SUBRESOURCE
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/pre1/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces/finalize"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/pre1/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces/finalize",
|
||||
ExpectedFinalURL: "http://localhost/%7Bprefix%7D",
|
||||
},
|
||||
{
|
||||
// dynamic client with core group + namespace + resourceResource (with name) where baseURL is a single /
|
||||
// /api/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uriSingleSlash, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/api/v1/namespaces/ns/r2/name1"),
|
||||
ExpectedFullURL: "http://localhost/api/v1/namespaces/ns/r2/name1",
|
||||
ExpectedFinalURL: "http://localhost/api/v1/namespaces/%7Bnamespace%7D/r2/%7Bname%7D",
|
||||
},
|
||||
{
|
||||
// dynamic client with core group + namespace + resourceResource (with name) where baseURL is 'some/base/url/path'
|
||||
// /api/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
|
||||
Request: NewRequestWithClient(uri, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/api/v1/namespaces/ns/r3/name1"),
|
||||
ExpectedFullURL: "http://localhost/some/base/url/path/api/v1/namespaces/ns/r3/name1",
|
||||
ExpectedFinalURL: "http://localhost/some/base/url/path/api/v1/namespaces/%7Bnamespace%7D/r3/%7Bname%7D",
|
||||
},
|
||||
{
|
||||
// dynamic client where baseURL is a single /
|
||||
// /
|
||||
Request: NewRequestWithClient(uriSingleSlash, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/"),
|
||||
ExpectedFullURL: "http://localhost/",
|
||||
ExpectedFinalURL: "http://localhost/",
|
||||
},
|
||||
{
|
||||
// dynamic client where baseURL is a single /
|
||||
// /version
|
||||
Request: NewRequestWithClient(uriSingleSlash, "", ClientContentConfig{GroupVersion: schema.GroupVersion{Group: "test"}}, nil).Verb("DELETE").
|
||||
Prefix("/version"),
|
||||
ExpectedFullURL: "http://localhost/version",
|
||||
ExpectedFinalURL: "http://localhost/version",
|
||||
},
|
||||
}
|
||||
for i, testCase := range testCases {
|
||||
r := testCase.Request
|
||||
full := r.URL()
|
||||
if full.String() != testCase.ExpectedFullURL {
|
||||
t.Errorf("%d: unexpected initial URL: %s %s", i, full, testCase.ExpectedFullURL)
|
||||
}
|
||||
actualURL := r.finalURLTemplate()
|
||||
actual := actualURL.String()
|
||||
if actual != testCase.ExpectedFinalURL {
|
||||
t.Errorf("%d: unexpected URL template: %s %s", i, actual, testCase.ExpectedFinalURL)
|
||||
}
|
||||
if r.URL().String() != full.String() {
|
||||
t.Errorf("%d, creating URL template changed request: %s -> %s", i, full.String(), r.URL().String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTransformResponse(t *testing.T) {
|
||||
invalid := []byte("aaaaa")
|
||||
uri, _ := url.Parse("http://localhost")
|
||||
@@ -1392,7 +1592,9 @@ func TestCheckRetryClosesBody(t *testing.T) {
|
||||
defer testServer.Close()
|
||||
|
||||
backoff := &testBackoffManager{}
|
||||
expectedSleeps := []time.Duration{0, time.Second, 0, time.Second, 0, time.Second, 0, time.Second, 0}
|
||||
|
||||
// testBackoffManager.CalculateBackoff always returns 0
|
||||
expectedSleeps := []time.Duration{0, time.Second, time.Second, time.Second, time.Second}
|
||||
|
||||
c := testRESTClient(t, testServer)
|
||||
c.createBackoffMgr = func() BackoffManager { return backoff }
|
||||
@@ -1440,10 +1642,12 @@ func TestConnectionResetByPeerIsRetried(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
// We have a sleep before each retry (including the initial one) and for
|
||||
// every "retry-after" call - thus 5 together.
|
||||
if len(backoff.sleeps) != 5 {
|
||||
t.Errorf("Expected 5 retries, got: %d", len(backoff.sleeps))
|
||||
if count != 3 {
|
||||
t.Errorf("Expected 3 attempts, got: %d", count)
|
||||
}
|
||||
// We have a sleep before each retry (including the initial one) thus 3 together.
|
||||
if len(backoff.sleeps) != 3 {
|
||||
t.Errorf("Expected 3 backoff.Sleep, got: %d", len(backoff.sleeps))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2560,7 +2764,7 @@ func TestRequestWatchWithRetry(t *testing.T) {
|
||||
testRequestWithRetry(t, "Watch", func(ctx context.Context, r *Request) {
|
||||
w, err := r.Watch(ctx)
|
||||
if err == nil {
|
||||
// in this test the the response body returned by the server is always empty,
|
||||
// in this test the response body returned by the server is always empty,
|
||||
// this will cause StreamWatcher.receive() to:
|
||||
// - return an io.EOF to indicate that the watch closed normally and
|
||||
// - then close the io.Reader
|
||||
@@ -2588,7 +2792,7 @@ func TestRequestWatchRetryWithRateLimiterBackoffAndMetrics(t *testing.T) {
|
||||
testRetryWithRateLimiterBackoffAndMetrics(t, "Watch", func(ctx context.Context, r *Request) {
|
||||
w, err := r.Watch(ctx)
|
||||
if err == nil {
|
||||
// in this test the the response body returned by the server is always empty,
|
||||
// in this test the response body returned by the server is always empty,
|
||||
// this will cause StreamWatcher.receive() to:
|
||||
// - return an io.EOF to indicate that the watch closed normally and
|
||||
// - then close the io.Reader
|
||||
@@ -2616,7 +2820,7 @@ func TestRequestWatchWithRetryInvokeOrder(t *testing.T) {
|
||||
testWithRetryInvokeOrder(t, "Watch", func(ctx context.Context, r *Request) {
|
||||
w, err := r.Watch(ctx)
|
||||
if err == nil {
|
||||
// in this test the the response body returned by the server is always empty,
|
||||
// in this test the response body returned by the server is always empty,
|
||||
// this will cause StreamWatcher.receive() to:
|
||||
// - return an io.EOF to indicate that the watch closed normally and
|
||||
// - then close the io.Reader
|
||||
@@ -2631,7 +2835,7 @@ func TestRequestWatchWithWrapPreviousError(t *testing.T) {
|
||||
testWithWrapPreviousError(t, func(ctx context.Context, r *Request) error {
|
||||
w, err := r.Watch(ctx)
|
||||
if err == nil {
|
||||
// in this test the the response body returned by the server is always empty,
|
||||
// in this test the response body returned by the server is always empty,
|
||||
// this will cause StreamWatcher.receive() to:
|
||||
// - return an io.EOF to indicate that the watch closed normally and
|
||||
// - then close the io.Reader
|
||||
@@ -2824,7 +3028,8 @@ type withRateLimiterBackoffManagerAndMetrics struct {
|
||||
flowcontrol.RateLimiter
|
||||
*NoBackoff
|
||||
metrics.ResultMetric
|
||||
backoffWaitSeconds int
|
||||
calculateBackoffSeq int64
|
||||
calculateBackoffFn func(i int64) time.Duration
|
||||
|
||||
invokeOrderGot []string
|
||||
sleepsGot []string
|
||||
@@ -2839,9 +3044,8 @@ func (lb *withRateLimiterBackoffManagerAndMetrics) Wait(ctx context.Context) err
|
||||
func (lb *withRateLimiterBackoffManagerAndMetrics) CalculateBackoff(actualUrl *url.URL) time.Duration {
|
||||
lb.invokeOrderGot = append(lb.invokeOrderGot, "BackoffManager.CalculateBackoff")
|
||||
|
||||
// we simulate a sleep sequence of 0m, 2m, 4m, 6m, ...
|
||||
waitFor := time.Duration(lb.backoffWaitSeconds) * time.Minute
|
||||
lb.backoffWaitSeconds += 2
|
||||
waitFor := lb.calculateBackoffFn(lb.calculateBackoffSeq)
|
||||
lb.calculateBackoffSeq++
|
||||
return waitFor
|
||||
}
|
||||
|
||||
@@ -2868,14 +3072,16 @@ func (lb *withRateLimiterBackoffManagerAndMetrics) Do() {
|
||||
|
||||
func testRetryWithRateLimiterBackoffAndMetrics(t *testing.T, key string, doFunc func(ctx context.Context, r *Request)) {
|
||||
type expected struct {
|
||||
attempts int
|
||||
order []string
|
||||
attempts int
|
||||
order []string
|
||||
sleeps []string
|
||||
statusCodes []string
|
||||
}
|
||||
|
||||
// we define the expected order of how the client invokes the
|
||||
// rate limiter, backoff, and metrics methods.
|
||||
// scenario:
|
||||
// - A: original request fails with a retryable response: (500, 'Retry-After: 1')
|
||||
// - A: original request fails with a retryable response: (500, 'Retry-After: N')
|
||||
// - B: retry 1: successful with a status code 200
|
||||
// so we have a total of 2 attempts
|
||||
invokeOrderWant := []string{
|
||||
@@ -2887,17 +3093,16 @@ func testRetryWithRateLimiterBackoffAndMetrics(t *testing.T, key string, doFunc
|
||||
"BackoffManager.Sleep",
|
||||
|
||||
// A: first attempt for which the server sends a retryable response
|
||||
// status code: 500, Retry-Afer: N
|
||||
"Client.Do",
|
||||
|
||||
// we got a response object, status code: 500, Retry-Afer: 1
|
||||
// we got a response object, status code: 500, Retry-Afer: N
|
||||
// - call metrics method with appropriate status code
|
||||
// - update backoff parameters with the status code returned
|
||||
// - sleep for N seconds from 'Retry-After: N' response header
|
||||
"RequestResult.Increment",
|
||||
"BackoffManager.UpdateBackoff",
|
||||
"BackoffManager.Sleep",
|
||||
// sleep for delay dictated by backoff parameters
|
||||
"BackoffManager.CalculateBackoff",
|
||||
// sleep for delay=max(BackoffManager.CalculateBackoff, Retry-After: N)
|
||||
"BackoffManager.Sleep",
|
||||
// wait as dictated by the client rate lmiter
|
||||
"RateLimiter.Wait",
|
||||
@@ -2910,46 +3115,104 @@ func testRetryWithRateLimiterBackoffAndMetrics(t *testing.T, key string, doFunc
|
||||
"RequestResult.Increment",
|
||||
"BackoffManager.UpdateBackoff",
|
||||
}
|
||||
sleepWant := []string{
|
||||
// initial backoff.Sleep before we send the request to the server for the first time
|
||||
"0s",
|
||||
// from 'Retry-After: 1' response header (A)
|
||||
(1 * time.Second).String(),
|
||||
// backoff.Sleep before retry 1 (B)
|
||||
(2 * time.Minute).String(),
|
||||
}
|
||||
statusCodesWant := []string{
|
||||
"500",
|
||||
"200",
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
maxRetries int
|
||||
serverReturns []responseErr
|
||||
name string
|
||||
maxRetries int
|
||||
serverReturns []responseErr
|
||||
calculateBackoffFn func(i int64) time.Duration
|
||||
// expectations differ based on whether it is 'Watch', 'Stream' or 'Do'
|
||||
expectations map[string]expected
|
||||
}{
|
||||
{
|
||||
name: "success after one retry",
|
||||
name: "success after one retry, Retry-After: N > BackoffManager.CalculateBackoff",
|
||||
maxRetries: 1,
|
||||
serverReturns: []responseErr{
|
||||
{response: retryAfterResponse(), err: nil},
|
||||
{response: retryAfterResponseWithDelay("5"), err: nil},
|
||||
{response: &http.Response{StatusCode: http.StatusOK}, err: nil},
|
||||
},
|
||||
// we simulate a sleep sequence of 0s, 1s, 2s, 3s, ...
|
||||
calculateBackoffFn: func(i int64) time.Duration { return time.Duration(i * int64(time.Second)) },
|
||||
expectations: map[string]expected{
|
||||
"Do": {
|
||||
attempts: 2,
|
||||
order: invokeOrderWant,
|
||||
attempts: 2,
|
||||
order: invokeOrderWant,
|
||||
statusCodes: statusCodesWant,
|
||||
sleeps: []string{
|
||||
// initial backoff.Sleep before we send the request to the server for the first time
|
||||
"0s",
|
||||
// maximum of:
|
||||
// - 'Retry-After: 5' response header from (A)
|
||||
// - BackoffManager.CalculateBackoff (will return 1s)
|
||||
(5 * time.Second).String(),
|
||||
},
|
||||
},
|
||||
"Watch": {
|
||||
attempts: 2,
|
||||
// Watch does not do 'RateLimiter.Wait' before initially sending the request to the server
|
||||
order: invokeOrderWant[1:],
|
||||
order: invokeOrderWant[1:],
|
||||
statusCodes: statusCodesWant,
|
||||
sleeps: []string{
|
||||
"0s",
|
||||
(5 * time.Second).String(),
|
||||
},
|
||||
},
|
||||
"Stream": {
|
||||
attempts: 2,
|
||||
order: invokeOrderWant,
|
||||
statusCodes: statusCodesWant,
|
||||
sleeps: []string{
|
||||
"0s",
|
||||
(5 * time.Second).String(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "success after one retry, Retry-After: N < BackoffManager.CalculateBackoff",
|
||||
maxRetries: 1,
|
||||
serverReturns: []responseErr{
|
||||
{response: retryAfterResponseWithDelay("2"), err: nil},
|
||||
{response: &http.Response{StatusCode: http.StatusOK}, err: nil},
|
||||
},
|
||||
// we simulate a sleep sequence of 0s, 4s, 8s, 16s, ...
|
||||
calculateBackoffFn: func(i int64) time.Duration { return time.Duration(i * int64(4*time.Second)) },
|
||||
expectations: map[string]expected{
|
||||
"Do": {
|
||||
attempts: 2,
|
||||
order: invokeOrderWant,
|
||||
statusCodes: statusCodesWant,
|
||||
sleeps: []string{
|
||||
// initial backoff.Sleep before we send the request to the server for the first time
|
||||
"0s",
|
||||
// maximum of:
|
||||
// - 'Retry-After: 2' response header from (A)
|
||||
// - BackoffManager.CalculateBackoff (will return 4s)
|
||||
(4 * time.Second).String(),
|
||||
},
|
||||
},
|
||||
"Watch": {
|
||||
attempts: 2,
|
||||
order: invokeOrderWant,
|
||||
// Watch does not do 'RateLimiter.Wait' before initially sending the request to the server
|
||||
order: invokeOrderWant[1:],
|
||||
statusCodes: statusCodesWant,
|
||||
sleeps: []string{
|
||||
"0s",
|
||||
(4 * time.Second).String(),
|
||||
},
|
||||
},
|
||||
"Stream": {
|
||||
attempts: 2,
|
||||
order: invokeOrderWant,
|
||||
statusCodes: statusCodesWant,
|
||||
sleeps: []string{
|
||||
"0s",
|
||||
(4 * time.Second).String(),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2958,8 +3221,9 @@ func testRetryWithRateLimiterBackoffAndMetrics(t *testing.T, key string, doFunc
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
interceptor := &withRateLimiterBackoffManagerAndMetrics{
|
||||
RateLimiter: flowcontrol.NewFakeAlwaysRateLimiter(),
|
||||
NoBackoff: &NoBackoff{},
|
||||
RateLimiter: flowcontrol.NewFakeAlwaysRateLimiter(),
|
||||
NoBackoff: &NoBackoff{},
|
||||
calculateBackoffFn: test.calculateBackoffFn,
|
||||
}
|
||||
|
||||
// TODO: today this is the only site where a test overrides the
|
||||
@@ -3027,11 +3291,11 @@ func testRetryWithRateLimiterBackoffAndMetrics(t *testing.T, key string, doFunc
|
||||
if !cmp.Equal(want.order, interceptor.invokeOrderGot) {
|
||||
t.Errorf("%s: Expected invoke order to match, diff: %s", key, cmp.Diff(want.order, interceptor.invokeOrderGot))
|
||||
}
|
||||
if !cmp.Equal(sleepWant, interceptor.sleepsGot) {
|
||||
t.Errorf("%s: Expected sleep sequence to match, diff: %s", key, cmp.Diff(sleepWant, interceptor.sleepsGot))
|
||||
if !cmp.Equal(want.sleeps, interceptor.sleepsGot) {
|
||||
t.Errorf("%s: Expected sleep sequence to match, diff: %s", key, cmp.Diff(want.sleeps, interceptor.sleepsGot))
|
||||
}
|
||||
if !cmp.Equal(statusCodesWant, interceptor.statusCodesGot) {
|
||||
t.Errorf("%s: Expected status codes to match, diff: %s", key, cmp.Diff(statusCodesWant, interceptor.statusCodesGot))
|
||||
if !cmp.Equal(want.statusCodes, interceptor.statusCodesGot) {
|
||||
t.Errorf("%s: Expected status codes to match, diff: %s", key, cmp.Diff(want.statusCodes, interceptor.statusCodesGot))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -40,9 +40,9 @@ var (
|
||||
|
||||
// SetDefaultWarningHandler sets the default handler clients use when warning headers are encountered.
|
||||
// By default, warnings are logged. Several built-in implementations are provided:
|
||||
// - NoWarnings suppresses warnings.
|
||||
// - WarningLogger logs warnings.
|
||||
// - NewWarningWriter() outputs warnings to the provided writer.
|
||||
// - NoWarnings suppresses warnings.
|
||||
// - WarningLogger logs warnings.
|
||||
// - NewWarningWriter() outputs warnings to the provided writer.
|
||||
func SetDefaultWarningHandler(l WarningHandler) {
|
||||
defaultWarningHandlerLock.Lock()
|
||||
defer defaultWarningHandlerLock.Unlock()
|
||||
|
||||
@@ -204,7 +204,9 @@ func (r *withRetry) Before(ctx context.Context, request *Request) error {
|
||||
if r.retryAfter == nil {
|
||||
// we do a backoff sleep before the first attempt is made,
|
||||
// (preserving current behavior).
|
||||
request.backoff.Sleep(request.backoff.CalculateBackoff(url))
|
||||
if request.backoff != nil {
|
||||
request.backoff.Sleep(request.backoff.CalculateBackoff(url))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -220,14 +222,13 @@ func (r *withRetry) Before(ctx context.Context, request *Request) error {
|
||||
}
|
||||
}
|
||||
|
||||
// if we are here, we have made attempt(s) al least once before.
|
||||
// if we are here, we have made attempt(s) at least once before.
|
||||
if request.backoff != nil {
|
||||
// TODO(tkashem) with default set to use exponential backoff
|
||||
// we can merge these two sleeps:
|
||||
// BackOffManager.Sleep(max(backoffManager.CalculateBackoff(), retryAfter))
|
||||
// see https://github.com/kubernetes/kubernetes/issues/108302
|
||||
request.backoff.Sleep(r.retryAfter.Wait)
|
||||
request.backoff.Sleep(request.backoff.CalculateBackoff(url))
|
||||
delay := request.backoff.CalculateBackoff(url)
|
||||
if r.retryAfter.Wait > delay {
|
||||
delay = r.retryAfter.Wait
|
||||
}
|
||||
request.backoff.Sleep(delay)
|
||||
}
|
||||
|
||||
// We are retrying the request that we already send to
|
||||
@@ -349,8 +350,12 @@ func readAndCloseResponseBody(resp *http.Response) {
|
||||
}
|
||||
|
||||
func retryAfterResponse() *http.Response {
|
||||
return retryAfterResponseWithDelay("1")
|
||||
}
|
||||
|
||||
func retryAfterResponseWithDelay(delay string) *http.Response {
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusInternalServerError,
|
||||
Header: http.Header{"Retry-After": []string{"1"}},
|
||||
Header: http.Header{"Retry-After": []string{delay}},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,18 @@ func NewShortcutExpander(delegate meta.RESTMapper, client discovery.DiscoveryInt
|
||||
|
||||
// KindFor fulfills meta.RESTMapper
|
||||
func (e shortcutExpander) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
|
||||
return e.RESTMapper.KindFor(e.expandResourceShortcut(resource))
|
||||
// expandResourceShortcut works with current API resources as read from discovery cache.
|
||||
// In case of new CRDs this means we potentially don't have current state of discovery.
|
||||
// In the current wiring in k8s.io/cli-runtime/pkg/genericclioptions/config_flags.go#toRESTMapper,
|
||||
// we are using DeferredDiscoveryRESTMapper which on KindFor failure will clear the
|
||||
// cache and fetch all data from a cluster (see vendor/k8s.io/client-go/restmapper/discovery.go#KindFor).
|
||||
// Thus another call to expandResourceShortcut, after a NoMatchError should successfully
|
||||
// read Kind to the user or an error.
|
||||
gvk, err := e.RESTMapper.KindFor(e.expandResourceShortcut(resource))
|
||||
if meta.IsNoMatchError(err) {
|
||||
return e.RESTMapper.KindFor(e.expandResourceShortcut(resource))
|
||||
}
|
||||
return gvk, err
|
||||
}
|
||||
|
||||
// KindsFor fulfills meta.RESTMapper
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"testing"
|
||||
|
||||
openapi_v2 "github.com/google/gnostic/openapiv2"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
@@ -195,6 +196,65 @@ func TestKindFor(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestKindForWithNewCRDs(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
in schema.GroupVersionResource
|
||||
expected schema.GroupVersionKind
|
||||
srvRes []*metav1.APIResourceList
|
||||
}{
|
||||
"": {
|
||||
in: schema.GroupVersionResource{Group: "a", Version: "", Resource: "sc"},
|
||||
expected: schema.GroupVersionKind{Group: "a", Version: "v1", Kind: "StorageClass"},
|
||||
srvRes: []*metav1.APIResourceList{
|
||||
{
|
||||
GroupVersion: "a/v1",
|
||||
APIResources: []metav1.APIResource{
|
||||
{
|
||||
Name: "storageclasses",
|
||||
ShortNames: []string{"sc"},
|
||||
Kind: "StorageClass",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
invalidateCalled := false
|
||||
fakeDiscovery := &fakeDiscoveryClient{}
|
||||
fakeDiscovery.serverResourcesHandler = func() ([]*metav1.APIResourceList, error) {
|
||||
if invalidateCalled {
|
||||
return test.srvRes, nil
|
||||
}
|
||||
return []*metav1.APIResourceList{}, nil
|
||||
}
|
||||
fakeCachedDiscovery := &fakeCachedDiscoveryClient{DiscoveryInterface: fakeDiscovery}
|
||||
fakeCachedDiscovery.invalidateHandler = func() {
|
||||
invalidateCalled = true
|
||||
}
|
||||
fakeCachedDiscovery.freshHandler = func() bool {
|
||||
return invalidateCalled
|
||||
}
|
||||
|
||||
// in real world the discovery client is fronted with a cache which
|
||||
// will answer the initial request, only failure to match will trigger
|
||||
// the cache invalidation and live discovery call
|
||||
delegate := NewDeferredDiscoveryRESTMapper(fakeCachedDiscovery)
|
||||
mapper := NewShortcutExpander(delegate, fakeCachedDiscovery)
|
||||
|
||||
gvk, err := mapper.KindFor(test.in)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if diff := cmp.Equal(gvk, test.expected); !diff {
|
||||
t.Errorf("unexpected data returned %#v, expected %#v", gvk, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type fakeRESTMapper struct {
|
||||
kindForInput schema.GroupVersionResource
|
||||
}
|
||||
@@ -301,3 +361,24 @@ func (c *fakeDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) {
|
||||
func (c *fakeDiscoveryClient) OpenAPIV3() openapi.Client {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
type fakeCachedDiscoveryClient struct {
|
||||
discovery.DiscoveryInterface
|
||||
freshHandler func() bool
|
||||
invalidateHandler func()
|
||||
}
|
||||
|
||||
var _ discovery.CachedDiscoveryInterface = &fakeCachedDiscoveryClient{}
|
||||
|
||||
func (c *fakeCachedDiscoveryClient) Fresh() bool {
|
||||
if c.freshHandler != nil {
|
||||
return c.freshHandler()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *fakeCachedDiscoveryClient) Invalidate() {
|
||||
if c.invalidateHandler != nil {
|
||||
c.invalidateHandler()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,10 +102,20 @@ func ObjectReaction(tracker ObjectTracker) ReactionFunc {
|
||||
if action.GetSubresource() == "" {
|
||||
err = tracker.Create(gvr, action.GetObject(), ns)
|
||||
} else {
|
||||
// TODO: Currently we're handling subresource creation as an update
|
||||
// on the enclosing resource. This works for some subresources but
|
||||
// might not be generic enough.
|
||||
err = tracker.Update(gvr, action.GetObject(), ns)
|
||||
oldObj, getOldObjErr := tracker.Get(gvr, ns, objMeta.GetName())
|
||||
if getOldObjErr != nil {
|
||||
return true, nil, getOldObjErr
|
||||
}
|
||||
// Check whether the existing historical object type is the same as the current operation object type that needs to be updated, and if it is the same, perform the update operation.
|
||||
if reflect.TypeOf(oldObj) == reflect.TypeOf(action.GetObject()) {
|
||||
// TODO: Currently we're handling subresource creation as an update
|
||||
// on the enclosing resource. This works for some subresources but
|
||||
// might not be generic enough.
|
||||
err = tracker.Update(gvr, action.GetObject(), ns)
|
||||
} else {
|
||||
// If the historical object type is different from the current object type, need to make sure we return the object submitted,don't persist the submitted object in the tracker.
|
||||
return true, action.GetObject(), nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return true, nil, err
|
||||
|
||||
58
third_party/forked/golang/template/exec.go
vendored
58
third_party/forked/golang/template/exec.go
vendored
@@ -8,19 +8,16 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var Indirect = indirect
|
||||
var PrintableValue = printableValue
|
||||
|
||||
var (
|
||||
errorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
|
||||
)
|
||||
|
||||
// indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
|
||||
// Indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
|
||||
// We indirect through pointers and empty interfaces (only) because
|
||||
// non-empty interfaces have methods we might need.
|
||||
func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
|
||||
for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
|
||||
func Indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
|
||||
for ; v.Kind() == reflect.Pointer || v.Kind() == reflect.Interface; v = v.Elem() {
|
||||
if v.IsNil() {
|
||||
return v, true
|
||||
}
|
||||
@@ -31,18 +28,18 @@ func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
|
||||
return v, false
|
||||
}
|
||||
|
||||
// printableValue returns the, possibly indirected, interface value inside v that
|
||||
// PrintableValue returns the, possibly indirected, interface value inside v that
|
||||
// is best for a call to formatted printer.
|
||||
func printableValue(v reflect.Value) (interface{}, bool) {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v, _ = indirect(v) // fmt.Fprint handles nil.
|
||||
func PrintableValue(v reflect.Value) (interface{}, bool) {
|
||||
if v.Kind() == reflect.Pointer {
|
||||
v, _ = Indirect(v) // fmt.Fprint handles nil.
|
||||
}
|
||||
if !v.IsValid() {
|
||||
return "<no value>", true
|
||||
}
|
||||
|
||||
if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) {
|
||||
if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) {
|
||||
if v.CanAddr() && (reflect.PointerTo(v.Type()).Implements(errorType) || reflect.PointerTo(v.Type()).Implements(fmtStringerType)) {
|
||||
v = v.Addr()
|
||||
} else {
|
||||
switch v.Kind() {
|
||||
@@ -53,42 +50,3 @@ func printableValue(v reflect.Value) (interface{}, bool) {
|
||||
}
|
||||
return v.Interface(), true
|
||||
}
|
||||
|
||||
// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
|
||||
func canBeNil(typ reflect.Type) bool {
|
||||
switch typ.Kind() {
|
||||
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// isTrue reports whether the value is 'true', in the sense of not the zero of its type,
|
||||
// and whether the value has a meaningful truth value.
|
||||
func isTrue(val reflect.Value) (truth, ok bool) {
|
||||
if !val.IsValid() {
|
||||
// Something like var x interface{}, never set. It's a form of nil.
|
||||
return false, true
|
||||
}
|
||||
switch val.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
truth = val.Len() > 0
|
||||
case reflect.Bool:
|
||||
truth = val.Bool()
|
||||
case reflect.Complex64, reflect.Complex128:
|
||||
truth = val.Complex() != 0
|
||||
case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface:
|
||||
truth = !val.IsNil()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
truth = val.Int() != 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
truth = val.Float() != 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
truth = val.Uint() != 0
|
||||
case reflect.Struct:
|
||||
truth = true // Struct values are always true.
|
||||
default:
|
||||
return
|
||||
}
|
||||
return truth, true
|
||||
}
|
||||
|
||||
456
third_party/forked/golang/template/funcs.go
vendored
456
third_party/forked/golang/template/funcs.go
vendored
@@ -4,264 +4,10 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var Equal = eq
|
||||
var GreaterEqual = ge
|
||||
var Greater = gt
|
||||
var LessEqual = le
|
||||
var Less = lt
|
||||
var NotEqual = ne
|
||||
|
||||
// FuncMap is the type of the map defining the mapping from names to functions.
|
||||
// Each function must have either a single return value, or two return values of
|
||||
// which the second has type error. In that case, if the second (error)
|
||||
// return value evaluates to non-nil during execution, execution terminates and
|
||||
// Execute returns that error.
|
||||
type FuncMap map[string]interface{}
|
||||
|
||||
var builtins = FuncMap{
|
||||
"and": and,
|
||||
"call": call,
|
||||
"html": HTMLEscaper,
|
||||
"index": index,
|
||||
"js": JSEscaper,
|
||||
"len": length,
|
||||
"not": not,
|
||||
"or": or,
|
||||
"print": fmt.Sprint,
|
||||
"printf": fmt.Sprintf,
|
||||
"println": fmt.Sprintln,
|
||||
"urlquery": URLQueryEscaper,
|
||||
|
||||
// Comparisons
|
||||
"eq": eq, // ==
|
||||
"ge": ge, // >=
|
||||
"gt": gt, // >
|
||||
"le": le, // <=
|
||||
"lt": lt, // <
|
||||
"ne": ne, // !=
|
||||
}
|
||||
|
||||
var builtinFuncs = createValueFuncs(builtins)
|
||||
|
||||
// createValueFuncs turns a FuncMap into a map[string]reflect.Value
|
||||
func createValueFuncs(funcMap FuncMap) map[string]reflect.Value {
|
||||
m := make(map[string]reflect.Value)
|
||||
addValueFuncs(m, funcMap)
|
||||
return m
|
||||
}
|
||||
|
||||
// addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
|
||||
func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
|
||||
for name, fn := range in {
|
||||
v := reflect.ValueOf(fn)
|
||||
if v.Kind() != reflect.Func {
|
||||
panic("value for " + name + " not a function")
|
||||
}
|
||||
if !goodFunc(v.Type()) {
|
||||
panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut()))
|
||||
}
|
||||
out[name] = v
|
||||
}
|
||||
}
|
||||
|
||||
// AddFuncs adds to values the functions in funcs. It does no checking of the input -
|
||||
// call addValueFuncs first.
|
||||
func addFuncs(out, in FuncMap) {
|
||||
for name, fn := range in {
|
||||
out[name] = fn
|
||||
}
|
||||
}
|
||||
|
||||
// goodFunc checks that the function or method has the right result signature.
|
||||
func goodFunc(typ reflect.Type) bool {
|
||||
// We allow functions with 1 result or 2 results where the second is an error.
|
||||
switch {
|
||||
case typ.NumOut() == 1:
|
||||
return true
|
||||
case typ.NumOut() == 2 && typ.Out(1) == errorType:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// findFunction looks for a function in the template, and global map.
|
||||
func findFunction(name string) (reflect.Value, bool) {
|
||||
if fn := builtinFuncs[name]; fn.IsValid() {
|
||||
return fn, true
|
||||
}
|
||||
return reflect.Value{}, false
|
||||
}
|
||||
|
||||
// Indexing.
|
||||
|
||||
// index returns the result of indexing its first argument by the following
|
||||
// arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
|
||||
// indexed item must be a map, slice, or array.
|
||||
func index(item interface{}, indices ...interface{}) (interface{}, error) {
|
||||
v := reflect.ValueOf(item)
|
||||
for _, i := range indices {
|
||||
index := reflect.ValueOf(i)
|
||||
var isNil bool
|
||||
if v, isNil = indirect(v); isNil {
|
||||
return nil, fmt.Errorf("index of nil pointer")
|
||||
}
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.String:
|
||||
var x int64
|
||||
switch index.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
x = index.Int()
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
x = int64(index.Uint())
|
||||
default:
|
||||
return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type())
|
||||
}
|
||||
if x < 0 || x >= int64(v.Len()) {
|
||||
return nil, fmt.Errorf("index out of range: %d", x)
|
||||
}
|
||||
v = v.Index(int(x))
|
||||
case reflect.Map:
|
||||
if !index.IsValid() {
|
||||
index = reflect.Zero(v.Type().Key())
|
||||
}
|
||||
if !index.Type().AssignableTo(v.Type().Key()) {
|
||||
return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
|
||||
}
|
||||
if x := v.MapIndex(index); x.IsValid() {
|
||||
v = x
|
||||
} else {
|
||||
v = reflect.Zero(v.Type().Elem())
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("can't index item of type %s", v.Type())
|
||||
}
|
||||
}
|
||||
return v.Interface(), nil
|
||||
}
|
||||
|
||||
// Length
|
||||
|
||||
// length returns the length of the item, with an error if it has no defined length.
|
||||
func length(item interface{}) (int, error) {
|
||||
v, isNil := indirect(reflect.ValueOf(item))
|
||||
if isNil {
|
||||
return 0, fmt.Errorf("len of nil pointer")
|
||||
}
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len(), nil
|
||||
}
|
||||
return 0, fmt.Errorf("len of type %s", v.Type())
|
||||
}
|
||||
|
||||
// Function invocation
|
||||
|
||||
// call returns the result of evaluating the first argument as a function.
|
||||
// The function must return 1 result, or 2 results, the second of which is an error.
|
||||
func call(fn interface{}, args ...interface{}) (interface{}, error) {
|
||||
v := reflect.ValueOf(fn)
|
||||
typ := v.Type()
|
||||
if typ.Kind() != reflect.Func {
|
||||
return nil, fmt.Errorf("non-function of type %s", typ)
|
||||
}
|
||||
if !goodFunc(typ) {
|
||||
return nil, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut())
|
||||
}
|
||||
numIn := typ.NumIn()
|
||||
var dddType reflect.Type
|
||||
if typ.IsVariadic() {
|
||||
if len(args) < numIn-1 {
|
||||
return nil, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1)
|
||||
}
|
||||
dddType = typ.In(numIn - 1).Elem()
|
||||
} else {
|
||||
if len(args) != numIn {
|
||||
return nil, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn)
|
||||
}
|
||||
}
|
||||
argv := make([]reflect.Value, len(args))
|
||||
for i, arg := range args {
|
||||
value := reflect.ValueOf(arg)
|
||||
// Compute the expected type. Clumsy because of variadics.
|
||||
var argType reflect.Type
|
||||
if !typ.IsVariadic() || i < numIn-1 {
|
||||
argType = typ.In(i)
|
||||
} else {
|
||||
argType = dddType
|
||||
}
|
||||
if !value.IsValid() && canBeNil(argType) {
|
||||
value = reflect.Zero(argType)
|
||||
}
|
||||
if !value.Type().AssignableTo(argType) {
|
||||
return nil, fmt.Errorf("arg %d has type %s; should be %s", i, value.Type(), argType)
|
||||
}
|
||||
argv[i] = value
|
||||
}
|
||||
result := v.Call(argv)
|
||||
if len(result) == 2 && !result[1].IsNil() {
|
||||
return result[0].Interface(), result[1].Interface().(error)
|
||||
}
|
||||
return result[0].Interface(), nil
|
||||
}
|
||||
|
||||
// Boolean logic.
|
||||
|
||||
func truth(a interface{}) bool {
|
||||
t, _ := isTrue(reflect.ValueOf(a))
|
||||
return t
|
||||
}
|
||||
|
||||
// and computes the Boolean AND of its arguments, returning
|
||||
// the first false argument it encounters, or the last argument.
|
||||
func and(arg0 interface{}, args ...interface{}) interface{} {
|
||||
if !truth(arg0) {
|
||||
return arg0
|
||||
}
|
||||
for i := range args {
|
||||
arg0 = args[i]
|
||||
if !truth(arg0) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return arg0
|
||||
}
|
||||
|
||||
// or computes the Boolean OR of its arguments, returning
|
||||
// the first true argument it encounters, or the last argument.
|
||||
func or(arg0 interface{}, args ...interface{}) interface{} {
|
||||
if truth(arg0) {
|
||||
return arg0
|
||||
}
|
||||
for i := range args {
|
||||
arg0 = args[i]
|
||||
if truth(arg0) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return arg0
|
||||
}
|
||||
|
||||
// not returns the Boolean negation of its argument.
|
||||
func not(arg interface{}) (truth bool) {
|
||||
truth, _ = isTrue(reflect.ValueOf(arg))
|
||||
return !truth
|
||||
}
|
||||
|
||||
// Comparison.
|
||||
|
||||
// TODO: Perhaps allow comparison between signed and unsigned integers.
|
||||
|
||||
var (
|
||||
errBadComparisonType = errors.New("invalid type for comparison")
|
||||
errBadComparison = errors.New("incompatible types for comparison")
|
||||
@@ -299,8 +45,8 @@ func basicKind(v reflect.Value) (kind, error) {
|
||||
return invalidKind, errBadComparisonType
|
||||
}
|
||||
|
||||
// eq evaluates the comparison a == b || a == c || ...
|
||||
func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
|
||||
// Equal evaluates the comparison a == b || a == c || ...
|
||||
func Equal(arg1 interface{}, arg2 ...interface{}) (bool, error) {
|
||||
v1 := reflect.ValueOf(arg1)
|
||||
k1, err := basicKind(v1)
|
||||
if err != nil {
|
||||
@@ -351,15 +97,15 @@ func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// ne evaluates the comparison a != b.
|
||||
func ne(arg1, arg2 interface{}) (bool, error) {
|
||||
// NotEqual evaluates the comparison a != b.
|
||||
func NotEqual(arg1, arg2 interface{}) (bool, error) {
|
||||
// != is the inverse of ==.
|
||||
equal, err := eq(arg1, arg2)
|
||||
equal, err := Equal(arg1, arg2)
|
||||
return !equal, err
|
||||
}
|
||||
|
||||
// lt evaluates the comparison a < b.
|
||||
func lt(arg1, arg2 interface{}) (bool, error) {
|
||||
// Less evaluates the comparison a < b.
|
||||
func Less(arg1, arg2 interface{}) (bool, error) {
|
||||
v1 := reflect.ValueOf(arg1)
|
||||
k1, err := basicKind(v1)
|
||||
if err != nil {
|
||||
@@ -400,200 +146,32 @@ func lt(arg1, arg2 interface{}) (bool, error) {
|
||||
return truth, nil
|
||||
}
|
||||
|
||||
// le evaluates the comparison <= b.
|
||||
func le(arg1, arg2 interface{}) (bool, error) {
|
||||
// LessEqual evaluates the comparison <= b.
|
||||
func LessEqual(arg1, arg2 interface{}) (bool, error) {
|
||||
// <= is < or ==.
|
||||
lessThan, err := lt(arg1, arg2)
|
||||
lessThan, err := Less(arg1, arg2)
|
||||
if lessThan || err != nil {
|
||||
return lessThan, err
|
||||
}
|
||||
return eq(arg1, arg2)
|
||||
return Equal(arg1, arg2)
|
||||
}
|
||||
|
||||
// gt evaluates the comparison a > b.
|
||||
func gt(arg1, arg2 interface{}) (bool, error) {
|
||||
// Greater evaluates the comparison a > b.
|
||||
func Greater(arg1, arg2 interface{}) (bool, error) {
|
||||
// > is the inverse of <=.
|
||||
lessOrEqual, err := le(arg1, arg2)
|
||||
lessOrEqual, err := LessEqual(arg1, arg2)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return !lessOrEqual, nil
|
||||
}
|
||||
|
||||
// ge evaluates the comparison a >= b.
|
||||
func ge(arg1, arg2 interface{}) (bool, error) {
|
||||
// GreaterEqual evaluates the comparison a >= b.
|
||||
func GreaterEqual(arg1, arg2 interface{}) (bool, error) {
|
||||
// >= is the inverse of <.
|
||||
lessThan, err := lt(arg1, arg2)
|
||||
lessThan, err := Less(arg1, arg2)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return !lessThan, nil
|
||||
}
|
||||
|
||||
// HTML escaping.
|
||||
|
||||
var (
|
||||
htmlQuot = []byte(""") // shorter than """
|
||||
htmlApos = []byte("'") // shorter than "'" and apos was not in HTML until HTML5
|
||||
htmlAmp = []byte("&")
|
||||
htmlLt = []byte("<")
|
||||
htmlGt = []byte(">")
|
||||
)
|
||||
|
||||
// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
|
||||
func HTMLEscape(w io.Writer, b []byte) {
|
||||
last := 0
|
||||
for i, c := range b {
|
||||
var html []byte
|
||||
switch c {
|
||||
case '"':
|
||||
html = htmlQuot
|
||||
case '\'':
|
||||
html = htmlApos
|
||||
case '&':
|
||||
html = htmlAmp
|
||||
case '<':
|
||||
html = htmlLt
|
||||
case '>':
|
||||
html = htmlGt
|
||||
default:
|
||||
continue
|
||||
}
|
||||
w.Write(b[last:i])
|
||||
w.Write(html)
|
||||
last = i + 1
|
||||
}
|
||||
w.Write(b[last:])
|
||||
}
|
||||
|
||||
// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
|
||||
func HTMLEscapeString(s string) string {
|
||||
// Avoid allocation if we can.
|
||||
if strings.IndexAny(s, `'"&<>`) < 0 {
|
||||
return s
|
||||
}
|
||||
var b bytes.Buffer
|
||||
HTMLEscape(&b, []byte(s))
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// HTMLEscaper returns the escaped HTML equivalent of the textual
|
||||
// representation of its arguments.
|
||||
func HTMLEscaper(args ...interface{}) string {
|
||||
return HTMLEscapeString(evalArgs(args))
|
||||
}
|
||||
|
||||
// JavaScript escaping.
|
||||
|
||||
var (
|
||||
jsLowUni = []byte(`\u00`)
|
||||
hex = []byte("0123456789ABCDEF")
|
||||
|
||||
jsBackslash = []byte(`\\`)
|
||||
jsApos = []byte(`\'`)
|
||||
jsQuot = []byte(`\"`)
|
||||
jsLt = []byte(`\x3C`)
|
||||
jsGt = []byte(`\x3E`)
|
||||
)
|
||||
|
||||
// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
|
||||
func JSEscape(w io.Writer, b []byte) {
|
||||
last := 0
|
||||
for i := 0; i < len(b); i++ {
|
||||
c := b[i]
|
||||
|
||||
if !jsIsSpecial(rune(c)) {
|
||||
// fast path: nothing to do
|
||||
continue
|
||||
}
|
||||
w.Write(b[last:i])
|
||||
|
||||
if c < utf8.RuneSelf {
|
||||
// Quotes, slashes and angle brackets get quoted.
|
||||
// Control characters get written as \u00XX.
|
||||
switch c {
|
||||
case '\\':
|
||||
w.Write(jsBackslash)
|
||||
case '\'':
|
||||
w.Write(jsApos)
|
||||
case '"':
|
||||
w.Write(jsQuot)
|
||||
case '<':
|
||||
w.Write(jsLt)
|
||||
case '>':
|
||||
w.Write(jsGt)
|
||||
default:
|
||||
w.Write(jsLowUni)
|
||||
t, b := c>>4, c&0x0f
|
||||
w.Write(hex[t : t+1])
|
||||
w.Write(hex[b : b+1])
|
||||
}
|
||||
} else {
|
||||
// Unicode rune.
|
||||
r, size := utf8.DecodeRune(b[i:])
|
||||
if unicode.IsPrint(r) {
|
||||
w.Write(b[i : i+size])
|
||||
} else {
|
||||
fmt.Fprintf(w, "\\u%04X", r)
|
||||
}
|
||||
i += size - 1
|
||||
}
|
||||
last = i + 1
|
||||
}
|
||||
w.Write(b[last:])
|
||||
}
|
||||
|
||||
// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
|
||||
func JSEscapeString(s string) string {
|
||||
// Avoid allocation if we can.
|
||||
if strings.IndexFunc(s, jsIsSpecial) < 0 {
|
||||
return s
|
||||
}
|
||||
var b bytes.Buffer
|
||||
JSEscape(&b, []byte(s))
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func jsIsSpecial(r rune) bool {
|
||||
switch r {
|
||||
case '\\', '\'', '"', '<', '>':
|
||||
return true
|
||||
}
|
||||
return r < ' ' || utf8.RuneSelf <= r
|
||||
}
|
||||
|
||||
// JSEscaper returns the escaped JavaScript equivalent of the textual
|
||||
// representation of its arguments.
|
||||
func JSEscaper(args ...interface{}) string {
|
||||
return JSEscapeString(evalArgs(args))
|
||||
}
|
||||
|
||||
// URLQueryEscaper returns the escaped value of the textual representation of
|
||||
// its arguments in a form suitable for embedding in a URL query.
|
||||
func URLQueryEscaper(args ...interface{}) string {
|
||||
return url.QueryEscape(evalArgs(args))
|
||||
}
|
||||
|
||||
// evalArgs formats the list of arguments into a string. It is therefore equivalent to
|
||||
// fmt.Sprint(args...)
|
||||
// except that each argument is indirected (if a pointer), as required,
|
||||
// using the same rules as the default string evaluation during template
|
||||
// execution.
|
||||
func evalArgs(args []interface{}) string {
|
||||
ok := false
|
||||
var s string
|
||||
// Fast path for simple common case.
|
||||
if len(args) == 1 {
|
||||
s, ok = args[0].(string)
|
||||
}
|
||||
if !ok {
|
||||
for i, arg := range args {
|
||||
a, ok := printableValue(reflect.ValueOf(arg))
|
||||
if ok {
|
||||
args[i] = a
|
||||
} // else left fmt do its thing
|
||||
}
|
||||
s = fmt.Sprint(args...)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@@ -45,20 +45,20 @@ client.Client from an authcfg.Info.
|
||||
|
||||
Example:
|
||||
|
||||
import (
|
||||
"pkg/client"
|
||||
"pkg/client/auth"
|
||||
)
|
||||
import (
|
||||
"pkg/client"
|
||||
"pkg/client/auth"
|
||||
)
|
||||
|
||||
info, err := auth.LoadFromFile(filename)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
clientConfig = client.Config{}
|
||||
clientConfig.Host = "example.com:4901"
|
||||
clientConfig = info.MergeWithConfig()
|
||||
client := client.New(clientConfig)
|
||||
client.Pods(ns).List()
|
||||
info, err := auth.LoadFromFile(filename)
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
clientConfig = client.Config{}
|
||||
clientConfig.Host = "example.com:4901"
|
||||
clientConfig = info.MergeWithConfig()
|
||||
client := client.New(clientConfig)
|
||||
client.Pods(ns).List()
|
||||
*/
|
||||
package auth
|
||||
|
||||
|
||||
77
tools/cache/controller.go
vendored
77
tools/cache/controller.go
vendored
@@ -199,17 +199,17 @@ func (c *controller) processLoop() {
|
||||
// can't return an error. The handlers MUST NOT modify the objects
|
||||
// received; this concerns not only the top level of structure but all
|
||||
// the data structures reachable from it.
|
||||
// * OnAdd is called when an object is added.
|
||||
// * OnUpdate is called when an object is modified. Note that oldObj is the
|
||||
// last known state of the object-- it is possible that several changes
|
||||
// were combined together, so you can't use this to see every single
|
||||
// change. OnUpdate is also called when a re-list happens, and it will
|
||||
// get called even if nothing changed. This is useful for periodically
|
||||
// evaluating or syncing something.
|
||||
// * OnDelete will get the final state of the item if it is known, otherwise
|
||||
// it will get an object of type DeletedFinalStateUnknown. This can
|
||||
// happen if the watch is closed and misses the delete event and we don't
|
||||
// notice the deletion until the subsequent re-list.
|
||||
// - OnAdd is called when an object is added.
|
||||
// - OnUpdate is called when an object is modified. Note that oldObj is the
|
||||
// last known state of the object-- it is possible that several changes
|
||||
// were combined together, so you can't use this to see every single
|
||||
// change. OnUpdate is also called when a re-list happens, and it will
|
||||
// get called even if nothing changed. This is useful for periodically
|
||||
// evaluating or syncing something.
|
||||
// - OnDelete will get the final state of the item if it is known, otherwise
|
||||
// it will get an object of type DeletedFinalStateUnknown. This can
|
||||
// happen if the watch is closed and misses the delete event and we don't
|
||||
// notice the deletion until the subsequent re-list.
|
||||
type ResourceEventHandler interface {
|
||||
OnAdd(obj interface{})
|
||||
OnUpdate(oldObj, newObj interface{})
|
||||
@@ -305,15 +305,14 @@ func DeletionHandlingMetaNamespaceKeyFunc(obj interface{}) (string, error) {
|
||||
// notifications to be faulty.
|
||||
//
|
||||
// Parameters:
|
||||
// * lw is list and watch functions for the source of the resource you want to
|
||||
// be informed of.
|
||||
// * objType is an object of the type that you expect to receive.
|
||||
// * resyncPeriod: if non-zero, will re-list this often (you will get OnUpdate
|
||||
// calls, even if nothing changed). Otherwise, re-list will be delayed as
|
||||
// long as possible (until the upstream source closes the watch or times out,
|
||||
// or you stop the controller).
|
||||
// * h is the object you want notifications sent to.
|
||||
//
|
||||
// - lw is list and watch functions for the source of the resource you want to
|
||||
// be informed of.
|
||||
// - objType is an object of the type that you expect to receive.
|
||||
// - resyncPeriod: if non-zero, will re-list this often (you will get OnUpdate
|
||||
// calls, even if nothing changed). Otherwise, re-list will be delayed as
|
||||
// long as possible (until the upstream source closes the watch or times out,
|
||||
// or you stop the controller).
|
||||
// - h is the object you want notifications sent to.
|
||||
func NewInformer(
|
||||
lw ListerWatcher,
|
||||
objType runtime.Object,
|
||||
@@ -332,16 +331,15 @@ func NewInformer(
|
||||
// notifications to be faulty.
|
||||
//
|
||||
// Parameters:
|
||||
// * lw is list and watch functions for the source of the resource you want to
|
||||
// be informed of.
|
||||
// * objType is an object of the type that you expect to receive.
|
||||
// * resyncPeriod: if non-zero, will re-list this often (you will get OnUpdate
|
||||
// calls, even if nothing changed). Otherwise, re-list will be delayed as
|
||||
// long as possible (until the upstream source closes the watch or times out,
|
||||
// or you stop the controller).
|
||||
// * h is the object you want notifications sent to.
|
||||
// * indexers is the indexer for the received object type.
|
||||
//
|
||||
// - lw is list and watch functions for the source of the resource you want to
|
||||
// be informed of.
|
||||
// - objType is an object of the type that you expect to receive.
|
||||
// - resyncPeriod: if non-zero, will re-list this often (you will get OnUpdate
|
||||
// calls, even if nothing changed). Otherwise, re-list will be delayed as
|
||||
// long as possible (until the upstream source closes the watch or times out,
|
||||
// or you stop the controller).
|
||||
// - h is the object you want notifications sent to.
|
||||
// - indexers is the indexer for the received object type.
|
||||
func NewIndexerInformer(
|
||||
lw ListerWatcher,
|
||||
objType runtime.Object,
|
||||
@@ -454,16 +452,15 @@ func processDeltas(
|
||||
// providing event notifications.
|
||||
//
|
||||
// Parameters
|
||||
// * lw is list and watch functions for the source of the resource you want to
|
||||
// be informed of.
|
||||
// * objType is an object of the type that you expect to receive.
|
||||
// * resyncPeriod: if non-zero, will re-list this often (you will get OnUpdate
|
||||
// calls, even if nothing changed). Otherwise, re-list will be delayed as
|
||||
// long as possible (until the upstream source closes the watch or times out,
|
||||
// or you stop the controller).
|
||||
// * h is the object you want notifications sent to.
|
||||
// * clientState is the store you want to populate
|
||||
//
|
||||
// - lw is list and watch functions for the source of the resource you want to
|
||||
// be informed of.
|
||||
// - objType is an object of the type that you expect to receive.
|
||||
// - resyncPeriod: if non-zero, will re-list this often (you will get OnUpdate
|
||||
// calls, even if nothing changed). Otherwise, re-list will be delayed as
|
||||
// long as possible (until the upstream source closes the watch or times out,
|
||||
// or you stop the controller).
|
||||
// - h is the object you want notifications sent to.
|
||||
// - clientState is the store you want to populate
|
||||
func newInformer(
|
||||
lw ListerWatcher,
|
||||
objType runtime.Object,
|
||||
|
||||
38
tools/cache/delta_fifo.go
vendored
38
tools/cache/delta_fifo.go
vendored
@@ -74,11 +74,11 @@ type DeltaFIFOOptions struct {
|
||||
// the Pop() method.
|
||||
//
|
||||
// DeltaFIFO solves this use case:
|
||||
// * You want to process every object change (delta) at most once.
|
||||
// * When you process an object, you want to see everything
|
||||
// that's happened to it since you last processed it.
|
||||
// * You want to process the deletion of some of the objects.
|
||||
// * You might want to periodically reprocess objects.
|
||||
// - You want to process every object change (delta) at most once.
|
||||
// - When you process an object, you want to see everything
|
||||
// that's happened to it since you last processed it.
|
||||
// - You want to process the deletion of some of the objects.
|
||||
// - You might want to periodically reprocess objects.
|
||||
//
|
||||
// DeltaFIFO's Pop(), Get(), and GetByKey() methods return
|
||||
// interface{} to satisfy the Store/Queue interfaces, but they
|
||||
@@ -179,21 +179,21 @@ type Deltas []Delta
|
||||
// "known" keys when Pop() is called. Have to think about how that
|
||||
// affects error retrying.
|
||||
//
|
||||
// NOTE: It is possible to misuse this and cause a race when using an
|
||||
// external known object source.
|
||||
// Whether there is a potential race depends on how the consumer
|
||||
// modifies knownObjects. In Pop(), process function is called under
|
||||
// lock, so it is safe to update data structures in it that need to be
|
||||
// in sync with the queue (e.g. knownObjects).
|
||||
// NOTE: It is possible to misuse this and cause a race when using an
|
||||
// external known object source.
|
||||
// Whether there is a potential race depends on how the consumer
|
||||
// modifies knownObjects. In Pop(), process function is called under
|
||||
// lock, so it is safe to update data structures in it that need to be
|
||||
// in sync with the queue (e.g. knownObjects).
|
||||
//
|
||||
// Example:
|
||||
// In case of sharedIndexInformer being a consumer
|
||||
// (https://github.com/kubernetes/kubernetes/blob/0cdd940f/staging/src/k8s.io/client-go/tools/cache/shared_informer.go#L192),
|
||||
// there is no race as knownObjects (s.indexer) is modified safely
|
||||
// under DeltaFIFO's lock. The only exceptions are GetStore() and
|
||||
// GetIndexer() methods, which expose ways to modify the underlying
|
||||
// storage. Currently these two methods are used for creating Lister
|
||||
// and internal tests.
|
||||
// Example:
|
||||
// In case of sharedIndexInformer being a consumer
|
||||
// (https://github.com/kubernetes/kubernetes/blob/0cdd940f/staging/src/k8s.io/client-go/tools/cache/shared_informer.go#L192),
|
||||
// there is no race as knownObjects (s.indexer) is modified safely
|
||||
// under DeltaFIFO's lock. The only exceptions are GetStore() and
|
||||
// GetIndexer() methods, which expose ways to modify the underlying
|
||||
// storage. Currently these two methods are used for creating Lister
|
||||
// and internal tests.
|
||||
//
|
||||
// Also see the comment on DeltaFIFO.
|
||||
//
|
||||
|
||||
15
tools/cache/expiration_cache.go
vendored
15
tools/cache/expiration_cache.go
vendored
@@ -25,13 +25,14 @@ import (
|
||||
)
|
||||
|
||||
// ExpirationCache implements the store interface
|
||||
// 1. All entries are automatically time stamped on insert
|
||||
// a. The key is computed based off the original item/keyFunc
|
||||
// b. The value inserted under that key is the timestamped item
|
||||
// 2. Expiration happens lazily on read based on the expiration policy
|
||||
// a. No item can be inserted into the store while we're expiring
|
||||
// *any* item in the cache.
|
||||
// 3. Time-stamps are stripped off unexpired entries before return
|
||||
// 1. All entries are automatically time stamped on insert
|
||||
// a. The key is computed based off the original item/keyFunc
|
||||
// b. The value inserted under that key is the timestamped item
|
||||
// 2. Expiration happens lazily on read based on the expiration policy
|
||||
// a. No item can be inserted into the store while we're expiring
|
||||
// *any* item in the cache.
|
||||
// 3. Time-stamps are stripped off unexpired entries before return
|
||||
//
|
||||
// Note that the ExpirationCache is inherently slower than a normal
|
||||
// threadSafeStore because it takes a write lock every time it checks if
|
||||
// an item has expired.
|
||||
|
||||
9
tools/cache/fifo.go
vendored
9
tools/cache/fifo.go
vendored
@@ -103,10 +103,11 @@ func Pop(queue Queue) interface{} {
|
||||
// recent version will be processed. This can't be done with a channel
|
||||
//
|
||||
// FIFO solves this use case:
|
||||
// * You want to process every object (exactly) once.
|
||||
// * You want to process the most recent version of the object when you process it.
|
||||
// * You do not want to process deleted objects, they should be removed from the queue.
|
||||
// * You do not want to periodically reprocess objects.
|
||||
// - You want to process every object (exactly) once.
|
||||
// - You want to process the most recent version of the object when you process it.
|
||||
// - You do not want to process deleted objects, they should be removed from the queue.
|
||||
// - You do not want to periodically reprocess objects.
|
||||
//
|
||||
// Compare with DeltaFIFO for other use cases.
|
||||
type FIFO struct {
|
||||
lock sync.RWMutex
|
||||
|
||||
10
tools/cache/index.go
vendored
10
tools/cache/index.go
vendored
@@ -28,10 +28,10 @@ import (
|
||||
// Delete).
|
||||
//
|
||||
// There are three kinds of strings here:
|
||||
// 1. a storage key, as defined in the Store interface,
|
||||
// 2. a name of an index, and
|
||||
// 3. an "indexed value", which is produced by an IndexFunc and
|
||||
// can be a field value or any other string computed from the object.
|
||||
// 1. a storage key, as defined in the Store interface,
|
||||
// 2. a name of an index, and
|
||||
// 3. an "indexed value", which is produced by an IndexFunc and
|
||||
// can be a field value or any other string computed from the object.
|
||||
type Indexer interface {
|
||||
Store
|
||||
// Index returns the stored objects whose set of indexed values
|
||||
@@ -47,7 +47,7 @@ type Indexer interface {
|
||||
// ByIndex returns the stored objects whose set of indexed values
|
||||
// for the named index includes the given indexed value
|
||||
ByIndex(indexName, indexedValue string) ([]interface{}, error)
|
||||
// GetIndexer return the indexers
|
||||
// GetIndexers return the indexers
|
||||
GetIndexers() Indexers
|
||||
|
||||
// AddIndexers adds more indexers to this store. If you call this after you already have data
|
||||
|
||||
287
tools/cache/reflector.go
vendored
287
tools/cache/reflector.go
vendored
@@ -71,6 +71,8 @@ type Reflector struct {
|
||||
backoffManager wait.BackoffManager
|
||||
// initConnBackoffManager manages backoff the initial connection with the Watch call of ListAndWatch.
|
||||
initConnBackoffManager wait.BackoffManager
|
||||
// MaxInternalErrorRetryDuration defines how long we should retry internal errors returned by watch.
|
||||
MaxInternalErrorRetryDuration time.Duration
|
||||
|
||||
resyncPeriod time.Duration
|
||||
// ShouldResync is invoked periodically and whenever it returns `true` the Store's Resync operation is invoked
|
||||
@@ -253,112 +255,9 @@ func (r *Reflector) resyncChan() (<-chan time.Time, func() bool) {
|
||||
// It returns error if ListAndWatch didn't even try to initialize watch.
|
||||
func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
|
||||
klog.V(3).Infof("Listing and watching %v from %s", r.expectedTypeName, r.name)
|
||||
var resourceVersion string
|
||||
|
||||
options := metav1.ListOptions{ResourceVersion: r.relistResourceVersion()}
|
||||
|
||||
if err := func() error {
|
||||
initTrace := trace.New("Reflector ListAndWatch", trace.Field{Key: "name", Value: r.name})
|
||||
defer initTrace.LogIfLong(10 * time.Second)
|
||||
var list runtime.Object
|
||||
var paginatedResult bool
|
||||
var err error
|
||||
listCh := make(chan struct{}, 1)
|
||||
panicCh := make(chan interface{}, 1)
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
panicCh <- r
|
||||
}
|
||||
}()
|
||||
// Attempt to gather list in chunks, if supported by listerWatcher, if not, the first
|
||||
// list request will return the full response.
|
||||
pager := pager.New(pager.SimplePageFunc(func(opts metav1.ListOptions) (runtime.Object, error) {
|
||||
return r.listerWatcher.List(opts)
|
||||
}))
|
||||
switch {
|
||||
case r.WatchListPageSize != 0:
|
||||
pager.PageSize = r.WatchListPageSize
|
||||
case r.paginatedResult:
|
||||
// We got a paginated result initially. Assume this resource and server honor
|
||||
// paging requests (i.e. watch cache is probably disabled) and leave the default
|
||||
// pager size set.
|
||||
case options.ResourceVersion != "" && options.ResourceVersion != "0":
|
||||
// User didn't explicitly request pagination.
|
||||
//
|
||||
// With ResourceVersion != "", we have a possibility to list from watch cache,
|
||||
// but we do that (for ResourceVersion != "0") only if Limit is unset.
|
||||
// To avoid thundering herd on etcd (e.g. on master upgrades), we explicitly
|
||||
// switch off pagination to force listing from watch cache (if enabled).
|
||||
// With the existing semantic of RV (result is at least as fresh as provided RV),
|
||||
// this is correct and doesn't lead to going back in time.
|
||||
//
|
||||
// We also don't turn off pagination for ResourceVersion="0", since watch cache
|
||||
// is ignoring Limit in that case anyway, and if watch cache is not enabled
|
||||
// we don't introduce regression.
|
||||
pager.PageSize = 0
|
||||
}
|
||||
|
||||
list, paginatedResult, err = pager.List(context.Background(), options)
|
||||
if isExpiredError(err) || isTooLargeResourceVersionError(err) {
|
||||
r.setIsLastSyncResourceVersionUnavailable(true)
|
||||
// Retry immediately if the resource version used to list is unavailable.
|
||||
// The pager already falls back to full list if paginated list calls fail due to an "Expired" error on
|
||||
// continuation pages, but the pager might not be enabled, the full list might fail because the
|
||||
// resource version it is listing at is expired or the cache may not yet be synced to the provided
|
||||
// resource version. So we need to fallback to resourceVersion="" in all to recover and ensure
|
||||
// the reflector makes forward progress.
|
||||
list, paginatedResult, err = pager.List(context.Background(), metav1.ListOptions{ResourceVersion: r.relistResourceVersion()})
|
||||
}
|
||||
close(listCh)
|
||||
}()
|
||||
select {
|
||||
case <-stopCh:
|
||||
return nil
|
||||
case r := <-panicCh:
|
||||
panic(r)
|
||||
case <-listCh:
|
||||
}
|
||||
initTrace.Step("Objects listed", trace.Field{Key: "error", Value: err})
|
||||
if err != nil {
|
||||
klog.Warningf("%s: failed to list %v: %v", r.name, r.expectedTypeName, err)
|
||||
return fmt.Errorf("failed to list %v: %v", r.expectedTypeName, err)
|
||||
}
|
||||
|
||||
// We check if the list was paginated and if so set the paginatedResult based on that.
|
||||
// However, we want to do that only for the initial list (which is the only case
|
||||
// when we set ResourceVersion="0"). The reasoning behind it is that later, in some
|
||||
// situations we may force listing directly from etcd (by setting ResourceVersion="")
|
||||
// which will return paginated result, even if watch cache is enabled. However, in
|
||||
// that case, we still want to prefer sending requests to watch cache if possible.
|
||||
//
|
||||
// Paginated result returned for request with ResourceVersion="0" mean that watch
|
||||
// cache is disabled and there are a lot of objects of a given type. In such case,
|
||||
// there is no need to prefer listing from watch cache.
|
||||
if options.ResourceVersion == "0" && paginatedResult {
|
||||
r.paginatedResult = true
|
||||
}
|
||||
|
||||
r.setIsLastSyncResourceVersionUnavailable(false) // list was successful
|
||||
listMetaInterface, err := meta.ListAccessor(list)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to understand list result %#v: %v", list, err)
|
||||
}
|
||||
resourceVersion = listMetaInterface.GetResourceVersion()
|
||||
initTrace.Step("Resource version extracted")
|
||||
items, err := meta.ExtractList(list)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to understand list result %#v (%v)", list, err)
|
||||
}
|
||||
initTrace.Step("Objects extracted")
|
||||
if err := r.syncWith(items, resourceVersion); err != nil {
|
||||
return fmt.Errorf("unable to sync list result: %v", err)
|
||||
}
|
||||
initTrace.Step("SyncWith done")
|
||||
r.setLastSyncResourceVersion(resourceVersion)
|
||||
initTrace.Step("Resource version updated")
|
||||
return nil
|
||||
}(); err != nil {
|
||||
err := r.list(stopCh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -390,6 +289,7 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
|
||||
}
|
||||
}()
|
||||
|
||||
retry := NewRetryWithDeadline(r.MaxInternalErrorRetryDuration, time.Minute, apierrors.IsInternalError, r.clock)
|
||||
for {
|
||||
// give the stopCh a chance to stop the loop, even in case of continue statements further down on errors
|
||||
select {
|
||||
@@ -399,8 +299,8 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
|
||||
}
|
||||
|
||||
timeoutSeconds := int64(minWatchTimeout.Seconds() * (rand.Float64() + 1.0))
|
||||
options = metav1.ListOptions{
|
||||
ResourceVersion: resourceVersion,
|
||||
options := metav1.ListOptions{
|
||||
ResourceVersion: r.LastSyncResourceVersion(),
|
||||
// We want to avoid situations of hanging watchers. Stop any watchers that do not
|
||||
// receive any events within the timeout window.
|
||||
TimeoutSeconds: &timeoutSeconds,
|
||||
@@ -426,7 +326,9 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := r.watchHandler(start, w, &resourceVersion, resyncerrc, stopCh); err != nil {
|
||||
err = watchHandler(start, w, r.store, r.expectedType, r.expectedGVK, r.name, r.expectedTypeName, r.setLastSyncResourceVersion, r.clock, resyncerrc, stopCh)
|
||||
retry.After(err)
|
||||
if err != nil {
|
||||
if err != errorStopRequested {
|
||||
switch {
|
||||
case isExpiredError(err):
|
||||
@@ -438,6 +340,9 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
|
||||
klog.V(2).Infof("%s: watch of %v returned 429 - backing off", r.name, r.expectedTypeName)
|
||||
<-r.initConnBackoffManager.Backoff().C()
|
||||
continue
|
||||
case apierrors.IsInternalError(err) && retry.ShouldRetry():
|
||||
klog.V(2).Infof("%s: retrying watch of %v internal error: %v", r.name, r.expectedTypeName, err)
|
||||
continue
|
||||
default:
|
||||
klog.Warningf("%s: watch of %v ended with: %v", r.name, r.expectedTypeName, err)
|
||||
}
|
||||
@@ -447,6 +352,114 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
|
||||
}
|
||||
}
|
||||
|
||||
// list simply lists all items and records a resource version obtained from the server at the moment of the call.
|
||||
// the resource version can be used for further progress notification (aka. watch).
|
||||
func (r *Reflector) list(stopCh <-chan struct{}) error {
|
||||
var resourceVersion string
|
||||
options := metav1.ListOptions{ResourceVersion: r.relistResourceVersion()}
|
||||
|
||||
initTrace := trace.New("Reflector ListAndWatch", trace.Field{Key: "name", Value: r.name})
|
||||
defer initTrace.LogIfLong(10 * time.Second)
|
||||
var list runtime.Object
|
||||
var paginatedResult bool
|
||||
var err error
|
||||
listCh := make(chan struct{}, 1)
|
||||
panicCh := make(chan interface{}, 1)
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
panicCh <- r
|
||||
}
|
||||
}()
|
||||
// Attempt to gather list in chunks, if supported by listerWatcher, if not, the first
|
||||
// list request will return the full response.
|
||||
pager := pager.New(pager.SimplePageFunc(func(opts metav1.ListOptions) (runtime.Object, error) {
|
||||
return r.listerWatcher.List(opts)
|
||||
}))
|
||||
switch {
|
||||
case r.WatchListPageSize != 0:
|
||||
pager.PageSize = r.WatchListPageSize
|
||||
case r.paginatedResult:
|
||||
// We got a paginated result initially. Assume this resource and server honor
|
||||
// paging requests (i.e. watch cache is probably disabled) and leave the default
|
||||
// pager size set.
|
||||
case options.ResourceVersion != "" && options.ResourceVersion != "0":
|
||||
// User didn't explicitly request pagination.
|
||||
//
|
||||
// With ResourceVersion != "", we have a possibility to list from watch cache,
|
||||
// but we do that (for ResourceVersion != "0") only if Limit is unset.
|
||||
// To avoid thundering herd on etcd (e.g. on master upgrades), we explicitly
|
||||
// switch off pagination to force listing from watch cache (if enabled).
|
||||
// With the existing semantic of RV (result is at least as fresh as provided RV),
|
||||
// this is correct and doesn't lead to going back in time.
|
||||
//
|
||||
// We also don't turn off pagination for ResourceVersion="0", since watch cache
|
||||
// is ignoring Limit in that case anyway, and if watch cache is not enabled
|
||||
// we don't introduce regression.
|
||||
pager.PageSize = 0
|
||||
}
|
||||
|
||||
list, paginatedResult, err = pager.List(context.Background(), options)
|
||||
if isExpiredError(err) || isTooLargeResourceVersionError(err) {
|
||||
r.setIsLastSyncResourceVersionUnavailable(true)
|
||||
// Retry immediately if the resource version used to list is unavailable.
|
||||
// The pager already falls back to full list if paginated list calls fail due to an "Expired" error on
|
||||
// continuation pages, but the pager might not be enabled, the full list might fail because the
|
||||
// resource version it is listing at is expired or the cache may not yet be synced to the provided
|
||||
// resource version. So we need to fallback to resourceVersion="" in all to recover and ensure
|
||||
// the reflector makes forward progress.
|
||||
list, paginatedResult, err = pager.List(context.Background(), metav1.ListOptions{ResourceVersion: r.relistResourceVersion()})
|
||||
}
|
||||
close(listCh)
|
||||
}()
|
||||
select {
|
||||
case <-stopCh:
|
||||
return nil
|
||||
case r := <-panicCh:
|
||||
panic(r)
|
||||
case <-listCh:
|
||||
}
|
||||
initTrace.Step("Objects listed", trace.Field{Key: "error", Value: err})
|
||||
if err != nil {
|
||||
klog.Warningf("%s: failed to list %v: %v", r.name, r.expectedTypeName, err)
|
||||
return fmt.Errorf("failed to list %v: %w", r.expectedTypeName, err)
|
||||
}
|
||||
|
||||
// We check if the list was paginated and if so set the paginatedResult based on that.
|
||||
// However, we want to do that only for the initial list (which is the only case
|
||||
// when we set ResourceVersion="0"). The reasoning behind it is that later, in some
|
||||
// situations we may force listing directly from etcd (by setting ResourceVersion="")
|
||||
// which will return paginated result, even if watch cache is enabled. However, in
|
||||
// that case, we still want to prefer sending requests to watch cache if possible.
|
||||
//
|
||||
// Paginated result returned for request with ResourceVersion="0" mean that watch
|
||||
// cache is disabled and there are a lot of objects of a given type. In such case,
|
||||
// there is no need to prefer listing from watch cache.
|
||||
if options.ResourceVersion == "0" && paginatedResult {
|
||||
r.paginatedResult = true
|
||||
}
|
||||
|
||||
r.setIsLastSyncResourceVersionUnavailable(false) // list was successful
|
||||
listMetaInterface, err := meta.ListAccessor(list)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to understand list result %#v: %v", list, err)
|
||||
}
|
||||
resourceVersion = listMetaInterface.GetResourceVersion()
|
||||
initTrace.Step("Resource version extracted")
|
||||
items, err := meta.ExtractList(list)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to understand list result %#v (%v)", list, err)
|
||||
}
|
||||
initTrace.Step("Objects extracted")
|
||||
if err := r.syncWith(items, resourceVersion); err != nil {
|
||||
return fmt.Errorf("unable to sync list result: %v", err)
|
||||
}
|
||||
initTrace.Step("SyncWith done")
|
||||
r.setLastSyncResourceVersion(resourceVersion)
|
||||
initTrace.Step("Resource version updated")
|
||||
return nil
|
||||
}
|
||||
|
||||
// syncWith replaces the store's items with the given list.
|
||||
func (r *Reflector) syncWith(items []runtime.Object, resourceVersion string) error {
|
||||
found := make([]interface{}, 0, len(items))
|
||||
@@ -456,8 +469,19 @@ func (r *Reflector) syncWith(items []runtime.Object, resourceVersion string) err
|
||||
return r.store.Replace(found, resourceVersion)
|
||||
}
|
||||
|
||||
// watchHandler watches w and keeps *resourceVersion up to date.
|
||||
func (r *Reflector) watchHandler(start time.Time, w watch.Interface, resourceVersion *string, errc chan error, stopCh <-chan struct{}) error {
|
||||
// watchHandler watches w and sets setLastSyncResourceVersion
|
||||
func watchHandler(start time.Time,
|
||||
w watch.Interface,
|
||||
store Store,
|
||||
expectedType reflect.Type,
|
||||
expectedGVK *schema.GroupVersionKind,
|
||||
name string,
|
||||
expectedTypeName string,
|
||||
setLastSyncResourceVersion func(string),
|
||||
clock clock.Clock,
|
||||
errc chan error,
|
||||
stopCh <-chan struct{},
|
||||
) error {
|
||||
eventCount := 0
|
||||
|
||||
// Stopping the watcher should be idempotent and if we return from this function there's no way
|
||||
@@ -478,62 +502,61 @@ loop:
|
||||
if event.Type == watch.Error {
|
||||
return apierrors.FromObject(event.Object)
|
||||
}
|
||||
if r.expectedType != nil {
|
||||
if e, a := r.expectedType, reflect.TypeOf(event.Object); e != a {
|
||||
utilruntime.HandleError(fmt.Errorf("%s: expected type %v, but watch event object had type %v", r.name, e, a))
|
||||
if expectedType != nil {
|
||||
if e, a := expectedType, reflect.TypeOf(event.Object); e != a {
|
||||
utilruntime.HandleError(fmt.Errorf("%s: expected type %v, but watch event object had type %v", name, e, a))
|
||||
continue
|
||||
}
|
||||
}
|
||||
if r.expectedGVK != nil {
|
||||
if e, a := *r.expectedGVK, event.Object.GetObjectKind().GroupVersionKind(); e != a {
|
||||
utilruntime.HandleError(fmt.Errorf("%s: expected gvk %v, but watch event object had gvk %v", r.name, e, a))
|
||||
if expectedGVK != nil {
|
||||
if e, a := *expectedGVK, event.Object.GetObjectKind().GroupVersionKind(); e != a {
|
||||
utilruntime.HandleError(fmt.Errorf("%s: expected gvk %v, but watch event object had gvk %v", name, e, a))
|
||||
continue
|
||||
}
|
||||
}
|
||||
meta, err := meta.Accessor(event.Object)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", r.name, event))
|
||||
utilruntime.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", name, event))
|
||||
continue
|
||||
}
|
||||
newResourceVersion := meta.GetResourceVersion()
|
||||
resourceVersion := meta.GetResourceVersion()
|
||||
switch event.Type {
|
||||
case watch.Added:
|
||||
err := r.store.Add(event.Object)
|
||||
err := store.Add(event.Object)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("%s: unable to add watch event object (%#v) to store: %v", r.name, event.Object, err))
|
||||
utilruntime.HandleError(fmt.Errorf("%s: unable to add watch event object (%#v) to store: %v", name, event.Object, err))
|
||||
}
|
||||
case watch.Modified:
|
||||
err := r.store.Update(event.Object)
|
||||
err := store.Update(event.Object)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("%s: unable to update watch event object (%#v) to store: %v", r.name, event.Object, err))
|
||||
utilruntime.HandleError(fmt.Errorf("%s: unable to update watch event object (%#v) to store: %v", name, event.Object, err))
|
||||
}
|
||||
case watch.Deleted:
|
||||
// TODO: Will any consumers need access to the "last known
|
||||
// state", which is passed in event.Object? If so, may need
|
||||
// to change this.
|
||||
err := r.store.Delete(event.Object)
|
||||
err := store.Delete(event.Object)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("%s: unable to delete watch event object (%#v) from store: %v", r.name, event.Object, err))
|
||||
utilruntime.HandleError(fmt.Errorf("%s: unable to delete watch event object (%#v) from store: %v", name, event.Object, err))
|
||||
}
|
||||
case watch.Bookmark:
|
||||
// A `Bookmark` means watch has synced here, just update the resourceVersion
|
||||
default:
|
||||
utilruntime.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", r.name, event))
|
||||
utilruntime.HandleError(fmt.Errorf("%s: unable to understand watch event %#v", name, event))
|
||||
}
|
||||
*resourceVersion = newResourceVersion
|
||||
r.setLastSyncResourceVersion(newResourceVersion)
|
||||
if rvu, ok := r.store.(ResourceVersionUpdater); ok {
|
||||
rvu.UpdateResourceVersion(newResourceVersion)
|
||||
setLastSyncResourceVersion(resourceVersion)
|
||||
if rvu, ok := store.(ResourceVersionUpdater); ok {
|
||||
rvu.UpdateResourceVersion(resourceVersion)
|
||||
}
|
||||
eventCount++
|
||||
}
|
||||
}
|
||||
|
||||
watchDuration := r.clock.Since(start)
|
||||
watchDuration := clock.Since(start)
|
||||
if watchDuration < 1*time.Second && eventCount == 0 {
|
||||
return fmt.Errorf("very short watch: %s: Unexpected watch close - watch lasted less than a second and no items received", r.name)
|
||||
return fmt.Errorf("very short watch: %s: Unexpected watch close - watch lasted less than a second and no items received", name)
|
||||
}
|
||||
klog.V(4).Infof("%s: Watch close - %v total %v items received", r.name, r.expectedTypeName, eventCount)
|
||||
klog.V(4).Infof("%s: Watch close - %v total %v items received", name, expectedTypeName, eventCount)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
84
tools/cache/reflector_test.go
vendored
84
tools/cache/reflector_test.go
vendored
@@ -138,8 +138,7 @@ func TestReflectorWatchHandlerError(t *testing.T) {
|
||||
go func() {
|
||||
fw.Stop()
|
||||
}()
|
||||
var resumeRV string
|
||||
err := g.watchHandler(time.Now(), fw, &resumeRV, nevererrc, wait.NeverStop)
|
||||
err := watchHandler(time.Now(), fw, s, g.expectedType, g.expectedGVK, g.name, g.expectedTypeName, g.setLastSyncResourceVersion, g.clock, nevererrc, wait.NeverStop)
|
||||
if err == nil {
|
||||
t.Errorf("unexpected non-error")
|
||||
}
|
||||
@@ -158,8 +157,7 @@ func TestReflectorWatchHandler(t *testing.T) {
|
||||
fw.Add(&v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "baz", ResourceVersion: "32"}})
|
||||
fw.Stop()
|
||||
}()
|
||||
var resumeRV string
|
||||
err := g.watchHandler(time.Now(), fw, &resumeRV, nevererrc, wait.NeverStop)
|
||||
err := watchHandler(time.Now(), fw, s, g.expectedType, g.expectedGVK, g.name, g.expectedTypeName, g.setLastSyncResourceVersion, g.clock, nevererrc, wait.NeverStop)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
}
|
||||
@@ -191,7 +189,7 @@ func TestReflectorWatchHandler(t *testing.T) {
|
||||
}
|
||||
|
||||
// RV should send the last version we see.
|
||||
if e, a := "32", resumeRV; e != a {
|
||||
if e, a := "32", g.LastSyncResourceVersion(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
@@ -205,10 +203,9 @@ func TestReflectorStopWatch(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 0)
|
||||
fw := watch.NewFake()
|
||||
var resumeRV string
|
||||
stopWatch := make(chan struct{}, 1)
|
||||
stopWatch <- struct{}{}
|
||||
err := g.watchHandler(time.Now(), fw, &resumeRV, nevererrc, stopWatch)
|
||||
err := watchHandler(time.Now(), fw, s, g.expectedType, g.expectedGVK, g.name, g.expectedTypeName, g.setLastSyncResourceVersion, g.clock, nevererrc, stopWatch)
|
||||
if err != errorStopRequested {
|
||||
t.Errorf("expected stop error, got %q", err)
|
||||
}
|
||||
@@ -490,6 +487,79 @@ func TestBackoffOnTooManyRequests(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRetryInternalError(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
maxInternalDuration time.Duration
|
||||
rewindTime int
|
||||
wantRetries int
|
||||
}{
|
||||
{
|
||||
name: "retries off",
|
||||
maxInternalDuration: time.Duration(0),
|
||||
wantRetries: 0,
|
||||
},
|
||||
{
|
||||
name: "retries on, all calls fail",
|
||||
maxInternalDuration: time.Second * 30,
|
||||
wantRetries: 31,
|
||||
},
|
||||
{
|
||||
name: "retries on, one call successful",
|
||||
maxInternalDuration: time.Second * 30,
|
||||
rewindTime: 10,
|
||||
wantRetries: 40,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
err := apierrors.NewInternalError(fmt.Errorf("etcdserver: no leader"))
|
||||
fakeClock := testingclock.NewFakeClock(time.Now())
|
||||
bm := &fakeBackoff{clock: fakeClock}
|
||||
|
||||
counter := 0
|
||||
|
||||
lw := &testLW{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
return &v1.PodList{ListMeta: metav1.ListMeta{ResourceVersion: "1"}}, nil
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
counter = counter + 1
|
||||
t.Logf("Counter: %v", counter)
|
||||
if counter == tc.rewindTime {
|
||||
t.Logf("Rewinding")
|
||||
fakeClock.Step(time.Minute)
|
||||
}
|
||||
|
||||
fakeClock.Step(time.Second)
|
||||
w := watch.NewFakeWithChanSize(1, false)
|
||||
status := err.Status()
|
||||
w.Error(&status)
|
||||
return w, nil
|
||||
},
|
||||
}
|
||||
|
||||
r := &Reflector{
|
||||
name: "test-reflector",
|
||||
listerWatcher: lw,
|
||||
store: NewFIFO(MetaNamespaceKeyFunc),
|
||||
initConnBackoffManager: bm,
|
||||
clock: fakeClock,
|
||||
watchErrorHandler: WatchErrorHandler(DefaultWatchErrorHandler),
|
||||
}
|
||||
|
||||
r.MaxInternalErrorRetryDuration = tc.maxInternalDuration
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
r.ListAndWatch(stopCh)
|
||||
close(stopCh)
|
||||
|
||||
if counter-1 != tc.wantRetries {
|
||||
t.Errorf("%v unexpected number of retries: %d", tc, counter-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestReflectorResync(t *testing.T) {
|
||||
iteration := 0
|
||||
stopCh := make(chan struct{})
|
||||
|
||||
78
tools/cache/retry_with_deadline.go
vendored
Normal file
78
tools/cache/retry_with_deadline.go
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright 2022 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 cache
|
||||
|
||||
import (
|
||||
"k8s.io/utils/clock"
|
||||
"time"
|
||||
)
|
||||
|
||||
type RetryWithDeadline interface {
|
||||
After(error)
|
||||
ShouldRetry() bool
|
||||
}
|
||||
|
||||
type retryWithDeadlineImpl struct {
|
||||
firstErrorTime time.Time
|
||||
lastErrorTime time.Time
|
||||
maxRetryDuration time.Duration
|
||||
minResetPeriod time.Duration
|
||||
isRetryable func(error) bool
|
||||
clock clock.Clock
|
||||
}
|
||||
|
||||
func NewRetryWithDeadline(maxRetryDuration, minResetPeriod time.Duration, isRetryable func(error) bool, clock clock.Clock) RetryWithDeadline {
|
||||
return &retryWithDeadlineImpl{
|
||||
firstErrorTime: time.Time{},
|
||||
lastErrorTime: time.Time{},
|
||||
maxRetryDuration: maxRetryDuration,
|
||||
minResetPeriod: minResetPeriod,
|
||||
isRetryable: isRetryable,
|
||||
clock: clock,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *retryWithDeadlineImpl) reset() {
|
||||
r.firstErrorTime = time.Time{}
|
||||
r.lastErrorTime = time.Time{}
|
||||
}
|
||||
|
||||
func (r *retryWithDeadlineImpl) After(err error) {
|
||||
if r.isRetryable(err) {
|
||||
if r.clock.Now().Sub(r.lastErrorTime) >= r.minResetPeriod {
|
||||
r.reset()
|
||||
}
|
||||
|
||||
if r.firstErrorTime.IsZero() {
|
||||
r.firstErrorTime = r.clock.Now()
|
||||
}
|
||||
r.lastErrorTime = r.clock.Now()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *retryWithDeadlineImpl) ShouldRetry() bool {
|
||||
if r.maxRetryDuration <= time.Duration(0) {
|
||||
return false
|
||||
}
|
||||
|
||||
if r.clock.Now().Sub(r.firstErrorTime) <= r.maxRetryDuration {
|
||||
return true
|
||||
}
|
||||
|
||||
r.reset()
|
||||
return false
|
||||
}
|
||||
143
tools/cache/retry_with_deadline_test.go
vendored
Normal file
143
tools/cache/retry_with_deadline_test.go
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
Copyright 2022 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 cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
testingclock "k8s.io/utils/clock/testing"
|
||||
)
|
||||
|
||||
type retryScenarioStep struct {
|
||||
clockStep time.Duration
|
||||
err error
|
||||
wantRetry bool
|
||||
}
|
||||
|
||||
func TestRetryWithDeadline(t *testing.T) {
|
||||
internalError := apierrors.NewInternalError(fmt.Errorf("etcdserver: no leader"))
|
||||
otherError := fmt.Errorf("some other error")
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
duration time.Duration
|
||||
reset time.Duration
|
||||
isRetryable func(error) bool
|
||||
scenario []retryScenarioStep
|
||||
}{
|
||||
{
|
||||
name: "Never retry when duration is zero",
|
||||
duration: time.Duration(0),
|
||||
reset: time.Second * 30,
|
||||
isRetryable: func(err error) bool { return false },
|
||||
scenario: []retryScenarioStep{
|
||||
{
|
||||
clockStep: time.Second * 1,
|
||||
err: nil,
|
||||
wantRetry: false,
|
||||
},
|
||||
{
|
||||
clockStep: time.Second * 0,
|
||||
err: internalError,
|
||||
wantRetry: false,
|
||||
},
|
||||
{
|
||||
clockStep: time.Second * 1,
|
||||
err: otherError,
|
||||
wantRetry: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Retry when internal error happens only within duration",
|
||||
duration: time.Second * 1,
|
||||
reset: time.Second * 30,
|
||||
isRetryable: apierrors.IsInternalError,
|
||||
scenario: []retryScenarioStep{
|
||||
{
|
||||
clockStep: time.Second * 1,
|
||||
err: internalError,
|
||||
wantRetry: true,
|
||||
},
|
||||
{
|
||||
clockStep: time.Second * 1,
|
||||
err: internalError,
|
||||
wantRetry: true,
|
||||
},
|
||||
{
|
||||
clockStep: time.Second * 1,
|
||||
err: internalError,
|
||||
wantRetry: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Don't retry when other error happens",
|
||||
duration: time.Second * 1,
|
||||
reset: time.Second * 30,
|
||||
isRetryable: apierrors.IsInternalError,
|
||||
scenario: []retryScenarioStep{
|
||||
{
|
||||
clockStep: time.Second * 1,
|
||||
err: otherError,
|
||||
wantRetry: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Ignore other errors for retries",
|
||||
duration: time.Second * 1,
|
||||
reset: time.Second * 30,
|
||||
isRetryable: apierrors.IsInternalError,
|
||||
scenario: []retryScenarioStep{
|
||||
{
|
||||
clockStep: time.Second * 1,
|
||||
err: internalError,
|
||||
wantRetry: true,
|
||||
},
|
||||
{
|
||||
clockStep: time.Second * 0,
|
||||
err: otherError,
|
||||
wantRetry: true,
|
||||
},
|
||||
{
|
||||
clockStep: time.Second * 1,
|
||||
err: internalError,
|
||||
wantRetry: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
fakeClock := testingclock.NewFakeClock(time.Now())
|
||||
retry := NewRetryWithDeadline(tc.duration, tc.reset, tc.isRetryable, fakeClock)
|
||||
|
||||
for i, step := range tc.scenario {
|
||||
fakeClock.Step(step.clockStep)
|
||||
retry.After(step.err)
|
||||
result := retry.ShouldRetry()
|
||||
if result != step.wantRetry {
|
||||
t.Errorf("%v unexpected retry, step %d, result %v want %v", tc, i, result, step.wantRetry)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
tools/cache/store.go
vendored
13
tools/cache/store.go
vendored
@@ -199,8 +199,11 @@ func (c *cache) Index(indexName string, obj interface{}) ([]interface{}, error)
|
||||
return c.cacheStorage.Index(indexName, obj)
|
||||
}
|
||||
|
||||
func (c *cache) IndexKeys(indexName, indexKey string) ([]string, error) {
|
||||
return c.cacheStorage.IndexKeys(indexName, indexKey)
|
||||
// IndexKeys returns the storage keys of the stored objects whose set of
|
||||
// indexed values for the named index includes the given indexed value.
|
||||
// The returned keys are suitable to pass to GetByKey().
|
||||
func (c *cache) IndexKeys(indexName, indexedValue string) ([]string, error) {
|
||||
return c.cacheStorage.IndexKeys(indexName, indexedValue)
|
||||
}
|
||||
|
||||
// ListIndexFuncValues returns the list of generated values of an Index func
|
||||
@@ -208,8 +211,10 @@ func (c *cache) ListIndexFuncValues(indexName string) []string {
|
||||
return c.cacheStorage.ListIndexFuncValues(indexName)
|
||||
}
|
||||
|
||||
func (c *cache) ByIndex(indexName, indexKey string) ([]interface{}, error) {
|
||||
return c.cacheStorage.ByIndex(indexName, indexKey)
|
||||
// ByIndex returns the stored objects whose set of indexed values
|
||||
// for the named index includes the given indexed value.
|
||||
func (c *cache) ByIndex(indexName, indexedValue string) ([]interface{}, error) {
|
||||
return c.cacheStorage.ByIndex(indexName, indexedValue)
|
||||
}
|
||||
|
||||
func (c *cache) AddIndexers(newIndexers Indexers) error {
|
||||
|
||||
@@ -275,11 +275,11 @@ func (f *FakeControllerSource) Watch(options metav1.ListOptions) (watch.Interfac
|
||||
// clients).
|
||||
changes = append(changes, watch.Event{Type: c.Type, Object: c.Object.DeepCopyObject()})
|
||||
}
|
||||
return f.Broadcaster.WatchWithPrefix(changes), nil
|
||||
return f.Broadcaster.WatchWithPrefix(changes)
|
||||
} else if rc > f.lastRV {
|
||||
return nil, errors.New("resource version in the future not supported by this fake")
|
||||
}
|
||||
return f.Broadcaster.Watch(), nil
|
||||
return f.Broadcaster.Watch()
|
||||
}
|
||||
|
||||
// Shutdown closes the underlying broadcaster, waiting for events to be
|
||||
|
||||
4
tools/cache/thread_safe_store.go
vendored
4
tools/cache/thread_safe_store.go
vendored
@@ -47,9 +47,9 @@ type ThreadSafeStore interface {
|
||||
ListKeys() []string
|
||||
Replace(map[string]interface{}, string)
|
||||
Index(indexName string, obj interface{}) ([]interface{}, error)
|
||||
IndexKeys(indexName, indexKey string) ([]string, error)
|
||||
IndexKeys(indexName, indexedValue string) ([]string, error)
|
||||
ListIndexFuncValues(name string) []string
|
||||
ByIndex(indexName, indexKey string) ([]interface{}, error)
|
||||
ByIndex(indexName, indexedValue string) ([]interface{}, error)
|
||||
GetIndexers() Indexers
|
||||
|
||||
// AddIndexers adds more indexers to this store. If you call this after you already have data
|
||||
|
||||
@@ -51,10 +51,10 @@ func (a *PromptingAuthLoader) LoadAuth(path string) (*clientauth.Info, error) {
|
||||
// Prompt for user/pass and write a file if none exists.
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
authPtr, err := a.Prompt()
|
||||
auth := *authPtr
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
auth := *authPtr
|
||||
data, err := json.Marshal(auth)
|
||||
if err != nil {
|
||||
return &auth, err
|
||||
|
||||
@@ -160,8 +160,10 @@ func NewDefaultClientConfigLoadingRules() *ClientConfigLoadingRules {
|
||||
|
||||
// Load starts by running the MigrationRules and then
|
||||
// takes the loading rules and returns a Config object based on following rules.
|
||||
// if the ExplicitPath, return the unmerged explicit file
|
||||
// Otherwise, return a merged config based on the Precedence slice
|
||||
//
|
||||
// if the ExplicitPath, return the unmerged explicit file
|
||||
// Otherwise, return a merged config based on the Precedence slice
|
||||
//
|
||||
// A missing ExplicitPath file produces an error. Empty filenames or other missing files are ignored.
|
||||
// Read errors or files with non-deserializable content produce errors.
|
||||
// The first file to set a particular map key wins and map key's value is never changed.
|
||||
|
||||
@@ -204,8 +204,19 @@ func ConfirmUsable(config clientcmdapi.Config, passedContextName string) error {
|
||||
|
||||
if exists {
|
||||
validationErrors = append(validationErrors, validateContext(contextName, *context, config)...)
|
||||
validationErrors = append(validationErrors, validateAuthInfo(context.AuthInfo, *config.AuthInfos[context.AuthInfo])...)
|
||||
validationErrors = append(validationErrors, validateClusterInfo(context.Cluster, *config.Clusters[context.Cluster])...)
|
||||
|
||||
// Default to empty users and clusters and let the validation function report an error.
|
||||
authInfo := config.AuthInfos[context.AuthInfo]
|
||||
if authInfo == nil {
|
||||
authInfo = &clientcmdapi.AuthInfo{}
|
||||
}
|
||||
validationErrors = append(validationErrors, validateAuthInfo(context.AuthInfo, *authInfo)...)
|
||||
|
||||
cluster := config.Clusters[context.Cluster]
|
||||
if cluster == nil {
|
||||
cluster = &clientcmdapi.Cluster{}
|
||||
}
|
||||
validationErrors = append(validationErrors, validateClusterInfo(context.Cluster, *cluster)...)
|
||||
}
|
||||
|
||||
return newErrConfigurationInvalid(validationErrors)
|
||||
|
||||
@@ -65,6 +65,42 @@ func TestConfirmUsableBadInfoButOkConfig(t *testing.T) {
|
||||
badValidation.testConfig(t)
|
||||
}
|
||||
|
||||
func TestConfirmUsableMissingObjects(t *testing.T) {
|
||||
config := clientcmdapi.NewConfig()
|
||||
config.Clusters["kind-cluster"] = &clientcmdapi.Cluster{
|
||||
Server: "anything",
|
||||
}
|
||||
config.AuthInfos["kind-user"] = &clientcmdapi.AuthInfo{
|
||||
Token: "any-value",
|
||||
}
|
||||
config.Contexts["missing-user"] = &clientcmdapi.Context{
|
||||
Cluster: "kind-cluster",
|
||||
AuthInfo: "garbage",
|
||||
}
|
||||
config.Contexts["missing-cluster"] = &clientcmdapi.Context{
|
||||
Cluster: "garbage",
|
||||
AuthInfo: "kind-user",
|
||||
}
|
||||
|
||||
missingUser := configValidationTest{
|
||||
config: config,
|
||||
expectedErrorSubstring: []string{
|
||||
`user "garbage" was not found for context "missing-user"`,
|
||||
},
|
||||
}
|
||||
missingUser.testConfirmUsable("missing-user", t)
|
||||
missingUser.testConfig(t)
|
||||
|
||||
missingCluster := configValidationTest{
|
||||
config: config,
|
||||
expectedErrorSubstring: []string{
|
||||
`cluster "garbage" was not found for context "missing-cluster"`,
|
||||
},
|
||||
}
|
||||
missingCluster.testConfirmUsable("missing-cluster", t)
|
||||
missingCluster.testConfig(t)
|
||||
}
|
||||
|
||||
func TestConfirmUsableBadInfoConfig(t *testing.T) {
|
||||
config := clientcmdapi.NewConfig()
|
||||
config.Clusters["missing ca"] = &clientcmdapi.Cluster{
|
||||
|
||||
@@ -307,7 +307,15 @@ func (e *eventBroadcasterImpl) StartStructuredLogging(verbosity klog.Level) func
|
||||
// StartEventWatcher starts sending events received from this EventBroadcaster to the given event handler function.
|
||||
// The return value is used to stop recording
|
||||
func (e *eventBroadcasterImpl) StartEventWatcher(eventHandler func(event runtime.Object)) func() {
|
||||
watcher := e.Watch()
|
||||
watcher, err := e.Watch()
|
||||
if err != nil {
|
||||
klog.Errorf("Unable start event watcher: '%v' (will not retry!)", err)
|
||||
// TODO: Rewrite the function signature to return an error, for
|
||||
// now just return a no-op function
|
||||
return func() {
|
||||
klog.Error("The event watcher failed to start")
|
||||
}
|
||||
}
|
||||
go func() {
|
||||
defer utilruntime.HandleCrash()
|
||||
for {
|
||||
|
||||
@@ -161,7 +161,7 @@ type LeaderElectionConfig struct {
|
||||
// lifecycle events of the LeaderElector. These are invoked asynchronously.
|
||||
//
|
||||
// possible future callbacks:
|
||||
// * OnChallenge()
|
||||
// - OnChallenge()
|
||||
type LeaderCallbacks struct {
|
||||
// OnStartedLeading is called when a LeaderElector client starts leading
|
||||
OnStartedLeading func(context.Context)
|
||||
|
||||
@@ -62,18 +62,18 @@ type ForwardedPort struct {
|
||||
}
|
||||
|
||||
/*
|
||||
valid port specifications:
|
||||
valid port specifications:
|
||||
|
||||
5000
|
||||
- forwards from localhost:5000 to pod:5000
|
||||
5000
|
||||
- forwards from localhost:5000 to pod:5000
|
||||
|
||||
8888:5000
|
||||
- forwards from localhost:8888 to pod:5000
|
||||
8888:5000
|
||||
- forwards from localhost:8888 to pod:5000
|
||||
|
||||
0:5000
|
||||
:5000
|
||||
- selects a random available local port,
|
||||
forwards from localhost:<random port> to pod:5000
|
||||
0:5000
|
||||
:5000
|
||||
- selects a random available local port,
|
||||
forwards from localhost:<random port> to pod:5000
|
||||
*/
|
||||
func parsePorts(ports []string) ([]ForwardedPort, error) {
|
||||
var forwards []ForwardedPort
|
||||
|
||||
@@ -92,7 +92,7 @@ type EventRecorder interface {
|
||||
// Event constructs an event from the given information and puts it in the queue for sending.
|
||||
// 'object' is the object this event is about. Event will make a reference-- or you may also
|
||||
// pass a reference to the object directly.
|
||||
// 'type' of this event, and can be one of Normal, Warning. New types could be added in future
|
||||
// 'eventtype' of this event, and can be one of Normal, Warning. New types could be added in future
|
||||
// 'reason' is the reason this event is generated. 'reason' should be short and unique; it
|
||||
// should be in UpperCamelCase format (starting with a capital letter). "reason" will be used
|
||||
// to automate handling of events, so imagine people writing switch statements to handle them.
|
||||
@@ -298,7 +298,10 @@ func (e *eventBroadcasterImpl) StartStructuredLogging(verbosity klog.Level) watc
|
||||
// StartEventWatcher starts sending events received from this EventBroadcaster to the given event handler function.
|
||||
// The return value can be ignored or used to stop recording, if desired.
|
||||
func (e *eventBroadcasterImpl) StartEventWatcher(eventHandler func(*v1.Event)) watch.Interface {
|
||||
watcher := e.Watch()
|
||||
watcher, err := e.Watch()
|
||||
if err != nil {
|
||||
klog.Errorf("Unable start event watcher: '%v' (will not retry!)", err)
|
||||
}
|
||||
go func() {
|
||||
defer utilruntime.HandleCrash()
|
||||
for watchEvent := range watcher.ResultChan() {
|
||||
@@ -346,7 +349,12 @@ func (recorder *recorderImpl) generateEvent(object runtime.Object, annotations m
|
||||
// when we go to shut down this broadcaster. Just drop events if we get overloaded,
|
||||
// and log an error if that happens (we've configured the broadcaster to drop
|
||||
// outgoing events anyway).
|
||||
if sent := recorder.ActionOrDrop(watch.Added, event); !sent {
|
||||
sent, err := recorder.ActionOrDrop(watch.Added, event)
|
||||
if err != nil {
|
||||
klog.Errorf("unable to record event: %v (will not retry!)", err)
|
||||
return
|
||||
}
|
||||
if !sent {
|
||||
klog.Errorf("unable to record event: too many queued events, dropped event %#v", event)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,10 +235,10 @@ type aggregateRecord struct {
|
||||
// EventAggregate checks if a similar event has been seen according to the
|
||||
// aggregation configuration (max events, max interval, etc) and returns:
|
||||
//
|
||||
// - The (potentially modified) event that should be created
|
||||
// - The cache key for the event, for correlation purposes. This will be set to
|
||||
// the full key for normal events, and to the result of
|
||||
// EventAggregatorMessageFunc for aggregate events.
|
||||
// - The (potentially modified) event that should be created
|
||||
// - The cache key for the event, for correlation purposes. This will be set to
|
||||
// the full key for normal events, and to the result of
|
||||
// EventAggregatorMessageFunc for aggregate events.
|
||||
func (e *EventAggregator) EventAggregate(newEvent *v1.Event) (*v1.Event, string) {
|
||||
now := metav1.NewTime(e.clock.Now())
|
||||
var record aggregateRecord
|
||||
@@ -427,14 +427,14 @@ type EventCorrelateResult struct {
|
||||
// prior to interacting with the API server to record the event.
|
||||
//
|
||||
// The default behavior is as follows:
|
||||
// * Aggregation is performed if a similar event is recorded 10 times
|
||||
// - Aggregation is performed if a similar event is recorded 10 times
|
||||
// in a 10 minute rolling interval. A similar event is an event that varies only by
|
||||
// the Event.Message field. Rather than recording the precise event, aggregation
|
||||
// will create a new event whose message reports that it has combined events with
|
||||
// the same reason.
|
||||
// * Events are incrementally counted if the exact same event is encountered multiple
|
||||
// - Events are incrementally counted if the exact same event is encountered multiple
|
||||
// times.
|
||||
// * A source may burst 25 events about an object, but has a refill rate budget
|
||||
// - A source may burst 25 events about an object, but has a refill rate budget
|
||||
// per object of 1 event every 5 minutes to control long-tail of spam.
|
||||
func NewEventCorrelator(clock clock.PassiveClock) *EventCorrelator {
|
||||
cacheSize := maxLruCacheEntries
|
||||
|
||||
@@ -101,7 +101,9 @@ func UntilWithoutRetry(ctx context.Context, watcher watch.Interface, conditions
|
||||
// It guarantees you to see all events and in the order they happened.
|
||||
// Due to this guarantee there is no way it can deal with 'Resource version too old error'. It will fail in this case.
|
||||
// (See `UntilWithSync` if you'd prefer to recover from all the errors including RV too old by re-listing
|
||||
// those items. In normal code you should care about being level driven so you'd not care about not seeing all the edges.)
|
||||
//
|
||||
// those items. In normal code you should care about being level driven so you'd not care about not seeing all the edges.)
|
||||
//
|
||||
// The most frequent usage for Until would be a test where you want to verify exact order of events ("edges").
|
||||
func Until(ctx context.Context, initialResourceVersion string, watcherClient cache.Watcher, conditions ...ConditionFunc) (*watch.Event, error) {
|
||||
w, err := NewRetryWatcher(initialResourceVersion, watcherClient)
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package transport
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -36,6 +37,11 @@ type tlsTransportCache struct {
|
||||
transports map[tlsCacheKey]*http.Transport
|
||||
}
|
||||
|
||||
// DialerStopCh is stop channel that is passed down to dynamic cert dialer.
|
||||
// It's exposed as variable for testing purposes to avoid testing for goroutine
|
||||
// leakages.
|
||||
var DialerStopCh = wait.NeverStop
|
||||
|
||||
const idleConnsPerHost = 25
|
||||
|
||||
var tlsCache = &tlsTransportCache{transports: make(map[tlsCacheKey]*http.Transport)}
|
||||
@@ -50,6 +56,9 @@ type tlsCacheKey struct {
|
||||
serverName string
|
||||
nextProtos string
|
||||
disableCompression bool
|
||||
// these functions are wrapped to allow them to be used as map keys
|
||||
getCert *GetCertHolder
|
||||
dial *DialHolder
|
||||
}
|
||||
|
||||
func (t tlsCacheKey) String() string {
|
||||
@@ -57,7 +66,8 @@ func (t tlsCacheKey) String() string {
|
||||
if len(t.keyData) > 0 {
|
||||
keyText = "<redacted>"
|
||||
}
|
||||
return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, serverName:%s, disableCompression:%t", t.insecure, t.caData, t.certData, keyText, t.serverName, t.disableCompression)
|
||||
return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, serverName:%s, disableCompression:%t, getCert:%p, dial:%p",
|
||||
t.insecure, t.caData, t.certData, keyText, t.serverName, t.disableCompression, t.getCert, t.dial)
|
||||
}
|
||||
|
||||
func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) {
|
||||
@@ -87,8 +97,10 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) {
|
||||
return http.DefaultTransport, nil
|
||||
}
|
||||
|
||||
dial := config.Dial
|
||||
if dial == nil {
|
||||
var dial func(ctx context.Context, network, address string) (net.Conn, error)
|
||||
if config.Dial != nil {
|
||||
dial = config.Dial
|
||||
} else {
|
||||
dial = (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
@@ -101,7 +113,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) {
|
||||
dynamicCertDialer := certRotatingDialer(tlsConfig.GetClientCertificate, dial)
|
||||
tlsConfig.GetClientCertificate = dynamicCertDialer.GetClientCertificate
|
||||
dial = dynamicCertDialer.connDialer.DialContext
|
||||
go dynamicCertDialer.Run(wait.NeverStop)
|
||||
go dynamicCertDialer.Run(DialerStopCh)
|
||||
}
|
||||
|
||||
proxy := http.ProxyFromEnvironment
|
||||
@@ -133,10 +145,18 @@ func tlsConfigKey(c *Config) (tlsCacheKey, bool, error) {
|
||||
return tlsCacheKey{}, false, err
|
||||
}
|
||||
|
||||
if c.TLS.GetCert != nil || c.Dial != nil || c.Proxy != nil {
|
||||
if c.Proxy != nil {
|
||||
// cannot determine equality for functions
|
||||
return tlsCacheKey{}, false, nil
|
||||
}
|
||||
if c.Dial != nil && c.DialHolder == nil {
|
||||
// cannot determine equality for dial function that doesn't have non-nil DialHolder set as well
|
||||
return tlsCacheKey{}, false, nil
|
||||
}
|
||||
if c.TLS.GetCert != nil && c.TLS.GetCertHolder == nil {
|
||||
// cannot determine equality for getCert function that doesn't have non-nil GetCertHolder set as well
|
||||
return tlsCacheKey{}, false, nil
|
||||
}
|
||||
|
||||
k := tlsCacheKey{
|
||||
insecure: c.TLS.Insecure,
|
||||
@@ -144,6 +164,8 @@ func tlsConfigKey(c *Config) (tlsCacheKey, bool, error) {
|
||||
serverName: c.TLS.ServerName,
|
||||
nextProtos: strings.Join(c.TLS.NextProtos, ","),
|
||||
disableCompression: c.DisableCompression,
|
||||
getCert: c.TLS.GetCertHolder,
|
||||
dial: c.DialHolder,
|
||||
}
|
||||
|
||||
if c.TLS.ReloadTLSFiles {
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -58,16 +59,24 @@ func TestTLSConfigKey(t *testing.T) {
|
||||
t.Errorf("Expected identical cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB)
|
||||
continue
|
||||
}
|
||||
if keyA != (tlsCacheKey{}) {
|
||||
t.Errorf("Expected empty cache keys for %q and %q, got:\n\t%s\n\t%s", nameA, nameB, keyA, keyB)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure config fields that affect the tls config affect the cache key
|
||||
dialer := net.Dialer{}
|
||||
getCert := func() (*tls.Certificate, error) { return nil, nil }
|
||||
getCertHolder := &GetCertHolder{GetCert: getCert}
|
||||
uniqueConfigurations := map[string]*Config{
|
||||
"proxy": {Proxy: func(request *http.Request) (*url.URL, error) { return nil, nil }},
|
||||
"no tls": {},
|
||||
"dialer": {Dial: dialer.DialContext},
|
||||
"dialer2": {Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil }},
|
||||
"dialer3": {Dial: dialer.DialContext, DialHolder: &DialHolder{Dial: dialer.DialContext}},
|
||||
"dialer4": {Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil }, DialHolder: &DialHolder{Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil }}},
|
||||
"insecure": {TLS: TLSConfig{Insecure: true}},
|
||||
"cadata 1": {TLS: TLSConfig{CAData: []byte{1}}},
|
||||
"cadata 2": {TLS: TLSConfig{CAData: []byte{2}}},
|
||||
@@ -128,6 +137,13 @@ func TestTLSConfigKey(t *testing.T) {
|
||||
GetCert: func() (*tls.Certificate, error) { return nil, nil },
|
||||
},
|
||||
},
|
||||
"getCert3": {
|
||||
TLS: TLSConfig{
|
||||
KeyData: []byte{1},
|
||||
GetCert: getCert,
|
||||
GetCertHolder: getCertHolder,
|
||||
},
|
||||
},
|
||||
"getCert1, key 2": {
|
||||
TLS: TLSConfig{
|
||||
KeyData: []byte{2},
|
||||
|
||||
@@ -68,7 +68,11 @@ type Config struct {
|
||||
WrapTransport WrapperFunc
|
||||
|
||||
// Dial specifies the dial function for creating unencrypted TCP connections.
|
||||
// If specified, this transport will be non-cacheable unless DialHolder is also set.
|
||||
Dial func(ctx context.Context, network, address string) (net.Conn, error)
|
||||
// DialHolder can be populated to make transport configs cacheable.
|
||||
// If specified, DialHolder.Dial must be equal to Dial.
|
||||
DialHolder *DialHolder
|
||||
|
||||
// Proxy is the proxy func to be used for all requests made by this
|
||||
// transport. If Proxy is nil, http.ProxyFromEnvironment is used. If Proxy
|
||||
@@ -78,6 +82,11 @@ type Config struct {
|
||||
Proxy func(*http.Request) (*url.URL, error)
|
||||
}
|
||||
|
||||
// DialHolder is used to make the wrapped function comparable so that it can be used as a map key.
|
||||
type DialHolder struct {
|
||||
Dial func(ctx context.Context, network, address string) (net.Conn, error)
|
||||
}
|
||||
|
||||
// ImpersonationConfig has all the available impersonation options
|
||||
type ImpersonationConfig struct {
|
||||
// UserName matches user.Info.GetName()
|
||||
@@ -143,5 +152,15 @@ type TLSConfig struct {
|
||||
// To use only http/1.1, set to ["http/1.1"].
|
||||
NextProtos []string
|
||||
|
||||
GetCert func() (*tls.Certificate, error) // Callback that returns a TLS client certificate. CertData, CertFile, KeyData and KeyFile supercede this field.
|
||||
// Callback that returns a TLS client certificate. CertData, CertFile, KeyData and KeyFile supercede this field.
|
||||
// If specified, this transport is non-cacheable unless CertHolder is populated.
|
||||
GetCert func() (*tls.Certificate, error)
|
||||
// CertHolder can be populated to make transport configs that set GetCert cacheable.
|
||||
// If set, CertHolder.GetCert must be equal to GetCert.
|
||||
GetCertHolder *GetCertHolder
|
||||
}
|
||||
|
||||
// GetCertHolder is used to make the wrapped function comparable so that it can be used as a map key.
|
||||
type GetCertHolder struct {
|
||||
GetCert func() (*tls.Certificate, error)
|
||||
}
|
||||
|
||||
@@ -491,7 +491,7 @@ func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, e
|
||||
DNSDone: func(info httptrace.DNSDoneInfo) {
|
||||
reqInfo.muTrace.Lock()
|
||||
defer reqInfo.muTrace.Unlock()
|
||||
reqInfo.DNSLookup = time.Now().Sub(dnsStart)
|
||||
reqInfo.DNSLookup = time.Since(dnsStart)
|
||||
klog.Infof("HTTP Trace: DNS Lookup for %s resolved to %v", host, info.Addrs)
|
||||
},
|
||||
// Dial
|
||||
@@ -503,7 +503,7 @@ func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, e
|
||||
ConnectDone: func(network, addr string, err error) {
|
||||
reqInfo.muTrace.Lock()
|
||||
defer reqInfo.muTrace.Unlock()
|
||||
reqInfo.Dialing = time.Now().Sub(dialStart)
|
||||
reqInfo.Dialing = time.Since(dialStart)
|
||||
if err != nil {
|
||||
klog.Infof("HTTP Trace: Dial to %s:%s failed: %v", network, addr, err)
|
||||
} else {
|
||||
@@ -517,7 +517,7 @@ func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, e
|
||||
TLSHandshakeDone: func(_ tls.ConnectionState, _ error) {
|
||||
reqInfo.muTrace.Lock()
|
||||
defer reqInfo.muTrace.Unlock()
|
||||
reqInfo.TLSHandshake = time.Now().Sub(tlsStart)
|
||||
reqInfo.TLSHandshake = time.Since(tlsStart)
|
||||
},
|
||||
// Connection (it can be DNS + Dial or just the time to get one from the connection pool)
|
||||
GetConn: func(hostPort string) {
|
||||
@@ -526,7 +526,7 @@ func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, e
|
||||
GotConn: func(info httptrace.GotConnInfo) {
|
||||
reqInfo.muTrace.Lock()
|
||||
defer reqInfo.muTrace.Unlock()
|
||||
reqInfo.GetConnection = time.Now().Sub(getConn)
|
||||
reqInfo.GetConnection = time.Since(getConn)
|
||||
reqInfo.ConnectionReused = info.Reused
|
||||
},
|
||||
// Server Processing (time since we wrote the request until first byte is received)
|
||||
@@ -538,7 +538,7 @@ func (rt *debuggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, e
|
||||
GotFirstResponseByte: func() {
|
||||
reqInfo.muTrace.Lock()
|
||||
defer reqInfo.muTrace.Unlock()
|
||||
reqInfo.ServerProcessing = time.Now().Sub(serverStart)
|
||||
reqInfo.ServerProcessing = time.Since(serverStart)
|
||||
},
|
||||
}
|
||||
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -39,6 +40,10 @@ func New(config *Config) (http.RoundTripper, error) {
|
||||
return nil, fmt.Errorf("using a custom transport with TLS certificate options or the insecure flag is not allowed")
|
||||
}
|
||||
|
||||
if !isValidHolders(config) {
|
||||
return nil, fmt.Errorf("misconfigured holder for dialer or cert callback")
|
||||
}
|
||||
|
||||
var (
|
||||
rt http.RoundTripper
|
||||
err error
|
||||
@@ -56,6 +61,26 @@ func New(config *Config) (http.RoundTripper, error) {
|
||||
return HTTPWrappersForConfig(config, rt)
|
||||
}
|
||||
|
||||
func isValidHolders(config *Config) bool {
|
||||
if config.TLS.GetCertHolder != nil {
|
||||
if config.TLS.GetCertHolder.GetCert == nil ||
|
||||
config.TLS.GetCert == nil ||
|
||||
reflect.ValueOf(config.TLS.GetCertHolder.GetCert).Pointer() != reflect.ValueOf(config.TLS.GetCert).Pointer() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if config.DialHolder != nil {
|
||||
if config.DialHolder.Dial == nil ||
|
||||
config.Dial == nil ||
|
||||
reflect.ValueOf(config.DialHolder.Dial).Pointer() != reflect.ValueOf(config.Dial).Pointer() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// TLSConfigFor returns a tls.Config that will provide the transport level security defined
|
||||
// by the provided Config. Will return nil if no transport level security is requested.
|
||||
func TLSConfigFor(c *Config) (*tls.Config, error) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
@@ -94,6 +95,13 @@ stR0Yiw0buV6DL/moUO0HIM9Bjh96HJp+LxiIS6UCdIhMPp5HoQa
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
globalGetCert := &GetCertHolder{
|
||||
GetCert: func() (*tls.Certificate, error) { return nil, nil },
|
||||
}
|
||||
globalDial := &DialHolder{
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil },
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
Config *Config
|
||||
Err bool
|
||||
@@ -255,6 +263,144 @@ func TestNew(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"nil holders and nil regular": {
|
||||
Config: &Config{
|
||||
TLS: TLSConfig{
|
||||
GetCert: nil,
|
||||
GetCertHolder: nil,
|
||||
},
|
||||
Dial: nil,
|
||||
DialHolder: nil,
|
||||
},
|
||||
Err: false,
|
||||
TLS: false,
|
||||
TLSCert: false,
|
||||
TLSErr: false,
|
||||
Default: true,
|
||||
Insecure: false,
|
||||
DefaultRoots: false,
|
||||
},
|
||||
"nil holders and non-nil regular get cert": {
|
||||
Config: &Config{
|
||||
TLS: TLSConfig{
|
||||
GetCert: func() (*tls.Certificate, error) { return nil, nil },
|
||||
GetCertHolder: nil,
|
||||
},
|
||||
Dial: nil,
|
||||
DialHolder: nil,
|
||||
},
|
||||
Err: false,
|
||||
TLS: true,
|
||||
TLSCert: true,
|
||||
TLSErr: false,
|
||||
Default: false,
|
||||
Insecure: false,
|
||||
DefaultRoots: true,
|
||||
},
|
||||
"nil holders and non-nil regular dial": {
|
||||
Config: &Config{
|
||||
TLS: TLSConfig{
|
||||
GetCert: nil,
|
||||
GetCertHolder: nil,
|
||||
},
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil },
|
||||
DialHolder: nil,
|
||||
},
|
||||
Err: false,
|
||||
TLS: true,
|
||||
TLSCert: false,
|
||||
TLSErr: false,
|
||||
Default: false,
|
||||
Insecure: false,
|
||||
DefaultRoots: true,
|
||||
},
|
||||
"non-nil dial holder and nil regular": {
|
||||
Config: &Config{
|
||||
TLS: TLSConfig{
|
||||
GetCert: nil,
|
||||
GetCertHolder: nil,
|
||||
},
|
||||
Dial: nil,
|
||||
DialHolder: &DialHolder{},
|
||||
},
|
||||
Err: true,
|
||||
},
|
||||
"non-nil cert holder and nil regular": {
|
||||
Config: &Config{
|
||||
TLS: TLSConfig{
|
||||
GetCert: nil,
|
||||
GetCertHolder: &GetCertHolder{},
|
||||
},
|
||||
Dial: nil,
|
||||
DialHolder: nil,
|
||||
},
|
||||
Err: true,
|
||||
},
|
||||
"non-nil dial holder and non-nil regular": {
|
||||
Config: &Config{
|
||||
TLS: TLSConfig{
|
||||
GetCert: nil,
|
||||
GetCertHolder: nil,
|
||||
},
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil },
|
||||
DialHolder: &DialHolder{},
|
||||
},
|
||||
Err: true,
|
||||
},
|
||||
"non-nil cert holder and non-nil regular": {
|
||||
Config: &Config{
|
||||
TLS: TLSConfig{
|
||||
GetCert: func() (*tls.Certificate, error) { return nil, nil },
|
||||
GetCertHolder: &GetCertHolder{},
|
||||
},
|
||||
Dial: nil,
|
||||
DialHolder: nil,
|
||||
},
|
||||
Err: true,
|
||||
},
|
||||
"non-nil dial holder+internal and non-nil regular": {
|
||||
Config: &Config{
|
||||
TLS: TLSConfig{
|
||||
GetCert: nil,
|
||||
GetCertHolder: nil,
|
||||
},
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil },
|
||||
DialHolder: &DialHolder{
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) { return nil, nil },
|
||||
},
|
||||
},
|
||||
Err: true,
|
||||
},
|
||||
"non-nil cert holder+internal and non-nil regular": {
|
||||
Config: &Config{
|
||||
TLS: TLSConfig{
|
||||
GetCert: func() (*tls.Certificate, error) { return nil, nil },
|
||||
GetCertHolder: &GetCertHolder{
|
||||
GetCert: func() (*tls.Certificate, error) { return nil, nil },
|
||||
},
|
||||
},
|
||||
Dial: nil,
|
||||
DialHolder: nil,
|
||||
},
|
||||
Err: true,
|
||||
},
|
||||
"non-nil holders+internal and non-nil regular with correct address": {
|
||||
Config: &Config{
|
||||
TLS: TLSConfig{
|
||||
GetCert: globalGetCert.GetCert,
|
||||
GetCertHolder: globalGetCert,
|
||||
},
|
||||
Dial: globalDial.Dial,
|
||||
DialHolder: globalDial,
|
||||
},
|
||||
Err: false,
|
||||
TLS: true,
|
||||
TLSCert: true,
|
||||
TLSErr: false,
|
||||
Default: false,
|
||||
Insecure: false,
|
||||
DefaultRoots: true,
|
||||
},
|
||||
}
|
||||
for k, testCase := range testCases {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
|
||||
@@ -27,7 +27,6 @@ import (
|
||||
|
||||
certificatesv1 "k8s.io/api/certificates/v1"
|
||||
certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
@@ -73,7 +72,7 @@ func RequestCertificate(client clientset.Interface, csrData []byte, name, signer
|
||||
case err == nil:
|
||||
return reqName, reqUID, err
|
||||
|
||||
case errors.IsAlreadyExists(err) && len(name) > 0:
|
||||
case apierrors.IsAlreadyExists(err) && len(name) > 0:
|
||||
klog.Infof("csr for this node already exists, reusing")
|
||||
req, err := get(client, name)
|
||||
if err != nil {
|
||||
@@ -346,8 +345,8 @@ func ensureCompatible(new, orig *certificatesv1.CertificateSigningRequest, priva
|
||||
// formatError preserves the type of an API message but alters the message. Expects
|
||||
// a single argument format string, and returns the wrapped error.
|
||||
func formatError(format string, err error) error {
|
||||
if s, ok := err.(errors.APIStatus); ok {
|
||||
se := &errors.StatusError{ErrStatus: s.Status()}
|
||||
if s, ok := err.(apierrors.APIStatus); ok {
|
||||
se := &apierrors.StatusError{ErrStatus: s.Status()}
|
||||
se.ErrStatus.Message = fmt.Sprintf(format, se.ErrStatus.Message)
|
||||
return se
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ func TestCloseAllRace(t *testing.T) {
|
||||
dialer.CloseAll()
|
||||
|
||||
// Expect all connections to close within 5 seconds
|
||||
for start := time.Now(); time.Now().Sub(start) < 5*time.Second; time.Sleep(10 * time.Millisecond) {
|
||||
for start := time.Now(); time.Since(start) < 5*time.Second; time.Sleep(10 * time.Millisecond) {
|
||||
// Ensure all connections were closed
|
||||
if c := atomic.LoadInt64(&conns); c == 0 {
|
||||
break
|
||||
|
||||
@@ -478,7 +478,7 @@ func isBool(s string) bool {
|
||||
return s == "true" || s == "false"
|
||||
}
|
||||
|
||||
//UnquoteExtend is almost same as strconv.Unquote(), but it support parse single quotes as a string
|
||||
// UnquoteExtend is almost same as strconv.Unquote(), but it support parse single quotes as a string
|
||||
func UnquoteExtend(s string) (string, error) {
|
||||
n := len(s)
|
||||
if n < 2 {
|
||||
|
||||
@@ -74,30 +74,30 @@ func OnError(backoff wait.Backoff, retriable func(error) bool, fn func() error)
|
||||
// backoff, and then try again. On a non-"Conflict" error, or if it retries too many times
|
||||
// and gives up, RetryOnConflict will return an error to the caller.
|
||||
//
|
||||
// err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
// // Fetch the resource here; you need to refetch it on every try, since
|
||||
// // if you got a conflict on the last update attempt then you need to get
|
||||
// // the current version before making your own changes.
|
||||
// pod, err := c.Pods("mynamespace").Get(name, metav1.GetOptions{})
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
// // Fetch the resource here; you need to refetch it on every try, since
|
||||
// // if you got a conflict on the last update attempt then you need to get
|
||||
// // the current version before making your own changes.
|
||||
// pod, err := c.Pods("mynamespace").Get(name, metav1.GetOptions{})
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// // Make whatever updates to the resource are needed
|
||||
// pod.Status.Phase = v1.PodFailed
|
||||
// // Make whatever updates to the resource are needed
|
||||
// pod.Status.Phase = v1.PodFailed
|
||||
//
|
||||
// // Try to update
|
||||
// _, err = c.Pods("mynamespace").UpdateStatus(pod)
|
||||
// // You have to return err itself here (not wrapped inside another error)
|
||||
// // so that RetryOnConflict can identify it correctly.
|
||||
// return err
|
||||
// })
|
||||
// if err != nil {
|
||||
// // May be conflict if max retries were hit, or may be something unrelated
|
||||
// // like permissions or a network error
|
||||
// return err
|
||||
// }
|
||||
// ...
|
||||
// // Try to update
|
||||
// _, err = c.Pods("mynamespace").UpdateStatus(pod)
|
||||
// // You have to return err itself here (not wrapped inside another error)
|
||||
// // so that RetryOnConflict can identify it correctly.
|
||||
// return err
|
||||
// })
|
||||
// if err != nil {
|
||||
// // May be conflict if max retries were hit, or may be something unrelated
|
||||
// // like permissions or a network error
|
||||
// return err
|
||||
// }
|
||||
// ...
|
||||
//
|
||||
// TODO: Make Backoff an interface?
|
||||
func RetryOnConflict(backoff wait.Backoff, fn func() error) error {
|
||||
|
||||
@@ -42,8 +42,9 @@ type FakeOpenAPIServer struct {
|
||||
// API server.
|
||||
//
|
||||
// specsPath - Give a path to some test data organized so that each GroupVersion
|
||||
// has its own OpenAPI V3 JSON file.
|
||||
// i.e. apps/v1beta1 is stored in <specsPath>/apps/v1beta1.json
|
||||
//
|
||||
// has its own OpenAPI V3 JSON file.
|
||||
// i.e. apps/v1beta1 is stored in <specsPath>/apps/v1beta1.json
|
||||
func NewFakeOpenAPIV3Server(specsPath string) (*FakeOpenAPIServer, error) {
|
||||
mux := &testMux{
|
||||
counts: map[string]int{},
|
||||
|
||||
@@ -123,9 +123,6 @@ func TestDeduping(t *testing.T) {
|
||||
if q.Len() != 0 {
|
||||
t.Errorf("should not have added")
|
||||
}
|
||||
if q.Len() != 0 {
|
||||
t.Errorf("should not have added")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddTwoFireEarly(t *testing.T) {
|
||||
|
||||
@@ -16,11 +16,11 @@ limitations under the License.
|
||||
|
||||
// Package workqueue provides a simple queue that supports the following
|
||||
// features:
|
||||
// * Fair: items processed in the order in which they are added.
|
||||
// * Stingy: a single item will not be processed multiple times concurrently,
|
||||
// and if an item is added multiple times before it can be processed, it
|
||||
// will only be processed once.
|
||||
// * Multiple consumers and producers. In particular, it is allowed for an
|
||||
// item to be reenqueued while it is being processed.
|
||||
// * Shutdown notifications.
|
||||
// - Fair: items processed in the order in which they are added.
|
||||
// - Stingy: a single item will not be processed multiple times concurrently,
|
||||
// and if an item is added multiple times before it can be processed, it
|
||||
// will only be processed once.
|
||||
// - Multiple consumers and producers. In particular, it is allowed for an
|
||||
// item to be reenqueued while it is being processed.
|
||||
// - Shutdown notifications.
|
||||
package workqueue // import "k8s.io/client-go/util/workqueue"
|
||||
|
||||
@@ -50,6 +50,13 @@ func NewNamedRateLimitingQueue(rateLimiter RateLimiter, name string) RateLimitin
|
||||
}
|
||||
}
|
||||
|
||||
func NewRateLimitingQueueWithDelayingInterface(di DelayingInterface, rateLimiter RateLimiter) RateLimitingInterface {
|
||||
return &rateLimitingType{
|
||||
DelayingInterface: di,
|
||||
rateLimiter: rateLimiter,
|
||||
}
|
||||
}
|
||||
|
||||
// rateLimitingType wraps an Interface and provides rateLimited re-enquing
|
||||
type rateLimitingType struct {
|
||||
DelayingInterface
|
||||
|
||||
Reference in New Issue
Block a user