vendor dependencies

This commit is contained in:
Sergiusz Urbaniak 2019-04-24 11:06:03 +02:00
parent 604208ef4f
commit 72abf135d6
1156 changed files with 78178 additions and 105799 deletions

2
vendor/k8s.io/apimachinery/pkg/api/errors/OWNERS generated vendored Executable file → Normal file
View file

@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
reviewers:
- thockin
- lavalamp

View file

@ -20,6 +20,7 @@ import (
"encoding/json"
"fmt"
"net/http"
"reflect"
"strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -82,7 +83,20 @@ func (u *UnexpectedObjectError) Error() string {
func FromObject(obj runtime.Object) error {
switch t := obj.(type) {
case *metav1.Status:
return &StatusError{*t}
return &StatusError{ErrStatus: *t}
case runtime.Unstructured:
var status metav1.Status
obj := t.UnstructuredContent()
if !reflect.DeepEqual(obj["kind"], "Status") {
break
}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(t.UnstructuredContent(), &status); err != nil {
return err
}
if status.APIVersion != "v1" && status.APIVersion != "meta.k8s.io/v1" {
break
}
return &StatusError{ErrStatus: status}
}
return &UnexpectedObjectError{obj}
}
@ -170,6 +184,20 @@ func NewConflict(qualifiedResource schema.GroupResource, name string, err error)
}}
}
// NewApplyConflict returns an error including details on the requests apply conflicts
func NewApplyConflict(causes []metav1.StatusCause, message string) *StatusError {
return &StatusError{ErrStatus: metav1.Status{
Status: metav1.StatusFailure,
Code: http.StatusConflict,
Reason: metav1.StatusReasonConflict,
Details: &metav1.StatusDetails{
// TODO: Get obj details here?
Causes: causes,
},
Message: message,
}}
}
// NewGone returns an error indicating the item no longer available at the server and no forwarding address is known.
func NewGone(message string) *StatusError {
return &StatusError{metav1.Status{
@ -327,6 +355,17 @@ func NewTooManyRequestsError(message string) *StatusError {
}}
}
// NewRequestEntityTooLargeError returns an error indicating that the request
// entity was too large.
func NewRequestEntityTooLargeError(message string) *StatusError {
return &StatusError{metav1.Status{
Status: metav1.StatusFailure,
Code: http.StatusRequestEntityTooLarge,
Reason: metav1.StatusReasonRequestEntityTooLarge,
Message: fmt.Sprintf("Request entity too large: %s", message),
}}
}
// NewGenericServerResponse returns a new error for server responses that are not in a recognizable form.
func NewGenericServerResponse(code int, verb string, qualifiedResource schema.GroupResource, name, serverMessage string, retryAfterSeconds int, isUnexpectedResponse bool) *StatusError {
reason := metav1.StatusReasonUnknown
@ -513,6 +552,19 @@ func IsTooManyRequests(err error) bool {
return false
}
// IsRequestEntityTooLargeError determines if err is an error which indicates
// the request entity is too large.
func IsRequestEntityTooLargeError(err error) bool {
if ReasonForError(err) == metav1.StatusReasonRequestEntityTooLarge {
return true
}
switch t := err.(type) {
case APIStatus:
return t.Status().Code == http.StatusRequestEntityTooLarge
}
return false
}
// IsUnexpectedServerError returns true if the server response was not in the expected API format,
// and may be the result of another HTTP actor.
func IsUnexpectedServerError(err error) bool {

2
vendor/k8s.io/apimachinery/pkg/api/meta/OWNERS generated vendored Executable file → Normal file
View file

@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
reviewers:
- thockin
- smarterclayton

View file

@ -158,6 +158,19 @@ func ExtractList(obj runtime.Object) ([]runtime.Object, error) {
// objectSliceType is the type of a slice of Objects
var objectSliceType = reflect.TypeOf([]runtime.Object{})
// LenList returns the length of this list or 0 if it is not a list.
func LenList(list runtime.Object) int {
itemsPtr, err := GetItemsPtr(list)
if err != nil {
return 0
}
items, err := conversion.EnforcePtr(itemsPtr)
if err != nil {
return 0
}
return items.Len()
}
// SetList sets the given list object's Items member have the elements given in
// objects.
// Returns an error if list is not a List type (does not have an Items member),

View file

@ -20,14 +20,13 @@ import (
"fmt"
"reflect"
"github.com/golang/glog"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog"
)
// errNotList is returned when an object implements the Object style interfaces but not the List style
@ -132,12 +131,13 @@ func AsPartialObjectMetadata(m metav1.Object) *metav1beta1.PartialObjectMetadata
CreationTimestamp: m.GetCreationTimestamp(),
DeletionTimestamp: m.GetDeletionTimestamp(),
DeletionGracePeriodSeconds: m.GetDeletionGracePeriodSeconds(),
Labels: m.GetLabels(),
Annotations: m.GetAnnotations(),
OwnerReferences: m.GetOwnerReferences(),
Finalizers: m.GetFinalizers(),
ClusterName: m.GetClusterName(),
Initializers: m.GetInitializers(),
Labels: m.GetLabels(),
Annotations: m.GetAnnotations(),
OwnerReferences: m.GetOwnerReferences(),
Finalizers: m.GetFinalizers(),
ClusterName: m.GetClusterName(),
Initializers: m.GetInitializers(),
ManagedFields: m.GetManagedFields(),
},
}
}
@ -607,7 +607,7 @@ func (a genericAccessor) GetOwnerReferences() []metav1.OwnerReference {
var ret []metav1.OwnerReference
s := a.ownerReferences
if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice {
glog.Errorf("expect %v to be a pointer to slice", s)
klog.Errorf("expect %v to be a pointer to slice", s)
return ret
}
s = s.Elem()
@ -615,7 +615,7 @@ func (a genericAccessor) GetOwnerReferences() []metav1.OwnerReference {
ret = make([]metav1.OwnerReference, s.Len(), s.Len()+1)
for i := 0; i < s.Len(); i++ {
if err := extractFromOwnerReference(s.Index(i), &ret[i]); err != nil {
glog.Errorf("extractFromOwnerReference failed: %v", err)
klog.Errorf("extractFromOwnerReference failed: %v", err)
return ret
}
}
@ -625,13 +625,13 @@ func (a genericAccessor) GetOwnerReferences() []metav1.OwnerReference {
func (a genericAccessor) SetOwnerReferences(references []metav1.OwnerReference) {
s := a.ownerReferences
if s.Kind() != reflect.Ptr || s.Elem().Kind() != reflect.Slice {
glog.Errorf("expect %v to be a pointer to slice", s)
klog.Errorf("expect %v to be a pointer to slice", s)
}
s = s.Elem()
newReferences := reflect.MakeSlice(s.Type(), len(references), len(references))
for i := 0; i < len(references); i++ {
if err := setOwnerReference(newReferences.Index(i), &references[i]); err != nil {
glog.Errorf("setOwnerReference failed: %v", err)
klog.Errorf("setOwnerReference failed: %v", err)
return
}
}

2
vendor/k8s.io/apimachinery/pkg/api/resource/OWNERS generated vendored Executable file → Normal file
View file

@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
reviewers:
- thockin
- lavalamp

View file

@ -14,9 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by protoc-gen-gogo.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/api/resource/generated.proto
// DO NOT EDIT!
/*
Package resource is a generated protocol buffer package.

View file

@ -27,9 +27,9 @@ option go_package = "resource";
// Quantity is a fixed-point representation of a number.
// It provides convenient marshaling/unmarshaling in JSON and YAML,
// in addition to String() and Int64() accessors.
//
//
// The serialization format is:
//
//
// <quantity> ::= <signedNumber><suffix>
// (Note that <suffix> may be empty, from the "" case in <decimalSI>.)
// <digit> ::= 0 | 1 | ... | 9
@ -43,16 +43,16 @@ option go_package = "resource";
// <decimalSI> ::= m | "" | k | M | G | T | P | E
// (Note that 1024 = 1Ki but 1000 = 1k; I didn't choose the capitalization.)
// <decimalExponent> ::= "e" <signedNumber> | "E" <signedNumber>
//
//
// No matter which of the three exponent forms is used, no quantity may represent
// a number greater than 2^63-1 in magnitude, nor may it have more than 3 decimal
// places. Numbers larger or more precise will be capped or rounded up.
// (E.g.: 0.1m will rounded up to 1m.)
// This may be extended in the future if we require larger or smaller quantities.
//
//
// When a Quantity is parsed from a string, it will remember the type of suffix
// it had, and will use the same type again when it is serialized.
//
//
// Before serializing, Quantity will be put in "canonical form".
// This means that Exponent/suffix will be adjusted up or down (with a
// corresponding increase or decrease in Mantissa) such that:
@ -60,27 +60,22 @@ option go_package = "resource";
// b. No fractional digits will be emitted
// c. The exponent (or suffix) is as large as possible.
// The sign will be omitted unless the number is negative.
//
//
// Examples:
// 1.5 will be serialized as "1500m"
// 1.5Gi will be serialized as "1536Mi"
//
// NOTE: We reserve the right to amend this canonical format, perhaps to
// allow 1.5 to be canonical.
// TODO: Remove above disclaimer after all bikeshedding about format is over,
// or after March 2015.
//
//
// Note that the quantity will NEVER be internally represented by a
// floating point number. That is the whole point of this exercise.
//
//
// Non-canonical values will still parse as long as they are well formed,
// but will be re-emitted in their canonical form. (So always use canonical
// form, or don't diff.)
//
//
// This format is intended to make it difficult to use these numbers without
// writing some sort of special handling code in the hopes that that will
// cause implementors to also use a fixed point implementation.
//
//
// +protobuf=true
// +protobuf.embed=string
// +protobuf.options.marshal=false

View file

@ -21,7 +21,6 @@ import (
"errors"
"fmt"
"math/big"
"regexp"
"strconv"
"strings"
@ -69,11 +68,6 @@ import (
// 1.5 will be serialized as "1500m"
// 1.5Gi will be serialized as "1536Mi"
//
// NOTE: We reserve the right to amend this canonical format, perhaps to
// allow 1.5 to be canonical.
// TODO: Remove above disclaimer after all bikeshedding about format is over,
// or after March 2015.
//
// Note that the quantity will NEVER be internally represented by a
// floating point number. That is the whole point of this exercise.
//
@ -142,9 +136,6 @@ const (
)
var (
// splitRE is used to get the various parts of a number.
splitRE = regexp.MustCompile(splitREString)
// Errors that could happen while parsing a string.
ErrFormatWrong = errors.New("quantities must match the regular expression '" + splitREString + "'")
ErrNumeric = errors.New("unable to parse numeric part of quantity")
@ -506,7 +497,7 @@ func (q *Quantity) Sign() int {
return q.i.Sign()
}
// AsScaled returns the current value, rounded up to the provided scale, and returns
// AsScale returns the current value, rounded up to the provided scale, and returns
// false if the scale resulted in a loss of precision.
func (q *Quantity) AsScale(scale Scale) (CanonicalValue, bool) {
if q.d.Dec != nil {
@ -689,7 +680,7 @@ func NewScaledQuantity(value int64, scale Scale) *Quantity {
}
}
// Value returns the value of q; any fractional part will be lost.
// Value returns the unscaled value of q rounded up to the nearest integer away from 0.
func (q *Quantity) Value() int64 {
return q.ScaledValue(0)
}

View file

@ -176,40 +176,17 @@ func ValidateObjectMetaAccessor(meta metav1.Object, requiresNamespace bool, name
allErrs = append(allErrs, field.Invalid(fldPath.Child("clusterName"), meta.GetClusterName(), msg))
}
}
for _, entry := range meta.GetManagedFields() {
allErrs = append(allErrs, v1validation.ValidateFieldManager(entry.Manager, fldPath.Child("fieldManager"))...)
}
allErrs = append(allErrs, ValidateNonnegativeField(meta.GetGeneration(), fldPath.Child("generation"))...)
allErrs = append(allErrs, v1validation.ValidateLabels(meta.GetLabels(), fldPath.Child("labels"))...)
allErrs = append(allErrs, ValidateAnnotations(meta.GetAnnotations(), fldPath.Child("annotations"))...)
allErrs = append(allErrs, ValidateOwnerReferences(meta.GetOwnerReferences(), fldPath.Child("ownerReferences"))...)
allErrs = append(allErrs, ValidateInitializers(meta.GetInitializers(), fldPath.Child("initializers"))...)
allErrs = append(allErrs, ValidateFinalizers(meta.GetFinalizers(), fldPath.Child("finalizers"))...)
return allErrs
}
func ValidateInitializers(initializers *metav1.Initializers, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
if initializers == nil {
return allErrs
}
for i, initializer := range initializers.Pending {
allErrs = append(allErrs, validation.IsFullyQualifiedName(fldPath.Child("pending").Index(i).Child("name"), initializer.Name)...)
}
allErrs = append(allErrs, validateInitializersResult(initializers.Result, fldPath.Child("result"))...)
return allErrs
}
func validateInitializersResult(result *metav1.Status, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
if result == nil {
return allErrs
}
switch result.Status {
case metav1.StatusFailure:
default:
allErrs = append(allErrs, field.Invalid(fldPath.Child("status"), result.Status, "must be 'Failure'"))
}
return allErrs
}
// ValidateFinalizers tests if the finalizers name are valid, and if there are conflicting finalizers.
func ValidateFinalizers(finalizers []string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
@ -265,8 +242,9 @@ func ValidateObjectMetaAccessorUpdate(newMeta, oldMeta metav1.Object, fldPath *f
allErrs = append(allErrs, field.Invalid(fldPath.Child("generation"), newMeta.GetGeneration(), "must not be decremented"))
}
allErrs = append(allErrs, ValidateInitializersUpdate(newMeta.GetInitializers(), oldMeta.GetInitializers(), fldPath.Child("initializers"))...)
for _, entry := range newMeta.GetManagedFields() {
allErrs = append(allErrs, v1validation.ValidateFieldManager(entry.Manager, fldPath.Child("fieldManager"))...)
}
allErrs = append(allErrs, ValidateImmutableField(newMeta.GetName(), oldMeta.GetName(), fldPath.Child("name"))...)
allErrs = append(allErrs, ValidateImmutableField(newMeta.GetNamespace(), oldMeta.GetNamespace(), fldPath.Child("namespace"))...)
allErrs = append(allErrs, ValidateImmutableField(newMeta.GetUID(), oldMeta.GetUID(), fldPath.Child("uid"))...)
@ -281,28 +259,3 @@ func ValidateObjectMetaAccessorUpdate(newMeta, oldMeta metav1.Object, fldPath *f
return allErrs
}
// ValidateInitializersUpdate checks the update of the metadata initializers field
func ValidateInitializersUpdate(newInit, oldInit *metav1.Initializers, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
switch {
case oldInit == nil && newInit != nil:
// Initializers may not be set on new objects
allErrs = append(allErrs, field.Invalid(fldPath, nil, "field is immutable once initialization has completed"))
case oldInit != nil && newInit == nil:
// this is a valid transition and means initialization was successful
case oldInit != nil && newInit != nil:
// validate changes to initializers
switch {
case oldInit.Result == nil && newInit.Result != nil:
// setting a result is allowed
allErrs = append(allErrs, validateInitializersResult(newInit.Result, fldPath.Child("result"))...)
case oldInit.Result != nil:
// setting Result implies permanent failure, and all future updates will be prevented
allErrs = append(allErrs, ValidateImmutableField(newInit.Result, oldInit.Result, fldPath.Child("result"))...)
default:
// leaving the result nil is allowed
}
}
return allErrs
}

View file

@ -17,11 +17,8 @@ limitations under the License.
package internalversion
import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/util/validation/field"
)
func Convert_internalversion_ListOptions_To_v1_ListOptions(in *ListOptions, out *metav1.ListOptions, s conversion.Scope) error {
@ -31,7 +28,6 @@ func Convert_internalversion_ListOptions_To_v1_ListOptions(in *ListOptions, out
if err := metav1.Convert_labels_Selector_To_string(&in.LabelSelector, &out.LabelSelector, s); err != nil {
return err
}
out.IncludeUninitialized = in.IncludeUninitialized
out.ResourceVersion = in.ResourceVersion
out.TimeoutSeconds = in.TimeoutSeconds
out.Watch = in.Watch
@ -47,7 +43,6 @@ func Convert_v1_ListOptions_To_internalversion_ListOptions(in *metav1.ListOption
if err := metav1.Convert_string_To_labels_Selector(&in.LabelSelector, &out.LabelSelector, s); err != nil {
return err
}
out.IncludeUninitialized = in.IncludeUninitialized
out.ResourceVersion = in.ResourceVersion
out.TimeoutSeconds = in.TimeoutSeconds
out.Watch = in.Watch
@ -55,23 +50,3 @@ func Convert_v1_ListOptions_To_internalversion_ListOptions(in *metav1.ListOption
out.Continue = in.Continue
return nil
}
func Convert_map_to_v1_LabelSelector(in *map[string]string, out *metav1.LabelSelector, s conversion.Scope) error {
if in == nil {
return nil
}
out = new(metav1.LabelSelector)
for labelKey, labelValue := range *in {
metav1.AddLabelToSelector(out, labelKey, labelValue)
}
return nil
}
func Convert_v1_LabelSelector_to_map(in *metav1.LabelSelector, out *map[string]string, s conversion.Scope) error {
var err error
*out, err = metav1.LabelSelectorAsMap(in)
if err != nil {
err = field.Invalid(field.NewPath("labelSelector"), *in, fmt.Sprintf("cannot convert to old selector: %v", err))
}
return err
}

View file

@ -17,4 +17,4 @@ limitations under the License.
// +k8s:deepcopy-gen=package
// +k8s:conversion-gen=k8s.io/apimachinery/pkg/apis/meta/v1
package internalversion
package internalversion // import "k8s.io/apimachinery/pkg/apis/meta/internalversion"

View file

@ -57,19 +57,22 @@ func addToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion)
if err := scheme.AddIgnoredConversionType(&metav1.TypeMeta{}, &metav1.TypeMeta{}); err != nil {
return err
}
scheme.AddConversionFuncs(
err := scheme.AddConversionFuncs(
metav1.Convert_string_To_labels_Selector,
metav1.Convert_labels_Selector_To_string,
metav1.Convert_string_To_fields_Selector,
metav1.Convert_fields_Selector_To_string,
Convert_map_to_v1_LabelSelector,
Convert_v1_LabelSelector_to_map,
metav1.Convert_Map_string_To_string_To_v1_LabelSelector,
metav1.Convert_v1_LabelSelector_To_Map_string_To_string,
Convert_internalversion_ListOptions_To_v1_ListOptions,
Convert_v1_ListOptions_To_internalversion_ListOptions,
)
if err != nil {
return err
}
// ListOptions is the only options struct which needs conversion (it exposes labels and fields
// as selectors for convenience). The other types have only a single representation today.
scheme.AddKnownTypes(SchemeGroupVersion,
@ -77,6 +80,8 @@ func addToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion)
&metav1.GetOptions{},
&metav1.ExportOptions{},
&metav1.DeleteOptions{},
&metav1.CreateOptions{},
&metav1.UpdateOptions{},
)
scheme.AddKnownTypes(SchemeGroupVersion,
&metav1beta1.Table{},
@ -91,7 +96,10 @@ func addToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion)
&metav1beta1.PartialObjectMetadataList{},
)
// Allow delete options to be decoded across all version in this scheme (we may want to be more clever than this)
scheme.AddUnversionedTypes(SchemeGroupVersion, &metav1.DeleteOptions{})
scheme.AddUnversionedTypes(SchemeGroupVersion,
&metav1.DeleteOptions{},
&metav1.CreateOptions{},
&metav1.UpdateOptions{})
metav1.AddToGroupVersion(scheme, metav1.SchemeGroupVersion)
return nil
}

View file

@ -33,9 +33,6 @@ type ListOptions struct {
LabelSelector labels.Selector
// A selector based on fields
FieldSelector fields.Selector
// If true, partially initialized resources are included in the response.
// +optional
IncludeUninitialized bool
// If true, watch for changes to this list
Watch bool
// When specified with a watch call, shows changes that occur after that particular version of a resource.

View file

@ -34,13 +34,38 @@ func init() {
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_internalversion_List_To_v1_List,
Convert_v1_List_To_internalversion_List,
Convert_internalversion_ListOptions_To_v1_ListOptions,
Convert_v1_ListOptions_To_internalversion_ListOptions,
)
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*List)(nil), (*v1.List)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_internalversion_List_To_v1_List(a.(*List), b.(*v1.List), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.List)(nil), (*List)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_List_To_internalversion_List(a.(*v1.List), b.(*List), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ListOptions)(nil), (*v1.ListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_internalversion_ListOptions_To_v1_ListOptions(a.(*ListOptions), b.(*v1.ListOptions), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1.ListOptions)(nil), (*ListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ListOptions_To_internalversion_ListOptions(a.(*v1.ListOptions), b.(*ListOptions), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*ListOptions)(nil), (*v1.ListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_internalversion_ListOptions_To_v1_ListOptions(a.(*ListOptions), b.(*v1.ListOptions), scope)
}); err != nil {
return err
}
if err := s.AddConversionFunc((*v1.ListOptions)(nil), (*ListOptions)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1_ListOptions_To_internalversion_ListOptions(a.(*v1.ListOptions), b.(*ListOptions), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_internalversion_List_To_v1_List(in *List, out *v1.List, s conversion.Scope) error {
@ -92,7 +117,6 @@ func autoConvert_internalversion_ListOptions_To_v1_ListOptions(in *ListOptions,
if err := v1.Convert_fields_Selector_To_string(&in.FieldSelector, &out.FieldSelector, s); err != nil {
return err
}
out.IncludeUninitialized = in.IncludeUninitialized
out.Watch = in.Watch
out.ResourceVersion = in.ResourceVersion
out.TimeoutSeconds = (*int64)(unsafe.Pointer(in.TimeoutSeconds))
@ -108,7 +132,6 @@ func autoConvert_v1_ListOptions_To_internalversion_ListOptions(in *v1.ListOption
if err := v1.Convert_string_To_fields_Selector(&in.FieldSelector, &out.FieldSelector, s); err != nil {
return err
}
out.IncludeUninitialized = in.IncludeUninitialized
out.Watch = in.Watch
out.ResourceVersion = in.ResourceVersion
out.TimeoutSeconds = (*int64)(unsafe.Pointer(in.TimeoutSeconds))

View file

@ -33,9 +33,7 @@ func (in *List) DeepCopyInto(out *List) {
in, out := &in.Items, &out.Items
*out = make([]runtime.Object, len(*in))
for i := range *in {
if (*in)[i] == nil {
(*out)[i] = nil
} else {
if (*in)[i] != nil {
(*out)[i] = (*in)[i].DeepCopyObject()
}
}
@ -65,24 +63,16 @@ func (in *List) DeepCopyObject() runtime.Object {
func (in *ListOptions) DeepCopyInto(out *ListOptions) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.LabelSelector == nil {
out.LabelSelector = nil
} else {
if in.LabelSelector != nil {
out.LabelSelector = in.LabelSelector.DeepCopySelector()
}
if in.FieldSelector == nil {
out.FieldSelector = nil
} else {
if in.FieldSelector != nil {
out.FieldSelector = in.FieldSelector.DeepCopySelector()
}
if in.TimeoutSeconds != nil {
in, out := &in.TimeoutSeconds, &out.TimeoutSeconds
if *in == nil {
*out = nil
} else {
*out = new(int64)
**out = **in
}
*out = new(int64)
**out = **in
}
return
}

2
vendor/k8s.io/apimachinery/pkg/apis/meta/v1/OWNERS generated vendored Executable file → Normal file
View file

@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
reviewers:
- thockin
- smarterclayton

View file

@ -33,17 +33,17 @@ func AddConversionFuncs(scheme *runtime.Scheme) error {
return scheme.AddConversionFuncs(
Convert_v1_TypeMeta_To_v1_TypeMeta,
Convert_unversioned_ListMeta_To_unversioned_ListMeta,
Convert_v1_ListMeta_To_v1_ListMeta,
Convert_intstr_IntOrString_To_intstr_IntOrString,
Convert_unversioned_Time_To_unversioned_Time,
Convert_unversioned_MicroTime_To_unversioned_MicroTime,
Convert_Pointer_v1_Duration_To_v1_Duration,
Convert_v1_Duration_To_Pointer_v1_Duration,
Convert_Slice_string_To_unversioned_Time,
Convert_Slice_string_To_v1_Time,
Convert_v1_Time_To_v1_Time,
Convert_v1_MicroTime_To_v1_MicroTime,
Convert_resource_Quantity_To_resource_Quantity,
@ -71,8 +71,8 @@ func AddConversionFuncs(scheme *runtime.Scheme) error {
Convert_Pointer_float64_To_float64,
Convert_float64_To_Pointer_float64,
Convert_map_to_unversioned_LabelSelector,
Convert_unversioned_LabelSelector_to_map,
Convert_Map_string_To_string_To_v1_LabelSelector,
Convert_v1_LabelSelector_To_Map_string_To_string,
Convert_Slice_string_To_Slice_int32,
@ -187,7 +187,7 @@ func Convert_v1_TypeMeta_To_v1_TypeMeta(in, out *TypeMeta, s conversion.Scope) e
}
// +k8s:conversion-fn=copy-only
func Convert_unversioned_ListMeta_To_unversioned_ListMeta(in, out *ListMeta, s conversion.Scope) error {
func Convert_v1_ListMeta_To_v1_ListMeta(in, out *ListMeta, s conversion.Scope) error {
*out = *in
return nil
}
@ -199,7 +199,14 @@ func Convert_intstr_IntOrString_To_intstr_IntOrString(in, out *intstr.IntOrStrin
}
// +k8s:conversion-fn=copy-only
func Convert_unversioned_Time_To_unversioned_Time(in *Time, out *Time, s conversion.Scope) error {
func Convert_v1_Time_To_v1_Time(in *Time, out *Time, s conversion.Scope) error {
// Cannot deep copy these, because time.Time has unexported fields.
*out = *in
return nil
}
// +k8s:conversion-fn=copy-only
func Convert_v1_MicroTime_To_v1_MicroTime(in *MicroTime, out *MicroTime, s conversion.Scope) error {
// Cannot deep copy these, because time.Time has unexported fields.
*out = *in
return nil
@ -220,14 +227,8 @@ func Convert_v1_Duration_To_Pointer_v1_Duration(in *Duration, out **Duration, s
return nil
}
func Convert_unversioned_MicroTime_To_unversioned_MicroTime(in *MicroTime, out *MicroTime, s conversion.Scope) error {
// Cannot deep copy these, because time.Time has unexported fields.
*out = *in
return nil
}
// Convert_Slice_string_To_unversioned_Time allows converting a URL query parameter value
func Convert_Slice_string_To_unversioned_Time(input *[]string, out *Time, s conversion.Scope) error {
// Convert_Slice_string_To_v1_Time allows converting a URL query parameter value
func Convert_Slice_string_To_v1_Time(input *[]string, out *Time, s conversion.Scope) error {
str := ""
if len(*input) > 0 {
str = (*input)[0]
@ -275,7 +276,7 @@ func Convert_resource_Quantity_To_resource_Quantity(in *resource.Quantity, out *
return nil
}
func Convert_map_to_unversioned_LabelSelector(in *map[string]string, out *LabelSelector, s conversion.Scope) error {
func Convert_Map_string_To_string_To_v1_LabelSelector(in *map[string]string, out *LabelSelector, s conversion.Scope) error {
if in == nil {
return nil
}
@ -285,7 +286,7 @@ func Convert_map_to_unversioned_LabelSelector(in *map[string]string, out *LabelS
return nil
}
func Convert_unversioned_LabelSelector_to_map(in *LabelSelector, out *map[string]string, s conversion.Scope) error {
func Convert_v1_LabelSelector_To_Map_string_To_string(in *LabelSelector, out *map[string]string, s conversion.Scope) error {
var err error
*out, err = LabelSelectorAsMap(in)
return err

View file

@ -19,4 +19,5 @@ limitations under the License.
// +k8s:defaulter-gen=TypeMeta
// +groupName=meta.k8s.io
package v1 // import "k8s.io/apimachinery/pkg/apis/meta/v1"

View file

@ -48,3 +48,13 @@ func (d *Duration) UnmarshalJSON(b []byte) error {
func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(d.Duration.String())
}
// OpenAPISchemaType is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
//
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
func (_ Duration) OpenAPISchemaType() []string { return []string{"string"} }
// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
func (_ Duration) OpenAPISchemaFormat() string { return "" }

File diff suppressed because it is too large Load diff

View file

@ -92,6 +92,16 @@ message APIResource {
// categories is a list of the grouped resources this resource belongs to (e.g. 'all')
repeated string categories = 7;
// The hash value of the storage version, the version this resource is
// converted to when written to the data store. Value must be treated
// as opaque by clients. Only equality comparison on the value is valid.
// This is an alpha feature and may change or be removed in the future.
// The field is populated by the apiserver only if the
// StorageVersionHash feature gate is enabled.
// This field will remain optional even if it graduates.
// +optional
optional string storageVersionHash = 10;
}
// APIResourceList is a list of APIResource, it is used to expose the name of the
@ -107,7 +117,7 @@ message APIResourceList {
// APIVersions lists the versions that are available, to allow clients to
// discover the API at /api, which is the root path of the legacy v1 API.
//
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
message APIVersions {
@ -124,6 +134,24 @@ message APIVersions {
repeated ServerAddressByClientCIDR serverAddressByClientCIDRs = 2;
}
// CreateOptions may be provided when creating an API object.
message CreateOptions {
// When present, indicates that modifications should not be
// persisted. An invalid or unrecognized dryRun directive will
// result in an error response and no further processing of the
// request. Valid values are:
// - All: all dry run stages will be processed
// +optional
repeated string dryRun = 1;
// fieldManager is a name associated with the actor or entity
// that is making these changes. The value must be less than or
// 128 characters long, and only contain printable characters,
// as defined by https://golang.org/pkg/unicode/#IsPrint.
// +optional
optional string fieldManager = 3;
}
// DeleteOptions may be provided when deleting an API object.
message DeleteOptions {
// The duration in seconds before the object should be deleted. Value must be non-negative integer.
@ -155,6 +183,14 @@ message DeleteOptions {
// foreground.
// +optional
optional string propagationPolicy = 4;
// When present, indicates that modifications should not be
// persisted. An invalid or unrecognized dryRun directive will
// result in an error response and no further processing of the
// request. Valid values are:
// - All: all dry run stages will be processed
// +optional
repeated string dryRun = 5;
}
// Duration is a wrapper around time.Duration which supports correct
@ -165,14 +201,34 @@ message Duration {
}
// ExportOptions is the query options to the standard REST get call.
// Deprecated. Planned for removal in 1.18.
message ExportOptions {
// Should this value be exported. Export strips fields that a user can not specify.
// Deprecated. Planned for removal in 1.18.
optional bool export = 1;
// Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'.
// Deprecated. Planned for removal in 1.18.
optional bool exact = 2;
}
// Fields stores a set of fields in a data structure like a Trie.
// To understand how this is used, see: https://github.com/kubernetes-sigs/structured-merge-diff
message Fields {
// Map stores a set of fields in a data structure like a Trie.
//
// Each key is either a '.' representing the field itself, and will always map to an empty set,
// or a string representing a sub-field or item. The string will follow one of these four formats:
// 'f:<name>', where <name> is the name of a field in a struct, or key in a map
// 'v:<value>', where <value> is the exact json formatted value of a list item
// 'i:<index>', where <index> is position of a item in a list
// 'k:<keys>', where <keys> is a map of a list item's key fields to their unique values
// If a key maps to an empty Fields value, the field that key represents is part of the set.
//
// The exact format is defined in k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal
map<string, Fields> map = 1;
}
// GetOptions is the standard query options to the standard REST get call.
message GetOptions {
// When specified:
@ -180,15 +236,11 @@ message GetOptions {
// - if it's 0, then we simply return what we currently have in cache, no guarantee;
// - if set to non zero, then the result is at least as fresh as given rv.
optional string resourceVersion = 1;
// If true, partially initialized resources are included in the response.
// +optional
optional bool includeUninitialized = 2;
}
// GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying
// concepts during lookup stages without having partially valid types
//
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
message GroupKind {
optional string group = 1;
@ -198,7 +250,7 @@ message GroupKind {
// GroupResource specifies a Group and a Resource, but does not force a version. This is useful for identifying
// concepts during lookup stages without having partially valid types
//
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
message GroupResource {
optional string group = 1;
@ -207,7 +259,7 @@ message GroupResource {
}
// GroupVersion contains the "group" and the "version", which uniquely identifies the API.
//
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
message GroupVersion {
optional string group = 1;
@ -228,7 +280,7 @@ message GroupVersionForDiscovery {
// GroupVersionKind unambiguously identifies a kind. It doesn't anonymously include GroupVersion
// to avoid automatic coersion. It doesn't use a GroupVersion to avoid custom marshalling
//
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
message GroupVersionKind {
optional string group = 1;
@ -240,7 +292,7 @@ message GroupVersionKind {
// GroupVersionResource unambiguously identifies a resource. It doesn't anonymously include GroupVersion
// to avoid automatic coersion. It doesn't use a GroupVersion to avoid custom marshalling
//
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
message GroupVersionResource {
optional string group = 1;
@ -338,9 +390,10 @@ message ListMeta {
// continue may be set if the user set a limit on the number of items returned, and indicates that
// the server has more data available. The value is opaque and may be used to issue another request
// to the endpoint that served this list to retrieve the next set of available objects. Continuing a
// list may not be possible if the server configuration has changed or more than a few minutes have
// passed. The resourceVersion field returned when using this continue value will be identical to
// the value in the first response.
// consistent list may not be possible if the server configuration has changed or more than a few
// minutes have passed. The resourceVersion field returned when using this continue value will be
// identical to the value in the first response, unless you have received this token from an error
// message.
optional string continue = 3;
}
@ -356,10 +409,6 @@ message ListOptions {
// +optional
optional string fieldSelector = 2;
// If true, partially initialized resources are included in the response.
// +optional
optional bool includeUninitialized = 6;
// Watch for changes to the described resources and return them as a stream of
// add, update, and remove notifications. Specify resourceVersion.
// +optional
@ -387,7 +436,7 @@ message ListOptions {
// more results are available. Servers may choose not to support the limit argument and will return
// all of the available results. If limit is specified and the continue field is empty, clients may
// assume that no more results are available. This field is not supported if watch is true.
//
//
// The server guarantees that the objects returned when using continue will be identical to issuing
// a single list call without a limit - that is, no objects created, modified, or deleted after the
// first request is issued will be included in any subsequent continued requests. This is sometimes
@ -397,19 +446,50 @@ message ListOptions {
// result was calculated is returned.
optional int64 limit = 7;
// The continue option should be set when retrieving more results from the server. Since this value
// is server defined, clients may only use the continue value from a previous query result with
// identical query parameters (except for the value of continue) and the server may reject a continue
// value it does not recognize. If the specified continue value is no longer valid whether due to
// expiration (generally five to fifteen minutes) or a configuration change on the server the server
// will respond with a 410 ResourceExpired error indicating the client must restart their list without
// the continue field. This field is not supported when watch is true. Clients may start a watch from
// the last resourceVersion value returned by the server and not miss any modifications.
// The continue option should be set when retrieving more results from the server. Since this value is
// server defined, clients may only use the continue value from a previous query result with identical
// query parameters (except for the value of continue) and the server may reject a continue value it
// does not recognize. If the specified continue value is no longer valid whether due to expiration
// (generally five to fifteen minutes) or a configuration change on the server, the server will
// respond with a 410 ResourceExpired error together with a continue token. If the client needs a
// consistent list, it must restart their list without the continue field. Otherwise, the client may
// send another list request with the token received with the 410 error, the server will respond with
// a list starting from the next key, but from the latest snapshot, which is inconsistent from the
// previous list results - objects that are created, modified, or deleted after the first list request
// will be included in the response, as long as their keys are after the "next key".
//
// This field is not supported when watch is true. Clients may start a watch from the last
// resourceVersion value returned by the server and not miss any modifications.
optional string continue = 8;
}
// ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource
// that the fieldset applies to.
message ManagedFieldsEntry {
// Manager is an identifier of the workflow managing these fields.
optional string manager = 1;
// Operation is the type of operation which lead to this ManagedFieldsEntry being created.
// The only valid values for this field are 'Apply' and 'Update'.
optional string operation = 2;
// APIVersion defines the version of this resource that this field set
// applies to. The format is "group/version" just like the top-level
// APIVersion field. It is necessary to track the version of a field
// set because it cannot be automatically converted.
optional string apiVersion = 3;
// Time is timestamp of when these fields were set. It should always be empty if Operation is 'Apply'
// +optional
optional Time time = 4;
// Fields identifies a set of fields.
// +optional
optional Fields fields = 5;
}
// MicroTime is version of Time with microsecond level precision.
//
//
// +protobuf.options.marshal=false
// +protobuf.as=Timestamp
// +protobuf.options.(gogoproto.goproto_stringer)=false
@ -445,12 +525,12 @@ message ObjectMeta {
// The provided value has the same validation rules as the Name field,
// and may be truncated by the length of the suffix required to make the value
// unique on the server.
//
//
// If this field is specified and the generated name exists, the server will
// NOT return a 409 - instead, it will either return 201 Created or 500 with Reason
// ServerTimeout indicating a unique name could not be found in the time allotted, and the client
// should retry (optionally after the time indicated in the Retry-After header).
//
//
// Applied only if Name is not specified.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency
// +optional
@ -460,7 +540,7 @@ message ObjectMeta {
// equivalent to the "default" namespace, but "default" is the canonical representation.
// Not all objects are required to be scoped to a namespace - the value of this field for
// those objects will be empty.
//
//
// Must be a DNS_LABEL.
// Cannot be updated.
// More info: http://kubernetes.io/docs/user-guide/namespaces
@ -476,7 +556,7 @@ message ObjectMeta {
// UID is the unique in time and space value for this object. It is typically generated by
// the server on successful creation of a resource and is not allowed to change on PUT
// operations.
//
//
// Populated by the system.
// Read-only.
// More info: http://kubernetes.io/docs/user-guide/identifiers#uids
@ -488,7 +568,7 @@ message ObjectMeta {
// concurrency, change detection, and the watch operation on a resource or set of resources.
// Clients must treat these values as opaque and passed unmodified back to the server.
// They may only be valid for a particular resource or set of resources.
//
//
// Populated by the system.
// Read-only.
// Value must be treated as opaque by clients and .
@ -504,7 +584,7 @@ message ObjectMeta {
// CreationTimestamp is a timestamp representing the server time when this object was
// created. It is not guaranteed to be set in happens-before order across separate operations.
// Clients may not set this value. It is represented in RFC3339 form and is in UTC.
//
//
// Populated by the system.
// Read-only.
// Null for lists.
@ -526,7 +606,7 @@ message ObjectMeta {
// exist after this timestamp, until an administrator or automated process can determine the
// resource is fully terminated.
// If not set, graceful deletion of the object has not been requested.
//
//
// Populated by the system when a graceful deletion is requested.
// Read-only.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
@ -568,10 +648,12 @@ message ObjectMeta {
// this object has been completely initialized. Otherwise, the object is considered uninitialized
// and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to
// observe uninitialized objects.
//
//
// When an object is created, the system will populate this list with the current set of initializers.
// Only privileged users may set or modify this list. Once it is empty, it may not be modified further
// by any user.
//
// DEPRECATED - initializers are an alpha field and will be removed in v1.15.
optional Initializers initializers = 16;
// Must be empty before the object is deleted from the registry. Each entry
@ -587,11 +669,24 @@ message ObjectMeta {
// This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.
// +optional
optional string clusterName = 15;
// ManagedFields maps workflow-id and version to the set of fields
// that are managed by that workflow. This is mostly for internal
// housekeeping, and users typically shouldn't need to set or
// understand this field. A workflow can be the user's name, a
// controller's name, or the name of a specific apply path like
// "ci-cd". The set of fields is always in the version that the
// workflow used when modifying the object.
//
// This field is alpha and can be changed or removed without notice.
//
// +optional
repeated ManagedFieldsEntry managedFields = 17;
}
// OwnerReference contains enough information to let you identify an owning
// object. Currently, an owning object must be in the same namespace, so there
// is no namespace field.
// object. An owning object must be in the same namespace as the dependent, or
// be cluster-scoped, so there is no namespace field.
message OwnerReference {
// API version of the referent.
optional string apiVersion = 5;
@ -626,11 +721,43 @@ message OwnerReference {
message Patch {
}
// PatchOptions may be provided when patching an API object.
// PatchOptions is meant to be a superset of UpdateOptions.
message PatchOptions {
// When present, indicates that modifications should not be
// persisted. An invalid or unrecognized dryRun directive will
// result in an error response and no further processing of the
// request. Valid values are:
// - All: all dry run stages will be processed
// +optional
repeated string dryRun = 1;
// Force is going to "force" Apply requests. It means user will
// re-acquire conflicting fields owned by other people. Force
// flag must be unset for non-apply patch requests.
// +optional
optional bool force = 2;
// fieldManager is a name associated with the actor or entity
// that is making these changes. The value must be less than or
// 128 characters long, and only contain printable characters,
// as defined by https://golang.org/pkg/unicode/#IsPrint. This
// field is required for apply requests
// (application/apply-patch) but optional for non-apply patch
// types (JsonPatch, MergePatch, StrategicMergePatch).
// +optional
optional string fieldManager = 3;
}
// Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.
message Preconditions {
// Specifies the target UID.
// +optional
optional string uid = 1;
// Specifies the target ResourceVersion
// +optional
optional string resourceVersion = 2;
}
// RootPaths lists the paths available at root.
@ -704,7 +831,7 @@ message StatusCause {
// Arrays are zero-indexed. Fields may appear more than once in an array of
// causes due to fields having multiple errors.
// Optional.
//
//
// Examples:
// "name" - the field "name" on the current resource
// "items[0].name" - the field "name" on the first array entry in "items"
@ -755,7 +882,7 @@ message StatusDetails {
// Time is a wrapper around time.Time which supports correct
// marshaling to YAML and JSON. Wrappers are provided for many
// of the factory methods that the time package offers.
//
//
// +protobuf.options.marshal=false
// +protobuf.as=Timestamp
// +protobuf.options.(gogoproto.goproto_stringer)=false
@ -791,7 +918,7 @@ message Timestamp {
// TypeMeta describes an individual object in an API response or request
// with strings representing the type of the object and its API schema version.
// Structures that are versioned or persisted should inline TypeMeta.
//
//
// +k8s:deepcopy-gen=false
message TypeMeta {
// Kind is a string value representing the REST resource this object represents.
@ -810,8 +937,27 @@ message TypeMeta {
optional string apiVersion = 2;
}
// UpdateOptions may be provided when updating an API object.
// All fields in UpdateOptions should also be present in PatchOptions.
message UpdateOptions {
// When present, indicates that modifications should not be
// persisted. An invalid or unrecognized dryRun directive will
// result in an error response and no further processing of the
// request. Valid values are:
// - All: all dry run stages will be processed
// +optional
repeated string dryRun = 1;
// fieldManager is a name associated with the actor or entity
// that is making these changes. The value must be less than or
// 128 characters long, and only contain printable characters,
// as defined by https://golang.org/pkg/unicode/#IsPrint.
// +optional
optional string fieldManager = 2;
}
// Verbs masks the value so protobuf can generate
//
//
// +protobuf.nullable=true
// +protobuf.options.(gogoproto.goproto_stringer)=false
message Verbs {
@ -821,7 +967,7 @@ message Verbs {
}
// Event represents a single event to a watched resource.
//
//
// +protobuf=true
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

View file

@ -17,6 +17,7 @@ limitations under the License.
package v1
import (
"encoding/json"
"fmt"
"k8s.io/apimachinery/pkg/fields"
@ -227,8 +228,40 @@ func NewUIDPreconditions(uid string) *Preconditions {
return &Preconditions{UID: &u}
}
// NewRVDeletionPrecondition returns a DeleteOptions with a ResourceVersion precondition set.
func NewRVDeletionPrecondition(rv string) *DeleteOptions {
p := Preconditions{ResourceVersion: &rv}
return &DeleteOptions{Preconditions: &p}
}
// HasObjectMetaSystemFieldValues returns true if fields that are managed by the system on ObjectMeta have values.
func HasObjectMetaSystemFieldValues(meta Object) bool {
return !meta.GetCreationTimestamp().Time.IsZero() ||
len(meta.GetUID()) != 0
}
// ResetObjectMetaForStatus forces the meta fields for a status update to match the meta fields
// for a pre-existing object. This is opt-in for new objects with Status subresource.
func ResetObjectMetaForStatus(meta, existingMeta Object) {
meta.SetDeletionTimestamp(existingMeta.GetDeletionTimestamp())
meta.SetGeneration(existingMeta.GetGeneration())
meta.SetSelfLink(existingMeta.GetSelfLink())
meta.SetLabels(existingMeta.GetLabels())
meta.SetAnnotations(existingMeta.GetAnnotations())
meta.SetFinalizers(existingMeta.GetFinalizers())
meta.SetOwnerReferences(existingMeta.GetOwnerReferences())
meta.SetManagedFields(existingMeta.GetManagedFields())
}
// MarshalJSON implements json.Marshaler
func (f Fields) MarshalJSON() ([]byte, error) {
return json.Marshal(&f.Map)
}
// UnmarshalJSON implements json.Unmarshaler
func (f *Fields) UnmarshalJSON(b []byte) error {
return json.Unmarshal(b, &f.Map)
}
var _ json.Marshaler = Fields{}
var _ json.Unmarshaler = &Fields{}

View file

@ -63,6 +63,8 @@ type Object interface {
SetOwnerReferences([]OwnerReference)
GetClusterName() string
SetClusterName(clusterName string)
GetManagedFields() []ManagedFieldsEntry
SetManagedFields(managedFields []ManagedFieldsEntry)
}
// ListMetaAccessor retrieves the list interface from an object
@ -162,55 +164,13 @@ func (meta *ObjectMeta) GetInitializers() *Initializers { return m
func (meta *ObjectMeta) SetInitializers(initializers *Initializers) { meta.Initializers = initializers }
func (meta *ObjectMeta) GetFinalizers() []string { return meta.Finalizers }
func (meta *ObjectMeta) SetFinalizers(finalizers []string) { meta.Finalizers = finalizers }
func (meta *ObjectMeta) GetOwnerReferences() []OwnerReference {
if meta.OwnerReferences == nil {
return nil
}
ret := make([]OwnerReference, len(meta.OwnerReferences))
for i := 0; i < len(meta.OwnerReferences); i++ {
ret[i].Kind = meta.OwnerReferences[i].Kind
ret[i].Name = meta.OwnerReferences[i].Name
ret[i].UID = meta.OwnerReferences[i].UID
ret[i].APIVersion = meta.OwnerReferences[i].APIVersion
if meta.OwnerReferences[i].Controller != nil {
value := *meta.OwnerReferences[i].Controller
ret[i].Controller = &value
}
if meta.OwnerReferences[i].BlockOwnerDeletion != nil {
value := *meta.OwnerReferences[i].BlockOwnerDeletion
ret[i].BlockOwnerDeletion = &value
}
}
return ret
}
func (meta *ObjectMeta) GetOwnerReferences() []OwnerReference { return meta.OwnerReferences }
func (meta *ObjectMeta) SetOwnerReferences(references []OwnerReference) {
if references == nil {
meta.OwnerReferences = nil
return
}
newReferences := make([]OwnerReference, len(references))
for i := 0; i < len(references); i++ {
newReferences[i].Kind = references[i].Kind
newReferences[i].Name = references[i].Name
newReferences[i].UID = references[i].UID
newReferences[i].APIVersion = references[i].APIVersion
if references[i].Controller != nil {
value := *references[i].Controller
newReferences[i].Controller = &value
}
if references[i].BlockOwnerDeletion != nil {
value := *references[i].BlockOwnerDeletion
newReferences[i].BlockOwnerDeletion = &value
}
}
meta.OwnerReferences = newReferences
meta.OwnerReferences = references
}
func (meta *ObjectMeta) GetClusterName() string {
return meta.ClusterName
}
func (meta *ObjectMeta) SetClusterName(clusterName string) {
meta.ClusterName = clusterName
func (meta *ObjectMeta) GetClusterName() string { return meta.ClusterName }
func (meta *ObjectMeta) SetClusterName(clusterName string) { meta.ClusterName = clusterName }
func (meta *ObjectMeta) GetManagedFields() []ManagedFieldsEntry { return meta.ManagedFields }
func (meta *ObjectMeta) SetManagedFields(managedFields []ManagedFieldsEntry) {
meta.ManagedFields = managedFields
}

View file

@ -19,6 +19,7 @@ package v1
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)
// GroupName is the group name for this API.
@ -52,14 +53,16 @@ func AddToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion)
&ExportOptions{},
&GetOptions{},
&DeleteOptions{},
&CreateOptions{},
&UpdateOptions{},
&PatchOptions{},
)
scheme.AddConversionFuncs(
Convert_versioned_Event_to_watch_Event,
Convert_versioned_InternalEvent_to_versioned_Event,
Convert_watch_Event_to_versioned_Event,
Convert_versioned_Event_to_versioned_InternalEvent,
)
utilruntime.Must(scheme.AddConversionFuncs(
Convert_v1_WatchEvent_To_watch_Event,
Convert_v1_InternalEvent_To_v1_WatchEvent,
Convert_watch_Event_To_v1_WatchEvent,
Convert_v1_WatchEvent_To_v1_InternalEvent,
))
// Register Unversioned types under their own special group
scheme.AddUnversionedTypes(Unversioned,
&Status{},
@ -70,8 +73,8 @@ func AddToGroupVersion(scheme *runtime.Scheme, groupVersion schema.GroupVersion)
)
// register manually. This usually goes through the SchemeBuilder, which we cannot use here.
AddConversionFuncs(scheme)
RegisterDefaults(scheme)
utilruntime.Must(AddConversionFuncs(scheme))
utilruntime.Must(RegisterDefaults(scheme))
}
// scheme is the registry for the common types that adhere to the meta v1 API spec.
@ -86,8 +89,11 @@ func init() {
&ExportOptions{},
&GetOptions{},
&DeleteOptions{},
&CreateOptions{},
&UpdateOptions{},
&PatchOptions{},
)
// register manually. This usually goes through the SchemeBuilder, which we cannot use here.
RegisterDefaults(scheme)
utilruntime.Must(RegisterDefaults(scheme))
}

View file

@ -76,9 +76,10 @@ type ListMeta struct {
// continue may be set if the user set a limit on the number of items returned, and indicates that
// the server has more data available. The value is opaque and may be used to issue another request
// to the endpoint that served this list to retrieve the next set of available objects. Continuing a
// list may not be possible if the server configuration has changed or more than a few minutes have
// passed. The resourceVersion field returned when using this continue value will be identical to
// the value in the first response.
// consistent list may not be possible if the server configuration has changed or more than a few
// minutes have passed. The resourceVersion field returned when using this continue value will be
// identical to the value in the first response, unless you have received this token from an error
// message.
Continue string `json:"continue,omitempty" protobuf:"bytes,3,opt,name=continue"`
}
@ -234,6 +235,8 @@ type ObjectMeta struct {
// When an object is created, the system will populate this list with the current set of initializers.
// Only privileged users may set or modify this list. Once it is empty, it may not be modified further
// by any user.
//
// DEPRECATED - initializers are an alpha field and will be removed in v1.15.
Initializers *Initializers `json:"initializers,omitempty" protobuf:"bytes,16,opt,name=initializers"`
// Must be empty before the object is deleted from the registry. Each entry
@ -249,6 +252,19 @@ type ObjectMeta struct {
// This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.
// +optional
ClusterName string `json:"clusterName,omitempty" protobuf:"bytes,15,opt,name=clusterName"`
// ManagedFields maps workflow-id and version to the set of fields
// that are managed by that workflow. This is mostly for internal
// housekeeping, and users typically shouldn't need to set or
// understand this field. A workflow can be the user's name, a
// controller's name, or the name of a specific apply path like
// "ci-cd". The set of fields is always in the version that the
// workflow used when modifying the object.
//
// This field is alpha and can be changed or removed without notice.
//
// +optional
ManagedFields []ManagedFieldsEntry `json:"managedFields,omitempty" protobuf:"bytes,17,rep,name=managedFields"`
}
// Initializers tracks the progress of initialization.
@ -285,8 +301,8 @@ const (
)
// OwnerReference contains enough information to let you identify an owning
// object. Currently, an owning object must be in the same namespace, so there
// is no namespace field.
// object. An owning object must be in the same namespace as the dependent, or
// be cluster-scoped, so there is no namespace field.
type OwnerReference struct {
// API version of the referent.
APIVersion string `json:"apiVersion" protobuf:"bytes,5,opt,name=apiVersion"`
@ -326,9 +342,9 @@ type ListOptions struct {
// Defaults to everything.
// +optional
FieldSelector string `json:"fieldSelector,omitempty" protobuf:"bytes,2,opt,name=fieldSelector"`
// If true, partially initialized resources are included in the response.
// +optional
IncludeUninitialized bool `json:"includeUninitialized,omitempty" protobuf:"varint,6,opt,name=includeUninitialized"`
// +k8s:deprecated=includeUninitialized,protobuf=6
// Watch for changes to the described resources and return them as a stream of
// add, update, and remove notifications. Specify resourceVersion.
// +optional
@ -363,25 +379,34 @@ type ListOptions struct {
// updated during a chunked list the version of the object that was present at the time the first list
// result was calculated is returned.
Limit int64 `json:"limit,omitempty" protobuf:"varint,7,opt,name=limit"`
// The continue option should be set when retrieving more results from the server. Since this value
// is server defined, clients may only use the continue value from a previous query result with
// identical query parameters (except for the value of continue) and the server may reject a continue
// value it does not recognize. If the specified continue value is no longer valid whether due to
// expiration (generally five to fifteen minutes) or a configuration change on the server the server
// will respond with a 410 ResourceExpired error indicating the client must restart their list without
// the continue field. This field is not supported when watch is true. Clients may start a watch from
// the last resourceVersion value returned by the server and not miss any modifications.
// The continue option should be set when retrieving more results from the server. Since this value is
// server defined, clients may only use the continue value from a previous query result with identical
// query parameters (except for the value of continue) and the server may reject a continue value it
// does not recognize. If the specified continue value is no longer valid whether due to expiration
// (generally five to fifteen minutes) or a configuration change on the server, the server will
// respond with a 410 ResourceExpired error together with a continue token. If the client needs a
// consistent list, it must restart their list without the continue field. Otherwise, the client may
// send another list request with the token received with the 410 error, the server will respond with
// a list starting from the next key, but from the latest snapshot, which is inconsistent from the
// previous list results - objects that are created, modified, or deleted after the first list request
// will be included in the response, as long as their keys are after the "next key".
//
// This field is not supported when watch is true. Clients may start a watch from the last
// resourceVersion value returned by the server and not miss any modifications.
Continue string `json:"continue,omitempty" protobuf:"bytes,8,opt,name=continue"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ExportOptions is the query options to the standard REST get call.
// Deprecated. Planned for removal in 1.18.
type ExportOptions struct {
TypeMeta `json:",inline"`
// Should this value be exported. Export strips fields that a user can not specify.
// Deprecated. Planned for removal in 1.18.
Export bool `json:"export" protobuf:"varint,1,opt,name=export"`
// Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'.
// Deprecated. Planned for removal in 1.18.
Exact bool `json:"exact" protobuf:"varint,2,opt,name=exact"`
}
@ -395,9 +420,7 @@ type GetOptions struct {
// - if it's 0, then we simply return what we currently have in cache, no guarantee;
// - if set to non zero, then the result is at least as fresh as given rv.
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,1,opt,name=resourceVersion"`
// If true, partially initialized resources are included in the response.
// +optional
IncludeUninitialized bool `json:"includeUninitialized,omitempty" protobuf:"varint,2,opt,name=includeUninitialized"`
// +k8s:deprecated=includeUninitialized,protobuf=2
}
// DeletionPropagation decides if a deletion will propagate to the dependents of
@ -418,6 +441,12 @@ const (
DeletePropagationForeground DeletionPropagation = "Foreground"
)
const (
// DryRunAll means to complete all processing stages, but don't
// persist changes to storage.
DryRunAll = "All"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// DeleteOptions may be provided when deleting an API object.
@ -453,6 +482,92 @@ type DeleteOptions struct {
// foreground.
// +optional
PropagationPolicy *DeletionPropagation `json:"propagationPolicy,omitempty" protobuf:"varint,4,opt,name=propagationPolicy"`
// When present, indicates that modifications should not be
// persisted. An invalid or unrecognized dryRun directive will
// result in an error response and no further processing of the
// request. Valid values are:
// - All: all dry run stages will be processed
// +optional
DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,5,rep,name=dryRun"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CreateOptions may be provided when creating an API object.
type CreateOptions struct {
TypeMeta `json:",inline"`
// When present, indicates that modifications should not be
// persisted. An invalid or unrecognized dryRun directive will
// result in an error response and no further processing of the
// request. Valid values are:
// - All: all dry run stages will be processed
// +optional
DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,1,rep,name=dryRun"`
// +k8s:deprecated=includeUninitialized,protobuf=2
// fieldManager is a name associated with the actor or entity
// that is making these changes. The value must be less than or
// 128 characters long, and only contain printable characters,
// as defined by https://golang.org/pkg/unicode/#IsPrint.
// +optional
FieldManager string `json:"fieldManager,omitempty" protobuf:"bytes,3,name=fieldManager"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// PatchOptions may be provided when patching an API object.
// PatchOptions is meant to be a superset of UpdateOptions.
type PatchOptions struct {
TypeMeta `json:",inline"`
// When present, indicates that modifications should not be
// persisted. An invalid or unrecognized dryRun directive will
// result in an error response and no further processing of the
// request. Valid values are:
// - All: all dry run stages will be processed
// +optional
DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,1,rep,name=dryRun"`
// Force is going to "force" Apply requests. It means user will
// re-acquire conflicting fields owned by other people. Force
// flag must be unset for non-apply patch requests.
// +optional
Force *bool `json:"force,omitempty" protobuf:"varint,2,opt,name=force"`
// fieldManager is a name associated with the actor or entity
// that is making these changes. The value must be less than or
// 128 characters long, and only contain printable characters,
// as defined by https://golang.org/pkg/unicode/#IsPrint. This
// field is required for apply requests
// (application/apply-patch) but optional for non-apply patch
// types (JsonPatch, MergePatch, StrategicMergePatch).
// +optional
FieldManager string `json:"fieldManager,omitempty" protobuf:"bytes,3,name=fieldManager"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// UpdateOptions may be provided when updating an API object.
// All fields in UpdateOptions should also be present in PatchOptions.
type UpdateOptions struct {
TypeMeta `json:",inline"`
// When present, indicates that modifications should not be
// persisted. An invalid or unrecognized dryRun directive will
// result in an error response and no further processing of the
// request. Valid values are:
// - All: all dry run stages will be processed
// +optional
DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,1,rep,name=dryRun"`
// fieldManager is a name associated with the actor or entity
// that is making these changes. The value must be less than or
// 128 characters long, and only contain printable characters,
// as defined by https://golang.org/pkg/unicode/#IsPrint.
// +optional
FieldManager string `json:"fieldManager,omitempty" protobuf:"bytes,2,name=fieldManager"`
}
// Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.
@ -460,6 +575,9 @@ type Preconditions struct {
// Specifies the target UID.
// +optional
UID *types.UID `json:"uid,omitempty" protobuf:"bytes,1,opt,name=uid,casttype=k8s.io/apimachinery/pkg/types.UID"`
// Specifies the target ResourceVersion
// +optional
ResourceVersion *string `json:"resourceVersion,omitempty" protobuf:"bytes,2,opt,name=resourceVersion"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@ -658,6 +776,10 @@ const (
// Status code 406
StatusReasonNotAcceptable StatusReason = "NotAcceptable"
// StatusReasonRequestEntityTooLarge means that the request entity is too large.
// Status code 413
StatusReasonRequestEntityTooLarge StatusReason = "RequestEntityTooLarge"
// StatusReasonUnsupportedMediaType means that the content type sent by the client is not acceptable
// to the server - for instance, attempting to send protobuf for a resource that supports only json and yaml.
// API calls that return UnsupportedMediaType can never succeed.
@ -733,6 +855,9 @@ const (
// without the expected return type. The presence of this cause indicates the error may be
// due to an intervening proxy or the server software malfunctioning.
CauseTypeUnexpectedServerResponse CauseType = "UnexpectedServerResponse"
// FieldManagerConflict is used to report when another client claims to manage this field,
// It should only be returned for a request using server-side apply.
CauseTypeFieldManagerConflict CauseType = "FieldManagerConflict"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
@ -847,6 +972,15 @@ type APIResource struct {
ShortNames []string `json:"shortNames,omitempty" protobuf:"bytes,5,rep,name=shortNames"`
// categories is a list of the grouped resources this resource belongs to (e.g. 'all')
Categories []string `json:"categories,omitempty" protobuf:"bytes,7,rep,name=categories"`
// The hash value of the storage version, the version this resource is
// converted to when written to the data store. Value must be treated
// as opaque by clients. Only equality comparison on the value is valid.
// This is an alpha feature and may change or be removed in the future.
// The field is populated by the apiserver only if the
// StorageVersionHash feature gate is enabled.
// This field will remain optional even if it graduates.
// +optional
StorageVersionHash string `json:"storageVersionHash,omitempty" protobuf:"bytes,10,opt,name=storageVersionHash"`
}
// Verbs masks the value so protobuf can generate
@ -948,3 +1082,49 @@ const (
LabelSelectorOpExists LabelSelectorOperator = "Exists"
LabelSelectorOpDoesNotExist LabelSelectorOperator = "DoesNotExist"
)
// ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource
// that the fieldset applies to.
type ManagedFieldsEntry struct {
// Manager is an identifier of the workflow managing these fields.
Manager string `json:"manager,omitempty" protobuf:"bytes,1,opt,name=manager"`
// Operation is the type of operation which lead to this ManagedFieldsEntry being created.
// The only valid values for this field are 'Apply' and 'Update'.
Operation ManagedFieldsOperationType `json:"operation,omitempty" protobuf:"bytes,2,opt,name=operation,casttype=ManagedFieldsOperationType"`
// APIVersion defines the version of this resource that this field set
// applies to. The format is "group/version" just like the top-level
// APIVersion field. It is necessary to track the version of a field
// set because it cannot be automatically converted.
APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,3,opt,name=apiVersion"`
// Time is timestamp of when these fields were set. It should always be empty if Operation is 'Apply'
// +optional
Time *Time `json:"time,omitempty" protobuf:"bytes,4,opt,name=time"`
// Fields identifies a set of fields.
// +optional
Fields *Fields `json:"fields,omitempty" protobuf:"bytes,5,opt,name=fields,casttype=Fields"`
}
// ManagedFieldsOperationType is the type of operation which lead to a ManagedFieldsEntry being created.
type ManagedFieldsOperationType string
const (
ManagedFieldsOperationApply ManagedFieldsOperationType = "Apply"
ManagedFieldsOperationUpdate ManagedFieldsOperationType = "Update"
)
// Fields stores a set of fields in a data structure like a Trie.
// To understand how this is used, see: https://github.com/kubernetes-sigs/structured-merge-diff
type Fields struct {
// Map stores a set of fields in a data structure like a Trie.
//
// Each key is either a '.' representing the field itself, and will always map to an empty set,
// or a string representing a sub-field or item. The string will follow one of these four formats:
// 'f:<name>', where <name> is the name of a field in a struct, or key in a map
// 'v:<value>', where <value> is the exact json formatted value of a list item
// 'i:<index>', where <index> is position of a item in a list
// 'k:<keys>', where <keys> is a map of a list item's key fields to their unique values
// If a key maps to an empty Fields value, the field that key represents is part of the set.
//
// The exact format is defined in k8s.io/apiserver/pkg/endpoints/handlers/fieldmanager/internal
Map map[string]Fields `json:",inline" protobuf:"bytes,1,rep,name=map"`
}

View file

@ -49,16 +49,17 @@ func (APIGroupList) SwaggerDoc() map[string]string {
}
var map_APIResource = map[string]string{
"": "APIResource specifies the name of a resource and whether it is namespaced.",
"name": "name is the plural name of the resource.",
"singularName": "singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely. The singularName is more correct for reporting status on a single item and both singular and plural are allowed from the kubectl CLI interface.",
"namespaced": "namespaced indicates if a resource is namespaced or not.",
"group": "group is the preferred group of the resource. Empty implies the group of the containing resource list. For subresources, this may have a different value, for example: Scale\".",
"version": "version is the preferred version of the resource. Empty implies the version of the containing resource list For subresources, this may have a different value, for example: v1 (while inside a v1beta1 version of the core resource's group)\".",
"kind": "kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')",
"verbs": "verbs is a list of supported kube verbs (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy)",
"shortNames": "shortNames is a list of suggested short names of the resource.",
"categories": "categories is a list of the grouped resources this resource belongs to (e.g. 'all')",
"": "APIResource specifies the name of a resource and whether it is namespaced.",
"name": "name is the plural name of the resource.",
"singularName": "singularName is the singular name of the resource. This allows clients to handle plural and singular opaquely. The singularName is more correct for reporting status on a single item and both singular and plural are allowed from the kubectl CLI interface.",
"namespaced": "namespaced indicates if a resource is namespaced or not.",
"group": "group is the preferred group of the resource. Empty implies the group of the containing resource list. For subresources, this may have a different value, for example: Scale\".",
"version": "version is the preferred version of the resource. Empty implies the version of the containing resource list For subresources, this may have a different value, for example: v1 (while inside a v1beta1 version of the core resource's group)\".",
"kind": "kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')",
"verbs": "verbs is a list of supported kube verbs (this includes get, list, watch, create, update, patch, delete, deletecollection, and proxy)",
"shortNames": "shortNames is a list of suggested short names of the resource.",
"categories": "categories is a list of the grouped resources this resource belongs to (e.g. 'all')",
"storageVersionHash": "The hash value of the storage version, the version this resource is converted to when written to the data store. Value must be treated as opaque by clients. Only equality comparison on the value is valid. This is an alpha feature and may change or be removed in the future. The field is populated by the apiserver only if the StorageVersionHash feature gate is enabled. This field will remain optional even if it graduates.",
}
func (APIResource) SwaggerDoc() map[string]string {
@ -85,12 +86,23 @@ func (APIVersions) SwaggerDoc() map[string]string {
return map_APIVersions
}
var map_CreateOptions = map[string]string{
"": "CreateOptions may be provided when creating an API object.",
"dryRun": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed",
"fieldManager": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.",
}
func (CreateOptions) SwaggerDoc() map[string]string {
return map_CreateOptions
}
var map_DeleteOptions = map[string]string{
"": "DeleteOptions may be provided when deleting an API object.",
"gracePeriodSeconds": "The duration in seconds before the object should be deleted. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period for the specified type will be used. Defaults to a per object value if not specified. zero means delete immediately.",
"preconditions": "Must be fulfilled before a deletion is carried out. If not possible, a 409 Conflict status will be returned.",
"orphanDependents": "Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7. Should the dependent objects be orphaned. If true/false, the \"orphan\" finalizer will be added to/removed from the object's finalizers list. Either this field or PropagationPolicy may be set, but not both.",
"propagationPolicy": "Whether and how garbage collection will be performed. Either this field or OrphanDependents may be set, but not both. The default policy is decided by the existing finalizer set in the metadata.finalizers and the resource-specific default policy. Acceptable values are: 'Orphan' - orphan the dependents; 'Background' - allow the garbage collector to delete the dependents in the background; 'Foreground' - a cascading policy that deletes all dependents in the foreground.",
"dryRun": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed",
}
func (DeleteOptions) SwaggerDoc() map[string]string {
@ -98,19 +110,26 @@ func (DeleteOptions) SwaggerDoc() map[string]string {
}
var map_ExportOptions = map[string]string{
"": "ExportOptions is the query options to the standard REST get call.",
"export": "Should this value be exported. Export strips fields that a user can not specify.",
"exact": "Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'.",
"": "ExportOptions is the query options to the standard REST get call. Deprecated. Planned for removal in 1.18.",
"export": "Should this value be exported. Export strips fields that a user can not specify. Deprecated. Planned for removal in 1.18.",
"exact": "Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'. Deprecated. Planned for removal in 1.18.",
}
func (ExportOptions) SwaggerDoc() map[string]string {
return map_ExportOptions
}
var map_Fields = map[string]string{
"": "Fields stores a set of fields in a data structure like a Trie. To understand how this is used, see: https://github.com/kubernetes-sigs/structured-merge-diff",
}
func (Fields) SwaggerDoc() map[string]string {
return map_Fields
}
var map_GetOptions = map[string]string{
"": "GetOptions is the standard query options to the standard REST get call.",
"resourceVersion": "When specified: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
"includeUninitialized": "If true, partially initialized resources are included in the response.",
"": "GetOptions is the standard query options to the standard REST get call.",
"resourceVersion": "When specified: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
}
func (GetOptions) SwaggerDoc() map[string]string {
@ -181,7 +200,7 @@ var map_ListMeta = map[string]string{
"": "ListMeta describes metadata that synthetic resources must have, including lists and various status objects. A resource may have only one of {ObjectMeta, ListMeta}.",
"selfLink": "selfLink is a URL representing this object. Populated by the system. Read-only.",
"resourceVersion": "String that identifies the server's internal version of this object that can be used by clients to determine when objects have changed. Value must be treated as opaque by clients and passed unmodified back to the server. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency",
"continue": "continue may be set if the user set a limit on the number of items returned, and indicates that the server has more data available. The value is opaque and may be used to issue another request to the endpoint that served this list to retrieve the next set of available objects. Continuing a list may not be possible if the server configuration has changed or more than a few minutes have passed. The resourceVersion field returned when using this continue value will be identical to the value in the first response.",
"continue": "continue may be set if the user set a limit on the number of items returned, and indicates that the server has more data available. The value is opaque and may be used to issue another request to the endpoint that served this list to retrieve the next set of available objects. Continuing a consistent list may not be possible if the server configuration has changed or more than a few minutes have passed. The resourceVersion field returned when using this continue value will be identical to the value in the first response, unless you have received this token from an error message.",
}
func (ListMeta) SwaggerDoc() map[string]string {
@ -189,21 +208,33 @@ func (ListMeta) SwaggerDoc() map[string]string {
}
var map_ListOptions = map[string]string{
"": "ListOptions is the query options to a standard REST list call.",
"labelSelector": "A selector to restrict the list of returned objects by their labels. Defaults to everything.",
"fieldSelector": "A selector to restrict the list of returned objects by their fields. Defaults to everything.",
"includeUninitialized": "If true, partially initialized resources are included in the response.",
"watch": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.",
"resourceVersion": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
"timeoutSeconds": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.",
"limit": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.",
"continue": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server the server will respond with a 410 ResourceExpired error indicating the client must restart their list without the continue field. This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.",
"": "ListOptions is the query options to a standard REST list call.",
"labelSelector": "A selector to restrict the list of returned objects by their labels. Defaults to everything.",
"fieldSelector": "A selector to restrict the list of returned objects by their fields. Defaults to everything.",
"watch": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.",
"resourceVersion": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
"timeoutSeconds": "Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.",
"limit": "limit is a maximum number of responses to return for a list call. If more items exist, the server will set the `continue` field on the list metadata to a value that can be used with the same initial query to retrieve the next set of results. Setting a limit may return fewer than the requested amount of items (up to zero items) in the event all requested objects are filtered out and clients should only use the presence of the continue field to determine whether more results are available. Servers may choose not to support the limit argument and will return all of the available results. If limit is specified and the continue field is empty, clients may assume that no more results are available. This field is not supported if watch is true.\n\nThe server guarantees that the objects returned when using continue will be identical to issuing a single list call without a limit - that is, no objects created, modified, or deleted after the first request is issued will be included in any subsequent continued requests. This is sometimes referred to as a consistent snapshot, and ensures that a client that is using limit to receive smaller chunks of a very large result can ensure they see all possible objects. If objects are updated during a chunked list the version of the object that was present at the time the first list result was calculated is returned.",
"continue": "The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\".\n\nThis field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.",
}
func (ListOptions) SwaggerDoc() map[string]string {
return map_ListOptions
}
var map_ManagedFieldsEntry = map[string]string{
"": "ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource that the fieldset applies to.",
"manager": "Manager is an identifier of the workflow managing these fields.",
"operation": "Operation is the type of operation which lead to this ManagedFieldsEntry being created. The only valid values for this field are 'Apply' and 'Update'.",
"apiVersion": "APIVersion defines the version of this resource that this field set applies to. The format is \"group/version\" just like the top-level APIVersion field. It is necessary to track the version of a field set because it cannot be automatically converted.",
"time": "Time is timestamp of when these fields were set. It should always be empty if Operation is 'Apply'",
"fields": "Fields identifies a set of fields.",
}
func (ManagedFieldsEntry) SwaggerDoc() map[string]string {
return map_ManagedFieldsEntry
}
var map_ObjectMeta = map[string]string{
"": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create.",
"name": "Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
@ -219,9 +250,10 @@ var map_ObjectMeta = map[string]string{
"labels": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels",
"annotations": "Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations",
"ownerReferences": "List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.",
"initializers": "An initializer is a controller which enforces some system invariant at object creation time. This field is a list of initializers that have not yet acted on this object. If nil or empty, this object has been completely initialized. Otherwise, the object is considered uninitialized and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to observe uninitialized objects.\n\nWhen an object is created, the system will populate this list with the current set of initializers. Only privileged users may set or modify this list. Once it is empty, it may not be modified further by any user.",
"initializers": "An initializer is a controller which enforces some system invariant at object creation time. This field is a list of initializers that have not yet acted on this object. If nil or empty, this object has been completely initialized. Otherwise, the object is considered uninitialized and is hidden (in list/watch and get calls) from clients that haven't explicitly asked to observe uninitialized objects.\n\nWhen an object is created, the system will populate this list with the current set of initializers. Only privileged users may set or modify this list. Once it is empty, it may not be modified further by any user.\n\nDEPRECATED - initializers are an alpha field and will be removed in v1.15.",
"finalizers": "Must be empty before the object is deleted from the registry. Each entry is an identifier for the responsible component that will remove the entry from the list. If the deletionTimestamp of the object is non-nil, entries in this list can only be removed.",
"clusterName": "The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.",
"managedFields": "ManagedFields maps workflow-id and version to the set of fields that are managed by that workflow. This is mostly for internal housekeeping, and users typically shouldn't need to set or understand this field. A workflow can be the user's name, a controller's name, or the name of a specific apply path like \"ci-cd\". The set of fields is always in the version that the workflow used when modifying the object.\n\nThis field is alpha and can be changed or removed without notice.",
}
func (ObjectMeta) SwaggerDoc() map[string]string {
@ -229,7 +261,7 @@ func (ObjectMeta) SwaggerDoc() map[string]string {
}
var map_OwnerReference = map[string]string{
"": "OwnerReference contains enough information to let you identify an owning object. Currently, an owning object must be in the same namespace, so there is no namespace field.",
"": "OwnerReference contains enough information to let you identify an owning object. An owning object must be in the same namespace as the dependent, or be cluster-scoped, so there is no namespace field.",
"apiVersion": "API version of the referent.",
"kind": "Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"name": "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names",
@ -250,9 +282,21 @@ func (Patch) SwaggerDoc() map[string]string {
return map_Patch
}
var map_PatchOptions = map[string]string{
"": "PatchOptions may be provided when patching an API object. PatchOptions is meant to be a superset of UpdateOptions.",
"dryRun": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed",
"force": "Force is going to \"force\" Apply requests. It means user will re-acquire conflicting fields owned by other people. Force flag must be unset for non-apply patch requests.",
"fieldManager": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. This field is required for apply requests (application/apply-patch) but optional for non-apply patch types (JsonPatch, MergePatch, StrategicMergePatch).",
}
func (PatchOptions) SwaggerDoc() map[string]string {
return map_PatchOptions
}
var map_Preconditions = map[string]string{
"": "Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.",
"uid": "Specifies the target UID.",
"": "Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.",
"uid": "Specifies the target UID.",
"resourceVersion": "Specifies the target ResourceVersion",
}
func (Preconditions) SwaggerDoc() map[string]string {
@ -327,4 +371,14 @@ func (TypeMeta) SwaggerDoc() map[string]string {
return map_TypeMeta
}
var map_UpdateOptions = map[string]string{
"": "UpdateOptions may be provided when updating an API object. All fields in UpdateOptions should also be present in PatchOptions.",
"dryRun": "When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed",
"fieldManager": "fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.",
}
func (UpdateOptions) SwaggerDoc() map[string]string {
return map_UpdateOptions
}
// AUTO-GENERATED FUNCTIONS END HERE

View file

@ -47,6 +47,9 @@ func NestedFieldNoCopy(obj map[string]interface{}, fields ...string) (interface{
var val interface{} = obj
for i, field := range fields {
if val == nil {
return nil, false, nil
}
if m, ok := val.(map[string]interface{}); ok {
val, ok = m[field]
if !ok {

View file

@ -143,13 +143,20 @@ func (u *Unstructured) setNestedField(value interface{}, fields ...string) {
SetNestedField(u.Object, value, fields...)
}
func (u *Unstructured) setNestedSlice(value []string, fields ...string) {
func (u *Unstructured) setNestedStringSlice(value []string, fields ...string) {
if u.Object == nil {
u.Object = make(map[string]interface{})
}
SetNestedStringSlice(u.Object, value, fields...)
}
func (u *Unstructured) setNestedSlice(value []interface{}, fields ...string) {
if u.Object == nil {
u.Object = make(map[string]interface{})
}
SetNestedSlice(u.Object, value, fields...)
}
func (u *Unstructured) setNestedMap(value map[string]string, fields ...string) {
if u.Object == nil {
u.Object = make(map[string]interface{})
@ -179,6 +186,11 @@ func (u *Unstructured) GetOwnerReferences() []metav1.OwnerReference {
}
func (u *Unstructured) SetOwnerReferences(references []metav1.OwnerReference) {
if references == nil {
RemoveNestedField(u.Object, "metadata", "ownerReferences")
return
}
newReferences := make([]interface{}, 0, len(references))
for _, reference := range references {
out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&reference)
@ -212,6 +224,10 @@ func (u *Unstructured) GetNamespace() string {
}
func (u *Unstructured) SetNamespace(namespace string) {
if len(namespace) == 0 {
RemoveNestedField(u.Object, "metadata", "namespace")
return
}
u.setNestedField(namespace, "metadata", "namespace")
}
@ -220,6 +236,10 @@ func (u *Unstructured) GetName() string {
}
func (u *Unstructured) SetName(name string) {
if len(name) == 0 {
RemoveNestedField(u.Object, "metadata", "name")
return
}
u.setNestedField(name, "metadata", "name")
}
@ -227,8 +247,12 @@ func (u *Unstructured) GetGenerateName() string {
return getNestedString(u.Object, "metadata", "generateName")
}
func (u *Unstructured) SetGenerateName(name string) {
u.setNestedField(name, "metadata", "generateName")
func (u *Unstructured) SetGenerateName(generateName string) {
if len(generateName) == 0 {
RemoveNestedField(u.Object, "metadata", "generateName")
return
}
u.setNestedField(generateName, "metadata", "generateName")
}
func (u *Unstructured) GetUID() types.UID {
@ -236,6 +260,10 @@ func (u *Unstructured) GetUID() types.UID {
}
func (u *Unstructured) SetUID(uid types.UID) {
if len(string(uid)) == 0 {
RemoveNestedField(u.Object, "metadata", "uid")
return
}
u.setNestedField(string(uid), "metadata", "uid")
}
@ -243,8 +271,12 @@ func (u *Unstructured) GetResourceVersion() string {
return getNestedString(u.Object, "metadata", "resourceVersion")
}
func (u *Unstructured) SetResourceVersion(version string) {
u.setNestedField(version, "metadata", "resourceVersion")
func (u *Unstructured) SetResourceVersion(resourceVersion string) {
if len(resourceVersion) == 0 {
RemoveNestedField(u.Object, "metadata", "resourceVersion")
return
}
u.setNestedField(resourceVersion, "metadata", "resourceVersion")
}
func (u *Unstructured) GetGeneration() int64 {
@ -256,6 +288,10 @@ func (u *Unstructured) GetGeneration() int64 {
}
func (u *Unstructured) SetGeneration(generation int64) {
if generation == 0 {
RemoveNestedField(u.Object, "metadata", "generation")
return
}
u.setNestedField(generation, "metadata", "generation")
}
@ -264,6 +300,10 @@ func (u *Unstructured) GetSelfLink() string {
}
func (u *Unstructured) SetSelfLink(selfLink string) {
if len(selfLink) == 0 {
RemoveNestedField(u.Object, "metadata", "selfLink")
return
}
u.setNestedField(selfLink, "metadata", "selfLink")
}
@ -272,6 +312,10 @@ func (u *Unstructured) GetContinue() string {
}
func (u *Unstructured) SetContinue(c string) {
if len(c) == 0 {
RemoveNestedField(u.Object, "metadata", "continue")
return
}
u.setNestedField(c, "metadata", "continue")
}
@ -330,6 +374,10 @@ func (u *Unstructured) GetLabels() map[string]string {
}
func (u *Unstructured) SetLabels(labels map[string]string) {
if labels == nil {
RemoveNestedField(u.Object, "metadata", "labels")
return
}
u.setNestedMap(labels, "metadata", "labels")
}
@ -339,6 +387,10 @@ func (u *Unstructured) GetAnnotations() map[string]string {
}
func (u *Unstructured) SetAnnotations(annotations map[string]string) {
if annotations == nil {
RemoveNestedField(u.Object, "metadata", "annotations")
return
}
u.setNestedMap(annotations, "metadata", "annotations")
}
@ -387,7 +439,11 @@ func (u *Unstructured) GetFinalizers() []string {
}
func (u *Unstructured) SetFinalizers(finalizers []string) {
u.setNestedSlice(finalizers, "metadata", "finalizers")
if finalizers == nil {
RemoveNestedField(u.Object, "metadata", "finalizers")
return
}
u.setNestedStringSlice(finalizers, "metadata", "finalizers")
}
func (u *Unstructured) GetClusterName() string {
@ -395,5 +451,48 @@ func (u *Unstructured) GetClusterName() string {
}
func (u *Unstructured) SetClusterName(clusterName string) {
if len(clusterName) == 0 {
RemoveNestedField(u.Object, "metadata", "clusterName")
return
}
u.setNestedField(clusterName, "metadata", "clusterName")
}
func (u *Unstructured) GetManagedFields() []metav1.ManagedFieldsEntry {
items, found, err := NestedSlice(u.Object, "metadata", "managedFields")
if !found || err != nil {
return nil
}
managedFields := []metav1.ManagedFieldsEntry{}
for _, item := range items {
m, ok := item.(map[string]interface{})
if !ok {
utilruntime.HandleError(fmt.Errorf("unable to retrieve managedFields for object, item %v is not a map", item))
return nil
}
out := metav1.ManagedFieldsEntry{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(m, &out); err != nil {
utilruntime.HandleError(fmt.Errorf("unable to retrieve managedFields for object: %v", err))
return nil
}
managedFields = append(managedFields, out)
}
return managedFields
}
func (u *Unstructured) SetManagedFields(managedFields []metav1.ManagedFieldsEntry) {
if managedFields == nil {
RemoveNestedField(u.Object, "metadata", "managedFields")
return
}
items := []interface{}{}
for _, managedFieldsEntry := range managedFields {
out, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&managedFieldsEntry)
if err != nil {
utilruntime.HandleError(fmt.Errorf("unable to set managedFields for object: %v", err))
return
}
items = append(items, out)
}
u.setNestedSlice(items, "metadata", "managedFields")
}

View file

@ -17,7 +17,12 @@ limitations under the License.
package validation
import (
"fmt"
"unicode"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field"
)
@ -84,6 +89,71 @@ func ValidateDeleteOptions(options *metav1.DeleteOptions) field.ErrorList {
*options.PropagationPolicy != metav1.DeletePropagationOrphan {
allErrs = append(allErrs, field.NotSupported(field.NewPath("propagationPolicy"), options.PropagationPolicy, []string{string(metav1.DeletePropagationForeground), string(metav1.DeletePropagationBackground), string(metav1.DeletePropagationOrphan), "nil"}))
}
allErrs = append(allErrs, ValidateDryRun(field.NewPath("dryRun"), options.DryRun)...)
return allErrs
}
func ValidateCreateOptions(options *metav1.CreateOptions) field.ErrorList {
return append(
ValidateFieldManager(options.FieldManager, field.NewPath("fieldManager")),
ValidateDryRun(field.NewPath("dryRun"), options.DryRun)...,
)
}
func ValidateUpdateOptions(options *metav1.UpdateOptions) field.ErrorList {
return append(
ValidateFieldManager(options.FieldManager, field.NewPath("fieldManager")),
ValidateDryRun(field.NewPath("dryRun"), options.DryRun)...,
)
}
func ValidatePatchOptions(options *metav1.PatchOptions, patchType types.PatchType) field.ErrorList {
allErrs := field.ErrorList{}
if patchType != types.ApplyPatchType {
if options.Force != nil {
allErrs = append(allErrs, field.Forbidden(field.NewPath("force"), "may not be specified for non-apply patch"))
}
} else {
if options.FieldManager == "" {
// This field is defaulted to "kubectl" by kubectl, but HAS TO be explicitly set by controllers.
allErrs = append(allErrs, field.Required(field.NewPath("fieldManager"), "is required for apply patch"))
}
}
allErrs = append(allErrs, ValidateFieldManager(options.FieldManager, field.NewPath("fieldManager"))...)
allErrs = append(allErrs, ValidateDryRun(field.NewPath("dryRun"), options.DryRun)...)
return allErrs
}
var FieldManagerMaxLength = 128
// ValidateFieldManager valides that the fieldManager is the proper length and
// only has printable characters.
func ValidateFieldManager(fieldManager string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
// the field can not be set as a `*string`, so a empty string ("") is
// considered as not set and is defaulted by the rest of the process
// (unless apply is used, in which case it is required).
if len(fieldManager) > FieldManagerMaxLength {
allErrs = append(allErrs, field.TooLong(fldPath, fieldManager, FieldManagerMaxLength))
}
// Verify that all characters are printable.
for i, r := range fieldManager {
if !unicode.IsPrint(r) {
allErrs = append(allErrs, field.Invalid(fldPath, fieldManager, fmt.Sprintf("invalid character %#U (at position %d)", r, i)))
}
}
return allErrs
}
var allowedDryRunValues = sets.NewString(metav1.DryRunAll)
// ValidateDryRun validates that a dryRun query param only contains allowed values.
func ValidateDryRun(fldPath *field.Path, dryRun []string) field.ErrorList {
allErrs := field.ErrorList{}
if !allowedDryRunValues.HasAll(dryRun...) {
allErrs = append(allErrs, field.NotSupported(fldPath, dryRun, allowedDryRunValues.List()))
}
return allErrs
}

View file

@ -39,7 +39,7 @@ type WatchEvent struct {
Object runtime.RawExtension `json:"object" protobuf:"bytes,2,opt,name=object"`
}
func Convert_watch_Event_to_versioned_Event(in *watch.Event, out *WatchEvent, s conversion.Scope) error {
func Convert_watch_Event_To_v1_WatchEvent(in *watch.Event, out *WatchEvent, s conversion.Scope) error {
out.Type = string(in.Type)
switch t := in.Object.(type) {
case *runtime.Unknown:
@ -52,11 +52,11 @@ func Convert_watch_Event_to_versioned_Event(in *watch.Event, out *WatchEvent, s
return nil
}
func Convert_versioned_InternalEvent_to_versioned_Event(in *InternalEvent, out *WatchEvent, s conversion.Scope) error {
return Convert_watch_Event_to_versioned_Event((*watch.Event)(in), out, s)
func Convert_v1_InternalEvent_To_v1_WatchEvent(in *InternalEvent, out *WatchEvent, s conversion.Scope) error {
return Convert_watch_Event_To_v1_WatchEvent((*watch.Event)(in), out, s)
}
func Convert_versioned_Event_to_watch_Event(in *WatchEvent, out *watch.Event, s conversion.Scope) error {
func Convert_v1_WatchEvent_To_watch_Event(in *WatchEvent, out *watch.Event, s conversion.Scope) error {
out.Type = watch.EventType(in.Type)
if in.Object.Object != nil {
out.Object = in.Object.Object
@ -70,8 +70,8 @@ func Convert_versioned_Event_to_watch_Event(in *WatchEvent, out *watch.Event, s
return nil
}
func Convert_versioned_Event_to_versioned_InternalEvent(in *WatchEvent, out *InternalEvent, s conversion.Scope) error {
return Convert_versioned_Event_to_watch_Event(in, (*watch.Event)(out), s)
func Convert_v1_WatchEvent_To_v1_InternalEvent(in *WatchEvent, out *InternalEvent, s conversion.Scope) error {
return Convert_v1_WatchEvent_To_watch_Event(in, (*watch.Event)(out), s)
}
// InternalEvent makes watch.Event versioned

View file

@ -191,45 +191,64 @@ func (in *APIVersions) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CreateOptions) DeepCopyInto(out *CreateOptions) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.DryRun != nil {
in, out := &in.DryRun, &out.DryRun
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CreateOptions.
func (in *CreateOptions) DeepCopy() *CreateOptions {
if in == nil {
return nil
}
out := new(CreateOptions)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *CreateOptions) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DeleteOptions) DeepCopyInto(out *DeleteOptions) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.GracePeriodSeconds != nil {
in, out := &in.GracePeriodSeconds, &out.GracePeriodSeconds
if *in == nil {
*out = nil
} else {
*out = new(int64)
**out = **in
}
*out = new(int64)
**out = **in
}
if in.Preconditions != nil {
in, out := &in.Preconditions, &out.Preconditions
if *in == nil {
*out = nil
} else {
*out = new(Preconditions)
(*in).DeepCopyInto(*out)
}
*out = new(Preconditions)
(*in).DeepCopyInto(*out)
}
if in.OrphanDependents != nil {
in, out := &in.OrphanDependents, &out.OrphanDependents
if *in == nil {
*out = nil
} else {
*out = new(bool)
**out = **in
}
*out = new(bool)
**out = **in
}
if in.PropagationPolicy != nil {
in, out := &in.PropagationPolicy, &out.PropagationPolicy
if *in == nil {
*out = nil
} else {
*out = new(DeletionPropagation)
**out = **in
}
*out = new(DeletionPropagation)
**out = **in
}
if in.DryRun != nil {
in, out := &in.DryRun, &out.DryRun
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
@ -293,6 +312,29 @@ func (in *ExportOptions) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Fields) DeepCopyInto(out *Fields) {
*out = *in
if in.Map != nil {
in, out := &in.Map, &out.Map
*out = make(map[string]Fields, len(*in))
for key, val := range *in {
(*out)[key] = *val.DeepCopy()
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Fields.
func (in *Fields) DeepCopy() *Fields {
if in == nil {
return nil
}
out := new(Fields)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GetOptions) DeepCopyInto(out *GetOptions) {
*out = *in
@ -440,12 +482,8 @@ func (in *Initializers) DeepCopyInto(out *Initializers) {
}
if in.Result != nil {
in, out := &in.Result, &out.Result
if *in == nil {
*out = nil
} else {
*out = new(Status)
(*in).DeepCopyInto(*out)
}
*out = new(Status)
(*in).DeepCopyInto(*out)
}
return
}
@ -463,9 +501,7 @@ func (in *Initializers) DeepCopy() *Initializers {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InternalEvent) DeepCopyInto(out *InternalEvent) {
*out = *in
if in.Object == nil {
out.Object = nil
} else {
if in.Object != nil {
out.Object = in.Object.DeepCopyObject()
}
return
@ -587,12 +623,8 @@ func (in *ListOptions) DeepCopyInto(out *ListOptions) {
out.TypeMeta = in.TypeMeta
if in.TimeoutSeconds != nil {
in, out := &in.TimeoutSeconds, &out.TimeoutSeconds
if *in == nil {
*out = nil
} else {
*out = new(int64)
**out = **in
}
*out = new(int64)
**out = **in
}
return
}
@ -615,6 +647,31 @@ func (in *ListOptions) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ManagedFieldsEntry) DeepCopyInto(out *ManagedFieldsEntry) {
*out = *in
if in.Time != nil {
in, out := &in.Time, &out.Time
*out = (*in).DeepCopy()
}
if in.Fields != nil {
in, out := &in.Fields, &out.Fields
*out = new(Fields)
(*in).DeepCopyInto(*out)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedFieldsEntry.
func (in *ManagedFieldsEntry) DeepCopy() *ManagedFieldsEntry {
if in == nil {
return nil
}
out := new(ManagedFieldsEntry)
in.DeepCopyInto(out)
return out
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MicroTime.
func (in *MicroTime) DeepCopy() *MicroTime {
if in == nil {
@ -631,20 +688,12 @@ func (in *ObjectMeta) DeepCopyInto(out *ObjectMeta) {
in.CreationTimestamp.DeepCopyInto(&out.CreationTimestamp)
if in.DeletionTimestamp != nil {
in, out := &in.DeletionTimestamp, &out.DeletionTimestamp
if *in == nil {
*out = nil
} else {
*out = (*in).DeepCopy()
}
*out = (*in).DeepCopy()
}
if in.DeletionGracePeriodSeconds != nil {
in, out := &in.DeletionGracePeriodSeconds, &out.DeletionGracePeriodSeconds
if *in == nil {
*out = nil
} else {
*out = new(int64)
**out = **in
}
*out = new(int64)
**out = **in
}
if in.Labels != nil {
in, out := &in.Labels, &out.Labels
@ -669,18 +718,21 @@ func (in *ObjectMeta) DeepCopyInto(out *ObjectMeta) {
}
if in.Initializers != nil {
in, out := &in.Initializers, &out.Initializers
if *in == nil {
*out = nil
} else {
*out = new(Initializers)
(*in).DeepCopyInto(*out)
}
*out = new(Initializers)
(*in).DeepCopyInto(*out)
}
if in.Finalizers != nil {
in, out := &in.Finalizers, &out.Finalizers
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ManagedFields != nil {
in, out := &in.ManagedFields, &out.ManagedFields
*out = make([]ManagedFieldsEntry, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
@ -699,21 +751,13 @@ func (in *OwnerReference) DeepCopyInto(out *OwnerReference) {
*out = *in
if in.Controller != nil {
in, out := &in.Controller, &out.Controller
if *in == nil {
*out = nil
} else {
*out = new(bool)
**out = **in
}
*out = new(bool)
**out = **in
}
if in.BlockOwnerDeletion != nil {
in, out := &in.BlockOwnerDeletion, &out.BlockOwnerDeletion
if *in == nil {
*out = nil
} else {
*out = new(bool)
**out = **in
}
*out = new(bool)
**out = **in
}
return
}
@ -744,17 +788,53 @@ func (in *Patch) DeepCopy() *Patch {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PatchOptions) DeepCopyInto(out *PatchOptions) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.DryRun != nil {
in, out := &in.DryRun, &out.DryRun
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Force != nil {
in, out := &in.Force, &out.Force
*out = new(bool)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PatchOptions.
func (in *PatchOptions) DeepCopy() *PatchOptions {
if in == nil {
return nil
}
out := new(PatchOptions)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PatchOptions) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Preconditions) DeepCopyInto(out *Preconditions) {
*out = *in
if in.UID != nil {
in, out := &in.UID, &out.UID
if *in == nil {
*out = nil
} else {
*out = new(types.UID)
**out = **in
}
*out = new(types.UID)
**out = **in
}
if in.ResourceVersion != nil {
in, out := &in.ResourceVersion, &out.ResourceVersion
*out = new(string)
**out = **in
}
return
}
@ -813,12 +893,8 @@ func (in *Status) DeepCopyInto(out *Status) {
out.ListMeta = in.ListMeta
if in.Details != nil {
in, out := &in.Details, &out.Details
if *in == nil {
*out = nil
} else {
*out = new(StatusDetails)
(*in).DeepCopyInto(*out)
}
*out = new(StatusDetails)
(*in).DeepCopyInto(*out)
}
return
}
@ -904,6 +980,36 @@ func (in *Timestamp) DeepCopy() *Timestamp {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UpdateOptions) DeepCopyInto(out *UpdateOptions) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.DryRun != nil {
in, out := &in.DryRun, &out.DryRun
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateOptions.
func (in *UpdateOptions) DeepCopy() *UpdateOptions {
if in == nil {
return nil
}
out := new(UpdateOptions)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *UpdateOptions) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in Verbs) DeepCopyInto(out *Verbs) {
{

View file

@ -19,4 +19,5 @@ limitations under the License.
// +k8s:defaulter-gen=TypeMeta
// +groupName=meta.k8s.io
package v1beta1
package v1beta1 // import "k8s.io/apimachinery/pkg/apis/meta/v1beta1"

View file

@ -14,9 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by protoc-gen-gogo.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1/generated.proto
// DO NOT EDIT!
/*
Package v1beta1 is a generated protocol buffer package.
@ -148,24 +147,6 @@ func (m *TableOptions) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
dAtA[offset+4] = uint8(v >> 32)
dAtA[offset+5] = uint8(v >> 40)
dAtA[offset+6] = uint8(v >> 48)
dAtA[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)

View file

@ -58,11 +58,10 @@ func (in *PartialObjectMetadataList) DeepCopyInto(out *PartialObjectMetadataList
in, out := &in.Items, &out.Items
*out = make([]*PartialObjectMetadata, len(*in))
for i := range *in {
if (*in)[i] == nil {
(*out)[i] = nil
} else {
(*out)[i] = new(PartialObjectMetadata)
(*in)[i].DeepCopyInto((*out)[i])
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(PartialObjectMetadata)
(*in).DeepCopyInto(*out)
}
}
}

View file

@ -40,7 +40,11 @@ type NameFunc func(t reflect.Type) string
var DefaultNameFunc = func(t reflect.Type) string { return t.Name() }
type GenericConversionFunc func(a, b interface{}, scope Scope) (bool, error)
// ConversionFunc converts the object a into the object b, reusing arrays or objects
// or pointers if necessary. It should return an error if the object cannot be converted
// or if some data is invalid. If you do not wish a and b to share fields or nested
// objects, you must copy a before calling this function.
type ConversionFunc func(a, b interface{}, scope Scope) error
// Converter knows how to convert one type to another.
type Converter struct {
@ -49,11 +53,6 @@ type Converter struct {
conversionFuncs ConversionFuncs
generatedConversionFuncs ConversionFuncs
// genericConversions are called during normal conversion to offer a "fast-path"
// that avoids all reflection. These methods are not called outside of the .Convert()
// method.
genericConversions []GenericConversionFunc
// Set of conversions that should be treated as a no-op
ignoredConversions map[typePair]struct{}
@ -98,14 +97,6 @@ func NewConverter(nameFn NameFunc) *Converter {
return c
}
// AddGenericConversionFunc adds a function that accepts the ConversionFunc call pattern
// (for two conversion types) to the converter. These functions are checked first during
// a normal conversion, but are otherwise not called. Use AddConversionFuncs when registering
// typed conversions.
func (c *Converter) AddGenericConversionFunc(fn GenericConversionFunc) {
c.genericConversions = append(c.genericConversions, fn)
}
// WithConversions returns a Converter that is a copy of c but with the additional
// fns merged on top.
func (c *Converter) WithConversions(fns ConversionFuncs) *Converter {
@ -161,11 +152,15 @@ type Scope interface {
type FieldMappingFunc func(key string, sourceTag, destTag reflect.StructTag) (source string, dest string)
func NewConversionFuncs() ConversionFuncs {
return ConversionFuncs{fns: make(map[typePair]reflect.Value)}
return ConversionFuncs{
fns: make(map[typePair]reflect.Value),
untyped: make(map[typePair]ConversionFunc),
}
}
type ConversionFuncs struct {
fns map[typePair]reflect.Value
fns map[typePair]reflect.Value
untyped map[typePair]ConversionFunc
}
// Add adds the provided conversion functions to the lookup table - they must have the signature
@ -183,6 +178,21 @@ func (c ConversionFuncs) Add(fns ...interface{}) error {
return nil
}
// AddUntyped adds the provided conversion function to the lookup table for the types that are
// supplied as a and b. a and b must be pointers or an error is returned. This method overwrites
// previously defined functions.
func (c ConversionFuncs) AddUntyped(a, b interface{}, fn ConversionFunc) error {
tA, tB := reflect.TypeOf(a), reflect.TypeOf(b)
if tA.Kind() != reflect.Ptr {
return fmt.Errorf("the type %T must be a pointer to register as an untyped conversion", a)
}
if tB.Kind() != reflect.Ptr {
return fmt.Errorf("the type %T must be a pointer to register as an untyped conversion", b)
}
c.untyped[typePair{tA, tB}] = fn
return nil
}
// Merge returns a new ConversionFuncs that contains all conversions from
// both other and c, with other conversions taking precedence.
func (c ConversionFuncs) Merge(other ConversionFuncs) ConversionFuncs {
@ -193,6 +203,12 @@ func (c ConversionFuncs) Merge(other ConversionFuncs) ConversionFuncs {
for k, v := range other.fns {
merged.fns[k] = v
}
for k, v := range c.untyped {
merged.untyped[k] = v
}
for k, v := range other.untyped {
merged.untyped[k] = v
}
return merged
}
@ -355,16 +371,32 @@ func verifyConversionFunctionSignature(ft reflect.Type) error {
// // conversion logic...
// return nil
// })
// DEPRECATED: Will be removed in favor of RegisterUntypedConversionFunc
func (c *Converter) RegisterConversionFunc(conversionFunc interface{}) error {
return c.conversionFuncs.Add(conversionFunc)
}
// Similar to RegisterConversionFunc, but registers conversion function that were
// automatically generated.
// DEPRECATED: Will be removed in favor of RegisterGeneratedUntypedConversionFunc
func (c *Converter) RegisterGeneratedConversionFunc(conversionFunc interface{}) error {
return c.generatedConversionFuncs.Add(conversionFunc)
}
// RegisterUntypedConversionFunc registers a function that converts between a and b by passing objects of those
// types to the provided function. The function *must* accept objects of a and b - this machinery will not enforce
// any other guarantee.
func (c *Converter) RegisterUntypedConversionFunc(a, b interface{}, fn ConversionFunc) error {
return c.conversionFuncs.AddUntyped(a, b, fn)
}
// RegisterGeneratedUntypedConversionFunc registers a function that converts between a and b by passing objects of those
// types to the provided function. The function *must* accept objects of a and b - this machinery will not enforce
// any other guarantee.
func (c *Converter) RegisterGeneratedUntypedConversionFunc(a, b interface{}, fn ConversionFunc) error {
return c.generatedConversionFuncs.AddUntyped(a, b, fn)
}
// RegisterIgnoredConversion registers a "no-op" for conversion, where any requested
// conversion between from and to is ignored.
func (c *Converter) RegisterIgnoredConversion(from, to interface{}) error {
@ -380,39 +412,6 @@ func (c *Converter) RegisterIgnoredConversion(from, to interface{}) error {
return nil
}
// IsConversionIgnored returns true if the specified objects should be dropped during
// conversion.
func (c *Converter) IsConversionIgnored(inType, outType reflect.Type) bool {
_, found := c.ignoredConversions[typePair{inType, outType}]
return found
}
func (c *Converter) HasConversionFunc(inType, outType reflect.Type) bool {
_, found := c.conversionFuncs.fns[typePair{inType, outType}]
return found
}
func (c *Converter) ConversionFuncValue(inType, outType reflect.Type) (reflect.Value, bool) {
value, found := c.conversionFuncs.fns[typePair{inType, outType}]
return value, found
}
// SetStructFieldCopy registers a correspondence. Whenever a struct field is encountered
// which has a type and name matching srcFieldType and srcFieldName, it wil be copied
// into the field in the destination struct matching destFieldType & Name, if such a
// field exists.
// May be called multiple times, even for the same source field & type--all applicable
// copies will be performed.
func (c *Converter) SetStructFieldCopy(srcFieldType interface{}, srcFieldName string, destFieldType interface{}, destFieldName string) error {
st := reflect.TypeOf(srcFieldType)
dt := reflect.TypeOf(destFieldType)
srcKey := typeNamePair{st, srcFieldName}
destKey := typeNamePair{dt, destFieldName}
c.structFieldDests[srcKey] = append(c.structFieldDests[srcKey], destKey)
c.structFieldSources[destKey] = append(c.structFieldSources[destKey], srcKey)
return nil
}
// RegisterInputDefaults registers a field name mapping function, used when converting
// from maps to structs. Inputs to the conversion methods are checked for this type and a mapping
// applied automatically if the input matches in. A set of default flags for the input conversion
@ -468,15 +467,6 @@ func (f FieldMatchingFlags) IsSet(flag FieldMatchingFlags) bool {
// it is not used by Convert() other than storing it in the scope.
// Not safe for objects with cyclic references!
func (c *Converter) Convert(src, dest interface{}, flags FieldMatchingFlags, meta *Meta) error {
if len(c.genericConversions) > 0 {
// TODO: avoid scope allocation
s := &scope{converter: c, flags: flags, meta: meta}
for _, fn := range c.genericConversions {
if ok, err := fn(src, dest, s); ok {
return err
}
}
}
return c.doConversion(src, dest, flags, meta, c.convert)
}
@ -495,6 +485,21 @@ func (c *Converter) DefaultConvert(src, dest interface{}, flags FieldMatchingFla
type conversionFunc func(sv, dv reflect.Value, scope *scope) error
func (c *Converter) doConversion(src, dest interface{}, flags FieldMatchingFlags, meta *Meta, f conversionFunc) error {
pair := typePair{reflect.TypeOf(src), reflect.TypeOf(dest)}
scope := &scope{
converter: c,
flags: flags,
meta: meta,
}
if fn, ok := c.conversionFuncs.untyped[pair]; ok {
return fn(src, dest, scope)
}
if fn, ok := c.generatedConversionFuncs.untyped[pair]; ok {
return fn(src, dest, scope)
}
// TODO: consider everything past this point deprecated - we want to support only point to point top level
// conversions
dv, err := EnforcePtr(dest)
if err != nil {
return err
@ -506,15 +511,10 @@ func (c *Converter) doConversion(src, dest interface{}, flags FieldMatchingFlags
if err != nil {
return err
}
s := &scope{
converter: c,
flags: flags,
meta: meta,
}
// Leave something on the stack, so that calls to struct tag getters never fail.
s.srcStack.push(scopeStackElem{})
s.destStack.push(scopeStackElem{})
return f(sv, dv, s)
scope.srcStack.push(scopeStackElem{})
scope.destStack.push(scopeStackElem{})
return f(sv, dv, scope)
}
// callCustom calls 'custom' with sv & dv. custom must be a conversion function.

View file

@ -23,10 +23,10 @@ import (
"strconv"
"strings"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/selection"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/klog"
)
// Requirements is AND of all requirements.
@ -211,13 +211,13 @@ func (r *Requirement) Matches(ls Labels) bool {
}
lsValue, err := strconv.ParseInt(ls.Get(r.key), 10, 64)
if err != nil {
glog.V(10).Infof("ParseInt failed for value %+v in label %+v, %+v", ls.Get(r.key), ls, err)
klog.V(10).Infof("ParseInt failed for value %+v in label %+v, %+v", ls.Get(r.key), ls, err)
return false
}
// There should be only one strValue in r.strValues, and can be converted to a integer.
if len(r.strValues) != 1 {
glog.V(10).Infof("Invalid values count %+v of requirement %#v, for 'Gt', 'Lt' operators, exactly one value is required", len(r.strValues), r)
klog.V(10).Infof("Invalid values count %+v of requirement %#v, for 'Gt', 'Lt' operators, exactly one value is required", len(r.strValues), r)
return false
}
@ -225,7 +225,7 @@ func (r *Requirement) Matches(ls Labels) bool {
for i := range r.strValues {
rValue, err = strconv.ParseInt(r.strValues[i], 10, 64)
if err != nil {
glog.V(10).Infof("ParseInt failed for value %+v in requirement %#v, for 'Gt', 'Lt' operators, the value must be an integer", r.strValues[i], r)
klog.V(10).Infof("ParseInt failed for value %+v in requirement %#v, for 'Gt', 'Lt' operators, the value must be an integer", r.strValues[i], r)
return false
}
}

View file

@ -76,24 +76,6 @@ func EncodeOrDie(e Encoder, obj Object) string {
return string(bytes)
}
// DefaultingSerializer invokes defaulting after decoding.
type DefaultingSerializer struct {
Defaulter ObjectDefaulter
Decoder Decoder
// Encoder is optional to allow this type to be used as both a Decoder and an Encoder
Encoder
}
// Decode performs a decode and then allows the defaulter to act on the provided object.
func (d DefaultingSerializer) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into Object) (Object, *schema.GroupVersionKind, error) {
obj, gvk, err := d.Decoder.Decode(data, defaultGVK, into)
if err != nil {
return obj, gvk, err
}
d.Defaulter.Default(obj)
return obj, gvk, nil
}
// UseOrCreateObject returns obj if the canonical ObjectKind returned by the provided typer matches gvk, or
// invokes the ObjectCreator to instantiate a new gvk. Returns an error if the typer cannot find the object.
func UseOrCreateObject(t ObjectTyper, c ObjectCreater, gvk schema.GroupVersionKind, obj Object) (Object, error) {
@ -301,6 +283,7 @@ var _ GroupVersioner = multiGroupVersioner{}
type multiGroupVersioner struct {
target schema.GroupVersion
acceptedGroupKinds []schema.GroupKind
coerce bool
}
// NewMultiGroupVersioner returns the provided group version for any kind that matches one of the provided group kinds.
@ -312,6 +295,22 @@ func NewMultiGroupVersioner(gv schema.GroupVersion, groupKinds ...schema.GroupKi
return multiGroupVersioner{target: gv, acceptedGroupKinds: groupKinds}
}
// NewCoercingMultiGroupVersioner returns the provided group version for any incoming kind.
// Incoming kinds that match the provided groupKinds are preferred.
// Kind may be empty in the provided group kind, in which case any kind will match.
// Examples:
// gv=mygroup/__internal, groupKinds=mygroup/Foo, anothergroup/Bar
// KindForGroupVersionKinds(yetanother/v1/Baz, anothergroup/v1/Bar) -> mygroup/__internal/Bar (matched preferred group/kind)
//
// gv=mygroup/__internal, groupKinds=mygroup, anothergroup
// KindForGroupVersionKinds(yetanother/v1/Baz, anothergroup/v1/Bar) -> mygroup/__internal/Bar (matched preferred group)
//
// gv=mygroup/__internal, groupKinds=mygroup, anothergroup
// KindForGroupVersionKinds(yetanother/v1/Baz, yetanother/v1/Bar) -> mygroup/__internal/Baz (no preferred group/kind match, uses first kind in list)
func NewCoercingMultiGroupVersioner(gv schema.GroupVersion, groupKinds ...schema.GroupKind) GroupVersioner {
return multiGroupVersioner{target: gv, acceptedGroupKinds: groupKinds, coerce: true}
}
// KindForGroupVersionKinds returns the target group version if any kind matches any of the original group kinds. It will
// use the originating kind where possible.
func (v multiGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (schema.GroupVersionKind, bool) {
@ -326,5 +325,8 @@ func (v multiGroupVersioner) KindForGroupVersionKinds(kinds []schema.GroupVersio
return v.target.WithKind(src.Kind), true
}
}
if v.coerce && len(kinds) > 0 {
return v.target.WithKind(kinds[0].Kind), true
}
return schema.GroupVersionKind{}, false
}

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Defines conversions between generic types and structs to map query strings
// Package runtime defines conversions between generic types and structs to map query strings
// to struct objects.
package runtime
@ -27,7 +27,7 @@ import (
"k8s.io/apimachinery/pkg/conversion"
)
// DefaultFieldSelectorConversion auto-accepts metav1 values for name and namespace.
// DefaultMetaV1FieldSelectorConversion auto-accepts metav1 values for name and namespace.
// A cluster scoped resource specifying namespace empty works fine and specifying a particular
// namespace will return no results, as expected.
func DefaultMetaV1FieldSelectorConversion(label, value string) (string, string, error) {
@ -82,7 +82,7 @@ func Convert_Slice_string_To_int(input *[]string, out *int, s conversion.Scope)
return nil
}
// Conver_Slice_string_To_bool will convert a string parameter to boolean.
// Convert_Slice_string_To_bool will convert a string parameter to boolean.
// Only the absence of a value, a value of "false", or a value of "0" resolve to false.
// Any other value (including empty string) resolves to true.
func Convert_Slice_string_To_bool(input *[]string, out *bool, s conversion.Scope) error {

View file

@ -33,7 +33,7 @@ import (
"k8s.io/apimachinery/pkg/util/json"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"github.com/golang/glog"
"k8s.io/klog"
)
// UnstructuredConverter is an interface for converting between interface{}
@ -133,10 +133,10 @@ func (c *unstructuredConverter) FromUnstructured(u map[string]interface{}, obj i
newObj := reflect.New(t.Elem()).Interface()
newErr := fromUnstructuredViaJSON(u, newObj)
if (err != nil) != (newErr != nil) {
glog.Fatalf("FromUnstructured unexpected error for %v: error: %v", u, err)
klog.Fatalf("FromUnstructured unexpected error for %v: error: %v", u, err)
}
if err == nil && !c.comparison.DeepEqual(obj, newObj) {
glog.Fatalf("FromUnstructured mismatch\nobj1: %#v\nobj2: %#v", obj, newObj)
klog.Fatalf("FromUnstructured mismatch\nobj1: %#v\nobj2: %#v", obj, newObj)
}
}
return err
@ -424,10 +424,10 @@ func (c *unstructuredConverter) ToUnstructured(obj interface{}) (map[string]inte
newUnstr := map[string]interface{}{}
newErr := toUnstructuredViaJSON(obj, &newUnstr)
if (err != nil) != (newErr != nil) {
glog.Fatalf("ToUnstructured unexpected error for %v: error: %v; newErr: %v", obj, err, newErr)
klog.Fatalf("ToUnstructured unexpected error for %v: error: %v; newErr: %v", obj, err, newErr)
}
if err == nil && !c.comparison.DeepEqual(u, newUnstr) {
glog.Fatalf("ToUnstructured mismatch\nobj1: %#v\nobj2: %#v", u, newUnstr)
klog.Fatalf("ToUnstructured mismatch\nobj1: %#v\nobj2: %#v", u, newUnstr)
}
}
if err != nil {
@ -746,7 +746,7 @@ func isZero(v reflect.Value) bool {
func structToUnstructured(sv, dv reflect.Value) error {
st, dt := sv.Type(), dv.Type()
if dt.Kind() == reflect.Interface && dv.NumMethod() == 0 {
dv.Set(reflect.MakeMap(mapStringInterfaceType))
dv.Set(reflect.MakeMapWithSize(mapStringInterfaceType, st.NumField()))
dv = dv.Elem()
dt = dv.Type()
}

View file

@ -18,20 +18,27 @@ limitations under the License.
// that follow the kubernetes API object conventions, which are:
//
// 0. Your API objects have a common metadata struct member, TypeMeta.
//
// 1. Your code refers to an internal set of API objects.
//
// 2. In a separate package, you have an external set of API objects.
//
// 3. The external set is considered to be versioned, and no breaking
// changes are ever made to it (fields may be added but not changed
// or removed).
// changes are ever made to it (fields may be added but not changed
// or removed).
//
// 4. As your api evolves, you'll make an additional versioned package
// with every major change.
// with every major change.
//
// 5. Versioned packages have conversion functions which convert to
// and from the internal version.
// and from the internal version.
//
// 6. You'll continue to support older versions according to your
// deprecation policy, and you can easily provide a program/library
// to update old versions into new versions because of 5.
// deprecation policy, and you can easily provide a program/library
// to update old versions into new versions because of 5.
//
// 7. All of your serializations and deserializations are handled in a
// centralized place.
// centralized place.
//
// Package runtime provides a conversion helper to make 5 easy, and the
// Encode/Decode/DecodeInto trio to accomplish 7. You can also register
@ -41,5 +48,4 @@ limitations under the License.
//
// As a bonus, a few common types useful from all api objects and versions
// are provided in types.go.
package runtime // import "k8s.io/apimachinery/pkg/runtime"

View file

@ -31,7 +31,7 @@ type encodable struct {
func (e encodable) GetObjectKind() schema.ObjectKind { return e.obj.GetObjectKind() }
func (e encodable) DeepCopyObject() Object {
var out encodable = e
out := e
out.obj = e.obj.DeepCopyObject()
copy(out.versions, e.versions)
return out
@ -46,14 +46,14 @@ func NewEncodable(e Encoder, obj Object, versions ...schema.GroupVersion) Object
return encodable{e, obj, versions}
}
func (re encodable) UnmarshalJSON(in []byte) error {
func (e encodable) UnmarshalJSON(in []byte) error {
return errors.New("runtime.encodable cannot be unmarshalled from JSON")
}
// Marshal may get called on pointers or values, so implement MarshalJSON on value.
// http://stackoverflow.com/questions/21390979/custom-marshaljson-never-gets-called-in-go
func (re encodable) MarshalJSON() ([]byte, error) {
return Encode(re.E, re.obj)
func (e encodable) MarshalJSON() ([]byte, error) {
return Encode(e.E, e.obj)
}
// NewEncodableList creates an object that will be encoded with the provided codec on demand.
@ -70,28 +70,28 @@ func NewEncodableList(e Encoder, objects []Object, versions ...schema.GroupVersi
return out
}
func (re *Unknown) UnmarshalJSON(in []byte) error {
if re == nil {
func (e *Unknown) UnmarshalJSON(in []byte) error {
if e == nil {
return errors.New("runtime.Unknown: UnmarshalJSON on nil pointer")
}
re.TypeMeta = TypeMeta{}
re.Raw = append(re.Raw[0:0], in...)
re.ContentEncoding = ""
re.ContentType = ContentTypeJSON
e.TypeMeta = TypeMeta{}
e.Raw = append(e.Raw[0:0], in...)
e.ContentEncoding = ""
e.ContentType = ContentTypeJSON
return nil
}
// Marshal may get called on pointers or values, so implement MarshalJSON on value.
// http://stackoverflow.com/questions/21390979/custom-marshaljson-never-gets-called-in-go
func (re Unknown) MarshalJSON() ([]byte, error) {
func (e Unknown) MarshalJSON() ([]byte, error) {
// If ContentType is unset, we assume this is JSON.
if re.ContentType != "" && re.ContentType != ContentTypeJSON {
if e.ContentType != "" && e.ContentType != ContentTypeJSON {
return nil, errors.New("runtime.Unknown: MarshalJSON on non-json data")
}
if re.Raw == nil {
if e.Raw == nil {
return []byte("null"), nil
}
return re.Raw, nil
return e.Raw, nil
}
func Convert_runtime_Object_To_runtime_RawExtension(in *Object, out *RawExtension, s conversion.Scope) error {

View file

@ -24,46 +24,47 @@ import (
)
type notRegisteredErr struct {
gvk schema.GroupVersionKind
target GroupVersioner
t reflect.Type
schemeName string
gvk schema.GroupVersionKind
target GroupVersioner
t reflect.Type
}
func NewNotRegisteredErrForKind(gvk schema.GroupVersionKind) error {
return &notRegisteredErr{gvk: gvk}
func NewNotRegisteredErrForKind(schemeName string, gvk schema.GroupVersionKind) error {
return &notRegisteredErr{schemeName: schemeName, gvk: gvk}
}
func NewNotRegisteredErrForType(t reflect.Type) error {
return &notRegisteredErr{t: t}
func NewNotRegisteredErrForType(schemeName string, t reflect.Type) error {
return &notRegisteredErr{schemeName: schemeName, t: t}
}
func NewNotRegisteredErrForTarget(t reflect.Type, target GroupVersioner) error {
return &notRegisteredErr{t: t, target: target}
func NewNotRegisteredErrForTarget(schemeName string, t reflect.Type, target GroupVersioner) error {
return &notRegisteredErr{schemeName: schemeName, t: t, target: target}
}
func NewNotRegisteredGVKErrForTarget(gvk schema.GroupVersionKind, target GroupVersioner) error {
return &notRegisteredErr{gvk: gvk, target: target}
func NewNotRegisteredGVKErrForTarget(schemeName string, gvk schema.GroupVersionKind, target GroupVersioner) error {
return &notRegisteredErr{schemeName: schemeName, gvk: gvk, target: target}
}
func (k *notRegisteredErr) Error() string {
if k.t != nil && k.target != nil {
return fmt.Sprintf("%v is not suitable for converting to %q", k.t, k.target)
return fmt.Sprintf("%v is not suitable for converting to %q in scheme %q", k.t, k.target, k.schemeName)
}
nullGVK := schema.GroupVersionKind{}
if k.gvk != nullGVK && k.target != nil {
return fmt.Sprintf("%q is not suitable for converting to %q", k.gvk.GroupVersion(), k.target)
return fmt.Sprintf("%q is not suitable for converting to %q in scheme %q", k.gvk.GroupVersion(), k.target, k.schemeName)
}
if k.t != nil {
return fmt.Sprintf("no kind is registered for the type %v", k.t)
return fmt.Sprintf("no kind is registered for the type %v in scheme %q", k.t, k.schemeName)
}
if len(k.gvk.Kind) == 0 {
return fmt.Sprintf("no version %q has been registered", k.gvk.GroupVersion())
return fmt.Sprintf("no version %q has been registered in scheme %q", k.gvk.GroupVersion(), k.schemeName)
}
if k.gvk.Version == APIVersionInternal {
return fmt.Sprintf("no kind %q is registered for the internal version of group %q", k.gvk.Kind, k.gvk.Group)
return fmt.Sprintf("no kind %q is registered for the internal version of group %q in scheme %q", k.gvk.Kind, k.gvk.Group, k.schemeName)
}
return fmt.Sprintf("no kind %q is registered for version %q", k.gvk.Kind, k.gvk.GroupVersion())
return fmt.Sprintf("no kind %q is registered for version %q in scheme %q", k.gvk.Kind, k.gvk.GroupVersion(), k.schemeName)
}
// IsNotRegisteredError returns true if the error indicates the provided

View file

@ -32,7 +32,7 @@ func (re *RawExtension) UnmarshalJSON(in []byte) error {
return nil
}
// Marshal may get called on pointers or values, so implement MarshalJSON on value.
// MarshalJSON may get called on pointers or values, so implement MarshalJSON on value.
// http://stackoverflow.com/questions/21390979/custom-marshaljson-never-gets-called-in-go
func (re RawExtension) MarshalJSON() ([]byte, error) {
if re.Raw == nil {

View file

@ -14,9 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by protoc-gen-gogo.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime/generated.proto
// DO NOT EDIT!
/*
Package runtime is a generated protocol buffer package.
@ -158,24 +157,6 @@ func (m *Unknown) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
dAtA[offset+4] = uint8(v >> 32)
dAtA[offset+5] = uint8(v >> 40)
dAtA[offset+6] = uint8(v >> 48)
dAtA[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)

View file

@ -25,11 +25,11 @@ package k8s.io.apimachinery.pkg.runtime;
option go_package = "runtime";
// RawExtension is used to hold extensions in external versions.
//
//
// To use this, make a field which has RawExtension as its type in your external, versioned
// struct, and Object in your internal struct. You also need to register your
// various plugin types.
//
//
// // Internal package:
// type MyAPIObject struct {
// runtime.TypeMeta `json:",inline"`
@ -38,7 +38,7 @@ option go_package = "runtime";
// type PluginA struct {
// AOption string `json:"aOption"`
// }
//
//
// // External package:
// type MyAPIObject struct {
// runtime.TypeMeta `json:",inline"`
@ -47,7 +47,7 @@ option go_package = "runtime";
// type PluginA struct {
// AOption string `json:"aOption"`
// }
//
//
// // On the wire, the JSON will look something like this:
// {
// "kind":"MyAPIObject",
@ -57,7 +57,7 @@ option go_package = "runtime";
// "aOption":"foo",
// },
// }
//
//
// So what happens? Decode first uses json or yaml to unmarshal the serialized data into
// your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked.
// The next step is to copy (using pkg/conversion) into the internal struct. The runtime
@ -65,13 +65,13 @@ option go_package = "runtime";
// JSON stored in RawExtension, turning it into the correct object type, and storing it
// in the Object. (TODO: In the case where the object is of an unknown type, a
// runtime.Unknown object will be created and stored.)
//
//
// +k8s:deepcopy-gen=true
// +protobuf=true
// +k8s:openapi-gen=true
message RawExtension {
// Raw is the underlying serialization of this object.
//
//
// TODO: Determine how to detect ContentType and ContentEncoding of 'Raw' data.
optional bytes raw = 1;
}
@ -83,10 +83,10 @@ message RawExtension {
// ... // other fields
// }
// func (obj *MyAwesomeAPIObject) SetGroupVersionKind(gvk *metav1.GroupVersionKind) { metav1.UpdateTypeMeta(obj,gvk) }; GroupVersionKind() *GroupVersionKind
//
//
// TypeMeta is provided here for convenience. You may use it directly from this package or define
// your own with the same fields.
//
//
// +k8s:deepcopy-gen=false
// +protobuf=true
// +k8s:openapi-gen=true
@ -103,7 +103,7 @@ message TypeMeta {
// TypeMeta features-- kind, version, etc.
// TODO: Make this object have easy access to field based accessors and settors for
// metadata and field mutatation.
//
//
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +protobuf=true

View file

@ -87,7 +87,7 @@ func Field(v reflect.Value, fieldName string, dest interface{}) error {
return fmt.Errorf("couldn't assign/convert %v to %v", field.Type(), destValue.Type())
}
// fieldPtr puts the address of fieldName, which must be a member of v,
// FieldPtr puts the address of fieldName, which must be a member of v,
// into dest, which must be an address of a variable to which this field's
// address can be assigned.
func FieldPtr(v reflect.Value, fieldName string, dest interface{}) error {

View file

@ -39,14 +39,14 @@ type GroupVersioner interface {
KindForGroupVersionKinds(kinds []schema.GroupVersionKind) (target schema.GroupVersionKind, ok bool)
}
// Encoders write objects to a serialized form
// Encoder writes objects to a serialized form
type Encoder interface {
// Encode writes an object to a stream. Implementations may return errors if the versions are
// incompatible, or if no conversion is defined.
Encode(obj Object, w io.Writer) error
}
// Decoders attempt to load an object from data.
// Decoder attempts to load an object from data.
type Decoder interface {
// Decode attempts to deserialize the provided data using either the innate typing of the scheme or the
// default kind, group, and version provided. It returns a decoded object as well as the kind, group, and
@ -185,7 +185,7 @@ type ObjectConvertor interface {
// This method is similar to Convert() but handles specific details of choosing the correct
// output version.
ConvertToVersion(in Object, gv GroupVersioner) (out Object, err error)
ConvertFieldLabel(version, kind, label, value string) (string, string, error)
ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error)
}
// ObjectTyper contains methods for extracting the APIVersion and Kind
@ -224,7 +224,7 @@ type SelfLinker interface {
Namespace(obj Object) (string, error)
}
// All API types registered with Scheme must support the Object interface. Since objects in a scheme are
// Object interface must be supported by all API types registered with Scheme. Since objects in a scheme are
// expected to be serialized to the wire, the interface an Object must provide to the Scheme allows
// serializers to set the kind, version, and group the object is represented as. An Object may choose
// to return a no-op ObjectKindAccessor in cases where it is not expected to be serialized.

View file

@ -14,9 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by protoc-gen-gogo.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/runtime/schema/generated.proto
// DO NOT EDIT!
/*
Package schema is a generated protocol buffer package.

View file

@ -66,7 +66,7 @@ func (gr GroupResource) Empty() bool {
return len(gr.Group) == 0 && len(gr.Resource) == 0
}
func (gr *GroupResource) String() string {
func (gr GroupResource) String() string {
if len(gr.Group) == 0 {
return gr.Resource
}
@ -85,11 +85,10 @@ func ParseGroupKind(gk string) GroupKind {
// ParseGroupResource turns "resource.group" string into a GroupResource struct. Empty strings are allowed
// for each field.
func ParseGroupResource(gr string) GroupResource {
if i := strings.Index(gr, "."); i == -1 {
return GroupResource{Resource: gr}
} else {
if i := strings.Index(gr, "."); i >= 0 {
return GroupResource{Group: gr[i+1:], Resource: gr[:i]}
}
return GroupResource{Resource: gr}
}
// GroupVersionResource unambiguously identifies a resource. It doesn't anonymously include GroupVersion
@ -112,7 +111,7 @@ func (gvr GroupVersionResource) GroupVersion() GroupVersion {
return GroupVersion{Group: gvr.Group, Version: gvr.Version}
}
func (gvr *GroupVersionResource) String() string {
func (gvr GroupVersionResource) String() string {
return strings.Join([]string{gvr.Group, "/", gvr.Version, ", Resource=", gvr.Resource}, "")
}
@ -131,7 +130,7 @@ func (gk GroupKind) WithVersion(version string) GroupVersionKind {
return GroupVersionKind{Group: gk.Group, Version: version, Kind: gk.Kind}
}
func (gk *GroupKind) String() string {
func (gk GroupKind) String() string {
if len(gk.Group) == 0 {
return gk.Kind
}
@ -282,8 +281,8 @@ func bestMatch(kinds []GroupVersionKind, targets []GroupVersionKind) GroupVersio
// ToAPIVersionAndKind is a convenience method for satisfying runtime.Object on types that
// do not use TypeMeta.
func (gvk *GroupVersionKind) ToAPIVersionAndKind() (string, string) {
if gvk == nil {
func (gvk GroupVersionKind) ToAPIVersionAndKind() (string, string) {
if gvk.Empty() {
return "", ""
}
return gvk.GroupVersion().String(), gvk.Kind

View file

@ -20,11 +20,12 @@ import (
"fmt"
"net/url"
"reflect"
"strings"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/naming"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/sets"
)
@ -62,14 +63,14 @@ type Scheme struct {
// Map from version and resource to the corresponding func to convert
// resource field labels in that version to internal version.
fieldLabelConversionFuncs map[string]map[string]FieldLabelConversionFunc
fieldLabelConversionFuncs map[schema.GroupVersionKind]FieldLabelConversionFunc
// defaulterFuncs is an array of interfaces to be called with an object to provide defaulting
// the provided object must be a pointer.
defaulterFuncs map[reflect.Type]func(interface{})
// converter stores all registered conversion functions. It also has
// default coverting behavior.
// default converting behavior.
converter *conversion.Converter
// versionPriority is a map of groups to ordered lists of versions for those groups indicating the
@ -78,9 +79,13 @@ type Scheme struct {
// observedVersions keeps track of the order we've seen versions during type registration
observedVersions []schema.GroupVersion
// schemeName is the name of this scheme. If you don't specify a name, the stack of the NewScheme caller will be used.
// This is useful for error reporting to indicate the origin of the scheme.
schemeName string
}
// Function to convert a field selector to internal representation.
// FieldLabelConversionFunc converts a field selector to internal representation.
type FieldLabelConversionFunc func(label, value string) (internalLabel, internalValue string, err error)
// NewScheme creates a new Scheme. This scheme is pluggable by default.
@ -90,24 +95,19 @@ func NewScheme() *Scheme {
typeToGVK: map[reflect.Type][]schema.GroupVersionKind{},
unversionedTypes: map[reflect.Type]schema.GroupVersionKind{},
unversionedKinds: map[string]reflect.Type{},
fieldLabelConversionFuncs: map[string]map[string]FieldLabelConversionFunc{},
fieldLabelConversionFuncs: map[schema.GroupVersionKind]FieldLabelConversionFunc{},
defaulterFuncs: map[reflect.Type]func(interface{}){},
versionPriority: map[string][]string{},
schemeName: naming.GetNameFromCallsite(internalPackages...),
}
s.converter = conversion.NewConverter(s.nameFunc)
s.AddConversionFuncs(DefaultEmbeddedConversions()...)
utilruntime.Must(s.AddConversionFuncs(DefaultEmbeddedConversions()...))
// Enable map[string][]string conversions by default
if err := s.AddConversionFuncs(DefaultStringConversions...); err != nil {
panic(err)
}
if err := s.RegisterInputDefaults(&map[string][]string{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields); err != nil {
panic(err)
}
if err := s.RegisterInputDefaults(&url.Values{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields); err != nil {
panic(err)
}
utilruntime.Must(s.AddConversionFuncs(DefaultStringConversions...))
utilruntime.Must(s.RegisterInputDefaults(&map[string][]string{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields))
utilruntime.Must(s.RegisterInputDefaults(&url.Values{}, JSONKeyMapper, conversion.AllowDifferentFieldTypeNames|conversion.IgnoreMissingFields))
return s
}
@ -159,7 +159,7 @@ func (s *Scheme) AddUnversionedTypes(version schema.GroupVersion, types ...Objec
gvk := version.WithKind(t.Name())
s.unversionedTypes[t] = gvk
if old, ok := s.unversionedKinds[gvk.Kind]; ok && t != old {
panic(fmt.Sprintf("%v.%v has already been registered as unversioned kind %q - kind name must be unique", old.PkgPath(), old.Name(), gvk))
panic(fmt.Sprintf("%v.%v has already been registered as unversioned kind %q - kind name must be unique in scheme %q", old.PkgPath(), old.Name(), gvk, s.schemeName))
}
s.unversionedKinds[gvk.Kind] = t
}
@ -200,7 +200,7 @@ func (s *Scheme) AddKnownTypeWithName(gvk schema.GroupVersionKind, obj Object) {
}
if oldT, found := s.gvkToType[gvk]; found && oldT != t {
panic(fmt.Sprintf("Double registration of different types for %v: old=%v.%v, new=%v.%v", gvk, oldT.PkgPath(), oldT.Name(), t.PkgPath(), t.Name()))
panic(fmt.Sprintf("Double registration of different types for %v: old=%v.%v, new=%v.%v in scheme %q", gvk, oldT.PkgPath(), oldT.Name(), t.PkgPath(), t.Name(), s.schemeName))
}
s.gvkToType[gvk] = t
@ -255,7 +255,7 @@ func (s *Scheme) ObjectKinds(obj Object) ([]schema.GroupVersionKind, bool, error
gvks, ok := s.typeToGVK[t]
if !ok {
return nil, false, NewNotRegisteredErrForType(t)
return nil, false, NewNotRegisteredErrForType(s.schemeName, t)
}
_, unversionedType := s.unversionedTypes[t]
@ -293,15 +293,7 @@ func (s *Scheme) New(kind schema.GroupVersionKind) (Object, error) {
if t, exists := s.unversionedKinds[kind.Kind]; exists {
return reflect.New(t).Interface().(Object), nil
}
return nil, NewNotRegisteredErrForKind(kind)
}
// AddGenericConversionFunc adds a function that accepts the ConversionFunc call pattern
// (for two conversion types) to the converter. These functions are checked first during
// a normal conversion, but are otherwise not called. Use AddConversionFuncs when registering
// typed conversions.
func (s *Scheme) AddGenericConversionFunc(fn conversion.GenericConversionFunc) {
s.converter.AddGenericConversionFunc(fn)
return nil, NewNotRegisteredErrForKind(s.schemeName, kind)
}
// Log sets a logger on the scheme. For test purposes only
@ -355,36 +347,27 @@ func (s *Scheme) AddConversionFuncs(conversionFuncs ...interface{}) error {
return nil
}
// AddGeneratedConversionFuncs registers conversion functions that were
// automatically generated.
func (s *Scheme) AddGeneratedConversionFuncs(conversionFuncs ...interface{}) error {
for _, f := range conversionFuncs {
if err := s.converter.RegisterGeneratedConversionFunc(f); err != nil {
return err
}
}
return nil
// AddConversionFunc registers a function that converts between a and b by passing objects of those
// types to the provided function. The function *must* accept objects of a and b - this machinery will not enforce
// any other guarantee.
func (s *Scheme) AddConversionFunc(a, b interface{}, fn conversion.ConversionFunc) error {
return s.converter.RegisterUntypedConversionFunc(a, b, fn)
}
// AddGeneratedConversionFunc registers a function that converts between a and b by passing objects of those
// types to the provided function. The function *must* accept objects of a and b - this machinery will not enforce
// any other guarantee.
func (s *Scheme) AddGeneratedConversionFunc(a, b interface{}, fn conversion.ConversionFunc) error {
return s.converter.RegisterGeneratedUntypedConversionFunc(a, b, fn)
}
// AddFieldLabelConversionFunc adds a conversion function to convert field selectors
// of the given kind from the given version to internal version representation.
func (s *Scheme) AddFieldLabelConversionFunc(version, kind string, conversionFunc FieldLabelConversionFunc) error {
if s.fieldLabelConversionFuncs[version] == nil {
s.fieldLabelConversionFuncs[version] = map[string]FieldLabelConversionFunc{}
}
s.fieldLabelConversionFuncs[version][kind] = conversionFunc
func (s *Scheme) AddFieldLabelConversionFunc(gvk schema.GroupVersionKind, conversionFunc FieldLabelConversionFunc) error {
s.fieldLabelConversionFuncs[gvk] = conversionFunc
return nil
}
// AddStructFieldConversion allows you to specify a mechanical copy for a moved
// or renamed struct field without writing an entire conversion function. See
// the comment in conversion.Converter.SetStructFieldCopy for parameter details.
// Call as many times as needed, even on the same fields.
func (s *Scheme) AddStructFieldConversion(srcFieldType interface{}, srcFieldName string, destFieldType interface{}, destFieldName string) error {
return s.converter.SetStructFieldCopy(srcFieldType, srcFieldName, destFieldType, destFieldName)
}
// RegisterInputDefaults sets the provided field mapping function and field matching
// as the defaults for the provided input type. The fn may be nil, in which case no
// mapping will happen by default. Use this method to register a mechanism for handling
@ -393,7 +376,7 @@ func (s *Scheme) RegisterInputDefaults(in interface{}, fn conversion.FieldMappin
return s.converter.RegisterInputDefaults(in, fn, defaultFlags)
}
// AddTypeDefaultingFuncs registers a function that is passed a pointer to an
// AddTypeDefaultingFunc registers a function that is passed a pointer to an
// object and can default fields on the object. These functions will be invoked
// when Default() is called. The function will never be called unless the
// defaulted object matches srcType. If this function is invoked twice with the
@ -486,11 +469,8 @@ func (s *Scheme) Convert(in, out interface{}, context interface{}) error {
// ConvertFieldLabel alters the given field label and value for an kind field selector from
// versioned representation to an unversioned one or returns an error.
func (s *Scheme) ConvertFieldLabel(version, kind, label, value string) (string, string, error) {
if s.fieldLabelConversionFuncs[version] == nil {
return DefaultMetaV1FieldSelectorConversion(label, value)
}
conversionFunc, ok := s.fieldLabelConversionFuncs[version][kind]
func (s *Scheme) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
conversionFunc, ok := s.fieldLabelConversionFuncs[gvk]
if !ok {
return DefaultMetaV1FieldSelectorConversion(label, value)
}
@ -541,7 +521,7 @@ func (s *Scheme) convertToVersion(copy bool, in Object, target GroupVersioner) (
kinds, ok := s.typeToGVK[t]
if !ok || len(kinds) == 0 {
return nil, NewNotRegisteredErrForType(t)
return nil, NewNotRegisteredErrForType(s.schemeName, t)
}
gvk, ok := target.KindForGroupVersionKinds(kinds)
@ -554,7 +534,7 @@ func (s *Scheme) convertToVersion(copy bool, in Object, target GroupVersioner) (
}
return copyAndSetTargetKind(copy, in, unversionedKind)
}
return nil, NewNotRegisteredErrForTarget(t, target)
return nil, NewNotRegisteredErrForTarget(s.schemeName, t, target)
}
// target wants to use the existing type, set kind and return (no conversion necessary)
@ -764,3 +744,11 @@ func (s *Scheme) addObservedVersion(version schema.GroupVersion) {
s.observedVersions = append(s.observedVersions, version)
}
func (s *Scheme) Name() string {
return s.schemeName
}
// internalPackages are packages that ignored when creating a default reflector name. These packages are in the common
// call chains to NewReflector, so they'd be low entropy names for reflectors
var internalPackages = []string{"k8s.io/apimachinery/pkg/runtime/scheme.go"}

View file

@ -22,8 +22,9 @@ import (
"strconv"
"unsafe"
"github.com/ghodss/yaml"
jsoniter "github.com/json-iterator/go"
"github.com/modern-go/reflect2"
"sigs.k8s.io/yaml"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
@ -68,43 +69,60 @@ type Serializer struct {
var _ runtime.Serializer = &Serializer{}
var _ recognizer.RecognizingDecoder = &Serializer{}
func init() {
// Force jsoniter to decode number to interface{} via ints, if possible.
decodeNumberAsInt64IfPossible := func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
switch iter.WhatIsNext() {
case jsoniter.NumberValue:
var number json.Number
iter.ReadVal(&number)
i64, err := strconv.ParseInt(string(number), 10, 64)
if err == nil {
*(*interface{})(ptr) = i64
return
}
f64, err := strconv.ParseFloat(string(number), 64)
if err == nil {
*(*interface{})(ptr) = f64
return
}
// Not much we can do here.
default:
*(*interface{})(ptr) = iter.Read()
}
type customNumberExtension struct {
jsoniter.DummyExtension
}
func (cne *customNumberExtension) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder {
if typ.String() == "interface {}" {
return customNumberDecoder{}
}
return nil
}
type customNumberDecoder struct {
}
func (customNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
switch iter.WhatIsNext() {
case jsoniter.NumberValue:
var number jsoniter.Number
iter.ReadVal(&number)
i64, err := strconv.ParseInt(string(number), 10, 64)
if err == nil {
*(*interface{})(ptr) = i64
return
}
f64, err := strconv.ParseFloat(string(number), 64)
if err == nil {
*(*interface{})(ptr) = f64
return
}
iter.ReportError("DecodeNumber", err.Error())
default:
*(*interface{})(ptr) = iter.Read()
}
jsoniter.RegisterTypeDecoderFunc("interface {}", decodeNumberAsInt64IfPossible)
}
// CaseSensitiveJsonIterator returns a jsoniterator API that's configured to be
// case-sensitive when unmarshalling, and otherwise compatible with
// the encoding/json standard library.
func CaseSensitiveJsonIterator() jsoniter.API {
return jsoniter.Config{
config := jsoniter.Config{
EscapeHTML: true,
SortMapKeys: true,
ValidateJsonRawMessage: true,
CaseSensitive: true,
}.Froze()
// Force jsoniter to decode number to interface{} via int64/float64, if possible.
config.RegisterExtension(&customNumberExtension{})
return config
}
// Private copy of jsoniter to try to shield against possible mutations
// from outside. Still does not protect from package level jsoniter.Register*() functions - someone calling them
// in some other library will mess with every usage of the jsoniter library in the whole program.
// See https://github.com/json-iterator/go/issues/265
var caseSensitiveJsonIterator = CaseSensitiveJsonIterator()
// gvkWithDefaults returns group kind and version defaulting from provided default
@ -255,7 +273,7 @@ func (jsonFramer) NewFrameReader(r io.ReadCloser) io.ReadCloser {
return framer.NewJSONFramedReader(r)
}
// Framer is the default JSON framing behavior, with newlines delimiting individual objects.
// YAMLFramer is the default JSON framing behavior, with newlines delimiting individual objects.
var YAMLFramer = yamlFramer{}
type yamlFramer struct{}

View file

@ -20,10 +20,12 @@ import (
"bytes"
"fmt"
"io"
"net/http"
"reflect"
"github.com/gogo/protobuf/proto"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
@ -50,6 +52,15 @@ func (e errNotMarshalable) Error() string {
return fmt.Sprintf("object %v does not implement the protobuf marshalling interface and cannot be encoded to a protobuf message", e.t)
}
func (e errNotMarshalable) Status() metav1.Status {
return metav1.Status{
Status: metav1.StatusFailure,
Code: http.StatusNotAcceptable,
Reason: metav1.StatusReason("NotAcceptable"),
Message: e.Error(),
}
}
func IsNotMarshalable(err error) bool {
_, ok := err.(errNotMarshalable)
return err != nil && ok

View file

@ -64,7 +64,7 @@ func NewDecoder(r io.ReadCloser, d runtime.Decoder) Decoder {
reader: r,
decoder: d,
buf: make([]byte, 1024),
maxBytes: 1024 * 1024,
maxBytes: 16 * 1024 * 1024,
}
}

View file

@ -18,24 +18,13 @@ package versioning
import (
"io"
"reflect"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// NewCodecForScheme is a convenience method for callers that are using a scheme.
func NewCodecForScheme(
// TODO: I should be a scheme interface?
scheme *runtime.Scheme,
encoder runtime.Encoder,
decoder runtime.Decoder,
encodeVersion runtime.GroupVersioner,
decodeVersion runtime.GroupVersioner,
) runtime.Codec {
return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, nil, encodeVersion, decodeVersion)
}
// NewDefaultingCodecForScheme is a convenience method for callers that are using a scheme.
func NewDefaultingCodecForScheme(
// TODO: I should be a scheme interface?
@ -45,7 +34,7 @@ func NewDefaultingCodecForScheme(
encodeVersion runtime.GroupVersioner,
decodeVersion runtime.GroupVersioner,
) runtime.Codec {
return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, scheme, encodeVersion, decodeVersion)
return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, scheme, encodeVersion, decodeVersion, scheme.Name())
}
// NewCodec takes objects in their internal versions and converts them to external versions before
@ -60,6 +49,7 @@ func NewCodec(
defaulter runtime.ObjectDefaulter,
encodeVersion runtime.GroupVersioner,
decodeVersion runtime.GroupVersioner,
originalSchemeName string,
) runtime.Codec {
internal := &codec{
encoder: encoder,
@ -71,6 +61,8 @@ func NewCodec(
encodeVersion: encodeVersion,
decodeVersion: decodeVersion,
originalSchemeName: originalSchemeName,
}
return internal
}
@ -85,6 +77,9 @@ type codec struct {
encodeVersion runtime.GroupVersioner
decodeVersion runtime.GroupVersioner
// originalSchemeName is optional, but when filled in it holds the name of the scheme from which this codec originates
originalSchemeName string
}
// Decode attempts a decode of the object, then tries to convert it to the internal version. If into is provided and the decoding is
@ -96,7 +91,16 @@ func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into ru
into = versioned.Last()
}
obj, gvk, err := c.decoder.Decode(data, defaultGVK, into)
// If the into object is unstructured and expresses an opinion about its group/version,
// create a new instance of the type so we always exercise the conversion path (skips short-circuiting on `into == obj`)
decodeInto := into
if into != nil {
if _, ok := into.(runtime.Unstructured); ok && !into.GetObjectKind().GroupVersionKind().GroupVersion().Empty() {
decodeInto = reflect.New(reflect.TypeOf(into).Elem()).Interface().(runtime.Object)
}
}
obj, gvk, err := c.decoder.Decode(data, defaultGVK, decodeInto)
if err != nil {
return nil, gvk, err
}
@ -182,7 +186,7 @@ func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
}
targetGVK, ok := c.encodeVersion.KindForGroupVersionKinds([]schema.GroupVersionKind{objGVK})
if !ok {
return runtime.NewNotRegisteredGVKErrForTarget(objGVK, c.encodeVersion)
return runtime.NewNotRegisteredGVKErrForTarget(c.originalSchemeName, objGVK, c.encodeVersion)
}
if targetGVK == objGVK {
return c.encoder.Encode(obj, w)

View file

@ -42,6 +42,7 @@ type TypeMeta struct {
const (
ContentTypeJSON string = "application/json"
ContentTypeYAML string = "application/yaml"
)
// RawExtension is used to hold extensions in external versions.

View file

@ -28,9 +28,7 @@ func (in *RawExtension) DeepCopyInto(out *RawExtension) {
*out = make([]byte, len(*in))
copy(*out, *in)
}
if in.Object == nil {
out.Object = nil
} else {
if in.Object != nil {
out.Object = in.Object.DeepCopyObject()
}
return
@ -83,9 +81,7 @@ func (in *VersionedObjects) DeepCopyInto(out *VersionedObjects) {
in, out := &in.Objects, &out.Objects
*out = make([]Object, len(*in))
for i := range *in {
if (*in)[i] == nil {
(*out)[i] = nil
} else {
if (*in)[i] != nil {
(*out)[i] = (*in)[i].DeepCopyObject()
}
}

View file

@ -25,4 +25,5 @@ const (
JSONPatchType PatchType = "application/json-patch+json"
MergePatchType PatchType = "application/merge-patch+json"
StrategicMergePatchType PatchType = "application/strategic-merge-patch+json"
ApplyPatchType PatchType = "application/apply-patch+yaml"
)

View file

@ -108,6 +108,14 @@ func limit(aObj, bObj interface{}, max int) (string, string) {
elidedASuffix := ""
elidedBSuffix := ""
a, b := fmt.Sprintf("%#v", aObj), fmt.Sprintf("%#v", bObj)
if aObj != nil && bObj != nil {
if aType, bType := fmt.Sprintf("%T", aObj), fmt.Sprintf("%T", bObj); aType != bType {
a = fmt.Sprintf("%s (%s)", a, aType)
b = fmt.Sprintf("%s (%s)", b, bType)
}
}
for {
switch {
case len(a) > max && len(a) > 4 && len(b) > 4 && a[:4] == b[:4]:

View file

@ -19,6 +19,8 @@ package errors
import (
"errors"
"fmt"
"k8s.io/apimachinery/pkg/util/sets"
)
// MessageCountMap contains occurrence for each error message.
@ -67,12 +69,38 @@ func (agg aggregate) Error() string {
if len(agg) == 1 {
return agg[0].Error()
}
result := fmt.Sprintf("[%s", agg[0].Error())
for i := 1; i < len(agg); i++ {
result += fmt.Sprintf(", %s", agg[i].Error())
seenerrs := sets.NewString()
result := ""
agg.visit(func(err error) {
msg := err.Error()
if seenerrs.Has(msg) {
return
}
seenerrs.Insert(msg)
if len(seenerrs) > 1 {
result += ", "
}
result += msg
})
if len(seenerrs) == 1 {
return result
}
return "[" + result + "]"
}
func (agg aggregate) visit(f func(err error)) {
for _, err := range agg {
switch err := err.(type) {
case aggregate:
err.visit(f)
case Aggregate:
for _, nestedErr := range err.Errors() {
f(nestedErr)
}
default:
f(err)
}
}
result += "]"
return result
}
// Errors is part of the Aggregate interface.

View file

@ -14,9 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by protoc-gen-gogo.
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: k8s.io/kubernetes/vendor/k8s.io/apimachinery/pkg/util/intstr/generated.proto
// DO NOT EDIT!
/*
Package intstr is a generated protocol buffer package.
@ -81,24 +80,6 @@ func (m *IntOrString) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
dAtA[offset+4] = uint8(v >> 32)
dAtA[offset+5] = uint8(v >> 40)
dAtA[offset+6] = uint8(v >> 48)
dAtA[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
dAtA[offset] = uint8(v)
dAtA[offset+1] = uint8(v >> 8)
dAtA[offset+2] = uint8(v >> 16)
dAtA[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)

View file

@ -29,7 +29,7 @@ option go_package = "intstr";
// inner type. This allows you to have, for example, a JSON field that can
// accept a name or number.
// TODO: Rename to Int32OrString
//
//
// +protobuf=true
// +protobuf.options.(gogoproto.goproto_stringer)=false
// +k8s:openapi-gen=true

View file

@ -18,14 +18,15 @@ package intstr
import (
"encoding/json"
"errors"
"fmt"
"math"
"runtime/debug"
"strconv"
"strings"
"github.com/golang/glog"
"github.com/google/gofuzz"
"k8s.io/klog"
)
// IntOrString is a type that can hold an int32 or a string. When used in
@ -57,7 +58,7 @@ const (
// TODO: convert to (val int32)
func FromInt(val int) IntOrString {
if val > math.MaxInt32 || val < math.MinInt32 {
glog.Errorf("value: %d overflows int32\n%s\n", val, debug.Stack())
klog.Errorf("value: %d overflows int32\n%s\n", val, debug.Stack())
}
return IntOrString{Type: Int, IntVal: int32(val)}
}
@ -142,7 +143,17 @@ func (intstr *IntOrString) Fuzz(c fuzz.Continue) {
}
}
func ValueOrDefault(intOrPercent *IntOrString, defaultValue IntOrString) *IntOrString {
if intOrPercent == nil {
return &defaultValue
}
return intOrPercent
}
func GetValueFromIntOrPercent(intOrPercent *IntOrString, total int, roundUp bool) (int, error) {
if intOrPercent == nil {
return 0, errors.New("nil value for IntOrString")
}
value, isPercent, err := getIntOrPercentValue(intOrPercent)
if err != nil {
return 0, fmt.Errorf("invalid value for IntOrString: %v", err)

View file

@ -1,3 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- pwittrock
reviewers:

View file

@ -21,7 +21,7 @@ import (
"reflect"
"github.com/davecgh/go-spew/spew"
"github.com/ghodss/yaml"
"sigs.k8s.io/yaml"
)
// PreconditionFunc asserts that an incompatible change is not present within a patch.
@ -125,7 +125,7 @@ func HasConflicts(left, right interface{}) (bool, error) {
default:
return true, nil
}
case string, float64, bool, int, int64, nil:
case string, float64, bool, int64, nil:
return !reflect.DeepEqual(left, right), nil
default:
return true, fmt.Errorf("unknown type: %v", reflect.TypeOf(left))

View file

@ -0,0 +1,93 @@
/*
Copyright 2018 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 naming
import (
"fmt"
"regexp"
goruntime "runtime"
"runtime/debug"
"strconv"
"strings"
)
// GetNameFromCallsite walks back through the call stack until we find a caller from outside of the ignoredPackages
// it returns back a shortpath/filename:line to aid in identification of this reflector when it starts logging
func GetNameFromCallsite(ignoredPackages ...string) string {
name := "????"
const maxStack = 10
for i := 1; i < maxStack; i++ {
_, file, line, ok := goruntime.Caller(i)
if !ok {
file, line, ok = extractStackCreator()
if !ok {
break
}
i += maxStack
}
if hasPackage(file, append(ignoredPackages, "/runtime/asm_")) {
continue
}
file = trimPackagePrefix(file)
name = fmt.Sprintf("%s:%d", file, line)
break
}
return name
}
// hasPackage returns true if the file is in one of the ignored packages.
func hasPackage(file string, ignoredPackages []string) bool {
for _, ignoredPackage := range ignoredPackages {
if strings.Contains(file, ignoredPackage) {
return true
}
}
return false
}
// trimPackagePrefix reduces duplicate values off the front of a package name.
func trimPackagePrefix(file string) string {
if l := strings.LastIndex(file, "/vendor/"); l >= 0 {
return file[l+len("/vendor/"):]
}
if l := strings.LastIndex(file, "/src/"); l >= 0 {
return file[l+5:]
}
if l := strings.LastIndex(file, "/pkg/"); l >= 0 {
return file[l+1:]
}
return file
}
var stackCreator = regexp.MustCompile(`(?m)^created by (.*)\n\s+(.*):(\d+) \+0x[[:xdigit:]]+$`)
// extractStackCreator retrieves the goroutine file and line that launched this stack. Returns false
// if the creator cannot be located.
// TODO: Go does not expose this via runtime https://github.com/golang/go/issues/11440
func extractStackCreator() (string, int, bool) {
stack := debug.Stack()
matches := stackCreator.FindStringSubmatch(string(stack))
if matches == nil || len(matches) != 4 {
return "", 0, false
}
line, err := strconv.Atoi(matches[3])
if err != nil {
return "", 0, false
}
return matches[2], line, true
}

View file

@ -31,8 +31,8 @@ import (
"strconv"
"strings"
"github.com/golang/glog"
"golang.org/x/net/http2"
"k8s.io/klog"
)
// JoinPreservingTrailingSlash does a path.Join of the specified elements,
@ -68,14 +68,17 @@ func IsProbableEOF(err error) bool {
if uerr, ok := err.(*url.Error); ok {
err = uerr.Err
}
msg := err.Error()
switch {
case err == io.EOF:
return true
case err.Error() == "http: can't write HTTP request on broken connection":
case msg == "http: can't write HTTP request on broken connection":
return true
case strings.Contains(err.Error(), "connection reset by peer"):
case strings.Contains(msg, "http2: server sent GOAWAY and closed the connection"):
return true
case strings.Contains(strings.ToLower(err.Error()), "use of closed network connection"):
case strings.Contains(msg, "connection reset by peer"):
return true
case strings.Contains(strings.ToLower(msg), "use of closed network connection"):
return true
}
return false
@ -91,7 +94,8 @@ func SetOldTransportDefaults(t *http.Transport) *http.Transport {
// ProxierWithNoProxyCIDR allows CIDR rules in NO_PROXY
t.Proxy = NewProxierWithNoProxyCIDR(http.ProxyFromEnvironment)
}
if t.DialContext == nil {
// If no custom dialer is set, use the default context dialer
if t.DialContext == nil && t.Dial == nil {
t.DialContext = defaultTransport.DialContext
}
if t.TLSHandshakeTimeout == 0 {
@ -106,10 +110,10 @@ func SetTransportDefaults(t *http.Transport) *http.Transport {
t = SetOldTransportDefaults(t)
// Allow clients to disable http2 if needed.
if s := os.Getenv("DISABLE_HTTP2"); len(s) > 0 {
glog.Infof("HTTP2 has been explicitly disabled")
klog.Infof("HTTP2 has been explicitly disabled")
} else {
if err := http2.ConfigureTransport(t); err != nil {
glog.Warningf("Transport failed http2 configuration: %v", err)
klog.Warningf("Transport failed http2 configuration: %v", err)
}
}
return t
@ -129,7 +133,18 @@ func DialerFor(transport http.RoundTripper) (DialFunc, error) {
switch transport := transport.(type) {
case *http.Transport:
return transport.DialContext, nil
// transport.DialContext takes precedence over transport.Dial
if transport.DialContext != nil {
return transport.DialContext, nil
}
// adapt transport.Dial to the DialWithContext signature
if transport.Dial != nil {
return func(ctx context.Context, net, addr string) (net.Conn, error) {
return transport.Dial(net, addr)
}, nil
}
// otherwise return nil
return nil, nil
case RoundTripperWrapper:
return DialerFor(transport.WrappedRoundTripper())
default:
@ -167,10 +182,8 @@ func FormatURL(scheme string, host string, port int, path string) *url.URL {
}
func GetHTTPClient(req *http.Request) string {
if userAgent, ok := req.Header["User-Agent"]; ok {
if len(userAgent) > 0 {
return userAgent[0]
}
if ua := req.UserAgent(); len(ua) != 0 {
return ua
}
return "unknown"
}
@ -311,9 +324,10 @@ type Dialer interface {
// ConnectWithRedirects uses dialer to send req, following up to 10 redirects (relative to
// originalLocation). It returns the opened net.Conn and the raw response bytes.
func ConnectWithRedirects(originalMethod string, originalLocation *url.URL, header http.Header, originalBody io.Reader, dialer Dialer) (net.Conn, []byte, error) {
// If requireSameHostRedirects is true, only redirects to the same host are permitted.
func ConnectWithRedirects(originalMethod string, originalLocation *url.URL, header http.Header, originalBody io.Reader, dialer Dialer, requireSameHostRedirects bool) (net.Conn, []byte, error) {
const (
maxRedirects = 10
maxRedirects = 9 // Fail on the 10th redirect
maxResponseSize = 16384 // play it safe to allow the potential for lots of / large headers
)
@ -357,7 +371,7 @@ redirectLoop:
resp, err := http.ReadResponse(respReader, nil)
if err != nil {
// Unable to read the backend response; let the client handle it.
glog.Warningf("Error reading backend response: %v", err)
klog.Warningf("Error reading backend response: %v", err)
break redirectLoop
}
@ -377,10 +391,6 @@ redirectLoop:
resp.Body.Close() // not used
// Reset the connection.
intermediateConn.Close()
intermediateConn = nil
// Prepare to follow the redirect.
redirectStr := resp.Header.Get("Location")
if redirectStr == "" {
@ -394,6 +404,15 @@ redirectLoop:
if err != nil {
return nil, nil, fmt.Errorf("malformed Location header: %v", err)
}
// Only follow redirects to the same host. Otherwise, propagate the redirect response back.
if requireSameHostRedirects && location.Hostname() != originalLocation.Hostname() {
break redirectLoop
}
// Reset the connection.
intermediateConn.Close()
intermediateConn = nil
}
connToReturn := intermediateConn

View file

@ -26,7 +26,7 @@ import (
"strings"
"github.com/golang/glog"
"k8s.io/klog"
)
type AddressFamily uint
@ -53,6 +53,28 @@ type RouteFile struct {
parse func(input io.Reader) ([]Route, error)
}
// noRoutesError can be returned by ChooseBindAddress() in case of no routes
type noRoutesError struct {
message string
}
func (e noRoutesError) Error() string {
return e.message
}
// IsNoRoutesError checks if an error is of type noRoutesError
func IsNoRoutesError(err error) bool {
if err == nil {
return false
}
switch err.(type) {
case noRoutesError:
return true
default:
return false
}
}
var (
v4File = RouteFile{name: ipv4RouteFile, parse: getIPv4DefaultRoutes}
v6File = RouteFile{name: ipv6RouteFile, parse: getIPv6DefaultRoutes}
@ -171,7 +193,7 @@ func isInterfaceUp(intf *net.Interface) bool {
return false
}
if intf.Flags&net.FlagUp != 0 {
glog.V(4).Infof("Interface %v is up", intf.Name)
klog.V(4).Infof("Interface %v is up", intf.Name)
return true
}
return false
@ -186,20 +208,20 @@ func isLoopbackOrPointToPoint(intf *net.Interface) bool {
func getMatchingGlobalIP(addrs []net.Addr, family AddressFamily) (net.IP, error) {
if len(addrs) > 0 {
for i := range addrs {
glog.V(4).Infof("Checking addr %s.", addrs[i].String())
klog.V(4).Infof("Checking addr %s.", addrs[i].String())
ip, _, err := net.ParseCIDR(addrs[i].String())
if err != nil {
return nil, err
}
if memberOf(ip, family) {
if ip.IsGlobalUnicast() {
glog.V(4).Infof("IP found %v", ip)
klog.V(4).Infof("IP found %v", ip)
return ip, nil
} else {
glog.V(4).Infof("Non-global unicast address found %v", ip)
klog.V(4).Infof("Non-global unicast address found %v", ip)
}
} else {
glog.V(4).Infof("%v is not an IPv%d address", ip, int(family))
klog.V(4).Infof("%v is not an IPv%d address", ip, int(family))
}
}
@ -219,13 +241,13 @@ func getIPFromInterface(intfName string, forFamily AddressFamily, nw networkInte
if err != nil {
return nil, err
}
glog.V(4).Infof("Interface %q has %d addresses :%v.", intfName, len(addrs), addrs)
klog.V(4).Infof("Interface %q has %d addresses :%v.", intfName, len(addrs), addrs)
matchingIP, err := getMatchingGlobalIP(addrs, forFamily)
if err != nil {
return nil, err
}
if matchingIP != nil {
glog.V(4).Infof("Found valid IPv%d address %v for interface %q.", int(forFamily), matchingIP, intfName)
klog.V(4).Infof("Found valid IPv%d address %v for interface %q.", int(forFamily), matchingIP, intfName)
return matchingIP, nil
}
}
@ -253,14 +275,14 @@ func chooseIPFromHostInterfaces(nw networkInterfacer) (net.IP, error) {
return nil, fmt.Errorf("no interfaces found on host.")
}
for _, family := range []AddressFamily{familyIPv4, familyIPv6} {
glog.V(4).Infof("Looking for system interface with a global IPv%d address", uint(family))
klog.V(4).Infof("Looking for system interface with a global IPv%d address", uint(family))
for _, intf := range intfs {
if !isInterfaceUp(&intf) {
glog.V(4).Infof("Skipping: down interface %q", intf.Name)
klog.V(4).Infof("Skipping: down interface %q", intf.Name)
continue
}
if isLoopbackOrPointToPoint(&intf) {
glog.V(4).Infof("Skipping: LB or P2P interface %q", intf.Name)
klog.V(4).Infof("Skipping: LB or P2P interface %q", intf.Name)
continue
}
addrs, err := nw.Addrs(&intf)
@ -268,7 +290,7 @@ func chooseIPFromHostInterfaces(nw networkInterfacer) (net.IP, error) {
return nil, err
}
if len(addrs) == 0 {
glog.V(4).Infof("Skipping: no addresses on interface %q", intf.Name)
klog.V(4).Infof("Skipping: no addresses on interface %q", intf.Name)
continue
}
for _, addr := range addrs {
@ -277,15 +299,15 @@ func chooseIPFromHostInterfaces(nw networkInterfacer) (net.IP, error) {
return nil, fmt.Errorf("Unable to parse CIDR for interface %q: %s", intf.Name, err)
}
if !memberOf(ip, family) {
glog.V(4).Infof("Skipping: no address family match for %q on interface %q.", ip, intf.Name)
klog.V(4).Infof("Skipping: no address family match for %q on interface %q.", ip, intf.Name)
continue
}
// TODO: Decide if should open up to allow IPv6 LLAs in future.
if !ip.IsGlobalUnicast() {
glog.V(4).Infof("Skipping: non-global address %q on interface %q.", ip, intf.Name)
klog.V(4).Infof("Skipping: non-global address %q on interface %q.", ip, intf.Name)
continue
}
glog.V(4).Infof("Found global unicast address %q on interface %q.", ip, intf.Name)
klog.V(4).Infof("Found global unicast address %q on interface %q.", ip, intf.Name)
return ip, nil
}
}
@ -347,7 +369,9 @@ func getAllDefaultRoutes() ([]Route, error) {
v6Routes, _ := v6File.extract()
routes = append(routes, v6Routes...)
if len(routes) == 0 {
return nil, fmt.Errorf("No default routes.")
return nil, noRoutesError{
message: fmt.Sprintf("no default routes found in %q or %q", v4File.name, v6File.name),
}
}
return routes, nil
}
@ -357,23 +381,23 @@ func getAllDefaultRoutes() ([]Route, error) {
// an IPv4 IP, and then will look at each IPv6 route for an IPv6 IP.
func chooseHostInterfaceFromRoute(routes []Route, nw networkInterfacer) (net.IP, error) {
for _, family := range []AddressFamily{familyIPv4, familyIPv6} {
glog.V(4).Infof("Looking for default routes with IPv%d addresses", uint(family))
klog.V(4).Infof("Looking for default routes with IPv%d addresses", uint(family))
for _, route := range routes {
if route.Family != family {
continue
}
glog.V(4).Infof("Default route transits interface %q", route.Interface)
klog.V(4).Infof("Default route transits interface %q", route.Interface)
finalIP, err := getIPFromInterface(route.Interface, family, nw)
if err != nil {
return nil, err
}
if finalIP != nil {
glog.V(4).Infof("Found active IP %v ", finalIP)
klog.V(4).Infof("Found active IP %v ", finalIP)
return finalIP, nil
}
}
}
glog.V(4).Infof("No active IP found by looking at default routes")
klog.V(4).Infof("No active IP found by looking at default routes")
return nil, fmt.Errorf("unable to select an IP from default routes.")
}

View file

@ -27,7 +27,14 @@ var rng = struct {
sync.Mutex
rand *rand.Rand
}{
rand: rand.New(rand.NewSource(time.Now().UTC().UnixNano())),
rand: rand.New(rand.NewSource(time.Now().UnixNano())),
}
// Int returns a non-negative pseudo-random int.
func Int() int {
rng.Lock()
defer rng.Unlock()
return rng.rand.Int()
}
// Intn generates an integer in range [0,max).

View file

@ -22,7 +22,7 @@ import (
"sync"
"time"
"github.com/golang/glog"
"k8s.io/klog"
)
var (
@ -63,7 +63,11 @@ func HandleCrash(additionalHandlers ...func(interface{})) {
// logPanic logs the caller tree when a panic occurs.
func logPanic(r interface{}) {
callers := getCallers(r)
glog.Errorf("Observed a panic: %#v (%v)\n%v", r, r, callers)
if _, ok := r.(string); ok {
klog.Errorf("Observed a panic: %s\n%v", r, callers)
} else {
klog.Errorf("Observed a panic: %#v (%v)\n%v", r, r, callers)
}
}
func getCallers(r interface{}) string {
@ -111,7 +115,7 @@ func HandleError(err error) {
// logError prints an error with the call stack of the location it was reported
func logError(err error) {
glog.ErrorDepth(2, err)
klog.ErrorDepth(2, err)
}
type rudimentaryErrorBackoff struct {

View file

@ -1,5 +1,8 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- pwittrock
- mengqiy
reviewers:
- mengqiy
- apelisse

View file

@ -1876,7 +1876,7 @@ func mergingMapFieldsHaveConflicts(
return true, nil
}
return slicesHaveConflicts(leftType, rightType, schema, fieldPatchStrategy, fieldPatchMergeKey)
case string, float64, bool, int, int64, nil:
case string, float64, bool, int64, nil:
return !reflect.DeepEqual(left, right), nil
default:
return true, fmt.Errorf("unknown type: %v", reflect.TypeOf(left))

View file

@ -48,7 +48,7 @@ func (v *Error) ErrorBody() string {
var s string
switch v.Type {
case ErrorTypeRequired, ErrorTypeForbidden, ErrorTypeTooLong, ErrorTypeInternal:
s = fmt.Sprintf("%s", v.Type)
s = v.Type.String()
default:
value := v.BadValue
valueType := reflect.TypeOf(value)

View file

@ -21,6 +21,7 @@ import (
"math"
"net"
"regexp"
"strconv"
"strings"
"k8s.io/apimachinery/pkg/util/validation/field"
@ -86,6 +87,8 @@ func IsFullyQualifiedName(fldPath *field.Path, name string) field.ErrorList {
const labelValueFmt string = "(" + qualifiedNameFmt + ")?"
const labelValueErrMsg string = "a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character"
// LabelValueMaxLength is a label's max length
const LabelValueMaxLength int = 63
var labelValueRegexp = regexp.MustCompile("^" + labelValueFmt + "$")
@ -106,6 +109,8 @@ func IsValidLabelValue(value string) []string {
const dns1123LabelFmt string = "[a-z0-9]([-a-z0-9]*[a-z0-9])?"
const dns1123LabelErrMsg string = "a DNS-1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character"
// DNS1123LabelMaxLength is a label's max length in DNS (RFC 1123)
const DNS1123LabelMaxLength int = 63
var dns1123LabelRegexp = regexp.MustCompile("^" + dns1123LabelFmt + "$")
@ -125,6 +130,8 @@ func IsDNS1123Label(value string) []string {
const dns1123SubdomainFmt string = dns1123LabelFmt + "(\\." + dns1123LabelFmt + ")*"
const dns1123SubdomainErrorMsg string = "a DNS-1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character"
// DNS1123SubdomainMaxLength is a subdomain's max length in DNS (RFC 1123)
const DNS1123SubdomainMaxLength int = 253
var dns1123SubdomainRegexp = regexp.MustCompile("^" + dns1123SubdomainFmt + "$")
@ -144,6 +151,8 @@ func IsDNS1123Subdomain(value string) []string {
const dns1035LabelFmt string = "[a-z]([-a-z0-9]*[a-z0-9])?"
const dns1035LabelErrMsg string = "a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character"
// DNS1035LabelMaxLength is a label's max length in DNS (RFC 1035)
const DNS1035LabelMaxLength int = 63
var dns1035LabelRegexp = regexp.MustCompile("^" + dns1035LabelFmt + "$")
@ -281,6 +290,7 @@ const percentErrMsg string = "a valid percent string must be a numeric string fo
var percentRegexp = regexp.MustCompile("^" + percentFmt + "$")
// IsValidPercent checks that string is in the form of a percentage
func IsValidPercent(percent string) []string {
if !percentRegexp.MatchString(percent) {
return []string{RegexError(percentErrMsg, percentFmt, "1%", "93%")}
@ -389,3 +399,18 @@ func hasChDirPrefix(value string) []string {
}
return errs
}
// IsValidSocketAddr checks that string represents a valid socket address
// as defined in RFC 789. (e.g 0.0.0.0:10254 or [::]:10254))
func IsValidSocketAddr(value string) []string {
var errs []string
ip, port, err := net.SplitHostPort(value)
if err != nil {
errs = append(errs, "must be a valid socket address format, (e.g. 0.0.0.0:10254 or [::]:10254)")
return errs
}
portInt, _ := strconv.Atoi(port)
errs = append(errs, IsValidPortNum(portInt)...)
errs = append(errs, IsValidIP(ip)...)
return errs
}

View file

@ -88,6 +88,15 @@ func Until(f func(), period time.Duration, stopCh <-chan struct{}) {
JitterUntil(f, period, 0.0, true, stopCh)
}
// UntilWithContext loops until context is done, running f every period.
//
// UntilWithContext is syntactic sugar on top of JitterUntilWithContext
// with zero jitter factor and with sliding = true (which means the timer
// for period starts after the f completes).
func UntilWithContext(ctx context.Context, f func(context.Context), period time.Duration) {
JitterUntilWithContext(ctx, f, period, 0.0, true)
}
// NonSlidingUntil loops until stop channel is closed, running f every
// period.
//
@ -98,6 +107,16 @@ func NonSlidingUntil(f func(), period time.Duration, stopCh <-chan struct{}) {
JitterUntil(f, period, 0.0, false, stopCh)
}
// NonSlidingUntilWithContext loops until context is done, running f every
// period.
//
// NonSlidingUntilWithContext is syntactic sugar on top of JitterUntilWithContext
// with zero jitter factor, with sliding = false (meaning the timer for period
// starts at the same time as the function starts).
func NonSlidingUntilWithContext(ctx context.Context, f func(context.Context), period time.Duration) {
JitterUntilWithContext(ctx, f, period, 0.0, false)
}
// JitterUntil loops until stop channel is closed, running f every period.
//
// If jitterFactor is positive, the period is jittered before every run of f.
@ -151,6 +170,19 @@ func JitterUntil(f func(), period time.Duration, jitterFactor float64, sliding b
}
}
// JitterUntilWithContext loops until context is done, running f every period.
//
// If jitterFactor is positive, the period is jittered before every run of f.
// If jitterFactor is not positive, the period is unchanged and not jittered.
//
// If sliding is true, the period is computed after f runs. If it is false then
// period includes the runtime for f.
//
// Cancel context to stop. f may not be invoked if context is already expired.
func JitterUntilWithContext(ctx context.Context, f func(context.Context), period time.Duration, jitterFactor float64, sliding bool) {
JitterUntil(func() { f(ctx) }, period, jitterFactor, sliding, ctx.Done())
}
// Jitter returns a time.Duration between duration and duration + maxFactor *
// duration.
//
@ -173,10 +205,49 @@ type ConditionFunc func() (done bool, err error)
// Backoff holds parameters applied to a Backoff function.
type Backoff struct {
Duration time.Duration // the base duration
Factor float64 // Duration is multiplied by factor each iteration
Jitter float64 // The amount of jitter applied each iteration
Steps int // Exit with error after this many steps
// The initial duration.
Duration time.Duration
// Duration is multiplied by factor each iteration. Must be greater
// than or equal to zero.
Factor float64
// The amount of jitter applied each iteration. Jitter is applied after
// cap.
Jitter float64
// The number of steps before duration stops changing. If zero, initial
// duration is always used. Used for exponential backoff in combination
// with Factor.
Steps int
// The returned duration will never be greater than cap *before* jitter
// is applied. The actual maximum cap is `cap * (1.0 + jitter)`.
Cap time.Duration
}
// Step returns the next interval in the exponential backoff. This method
// will mutate the provided backoff.
func (b *Backoff) Step() time.Duration {
if b.Steps < 1 {
if b.Jitter > 0 {
return Jitter(b.Duration, b.Jitter)
}
return b.Duration
}
b.Steps--
duration := b.Duration
// calculate the next step
if b.Factor != 0 {
b.Duration = time.Duration(float64(b.Duration) * b.Factor)
if b.Cap > 0 && b.Duration > b.Cap {
b.Duration = b.Cap
b.Steps = 0
}
}
if b.Jitter > 0 {
duration = Jitter(duration, b.Jitter)
}
return duration
}
// ExponentialBackoff repeats a condition check with exponential backoff.
@ -190,19 +261,14 @@ type Backoff struct {
// If the condition never returns true, ErrWaitTimeout is returned. All other
// errors terminate immediately.
func ExponentialBackoff(backoff Backoff, condition ConditionFunc) error {
duration := backoff.Duration
for i := 0; i < backoff.Steps; i++ {
if i != 0 {
adjusted := duration
if backoff.Jitter > 0.0 {
adjusted = Jitter(duration, backoff.Jitter)
}
time.Sleep(adjusted)
duration = time.Duration(float64(duration) * backoff.Factor)
}
for backoff.Steps > 0 {
if ok, err := condition(); err != nil || ok {
return err
}
if backoff.Steps == 1 {
break
}
time.Sleep(backoff.Step())
}
return ErrWaitTimeout
}
@ -230,13 +296,13 @@ func pollInternal(wait WaitFunc, condition ConditionFunc) error {
// PollImmediate tries a condition func until it returns true, an error, or the timeout
// is reached.
//
// Poll always checks 'condition' before waiting for the interval. 'condition'
// PollImmediate always checks 'condition' before waiting for the interval. 'condition'
// will always be invoked at least once.
//
// Some intervals may be missed if the condition takes too long or the time
// window is too short.
//
// If you want to Poll something forever, see PollInfinite.
// If you want to immediately Poll something forever, see PollImmediateInfinite.
func PollImmediate(interval, timeout time.Duration, condition ConditionFunc) error {
return pollImmediateInternal(poller(interval, timeout), condition)
}
@ -317,29 +383,39 @@ type WaitFunc func(done <-chan struct{}) <-chan struct{}
// WaitFor continually checks 'fn' as driven by 'wait'.
//
// WaitFor gets a channel from 'wait()'', and then invokes 'fn' once for every value
// placed on the channel and once more when the channel is closed.
// placed on the channel and once more when the channel is closed. If the channel is closed
// and 'fn' returns false without error, WaitFor returns ErrWaitTimeout.
//
// If 'fn' returns an error the loop ends and that error is returned, and if
// If 'fn' returns an error the loop ends and that error is returned. If
// 'fn' returns true the loop ends and nil is returned.
//
// ErrWaitTimeout will be returned if the channel is closed without fn ever
// ErrWaitTimeout will be returned if the 'done' channel is closed without fn ever
// returning true.
//
// When the done channel is closed, because the golang `select` statement is
// "uniform pseudo-random", the `fn` might still run one or multiple time,
// though eventually `WaitFor` will return.
func WaitFor(wait WaitFunc, fn ConditionFunc, done <-chan struct{}) error {
c := wait(done)
stopCh := make(chan struct{})
defer close(stopCh)
c := wait(stopCh)
for {
_, open := <-c
ok, err := fn()
if err != nil {
return err
}
if ok {
return nil
}
if !open {
break
select {
case _, open := <-c:
ok, err := fn()
if err != nil {
return err
}
if ok {
return nil
}
if !open {
return ErrWaitTimeout
}
case <-done:
return ErrWaitTimeout
}
}
return ErrWaitTimeout
}
// poller returns a WaitFunc that will send to the channel every interval until

View file

@ -26,8 +26,8 @@ import (
"strings"
"unicode"
"github.com/ghodss/yaml"
"github.com/golang/glog"
"k8s.io/klog"
"sigs.k8s.io/yaml"
)
// ToJSON converts a single YAML document into a JSON document
@ -217,11 +217,9 @@ func (d *YAMLOrJSONDecoder) Decode(into interface{}) error {
if d.decoder == nil {
buffer, origData, isJSON := GuessJSONStream(d.r, d.bufferSize)
if isJSON {
glog.V(4).Infof("decoding stream as JSON")
d.decoder = json.NewDecoder(buffer)
d.rawData = origData
} else {
glog.V(4).Infof("decoding stream as YAML")
d.decoder = NewYAMLToJSONDecoder(buffer)
}
}
@ -230,7 +228,7 @@ func (d *YAMLOrJSONDecoder) Decode(into interface{}) error {
if syntax, ok := err.(*json.SyntaxError); ok {
data, readErr := ioutil.ReadAll(jsonDecoder.Buffered())
if readErr != nil {
glog.V(4).Infof("reading stream failed: %v", readErr)
klog.V(4).Infof("reading stream failed: %v", readErr)
}
js := string(data)

View file

@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// Package version supplies the type for version information collected at build time.
// +k8s:openapi-gen=true
// Package version supplies the type for version information collected at build time.
package version // import "k8s.io/apimachinery/pkg/version"

View file

@ -20,10 +20,10 @@ import (
"io"
"sync"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/net"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/klog"
)
// Decoder allows StreamWatcher to watch any stream for which a Decoder can be written.
@ -100,13 +100,13 @@ func (sw *StreamWatcher) receive() {
case io.EOF:
// watch closed normally
case io.ErrUnexpectedEOF:
glog.V(1).Infof("Unexpected EOF during watch stream event decoding: %v", err)
klog.V(1).Infof("Unexpected EOF during watch stream event decoding: %v", err)
default:
msg := "Unable to decode an event from the watch stream: %v"
if net.IsProbableEOF(err) {
glog.V(5).Infof(msg, err)
klog.V(5).Infof(msg, err)
} else {
glog.Errorf(msg, err)
klog.Errorf(msg, err)
}
}
return

View file

@ -1,87 +0,0 @@
/*
Copyright 2016 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 watch
import (
"errors"
"time"
"k8s.io/apimachinery/pkg/util/wait"
)
// ConditionFunc returns true if the condition has been reached, false if it has not been reached yet,
// or an error if the condition cannot be checked and should terminate. In general, it is better to define
// level driven conditions over edge driven conditions (pod has ready=true, vs pod modified and ready changed
// from false to true).
type ConditionFunc func(event Event) (bool, error)
// ErrWatchClosed is returned when the watch channel is closed before timeout in Until.
var ErrWatchClosed = errors.New("watch closed before Until timeout")
// Until reads items from the watch until each provided condition succeeds, and then returns the last watch
// encountered. The first condition that returns an error terminates the watch (and the event is also returned).
// If no event has been received, the returned event will be nil.
// Conditions are satisfied sequentially so as to provide a useful primitive for higher level composition.
// A zero timeout means to wait forever.
func Until(timeout time.Duration, watcher Interface, conditions ...ConditionFunc) (*Event, error) {
ch := watcher.ResultChan()
defer watcher.Stop()
var after <-chan time.Time
if timeout > 0 {
after = time.After(timeout)
} else {
ch := make(chan time.Time)
defer close(ch)
after = ch
}
var lastEvent *Event
for _, condition := range conditions {
// check the next condition against the previous event and short circuit waiting for the next watch
if lastEvent != nil {
done, err := condition(*lastEvent)
if err != nil {
return lastEvent, err
}
if done {
continue
}
}
ConditionSucceeded:
for {
select {
case event, ok := <-ch:
if !ok {
return lastEvent, ErrWatchClosed
}
lastEvent = &event
// TODO: check for watch expired error and retry watch from latest point?
done, err := condition(event)
if err != nil {
return lastEvent, err
}
if done {
break ConditionSucceeded
}
case <-after:
return lastEvent, wait.ErrWaitTimeout
}
}
}
return lastEvent, nil
}

View file

@ -20,7 +20,7 @@ import (
"fmt"
"sync"
"github.com/golang/glog"
"k8s.io/klog"
"k8s.io/apimachinery/pkg/runtime"
)
@ -106,7 +106,7 @@ func (f *FakeWatcher) Stop() {
f.Lock()
defer f.Unlock()
if !f.Stopped {
glog.V(4).Infof("Stopping fake watcher.")
klog.V(4).Infof("Stopping fake watcher.")
close(f.result)
f.Stopped = true
}
@ -173,7 +173,7 @@ func (f *RaceFreeFakeWatcher) Stop() {
f.Lock()
defer f.Unlock()
if !f.Stopped {
glog.V(4).Infof("Stopping fake watcher.")
klog.V(4).Infof("Stopping fake watcher.")
close(f.result)
f.Stopped = true
}
@ -268,3 +268,50 @@ func (f *RaceFreeFakeWatcher) Action(action EventType, obj runtime.Object) {
}
}
}
// ProxyWatcher lets you wrap your channel in watch Interface. Threadsafe.
type ProxyWatcher struct {
result chan Event
stopCh chan struct{}
mutex sync.Mutex
stopped bool
}
var _ Interface = &ProxyWatcher{}
// NewProxyWatcher creates new ProxyWatcher by wrapping a channel
func NewProxyWatcher(ch chan Event) *ProxyWatcher {
return &ProxyWatcher{
result: ch,
stopCh: make(chan struct{}),
stopped: false,
}
}
// Stop implements Interface
func (pw *ProxyWatcher) Stop() {
pw.mutex.Lock()
defer pw.mutex.Unlock()
if !pw.stopped {
pw.stopped = true
close(pw.stopCh)
}
}
// Stopping returns true if Stop() has been called
func (pw *ProxyWatcher) Stopping() bool {
pw.mutex.Lock()
defer pw.mutex.Unlock()
return pw.stopped
}
// ResultChan implements Interface
func (pw *ProxyWatcher) ResultChan() <-chan Event {
return pw.result
}
// StopChan returns stop channel
func (pw *ProxyWatcher) StopChan() <-chan struct{} {
return pw.stopCh
}

View file

@ -23,9 +23,7 @@ package watch
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Event) DeepCopyInto(out *Event) {
*out = *in
if in.Object == nil {
out.Object = nil
} else {
if in.Object != nil {
out.Object = in.Object.DeepCopyObject()
}
return