1
0
Fork 0

Bump kubernetes/client-go

This commit is contained in:
Kim Min 2018-02-14 16:56:04 +08:00 committed by Traefiker Bot
parent 029fa83690
commit 83a92596c3
901 changed files with 169303 additions and 306433 deletions

View file

@ -1,152 +0,0 @@
/*
Copyright 2014 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 api
import (
stderrs "errors"
"time"
"golang.org/x/net/context"
"k8s.io/client-go/pkg/auth/user"
"k8s.io/client-go/pkg/types"
)
// Context carries values across API boundaries.
// This context matches the context.Context interface
// (https://blog.golang.org/context), for the purposes
// of passing the api.Context through to the storage tier.
// TODO: Determine the extent that this abstraction+interface
// is used by the api, and whether we can remove.
type Context interface {
// Value returns the value associated with key or nil if none.
Value(key interface{}) interface{}
// Deadline returns the time when this Context will be canceled, if any.
Deadline() (deadline time.Time, ok bool)
// Done returns a channel that is closed when this Context is canceled
// or times out.
Done() <-chan struct{}
// Err indicates why this context was canceled, after the Done channel
// is closed.
Err() error
}
// The key type is unexported to prevent collisions
type key int
const (
// namespaceKey is the context key for the request namespace.
namespaceKey key = iota
// userKey is the context key for the request user.
userKey
// uidKey is the context key for the uid to assign to an object on create.
uidKey
// userAgentKey is the context key for the request user agent.
userAgentKey
)
// NewContext instantiates a base context object for request flows.
func NewContext() Context {
return context.TODO()
}
// NewDefaultContext instantiates a base context object for request flows in the default namespace
func NewDefaultContext() Context {
return WithNamespace(NewContext(), NamespaceDefault)
}
// WithValue returns a copy of parent in which the value associated with key is val.
func WithValue(parent Context, key interface{}, val interface{}) Context {
internalCtx, ok := parent.(context.Context)
if !ok {
panic(stderrs.New("Invalid context type"))
}
return context.WithValue(internalCtx, key, val)
}
// WithNamespace returns a copy of parent in which the namespace value is set
func WithNamespace(parent Context, namespace string) Context {
return WithValue(parent, namespaceKey, namespace)
}
// NamespaceFrom returns the value of the namespace key on the ctx
func NamespaceFrom(ctx Context) (string, bool) {
namespace, ok := ctx.Value(namespaceKey).(string)
return namespace, ok
}
// NamespaceValue returns the value of the namespace key on the ctx, or the empty string if none
func NamespaceValue(ctx Context) string {
namespace, _ := NamespaceFrom(ctx)
return namespace
}
// ValidNamespace returns false if the namespace on the context differs from the resource. If the resource has no namespace, it is set to the value in the context.
func ValidNamespace(ctx Context, resource *ObjectMeta) bool {
ns, ok := NamespaceFrom(ctx)
if len(resource.Namespace) == 0 {
resource.Namespace = ns
}
return ns == resource.Namespace && ok
}
// WithNamespaceDefaultIfNone returns a context whose namespace is the default if and only if the parent context has no namespace value
func WithNamespaceDefaultIfNone(parent Context) Context {
namespace, ok := NamespaceFrom(parent)
if !ok || len(namespace) == 0 {
return WithNamespace(parent, NamespaceDefault)
}
return parent
}
// WithUser returns a copy of parent in which the user value is set
func WithUser(parent Context, user user.Info) Context {
return WithValue(parent, userKey, user)
}
// UserFrom returns the value of the user key on the ctx
func UserFrom(ctx Context) (user.Info, bool) {
user, ok := ctx.Value(userKey).(user.Info)
return user, ok
}
// WithUID returns a copy of parent in which the uid value is set
func WithUID(parent Context, uid types.UID) Context {
return WithValue(parent, uidKey, uid)
}
// UIDFrom returns the value of the uid key on the ctx
func UIDFrom(ctx Context) (types.UID, bool) {
uid, ok := ctx.Value(uidKey).(types.UID)
return uid, ok
}
// WithUserAgent returns a copy of parent in which the user value is set
func WithUserAgent(parent Context, userAgent string) Context {
return WithValue(parent, userAgentKey, userAgent)
}
// UserAgentFrom returns the value of the userAgent key on the ctx
func UserAgentFrom(ctx Context) (string, bool) {
userAgent, ok := ctx.Value(userAgentKey).(string)
return userAgent, ok
}

View file

@ -1,250 +0,0 @@
/*
Copyright 2014 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 api
import (
"fmt"
"k8s.io/client-go/pkg/api/resource"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/conversion"
"k8s.io/client-go/pkg/fields"
"k8s.io/client-go/pkg/labels"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/util/intstr"
utillabels "k8s.io/client-go/pkg/util/labels"
"k8s.io/client-go/pkg/util/validation/field"
)
func addConversionFuncs(scheme *runtime.Scheme) error {
return scheme.AddConversionFuncs(
Convert_unversioned_TypeMeta_To_unversioned_TypeMeta,
Convert_unversioned_ListMeta_To_unversioned_ListMeta,
Convert_intstr_IntOrString_To_intstr_IntOrString,
Convert_unversioned_Time_To_unversioned_Time,
Convert_Slice_string_To_unversioned_Time,
Convert_resource_Quantity_To_resource_Quantity,
Convert_string_To_labels_Selector,
Convert_labels_Selector_To_string,
Convert_string_To_fields_Selector,
Convert_fields_Selector_To_string,
Convert_Pointer_bool_To_bool,
Convert_bool_To_Pointer_bool,
Convert_Pointer_string_To_string,
Convert_string_To_Pointer_string,
Convert_Pointer_int64_To_int,
Convert_int_To_Pointer_int64,
Convert_Pointer_int32_To_int32,
Convert_int32_To_Pointer_int32,
Convert_Pointer_float64_To_float64,
Convert_float64_To_Pointer_float64,
Convert_map_to_unversioned_LabelSelector,
Convert_unversioned_LabelSelector_to_map,
)
}
func Convert_Pointer_float64_To_float64(in **float64, out *float64, s conversion.Scope) error {
if *in == nil {
*out = 0
return nil
}
*out = float64(**in)
return nil
}
func Convert_float64_To_Pointer_float64(in *float64, out **float64, s conversion.Scope) error {
temp := float64(*in)
*out = &temp
return nil
}
func Convert_Pointer_int32_To_int32(in **int32, out *int32, s conversion.Scope) error {
if *in == nil {
*out = 0
return nil
}
*out = int32(**in)
return nil
}
func Convert_int32_To_Pointer_int32(in *int32, out **int32, s conversion.Scope) error {
temp := int32(*in)
*out = &temp
return nil
}
func Convert_Pointer_int64_To_int(in **int64, out *int, s conversion.Scope) error {
if *in == nil {
*out = 0
return nil
}
*out = int(**in)
return nil
}
func Convert_int_To_Pointer_int64(in *int, out **int64, s conversion.Scope) error {
temp := int64(*in)
*out = &temp
return nil
}
func Convert_Pointer_string_To_string(in **string, out *string, s conversion.Scope) error {
if *in == nil {
*out = ""
return nil
}
*out = **in
return nil
}
func Convert_string_To_Pointer_string(in *string, out **string, s conversion.Scope) error {
if in == nil {
stringVar := ""
*out = &stringVar
return nil
}
*out = in
return nil
}
func Convert_Pointer_bool_To_bool(in **bool, out *bool, s conversion.Scope) error {
if *in == nil {
*out = false
return nil
}
*out = **in
return nil
}
func Convert_bool_To_Pointer_bool(in *bool, out **bool, s conversion.Scope) error {
if in == nil {
boolVar := false
*out = &boolVar
return nil
}
*out = in
return nil
}
// +k8s:conversion-fn=drop
func Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(in, out *unversioned.TypeMeta, s conversion.Scope) error {
// These values are explicitly not copied
//out.APIVersion = in.APIVersion
//out.Kind = in.Kind
return nil
}
// +k8s:conversion-fn=copy-only
func Convert_unversioned_ListMeta_To_unversioned_ListMeta(in, out *unversioned.ListMeta, s conversion.Scope) error {
*out = *in
return nil
}
// +k8s:conversion-fn=copy-only
func Convert_intstr_IntOrString_To_intstr_IntOrString(in, out *intstr.IntOrString, s conversion.Scope) error {
*out = *in
return nil
}
// +k8s:conversion-fn=copy-only
func Convert_unversioned_Time_To_unversioned_Time(in *unversioned.Time, out *unversioned.Time, 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 *unversioned.Time, s conversion.Scope) error {
str := ""
if len(*input) > 0 {
str = (*input)[0]
}
return out.UnmarshalQueryParameter(str)
}
func Convert_string_To_labels_Selector(in *string, out *labels.Selector, s conversion.Scope) error {
selector, err := labels.Parse(*in)
if err != nil {
return err
}
*out = selector
return nil
}
func Convert_string_To_fields_Selector(in *string, out *fields.Selector, s conversion.Scope) error {
selector, err := fields.ParseSelector(*in)
if err != nil {
return err
}
*out = selector
return nil
}
func Convert_labels_Selector_To_string(in *labels.Selector, out *string, s conversion.Scope) error {
if *in == nil {
return nil
}
*out = (*in).String()
return nil
}
func Convert_fields_Selector_To_string(in *fields.Selector, out *string, s conversion.Scope) error {
if *in == nil {
return nil
}
*out = (*in).String()
return nil
}
// +k8s:conversion-fn=copy-only
func Convert_resource_Quantity_To_resource_Quantity(in *resource.Quantity, out *resource.Quantity, s conversion.Scope) error {
*out = *in
return nil
}
func Convert_map_to_unversioned_LabelSelector(in *map[string]string, out *unversioned.LabelSelector, s conversion.Scope) error {
if in == nil {
return nil
}
out = new(unversioned.LabelSelector)
for labelKey, labelValue := range *in {
utillabels.AddLabelToSelector(out, labelKey, labelValue)
}
return nil
}
func Convert_unversioned_LabelSelector_to_map(in *unversioned.LabelSelector, out *map[string]string, s conversion.Scope) error {
var err error
*out, err = unversioned.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

@ -1,36 +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 api
import (
"k8s.io/client-go/pkg/fields"
"k8s.io/client-go/pkg/labels"
"k8s.io/client-go/pkg/runtime"
)
func addDefaultingFuncs(scheme *runtime.Scheme) error {
return scheme.AddDefaultingFuncs(
func(obj *ListOptions) {
if obj.LabelSelector == nil {
obj.LabelSelector = labels.Everything()
}
if obj.FieldSelector == nil {
obj.FieldSelector = fields.Everything()
}
},
)
}

View file

@ -1,24 +0,0 @@
/*
Copyright 2014 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.
*/
// +k8s:deepcopy-gen=package,register
// Package api contains the latest (or "internal") version of the
// Kubernetes API objects. This is the API objects as represented in memory.
// The contract presented to clients is located in the versioned packages,
// which are sub-directories. The first one is "v1". Those packages
// describe how a particular version is serialized to storage/network.
package api

View file

@ -1,18 +0,0 @@
/*
Copyright 2014 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 errors provides detailed error types for api field validation.
package errors

View file

@ -1,470 +0,0 @@
/*
Copyright 2014 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 errors
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/util/validation/field"
)
// HTTP Status codes not in the golang http package.
const (
StatusUnprocessableEntity = 422
StatusTooManyRequests = 429
// StatusServerTimeout is an indication that a transient server error has
// occurred and the client *should* retry, with an optional Retry-After
// header to specify the back off window.
StatusServerTimeout = 504
)
// StatusError is an error intended for consumption by a REST API server; it can also be
// reconstructed by clients from a REST response. Public to allow easy type switches.
type StatusError struct {
ErrStatus unversioned.Status
}
// APIStatus is exposed by errors that can be converted to an api.Status object
// for finer grained details.
type APIStatus interface {
Status() unversioned.Status
}
var _ error = &StatusError{}
// Error implements the Error interface.
func (e *StatusError) Error() string {
return e.ErrStatus.Message
}
// Status allows access to e's status without having to know the detailed workings
// of StatusError. Used by pkg/apiserver.
func (e *StatusError) Status() unversioned.Status {
return e.ErrStatus
}
// DebugError reports extended info about the error to debug output.
func (e *StatusError) DebugError() (string, []interface{}) {
if out, err := json.MarshalIndent(e.ErrStatus, "", " "); err == nil {
return "server response object: %s", []interface{}{string(out)}
}
return "server response object: %#v", []interface{}{e.ErrStatus}
}
// UnexpectedObjectError can be returned by FromObject if it's passed a non-status object.
type UnexpectedObjectError struct {
Object runtime.Object
}
// Error returns an error message describing 'u'.
func (u *UnexpectedObjectError) Error() string {
return fmt.Sprintf("unexpected object: %v", u.Object)
}
// FromObject generates an StatusError from an unversioned.Status, if that is the type of obj; otherwise,
// returns an UnexpecteObjectError.
func FromObject(obj runtime.Object) error {
switch t := obj.(type) {
case *unversioned.Status:
return &StatusError{*t}
}
return &UnexpectedObjectError{obj}
}
// NewNotFound returns a new error which indicates that the resource of the kind and the name was not found.
func NewNotFound(qualifiedResource unversioned.GroupResource, name string) *StatusError {
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: http.StatusNotFound,
Reason: unversioned.StatusReasonNotFound,
Details: &unversioned.StatusDetails{
Group: qualifiedResource.Group,
Kind: qualifiedResource.Resource,
Name: name,
},
Message: fmt.Sprintf("%s %q not found", qualifiedResource.String(), name),
}}
}
// NewAlreadyExists returns an error indicating the item requested exists by that identifier.
func NewAlreadyExists(qualifiedResource unversioned.GroupResource, name string) *StatusError {
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: http.StatusConflict,
Reason: unversioned.StatusReasonAlreadyExists,
Details: &unversioned.StatusDetails{
Group: qualifiedResource.Group,
Kind: qualifiedResource.Resource,
Name: name,
},
Message: fmt.Sprintf("%s %q already exists", qualifiedResource.String(), name),
}}
}
// NewUnauthorized returns an error indicating the client is not authorized to perform the requested
// action.
func NewUnauthorized(reason string) *StatusError {
message := reason
if len(message) == 0 {
message = "not authorized"
}
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: http.StatusUnauthorized,
Reason: unversioned.StatusReasonUnauthorized,
Message: message,
}}
}
// NewForbidden returns an error indicating the requested action was forbidden
func NewForbidden(qualifiedResource unversioned.GroupResource, name string, err error) *StatusError {
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: http.StatusForbidden,
Reason: unversioned.StatusReasonForbidden,
Details: &unversioned.StatusDetails{
Group: qualifiedResource.Group,
Kind: qualifiedResource.Resource,
Name: name,
},
Message: fmt.Sprintf("%s %q is forbidden: %v", qualifiedResource.String(), name, err),
}}
}
// NewConflict returns an error indicating the item can't be updated as provided.
func NewConflict(qualifiedResource unversioned.GroupResource, name string, err error) *StatusError {
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: http.StatusConflict,
Reason: unversioned.StatusReasonConflict,
Details: &unversioned.StatusDetails{
Group: qualifiedResource.Group,
Kind: qualifiedResource.Resource,
Name: name,
},
Message: fmt.Sprintf("Operation cannot be fulfilled on %s %q: %v", qualifiedResource.String(), name, err),
}}
}
// 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{unversioned.Status{
Status: unversioned.StatusFailure,
Code: http.StatusGone,
Reason: unversioned.StatusReasonGone,
Message: message,
}}
}
// NewInvalid returns an error indicating the item is invalid and cannot be processed.
func NewInvalid(qualifiedKind unversioned.GroupKind, name string, errs field.ErrorList) *StatusError {
causes := make([]unversioned.StatusCause, 0, len(errs))
for i := range errs {
err := errs[i]
causes = append(causes, unversioned.StatusCause{
Type: unversioned.CauseType(err.Type),
Message: err.ErrorBody(),
Field: err.Field,
})
}
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: StatusUnprocessableEntity, // RFC 4918: StatusUnprocessableEntity
Reason: unversioned.StatusReasonInvalid,
Details: &unversioned.StatusDetails{
Group: qualifiedKind.Group,
Kind: qualifiedKind.Kind,
Name: name,
Causes: causes,
},
Message: fmt.Sprintf("%s %q is invalid: %v", qualifiedKind.String(), name, errs.ToAggregate()),
}}
}
// NewBadRequest creates an error that indicates that the request is invalid and can not be processed.
func NewBadRequest(reason string) *StatusError {
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: http.StatusBadRequest,
Reason: unversioned.StatusReasonBadRequest,
Message: reason,
}}
}
// NewServiceUnavailable creates an error that indicates that the requested service is unavailable.
func NewServiceUnavailable(reason string) *StatusError {
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: http.StatusServiceUnavailable,
Reason: unversioned.StatusReasonServiceUnavailable,
Message: reason,
}}
}
// NewMethodNotSupported returns an error indicating the requested action is not supported on this kind.
func NewMethodNotSupported(qualifiedResource unversioned.GroupResource, action string) *StatusError {
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: http.StatusMethodNotAllowed,
Reason: unversioned.StatusReasonMethodNotAllowed,
Details: &unversioned.StatusDetails{
Group: qualifiedResource.Group,
Kind: qualifiedResource.Resource,
},
Message: fmt.Sprintf("%s is not supported on resources of kind %q", action, qualifiedResource.String()),
}}
}
// NewServerTimeout returns an error indicating the requested action could not be completed due to a
// transient error, and the client should try again.
func NewServerTimeout(qualifiedResource unversioned.GroupResource, operation string, retryAfterSeconds int) *StatusError {
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: http.StatusInternalServerError,
Reason: unversioned.StatusReasonServerTimeout,
Details: &unversioned.StatusDetails{
Group: qualifiedResource.Group,
Kind: qualifiedResource.Resource,
Name: operation,
RetryAfterSeconds: int32(retryAfterSeconds),
},
Message: fmt.Sprintf("The %s operation against %s could not be completed at this time, please try again.", operation, qualifiedResource.String()),
}}
}
// NewServerTimeoutForKind should not exist. Server timeouts happen when accessing resources, the Kind is just what we
// happened to be looking at when the request failed. This delegates to keep code sane, but we should work towards removing this.
func NewServerTimeoutForKind(qualifiedKind unversioned.GroupKind, operation string, retryAfterSeconds int) *StatusError {
return NewServerTimeout(unversioned.GroupResource{Group: qualifiedKind.Group, Resource: qualifiedKind.Kind}, operation, retryAfterSeconds)
}
// NewInternalError returns an error indicating the item is invalid and cannot be processed.
func NewInternalError(err error) *StatusError {
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: http.StatusInternalServerError,
Reason: unversioned.StatusReasonInternalError,
Details: &unversioned.StatusDetails{
Causes: []unversioned.StatusCause{{Message: err.Error()}},
},
Message: fmt.Sprintf("Internal error occurred: %v", err),
}}
}
// NewTimeoutError returns an error indicating that a timeout occurred before the request
// could be completed. Clients may retry, but the operation may still complete.
func NewTimeoutError(message string, retryAfterSeconds int) *StatusError {
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: StatusServerTimeout,
Reason: unversioned.StatusReasonTimeout,
Message: fmt.Sprintf("Timeout: %s", message),
Details: &unversioned.StatusDetails{
RetryAfterSeconds: int32(retryAfterSeconds),
},
}}
}
// NewGenericServerResponse returns a new error for server responses that are not in a recognizable form.
func NewGenericServerResponse(code int, verb string, qualifiedResource unversioned.GroupResource, name, serverMessage string, retryAfterSeconds int, isUnexpectedResponse bool) *StatusError {
reason := unversioned.StatusReasonUnknown
message := fmt.Sprintf("the server responded with the status code %d but did not return more information", code)
switch code {
case http.StatusConflict:
if verb == "POST" {
reason = unversioned.StatusReasonAlreadyExists
} else {
reason = unversioned.StatusReasonConflict
}
message = "the server reported a conflict"
case http.StatusNotFound:
reason = unversioned.StatusReasonNotFound
message = "the server could not find the requested resource"
case http.StatusBadRequest:
reason = unversioned.StatusReasonBadRequest
message = "the server rejected our request for an unknown reason"
case http.StatusUnauthorized:
reason = unversioned.StatusReasonUnauthorized
message = "the server has asked for the client to provide credentials"
case http.StatusForbidden:
reason = unversioned.StatusReasonForbidden
message = "the server does not allow access to the requested resource"
case http.StatusMethodNotAllowed:
reason = unversioned.StatusReasonMethodNotAllowed
message = "the server does not allow this method on the requested resource"
case StatusUnprocessableEntity:
reason = unversioned.StatusReasonInvalid
message = "the server rejected our request due to an error in our request"
case StatusServerTimeout:
reason = unversioned.StatusReasonServerTimeout
message = "the server cannot complete the requested operation at this time, try again later"
case StatusTooManyRequests:
reason = unversioned.StatusReasonTimeout
message = "the server has received too many requests and has asked us to try again later"
default:
if code >= 500 {
reason = unversioned.StatusReasonInternalError
message = fmt.Sprintf("an error on the server (%q) has prevented the request from succeeding", serverMessage)
}
}
switch {
case !qualifiedResource.Empty() && len(name) > 0:
message = fmt.Sprintf("%s (%s %s %s)", message, strings.ToLower(verb), qualifiedResource.String(), name)
case !qualifiedResource.Empty():
message = fmt.Sprintf("%s (%s %s)", message, strings.ToLower(verb), qualifiedResource.String())
}
var causes []unversioned.StatusCause
if isUnexpectedResponse {
causes = []unversioned.StatusCause{
{
Type: unversioned.CauseTypeUnexpectedServerResponse,
Message: serverMessage,
},
}
} else {
causes = nil
}
return &StatusError{unversioned.Status{
Status: unversioned.StatusFailure,
Code: int32(code),
Reason: reason,
Details: &unversioned.StatusDetails{
Group: qualifiedResource.Group,
Kind: qualifiedResource.Resource,
Name: name,
Causes: causes,
RetryAfterSeconds: int32(retryAfterSeconds),
},
Message: message,
}}
}
// IsNotFound returns true if the specified error was created by NewNotFound.
func IsNotFound(err error) bool {
return reasonForError(err) == unversioned.StatusReasonNotFound
}
// IsAlreadyExists determines if the err is an error which indicates that a specified resource already exists.
func IsAlreadyExists(err error) bool {
return reasonForError(err) == unversioned.StatusReasonAlreadyExists
}
// IsConflict determines if the err is an error which indicates the provided update conflicts.
func IsConflict(err error) bool {
return reasonForError(err) == unversioned.StatusReasonConflict
}
// IsInvalid determines if the err is an error which indicates the provided resource is not valid.
func IsInvalid(err error) bool {
return reasonForError(err) == unversioned.StatusReasonInvalid
}
// IsMethodNotSupported determines if the err is an error which indicates the provided action could not
// be performed because it is not supported by the server.
func IsMethodNotSupported(err error) bool {
return reasonForError(err) == unversioned.StatusReasonMethodNotAllowed
}
// IsBadRequest determines if err is an error which indicates that the request is invalid.
func IsBadRequest(err error) bool {
return reasonForError(err) == unversioned.StatusReasonBadRequest
}
// IsUnauthorized determines if err is an error which indicates that the request is unauthorized and
// requires authentication by the user.
func IsUnauthorized(err error) bool {
return reasonForError(err) == unversioned.StatusReasonUnauthorized
}
// IsForbidden determines if err is an error which indicates that the request is forbidden and cannot
// be completed as requested.
func IsForbidden(err error) bool {
return reasonForError(err) == unversioned.StatusReasonForbidden
}
// IsServerTimeout determines if err is an error which indicates that the request needs to be retried
// by the client.
func IsServerTimeout(err error) bool {
return reasonForError(err) == unversioned.StatusReasonServerTimeout
}
// IsInternalError determines if err is an error which indicates an internal server error.
func IsInternalError(err error) bool {
return reasonForError(err) == unversioned.StatusReasonInternalError
}
// IsTooManyRequests determines if err is an error which indicates that there are too many requests
// that the server cannot handle.
// TODO: update IsTooManyRequests() when the TooManyRequests(429) error returned from the API server has a non-empty Reason field
func IsTooManyRequests(err error) bool {
switch t := err.(type) {
case APIStatus:
return t.Status().Code == StatusTooManyRequests
}
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 {
switch t := err.(type) {
case APIStatus:
if d := t.Status().Details; d != nil {
for _, cause := range d.Causes {
if cause.Type == unversioned.CauseTypeUnexpectedServerResponse {
return true
}
}
}
}
return false
}
// IsUnexpectedObjectError determines if err is due to an unexpected object from the master.
func IsUnexpectedObjectError(err error) bool {
_, ok := err.(*UnexpectedObjectError)
return err != nil && ok
}
// SuggestsClientDelay returns true if this error suggests a client delay as well as the
// suggested seconds to wait, or false if the error does not imply a wait.
func SuggestsClientDelay(err error) (int, bool) {
switch t := err.(type) {
case APIStatus:
if t.Status().Details != nil {
switch t.Status().Reason {
case unversioned.StatusReasonServerTimeout, unversioned.StatusReasonTimeout:
return int(t.Status().Details.RetryAfterSeconds), true
}
}
}
return 0, false
}
func reasonForError(err error) unversioned.StatusReason {
switch t := err.(type) {
case APIStatus:
return t.Status().Reason
}
return unversioned.StatusReasonUnknown
}

View file

@ -1,38 +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 api
// Field path constants that are specific to the internal API
// representation.
const (
NodeUnschedulableField = "spec.unschedulable"
ObjectNameField = "metadata.name"
PodHostField = "spec.nodeName"
PodStatusField = "status.phase"
SecretTypeField = "type"
EventReasonField = "reason"
EventSourceField = "source"
EventTypeField = "type"
EventInvolvedKindField = "involvedObject.kind"
EventInvolvedNamespaceField = "involvedObject.namespace"
EventInvolvedNameField = "involvedObject.name"
EventInvolvedUIDField = "involvedObject.uid"
EventInvolvedAPIVersionField = "involvedObject.apiVersion"
EventInvolvedResourceVersionField = "involvedObject.resourceVersion"
EventInvolvedFieldPathField = "involvedObject.fieldPath"
)

View file

@ -1,64 +0,0 @@
/*
Copyright 2014 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 api
import (
"fmt"
utilrand "k8s.io/client-go/pkg/util/rand"
)
// NameGenerator generates names for objects. Some backends may have more information
// available to guide selection of new names and this interface hides those details.
type NameGenerator interface {
// GenerateName generates a valid name from the base name, adding a random suffix to the
// the base. If base is valid, the returned name must also be valid. The generator is
// responsible for knowing the maximum valid name length.
GenerateName(base string) string
}
// GenerateName will resolve the object name of the provided ObjectMeta to a generated version if
// necessary. It expects that validation for ObjectMeta has already completed (that Base is a
// valid name) and that the NameGenerator generates a name that is also valid.
func GenerateName(u NameGenerator, meta *ObjectMeta) {
if len(meta.GenerateName) == 0 || len(meta.Name) != 0 {
return
}
meta.Name = u.GenerateName(meta.GenerateName)
}
// simpleNameGenerator generates random names.
type simpleNameGenerator struct{}
// SimpleNameGenerator is a generator that returns the name plus a random suffix of five alphanumerics
// when a name is requested. The string is guaranteed to not exceed the length of a standard Kubernetes
// name (63 characters)
var SimpleNameGenerator NameGenerator = simpleNameGenerator{}
const (
// TODO: make this flexible for non-core resources with alternate naming rules.
maxNameLength = 63
randomLength = 5
maxGeneratedNameLength = maxNameLength - randomLength
)
func (simpleNameGenerator) GenerateName(base string) string {
if len(base) > maxGeneratedNameLength {
base = base[:maxGeneratedNameLength]
}
return fmt.Sprintf("%s%s", base, utilrand.String(randomLength))
}

View file

@ -1,631 +0,0 @@
/*
Copyright 2014 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 api
import (
"crypto/md5"
"encoding/json"
"fmt"
"reflect"
"strings"
"time"
"k8s.io/client-go/pkg/api/resource"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/conversion"
"k8s.io/client-go/pkg/fields"
"k8s.io/client-go/pkg/labels"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/selection"
"k8s.io/client-go/pkg/types"
"k8s.io/client-go/pkg/util/sets"
"github.com/davecgh/go-spew/spew"
)
// Conversion error conveniently packages up errors in conversions.
type ConversionError struct {
In, Out interface{}
Message string
}
// Return a helpful string about the error
func (c *ConversionError) Error() string {
return spew.Sprintf(
"Conversion error: %s. (in: %v(%+v) out: %v)",
c.Message, reflect.TypeOf(c.In), c.In, reflect.TypeOf(c.Out),
)
}
// Semantic can do semantic deep equality checks for api objects.
// Example: api.Semantic.DeepEqual(aPod, aPodWithNonNilButEmptyMaps) == true
var Semantic = conversion.EqualitiesOrDie(
func(a, b resource.Quantity) bool {
// Ignore formatting, only care that numeric value stayed the same.
// TODO: if we decide it's important, it should be safe to start comparing the format.
//
// Uninitialized quantities are equivalent to 0 quantities.
return a.Cmp(b) == 0
},
func(a, b unversioned.Time) bool {
return a.UTC() == b.UTC()
},
func(a, b labels.Selector) bool {
return a.String() == b.String()
},
func(a, b fields.Selector) bool {
return a.String() == b.String()
},
)
var standardResourceQuotaScopes = sets.NewString(
string(ResourceQuotaScopeTerminating),
string(ResourceQuotaScopeNotTerminating),
string(ResourceQuotaScopeBestEffort),
string(ResourceQuotaScopeNotBestEffort),
)
// IsStandardResourceQuotaScope returns true if the scope is a standard value
func IsStandardResourceQuotaScope(str string) bool {
return standardResourceQuotaScopes.Has(str)
}
var podObjectCountQuotaResources = sets.NewString(
string(ResourcePods),
)
var podComputeQuotaResources = sets.NewString(
string(ResourceCPU),
string(ResourceMemory),
string(ResourceLimitsCPU),
string(ResourceLimitsMemory),
string(ResourceRequestsCPU),
string(ResourceRequestsMemory),
)
// IsResourceQuotaScopeValidForResource returns true if the resource applies to the specified scope
func IsResourceQuotaScopeValidForResource(scope ResourceQuotaScope, resource string) bool {
switch scope {
case ResourceQuotaScopeTerminating, ResourceQuotaScopeNotTerminating, ResourceQuotaScopeNotBestEffort:
return podObjectCountQuotaResources.Has(resource) || podComputeQuotaResources.Has(resource)
case ResourceQuotaScopeBestEffort:
return podObjectCountQuotaResources.Has(resource)
default:
return true
}
}
var standardContainerResources = sets.NewString(
string(ResourceCPU),
string(ResourceMemory),
)
// IsStandardContainerResourceName returns true if the container can make a resource request
// for the specified resource
func IsStandardContainerResourceName(str string) bool {
return standardContainerResources.Has(str)
}
// IsOpaqueIntResourceName returns true if the resource name has the opaque
// integer resource prefix.
func IsOpaqueIntResourceName(name ResourceName) bool {
return strings.HasPrefix(string(name), ResourceOpaqueIntPrefix)
}
// OpaqueIntResourceName returns a ResourceName with the canonical opaque
// integer prefix prepended. If the argument already has the prefix, it is
// returned unmodified.
func OpaqueIntResourceName(name string) ResourceName {
if IsOpaqueIntResourceName(ResourceName(name)) {
return ResourceName(name)
}
return ResourceName(fmt.Sprintf("%s%s", ResourceOpaqueIntPrefix, name))
}
var standardLimitRangeTypes = sets.NewString(
string(LimitTypePod),
string(LimitTypeContainer),
string(LimitTypePersistentVolumeClaim),
)
// IsStandardLimitRangeType returns true if the type is Pod or Container
func IsStandardLimitRangeType(str string) bool {
return standardLimitRangeTypes.Has(str)
}
var standardQuotaResources = sets.NewString(
string(ResourceCPU),
string(ResourceMemory),
string(ResourceRequestsCPU),
string(ResourceRequestsMemory),
string(ResourceRequestsStorage),
string(ResourceLimitsCPU),
string(ResourceLimitsMemory),
string(ResourcePods),
string(ResourceQuotas),
string(ResourceServices),
string(ResourceReplicationControllers),
string(ResourceSecrets),
string(ResourcePersistentVolumeClaims),
string(ResourceConfigMaps),
string(ResourceServicesNodePorts),
string(ResourceServicesLoadBalancers),
)
// IsStandardQuotaResourceName returns true if the resource is known to
// the quota tracking system
func IsStandardQuotaResourceName(str string) bool {
return standardQuotaResources.Has(str)
}
var standardResources = sets.NewString(
string(ResourceCPU),
string(ResourceMemory),
string(ResourceRequestsCPU),
string(ResourceRequestsMemory),
string(ResourceLimitsCPU),
string(ResourceLimitsMemory),
string(ResourcePods),
string(ResourceQuotas),
string(ResourceServices),
string(ResourceReplicationControllers),
string(ResourceSecrets),
string(ResourceConfigMaps),
string(ResourcePersistentVolumeClaims),
string(ResourceStorage),
string(ResourceRequestsStorage),
)
// IsStandardResourceName returns true if the resource is known to the system
func IsStandardResourceName(str string) bool {
return standardResources.Has(str)
}
var integerResources = sets.NewString(
string(ResourcePods),
string(ResourceQuotas),
string(ResourceServices),
string(ResourceReplicationControllers),
string(ResourceSecrets),
string(ResourceConfigMaps),
string(ResourcePersistentVolumeClaims),
string(ResourceServicesNodePorts),
string(ResourceServicesLoadBalancers),
)
// IsIntegerResourceName returns true if the resource is measured in integer values
func IsIntegerResourceName(str string) bool {
return integerResources.Has(str) || IsOpaqueIntResourceName(ResourceName(str))
}
// NewDeleteOptions returns a DeleteOptions indicating the resource should
// be deleted within the specified grace period. Use zero to indicate
// immediate deletion. If you would prefer to use the default grace period,
// use &api.DeleteOptions{} directly.
func NewDeleteOptions(grace int64) *DeleteOptions {
return &DeleteOptions{GracePeriodSeconds: &grace}
}
// NewPreconditionDeleteOptions returns a DeleteOptions with a UID precondition set.
func NewPreconditionDeleteOptions(uid string) *DeleteOptions {
u := types.UID(uid)
p := Preconditions{UID: &u}
return &DeleteOptions{Preconditions: &p}
}
// NewUIDPreconditions returns a Preconditions with UID set.
func NewUIDPreconditions(uid string) *Preconditions {
u := types.UID(uid)
return &Preconditions{UID: &u}
}
// this function aims to check if the service's ClusterIP is set or not
// the objective is not to perform validation here
func IsServiceIPSet(service *Service) bool {
return service.Spec.ClusterIP != ClusterIPNone && service.Spec.ClusterIP != ""
}
// this function aims to check if the service's cluster IP is requested or not
func IsServiceIPRequested(service *Service) bool {
// ExternalName services are CNAME aliases to external ones. Ignore the IP.
if service.Spec.Type == ServiceTypeExternalName {
return false
}
return service.Spec.ClusterIP == ""
}
var standardFinalizers = sets.NewString(
string(FinalizerKubernetes),
FinalizerOrphan,
)
// HasAnnotation returns a bool if passed in annotation exists
func HasAnnotation(obj ObjectMeta, ann string) bool {
_, found := obj.Annotations[ann]
return found
}
// SetMetaDataAnnotation sets the annotation and value
func SetMetaDataAnnotation(obj *ObjectMeta, ann string, value string) {
if obj.Annotations == nil {
obj.Annotations = make(map[string]string)
}
obj.Annotations[ann] = value
}
func IsStandardFinalizerName(str string) bool {
return standardFinalizers.Has(str)
}
// SingleObject returns a ListOptions for watching a single object.
func SingleObject(meta ObjectMeta) ListOptions {
return ListOptions{
FieldSelector: fields.OneTermEqualSelector("metadata.name", meta.Name),
ResourceVersion: meta.ResourceVersion,
}
}
// AddToNodeAddresses appends the NodeAddresses to the passed-by-pointer slice,
// only if they do not already exist
func AddToNodeAddresses(addresses *[]NodeAddress, addAddresses ...NodeAddress) {
for _, add := range addAddresses {
exists := false
for _, existing := range *addresses {
if existing.Address == add.Address && existing.Type == add.Type {
exists = true
break
}
}
if !exists {
*addresses = append(*addresses, add)
}
}
}
func HashObject(obj runtime.Object, codec runtime.Codec) (string, error) {
data, err := runtime.Encode(codec, obj)
if err != nil {
return "", err
}
return fmt.Sprintf("%x", md5.Sum(data)), nil
}
// TODO: make method on LoadBalancerStatus?
func LoadBalancerStatusEqual(l, r *LoadBalancerStatus) bool {
return ingressSliceEqual(l.Ingress, r.Ingress)
}
func ingressSliceEqual(lhs, rhs []LoadBalancerIngress) bool {
if len(lhs) != len(rhs) {
return false
}
for i := range lhs {
if !ingressEqual(&lhs[i], &rhs[i]) {
return false
}
}
return true
}
func ingressEqual(lhs, rhs *LoadBalancerIngress) bool {
if lhs.IP != rhs.IP {
return false
}
if lhs.Hostname != rhs.Hostname {
return false
}
return true
}
// TODO: make method on LoadBalancerStatus?
func LoadBalancerStatusDeepCopy(lb *LoadBalancerStatus) *LoadBalancerStatus {
c := &LoadBalancerStatus{}
c.Ingress = make([]LoadBalancerIngress, len(lb.Ingress))
for i := range lb.Ingress {
c.Ingress[i] = lb.Ingress[i]
}
return c
}
// GetAccessModesAsString returns a string representation of an array of access modes.
// modes, when present, are always in the same order: RWO,ROX,RWX.
func GetAccessModesAsString(modes []PersistentVolumeAccessMode) string {
modes = removeDuplicateAccessModes(modes)
modesStr := []string{}
if containsAccessMode(modes, ReadWriteOnce) {
modesStr = append(modesStr, "RWO")
}
if containsAccessMode(modes, ReadOnlyMany) {
modesStr = append(modesStr, "ROX")
}
if containsAccessMode(modes, ReadWriteMany) {
modesStr = append(modesStr, "RWX")
}
return strings.Join(modesStr, ",")
}
// GetAccessModesAsString returns an array of AccessModes from a string created by GetAccessModesAsString
func GetAccessModesFromString(modes string) []PersistentVolumeAccessMode {
strmodes := strings.Split(modes, ",")
accessModes := []PersistentVolumeAccessMode{}
for _, s := range strmodes {
s = strings.Trim(s, " ")
switch {
case s == "RWO":
accessModes = append(accessModes, ReadWriteOnce)
case s == "ROX":
accessModes = append(accessModes, ReadOnlyMany)
case s == "RWX":
accessModes = append(accessModes, ReadWriteMany)
}
}
return accessModes
}
// removeDuplicateAccessModes returns an array of access modes without any duplicates
func removeDuplicateAccessModes(modes []PersistentVolumeAccessMode) []PersistentVolumeAccessMode {
accessModes := []PersistentVolumeAccessMode{}
for _, m := range modes {
if !containsAccessMode(accessModes, m) {
accessModes = append(accessModes, m)
}
}
return accessModes
}
func containsAccessMode(modes []PersistentVolumeAccessMode, mode PersistentVolumeAccessMode) bool {
for _, m := range modes {
if m == mode {
return true
}
}
return false
}
// ParseRFC3339 parses an RFC3339 date in either RFC3339Nano or RFC3339 format.
func ParseRFC3339(s string, nowFn func() unversioned.Time) (unversioned.Time, error) {
if t, timeErr := time.Parse(time.RFC3339Nano, s); timeErr == nil {
return unversioned.Time{Time: t}, nil
}
t, err := time.Parse(time.RFC3339, s)
if err != nil {
return unversioned.Time{}, err
}
return unversioned.Time{Time: t}, nil
}
// NodeSelectorRequirementsAsSelector converts the []NodeSelectorRequirement api type into a struct that implements
// labels.Selector.
func NodeSelectorRequirementsAsSelector(nsm []NodeSelectorRequirement) (labels.Selector, error) {
if len(nsm) == 0 {
return labels.Nothing(), nil
}
selector := labels.NewSelector()
for _, expr := range nsm {
var op selection.Operator
switch expr.Operator {
case NodeSelectorOpIn:
op = selection.In
case NodeSelectorOpNotIn:
op = selection.NotIn
case NodeSelectorOpExists:
op = selection.Exists
case NodeSelectorOpDoesNotExist:
op = selection.DoesNotExist
case NodeSelectorOpGt:
op = selection.GreaterThan
case NodeSelectorOpLt:
op = selection.LessThan
default:
return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator)
}
r, err := labels.NewRequirement(expr.Key, op, expr.Values)
if err != nil {
return nil, err
}
selector = selector.Add(*r)
}
return selector, nil
}
const (
// AffinityAnnotationKey represents the key of affinity data (json serialized)
// in the Annotations of a Pod.
AffinityAnnotationKey string = "scheduler.alpha.kubernetes.io/affinity"
// TolerationsAnnotationKey represents the key of tolerations data (json serialized)
// in the Annotations of a Pod.
TolerationsAnnotationKey string = "scheduler.alpha.kubernetes.io/tolerations"
// TaintsAnnotationKey represents the key of taints data (json serialized)
// in the Annotations of a Node.
TaintsAnnotationKey string = "scheduler.alpha.kubernetes.io/taints"
// SeccompPodAnnotationKey represents the key of a seccomp profile applied
// to all containers of a pod.
SeccompPodAnnotationKey string = "seccomp.security.alpha.kubernetes.io/pod"
// SeccompContainerAnnotationKeyPrefix represents the key of a seccomp profile applied
// to one container of a pod.
SeccompContainerAnnotationKeyPrefix string = "container.seccomp.security.alpha.kubernetes.io/"
// CreatedByAnnotation represents the key used to store the spec(json)
// used to create the resource.
CreatedByAnnotation = "kubernetes.io/created-by"
// PreferAvoidPodsAnnotationKey represents the key of preferAvoidPods data (json serialized)
// in the Annotations of a Node.
PreferAvoidPodsAnnotationKey string = "scheduler.alpha.kubernetes.io/preferAvoidPods"
// SysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure
// container of a pod. The annotation value is a comma separated list of sysctl_name=value
// key-value pairs. Only a limited set of whitelisted and isolated sysctls is supported by
// the kubelet. Pods with other sysctls will fail to launch.
SysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/sysctls"
// UnsafeSysctlsPodAnnotationKey represents the key of sysctls which are set for the infrastructure
// container of a pod. The annotation value is a comma separated list of sysctl_name=value
// key-value pairs. Unsafe sysctls must be explicitly enabled for a kubelet. They are properly
// namespaced to a pod or a container, but their isolation is usually unclear or weak. Their use
// is at-your-own-risk. Pods that attempt to set an unsafe sysctl that is not enabled for a kubelet
// will fail to launch.
UnsafeSysctlsPodAnnotationKey string = "security.alpha.kubernetes.io/unsafe-sysctls"
)
// GetAffinityFromPod gets the json serialized affinity data from Pod.Annotations
// and converts it to the Affinity type in api.
func GetAffinityFromPodAnnotations(annotations map[string]string) (*Affinity, error) {
if len(annotations) > 0 && annotations[AffinityAnnotationKey] != "" {
var affinity Affinity
err := json.Unmarshal([]byte(annotations[AffinityAnnotationKey]), &affinity)
if err != nil {
return nil, err
}
return &affinity, nil
}
return nil, nil
}
// GetTolerationsFromPodAnnotations gets the json serialized tolerations data from Pod.Annotations
// and converts it to the []Toleration type in api.
func GetTolerationsFromPodAnnotations(annotations map[string]string) ([]Toleration, error) {
var tolerations []Toleration
if len(annotations) > 0 && annotations[TolerationsAnnotationKey] != "" {
err := json.Unmarshal([]byte(annotations[TolerationsAnnotationKey]), &tolerations)
if err != nil {
return tolerations, err
}
}
return tolerations, nil
}
// GetTaintsFromNodeAnnotations gets the json serialized taints data from Pod.Annotations
// and converts it to the []Taint type in api.
func GetTaintsFromNodeAnnotations(annotations map[string]string) ([]Taint, error) {
var taints []Taint
if len(annotations) > 0 && annotations[TaintsAnnotationKey] != "" {
err := json.Unmarshal([]byte(annotations[TaintsAnnotationKey]), &taints)
if err != nil {
return []Taint{}, err
}
}
return taints, nil
}
// TolerationToleratesTaint checks if the toleration tolerates the taint.
func TolerationToleratesTaint(toleration *Toleration, taint *Taint) bool {
if len(toleration.Effect) != 0 && toleration.Effect != taint.Effect {
return false
}
if toleration.Key != taint.Key {
return false
}
// TODO: Use proper defaulting when Toleration becomes a field of PodSpec
if (len(toleration.Operator) == 0 || toleration.Operator == TolerationOpEqual) && toleration.Value == taint.Value {
return true
}
if toleration.Operator == TolerationOpExists {
return true
}
return false
}
// TaintToleratedByTolerations checks if taint is tolerated by any of the tolerations.
func TaintToleratedByTolerations(taint *Taint, tolerations []Toleration) bool {
tolerated := false
for i := range tolerations {
if TolerationToleratesTaint(&tolerations[i], taint) {
tolerated = true
break
}
}
return tolerated
}
// MatchTaint checks if the taint matches taintToMatch. Taints are unique by key:effect,
// if the two taints have same key:effect, regard as they match.
func (t *Taint) MatchTaint(taintToMatch Taint) bool {
return t.Key == taintToMatch.Key && t.Effect == taintToMatch.Effect
}
// taint.ToString() converts taint struct to string in format key=value:effect or key:effect.
func (t *Taint) ToString() string {
if len(t.Value) == 0 {
return fmt.Sprintf("%v:%v", t.Key, t.Effect)
}
return fmt.Sprintf("%v=%v:%v", t.Key, t.Value, t.Effect)
}
func GetAvoidPodsFromNodeAnnotations(annotations map[string]string) (AvoidPods, error) {
var avoidPods AvoidPods
if len(annotations) > 0 && annotations[PreferAvoidPodsAnnotationKey] != "" {
err := json.Unmarshal([]byte(annotations[PreferAvoidPodsAnnotationKey]), &avoidPods)
if err != nil {
return avoidPods, err
}
}
return avoidPods, nil
}
// SysctlsFromPodAnnotations parses the sysctl annotations into a slice of safe Sysctls
// and a slice of unsafe Sysctls. This is only a convenience wrapper around
// SysctlsFromPodAnnotation.
func SysctlsFromPodAnnotations(a map[string]string) ([]Sysctl, []Sysctl, error) {
safe, err := SysctlsFromPodAnnotation(a[SysctlsPodAnnotationKey])
if err != nil {
return nil, nil, err
}
unsafe, err := SysctlsFromPodAnnotation(a[UnsafeSysctlsPodAnnotationKey])
if err != nil {
return nil, nil, err
}
return safe, unsafe, nil
}
// SysctlsFromPodAnnotation parses an annotation value into a slice of Sysctls.
func SysctlsFromPodAnnotation(annotation string) ([]Sysctl, error) {
if len(annotation) == 0 {
return nil, nil
}
kvs := strings.Split(annotation, ",")
sysctls := make([]Sysctl, len(kvs))
for i, kv := range kvs {
cs := strings.Split(kv, "=")
if len(cs) != 2 || len(cs[0]) == 0 {
return nil, fmt.Errorf("sysctl %q not of the format sysctl_name=value", kv)
}
sysctls[i].Name = cs[0]
sysctls[i].Value = cs[1]
}
return sysctls, nil
}
// PodAnnotationsFromSysctls creates an annotation value for a slice of Sysctls.
func PodAnnotationsFromSysctls(sysctls []Sysctl) string {
if len(sysctls) == 0 {
return ""
}
kvs := make([]string, len(sysctls))
for i := range sysctls {
kvs[i] = fmt.Sprintf("%s=%s", sysctls[i].Name, sysctls[i].Value)
}
return strings.Join(kvs, ",")
}

View file

@ -1,153 +0,0 @@
/*
Copyright 2014 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 install installs the v1 monolithic api, making it available as an
// option to all of the API encoding/decoding machinery.
package install
import (
"fmt"
"github.com/golang/glog"
"k8s.io/client-go/pkg/api"
"k8s.io/client-go/pkg/api/meta"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/pkg/apimachinery"
"k8s.io/client-go/pkg/apimachinery/registered"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/util/sets"
)
const importPrefix = "k8s.io/client-go/pkg/api"
var accessor = meta.NewAccessor()
// availableVersions lists all known external versions for this group from most preferred to least preferred
var availableVersions = []unversioned.GroupVersion{v1.SchemeGroupVersion}
func init() {
registered.RegisterVersions(availableVersions)
externalVersions := []unversioned.GroupVersion{}
for _, v := range availableVersions {
if registered.IsAllowedVersion(v) {
externalVersions = append(externalVersions, v)
}
}
if len(externalVersions) == 0 {
glog.V(4).Infof("No version is registered for group %v", api.GroupName)
return
}
if err := registered.EnableVersions(externalVersions...); err != nil {
glog.V(4).Infof("%v", err)
return
}
if err := enableVersions(externalVersions); err != nil {
glog.V(4).Infof("%v", err)
return
}
}
// TODO: enableVersions should be centralized rather than spread in each API
// group.
// We can combine registered.RegisterVersions, registered.EnableVersions and
// registered.RegisterGroup once we have moved enableVersions there.
func enableVersions(externalVersions []unversioned.GroupVersion) error {
addVersionsToScheme(externalVersions...)
preferredExternalVersion := externalVersions[0]
groupMeta := apimachinery.GroupMeta{
GroupVersion: preferredExternalVersion,
GroupVersions: externalVersions,
RESTMapper: newRESTMapper(externalVersions),
SelfLinker: runtime.SelfLinker(accessor),
InterfacesFor: interfacesFor,
}
if err := registered.RegisterGroup(groupMeta); err != nil {
return err
}
return nil
}
func newRESTMapper(externalVersions []unversioned.GroupVersion) meta.RESTMapper {
// the list of kinds that are scoped at the root of the api hierarchy
// if a kind is not enumerated here, it is assumed to have a namespace scope
rootScoped := sets.NewString(
"Node",
"Namespace",
"PersistentVolume",
"ComponentStatus",
)
// these kinds should be excluded from the list of resources
ignoredKinds := sets.NewString(
"ListOptions",
"DeleteOptions",
"Status",
"PodLogOptions",
"PodExecOptions",
"PodAttachOptions",
"PodProxyOptions",
"NodeProxyOptions",
"ServiceProxyOptions",
"ThirdPartyResource",
"ThirdPartyResourceData",
"ThirdPartyResourceList")
mapper := api.NewDefaultRESTMapper(externalVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped)
return mapper
}
// InterfacesFor returns the default Codec and ResourceVersioner for a given version
// string, or an error if the version is not known.
func interfacesFor(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
switch version {
case v1.SchemeGroupVersion:
return &meta.VersionInterfaces{
ObjectConvertor: api.Scheme,
MetadataAccessor: accessor,
}, nil
default:
g, _ := registered.Group(api.GroupName)
return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, g.GroupVersions)
}
}
func addVersionsToScheme(externalVersions ...unversioned.GroupVersion) {
// add the internal version to Scheme
if err := api.AddToScheme(api.Scheme); err != nil {
// Programmer error, detect immediately
panic(err)
}
// add the enabled external versions to Scheme
for _, v := range externalVersions {
if !registered.IsEnabledVersion(v) {
glog.Errorf("Version %s is not enabled, so it will not be added to the Scheme.", v)
continue
}
switch v {
case v1.SchemeGroupVersion:
if err := v1.AddToScheme(api.Scheme); err != nil {
// Programmer error, detect immediately
panic(err)
}
}
}
}

View file

@ -1,58 +0,0 @@
/*
Copyright 2015 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 api
import (
"strings"
"k8s.io/client-go/pkg/api/meta"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/util/sets"
)
// Instantiates a DefaultRESTMapper based on types registered in api.Scheme
func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, interfacesFunc meta.VersionInterfacesFunc,
importPathPrefix string, ignoredKinds, rootScoped sets.String) *meta.DefaultRESTMapper {
return NewDefaultRESTMapperFromScheme(defaultGroupVersions, interfacesFunc, importPathPrefix, ignoredKinds, rootScoped, Scheme)
}
// Instantiates a DefaultRESTMapper based on types registered in the given scheme.
func NewDefaultRESTMapperFromScheme(defaultGroupVersions []unversioned.GroupVersion, interfacesFunc meta.VersionInterfacesFunc,
importPathPrefix string, ignoredKinds, rootScoped sets.String, scheme *runtime.Scheme) *meta.DefaultRESTMapper {
mapper := meta.NewDefaultRESTMapper(defaultGroupVersions, interfacesFunc)
// enumerate all supported versions, get the kinds, and register with the mapper how to address
// our resources.
for _, gv := range defaultGroupVersions {
for kind, oType := range scheme.KnownTypes(gv) {
gvk := gv.WithKind(kind)
// TODO: Remove import path check.
// We check the import path because we currently stuff both "api" and "extensions" objects
// into the same group within Scheme since Scheme has no notion of groups yet.
if !strings.Contains(oType.PkgPath(), importPathPrefix) || ignoredKinds.Has(kind) {
continue
}
scope := meta.RESTScopeNamespace
if rootScoped.Has(kind) {
scope = meta.RESTScopeRoot
}
mapper.Add(gvk, scope)
}
}
return mapper
}

View file

@ -1,140 +0,0 @@
/*
Copyright 2014 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 api
import (
"k8s.io/client-go/pkg/api/meta"
"k8s.io/client-go/pkg/api/meta/metatypes"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/conversion"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/types"
"k8s.io/client-go/pkg/util/uuid"
)
// FillObjectMetaSystemFields populates fields that are managed by the system on ObjectMeta.
func FillObjectMetaSystemFields(ctx Context, meta *ObjectMeta) {
meta.CreationTimestamp = unversioned.Now()
// allows admission controllers to assign a UID earlier in the request processing
// to support tracking resources pending creation.
uid, found := UIDFrom(ctx)
if !found {
uid = uuid.NewUUID()
}
meta.UID = uid
meta.SelfLink = ""
}
// HasObjectMetaSystemFieldValues returns true if fields that are managed by the system on ObjectMeta have values.
func HasObjectMetaSystemFieldValues(meta *ObjectMeta) bool {
return !meta.CreationTimestamp.Time.IsZero() ||
len(meta.UID) != 0
}
// ObjectMetaFor returns a pointer to a provided object's ObjectMeta.
// TODO: allow runtime.Unknown to extract this object
// TODO: Remove this function and use meta.Accessor() instead.
func ObjectMetaFor(obj runtime.Object) (*ObjectMeta, error) {
v, err := conversion.EnforcePtr(obj)
if err != nil {
return nil, err
}
var meta *ObjectMeta
err = runtime.FieldPtr(v, "ObjectMeta", &meta)
return meta, err
}
// ListMetaFor returns a pointer to a provided object's ListMeta,
// or an error if the object does not have that pointer.
// TODO: allow runtime.Unknown to extract this object
func ListMetaFor(obj runtime.Object) (*unversioned.ListMeta, error) {
v, err := conversion.EnforcePtr(obj)
if err != nil {
return nil, err
}
var meta *unversioned.ListMeta
err = runtime.FieldPtr(v, "ListMeta", &meta)
return meta, err
}
func (obj *ObjectMeta) GetObjectMeta() meta.Object { return obj }
// Namespace implements meta.Object for any object with an ObjectMeta typed field. Allows
// fast, direct access to metadata fields for API objects.
func (meta *ObjectMeta) GetNamespace() string { return meta.Namespace }
func (meta *ObjectMeta) SetNamespace(namespace string) { meta.Namespace = namespace }
func (meta *ObjectMeta) GetName() string { return meta.Name }
func (meta *ObjectMeta) SetName(name string) { meta.Name = name }
func (meta *ObjectMeta) GetGenerateName() string { return meta.GenerateName }
func (meta *ObjectMeta) SetGenerateName(generateName string) { meta.GenerateName = generateName }
func (meta *ObjectMeta) GetUID() types.UID { return meta.UID }
func (meta *ObjectMeta) SetUID(uid types.UID) { meta.UID = uid }
func (meta *ObjectMeta) GetResourceVersion() string { return meta.ResourceVersion }
func (meta *ObjectMeta) SetResourceVersion(version string) { meta.ResourceVersion = version }
func (meta *ObjectMeta) GetSelfLink() string { return meta.SelfLink }
func (meta *ObjectMeta) SetSelfLink(selfLink string) { meta.SelfLink = selfLink }
func (meta *ObjectMeta) GetCreationTimestamp() unversioned.Time { return meta.CreationTimestamp }
func (meta *ObjectMeta) SetCreationTimestamp(creationTimestamp unversioned.Time) {
meta.CreationTimestamp = creationTimestamp
}
func (meta *ObjectMeta) GetDeletionTimestamp() *unversioned.Time { return meta.DeletionTimestamp }
func (meta *ObjectMeta) SetDeletionTimestamp(deletionTimestamp *unversioned.Time) {
meta.DeletionTimestamp = deletionTimestamp
}
func (meta *ObjectMeta) GetLabels() map[string]string { return meta.Labels }
func (meta *ObjectMeta) SetLabels(labels map[string]string) { meta.Labels = labels }
func (meta *ObjectMeta) GetAnnotations() map[string]string { return meta.Annotations }
func (meta *ObjectMeta) SetAnnotations(annotations map[string]string) { meta.Annotations = annotations }
func (meta *ObjectMeta) GetFinalizers() []string { return meta.Finalizers }
func (meta *ObjectMeta) SetFinalizers(finalizers []string) { meta.Finalizers = finalizers }
func (meta *ObjectMeta) GetOwnerReferences() []metatypes.OwnerReference {
ret := make([]metatypes.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
}
}
return ret
}
func (meta *ObjectMeta) SetOwnerReferences(references []metatypes.OwnerReference) {
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
}
}
meta.OwnerReferences = newReferences
}
func (meta *ObjectMeta) GetClusterName() string {
return meta.ClusterName
}
func (meta *ObjectMeta) SetClusterName(clusterName string) {
meta.ClusterName = clusterName
}

View file

@ -1,19 +0,0 @@
/*
Copyright 2014 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 meta provides functions for retrieving API metadata from objects
// belonging to the Kubernetes API
package meta

View file

@ -1,105 +0,0 @@
/*
Copyright 2014 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 meta
import (
"fmt"
"k8s.io/client-go/pkg/api/unversioned"
)
// AmbiguousResourceError is returned if the RESTMapper finds multiple matches for a resource
type AmbiguousResourceError struct {
PartialResource unversioned.GroupVersionResource
MatchingResources []unversioned.GroupVersionResource
MatchingKinds []unversioned.GroupVersionKind
}
func (e *AmbiguousResourceError) Error() string {
switch {
case len(e.MatchingKinds) > 0 && len(e.MatchingResources) > 0:
return fmt.Sprintf("%v matches multiple resources %v and kinds %v", e.PartialResource, e.MatchingResources, e.MatchingKinds)
case len(e.MatchingKinds) > 0:
return fmt.Sprintf("%v matches multiple kinds %v", e.PartialResource, e.MatchingKinds)
case len(e.MatchingResources) > 0:
return fmt.Sprintf("%v matches multiple resources %v", e.PartialResource, e.MatchingResources)
}
return fmt.Sprintf("%v matches multiple resources or kinds", e.PartialResource)
}
// AmbiguousKindError is returned if the RESTMapper finds multiple matches for a kind
type AmbiguousKindError struct {
PartialKind unversioned.GroupVersionKind
MatchingResources []unversioned.GroupVersionResource
MatchingKinds []unversioned.GroupVersionKind
}
func (e *AmbiguousKindError) Error() string {
switch {
case len(e.MatchingKinds) > 0 && len(e.MatchingResources) > 0:
return fmt.Sprintf("%v matches multiple resources %v and kinds %v", e.PartialKind, e.MatchingResources, e.MatchingKinds)
case len(e.MatchingKinds) > 0:
return fmt.Sprintf("%v matches multiple kinds %v", e.PartialKind, e.MatchingKinds)
case len(e.MatchingResources) > 0:
return fmt.Sprintf("%v matches multiple resources %v", e.PartialKind, e.MatchingResources)
}
return fmt.Sprintf("%v matches multiple resources or kinds", e.PartialKind)
}
func IsAmbiguousError(err error) bool {
if err == nil {
return false
}
switch err.(type) {
case *AmbiguousResourceError, *AmbiguousKindError:
return true
default:
return false
}
}
// NoResourceMatchError is returned if the RESTMapper can't find any match for a resource
type NoResourceMatchError struct {
PartialResource unversioned.GroupVersionResource
}
func (e *NoResourceMatchError) Error() string {
return fmt.Sprintf("no matches for %v", e.PartialResource)
}
// NoKindMatchError is returned if the RESTMapper can't find any match for a kind
type NoKindMatchError struct {
PartialKind unversioned.GroupVersionKind
}
func (e *NoKindMatchError) Error() string {
return fmt.Sprintf("no matches for %v", e.PartialKind)
}
func IsNoMatchError(err error) bool {
if err == nil {
return false
}
switch err.(type) {
case *NoResourceMatchError, *NoKindMatchError:
return true
default:
return false
}
}

View file

@ -1,97 +0,0 @@
/*
Copyright 2014 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 meta
import (
"fmt"
"k8s.io/client-go/pkg/api/unversioned"
utilerrors "k8s.io/client-go/pkg/util/errors"
)
// FirstHitRESTMapper is a wrapper for multiple RESTMappers which returns the
// first successful result for the singular requests
type FirstHitRESTMapper struct {
MultiRESTMapper
}
func (m FirstHitRESTMapper) String() string {
return fmt.Sprintf("FirstHitRESTMapper{\n\t%v\n}", m.MultiRESTMapper)
}
func (m FirstHitRESTMapper) ResourceFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
errors := []error{}
for _, t := range m.MultiRESTMapper {
ret, err := t.ResourceFor(resource)
if err == nil {
return ret, nil
}
errors = append(errors, err)
}
return unversioned.GroupVersionResource{}, collapseAggregateErrors(errors)
}
func (m FirstHitRESTMapper) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
errors := []error{}
for _, t := range m.MultiRESTMapper {
ret, err := t.KindFor(resource)
if err == nil {
return ret, nil
}
errors = append(errors, err)
}
return unversioned.GroupVersionKind{}, collapseAggregateErrors(errors)
}
// RESTMapping provides the REST mapping for the resource based on the
// kind and version. This implementation supports multiple REST schemas and
// return the first match.
func (m FirstHitRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (*RESTMapping, error) {
errors := []error{}
for _, t := range m.MultiRESTMapper {
ret, err := t.RESTMapping(gk, versions...)
if err == nil {
return ret, nil
}
errors = append(errors, err)
}
return nil, collapseAggregateErrors(errors)
}
// collapseAggregateErrors returns the minimal errors. it handles empty as nil, handles one item in a list
// by returning the item, and collapses all NoMatchErrors to a single one (since they should all be the same)
func collapseAggregateErrors(errors []error) error {
if len(errors) == 0 {
return nil
}
if len(errors) == 1 {
return errors[0]
}
allNoMatchErrors := true
for _, err := range errors {
allNoMatchErrors = allNoMatchErrors && IsNoMatchError(err)
}
if allNoMatchErrors {
return errors[0]
}
return utilerrors.NewAggregate(errors)
}

View file

@ -1,201 +0,0 @@
/*
Copyright 2015 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 meta
import (
"fmt"
"reflect"
"k8s.io/client-go/pkg/conversion"
"k8s.io/client-go/pkg/runtime"
)
// IsListType returns true if the provided Object has a slice called Items
func IsListType(obj runtime.Object) bool {
// if we're a runtime.Unstructured, check to see if we have an `items` key
// This is a list type for recognition, but other Items type methods will fail on it
// and give you errors.
if unstructured, ok := obj.(*runtime.Unstructured); ok {
_, ok := unstructured.Object["items"]
return ok
}
_, err := GetItemsPtr(obj)
return err == nil
}
// GetItemsPtr returns a pointer to the list object's Items member.
// If 'list' doesn't have an Items member, it's not really a list type
// and an error will be returned.
// This function will either return a pointer to a slice, or an error, but not both.
func GetItemsPtr(list runtime.Object) (interface{}, error) {
v, err := conversion.EnforcePtr(list)
if err != nil {
return nil, err
}
items := v.FieldByName("Items")
if !items.IsValid() {
return nil, fmt.Errorf("no Items field in %#v", list)
}
switch items.Kind() {
case reflect.Interface, reflect.Ptr:
target := reflect.TypeOf(items.Interface()).Elem()
if target.Kind() != reflect.Slice {
return nil, fmt.Errorf("items: Expected slice, got %s", target.Kind())
}
return items.Interface(), nil
case reflect.Slice:
return items.Addr().Interface(), nil
default:
return nil, fmt.Errorf("items: Expected slice, got %s", items.Kind())
}
}
// EachListItem invokes fn on each runtime.Object in the list. Any error immediately terminates
// the loop.
func EachListItem(obj runtime.Object, fn func(runtime.Object) error) error {
// TODO: Change to an interface call?
itemsPtr, err := GetItemsPtr(obj)
if err != nil {
return err
}
items, err := conversion.EnforcePtr(itemsPtr)
if err != nil {
return err
}
len := items.Len()
if len == 0 {
return nil
}
takeAddr := false
if elemType := items.Type().Elem(); elemType.Kind() != reflect.Ptr && elemType.Kind() != reflect.Interface {
if !items.Index(0).CanAddr() {
return fmt.Errorf("unable to take address of items in %T for EachListItem", obj)
}
takeAddr = true
}
for i := 0; i < len; i++ {
raw := items.Index(i)
if takeAddr {
raw = raw.Addr()
}
switch item := raw.Interface().(type) {
case *runtime.RawExtension:
if err := fn(item.Object); err != nil {
return err
}
case runtime.Object:
if err := fn(item); err != nil {
return err
}
default:
obj, ok := item.(runtime.Object)
if !ok {
return fmt.Errorf("%v: item[%v]: Expected object, got %#v(%s)", obj, i, raw.Interface(), raw.Kind())
}
if err := fn(obj); err != nil {
return err
}
}
}
return nil
}
// ExtractList returns obj's Items element as an array of runtime.Objects.
// Returns an error if obj is not a List type (does not have an Items member).
func ExtractList(obj runtime.Object) ([]runtime.Object, error) {
itemsPtr, err := GetItemsPtr(obj)
if err != nil {
return nil, err
}
items, err := conversion.EnforcePtr(itemsPtr)
if err != nil {
return nil, err
}
list := make([]runtime.Object, items.Len())
for i := range list {
raw := items.Index(i)
switch item := raw.Interface().(type) {
case runtime.RawExtension:
switch {
case item.Object != nil:
list[i] = item.Object
case item.Raw != nil:
// TODO: Set ContentEncoding and ContentType correctly.
list[i] = &runtime.Unknown{Raw: item.Raw}
default:
list[i] = nil
}
case runtime.Object:
list[i] = item
default:
var found bool
if list[i], found = raw.Addr().Interface().(runtime.Object); !found {
return nil, fmt.Errorf("%v: item[%v]: Expected object, got %#v(%s)", obj, i, raw.Interface(), raw.Kind())
}
}
}
return list, nil
}
// objectSliceType is the type of a slice of Objects
var objectSliceType = reflect.TypeOf([]runtime.Object{})
// 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),
// or if any of the objects are not of the right type.
func SetList(list runtime.Object, objects []runtime.Object) error {
itemsPtr, err := GetItemsPtr(list)
if err != nil {
return err
}
items, err := conversion.EnforcePtr(itemsPtr)
if err != nil {
return err
}
if items.Type() == objectSliceType {
items.Set(reflect.ValueOf(objects))
return nil
}
slice := reflect.MakeSlice(items.Type(), len(objects), len(objects))
for i := range objects {
dest := slice.Index(i)
// check to see if you're directly assignable
if reflect.TypeOf(objects[i]).AssignableTo(dest.Type()) {
dest.Set(reflect.ValueOf(objects[i]))
continue
}
src, err := conversion.EnforcePtr(objects[i])
if err != nil {
return err
}
if src.Type().AssignableTo(dest.Type()) {
dest.Set(src)
} else if src.Type().ConvertibleTo(dest.Type()) {
dest.Set(src.Convert(dest.Type()))
} else {
return fmt.Errorf("item[%d]: can't assign or convert %v into %v", i, src.Type(), dest.Type())
}
}
items.Set(slice)
return nil
}

View file

@ -1,184 +0,0 @@
/*
Copyright 2014 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 meta
import (
"k8s.io/client-go/pkg/api/meta/metatypes"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/types"
)
// VersionInterfaces contains the interfaces one should use for dealing with types of a particular version.
type VersionInterfaces struct {
runtime.ObjectConvertor
MetadataAccessor
}
type ObjectMetaAccessor interface {
GetObjectMeta() Object
}
// Object lets you work with object metadata from any of the versioned or
// internal API objects. Attempting to set or retrieve a field on an object that does
// not support that field (Name, UID, Namespace on lists) will be a no-op and return
// a default value.
type Object interface {
GetNamespace() string
SetNamespace(namespace string)
GetName() string
SetName(name string)
GetGenerateName() string
SetGenerateName(name string)
GetUID() types.UID
SetUID(uid types.UID)
GetResourceVersion() string
SetResourceVersion(version string)
GetSelfLink() string
SetSelfLink(selfLink string)
GetCreationTimestamp() unversioned.Time
SetCreationTimestamp(timestamp unversioned.Time)
GetDeletionTimestamp() *unversioned.Time
SetDeletionTimestamp(timestamp *unversioned.Time)
GetLabels() map[string]string
SetLabels(labels map[string]string)
GetAnnotations() map[string]string
SetAnnotations(annotations map[string]string)
GetFinalizers() []string
SetFinalizers(finalizers []string)
GetOwnerReferences() []metatypes.OwnerReference
SetOwnerReferences([]metatypes.OwnerReference)
GetClusterName() string
SetClusterName(clusterName string)
}
var _ Object = &runtime.Unstructured{}
type ListMetaAccessor interface {
GetListMeta() List
}
// List lets you work with list metadata from any of the versioned or
// internal API objects. Attempting to set or retrieve a field on an object that does
// not support that field will be a no-op and return a default value.
type List unversioned.List
// Type exposes the type and APIVersion of versioned or internal API objects.
type Type unversioned.Type
// MetadataAccessor lets you work with object and list metadata from any of the versioned or
// internal API objects. Attempting to set or retrieve a field on an object that does
// not support that field (Name, UID, Namespace on lists) will be a no-op and return
// a default value.
//
// MetadataAccessor exposes Interface in a way that can be used with multiple objects.
type MetadataAccessor interface {
APIVersion(obj runtime.Object) (string, error)
SetAPIVersion(obj runtime.Object, version string) error
Kind(obj runtime.Object) (string, error)
SetKind(obj runtime.Object, kind string) error
Namespace(obj runtime.Object) (string, error)
SetNamespace(obj runtime.Object, namespace string) error
Name(obj runtime.Object) (string, error)
SetName(obj runtime.Object, name string) error
GenerateName(obj runtime.Object) (string, error)
SetGenerateName(obj runtime.Object, name string) error
UID(obj runtime.Object) (types.UID, error)
SetUID(obj runtime.Object, uid types.UID) error
SelfLink(obj runtime.Object) (string, error)
SetSelfLink(obj runtime.Object, selfLink string) error
Labels(obj runtime.Object) (map[string]string, error)
SetLabels(obj runtime.Object, labels map[string]string) error
Annotations(obj runtime.Object) (map[string]string, error)
SetAnnotations(obj runtime.Object, annotations map[string]string) error
runtime.ResourceVersioner
}
type RESTScopeName string
const (
RESTScopeNameNamespace RESTScopeName = "namespace"
RESTScopeNameRoot RESTScopeName = "root"
)
// RESTScope contains the information needed to deal with REST resources that are in a resource hierarchy
type RESTScope interface {
// Name of the scope
Name() RESTScopeName
// ParamName is the optional name of the parameter that should be inserted in the resource url
// If empty, no param will be inserted
ParamName() string
// ArgumentName is the optional name that should be used for the variable holding the value.
ArgumentName() string
// ParamDescription is the optional description to use to document the parameter in api documentation
ParamDescription() string
}
// RESTMapping contains the information needed to deal with objects of a specific
// resource and kind in a RESTful manner.
type RESTMapping struct {
// Resource is a string representing the name of this resource as a REST client would see it
Resource string
GroupVersionKind unversioned.GroupVersionKind
// Scope contains the information needed to deal with REST Resources that are in a resource hierarchy
Scope RESTScope
runtime.ObjectConvertor
MetadataAccessor
}
// RESTMapper allows clients to map resources to kind, and map kind and version
// to interfaces for manipulating those objects. It is primarily intended for
// consumers of Kubernetes compatible REST APIs as defined in docs/devel/api-conventions.md.
//
// The Kubernetes API provides versioned resources and object kinds which are scoped
// to API groups. In other words, kinds and resources should not be assumed to be
// unique across groups.
//
// TODO: split into sub-interfaces
type RESTMapper interface {
// KindFor takes a partial resource and returns the single match. Returns an error if there are multiple matches
KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error)
// KindsFor takes a partial resource and returns the list of potential kinds in priority order
KindsFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionKind, error)
// ResourceFor takes a partial resource and returns the single match. Returns an error if there are multiple matches
ResourceFor(input unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error)
// ResourcesFor takes a partial resource and returns the list of potential resource in priority order
ResourcesFor(input unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error)
// RESTMapping identifies a preferred resource mapping for the provided group kind.
RESTMapping(gk unversioned.GroupKind, versions ...string) (*RESTMapping, error)
// RESTMappings returns all resource mappings for the provided group kind.
RESTMappings(gk unversioned.GroupKind) ([]*RESTMapping, error)
AliasesForResource(resource string) ([]string, bool)
ResourceSingularizer(resource string) (singular string, err error)
}

View file

@ -1,567 +0,0 @@
/*
Copyright 2014 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 meta
import (
"fmt"
"reflect"
"k8s.io/client-go/pkg/api/meta/metatypes"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/conversion"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/types"
"github.com/golang/glog"
)
// errNotList is returned when an object implements the Object style interfaces but not the List style
// interfaces.
var errNotList = fmt.Errorf("object does not implement the List interfaces")
// ListAccessor returns a List interface for the provided object or an error if the object does
// not provide List.
// IMPORTANT: Objects are a superset of lists, so all Objects return List metadata. Do not use this
// check to determine whether an object *is* a List.
// TODO: return bool instead of error
func ListAccessor(obj interface{}) (List, error) {
switch t := obj.(type) {
case List:
return t, nil
case unversioned.List:
return t, nil
case ListMetaAccessor:
if m := t.GetListMeta(); m != nil {
return m, nil
}
return nil, errNotList
case unversioned.ListMetaAccessor:
if m := t.GetListMeta(); m != nil {
return m, nil
}
return nil, errNotList
case Object:
return t, nil
case ObjectMetaAccessor:
if m := t.GetObjectMeta(); m != nil {
return m, nil
}
return nil, errNotList
default:
return nil, errNotList
}
}
// errNotObject is returned when an object implements the List style interfaces but not the Object style
// interfaces.
var errNotObject = fmt.Errorf("object does not implement the Object interfaces")
// Accessor takes an arbitrary object pointer and returns meta.Interface.
// obj must be a pointer to an API type. An error is returned if the minimum
// required fields are missing. Fields that are not required return the default
// value and are a no-op if set.
// TODO: return bool instead of error
func Accessor(obj interface{}) (Object, error) {
switch t := obj.(type) {
case Object:
return t, nil
case ObjectMetaAccessor:
if m := t.GetObjectMeta(); m != nil {
return m, nil
}
return nil, errNotObject
case List, unversioned.List, ListMetaAccessor, unversioned.ListMetaAccessor:
return nil, errNotObject
default:
return nil, errNotObject
}
}
// TypeAccessor returns an interface that allows retrieving and modifying the APIVersion
// and Kind of an in-memory internal object.
// TODO: this interface is used to test code that does not have ObjectMeta or ListMeta
// in round tripping (objects which can use apiVersion/kind, but do not fit the Kube
// api conventions).
func TypeAccessor(obj interface{}) (Type, error) {
if typed, ok := obj.(runtime.Object); ok {
return objectAccessor{typed}, nil
}
v, err := conversion.EnforcePtr(obj)
if err != nil {
return nil, err
}
t := v.Type()
if v.Kind() != reflect.Struct {
return nil, fmt.Errorf("expected struct, but got %v: %v (%#v)", v.Kind(), t, v.Interface())
}
typeMeta := v.FieldByName("TypeMeta")
if !typeMeta.IsValid() {
return nil, fmt.Errorf("struct %v lacks embedded TypeMeta type", t)
}
a := &genericAccessor{}
if err := extractFromTypeMeta(typeMeta, a); err != nil {
return nil, fmt.Errorf("unable to find type fields on %#v: %v", typeMeta, err)
}
return a, nil
}
type objectAccessor struct {
runtime.Object
}
func (obj objectAccessor) GetKind() string {
return obj.GetObjectKind().GroupVersionKind().Kind
}
func (obj objectAccessor) SetKind(kind string) {
gvk := obj.GetObjectKind().GroupVersionKind()
gvk.Kind = kind
obj.GetObjectKind().SetGroupVersionKind(gvk)
}
func (obj objectAccessor) GetAPIVersion() string {
return obj.GetObjectKind().GroupVersionKind().GroupVersion().String()
}
func (obj objectAccessor) SetAPIVersion(version string) {
gvk := obj.GetObjectKind().GroupVersionKind()
gv, err := unversioned.ParseGroupVersion(version)
if err != nil {
gv = unversioned.GroupVersion{Version: version}
}
gvk.Group, gvk.Version = gv.Group, gv.Version
obj.GetObjectKind().SetGroupVersionKind(gvk)
}
// NewAccessor returns a MetadataAccessor that can retrieve
// or manipulate resource version on objects derived from core API
// metadata concepts.
func NewAccessor() MetadataAccessor {
return resourceAccessor{}
}
// resourceAccessor implements ResourceVersioner and SelfLinker.
type resourceAccessor struct{}
func (resourceAccessor) Kind(obj runtime.Object) (string, error) {
return objectAccessor{obj}.GetKind(), nil
}
func (resourceAccessor) SetKind(obj runtime.Object, kind string) error {
objectAccessor{obj}.SetKind(kind)
return nil
}
func (resourceAccessor) APIVersion(obj runtime.Object) (string, error) {
return objectAccessor{obj}.GetAPIVersion(), nil
}
func (resourceAccessor) SetAPIVersion(obj runtime.Object, version string) error {
objectAccessor{obj}.SetAPIVersion(version)
return nil
}
func (resourceAccessor) Namespace(obj runtime.Object) (string, error) {
accessor, err := Accessor(obj)
if err != nil {
return "", err
}
return accessor.GetNamespace(), nil
}
func (resourceAccessor) SetNamespace(obj runtime.Object, namespace string) error {
accessor, err := Accessor(obj)
if err != nil {
return err
}
accessor.SetNamespace(namespace)
return nil
}
func (resourceAccessor) Name(obj runtime.Object) (string, error) {
accessor, err := Accessor(obj)
if err != nil {
return "", err
}
return accessor.GetName(), nil
}
func (resourceAccessor) SetName(obj runtime.Object, name string) error {
accessor, err := Accessor(obj)
if err != nil {
return err
}
accessor.SetName(name)
return nil
}
func (resourceAccessor) GenerateName(obj runtime.Object) (string, error) {
accessor, err := Accessor(obj)
if err != nil {
return "", err
}
return accessor.GetGenerateName(), nil
}
func (resourceAccessor) SetGenerateName(obj runtime.Object, name string) error {
accessor, err := Accessor(obj)
if err != nil {
return err
}
accessor.SetGenerateName(name)
return nil
}
func (resourceAccessor) UID(obj runtime.Object) (types.UID, error) {
accessor, err := Accessor(obj)
if err != nil {
return "", err
}
return accessor.GetUID(), nil
}
func (resourceAccessor) SetUID(obj runtime.Object, uid types.UID) error {
accessor, err := Accessor(obj)
if err != nil {
return err
}
accessor.SetUID(uid)
return nil
}
func (resourceAccessor) SelfLink(obj runtime.Object) (string, error) {
accessor, err := ListAccessor(obj)
if err != nil {
return "", err
}
return accessor.GetSelfLink(), nil
}
func (resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error {
accessor, err := ListAccessor(obj)
if err != nil {
return err
}
accessor.SetSelfLink(selfLink)
return nil
}
func (resourceAccessor) Labels(obj runtime.Object) (map[string]string, error) {
accessor, err := Accessor(obj)
if err != nil {
return nil, err
}
return accessor.GetLabels(), nil
}
func (resourceAccessor) SetLabels(obj runtime.Object, labels map[string]string) error {
accessor, err := Accessor(obj)
if err != nil {
return err
}
accessor.SetLabels(labels)
return nil
}
func (resourceAccessor) Annotations(obj runtime.Object) (map[string]string, error) {
accessor, err := Accessor(obj)
if err != nil {
return nil, err
}
return accessor.GetAnnotations(), nil
}
func (resourceAccessor) SetAnnotations(obj runtime.Object, annotations map[string]string) error {
accessor, err := Accessor(obj)
if err != nil {
return err
}
accessor.SetAnnotations(annotations)
return nil
}
func (resourceAccessor) ResourceVersion(obj runtime.Object) (string, error) {
accessor, err := ListAccessor(obj)
if err != nil {
return "", err
}
return accessor.GetResourceVersion(), nil
}
func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error {
accessor, err := ListAccessor(obj)
if err != nil {
return err
}
accessor.SetResourceVersion(version)
return nil
}
// extractFromOwnerReference extracts v to o. v is the OwnerReferences field of an object.
func extractFromOwnerReference(v reflect.Value, o *metatypes.OwnerReference) error {
if err := runtime.Field(v, "APIVersion", &o.APIVersion); err != nil {
return err
}
if err := runtime.Field(v, "Kind", &o.Kind); err != nil {
return err
}
if err := runtime.Field(v, "Name", &o.Name); err != nil {
return err
}
if err := runtime.Field(v, "UID", &o.UID); err != nil {
return err
}
var controllerPtr *bool
if err := runtime.Field(v, "Controller", &controllerPtr); err != nil {
return err
}
if controllerPtr != nil {
controller := *controllerPtr
o.Controller = &controller
}
return nil
}
// setOwnerReference sets v to o. v is the OwnerReferences field of an object.
func setOwnerReference(v reflect.Value, o *metatypes.OwnerReference) error {
if err := runtime.SetField(o.APIVersion, v, "APIVersion"); err != nil {
return err
}
if err := runtime.SetField(o.Kind, v, "Kind"); err != nil {
return err
}
if err := runtime.SetField(o.Name, v, "Name"); err != nil {
return err
}
if err := runtime.SetField(o.UID, v, "UID"); err != nil {
return err
}
if o.Controller != nil {
controller := *(o.Controller)
if err := runtime.SetField(&controller, v, "Controller"); err != nil {
return err
}
}
return nil
}
// genericAccessor contains pointers to strings that can modify an arbitrary
// struct and implements the Accessor interface.
type genericAccessor struct {
namespace *string
name *string
generateName *string
uid *types.UID
apiVersion *string
kind *string
resourceVersion *string
selfLink *string
creationTimestamp *unversioned.Time
deletionTimestamp **unversioned.Time
labels *map[string]string
annotations *map[string]string
ownerReferences reflect.Value
finalizers *[]string
}
func (a genericAccessor) GetNamespace() string {
if a.namespace == nil {
return ""
}
return *a.namespace
}
func (a genericAccessor) SetNamespace(namespace string) {
if a.namespace == nil {
return
}
*a.namespace = namespace
}
func (a genericAccessor) GetName() string {
if a.name == nil {
return ""
}
return *a.name
}
func (a genericAccessor) SetName(name string) {
if a.name == nil {
return
}
*a.name = name
}
func (a genericAccessor) GetGenerateName() string {
if a.generateName == nil {
return ""
}
return *a.generateName
}
func (a genericAccessor) SetGenerateName(generateName string) {
if a.generateName == nil {
return
}
*a.generateName = generateName
}
func (a genericAccessor) GetUID() types.UID {
if a.uid == nil {
return ""
}
return *a.uid
}
func (a genericAccessor) SetUID(uid types.UID) {
if a.uid == nil {
return
}
*a.uid = uid
}
func (a genericAccessor) GetAPIVersion() string {
return *a.apiVersion
}
func (a genericAccessor) SetAPIVersion(version string) {
*a.apiVersion = version
}
func (a genericAccessor) GetKind() string {
return *a.kind
}
func (a genericAccessor) SetKind(kind string) {
*a.kind = kind
}
func (a genericAccessor) GetResourceVersion() string {
return *a.resourceVersion
}
func (a genericAccessor) SetResourceVersion(version string) {
*a.resourceVersion = version
}
func (a genericAccessor) GetSelfLink() string {
return *a.selfLink
}
func (a genericAccessor) SetSelfLink(selfLink string) {
*a.selfLink = selfLink
}
func (a genericAccessor) GetCreationTimestamp() unversioned.Time {
return *a.creationTimestamp
}
func (a genericAccessor) SetCreationTimestamp(timestamp unversioned.Time) {
*a.creationTimestamp = timestamp
}
func (a genericAccessor) GetDeletionTimestamp() *unversioned.Time {
return *a.deletionTimestamp
}
func (a genericAccessor) SetDeletionTimestamp(timestamp *unversioned.Time) {
*a.deletionTimestamp = timestamp
}
func (a genericAccessor) GetLabels() map[string]string {
if a.labels == nil {
return nil
}
return *a.labels
}
func (a genericAccessor) SetLabels(labels map[string]string) {
*a.labels = labels
}
func (a genericAccessor) GetAnnotations() map[string]string {
if a.annotations == nil {
return nil
}
return *a.annotations
}
func (a genericAccessor) SetAnnotations(annotations map[string]string) {
if a.annotations == nil {
emptyAnnotations := make(map[string]string)
a.annotations = &emptyAnnotations
}
*a.annotations = annotations
}
func (a genericAccessor) GetFinalizers() []string {
if a.finalizers == nil {
return nil
}
return *a.finalizers
}
func (a genericAccessor) SetFinalizers(finalizers []string) {
*a.finalizers = finalizers
}
func (a genericAccessor) GetOwnerReferences() []metatypes.OwnerReference {
var ret []metatypes.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)
return ret
}
s = s.Elem()
// Set the capacity to one element greater to avoid copy if the caller later append an element.
ret = make([]metatypes.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)
return ret
}
}
return ret
}
func (a genericAccessor) SetOwnerReferences(references []metatypes.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)
}
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)
return
}
}
s.Set(newReferences)
}
// extractFromTypeMeta extracts pointers to version and kind fields from an object
func extractFromTypeMeta(v reflect.Value, a *genericAccessor) error {
if err := runtime.FieldPtr(v, "APIVersion", &a.apiVersion); err != nil {
return err
}
if err := runtime.FieldPtr(v, "Kind", &a.kind); err != nil {
return err
}
return nil
}

View file

@ -1,30 +0,0 @@
/*
Copyright 2014 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.
*/
// The types defined in this package are used by the meta package to represent
// the in-memory version of objects. We cannot reuse the __internal version of
// API objects because it causes import cycle.
package metatypes
import "k8s.io/client-go/pkg/types"
type OwnerReference struct {
APIVersion string
Kind string
UID types.UID
Name string
Controller *bool
}

View file

@ -1,231 +0,0 @@
/*
Copyright 2014 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 meta
import (
"fmt"
"strings"
"k8s.io/client-go/pkg/api/unversioned"
utilerrors "k8s.io/client-go/pkg/util/errors"
"k8s.io/client-go/pkg/util/sets"
)
// MultiRESTMapper is a wrapper for multiple RESTMappers.
type MultiRESTMapper []RESTMapper
func (m MultiRESTMapper) String() string {
nested := []string{}
for _, t := range m {
currString := fmt.Sprintf("%v", t)
splitStrings := strings.Split(currString, "\n")
nested = append(nested, strings.Join(splitStrings, "\n\t"))
}
return fmt.Sprintf("MultiRESTMapper{\n\t%s\n}", strings.Join(nested, "\n\t"))
}
// ResourceSingularizer converts a REST resource name from plural to singular (e.g., from pods to pod)
// This implementation supports multiple REST schemas and return the first match.
func (m MultiRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
for _, t := range m {
singular, err = t.ResourceSingularizer(resource)
if err == nil {
return
}
}
return
}
func (m MultiRESTMapper) ResourcesFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) {
allGVRs := []unversioned.GroupVersionResource{}
for _, t := range m {
gvrs, err := t.ResourcesFor(resource)
// ignore "no match" errors, but any other error percolates back up
if IsNoMatchError(err) {
continue
}
if err != nil {
return nil, err
}
// walk the existing values to de-dup
for _, curr := range gvrs {
found := false
for _, existing := range allGVRs {
if curr == existing {
found = true
break
}
}
if !found {
allGVRs = append(allGVRs, curr)
}
}
}
if len(allGVRs) == 0 {
return nil, &NoResourceMatchError{PartialResource: resource}
}
return allGVRs, nil
}
func (m MultiRESTMapper) KindsFor(resource unversioned.GroupVersionResource) (gvk []unversioned.GroupVersionKind, err error) {
allGVKs := []unversioned.GroupVersionKind{}
for _, t := range m {
gvks, err := t.KindsFor(resource)
// ignore "no match" errors, but any other error percolates back up
if IsNoMatchError(err) {
continue
}
if err != nil {
return nil, err
}
// walk the existing values to de-dup
for _, curr := range gvks {
found := false
for _, existing := range allGVKs {
if curr == existing {
found = true
break
}
}
if !found {
allGVKs = append(allGVKs, curr)
}
}
}
if len(allGVKs) == 0 {
return nil, &NoResourceMatchError{PartialResource: resource}
}
return allGVKs, nil
}
func (m MultiRESTMapper) ResourceFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
resources, err := m.ResourcesFor(resource)
if err != nil {
return unversioned.GroupVersionResource{}, err
}
if len(resources) == 1 {
return resources[0], nil
}
return unversioned.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: resource, MatchingResources: resources}
}
func (m MultiRESTMapper) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
kinds, err := m.KindsFor(resource)
if err != nil {
return unversioned.GroupVersionKind{}, err
}
if len(kinds) == 1 {
return kinds[0], nil
}
return unversioned.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: resource, MatchingKinds: kinds}
}
// RESTMapping provides the REST mapping for the resource based on the
// kind and version. This implementation supports multiple REST schemas and
// return the first match.
func (m MultiRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (*RESTMapping, error) {
allMappings := []*RESTMapping{}
errors := []error{}
for _, t := range m {
currMapping, err := t.RESTMapping(gk, versions...)
// ignore "no match" errors, but any other error percolates back up
if IsNoMatchError(err) {
continue
}
if err != nil {
errors = append(errors, err)
continue
}
allMappings = append(allMappings, currMapping)
}
// if we got exactly one mapping, then use it even if other requested failed
if len(allMappings) == 1 {
return allMappings[0], nil
}
if len(allMappings) > 1 {
var kinds []unversioned.GroupVersionKind
for _, m := range allMappings {
kinds = append(kinds, m.GroupVersionKind)
}
return nil, &AmbiguousKindError{PartialKind: gk.WithVersion(""), MatchingKinds: kinds}
}
if len(errors) > 0 {
return nil, utilerrors.NewAggregate(errors)
}
return nil, &NoKindMatchError{PartialKind: gk.WithVersion("")}
}
// RESTMappings returns all possible RESTMappings for the provided group kind, or an error
// if the type is not recognized.
func (m MultiRESTMapper) RESTMappings(gk unversioned.GroupKind) ([]*RESTMapping, error) {
var allMappings []*RESTMapping
var errors []error
for _, t := range m {
currMappings, err := t.RESTMappings(gk)
// ignore "no match" errors, but any other error percolates back up
if IsNoMatchError(err) {
continue
}
if err != nil {
errors = append(errors, err)
continue
}
allMappings = append(allMappings, currMappings...)
}
if len(errors) > 0 {
return nil, utilerrors.NewAggregate(errors)
}
if len(allMappings) == 0 {
return nil, &NoKindMatchError{PartialKind: gk.WithVersion("")}
}
return allMappings, nil
}
// AliasesForResource finds the first alias response for the provided mappers.
func (m MultiRESTMapper) AliasesForResource(alias string) ([]string, bool) {
seenAliases := sets.NewString()
allAliases := []string{}
handled := false
for _, t := range m {
if currAliases, currOk := t.AliasesForResource(alias); currOk {
for _, currAlias := range currAliases {
if !seenAliases.Has(currAlias) {
allAliases = append(allAliases, currAlias)
seenAliases.Insert(currAlias)
}
}
handled = true
}
}
return allAliases, handled
}

View file

@ -1,226 +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 meta
import (
"fmt"
"k8s.io/client-go/pkg/api/unversioned"
)
const (
AnyGroup = "*"
AnyVersion = "*"
AnyResource = "*"
AnyKind = "*"
)
// PriorityRESTMapper is a wrapper for automatically choosing a particular Resource or Kind
// when multiple matches are possible
type PriorityRESTMapper struct {
// Delegate is the RESTMapper to use to locate all the Kind and Resource matches
Delegate RESTMapper
// ResourcePriority is a list of priority patterns to apply to matching resources.
// The list of all matching resources is narrowed based on the patterns until only one remains.
// A pattern with no matches is skipped. A pattern with more than one match uses its
// matches as the list to continue matching against.
ResourcePriority []unversioned.GroupVersionResource
// KindPriority is a list of priority patterns to apply to matching kinds.
// The list of all matching kinds is narrowed based on the patterns until only one remains.
// A pattern with no matches is skipped. A pattern with more than one match uses its
// matches as the list to continue matching against.
KindPriority []unversioned.GroupVersionKind
}
func (m PriorityRESTMapper) String() string {
return fmt.Sprintf("PriorityRESTMapper{\n\t%v\n\t%v\n\t%v\n}", m.ResourcePriority, m.KindPriority, m.Delegate)
}
// ResourceFor finds all resources, then passes them through the ResourcePriority patterns to find a single matching hit.
func (m PriorityRESTMapper) ResourceFor(partiallySpecifiedResource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
originalGVRs, err := m.Delegate.ResourcesFor(partiallySpecifiedResource)
if err != nil {
return unversioned.GroupVersionResource{}, err
}
if len(originalGVRs) == 1 {
return originalGVRs[0], nil
}
remainingGVRs := append([]unversioned.GroupVersionResource{}, originalGVRs...)
for _, pattern := range m.ResourcePriority {
matchedGVRs := []unversioned.GroupVersionResource{}
for _, gvr := range remainingGVRs {
if resourceMatches(pattern, gvr) {
matchedGVRs = append(matchedGVRs, gvr)
}
}
switch len(matchedGVRs) {
case 0:
// if you have no matches, then nothing matched this pattern just move to the next
continue
case 1:
// one match, return
return matchedGVRs[0], nil
default:
// more than one match, use the matched hits as the list moving to the next pattern.
// this way you can have a series of selection criteria
remainingGVRs = matchedGVRs
}
}
return unversioned.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: partiallySpecifiedResource, MatchingResources: originalGVRs}
}
// KindFor finds all kinds, then passes them through the KindPriority patterns to find a single matching hit.
func (m PriorityRESTMapper) KindFor(partiallySpecifiedResource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
originalGVKs, err := m.Delegate.KindsFor(partiallySpecifiedResource)
if err != nil {
return unversioned.GroupVersionKind{}, err
}
if len(originalGVKs) == 1 {
return originalGVKs[0], nil
}
remainingGVKs := append([]unversioned.GroupVersionKind{}, originalGVKs...)
for _, pattern := range m.KindPriority {
matchedGVKs := []unversioned.GroupVersionKind{}
for _, gvr := range remainingGVKs {
if kindMatches(pattern, gvr) {
matchedGVKs = append(matchedGVKs, gvr)
}
}
switch len(matchedGVKs) {
case 0:
// if you have no matches, then nothing matched this pattern just move to the next
continue
case 1:
// one match, return
return matchedGVKs[0], nil
default:
// more than one match, use the matched hits as the list moving to the next pattern.
// this way you can have a series of selection criteria
remainingGVKs = matchedGVKs
}
}
return unversioned.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: partiallySpecifiedResource, MatchingKinds: originalGVKs}
}
func resourceMatches(pattern unversioned.GroupVersionResource, resource unversioned.GroupVersionResource) bool {
if pattern.Group != AnyGroup && pattern.Group != resource.Group {
return false
}
if pattern.Version != AnyVersion && pattern.Version != resource.Version {
return false
}
if pattern.Resource != AnyResource && pattern.Resource != resource.Resource {
return false
}
return true
}
func kindMatches(pattern unversioned.GroupVersionKind, kind unversioned.GroupVersionKind) bool {
if pattern.Group != AnyGroup && pattern.Group != kind.Group {
return false
}
if pattern.Version != AnyVersion && pattern.Version != kind.Version {
return false
}
if pattern.Kind != AnyKind && pattern.Kind != kind.Kind {
return false
}
return true
}
func (m PriorityRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (mapping *RESTMapping, err error) {
mappings, err := m.Delegate.RESTMappings(gk)
if err != nil {
return nil, err
}
// any versions the user provides take priority
priorities := m.KindPriority
if len(versions) > 0 {
priorities = make([]unversioned.GroupVersionKind, 0, len(m.KindPriority)+len(versions))
for _, version := range versions {
gv, err := unversioned.ParseGroupVersion(version)
if err != nil {
return nil, err
}
priorities = append(priorities, gv.WithKind(AnyKind))
}
priorities = append(priorities, m.KindPriority...)
}
remaining := append([]*RESTMapping{}, mappings...)
for _, pattern := range priorities {
var matching []*RESTMapping
for _, m := range remaining {
if kindMatches(pattern, m.GroupVersionKind) {
matching = append(matching, m)
}
}
switch len(matching) {
case 0:
// if you have no matches, then nothing matched this pattern just move to the next
continue
case 1:
// one match, return
return matching[0], nil
default:
// more than one match, use the matched hits as the list moving to the next pattern.
// this way you can have a series of selection criteria
remaining = matching
}
}
if len(remaining) == 1 {
return remaining[0], nil
}
var kinds []unversioned.GroupVersionKind
for _, m := range mappings {
kinds = append(kinds, m.GroupVersionKind)
}
return nil, &AmbiguousKindError{PartialKind: gk.WithVersion(""), MatchingKinds: kinds}
}
func (m PriorityRESTMapper) RESTMappings(gk unversioned.GroupKind) ([]*RESTMapping, error) {
return m.Delegate.RESTMappings(gk)
}
func (m PriorityRESTMapper) AliasesForResource(alias string) (aliases []string, ok bool) {
return m.Delegate.AliasesForResource(alias)
}
func (m PriorityRESTMapper) ResourceSingularizer(resource string) (singular string, err error) {
return m.Delegate.ResourceSingularizer(resource)
}
func (m PriorityRESTMapper) ResourcesFor(partiallySpecifiedResource unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) {
return m.Delegate.ResourcesFor(partiallySpecifiedResource)
}
func (m PriorityRESTMapper) KindsFor(partiallySpecifiedResource unversioned.GroupVersionResource) (gvk []unversioned.GroupVersionKind, err error) {
return m.Delegate.KindsFor(partiallySpecifiedResource)
}

View file

@ -1,601 +0,0 @@
/*
Copyright 2014 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.
*/
// TODO: move everything in this file to pkg/api/rest
package meta
import (
"fmt"
"sort"
"strings"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
)
// Implements RESTScope interface
type restScope struct {
name RESTScopeName
paramName string
argumentName string
paramDescription string
}
func (r *restScope) Name() RESTScopeName {
return r.name
}
func (r *restScope) ParamName() string {
return r.paramName
}
func (r *restScope) ArgumentName() string {
return r.argumentName
}
func (r *restScope) ParamDescription() string {
return r.paramDescription
}
var RESTScopeNamespace = &restScope{
name: RESTScopeNameNamespace,
paramName: "namespaces",
argumentName: "namespace",
paramDescription: "object name and auth scope, such as for teams and projects",
}
var RESTScopeRoot = &restScope{
name: RESTScopeNameRoot,
}
// DefaultRESTMapper exposes mappings between the types defined in a
// runtime.Scheme. It assumes that all types defined the provided scheme
// can be mapped with the provided MetadataAccessor and Codec interfaces.
//
// The resource name of a Kind is defined as the lowercase,
// English-plural version of the Kind string.
// When converting from resource to Kind, the singular version of the
// resource name is also accepted for convenience.
//
// TODO: Only accept plural for some operations for increased control?
// (`get pod bar` vs `get pods bar`)
type DefaultRESTMapper struct {
defaultGroupVersions []unversioned.GroupVersion
resourceToKind map[unversioned.GroupVersionResource]unversioned.GroupVersionKind
kindToPluralResource map[unversioned.GroupVersionKind]unversioned.GroupVersionResource
kindToScope map[unversioned.GroupVersionKind]RESTScope
singularToPlural map[unversioned.GroupVersionResource]unversioned.GroupVersionResource
pluralToSingular map[unversioned.GroupVersionResource]unversioned.GroupVersionResource
interfacesFunc VersionInterfacesFunc
// aliasToResource is used for mapping aliases to resources
aliasToResource map[string][]string
}
func (m *DefaultRESTMapper) String() string {
return fmt.Sprintf("DefaultRESTMapper{kindToPluralResource=%v}", m.kindToPluralResource)
}
var _ RESTMapper = &DefaultRESTMapper{}
// VersionInterfacesFunc returns the appropriate typer, and metadata accessor for a
// given api version, or an error if no such api version exists.
type VersionInterfacesFunc func(version unversioned.GroupVersion) (*VersionInterfaces, error)
// NewDefaultRESTMapper initializes a mapping between Kind and APIVersion
// to a resource name and back based on the objects in a runtime.Scheme
// and the Kubernetes API conventions. Takes a group name, a priority list of the versions
// to search when an object has no default version (set empty to return an error),
// and a function that retrieves the correct metadata for a given version.
func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, f VersionInterfacesFunc) *DefaultRESTMapper {
resourceToKind := make(map[unversioned.GroupVersionResource]unversioned.GroupVersionKind)
kindToPluralResource := make(map[unversioned.GroupVersionKind]unversioned.GroupVersionResource)
kindToScope := make(map[unversioned.GroupVersionKind]RESTScope)
singularToPlural := make(map[unversioned.GroupVersionResource]unversioned.GroupVersionResource)
pluralToSingular := make(map[unversioned.GroupVersionResource]unversioned.GroupVersionResource)
aliasToResource := make(map[string][]string)
// TODO: verify name mappings work correctly when versions differ
return &DefaultRESTMapper{
resourceToKind: resourceToKind,
kindToPluralResource: kindToPluralResource,
kindToScope: kindToScope,
defaultGroupVersions: defaultGroupVersions,
singularToPlural: singularToPlural,
pluralToSingular: pluralToSingular,
aliasToResource: aliasToResource,
interfacesFunc: f,
}
}
func (m *DefaultRESTMapper) Add(kind unversioned.GroupVersionKind, scope RESTScope) {
plural, singular := KindToResource(kind)
m.singularToPlural[singular] = plural
m.pluralToSingular[plural] = singular
m.resourceToKind[singular] = kind
m.resourceToKind[plural] = kind
m.kindToPluralResource[kind] = plural
m.kindToScope[kind] = scope
}
// unpluralizedSuffixes is a list of resource suffixes that are the same plural and singular
// This is only is only necessary because some bits of code are lazy and don't actually use the RESTMapper like they should.
// TODO eliminate this so that different callers can correctly map to resources. This probably means updating all
// callers to use the RESTMapper they mean.
var unpluralizedSuffixes = []string{
"endpoints",
}
// KindToResource converts Kind to a resource name.
// Broken. This method only "sort of" works when used outside of this package. It assumes that Kinds and Resources match
// and they aren't guaranteed to do so.
func KindToResource(kind unversioned.GroupVersionKind) ( /*plural*/ unversioned.GroupVersionResource /*singular*/, unversioned.GroupVersionResource) {
kindName := kind.Kind
if len(kindName) == 0 {
return unversioned.GroupVersionResource{}, unversioned.GroupVersionResource{}
}
singularName := strings.ToLower(kindName)
singular := kind.GroupVersion().WithResource(singularName)
for _, skip := range unpluralizedSuffixes {
if strings.HasSuffix(singularName, skip) {
return singular, singular
}
}
switch string(singularName[len(singularName)-1]) {
case "s":
return kind.GroupVersion().WithResource(singularName + "es"), singular
case "y":
return kind.GroupVersion().WithResource(strings.TrimSuffix(singularName, "y") + "ies"), singular
}
return kind.GroupVersion().WithResource(singularName + "s"), singular
}
// ResourceSingularizer implements RESTMapper
// It converts a resource name from plural to singular (e.g., from pods to pod)
func (m *DefaultRESTMapper) ResourceSingularizer(resourceType string) (string, error) {
partialResource := unversioned.GroupVersionResource{Resource: resourceType}
resources, err := m.ResourcesFor(partialResource)
if err != nil {
return resourceType, err
}
singular := unversioned.GroupVersionResource{}
for _, curr := range resources {
currSingular, ok := m.pluralToSingular[curr]
if !ok {
continue
}
if singular.Empty() {
singular = currSingular
continue
}
if currSingular.Resource != singular.Resource {
return resourceType, fmt.Errorf("multiple possible singular resources (%v) found for %v", resources, resourceType)
}
}
if singular.Empty() {
return resourceType, fmt.Errorf("no singular of resource %v has been defined", resourceType)
}
return singular.Resource, nil
}
// coerceResourceForMatching makes the resource lower case and converts internal versions to unspecified (legacy behavior)
func coerceResourceForMatching(resource unversioned.GroupVersionResource) unversioned.GroupVersionResource {
resource.Resource = strings.ToLower(resource.Resource)
if resource.Version == runtime.APIVersionInternal {
resource.Version = ""
}
return resource
}
func (m *DefaultRESTMapper) ResourcesFor(input unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error) {
resource := coerceResourceForMatching(input)
hasResource := len(resource.Resource) > 0
hasGroup := len(resource.Group) > 0
hasVersion := len(resource.Version) > 0
if !hasResource {
return nil, fmt.Errorf("a resource must be present, got: %v", resource)
}
ret := []unversioned.GroupVersionResource{}
switch {
case hasGroup && hasVersion:
// fully qualified. Find the exact match
for plural, singular := range m.pluralToSingular {
if singular == resource {
ret = append(ret, plural)
break
}
if plural == resource {
ret = append(ret, plural)
break
}
}
case hasGroup:
// given a group, prefer an exact match. If you don't find one, resort to a prefix match on group
foundExactMatch := false
requestedGroupResource := resource.GroupResource()
for plural, singular := range m.pluralToSingular {
if singular.GroupResource() == requestedGroupResource {
foundExactMatch = true
ret = append(ret, plural)
}
if plural.GroupResource() == requestedGroupResource {
foundExactMatch = true
ret = append(ret, plural)
}
}
// if you didn't find an exact match, match on group prefixing. This allows storageclass.storage to match
// storageclass.storage.k8s.io
if !foundExactMatch {
for plural, singular := range m.pluralToSingular {
if !strings.HasPrefix(plural.Group, requestedGroupResource.Group) {
continue
}
if singular.Resource == requestedGroupResource.Resource {
ret = append(ret, plural)
}
if plural.Resource == requestedGroupResource.Resource {
ret = append(ret, plural)
}
}
}
case hasVersion:
for plural, singular := range m.pluralToSingular {
if singular.Version == resource.Version && singular.Resource == resource.Resource {
ret = append(ret, plural)
}
if plural.Version == resource.Version && plural.Resource == resource.Resource {
ret = append(ret, plural)
}
}
default:
for plural, singular := range m.pluralToSingular {
if singular.Resource == resource.Resource {
ret = append(ret, plural)
}
if plural.Resource == resource.Resource {
ret = append(ret, plural)
}
}
}
if len(ret) == 0 {
return nil, &NoResourceMatchError{PartialResource: resource}
}
sort.Sort(resourceByPreferredGroupVersion{ret, m.defaultGroupVersions})
return ret, nil
}
func (m *DefaultRESTMapper) ResourceFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionResource, error) {
resources, err := m.ResourcesFor(resource)
if err != nil {
return unversioned.GroupVersionResource{}, err
}
if len(resources) == 1 {
return resources[0], nil
}
return unversioned.GroupVersionResource{}, &AmbiguousResourceError{PartialResource: resource, MatchingResources: resources}
}
func (m *DefaultRESTMapper) KindsFor(input unversioned.GroupVersionResource) ([]unversioned.GroupVersionKind, error) {
resource := coerceResourceForMatching(input)
hasResource := len(resource.Resource) > 0
hasGroup := len(resource.Group) > 0
hasVersion := len(resource.Version) > 0
if !hasResource {
return nil, fmt.Errorf("a resource must be present, got: %v", resource)
}
ret := []unversioned.GroupVersionKind{}
switch {
// fully qualified. Find the exact match
case hasGroup && hasVersion:
kind, exists := m.resourceToKind[resource]
if exists {
ret = append(ret, kind)
}
case hasGroup:
foundExactMatch := false
requestedGroupResource := resource.GroupResource()
for currResource, currKind := range m.resourceToKind {
if currResource.GroupResource() == requestedGroupResource {
foundExactMatch = true
ret = append(ret, currKind)
}
}
// if you didn't find an exact match, match on group prefixing. This allows storageclass.storage to match
// storageclass.storage.k8s.io
if !foundExactMatch {
for currResource, currKind := range m.resourceToKind {
if !strings.HasPrefix(currResource.Group, requestedGroupResource.Group) {
continue
}
if currResource.Resource == requestedGroupResource.Resource {
ret = append(ret, currKind)
}
}
}
case hasVersion:
for currResource, currKind := range m.resourceToKind {
if currResource.Version == resource.Version && currResource.Resource == resource.Resource {
ret = append(ret, currKind)
}
}
default:
for currResource, currKind := range m.resourceToKind {
if currResource.Resource == resource.Resource {
ret = append(ret, currKind)
}
}
}
if len(ret) == 0 {
return nil, &NoResourceMatchError{PartialResource: input}
}
sort.Sort(kindByPreferredGroupVersion{ret, m.defaultGroupVersions})
return ret, nil
}
func (m *DefaultRESTMapper) KindFor(resource unversioned.GroupVersionResource) (unversioned.GroupVersionKind, error) {
kinds, err := m.KindsFor(resource)
if err != nil {
return unversioned.GroupVersionKind{}, err
}
if len(kinds) == 1 {
return kinds[0], nil
}
return unversioned.GroupVersionKind{}, &AmbiguousResourceError{PartialResource: resource, MatchingKinds: kinds}
}
type kindByPreferredGroupVersion struct {
list []unversioned.GroupVersionKind
sortOrder []unversioned.GroupVersion
}
func (o kindByPreferredGroupVersion) Len() int { return len(o.list) }
func (o kindByPreferredGroupVersion) Swap(i, j int) { o.list[i], o.list[j] = o.list[j], o.list[i] }
func (o kindByPreferredGroupVersion) Less(i, j int) bool {
lhs := o.list[i]
rhs := o.list[j]
if lhs == rhs {
return false
}
if lhs.GroupVersion() == rhs.GroupVersion() {
return lhs.Kind < rhs.Kind
}
// otherwise, the difference is in the GroupVersion, so we need to sort with respect to the preferred order
lhsIndex := -1
rhsIndex := -1
for i := range o.sortOrder {
if o.sortOrder[i] == lhs.GroupVersion() {
lhsIndex = i
}
if o.sortOrder[i] == rhs.GroupVersion() {
rhsIndex = i
}
}
if rhsIndex == -1 {
return true
}
return lhsIndex < rhsIndex
}
type resourceByPreferredGroupVersion struct {
list []unversioned.GroupVersionResource
sortOrder []unversioned.GroupVersion
}
func (o resourceByPreferredGroupVersion) Len() int { return len(o.list) }
func (o resourceByPreferredGroupVersion) Swap(i, j int) { o.list[i], o.list[j] = o.list[j], o.list[i] }
func (o resourceByPreferredGroupVersion) Less(i, j int) bool {
lhs := o.list[i]
rhs := o.list[j]
if lhs == rhs {
return false
}
if lhs.GroupVersion() == rhs.GroupVersion() {
return lhs.Resource < rhs.Resource
}
// otherwise, the difference is in the GroupVersion, so we need to sort with respect to the preferred order
lhsIndex := -1
rhsIndex := -1
for i := range o.sortOrder {
if o.sortOrder[i] == lhs.GroupVersion() {
lhsIndex = i
}
if o.sortOrder[i] == rhs.GroupVersion() {
rhsIndex = i
}
}
if rhsIndex == -1 {
return true
}
return lhsIndex < rhsIndex
}
// RESTMapping returns a struct representing the resource path and conversion interfaces a
// RESTClient should use to operate on the provided group/kind in order of versions. If a version search
// order is not provided, the search order provided to DefaultRESTMapper will be used to resolve which
// version should be used to access the named group/kind.
// TODO: consider refactoring to use RESTMappings in a way that preserves version ordering and preference
func (m *DefaultRESTMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (*RESTMapping, error) {
// Pick an appropriate version
var gvk *unversioned.GroupVersionKind
hadVersion := false
for _, version := range versions {
if len(version) == 0 || version == runtime.APIVersionInternal {
continue
}
currGVK := gk.WithVersion(version)
hadVersion = true
if _, ok := m.kindToPluralResource[currGVK]; ok {
gvk = &currGVK
break
}
}
// Use the default preferred versions
if !hadVersion && (gvk == nil) {
for _, gv := range m.defaultGroupVersions {
if gv.Group != gk.Group {
continue
}
currGVK := gk.WithVersion(gv.Version)
if _, ok := m.kindToPluralResource[currGVK]; ok {
gvk = &currGVK
break
}
}
}
if gvk == nil {
return nil, &NoKindMatchError{PartialKind: gk.WithVersion("")}
}
// Ensure we have a REST mapping
resource, ok := m.kindToPluralResource[*gvk]
if !ok {
found := []unversioned.GroupVersion{}
for _, gv := range m.defaultGroupVersions {
if _, ok := m.kindToPluralResource[*gvk]; ok {
found = append(found, gv)
}
}
if len(found) > 0 {
return nil, fmt.Errorf("object with kind %q exists in versions %v, not %v", gvk.Kind, found, gvk.GroupVersion().String())
}
return nil, fmt.Errorf("the provided version %q and kind %q cannot be mapped to a supported object", gvk.GroupVersion().String(), gvk.Kind)
}
// Ensure we have a REST scope
scope, ok := m.kindToScope[*gvk]
if !ok {
return nil, fmt.Errorf("the provided version %q and kind %q cannot be mapped to a supported scope", gvk.GroupVersion().String(), gvk.Kind)
}
interfaces, err := m.interfacesFunc(gvk.GroupVersion())
if err != nil {
return nil, fmt.Errorf("the provided version %q has no relevant versions: %v", gvk.GroupVersion().String(), err)
}
retVal := &RESTMapping{
Resource: resource.Resource,
GroupVersionKind: *gvk,
Scope: scope,
ObjectConvertor: interfaces.ObjectConvertor,
MetadataAccessor: interfaces.MetadataAccessor,
}
return retVal, nil
}
// RESTMappings returns the RESTMappings for the provided group kind in a rough internal preferred order. If no
// kind is found it will return a NoResourceMatchError.
func (m *DefaultRESTMapper) RESTMappings(gk unversioned.GroupKind) ([]*RESTMapping, error) {
// Use the default preferred versions
var mappings []*RESTMapping
for _, gv := range m.defaultGroupVersions {
if gv.Group != gk.Group {
continue
}
gvk := gk.WithVersion(gv.Version)
gvr, ok := m.kindToPluralResource[gvk]
if !ok {
continue
}
// Ensure we have a REST scope
scope, ok := m.kindToScope[gvk]
if !ok {
return nil, fmt.Errorf("the provided version %q and kind %q cannot be mapped to a supported scope", gvk.GroupVersion(), gvk.Kind)
}
interfaces, err := m.interfacesFunc(gvk.GroupVersion())
if err != nil {
return nil, fmt.Errorf("the provided version %q has no relevant versions: %v", gvk.GroupVersion().String(), err)
}
mappings = append(mappings, &RESTMapping{
Resource: gvr.Resource,
GroupVersionKind: gvk,
Scope: scope,
ObjectConvertor: interfaces.ObjectConvertor,
MetadataAccessor: interfaces.MetadataAccessor,
})
}
if len(mappings) == 0 {
return nil, &NoResourceMatchError{PartialResource: unversioned.GroupVersionResource{Group: gk.Group, Resource: gk.Kind}}
}
return mappings, nil
}
// AddResourceAlias maps aliases to resources
func (m *DefaultRESTMapper) AddResourceAlias(alias string, resources ...string) {
if len(resources) == 0 {
return
}
m.aliasToResource[alias] = resources
}
// AliasesForResource returns whether a resource has an alias or not
func (m *DefaultRESTMapper) AliasesForResource(alias string) ([]string, bool) {
if res, ok := m.aliasToResource[alias]; ok {
return res, true
}
return nil, false
}

View file

@ -1,31 +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 meta
import (
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
)
// InterfacesForUnstructured returns VersionInterfaces suitable for
// dealing with runtime.Unstructured objects.
func InterfacesForUnstructured(unversioned.GroupVersion) (*VersionInterfaces, error) {
return &VersionInterfaces{
ObjectConvertor: &runtime.UnstructuredObjectConverter{},
MetadataAccessor: NewAccessor(),
}, nil
}

View file

@ -1,132 +0,0 @@
/*
Copyright 2014 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 api
import (
"errors"
"fmt"
"net/url"
"strings"
"k8s.io/client-go/pkg/api/meta"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
)
var (
// Errors that could be returned by GetReference.
ErrNilObject = errors.New("can't reference a nil object")
ErrNoSelfLink = errors.New("selfLink was empty, can't make reference")
)
// GetReference returns an ObjectReference which refers to the given
// object, or an error if the object doesn't follow the conventions
// that would allow this.
// TODO: should take a meta.Interface see http://issue.k8s.io/7127
func GetReference(obj runtime.Object) (*ObjectReference, error) {
if obj == nil {
return nil, ErrNilObject
}
if ref, ok := obj.(*ObjectReference); ok {
// Don't make a reference to a reference.
return ref, nil
}
gvk := obj.GetObjectKind().GroupVersionKind()
// if the object referenced is actually persisted, we can just get kind from meta
// if we are building an object reference to something not yet persisted, we should fallback to scheme
kind := gvk.Kind
if len(kind) == 0 {
// TODO: this is wrong
gvks, _, err := Scheme.ObjectKinds(obj)
if err != nil {
return nil, err
}
kind = gvks[0].Kind
}
// An object that implements only List has enough metadata to build a reference
var listMeta meta.List
objectMeta, err := meta.Accessor(obj)
if err != nil {
listMeta, err = meta.ListAccessor(obj)
if err != nil {
return nil, err
}
} else {
listMeta = objectMeta
}
// if the object referenced is actually persisted, we can also get version from meta
version := gvk.GroupVersion().String()
if len(version) == 0 {
selfLink := listMeta.GetSelfLink()
if len(selfLink) == 0 {
return nil, ErrNoSelfLink
}
selfLinkUrl, err := url.Parse(selfLink)
if err != nil {
return nil, err
}
// example paths: /<prefix>/<version>/*
parts := strings.Split(selfLinkUrl.Path, "/")
if len(parts) < 3 {
return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", selfLink, version)
}
version = parts[2]
}
// only has list metadata
if objectMeta == nil {
return &ObjectReference{
Kind: kind,
APIVersion: version,
ResourceVersion: listMeta.GetResourceVersion(),
}, nil
}
return &ObjectReference{
Kind: kind,
APIVersion: version,
Name: objectMeta.GetName(),
Namespace: objectMeta.GetNamespace(),
UID: objectMeta.GetUID(),
ResourceVersion: objectMeta.GetResourceVersion(),
}, nil
}
// GetPartialReference is exactly like GetReference, but allows you to set the FieldPath.
func GetPartialReference(obj runtime.Object, fieldPath string) (*ObjectReference, error) {
ref, err := GetReference(obj)
if err != nil {
return nil, err
}
ref.FieldPath = fieldPath
return ref, nil
}
// IsAnAPIObject allows clients to preemptively get a reference to an API object and pass it to places that
// intend only to get a reference to that object. This simplifies the event recording interface.
func (obj *ObjectReference) SetGroupVersionKind(gvk unversioned.GroupVersionKind) {
obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind()
}
func (obj *ObjectReference) GroupVersionKind() unversioned.GroupVersionKind {
return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind)
}
func (obj *ObjectReference) GetObjectKind() unversioned.ObjectKind { return obj }

View file

@ -1,139 +0,0 @@
/*
Copyright 2014 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 api
import (
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/runtime/serializer"
)
// Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered.
// NOTE: If you are copying this file to start a new api group, STOP! Copy the
// extensions group instead. This Scheme is special and should appear ONLY in
// the api group, unless you really know what you're doing.
// TODO(lavalamp): make the above error impossible.
var Scheme = runtime.NewScheme()
// Codecs provides access to encoding and decoding for the scheme
var Codecs = serializer.NewCodecFactory(Scheme)
// GroupName is the group name use in this package
const GroupName = ""
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
// Unversioned is group version for unversioned API objects
// TODO: this should be v1 probably
var Unversioned = unversioned.GroupVersion{Group: "", Version: "v1"}
// ParameterCodec handles versioning of objects that are converted to query parameters.
var ParameterCodec = runtime.NewParameterCodec(Scheme)
// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) unversioned.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) unversioned.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addDefaultingFuncs)
AddToScheme = SchemeBuilder.AddToScheme
)
func init() {
// TODO(lavalamp): move this call to scheme builder above. Can't
// remove it from here because lots of people inappropriately rely on it
// (specifically the unversioned time conversion). Can't have it in
// both places because then it gets double registered. Consequence of
// current state is that it only ever gets registered in the main
// api.Scheme, even though everyone that uses anything from unversioned
// needs these.
if err := addConversionFuncs(Scheme); err != nil {
// Programmer error.
panic(err)
}
}
func addKnownTypes(scheme *runtime.Scheme) error {
if err := scheme.AddIgnoredConversionType(&unversioned.TypeMeta{}, &unversioned.TypeMeta{}); err != nil {
return err
}
scheme.AddKnownTypes(SchemeGroupVersion,
&Pod{},
&PodList{},
&PodStatusResult{},
&PodTemplate{},
&PodTemplateList{},
&ReplicationControllerList{},
&ReplicationController{},
&ServiceList{},
&Service{},
&ServiceProxyOptions{},
&NodeList{},
&Node{},
&NodeProxyOptions{},
&Endpoints{},
&EndpointsList{},
&Binding{},
&Event{},
&EventList{},
&List{},
&LimitRange{},
&LimitRangeList{},
&ResourceQuota{},
&ResourceQuotaList{},
&Namespace{},
&NamespaceList{},
&ServiceAccount{},
&ServiceAccountList{},
&Secret{},
&SecretList{},
&PersistentVolume{},
&PersistentVolumeList{},
&PersistentVolumeClaim{},
&PersistentVolumeClaimList{},
&DeleteOptions{},
&ListOptions{},
&PodAttachOptions{},
&PodLogOptions{},
&PodExecOptions{},
&PodProxyOptions{},
&ComponentStatus{},
&ComponentStatusList{},
&SerializedReference{},
&RangeAllocation{},
&ConfigMap{},
&ConfigMapList{},
)
// Register Unversioned types under their own special group
scheme.AddUnversionedTypes(Unversioned,
&unversioned.ExportOptions{},
&unversioned.Status{},
&unversioned.APIVersions{},
&unversioned.APIGroupList{},
&unversioned.APIGroup{},
&unversioned.APIResourceList{},
)
return nil
}

View file

@ -1,117 +0,0 @@
/*
Copyright 2014 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 api
import (
"errors"
"net/http"
"sync"
"github.com/golang/glog"
)
// RequestContextMapper keeps track of the context associated with a particular request
type RequestContextMapper interface {
// Get returns the context associated with the given request (if any), and true if the request has an associated context, and false if it does not.
Get(req *http.Request) (Context, bool)
// Update maps the request to the given context. If no context was previously associated with the request, an error is returned.
// Update should only be called with a descendant context of the previously associated context.
// Updating to an unrelated context may return an error in the future.
// The context associated with a request should only be updated by a limited set of callers.
// Valid examples include the authentication layer, or an audit/tracing layer.
Update(req *http.Request, context Context) error
}
type requestContextMap struct {
contexts map[*http.Request]Context
lock sync.Mutex
}
// NewRequestContextMapper returns a new RequestContextMapper.
// The returned mapper must be added as a request filter using NewRequestContextFilter.
func NewRequestContextMapper() RequestContextMapper {
return &requestContextMap{
contexts: make(map[*http.Request]Context),
}
}
// Get returns the context associated with the given request (if any), and true if the request has an associated context, and false if it does not.
// Get will only return a valid context when called from inside the filter chain set up by NewRequestContextFilter()
func (c *requestContextMap) Get(req *http.Request) (Context, bool) {
c.lock.Lock()
defer c.lock.Unlock()
context, ok := c.contexts[req]
return context, ok
}
// Update maps the request to the given context.
// If no context was previously associated with the request, an error is returned and the context is ignored.
func (c *requestContextMap) Update(req *http.Request, context Context) error {
c.lock.Lock()
defer c.lock.Unlock()
if _, ok := c.contexts[req]; !ok {
return errors.New("No context associated")
}
// TODO: ensure the new context is a descendant of the existing one
c.contexts[req] = context
return nil
}
// init maps the request to the given context and returns true if there was no context associated with the request already.
// if a context was already associated with the request, it ignores the given context and returns false.
// init is intentionally unexported to ensure that all init calls are paired with a remove after a request is handled
func (c *requestContextMap) init(req *http.Request, context Context) bool {
c.lock.Lock()
defer c.lock.Unlock()
if _, exists := c.contexts[req]; exists {
return false
}
c.contexts[req] = context
return true
}
// remove is intentionally unexported to ensure that the context is not removed until a request is handled
func (c *requestContextMap) remove(req *http.Request) {
c.lock.Lock()
defer c.lock.Unlock()
delete(c.contexts, req)
}
// WithRequestContext ensures there is a Context object associated with the request before calling the passed handler.
// After the passed handler runs, the context is cleaned up.
func WithRequestContext(handler http.Handler, mapper RequestContextMapper) http.Handler {
rcMap, ok := mapper.(*requestContextMap)
if !ok {
glog.Fatal("Unknown RequestContextMapper implementation.")
}
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if rcMap.init(req, NewContext()) {
// If we were the ones to successfully initialize, pair with a remove
defer rcMap.remove(req)
}
handler.ServeHTTP(w, req)
})
}
// IsEmpty returns true if there are no contexts registered, or an error if it could not be determined. Intended for use by tests.
func IsEmpty(requestsToContexts RequestContextMapper) (bool, error) {
if requestsToContexts, ok := requestsToContexts.(*requestContextMap); ok {
return len(requestsToContexts.contexts) == 0, nil
}
return true, errors.New("Unknown RequestContextMapper implementation")
}

View file

@ -1,299 +0,0 @@
/*
Copyright 2014 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 resource
import (
"math/big"
"strconv"
inf "gopkg.in/inf.v0"
)
// Scale is used for getting and setting the base-10 scaled value.
// Base-2 scales are omitted for mathematical simplicity.
// See Quantity.ScaledValue for more details.
type Scale int32
// infScale adapts a Scale value to an inf.Scale value.
func (s Scale) infScale() inf.Scale {
return inf.Scale(-s) // inf.Scale is upside-down
}
const (
Nano Scale = -9
Micro Scale = -6
Milli Scale = -3
Kilo Scale = 3
Mega Scale = 6
Giga Scale = 9
Tera Scale = 12
Peta Scale = 15
Exa Scale = 18
)
var (
Zero = int64Amount{}
// Used by quantity strings - treat as read only
zeroBytes = []byte("0")
)
// int64Amount represents a fixed precision numerator and arbitrary scale exponent. It is faster
// than operations on inf.Dec for values that can be represented as int64.
// +k8s:openapi-gen=true
type int64Amount struct {
value int64
scale Scale
}
// Sign returns 0 if the value is zero, -1 if it is less than 0, or 1 if it is greater than 0.
func (a int64Amount) Sign() int {
switch {
case a.value == 0:
return 0
case a.value > 0:
return 1
default:
return -1
}
}
// AsInt64 returns the current amount as an int64 at scale 0, or false if the value cannot be
// represented in an int64 OR would result in a loss of precision. This method is intended as
// an optimization to avoid calling AsDec.
func (a int64Amount) AsInt64() (int64, bool) {
if a.scale == 0 {
return a.value, true
}
if a.scale < 0 {
// TODO: attempt to reduce factors, although it is assumed that factors are reduced prior
// to the int64Amount being created.
return 0, false
}
return positiveScaleInt64(a.value, a.scale)
}
// AsScaledInt64 returns an int64 representing the value of this amount at the specified scale,
// rounding up, or false if that would result in overflow. (1e20).AsScaledInt64(1) would result
// in overflow because 1e19 is not representable as an int64. Note that setting a scale larger
// than the current value may result in loss of precision - i.e. (1e-6).AsScaledInt64(0) would
// return 1, because 0.000001 is rounded up to 1.
func (a int64Amount) AsScaledInt64(scale Scale) (result int64, ok bool) {
if a.scale < scale {
result, _ = negativeScaleInt64(a.value, scale-a.scale)
return result, true
}
return positiveScaleInt64(a.value, a.scale-scale)
}
// AsDec returns an inf.Dec representation of this value.
func (a int64Amount) AsDec() *inf.Dec {
var base inf.Dec
base.SetUnscaled(a.value)
base.SetScale(inf.Scale(-a.scale))
return &base
}
// Cmp returns 0 if a and b are equal, 1 if a is greater than b, or -1 if a is less than b.
func (a int64Amount) Cmp(b int64Amount) int {
switch {
case a.scale == b.scale:
// compare only the unscaled portion
case a.scale > b.scale:
result, remainder, exact := divideByScaleInt64(b.value, a.scale-b.scale)
if !exact {
return a.AsDec().Cmp(b.AsDec())
}
if result == a.value {
switch {
case remainder == 0:
return 0
case remainder > 0:
return -1
default:
return 1
}
}
b.value = result
default:
result, remainder, exact := divideByScaleInt64(a.value, b.scale-a.scale)
if !exact {
return a.AsDec().Cmp(b.AsDec())
}
if result == b.value {
switch {
case remainder == 0:
return 0
case remainder > 0:
return 1
default:
return -1
}
}
a.value = result
}
switch {
case a.value == b.value:
return 0
case a.value < b.value:
return -1
default:
return 1
}
}
// Add adds two int64Amounts together, matching scales. It will return false and not mutate
// a if overflow or underflow would result.
func (a *int64Amount) Add(b int64Amount) bool {
switch {
case b.value == 0:
return true
case a.value == 0:
a.value = b.value
a.scale = b.scale
return true
case a.scale == b.scale:
c, ok := int64Add(a.value, b.value)
if !ok {
return false
}
a.value = c
case a.scale > b.scale:
c, ok := positiveScaleInt64(a.value, a.scale-b.scale)
if !ok {
return false
}
c, ok = int64Add(c, b.value)
if !ok {
return false
}
a.scale = b.scale
a.value = c
default:
c, ok := positiveScaleInt64(b.value, b.scale-a.scale)
if !ok {
return false
}
c, ok = int64Add(a.value, c)
if !ok {
return false
}
a.value = c
}
return true
}
// Sub removes the value of b from the current amount, or returns false if underflow would result.
func (a *int64Amount) Sub(b int64Amount) bool {
return a.Add(int64Amount{value: -b.value, scale: b.scale})
}
// AsScale adjusts this amount to set a minimum scale, rounding up, and returns true iff no precision
// was lost. (1.1e5).AsScale(5) would return 1.1e5, but (1.1e5).AsScale(6) would return 1e6.
func (a int64Amount) AsScale(scale Scale) (int64Amount, bool) {
if a.scale >= scale {
return a, true
}
result, exact := negativeScaleInt64(a.value, scale-a.scale)
return int64Amount{value: result, scale: scale}, exact
}
// AsCanonicalBytes accepts a buffer to write the base-10 string value of this field to, and returns
// either that buffer or a larger buffer and the current exponent of the value. The value is adjusted
// until the exponent is a multiple of 3 - i.e. 1.1e5 would return "110", 3.
func (a int64Amount) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
mantissa := a.value
exponent = int32(a.scale)
amount, times := removeInt64Factors(mantissa, 10)
exponent += int32(times)
// make sure exponent is a multiple of 3
var ok bool
switch exponent % 3 {
case 1, -2:
amount, ok = int64MultiplyScale10(amount)
if !ok {
return infDecAmount{a.AsDec()}.AsCanonicalBytes(out)
}
exponent = exponent - 1
case 2, -1:
amount, ok = int64MultiplyScale100(amount)
if !ok {
return infDecAmount{a.AsDec()}.AsCanonicalBytes(out)
}
exponent = exponent - 2
}
return strconv.AppendInt(out, amount, 10), exponent
}
// AsCanonicalBase1024Bytes accepts a buffer to write the base-1024 string value of this field to, and returns
// either that buffer or a larger buffer and the current exponent of the value. 2048 is 2 * 1024 ^ 1 and would
// return []byte("2048"), 1.
func (a int64Amount) AsCanonicalBase1024Bytes(out []byte) (result []byte, exponent int32) {
value, ok := a.AsScaledInt64(0)
if !ok {
return infDecAmount{a.AsDec()}.AsCanonicalBase1024Bytes(out)
}
amount, exponent := removeInt64Factors(value, 1024)
return strconv.AppendInt(out, amount, 10), exponent
}
// infDecAmount implements common operations over an inf.Dec that are specific to the quantity
// representation.
type infDecAmount struct {
*inf.Dec
}
// AsScale adjusts this amount to set a minimum scale, rounding up, and returns true iff no precision
// was lost. (1.1e5).AsScale(5) would return 1.1e5, but (1.1e5).AsScale(6) would return 1e6.
func (a infDecAmount) AsScale(scale Scale) (infDecAmount, bool) {
tmp := &inf.Dec{}
tmp.Round(a.Dec, scale.infScale(), inf.RoundUp)
return infDecAmount{tmp}, tmp.Cmp(a.Dec) == 0
}
// AsCanonicalBytes accepts a buffer to write the base-10 string value of this field to, and returns
// either that buffer or a larger buffer and the current exponent of the value. The value is adjusted
// until the exponent is a multiple of 3 - i.e. 1.1e5 would return "110", 3.
func (a infDecAmount) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
mantissa := a.Dec.UnscaledBig()
exponent = int32(-a.Dec.Scale())
amount := big.NewInt(0).Set(mantissa)
// move all factors of 10 into the exponent for easy reasoning
amount, times := removeBigIntFactors(amount, bigTen)
exponent += times
// make sure exponent is a multiple of 3
for exponent%3 != 0 {
amount.Mul(amount, bigTen)
exponent--
}
return append(out, amount.String()...), exponent
}
// AsCanonicalBase1024Bytes accepts a buffer to write the base-1024 string value of this field to, and returns
// either that buffer or a larger buffer and the current exponent of the value. 2048 is 2 * 1024 ^ 1 and would
// return []byte("2048"), 1.
func (a infDecAmount) AsCanonicalBase1024Bytes(out []byte) (result []byte, exponent int32) {
tmp := &inf.Dec{}
tmp.Round(a.Dec, 0, inf.RoundUp)
amount, exponent := removeBigIntFactors(tmp.UnscaledBig(), big1024)
return append(out, amount.String()...), exponent
}

View file

@ -1,70 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by protoc-gen-gogo.
// source: k8s.io/kubernetes/pkg/api/resource/generated.proto
// DO NOT EDIT!
/*
Package resource is a generated protocol buffer package.
It is generated from these files:
k8s.io/kubernetes/pkg/api/resource/generated.proto
It has these top-level messages:
Quantity
*/
package resource
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
const _ = proto.GoGoProtoPackageIsVersion1
func (m *Quantity) Reset() { *m = Quantity{} }
func (*Quantity) ProtoMessage() {}
func (*Quantity) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} }
func init() {
proto.RegisterType((*Quantity)(nil), "k8s.io.client-go.pkg.api.resource.Quantity")
}
var fileDescriptorGenerated = []byte{
// 236 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x8f, 0xa1, 0x4e, 0x03, 0x41,
0x10, 0x86, 0x67, 0x0d, 0x29, 0x27, 0x1b, 0x42, 0x48, 0xc5, 0x5e, 0x53, 0x45, 0x48, 0xd8, 0x09,
0xa8, 0x06, 0xc9, 0x1b, 0x80, 0xc4, 0xdd, 0x95, 0x61, 0x99, 0x1c, 0xec, 0x6e, 0x76, 0x67, 0x05,
0xae, 0x12, 0x59, 0x89, 0xec, 0xbd, 0x4d, 0x65, 0x25, 0x02, 0xc1, 0x1d, 0x2f, 0x42, 0x72, 0xa5,
0x21, 0x21, 0xb8, 0xf9, 0xc4, 0x37, 0xf9, 0xfe, 0xe2, 0xb2, 0x99, 0x27, 0xc3, 0x1e, 0x9b, 0x5c,
0x53, 0x74, 0x24, 0x94, 0x30, 0x34, 0x16, 0xab, 0xc0, 0x18, 0x29, 0xf9, 0x1c, 0x17, 0x84, 0x96,
0x1c, 0xc5, 0x4a, 0xe8, 0xde, 0x84, 0xe8, 0xc5, 0x8f, 0x67, 0x3b, 0xc7, 0xfc, 0x3a, 0x26, 0x34,
0xd6, 0x54, 0x81, 0xcd, 0xde, 0x99, 0x9c, 0x5b, 0x96, 0xc7, 0x5c, 0x9b, 0x85, 0x7f, 0x46, 0xeb,
0xad, 0xc7, 0x41, 0xad, 0xf3, 0xc3, 0x40, 0x03, 0x0c, 0xd7, 0xee, 0xe5, 0xe4, 0xe2, 0xff, 0x8c,
0x2c, 0xfc, 0x84, 0xec, 0x24, 0x49, 0xfc, 0x5b, 0x31, 0x9b, 0x17, 0xa3, 0x9b, 0x5c, 0x39, 0x61,
0x79, 0x19, 0x1f, 0x17, 0x07, 0x49, 0x22, 0x3b, 0x7b, 0xa2, 0xa6, 0xea, 0xf4, 0xf0, 0xf6, 0x87,
0xae, 0x8e, 0xde, 0xd6, 0x25, 0xbc, 0xb6, 0x25, 0xac, 0xda, 0x12, 0xd6, 0x6d, 0x09, 0xcb, 0x8f,
0x29, 0x5c, 0x9f, 0x6d, 0x3a, 0x0d, 0xdb, 0x4e, 0xc3, 0x7b, 0xa7, 0x61, 0xd9, 0x6b, 0xb5, 0xe9,
0xb5, 0xda, 0xf6, 0x5a, 0x7d, 0xf6, 0x5a, 0xad, 0xbe, 0x34, 0xdc, 0x8d, 0xf6, 0x3b, 0xbe, 0x03,
0x00, 0x00, 0xff, 0xff, 0x90, 0x1c, 0x7f, 0xff, 0x20, 0x01, 0x00, 0x00,
}

View file

@ -1,327 +0,0 @@
/*
Copyright 2014 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 resource
import (
"math/big"
inf "gopkg.in/inf.v0"
)
const (
// maxInt64Factors is the highest value that will be checked when removing factors of 10 from an int64.
// It is also the maximum decimal digits that can be represented with an int64.
maxInt64Factors = 18
)
var (
// Commonly needed big.Int values-- treat as read only!
bigTen = big.NewInt(10)
bigZero = big.NewInt(0)
bigOne = big.NewInt(1)
bigThousand = big.NewInt(1000)
big1024 = big.NewInt(1024)
// Commonly needed inf.Dec values-- treat as read only!
decZero = inf.NewDec(0, 0)
decOne = inf.NewDec(1, 0)
decMinusOne = inf.NewDec(-1, 0)
decThousand = inf.NewDec(1000, 0)
dec1024 = inf.NewDec(1024, 0)
decMinus1024 = inf.NewDec(-1024, 0)
// Largest (in magnitude) number allowed.
maxAllowed = infDecAmount{inf.NewDec((1<<63)-1, 0)} // == max int64
// The maximum value we can represent milli-units for.
// Compare with the return value of Quantity.Value() to
// see if it's safe to use Quantity.MilliValue().
MaxMilliValue = int64(((1 << 63) - 1) / 1000)
)
const mostNegative = -(mostPositive + 1)
const mostPositive = 1<<63 - 1
// int64Add returns a+b, or false if that would overflow int64.
func int64Add(a, b int64) (int64, bool) {
c := a + b
switch {
case a > 0 && b > 0:
if c < 0 {
return 0, false
}
case a < 0 && b < 0:
if c > 0 {
return 0, false
}
if a == mostNegative && b == mostNegative {
return 0, false
}
}
return c, true
}
// int64Multiply returns a*b, or false if that would overflow or underflow int64.
func int64Multiply(a, b int64) (int64, bool) {
if a == 0 || b == 0 || a == 1 || b == 1 {
return a * b, true
}
if a == mostNegative || b == mostNegative {
return 0, false
}
c := a * b
return c, c/b == a
}
// int64MultiplyScale returns a*b, assuming b is greater than one, or false if that would overflow or underflow int64.
// Use when b is known to be greater than one.
func int64MultiplyScale(a int64, b int64) (int64, bool) {
if a == 0 || a == 1 {
return a * b, true
}
if a == mostNegative && b != 1 {
return 0, false
}
c := a * b
return c, c/b == a
}
// int64MultiplyScale10 multiplies a by 10, or returns false if that would overflow. This method is faster than
// int64Multiply(a, 10) because the compiler can optimize constant factor multiplication.
func int64MultiplyScale10(a int64) (int64, bool) {
if a == 0 || a == 1 {
return a * 10, true
}
if a == mostNegative {
return 0, false
}
c := a * 10
return c, c/10 == a
}
// int64MultiplyScale100 multiplies a by 100, or returns false if that would overflow. This method is faster than
// int64Multiply(a, 100) because the compiler can optimize constant factor multiplication.
func int64MultiplyScale100(a int64) (int64, bool) {
if a == 0 || a == 1 {
return a * 100, true
}
if a == mostNegative {
return 0, false
}
c := a * 100
return c, c/100 == a
}
// int64MultiplyScale1000 multiplies a by 1000, or returns false if that would overflow. This method is faster than
// int64Multiply(a, 1000) because the compiler can optimize constant factor multiplication.
func int64MultiplyScale1000(a int64) (int64, bool) {
if a == 0 || a == 1 {
return a * 1000, true
}
if a == mostNegative {
return 0, false
}
c := a * 1000
return c, c/1000 == a
}
// positiveScaleInt64 multiplies base by 10^scale, returning false if the
// value overflows. Passing a negative scale is undefined.
func positiveScaleInt64(base int64, scale Scale) (int64, bool) {
switch scale {
case 0:
return base, true
case 1:
return int64MultiplyScale10(base)
case 2:
return int64MultiplyScale100(base)
case 3:
return int64MultiplyScale1000(base)
case 6:
return int64MultiplyScale(base, 1000000)
case 9:
return int64MultiplyScale(base, 1000000000)
default:
value := base
var ok bool
for i := Scale(0); i < scale; i++ {
if value, ok = int64MultiplyScale(value, 10); !ok {
return 0, false
}
}
return value, true
}
}
// negativeScaleInt64 reduces base by the provided scale, rounding up, until the
// value is zero or the scale is reached. Passing a negative scale is undefined.
// The value returned, if not exact, is rounded away from zero.
func negativeScaleInt64(base int64, scale Scale) (result int64, exact bool) {
if scale == 0 {
return base, true
}
value := base
var fraction bool
for i := Scale(0); i < scale; i++ {
if !fraction && value%10 != 0 {
fraction = true
}
value = value / 10
if value == 0 {
if fraction {
if base > 0 {
return 1, false
}
return -1, false
}
return 0, true
}
}
if fraction {
if base > 0 {
value += 1
} else {
value += -1
}
}
return value, !fraction
}
func pow10Int64(b int64) int64 {
switch b {
case 0:
return 1
case 1:
return 10
case 2:
return 100
case 3:
return 1000
case 4:
return 10000
case 5:
return 100000
case 6:
return 1000000
case 7:
return 10000000
case 8:
return 100000000
case 9:
return 1000000000
case 10:
return 10000000000
case 11:
return 100000000000
case 12:
return 1000000000000
case 13:
return 10000000000000
case 14:
return 100000000000000
case 15:
return 1000000000000000
case 16:
return 10000000000000000
case 17:
return 100000000000000000
case 18:
return 1000000000000000000
default:
return 0
}
}
// powInt64 raises a to the bth power. Is not overflow aware.
func powInt64(a, b int64) int64 {
p := int64(1)
for b > 0 {
if b&1 != 0 {
p *= a
}
b >>= 1
a *= a
}
return p
}
// negativeScaleInt64 returns the result of dividing base by scale * 10 and the remainder, or
// false if no such division is possible. Dividing by negative scales is undefined.
func divideByScaleInt64(base int64, scale Scale) (result, remainder int64, exact bool) {
if scale == 0 {
return base, 0, true
}
// the max scale representable in base 10 in an int64 is 18 decimal places
if scale >= 18 {
return 0, base, false
}
divisor := pow10Int64(int64(scale))
return base / divisor, base % divisor, true
}
// removeInt64Factors divides in a loop; the return values have the property that
// value == result * base ^ scale
func removeInt64Factors(value int64, base int64) (result int64, times int32) {
times = 0
result = value
negative := result < 0
if negative {
result = -result
}
switch base {
// allow the compiler to optimize the common cases
case 10:
for result >= 10 && result%10 == 0 {
times++
result = result / 10
}
// allow the compiler to optimize the common cases
case 1024:
for result >= 1024 && result%1024 == 0 {
times++
result = result / 1024
}
default:
for result >= base && result%base == 0 {
times++
result = result / base
}
}
if negative {
result = -result
}
return result, times
}
// removeBigIntFactors divides in a loop; the return values have the property that
// d == result * factor ^ times
// d may be modified in place.
// If d == 0, then the return values will be (0, 0)
func removeBigIntFactors(d, factor *big.Int) (result *big.Int, times int32) {
q := big.NewInt(0)
m := big.NewInt(0)
for d.Cmp(bigZero) != 0 {
q.DivMod(d, factor, m)
if m.Cmp(bigZero) != 0 {
break
}
times++
d, q = q, d
}
return d, times
}

View file

@ -1,792 +0,0 @@
/*
Copyright 2014 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 resource
import (
"bytes"
"errors"
"fmt"
"math/big"
"regexp"
"strconv"
"strings"
flag "github.com/spf13/pflag"
"github.com/go-openapi/spec"
inf "gopkg.in/inf.v0"
"k8s.io/client-go/pkg/genericapiserver/openapi/common"
)
// 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
// <digits> ::= <digit> | <digit><digits>
// <number> ::= <digits> | <digits>.<digits> | <digits>. | .<digits>
// <sign> ::= "+" | "-"
// <signedNumber> ::= <number> | <sign><number>
// <suffix> ::= <binarySI> | <decimalExponent> | <decimalSI>
// <binarySI> ::= Ki | Mi | Gi | Ti | Pi | Ei
// (International System of units; See: http://physics.nist.gov/cuu/Units/binary.html)
// <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:
// a. No precision is lost
// 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
// +protobuf.options.(gogoproto.goproto_stringer)=false
// +k8s:openapi-gen=true
type Quantity struct {
// i is the quantity in int64 scaled form, if d.Dec == nil
i int64Amount
// d is the quantity in inf.Dec form if d.Dec != nil
d infDecAmount
// s is the generated value of this quantity to avoid recalculation
s string
// Change Format at will. See the comment for Canonicalize for
// more details.
Format
}
// CanonicalValue allows a quantity amount to be converted to a string.
type CanonicalValue interface {
// AsCanonicalBytes returns a byte array representing the string representation
// of the value mantissa and an int32 representing its exponent in base-10. Callers may
// pass a byte slice to the method to avoid allocations.
AsCanonicalBytes(out []byte) ([]byte, int32)
// AsCanonicalBase1024Bytes returns a byte array representing the string representation
// of the value mantissa and an int32 representing its exponent in base-1024. Callers
// may pass a byte slice to the method to avoid allocations.
AsCanonicalBase1024Bytes(out []byte) ([]byte, int32)
}
// Format lists the three possible formattings of a quantity.
type Format string
const (
DecimalExponent = Format("DecimalExponent") // e.g., 12e6
BinarySI = Format("BinarySI") // e.g., 12Mi (12 * 2^20)
DecimalSI = Format("DecimalSI") // e.g., 12M (12 * 10^6)
)
// MustParse turns the given string into a quantity or panics; for tests
// or others cases where you know the string is valid.
func MustParse(str string) Quantity {
q, err := ParseQuantity(str)
if err != nil {
panic(fmt.Errorf("cannot parse '%v': %v", str, err))
}
return q
}
const (
// splitREString is used to separate a number from its suffix; as such,
// this is overly permissive, but that's OK-- it will be checked later.
splitREString = "^([+-]?[0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$"
)
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")
ErrSuffix = errors.New("unable to parse quantity's suffix")
)
// parseQuantityString is a fast scanner for quantity values.
func parseQuantityString(str string) (positive bool, value, num, denom, suffix string, err error) {
positive = true
pos := 0
end := len(str)
// handle leading sign
if pos < end {
switch str[0] {
case '-':
positive = false
pos++
case '+':
pos++
}
}
// strip leading zeros
Zeroes:
for i := pos; ; i++ {
if i >= end {
num = "0"
value = num
return
}
switch str[i] {
case '0':
pos++
default:
break Zeroes
}
}
// extract the numerator
Num:
for i := pos; ; i++ {
if i >= end {
num = str[pos:end]
value = str[0:end]
return
}
switch str[i] {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
default:
num = str[pos:i]
pos = i
break Num
}
}
// if we stripped all numerator positions, always return 0
if len(num) == 0 {
num = "0"
}
// handle a denominator
if pos < end && str[pos] == '.' {
pos++
Denom:
for i := pos; ; i++ {
if i >= end {
denom = str[pos:end]
value = str[0:end]
return
}
switch str[i] {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
default:
denom = str[pos:i]
pos = i
break Denom
}
}
// TODO: we currently allow 1.G, but we may not want to in the future.
// if len(denom) == 0 {
// err = ErrFormatWrong
// return
// }
}
value = str[0:pos]
// grab the elements of the suffix
suffixStart := pos
for i := pos; ; i++ {
if i >= end {
suffix = str[suffixStart:end]
return
}
if !strings.ContainsAny(str[i:i+1], "eEinumkKMGTP") {
pos = i
break
}
}
if pos < end {
switch str[pos] {
case '-', '+':
pos++
}
}
Suffix:
for i := pos; ; i++ {
if i >= end {
suffix = str[suffixStart:end]
return
}
switch str[i] {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
default:
break Suffix
}
}
// we encountered a non decimal in the Suffix loop, but the last character
// was not a valid exponent
err = ErrFormatWrong
return
}
// ParseQuantity turns str into a Quantity, or returns an error.
func ParseQuantity(str string) (Quantity, error) {
if len(str) == 0 {
return Quantity{}, ErrFormatWrong
}
if str == "0" {
return Quantity{Format: DecimalSI, s: str}, nil
}
positive, value, num, denom, suf, err := parseQuantityString(str)
if err != nil {
return Quantity{}, err
}
base, exponent, format, ok := quantitySuffixer.interpret(suffix(suf))
if !ok {
return Quantity{}, ErrSuffix
}
precision := int32(0)
scale := int32(0)
mantissa := int64(1)
switch format {
case DecimalExponent, DecimalSI:
scale = exponent
precision = maxInt64Factors - int32(len(num)+len(denom))
case BinarySI:
scale = 0
switch {
case exponent >= 0 && len(denom) == 0:
// only handle positive binary numbers with the fast path
mantissa = int64(int64(mantissa) << uint64(exponent))
// 1Mi (2^20) has ~6 digits of decimal precision, so exponent*3/10 -1 is roughly the precision
precision = 15 - int32(len(num)) - int32(float32(exponent)*3/10) - 1
default:
precision = -1
}
}
if precision >= 0 {
// if we have a denominator, shift the entire value to the left by the number of places in the
// denominator
scale -= int32(len(denom))
if scale >= int32(Nano) {
shifted := num + denom
var value int64
value, err := strconv.ParseInt(shifted, 10, 64)
if err != nil {
return Quantity{}, ErrNumeric
}
if result, ok := int64Multiply(value, int64(mantissa)); ok {
if !positive {
result = -result
}
// if the number is in canonical form, reuse the string
switch format {
case BinarySI:
if exponent%10 == 0 && (value&0x07 != 0) {
return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format, s: str}, nil
}
default:
if scale%3 == 0 && !strings.HasSuffix(shifted, "000") && shifted[0] != '0' {
return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format, s: str}, nil
}
}
return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format}, nil
}
}
}
amount := new(inf.Dec)
if _, ok := amount.SetString(value); !ok {
return Quantity{}, ErrNumeric
}
// So that no one but us has to think about suffixes, remove it.
if base == 10 {
amount.SetScale(amount.Scale() + Scale(exponent).infScale())
} else if base == 2 {
// numericSuffix = 2 ** exponent
numericSuffix := big.NewInt(1).Lsh(bigOne, uint(exponent))
ub := amount.UnscaledBig()
amount.SetUnscaledBig(ub.Mul(ub, numericSuffix))
}
// Cap at min/max bounds.
sign := amount.Sign()
if sign == -1 {
amount.Neg(amount)
}
// This rounds non-zero values up to the minimum representable value, under the theory that
// if you want some resources, you should get some resources, even if you asked for way too small
// of an amount. Arguably, this should be inf.RoundHalfUp (normal rounding), but that would have
// the side effect of rounding values < .5n to zero.
if v, ok := amount.Unscaled(); v != int64(0) || !ok {
amount.Round(amount, Nano.infScale(), inf.RoundUp)
}
// The max is just a simple cap.
// TODO: this prevents accumulating quantities greater than int64, for instance quota across a cluster
if format == BinarySI && amount.Cmp(maxAllowed.Dec) > 0 {
amount.Set(maxAllowed.Dec)
}
if format == BinarySI && amount.Cmp(decOne) < 0 && amount.Cmp(decZero) > 0 {
// This avoids rounding and hopefully confusion, too.
format = DecimalSI
}
if sign == -1 {
amount.Neg(amount)
}
return Quantity{d: infDecAmount{amount}, Format: format}, nil
}
// DeepCopy returns a deep-copy of the Quantity value. Note that the method
// receiver is a value, so we can mutate it in-place and return it.
func (q Quantity) DeepCopy() Quantity {
if q.d.Dec != nil {
tmp := &inf.Dec{}
q.d.Dec = tmp.Set(q.d.Dec)
}
return q
}
// OpenAPIDefinition returns openAPI definition for this type.
func (_ Quantity) OpenAPIDefinition() common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
}
}
// CanonicalizeBytes returns the canonical form of q and its suffix (see comment on Quantity).
//
// Note about BinarySI:
// * If q.Format is set to BinarySI and q.Amount represents a non-zero value between
// -1 and +1, it will be emitted as if q.Format were DecimalSI.
// * Otherwise, if q.Format is set to BinarySI, frational parts of q.Amount will be
// rounded up. (1.1i becomes 2i.)
func (q *Quantity) CanonicalizeBytes(out []byte) (result, suffix []byte) {
if q.IsZero() {
return zeroBytes, nil
}
var rounded CanonicalValue
format := q.Format
switch format {
case DecimalExponent, DecimalSI:
case BinarySI:
if q.CmpInt64(-1024) > 0 && q.CmpInt64(1024) < 0 {
// This avoids rounding and hopefully confusion, too.
format = DecimalSI
} else {
var exact bool
if rounded, exact = q.AsScale(0); !exact {
// Don't lose precision-- show as DecimalSI
format = DecimalSI
}
}
default:
format = DecimalExponent
}
// TODO: If BinarySI formatting is requested but would cause rounding, upgrade to
// one of the other formats.
switch format {
case DecimalExponent, DecimalSI:
number, exponent := q.AsCanonicalBytes(out)
suffix, _ := quantitySuffixer.constructBytes(10, exponent, format)
return number, suffix
default:
// format must be BinarySI
number, exponent := rounded.AsCanonicalBase1024Bytes(out)
suffix, _ := quantitySuffixer.constructBytes(2, exponent*10, format)
return number, suffix
}
}
// AsInt64 returns a representation of the current value as an int64 if a fast conversion
// is possible. If false is returned, callers must use the inf.Dec form of this quantity.
func (q *Quantity) AsInt64() (int64, bool) {
if q.d.Dec != nil {
return 0, false
}
return q.i.AsInt64()
}
// ToDec promotes the quantity in place to use an inf.Dec representation and returns itself.
func (q *Quantity) ToDec() *Quantity {
if q.d.Dec == nil {
q.d.Dec = q.i.AsDec()
q.i = int64Amount{}
}
return q
}
// AsDec returns the quantity as represented by a scaled inf.Dec.
func (q *Quantity) AsDec() *inf.Dec {
if q.d.Dec != nil {
return q.d.Dec
}
q.d.Dec = q.i.AsDec()
q.i = int64Amount{}
return q.d.Dec
}
// AsCanonicalBytes returns the canonical byte representation of this quantity as a mantissa
// and base 10 exponent. The out byte slice may be passed to the method to avoid an extra
// allocation.
func (q *Quantity) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
if q.d.Dec != nil {
return q.d.AsCanonicalBytes(out)
}
return q.i.AsCanonicalBytes(out)
}
// IsZero returns true if the quantity is equal to zero.
func (q *Quantity) IsZero() bool {
if q.d.Dec != nil {
return q.d.Dec.Sign() == 0
}
return q.i.value == 0
}
// Sign returns 0 if the quantity is zero, -1 if the quantity is less than zero, or 1 if the
// quantity is greater than zero.
func (q *Quantity) Sign() int {
if q.d.Dec != nil {
return q.d.Dec.Sign()
}
return q.i.Sign()
}
// AsScaled 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 {
return q.d.AsScale(scale)
}
return q.i.AsScale(scale)
}
// RoundUp updates the quantity to the provided scale, ensuring that the value is at
// least 1. False is returned if the rounding operation resulted in a loss of precision.
// Negative numbers are rounded away from zero (-9 scale 1 rounds to -10).
func (q *Quantity) RoundUp(scale Scale) bool {
if q.d.Dec != nil {
q.s = ""
d, exact := q.d.AsScale(scale)
q.d = d
return exact
}
// avoid clearing the string value if we have already calculated it
if q.i.scale >= scale {
return true
}
q.s = ""
i, exact := q.i.AsScale(scale)
q.i = i
return exact
}
// Add adds the provide y quantity to the current value. If the current value is zero,
// the format of the quantity will be updated to the format of y.
func (q *Quantity) Add(y Quantity) {
q.s = ""
if q.d.Dec == nil && y.d.Dec == nil {
if q.i.value == 0 {
q.Format = y.Format
}
if q.i.Add(y.i) {
return
}
} else if q.IsZero() {
q.Format = y.Format
}
q.ToDec().d.Dec.Add(q.d.Dec, y.AsDec())
}
// Sub subtracts the provided quantity from the current value in place. If the current
// value is zero, the format of the quantity will be updated to the format of y.
func (q *Quantity) Sub(y Quantity) {
q.s = ""
if q.IsZero() {
q.Format = y.Format
}
if q.d.Dec == nil && y.d.Dec == nil && q.i.Sub(y.i) {
return
}
q.ToDec().d.Dec.Sub(q.d.Dec, y.AsDec())
}
// Cmp returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the
// quantity is greater than y.
func (q *Quantity) Cmp(y Quantity) int {
if q.d.Dec == nil && y.d.Dec == nil {
return q.i.Cmp(y.i)
}
return q.AsDec().Cmp(y.AsDec())
}
// CmpInt64 returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the
// quantity is greater than y.
func (q *Quantity) CmpInt64(y int64) int {
if q.d.Dec != nil {
return q.d.Dec.Cmp(inf.NewDec(y, inf.Scale(0)))
}
return q.i.Cmp(int64Amount{value: y})
}
// Neg sets quantity to be the negative value of itself.
func (q *Quantity) Neg() {
q.s = ""
if q.d.Dec == nil {
q.i.value = -q.i.value
return
}
q.d.Dec.Neg(q.d.Dec)
}
// int64QuantityExpectedBytes is the expected width in bytes of the canonical string representation
// of most Quantity values.
const int64QuantityExpectedBytes = 18
// String formats the Quantity as a string, caching the result if not calculated.
// String is an expensive operation and caching this result significantly reduces the cost of
// normal parse / marshal operations on Quantity.
func (q *Quantity) String() string {
if len(q.s) == 0 {
result := make([]byte, 0, int64QuantityExpectedBytes)
number, suffix := q.CanonicalizeBytes(result)
number = append(number, suffix...)
q.s = string(number)
}
return q.s
}
// MarshalJSON implements the json.Marshaller interface.
func (q Quantity) MarshalJSON() ([]byte, error) {
if len(q.s) > 0 {
out := make([]byte, len(q.s)+2)
out[0], out[len(out)-1] = '"', '"'
copy(out[1:], q.s)
return out, nil
}
result := make([]byte, int64QuantityExpectedBytes, int64QuantityExpectedBytes)
result[0] = '"'
number, suffix := q.CanonicalizeBytes(result[1:1])
// if the same slice was returned to us that we passed in, avoid another allocation by copying number into
// the source slice and returning that
if len(number) > 0 && &number[0] == &result[1] && (len(number)+len(suffix)+2) <= int64QuantityExpectedBytes {
number = append(number, suffix...)
number = append(number, '"')
return result[:1+len(number)], nil
}
// if CanonicalizeBytes needed more space than our slice provided, we may need to allocate again so use
// append
result = result[:1]
result = append(result, number...)
result = append(result, suffix...)
result = append(result, '"')
return result, nil
}
// UnmarshalJSON implements the json.Unmarshaller interface.
// TODO: Remove support for leading/trailing whitespace
func (q *Quantity) UnmarshalJSON(value []byte) error {
l := len(value)
if l == 4 && bytes.Equal(value, []byte("null")) {
q.d.Dec = nil
q.i = int64Amount{}
return nil
}
if l >= 2 && value[0] == '"' && value[l-1] == '"' {
value = value[1 : l-1]
}
parsed, err := ParseQuantity(strings.TrimSpace(string(value)))
if err != nil {
return err
}
// This copy is safe because parsed will not be referred to again.
*q = parsed
return nil
}
// NewQuantity returns a new Quantity representing the given
// value in the given format.
func NewQuantity(value int64, format Format) *Quantity {
return &Quantity{
i: int64Amount{value: value},
Format: format,
}
}
// NewMilliQuantity returns a new Quantity representing the given
// value * 1/1000 in the given format. Note that BinarySI formatting
// will round fractional values, and will be changed to DecimalSI for
// values x where (-1 < x < 1) && (x != 0).
func NewMilliQuantity(value int64, format Format) *Quantity {
return &Quantity{
i: int64Amount{value: value, scale: -3},
Format: format,
}
}
// NewScaledQuantity returns a new Quantity representing the given
// value * 10^scale in DecimalSI format.
func NewScaledQuantity(value int64, scale Scale) *Quantity {
return &Quantity{
i: int64Amount{value: value, scale: scale},
Format: DecimalSI,
}
}
// Value returns the value of q; any fractional part will be lost.
func (q *Quantity) Value() int64 {
return q.ScaledValue(0)
}
// MilliValue returns the value of ceil(q * 1000); this could overflow an int64;
// if that's a concern, call Value() first to verify the number is small enough.
func (q *Quantity) MilliValue() int64 {
return q.ScaledValue(Milli)
}
// ScaledValue returns the value of ceil(q * 10^scale); this could overflow an int64.
// To detect overflow, call Value() first and verify the expected magnitude.
func (q *Quantity) ScaledValue(scale Scale) int64 {
if q.d.Dec == nil {
i, _ := q.i.AsScaledInt64(scale)
return i
}
dec := q.d.Dec
return scaledValue(dec.UnscaledBig(), int(dec.Scale()), int(scale.infScale()))
}
// Set sets q's value to be value.
func (q *Quantity) Set(value int64) {
q.SetScaled(value, 0)
}
// SetMilli sets q's value to be value * 1/1000.
func (q *Quantity) SetMilli(value int64) {
q.SetScaled(value, Milli)
}
// SetScaled sets q's value to be value * 10^scale
func (q *Quantity) SetScaled(value int64, scale Scale) {
q.s = ""
q.d.Dec = nil
q.i = int64Amount{value: value, scale: scale}
}
// Copy is a convenience function that makes a deep copy for you. Non-deep
// copies of quantities share pointers and you will regret that.
func (q *Quantity) Copy() *Quantity {
if q.d.Dec == nil {
return &Quantity{
s: q.s,
i: q.i,
Format: q.Format,
}
}
tmp := &inf.Dec{}
return &Quantity{
s: q.s,
d: infDecAmount{tmp.Set(q.d.Dec)},
Format: q.Format,
}
}
// qFlag is a helper type for the Flag function
type qFlag struct {
dest *Quantity
}
// Sets the value of the internal Quantity. (used by flag & pflag)
func (qf qFlag) Set(val string) error {
q, err := ParseQuantity(val)
if err != nil {
return err
}
// This copy is OK because q will not be referenced again.
*qf.dest = q
return nil
}
// Converts the value of the internal Quantity to a string. (used by flag & pflag)
func (qf qFlag) String() string {
return qf.dest.String()
}
// States the type of flag this is (Quantity). (used by pflag)
func (qf qFlag) Type() string {
return "quantity"
}
// QuantityFlag is a helper that makes a quantity flag (using standard flag package).
// Will panic if defaultValue is not a valid quantity.
func QuantityFlag(flagName, defaultValue, description string) *Quantity {
q := MustParse(defaultValue)
flag.Var(NewQuantityFlagValue(&q), flagName, description)
return &q
}
// NewQuantityFlagValue returns an object that can be used to back a flag,
// pointing at the given Quantity variable.
func NewQuantityFlagValue(q *Quantity) flag.Value {
return qFlag{q}
}

View file

@ -1,284 +0,0 @@
/*
Copyright 2015 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 resource
import (
"fmt"
"io"
"github.com/gogo/protobuf/proto"
)
var _ proto.Sizer = &Quantity{}
func (m *Quantity) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
n, err := m.MarshalTo(data)
if err != nil {
return nil, err
}
return data[:n], nil
}
// MarshalTo is a customized version of the generated Protobuf unmarshaler for a struct
// with a single string field.
func (m *Quantity) MarshalTo(data []byte) (int, error) {
var i int
_ = i
var l int
_ = l
data[i] = 0xa
i++
// BEGIN CUSTOM MARSHAL
out := m.String()
i = encodeVarintGenerated(data, i, uint64(len(out)))
i += copy(data[i:], out)
// END CUSTOM MARSHAL
return i, nil
}
func encodeVarintGenerated(data []byte, offset int, v uint64) int {
for v >= 1<<7 {
data[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
data[offset] = uint8(v)
return offset + 1
}
func (m *Quantity) Size() (n int) {
var l int
_ = l
// BEGIN CUSTOM SIZE
l = len(m.String())
// END CUSTOM SIZE
n += 1 + l + sovGenerated(uint64(l))
return n
}
func sovGenerated(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
// Unmarshal is a customized version of the generated Protobuf unmarshaler for a struct
// with a single string field.
func (m *Quantity) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Quantity: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Quantity: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field String_", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
s := string(data[iNdEx:postIndex])
// BEGIN CUSTOM DECODE
p, err := ParseQuantity(s)
if err != nil {
return err
}
*m = p
// END CUSTOM DECODE
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenerated(data[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthGenerated
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipGenerated(data []byte) (n int, err error) {
l := len(data)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenerated
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenerated
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if data[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenerated
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
iNdEx += length
if length < 0 {
return 0, ErrInvalidLengthGenerated
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowGenerated
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipGenerated(data[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowGenerated = fmt.Errorf("proto: integer overflow")
)

View file

@ -1,95 +0,0 @@
/*
Copyright 2015 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 resource
import (
"math"
"math/big"
"sync"
)
var (
// A sync pool to reduce allocation.
intPool sync.Pool
maxInt64 = big.NewInt(math.MaxInt64)
)
func init() {
intPool.New = func() interface{} {
return &big.Int{}
}
}
// scaledValue scales given unscaled value from scale to new Scale and returns
// an int64. It ALWAYS rounds up the result when scale down. The final result might
// overflow.
//
// scale, newScale represents the scale of the unscaled decimal.
// The mathematical value of the decimal is unscaled * 10**(-scale).
func scaledValue(unscaled *big.Int, scale, newScale int) int64 {
dif := scale - newScale
if dif == 0 {
return unscaled.Int64()
}
// Handle scale up
// This is an easy case, we do not need to care about rounding and overflow.
// If any intermediate operation causes overflow, the result will overflow.
if dif < 0 {
return unscaled.Int64() * int64(math.Pow10(-dif))
}
// Handle scale down
// We have to be careful about the intermediate operations.
// fast path when unscaled < max.Int64 and exp(10,dif) < max.Int64
const log10MaxInt64 = 19
if unscaled.Cmp(maxInt64) < 0 && dif < log10MaxInt64 {
divide := int64(math.Pow10(dif))
result := unscaled.Int64() / divide
mod := unscaled.Int64() % divide
if mod != 0 {
return result + 1
}
return result
}
// We should only convert back to int64 when getting the result.
divisor := intPool.Get().(*big.Int)
exp := intPool.Get().(*big.Int)
result := intPool.Get().(*big.Int)
defer func() {
intPool.Put(divisor)
intPool.Put(exp)
intPool.Put(result)
}()
// divisor = 10^(dif)
// TODO: create loop up table if exp costs too much.
divisor.Exp(bigTen, exp.SetInt64(int64(dif)), nil)
// reuse exp
remainder := exp
// result = unscaled / divisor
// remainder = unscaled % divisor
result.DivMod(unscaled, divisor, remainder)
if remainder.Sign() != 0 {
return result.Int64() + 1
}
return result.Int64()
}

View file

@ -1,198 +0,0 @@
/*
Copyright 2014 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 resource
import (
"strconv"
)
type suffix string
// suffixer can interpret and construct suffixes.
type suffixer interface {
interpret(suffix) (base, exponent int32, fmt Format, ok bool)
construct(base, exponent int32, fmt Format) (s suffix, ok bool)
constructBytes(base, exponent int32, fmt Format) (s []byte, ok bool)
}
// quantitySuffixer handles suffixes for all three formats that quantity
// can handle.
var quantitySuffixer = newSuffixer()
type bePair struct {
base, exponent int32
}
type listSuffixer struct {
suffixToBE map[suffix]bePair
beToSuffix map[bePair]suffix
beToSuffixBytes map[bePair][]byte
}
func (ls *listSuffixer) addSuffix(s suffix, pair bePair) {
if ls.suffixToBE == nil {
ls.suffixToBE = map[suffix]bePair{}
}
if ls.beToSuffix == nil {
ls.beToSuffix = map[bePair]suffix{}
}
if ls.beToSuffixBytes == nil {
ls.beToSuffixBytes = map[bePair][]byte{}
}
ls.suffixToBE[s] = pair
ls.beToSuffix[pair] = s
ls.beToSuffixBytes[pair] = []byte(s)
}
func (ls *listSuffixer) lookup(s suffix) (base, exponent int32, ok bool) {
pair, ok := ls.suffixToBE[s]
if !ok {
return 0, 0, false
}
return pair.base, pair.exponent, true
}
func (ls *listSuffixer) construct(base, exponent int32) (s suffix, ok bool) {
s, ok = ls.beToSuffix[bePair{base, exponent}]
return
}
func (ls *listSuffixer) constructBytes(base, exponent int32) (s []byte, ok bool) {
s, ok = ls.beToSuffixBytes[bePair{base, exponent}]
return
}
type suffixHandler struct {
decSuffixes listSuffixer
binSuffixes listSuffixer
}
type fastLookup struct {
*suffixHandler
}
func (l fastLookup) interpret(s suffix) (base, exponent int32, format Format, ok bool) {
switch s {
case "":
return 10, 0, DecimalSI, true
case "n":
return 10, -9, DecimalSI, true
case "u":
return 10, -6, DecimalSI, true
case "m":
return 10, -3, DecimalSI, true
case "k":
return 10, 3, DecimalSI, true
case "M":
return 10, 6, DecimalSI, true
case "G":
return 10, 9, DecimalSI, true
}
return l.suffixHandler.interpret(s)
}
func newSuffixer() suffixer {
sh := &suffixHandler{}
// IMPORTANT: if you change this section you must change fastLookup
sh.binSuffixes.addSuffix("Ki", bePair{2, 10})
sh.binSuffixes.addSuffix("Mi", bePair{2, 20})
sh.binSuffixes.addSuffix("Gi", bePair{2, 30})
sh.binSuffixes.addSuffix("Ti", bePair{2, 40})
sh.binSuffixes.addSuffix("Pi", bePair{2, 50})
sh.binSuffixes.addSuffix("Ei", bePair{2, 60})
// Don't emit an error when trying to produce
// a suffix for 2^0.
sh.decSuffixes.addSuffix("", bePair{2, 0})
sh.decSuffixes.addSuffix("n", bePair{10, -9})
sh.decSuffixes.addSuffix("u", bePair{10, -6})
sh.decSuffixes.addSuffix("m", bePair{10, -3})
sh.decSuffixes.addSuffix("", bePair{10, 0})
sh.decSuffixes.addSuffix("k", bePair{10, 3})
sh.decSuffixes.addSuffix("M", bePair{10, 6})
sh.decSuffixes.addSuffix("G", bePair{10, 9})
sh.decSuffixes.addSuffix("T", bePair{10, 12})
sh.decSuffixes.addSuffix("P", bePair{10, 15})
sh.decSuffixes.addSuffix("E", bePair{10, 18})
return fastLookup{sh}
}
func (sh *suffixHandler) construct(base, exponent int32, fmt Format) (s suffix, ok bool) {
switch fmt {
case DecimalSI:
return sh.decSuffixes.construct(base, exponent)
case BinarySI:
return sh.binSuffixes.construct(base, exponent)
case DecimalExponent:
if base != 10 {
return "", false
}
if exponent == 0 {
return "", true
}
return suffix("e" + strconv.FormatInt(int64(exponent), 10)), true
}
return "", false
}
func (sh *suffixHandler) constructBytes(base, exponent int32, format Format) (s []byte, ok bool) {
switch format {
case DecimalSI:
return sh.decSuffixes.constructBytes(base, exponent)
case BinarySI:
return sh.binSuffixes.constructBytes(base, exponent)
case DecimalExponent:
if base != 10 {
return nil, false
}
if exponent == 0 {
return nil, true
}
result := make([]byte, 8, 8)
result[0] = 'e'
number := strconv.AppendInt(result[1:1], int64(exponent), 10)
if &result[1] == &number[0] {
return result[:1+len(number)], true
}
result = append(result[:1], number...)
return result, true
}
return nil, false
}
func (sh *suffixHandler) interpret(suffix suffix) (base, exponent int32, fmt Format, ok bool) {
// Try lookup tables first
if b, e, ok := sh.decSuffixes.lookup(suffix); ok {
return b, e, DecimalSI, true
}
if b, e, ok := sh.binSuffixes.lookup(suffix); ok {
return b, e, BinarySI, true
}
if len(suffix) > 1 && (suffix[0] == 'E' || suffix[0] == 'e') {
parsed, err := strconv.ParseInt(string(suffix[1:]), 10, 64)
if err != nil {
return 0, 0, DecimalExponent, false
}
return 10, int32(parsed), DecimalExponent, true
}
return 0, 0, DecimalExponent, false
}

View file

@ -1,229 +0,0 @@
/*
Copyright 2014 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 api
import (
"time"
"k8s.io/client-go/pkg/api/resource"
"k8s.io/client-go/pkg/api/unversioned"
)
// Returns string version of ResourceName.
func (self ResourceName) String() string {
return string(self)
}
// Returns the CPU limit if specified.
func (self *ResourceList) Cpu() *resource.Quantity {
if val, ok := (*self)[ResourceCPU]; ok {
return &val
}
return &resource.Quantity{Format: resource.DecimalSI}
}
// Returns the Memory limit if specified.
func (self *ResourceList) Memory() *resource.Quantity {
if val, ok := (*self)[ResourceMemory]; ok {
return &val
}
return &resource.Quantity{Format: resource.BinarySI}
}
func (self *ResourceList) Pods() *resource.Quantity {
if val, ok := (*self)[ResourcePods]; ok {
return &val
}
return &resource.Quantity{}
}
func (self *ResourceList) NvidiaGPU() *resource.Quantity {
if val, ok := (*self)[ResourceNvidiaGPU]; ok {
return &val
}
return &resource.Quantity{}
}
func GetContainerStatus(statuses []ContainerStatus, name string) (ContainerStatus, bool) {
for i := range statuses {
if statuses[i].Name == name {
return statuses[i], true
}
}
return ContainerStatus{}, false
}
func GetExistingContainerStatus(statuses []ContainerStatus, name string) ContainerStatus {
for i := range statuses {
if statuses[i].Name == name {
return statuses[i]
}
}
return ContainerStatus{}
}
// IsPodAvailable returns true if a pod is available; false otherwise.
// Precondition for an available pod is that it must be ready. On top
// of that, there are two cases when a pod can be considered available:
// 1. minReadySeconds == 0, or
// 2. LastTransitionTime (is set) + minReadySeconds < current time
func IsPodAvailable(pod *Pod, minReadySeconds int32, now unversioned.Time) bool {
if !IsPodReady(pod) {
return false
}
c := GetPodReadyCondition(pod.Status)
minReadySecondsDuration := time.Duration(minReadySeconds) * time.Second
if minReadySeconds == 0 || !c.LastTransitionTime.IsZero() && c.LastTransitionTime.Add(minReadySecondsDuration).Before(now.Time) {
return true
}
return false
}
// IsPodReady returns true if a pod is ready; false otherwise.
func IsPodReady(pod *Pod) bool {
return IsPodReadyConditionTrue(pod.Status)
}
// IsPodReady retruns true if a pod is ready; false otherwise.
func IsPodReadyConditionTrue(status PodStatus) bool {
condition := GetPodReadyCondition(status)
return condition != nil && condition.Status == ConditionTrue
}
// Extracts the pod ready condition from the given status and returns that.
// Returns nil if the condition is not present.
func GetPodReadyCondition(status PodStatus) *PodCondition {
_, condition := GetPodCondition(&status, PodReady)
return condition
}
// GetPodCondition extracts the provided condition from the given status and returns that.
// Returns nil and -1 if the condition is not present, and the index of the located condition.
func GetPodCondition(status *PodStatus, conditionType PodConditionType) (int, *PodCondition) {
if status == nil {
return -1, nil
}
for i := range status.Conditions {
if status.Conditions[i].Type == conditionType {
return i, &status.Conditions[i]
}
}
return -1, nil
}
// GetNodeCondition extracts the provided condition from the given status and returns that.
// Returns nil and -1 if the condition is not present, and the index of the located condition.
func GetNodeCondition(status *NodeStatus, conditionType NodeConditionType) (int, *NodeCondition) {
if status == nil {
return -1, nil
}
for i := range status.Conditions {
if status.Conditions[i].Type == conditionType {
return i, &status.Conditions[i]
}
}
return -1, nil
}
// Updates existing pod condition or creates a new one. Sets LastTransitionTime to now if the
// status has changed.
// Returns true if pod condition has changed or has been added.
func UpdatePodCondition(status *PodStatus, condition *PodCondition) bool {
condition.LastTransitionTime = unversioned.Now()
// Try to find this pod condition.
conditionIndex, oldCondition := GetPodCondition(status, condition.Type)
if oldCondition == nil {
// We are adding new pod condition.
status.Conditions = append(status.Conditions, *condition)
return true
} else {
// We are updating an existing condition, so we need to check if it has changed.
if condition.Status == oldCondition.Status {
condition.LastTransitionTime = oldCondition.LastTransitionTime
}
isEqual := condition.Status == oldCondition.Status &&
condition.Reason == oldCondition.Reason &&
condition.Message == oldCondition.Message &&
condition.LastProbeTime.Equal(oldCondition.LastProbeTime) &&
condition.LastTransitionTime.Equal(oldCondition.LastTransitionTime)
status.Conditions[conditionIndex] = *condition
// Return true if one of the fields have changed.
return !isEqual
}
}
// IsNodeReady returns true if a node is ready; false otherwise.
func IsNodeReady(node *Node) bool {
for _, c := range node.Status.Conditions {
if c.Type == NodeReady {
return c.Status == ConditionTrue
}
}
return false
}
// PodRequestsAndLimits returns a dictionary of all defined resources summed up for all
// containers of the pod.
func PodRequestsAndLimits(pod *Pod) (reqs map[ResourceName]resource.Quantity, limits map[ResourceName]resource.Quantity, err error) {
reqs, limits = map[ResourceName]resource.Quantity{}, map[ResourceName]resource.Quantity{}
for _, container := range pod.Spec.Containers {
for name, quantity := range container.Resources.Requests {
if value, ok := reqs[name]; !ok {
reqs[name] = *quantity.Copy()
} else {
value.Add(quantity)
reqs[name] = value
}
}
for name, quantity := range container.Resources.Limits {
if value, ok := limits[name]; !ok {
limits[name] = *quantity.Copy()
} else {
value.Add(quantity)
limits[name] = value
}
}
}
// init containers define the minimum of any resource
for _, container := range pod.Spec.InitContainers {
for name, quantity := range container.Resources.Requests {
value, ok := reqs[name]
if !ok {
reqs[name] = *quantity.Copy()
continue
}
if quantity.Cmp(value) > 0 {
reqs[name] = *quantity.Copy()
}
}
for name, quantity := range container.Resources.Limits {
value, ok := limits[name]
if !ok {
limits[name] = *quantity.Copy()
continue
}
if quantity.Cmp(value) > 0 {
limits[name] = *quantity.Copy()
}
}
}
return
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,21 +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.
*/
// +k8s:deepcopy-gen=package
// +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
package unversioned

View file

@ -1,47 +0,0 @@
/*
Copyright 2014 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 unversioned
import (
"encoding/json"
"time"
)
// Duration is a wrapper around time.Duration which supports correct
// marshaling to YAML and JSON. In particular, it marshals into strings, which
// can be used as map keys in json.
type Duration struct {
time.Duration `protobuf:"varint,1,opt,name=duration,casttype=time.Duration"`
}
// UnmarshalJSON implements the json.Unmarshaller interface.
func (d *Duration) UnmarshalJSON(b []byte) error {
var str string
json.Unmarshal(b, &str)
pd, err := time.ParseDuration(str)
if err != nil {
return err
}
d.Duration = pd
return nil
}
// MarshalJSON implements the json.Marshaler interface.
func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(d.Duration.String())
}

File diff suppressed because it is too large Load diff

View file

@ -1,345 +0,0 @@
/*
Copyright 2015 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 unversioned
import (
"encoding/json"
"fmt"
"strings"
)
// ParseResourceArg takes the common style of string which may be either `resource.group.com` or `resource.version.group.com`
// and parses it out into both possibilities. This code takes no responsibility for knowing which representation was intended
// but with a knowledge of all GroupVersions, calling code can take a very good guess. If there are only two segments, then
// `*GroupVersionResource` is nil.
// `resource.group.com` -> `group=com, version=group, resource=resource` and `group=group.com, resource=resource`
func ParseResourceArg(arg string) (*GroupVersionResource, GroupResource) {
var gvr *GroupVersionResource
if strings.Count(arg, ".") >= 2 {
s := strings.SplitN(arg, ".", 3)
gvr = &GroupVersionResource{Group: s[2], Version: s[1], Resource: s[0]}
}
return gvr, ParseGroupResource(arg)
}
// 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
type GroupResource struct {
Group string `protobuf:"bytes,1,opt,name=group"`
Resource string `protobuf:"bytes,2,opt,name=resource"`
}
func (gr GroupResource) WithVersion(version string) GroupVersionResource {
return GroupVersionResource{Group: gr.Group, Version: version, Resource: gr.Resource}
}
func (gr GroupResource) Empty() bool {
return len(gr.Group) == 0 && len(gr.Resource) == 0
}
func (gr *GroupResource) String() string {
if len(gr.Group) == 0 {
return gr.Resource
}
return gr.Resource + "." + gr.Group
}
// 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 {
return GroupResource{Group: gr[i+1:], Resource: gr[:i]}
}
}
// 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
type GroupVersionResource struct {
Group string `protobuf:"bytes,1,opt,name=group"`
Version string `protobuf:"bytes,2,opt,name=version"`
Resource string `protobuf:"bytes,3,opt,name=resource"`
}
func (gvr GroupVersionResource) Empty() bool {
return len(gvr.Group) == 0 && len(gvr.Version) == 0 && len(gvr.Resource) == 0
}
func (gvr GroupVersionResource) GroupResource() GroupResource {
return GroupResource{Group: gvr.Group, Resource: gvr.Resource}
}
func (gvr GroupVersionResource) GroupVersion() GroupVersion {
return GroupVersion{Group: gvr.Group, Version: gvr.Version}
}
func (gvr *GroupVersionResource) String() string {
return strings.Join([]string{gvr.Group, "/", gvr.Version, ", Resource=", gvr.Resource}, "")
}
// 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
type GroupKind struct {
Group string `protobuf:"bytes,1,opt,name=group"`
Kind string `protobuf:"bytes,2,opt,name=kind"`
}
func (gk GroupKind) Empty() bool {
return len(gk.Group) == 0 && len(gk.Kind) == 0
}
func (gk GroupKind) WithVersion(version string) GroupVersionKind {
return GroupVersionKind{Group: gk.Group, Version: version, Kind: gk.Kind}
}
func (gk *GroupKind) String() string {
if len(gk.Group) == 0 {
return gk.Kind
}
return gk.Kind + "." + gk.Group
}
// 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
type GroupVersionKind struct {
Group string `protobuf:"bytes,1,opt,name=group"`
Version string `protobuf:"bytes,2,opt,name=version"`
Kind string `protobuf:"bytes,3,opt,name=kind"`
}
// Empty returns true if group, version, and kind are empty
func (gvk GroupVersionKind) Empty() bool {
return len(gvk.Group) == 0 && len(gvk.Version) == 0 && len(gvk.Kind) == 0
}
func (gvk GroupVersionKind) GroupKind() GroupKind {
return GroupKind{Group: gvk.Group, Kind: gvk.Kind}
}
func (gvk GroupVersionKind) GroupVersion() GroupVersion {
return GroupVersion{Group: gvk.Group, Version: gvk.Version}
}
func (gvk GroupVersionKind) String() string {
return gvk.Group + "/" + gvk.Version + ", Kind=" + gvk.Kind
}
// GroupVersion contains the "group" and the "version", which uniquely identifies the API.
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
type GroupVersion struct {
Group string `protobuf:"bytes,1,opt,name=group"`
Version string `protobuf:"bytes,2,opt,name=version"`
}
// Empty returns true if group and version are empty
func (gv GroupVersion) Empty() bool {
return len(gv.Group) == 0 && len(gv.Version) == 0
}
// String puts "group" and "version" into a single "group/version" string. For the legacy v1
// it returns "v1".
func (gv GroupVersion) String() string {
// special case the internal apiVersion for the legacy kube types
if gv.Empty() {
return ""
}
// special case of "v1" for backward compatibility
if len(gv.Group) == 0 && gv.Version == "v1" {
return gv.Version
}
if len(gv.Group) > 0 {
return gv.Group + "/" + gv.Version
}
return gv.Version
}
// KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false
// if none of the options match the group. It prefers a match to group and version over just group.
// TODO: Move GroupVersion to a package under pkg/runtime, since it's used by scheme.
// TODO: Introduce an adapter type between GroupVersion and runtime.GroupVersioner, and use LegacyCodec(GroupVersion)
// in fewer places.
func (gv GroupVersion) KindForGroupVersionKinds(kinds []GroupVersionKind) (target GroupVersionKind, ok bool) {
for _, gvk := range kinds {
if gvk.Group == gv.Group && gvk.Version == gv.Version {
return gvk, true
}
}
for _, gvk := range kinds {
if gvk.Group == gv.Group {
return gv.WithKind(gvk.Kind), true
}
}
return GroupVersionKind{}, false
}
// ParseGroupVersion turns "group/version" string into a GroupVersion struct. It reports error
// if it cannot parse the string.
func ParseGroupVersion(gv string) (GroupVersion, error) {
// this can be the internal version for the legacy kube types
// TODO once we've cleared the last uses as strings, this special case should be removed.
if (len(gv) == 0) || (gv == "/") {
return GroupVersion{}, nil
}
switch strings.Count(gv, "/") {
case 0:
return GroupVersion{"", gv}, nil
case 1:
i := strings.Index(gv, "/")
return GroupVersion{gv[:i], gv[i+1:]}, nil
default:
return GroupVersion{}, fmt.Errorf("unexpected GroupVersion string: %v", gv)
}
}
// WithKind creates a GroupVersionKind based on the method receiver's GroupVersion and the passed Kind.
func (gv GroupVersion) WithKind(kind string) GroupVersionKind {
return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}
}
// WithResource creates a GroupVersionResource based on the method receiver's GroupVersion and the passed Resource.
func (gv GroupVersion) WithResource(resource string) GroupVersionResource {
return GroupVersionResource{Group: gv.Group, Version: gv.Version, Resource: resource}
}
// MarshalJSON implements the json.Marshaller interface.
func (gv GroupVersion) MarshalJSON() ([]byte, error) {
s := gv.String()
if strings.Count(s, "/") > 1 {
return []byte{}, fmt.Errorf("illegal GroupVersion %v: contains more than one /", s)
}
return json.Marshal(s)
}
func (gv *GroupVersion) unmarshal(value []byte) error {
var s string
if err := json.Unmarshal(value, &s); err != nil {
return err
}
parsed, err := ParseGroupVersion(s)
if err != nil {
return err
}
*gv = parsed
return nil
}
// UnmarshalJSON implements the json.Unmarshaller interface.
func (gv *GroupVersion) UnmarshalJSON(value []byte) error {
return gv.unmarshal(value)
}
// UnmarshalTEXT implements the Ugorji's encoding.TextUnmarshaler interface.
func (gv *GroupVersion) UnmarshalText(value []byte) error {
return gv.unmarshal(value)
}
// GroupVersions can be used to represent a set of desired group versions.
// TODO: Move GroupVersions to a package under pkg/runtime, since it's used by scheme.
// TODO: Introduce an adapter type between GroupVersions and runtime.GroupVersioner, and use LegacyCodec(GroupVersion)
// in fewer places.
type GroupVersions []GroupVersion
// KindForGroupVersionKinds identifies the preferred GroupVersionKind out of a list. It returns ok false
// if none of the options match the group.
func (gvs GroupVersions) KindForGroupVersionKinds(kinds []GroupVersionKind) (GroupVersionKind, bool) {
var targets []GroupVersionKind
for _, gv := range gvs {
target, ok := gv.KindForGroupVersionKinds(kinds)
if !ok {
continue
}
targets = append(targets, target)
}
if len(targets) == 1 {
return targets[0], true
}
if len(targets) > 1 {
return bestMatch(kinds, targets), true
}
return GroupVersionKind{}, false
}
// bestMatch tries to pick best matching GroupVersionKind and falls back to the first
// found if no exact match exists.
func bestMatch(kinds []GroupVersionKind, targets []GroupVersionKind) GroupVersionKind {
for _, gvk := range targets {
for _, k := range kinds {
if k == gvk {
return k
}
}
}
return targets[0]
}
// 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 {
return "", ""
}
return gvk.GroupVersion().String(), gvk.Kind
}
// FromAPIVersionAndKind returns a GVK representing the provided fields for types that
// do not use TypeMeta. This method exists to support test types and legacy serializations
// that have a distinct group and kind.
// TODO: further reduce usage of this method.
func FromAPIVersionAndKind(apiVersion, kind string) GroupVersionKind {
if gv, err := ParseGroupVersion(apiVersion); err == nil {
return GroupVersionKind{Group: gv.Group, Version: gv.Version, Kind: kind}
}
return GroupVersionKind{Kind: kind}
}
// All objects that are serialized from a Scheme encode their type information. This interface is used
// by serialization to set type information from the Scheme onto the serialized version of an object.
// For objects that cannot be serialized or have unique requirements, this interface may be a no-op.
// TODO: this belongs in pkg/runtime, move unversioned.GVK into runtime.
type ObjectKind interface {
// SetGroupVersionKind sets or clears the intended serialized kind of an object. Passing kind nil
// should clear the current setting.
SetGroupVersionKind(kind GroupVersionKind)
// GroupVersionKind returns the stored group, version, and kind of an object, or nil if the object does
// not expose or provide these fields.
GroupVersionKind() GroupVersionKind
}
// EmptyObjectKind implements the ObjectKind interface as a noop
// TODO: this belongs in pkg/runtime, move unversioned.GVK into runtime.
var EmptyObjectKind = emptyObjectKind{}
type emptyObjectKind struct{}
// SetGroupVersionKind implements the ObjectKind interface
func (emptyObjectKind) SetGroupVersionKind(gvk GroupVersionKind) {}
// GroupVersionKind implements the ObjectKind interface
func (emptyObjectKind) GroupVersionKind() GroupVersionKind { return GroupVersionKind{} }

View file

@ -1,183 +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 unversioned
import (
"fmt"
"k8s.io/client-go/pkg/labels"
"k8s.io/client-go/pkg/selection"
)
// LabelSelectorAsSelector converts the LabelSelector api type into a struct that implements
// labels.Selector
// Note: This function should be kept in sync with the selector methods in pkg/labels/selector.go
func LabelSelectorAsSelector(ps *LabelSelector) (labels.Selector, error) {
if ps == nil {
return labels.Nothing(), nil
}
if len(ps.MatchLabels)+len(ps.MatchExpressions) == 0 {
return labels.Everything(), nil
}
selector := labels.NewSelector()
for k, v := range ps.MatchLabels {
r, err := labels.NewRequirement(k, selection.Equals, []string{v})
if err != nil {
return nil, err
}
selector = selector.Add(*r)
}
for _, expr := range ps.MatchExpressions {
var op selection.Operator
switch expr.Operator {
case LabelSelectorOpIn:
op = selection.In
case LabelSelectorOpNotIn:
op = selection.NotIn
case LabelSelectorOpExists:
op = selection.Exists
case LabelSelectorOpDoesNotExist:
op = selection.DoesNotExist
default:
return nil, fmt.Errorf("%q is not a valid pod selector operator", expr.Operator)
}
r, err := labels.NewRequirement(expr.Key, op, append([]string(nil), expr.Values...))
if err != nil {
return nil, err
}
selector = selector.Add(*r)
}
return selector, nil
}
// LabelSelectorAsMap converts the LabelSelector api type into a map of strings, ie. the
// original structure of a label selector. Operators that cannot be converted into plain
// labels (Exists, DoesNotExist, NotIn, and In with more than one value) will result in
// an error.
func LabelSelectorAsMap(ps *LabelSelector) (map[string]string, error) {
if ps == nil {
return nil, nil
}
selector := map[string]string{}
for k, v := range ps.MatchLabels {
selector[k] = v
}
for _, expr := range ps.MatchExpressions {
switch expr.Operator {
case LabelSelectorOpIn:
if len(expr.Values) != 1 {
return selector, fmt.Errorf("operator %q without a single value cannot be converted into the old label selector format", expr.Operator)
}
// Should we do anything in case this will override a previous key-value pair?
selector[expr.Key] = expr.Values[0]
case LabelSelectorOpNotIn, LabelSelectorOpExists, LabelSelectorOpDoesNotExist:
return selector, fmt.Errorf("operator %q cannot be converted into the old label selector format", expr.Operator)
default:
return selector, fmt.Errorf("%q is not a valid selector operator", expr.Operator)
}
}
return selector, nil
}
// ParseToLabelSelector parses a string representing a selector into a LabelSelector object.
// Note: This function should be kept in sync with the parser in pkg/labels/selector.go
func ParseToLabelSelector(selector string) (*LabelSelector, error) {
reqs, err := labels.ParseToRequirements(selector)
if err != nil {
return nil, fmt.Errorf("couldn't parse the selector string \"%s\": %v", selector, err)
}
labelSelector := &LabelSelector{
MatchLabels: map[string]string{},
MatchExpressions: []LabelSelectorRequirement{},
}
for _, req := range reqs {
var op LabelSelectorOperator
switch req.Operator() {
case selection.Equals, selection.DoubleEquals:
vals := req.Values()
if vals.Len() != 1 {
return nil, fmt.Errorf("equals operator must have exactly one value")
}
val, ok := vals.PopAny()
if !ok {
return nil, fmt.Errorf("equals operator has exactly one value but it cannot be retrieved")
}
labelSelector.MatchLabels[req.Key()] = val
continue
case selection.In:
op = LabelSelectorOpIn
case selection.NotIn:
op = LabelSelectorOpNotIn
case selection.Exists:
op = LabelSelectorOpExists
case selection.DoesNotExist:
op = LabelSelectorOpDoesNotExist
case selection.GreaterThan, selection.LessThan:
// Adding a separate case for these operators to indicate that this is deliberate
return nil, fmt.Errorf("%q isn't supported in label selectors", req.Operator())
default:
return nil, fmt.Errorf("%q is not a valid label selector operator", req.Operator())
}
labelSelector.MatchExpressions = append(labelSelector.MatchExpressions, LabelSelectorRequirement{
Key: req.Key(),
Operator: op,
Values: req.Values().List(),
})
}
return labelSelector, nil
}
// SetAsLabelSelector converts the labels.Set object into a LabelSelector api object.
func SetAsLabelSelector(ls labels.Set) *LabelSelector {
if ls == nil {
return nil
}
selector := &LabelSelector{
MatchLabels: make(map[string]string),
}
for label, value := range ls {
selector.MatchLabels[label] = value
}
return selector
}
// FormatLabelSelector convert labelSelector into plain string
func FormatLabelSelector(labelSelector *LabelSelector) string {
selector, err := LabelSelectorAsSelector(labelSelector)
if err != nil {
return "<error>"
}
l := selector.String()
if len(l) == 0 {
l = "<none>"
}
return l
}
func ExtractGroupVersions(l *APIGroupList) []string {
var groupVersions []string
for _, g := range l.Groups {
for _, gv := range g.Versions {
groupVersions = append(groupVersions, gv.GroupVersion)
}
}
return groupVersions
}

View file

@ -1,62 +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 unversioned
// ListMetaAccessor retrieves the list interface from an object
// TODO: move this, and TypeMeta and ListMeta, to a different package
type ListMetaAccessor interface {
GetListMeta() List
}
// List lets you work with list metadata from any of the versioned or
// internal API objects. Attempting to set or retrieve a field on an object that does
// not support that field will be a no-op and return a default value.
// TODO: move this, and TypeMeta and ListMeta, to a different package
type List interface {
GetResourceVersion() string
SetResourceVersion(version string)
GetSelfLink() string
SetSelfLink(selfLink string)
}
// Type exposes the type and APIVersion of versioned or internal API objects.
// TODO: move this, and TypeMeta and ListMeta, to a different package
type Type interface {
GetAPIVersion() string
SetAPIVersion(version string)
GetKind() string
SetKind(kind string)
}
func (meta *ListMeta) GetResourceVersion() string { return meta.ResourceVersion }
func (meta *ListMeta) SetResourceVersion(version string) { meta.ResourceVersion = version }
func (meta *ListMeta) GetSelfLink() string { return meta.SelfLink }
func (meta *ListMeta) SetSelfLink(selfLink string) { meta.SelfLink = selfLink }
func (obj *TypeMeta) GetObjectKind() ObjectKind { return obj }
// SetGroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta
func (obj *TypeMeta) SetGroupVersionKind(gvk GroupVersionKind) {
obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind()
}
// GroupVersionKind satisfies the ObjectKind interface for all objects that embed TypeMeta
func (obj *TypeMeta) GroupVersionKind() GroupVersionKind {
return FromAPIVersionAndKind(obj.APIVersion, obj.Kind)
}
func (obj *ListMeta) GetListMeta() List { return obj }

View file

@ -1,25 +0,0 @@
/*
Copyright 2014 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 unversioned
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = GroupVersion{Group: "", Version: ""}
// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}

View file

@ -1,180 +0,0 @@
/*
Copyright 2014 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 unversioned
import (
"encoding/json"
"time"
"k8s.io/client-go/pkg/genericapiserver/openapi/common"
"github.com/go-openapi/spec"
"github.com/google/gofuzz"
)
// 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
type Time struct {
time.Time `protobuf:"-"`
}
// DeepCopy returns a deep-copy of the Time value. The underlying time.Time
// type is effectively immutable in the time API, so it is safe to
// copy-by-assign, despite the presence of (unexported) Pointer fields.
func (t Time) DeepCopy() Time {
return t
}
// String returns the representation of the time.
func (t Time) String() string {
return t.Time.String()
}
// NewTime returns a wrapped instance of the provided time
func NewTime(time time.Time) Time {
return Time{time}
}
// Date returns the Time corresponding to the supplied parameters
// by wrapping time.Date.
func Date(year int, month time.Month, day, hour, min, sec, nsec int, loc *time.Location) Time {
return Time{time.Date(year, month, day, hour, min, sec, nsec, loc)}
}
// Now returns the current local time.
func Now() Time {
return Time{time.Now()}
}
// IsZero returns true if the value is nil or time is zero.
func (t *Time) IsZero() bool {
if t == nil {
return true
}
return t.Time.IsZero()
}
// Before reports whether the time instant t is before u.
func (t Time) Before(u Time) bool {
return t.Time.Before(u.Time)
}
// Equal reports whether the time instant t is equal to u.
func (t Time) Equal(u Time) bool {
return t.Time.Equal(u.Time)
}
// Unix returns the local time corresponding to the given Unix time
// by wrapping time.Unix.
func Unix(sec int64, nsec int64) Time {
return Time{time.Unix(sec, nsec)}
}
// Rfc3339Copy returns a copy of the Time at second-level precision.
func (t Time) Rfc3339Copy() Time {
copied, _ := time.Parse(time.RFC3339, t.Format(time.RFC3339))
return Time{copied}
}
// UnmarshalJSON implements the json.Unmarshaller interface.
func (t *Time) UnmarshalJSON(b []byte) error {
if len(b) == 4 && string(b) == "null" {
t.Time = time.Time{}
return nil
}
var str string
json.Unmarshal(b, &str)
pt, err := time.Parse(time.RFC3339, str)
if err != nil {
return err
}
t.Time = pt.Local()
return nil
}
// UnmarshalQueryParameter converts from a URL query parameter value to an object
func (t *Time) UnmarshalQueryParameter(str string) error {
if len(str) == 0 {
t.Time = time.Time{}
return nil
}
// Tolerate requests from older clients that used JSON serialization to build query params
if len(str) == 4 && str == "null" {
t.Time = time.Time{}
return nil
}
pt, err := time.Parse(time.RFC3339, str)
if err != nil {
return err
}
t.Time = pt.Local()
return nil
}
// MarshalJSON implements the json.Marshaler interface.
func (t Time) MarshalJSON() ([]byte, error) {
if t.IsZero() {
// Encode unset/nil objects as JSON's "null".
return []byte("null"), nil
}
return json.Marshal(t.UTC().Format(time.RFC3339))
}
func (_ Time) OpenAPIDefinition() common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "date-time",
},
},
}
}
// MarshalQueryParameter converts to a URL query parameter value
func (t Time) MarshalQueryParameter() (string, error) {
if t.IsZero() {
// Encode unset/nil objects as an empty string
return "", nil
}
return t.UTC().Format(time.RFC3339), nil
}
// Fuzz satisfies fuzz.Interface.
func (t *Time) Fuzz(c fuzz.Continue) {
if t == nil {
return
}
// Allow for about 1000 years of randomness. Leave off nanoseconds
// because JSON doesn't represent them so they can't round-trip
// properly.
t.Time = time.Unix(c.Rand.Int63n(1000*365*24*60*60), 0)
}
var _ fuzz.Interface = &Time{}

View file

@ -1,85 +0,0 @@
/*
Copyright 2015 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 unversioned
import (
"time"
)
// Timestamp is a struct that is equivalent to Time, but intended for
// protobuf marshalling/unmarshalling. It is generated into a serialization
// that matches Time. Do not use in Go structs.
type Timestamp struct {
// Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive.
Seconds int64 `json:"seconds" protobuf:"varint,1,opt,name=seconds"`
// Non-negative fractions of a second at nanosecond resolution. Negative
// second values with fractions must still have non-negative nanos values
// that count forward in time. Must be from 0 to 999,999,999
// inclusive. This field may be limited in precision depending on context.
Nanos int32 `json:"nanos" protobuf:"varint,2,opt,name=nanos"`
}
// Timestamp returns the Time as a new Timestamp value.
func (m *Time) ProtoTime() *Timestamp {
if m == nil {
return &Timestamp{}
}
return &Timestamp{
Seconds: m.Time.Unix(),
Nanos: int32(m.Time.Nanosecond()),
}
}
// Size implements the protobuf marshalling interface.
func (m *Time) Size() (n int) {
if m == nil || m.Time.IsZero() {
return 0
}
return m.ProtoTime().Size()
}
// Reset implements the protobuf marshalling interface.
func (m *Time) Unmarshal(data []byte) error {
if len(data) == 0 {
m.Time = time.Time{}
return nil
}
p := Timestamp{}
if err := p.Unmarshal(data); err != nil {
return err
}
m.Time = time.Unix(p.Seconds, int64(p.Nanos)).Local()
return nil
}
// Marshal implements the protobuf marshalling interface.
func (m *Time) Marshal() (data []byte, err error) {
if m == nil || m.Time.IsZero() {
return nil, nil
}
return m.ProtoTime().Marshal()
}
// MarshalTo implements the protobuf marshalling interface.
func (m *Time) MarshalTo(data []byte) (int, error) {
if m == nil || m.Time.IsZero() {
return 0, nil
}
return m.ProtoTime().MarshalTo(data)
}

View file

@ -1,482 +0,0 @@
/*
Copyright 2015 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 unversioned contains API types that are common to all versions.
//
// The package contains two categories of types:
// - external (serialized) types that lack their own version (e.g TypeMeta)
// - internal (never-serialized) types that are needed by several different
// api groups, and so live here, to avoid duplication and/or import loops
// (e.g. LabelSelector).
// In the future, we will probably move these categories of objects into
// separate packages.
package unversioned
import "strings"
// 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.
type TypeMeta struct {
// Kind is a string value representing the REST resource this object represents.
// Servers may infer this from the endpoint the client submits requests to.
// Cannot be updated.
// In CamelCase.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
// +optional
Kind string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"`
// APIVersion defines the versioned schema of this representation of an object.
// Servers should convert recognized schemas to the latest internal value, and
// may reject unrecognized values.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources
// +optional
APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,2,opt,name=apiVersion"`
}
// ListMeta describes metadata that synthetic resources must have, including lists and
// various status objects. A resource may have only one of {ObjectMeta, ListMeta}.
type ListMeta struct {
// SelfLink is a URL representing this object.
// Populated by the system.
// Read-only.
// +optional
SelfLink string `json:"selfLink,omitempty" protobuf:"bytes,1,opt,name=selfLink"`
// 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: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#concurrency-control-and-consistency
// +optional
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,2,opt,name=resourceVersion"`
}
// ExportOptions is the query options to the standard REST get call.
type ExportOptions struct {
TypeMeta `json:",inline"`
// Should this value be exported. Export strips fields that a user can not specify.`
Export bool `json:"export" protobuf:"varint,1,opt,name=export"`
// Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'
Exact bool `json:"exact" protobuf:"varint,2,opt,name=exact"`
}
// Status is a return value for calls that don't return other objects.
type Status struct {
TypeMeta `json:",inline"`
// Standard list metadata.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
// +optional
ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Status of the operation.
// One of: "Success" or "Failure".
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status
// +optional
Status string `json:"status,omitempty" protobuf:"bytes,2,opt,name=status"`
// A human-readable description of the status of this operation.
// +optional
Message string `json:"message,omitempty" protobuf:"bytes,3,opt,name=message"`
// A machine-readable description of why this operation is in the
// "Failure" status. If this value is empty there
// is no information available. A Reason clarifies an HTTP status
// code but does not override it.
// +optional
Reason StatusReason `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason,casttype=StatusReason"`
// Extended data associated with the reason. Each reason may define its
// own extended details. This field is optional and the data returned
// is not guaranteed to conform to any schema except that defined by
// the reason type.
// +optional
Details *StatusDetails `json:"details,omitempty" protobuf:"bytes,5,opt,name=details"`
// Suggested HTTP return code for this status, 0 if not set.
// +optional
Code int32 `json:"code,omitempty" protobuf:"varint,6,opt,name=code"`
}
// StatusDetails is a set of additional properties that MAY be set by the
// server to provide additional information about a response. The Reason
// field of a Status object defines what attributes will be set. Clients
// must ignore fields that do not match the defined type of each attribute,
// and should assume that any attribute may be empty, invalid, or under
// defined.
type StatusDetails struct {
// The name attribute of the resource associated with the status StatusReason
// (when there is a single name which can be described).
// +optional
Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`
// The group attribute of the resource associated with the status StatusReason.
// +optional
Group string `json:"group,omitempty" protobuf:"bytes,2,opt,name=group"`
// The kind attribute of the resource associated with the status StatusReason.
// On some operations may differ from the requested resource Kind.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
// +optional
Kind string `json:"kind,omitempty" protobuf:"bytes,3,opt,name=kind"`
// The Causes array includes more details associated with the StatusReason
// failure. Not all StatusReasons may provide detailed causes.
// +optional
Causes []StatusCause `json:"causes,omitempty" protobuf:"bytes,4,rep,name=causes"`
// If specified, the time in seconds before the operation should be retried.
// +optional
RetryAfterSeconds int32 `json:"retryAfterSeconds,omitempty" protobuf:"varint,5,opt,name=retryAfterSeconds"`
}
// Values of Status.Status
const (
StatusSuccess = "Success"
StatusFailure = "Failure"
)
// StatusReason is an enumeration of possible failure causes. Each StatusReason
// must map to a single HTTP status code, but multiple reasons may map
// to the same HTTP status code.
// TODO: move to apiserver
type StatusReason string
const (
// StatusReasonUnknown means the server has declined to indicate a specific reason.
// The details field may contain other information about this error.
// Status code 500.
StatusReasonUnknown StatusReason = ""
// StatusReasonUnauthorized means the server can be reached and understood the request, but requires
// the user to present appropriate authorization credentials (identified by the WWW-Authenticate header)
// in order for the action to be completed. If the user has specified credentials on the request, the
// server considers them insufficient.
// Status code 401
StatusReasonUnauthorized StatusReason = "Unauthorized"
// StatusReasonForbidden means the server can be reached and understood the request, but refuses
// to take any further action. It is the result of the server being configured to deny access for some reason
// to the requested resource by the client.
// Details (optional):
// "kind" string - the kind attribute of the forbidden resource
// on some operations may differ from the requested
// resource.
// "id" string - the identifier of the forbidden resource
// Status code 403
StatusReasonForbidden StatusReason = "Forbidden"
// StatusReasonNotFound means one or more resources required for this operation
// could not be found.
// Details (optional):
// "kind" string - the kind attribute of the missing resource
// on some operations may differ from the requested
// resource.
// "id" string - the identifier of the missing resource
// Status code 404
StatusReasonNotFound StatusReason = "NotFound"
// StatusReasonAlreadyExists means the resource you are creating already exists.
// Details (optional):
// "kind" string - the kind attribute of the conflicting resource
// "id" string - the identifier of the conflicting resource
// Status code 409
StatusReasonAlreadyExists StatusReason = "AlreadyExists"
// StatusReasonConflict means the requested operation cannot be completed
// due to a conflict in the operation. The client may need to alter the
// request. Each resource may define custom details that indicate the
// nature of the conflict.
// Status code 409
StatusReasonConflict StatusReason = "Conflict"
// StatusReasonGone means the item is no longer available at the server and no
// forwarding address is known.
// Status code 410
StatusReasonGone StatusReason = "Gone"
// StatusReasonInvalid means the requested create or update operation cannot be
// completed due to invalid data provided as part of the request. The client may
// need to alter the request. When set, the client may use the StatusDetails
// message field as a summary of the issues encountered.
// Details (optional):
// "kind" string - the kind attribute of the invalid resource
// "id" string - the identifier of the invalid resource
// "causes" - one or more StatusCause entries indicating the data in the
// provided resource that was invalid. The code, message, and
// field attributes will be set.
// Status code 422
StatusReasonInvalid StatusReason = "Invalid"
// StatusReasonServerTimeout means the server can be reached and understood the request,
// but cannot complete the action in a reasonable time. The client should retry the request.
// This is may be due to temporary server load or a transient communication issue with
// another server. Status code 500 is used because the HTTP spec provides no suitable
// server-requested client retry and the 5xx class represents actionable errors.
// Details (optional):
// "kind" string - the kind attribute of the resource being acted on.
// "id" string - the operation that is being attempted.
// "retryAfterSeconds" int32 - the number of seconds before the operation should be retried
// Status code 500
StatusReasonServerTimeout StatusReason = "ServerTimeout"
// StatusReasonTimeout means that the request could not be completed within the given time.
// Clients can get this response only when they specified a timeout param in the request,
// or if the server cannot complete the operation within a reasonable amount of time.
// The request might succeed with an increased value of timeout param. The client *should*
// wait at least the number of seconds specified by the retryAfterSeconds field.
// Details (optional):
// "retryAfterSeconds" int32 - the number of seconds before the operation should be retried
// Status code 504
StatusReasonTimeout StatusReason = "Timeout"
// StatusReasonBadRequest means that the request itself was invalid, because the request
// doesn't make any sense, for example deleting a read-only object. This is different than
// StatusReasonInvalid above which indicates that the API call could possibly succeed, but the
// data was invalid. API calls that return BadRequest can never succeed.
StatusReasonBadRequest StatusReason = "BadRequest"
// StatusReasonMethodNotAllowed means that the action the client attempted to perform on the
// resource was not supported by the code - for instance, attempting to delete a resource that
// can only be created. API calls that return MethodNotAllowed can never succeed.
StatusReasonMethodNotAllowed StatusReason = "MethodNotAllowed"
// StatusReasonInternalError indicates that an internal error occurred, it is unexpected
// and the outcome of the call is unknown.
// Details (optional):
// "causes" - The original error
// Status code 500
StatusReasonInternalError StatusReason = "InternalError"
// StatusReasonExpired indicates that the request is invalid because the content you are requesting
// has expired and is no longer available. It is typically associated with watches that can't be
// serviced.
// Status code 410 (gone)
StatusReasonExpired StatusReason = "Expired"
// StatusReasonServiceUnavailable means that the request itself was valid,
// but the requested service is unavailable at this time.
// Retrying the request after some time might succeed.
// Status code 503
StatusReasonServiceUnavailable StatusReason = "ServiceUnavailable"
)
// StatusCause provides more information about an api.Status failure, including
// cases when multiple errors are encountered.
type StatusCause struct {
// A machine-readable description of the cause of the error. If this value is
// empty there is no information available.
// +optional
Type CauseType `json:"reason,omitempty" protobuf:"bytes,1,opt,name=reason,casttype=CauseType"`
// A human-readable description of the cause of the error. This field may be
// presented as-is to a reader.
// +optional
Message string `json:"message,omitempty" protobuf:"bytes,2,opt,name=message"`
// The field of the resource that has caused this error, as named by its JSON
// serialization. May include dot and postfix notation for nested attributes.
// 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"
// +optional
Field string `json:"field,omitempty" protobuf:"bytes,3,opt,name=field"`
}
// CauseType is a machine readable value providing more detail about what
// occurred in a status response. An operation may have multiple causes for a
// status (whether Failure or Success).
type CauseType string
const (
// CauseTypeFieldValueNotFound is used to report failure to find a requested value
// (e.g. looking up an ID).
CauseTypeFieldValueNotFound CauseType = "FieldValueNotFound"
// CauseTypeFieldValueRequired is used to report required values that are not
// provided (e.g. empty strings, null values, or empty arrays).
CauseTypeFieldValueRequired CauseType = "FieldValueRequired"
// CauseTypeFieldValueDuplicate is used to report collisions of values that must be
// unique (e.g. unique IDs).
CauseTypeFieldValueDuplicate CauseType = "FieldValueDuplicate"
// CauseTypeFieldValueInvalid is used to report malformed values (e.g. failed regex
// match).
CauseTypeFieldValueInvalid CauseType = "FieldValueInvalid"
// CauseTypeFieldValueNotSupported is used to report valid (as per formatting rules)
// values that can not be handled (e.g. an enumerated string).
CauseTypeFieldValueNotSupported CauseType = "FieldValueNotSupported"
// CauseTypeUnexpectedServerResponse is used to report when the server responded to the client
// 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"
)
// 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
type APIVersions struct {
TypeMeta `json:",inline"`
// versions are the api versions that are available.
Versions []string `json:"versions" protobuf:"bytes,1,rep,name=versions"`
// a map of client CIDR to server address that is serving this group.
// This is to help clients reach servers in the most network-efficient way possible.
// Clients can use the appropriate server address as per the CIDR that they match.
// In case of multiple matches, clients should use the longest matching CIDR.
// The server returns only those CIDRs that it thinks that the client can match.
// For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP.
// Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.
ServerAddressByClientCIDRs []ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs" protobuf:"bytes,2,rep,name=serverAddressByClientCIDRs"`
}
// APIGroupList is a list of APIGroup, to allow clients to discover the API at
// /apis.
type APIGroupList struct {
TypeMeta `json:",inline"`
// groups is a list of APIGroup.
Groups []APIGroup `json:"groups" protobuf:"bytes,1,rep,name=groups"`
}
// APIGroup contains the name, the supported versions, and the preferred version
// of a group.
type APIGroup struct {
TypeMeta `json:",inline"`
// name is the name of the group.
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
// versions are the versions supported in this group.
Versions []GroupVersionForDiscovery `json:"versions" protobuf:"bytes,2,rep,name=versions"`
// preferredVersion is the version preferred by the API server, which
// probably is the storage version.
// +optional
PreferredVersion GroupVersionForDiscovery `json:"preferredVersion,omitempty" protobuf:"bytes,3,opt,name=preferredVersion"`
// a map of client CIDR to server address that is serving this group.
// This is to help clients reach servers in the most network-efficient way possible.
// Clients can use the appropriate server address as per the CIDR that they match.
// In case of multiple matches, clients should use the longest matching CIDR.
// The server returns only those CIDRs that it thinks that the client can match.
// For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP.
// Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.
ServerAddressByClientCIDRs []ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs" protobuf:"bytes,4,rep,name=serverAddressByClientCIDRs"`
}
// ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match.
type ServerAddressByClientCIDR struct {
// The CIDR with which clients can match their IP to figure out the server address that they should use.
ClientCIDR string `json:"clientCIDR" protobuf:"bytes,1,opt,name=clientCIDR"`
// Address of this server, suitable for a client that matches the above CIDR.
// This can be a hostname, hostname:port, IP or IP:port.
ServerAddress string `json:"serverAddress" protobuf:"bytes,2,opt,name=serverAddress"`
}
// GroupVersion contains the "group/version" and "version" string of a version.
// It is made a struct to keep extensibility.
type GroupVersionForDiscovery struct {
// groupVersion specifies the API group and version in the form "group/version"
GroupVersion string `json:"groupVersion" protobuf:"bytes,1,opt,name=groupVersion"`
// version specifies the version in the form of "version". This is to save
// the clients the trouble of splitting the GroupVersion.
Version string `json:"version" protobuf:"bytes,2,opt,name=version"`
}
// APIResource specifies the name of a resource and whether it is namespaced.
type APIResource struct {
// name is the name of the resource.
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
// namespaced indicates if a resource is namespaced or not.
Namespaced bool `json:"namespaced" protobuf:"varint,2,opt,name=namespaced"`
// kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')
Kind string `json:"kind" protobuf:"bytes,3,opt,name=kind"`
}
// APIResourceList is a list of APIResource, it is used to expose the name of the
// resources supported in a specific group and version, and if the resource
// is namespaced.
type APIResourceList struct {
TypeMeta `json:",inline"`
// groupVersion is the group and version this APIResourceList is for.
GroupVersion string `json:"groupVersion" protobuf:"bytes,1,opt,name=groupVersion"`
// resources contains the name of the resources and if they are namespaced.
APIResources []APIResource `json:"resources" protobuf:"bytes,2,rep,name=resources"`
}
// RootPaths lists the paths available at root.
// For example: "/healthz", "/apis".
type RootPaths struct {
// paths are the paths available at root.
Paths []string `json:"paths" protobuf:"bytes,1,rep,name=paths"`
}
// TODO: remove me when watch is refactored
func LabelSelectorQueryParam(version string) string {
return "labelSelector"
}
// TODO: remove me when watch is refactored
func FieldSelectorQueryParam(version string) string {
return "fieldSelector"
}
// String returns available api versions as a human-friendly version string.
func (apiVersions APIVersions) String() string {
return strings.Join(apiVersions.Versions, ",")
}
func (apiVersions APIVersions) GoString() string {
return apiVersions.String()
}
// Patch is provided to give a concrete name and type to the Kubernetes PATCH request body.
type Patch struct{}
// Note:
// There are two different styles of label selectors used in versioned types:
// an older style which is represented as just a string in versioned types, and a
// newer style that is structured. LabelSelector is an internal representation for the
// latter style.
// A label selector is a label query over a set of resources. The result of matchLabels and
// matchExpressions are ANDed. An empty label selector matches all objects. A null
// label selector matches no objects.
type LabelSelector struct {
// matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
// map is equivalent to an element of matchExpressions, whose key field is "key", the
// operator is "In", and the values array contains only "value". The requirements are ANDed.
// +optional
MatchLabels map[string]string `json:"matchLabels,omitempty" protobuf:"bytes,1,rep,name=matchLabels"`
// matchExpressions is a list of label selector requirements. The requirements are ANDed.
// +optional
MatchExpressions []LabelSelectorRequirement `json:"matchExpressions,omitempty" protobuf:"bytes,2,rep,name=matchExpressions"`
}
// A label selector requirement is a selector that contains values, a key, and an operator that
// relates the key and values.
type LabelSelectorRequirement struct {
// key is the label key that the selector applies to.
Key string `json:"key" patchStrategy:"merge" patchMergeKey:"key" protobuf:"bytes,1,opt,name=key"`
// operator represents a key's relationship to a set of values.
// Valid operators ard In, NotIn, Exists and DoesNotExist.
Operator LabelSelectorOperator `json:"operator" protobuf:"bytes,2,opt,name=operator,casttype=LabelSelectorOperator"`
// values is an array of string values. If the operator is In or NotIn,
// the values array must be non-empty. If the operator is Exists or DoesNotExist,
// the values array must be empty. This array is replaced during a strategic
// merge patch.
// +optional
Values []string `json:"values,omitempty" protobuf:"bytes,3,rep,name=values"`
}
// A label selector operator is the set of operators that can be used in a selector requirement.
type LabelSelectorOperator string
const (
LabelSelectorOpIn LabelSelectorOperator = "In"
LabelSelectorOpNotIn LabelSelectorOperator = "NotIn"
LabelSelectorOpExists LabelSelectorOperator = "Exists"
LabelSelectorOpDoesNotExist LabelSelectorOperator = "DoesNotExist"
)

View file

@ -1,208 +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 unversioned
// This file contains a collection of methods that can be used from go-restful to
// generate Swagger API documentation for its models. Please read this PR for more
// information on the implementation: https://github.com/emicklei/go-restful/pull/215
//
// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if
// they are on one line! For multiple line or blocks that you want to ignore use ---.
// Any context after a --- is ignored.
//
// Those methods can be generated by using hack/update-generated-swagger-docs.sh
// AUTO-GENERATED FUNCTIONS START HERE
var map_APIGroup = map[string]string{
"": "APIGroup contains the name, the supported versions, and the preferred version of a group.",
"name": "name is the name of the group.",
"versions": "versions are the versions supported in this group.",
"preferredVersion": "preferredVersion is the version preferred by the API server, which probably is the storage version.",
"serverAddressByClientCIDRs": "a map of client CIDR to server address that is serving this group. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR. The server returns only those CIDRs that it thinks that the client can match. For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.",
}
func (APIGroup) SwaggerDoc() map[string]string {
return map_APIGroup
}
var map_APIGroupList = map[string]string{
"": "APIGroupList is a list of APIGroup, to allow clients to discover the API at /apis.",
"groups": "groups is a list of APIGroup.",
}
func (APIGroupList) SwaggerDoc() map[string]string {
return map_APIGroupList
}
var map_APIResource = map[string]string{
"": "APIResource specifies the name of a resource and whether it is namespaced.",
"name": "name is the name of the resource.",
"namespaced": "namespaced indicates if a resource is namespaced or not.",
"kind": "kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')",
}
func (APIResource) SwaggerDoc() map[string]string {
return map_APIResource
}
var map_APIResourceList = map[string]string{
"": "APIResourceList is a list of APIResource, it is used to expose the name of the resources supported in a specific group and version, and if the resource is namespaced.",
"groupVersion": "groupVersion is the group and version this APIResourceList is for.",
"resources": "resources contains the name of the resources and if they are namespaced.",
}
func (APIResourceList) SwaggerDoc() map[string]string {
return map_APIResourceList
}
var map_APIVersions = map[string]string{
"": "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.",
"versions": "versions are the api versions that are available.",
"serverAddressByClientCIDRs": "a map of client CIDR to server address that is serving this group. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR. The server returns only those CIDRs that it thinks that the client can match. For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP.",
}
func (APIVersions) SwaggerDoc() map[string]string {
return map_APIVersions
}
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'",
}
func (ExportOptions) SwaggerDoc() map[string]string {
return map_ExportOptions
}
var map_GroupVersionForDiscovery = map[string]string{
"": "GroupVersion contains the \"group/version\" and \"version\" string of a version. It is made a struct to keep extensibility.",
"groupVersion": "groupVersion specifies the API group and version in the form \"group/version\"",
"version": "version specifies the version in the form of \"version\". This is to save the clients the trouble of splitting the GroupVersion.",
}
func (GroupVersionForDiscovery) SwaggerDoc() map[string]string {
return map_GroupVersionForDiscovery
}
var map_LabelSelector = map[string]string{
"": "A label selector is a label query over a set of resources. The result of matchLabels and matchExpressions are ANDed. An empty label selector matches all objects. A null label selector matches no objects.",
"matchLabels": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.",
"matchExpressions": "matchExpressions is a list of label selector requirements. The requirements are ANDed.",
}
func (LabelSelector) SwaggerDoc() map[string]string {
return map_LabelSelector
}
var map_LabelSelectorRequirement = map[string]string{
"": "A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values.",
"key": "key is the label key that the selector applies to.",
"operator": "operator represents a key's relationship to a set of values. Valid operators ard In, NotIn, Exists and DoesNotExist.",
"values": "values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch.",
}
func (LabelSelectorRequirement) SwaggerDoc() map[string]string {
return map_LabelSelectorRequirement
}
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: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#concurrency-control-and-consistency",
}
func (ListMeta) SwaggerDoc() map[string]string {
return map_ListMeta
}
var map_Patch = map[string]string{
"": "Patch is provided to give a concrete name and type to the Kubernetes PATCH request body.",
}
func (Patch) SwaggerDoc() map[string]string {
return map_Patch
}
var map_RootPaths = map[string]string{
"": "RootPaths lists the paths available at root. For example: \"/healthz\", \"/apis\".",
"paths": "paths are the paths available at root.",
}
func (RootPaths) SwaggerDoc() map[string]string {
return map_RootPaths
}
var map_ServerAddressByClientCIDR = map[string]string{
"": "ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match.",
"clientCIDR": "The CIDR with which clients can match their IP to figure out the server address that they should use.",
"serverAddress": "Address of this server, suitable for a client that matches the above CIDR. This can be a hostname, hostname:port, IP or IP:port.",
}
func (ServerAddressByClientCIDR) SwaggerDoc() map[string]string {
return map_ServerAddressByClientCIDR
}
var map_Status = map[string]string{
"": "Status is a return value for calls that don't return other objects.",
"metadata": "Standard list metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds",
"status": "Status of the operation. One of: \"Success\" or \"Failure\". More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status",
"message": "A human-readable description of the status of this operation.",
"reason": "A machine-readable description of why this operation is in the \"Failure\" status. If this value is empty there is no information available. A Reason clarifies an HTTP status code but does not override it.",
"details": "Extended data associated with the reason. Each reason may define its own extended details. This field is optional and the data returned is not guaranteed to conform to any schema except that defined by the reason type.",
"code": "Suggested HTTP return code for this status, 0 if not set.",
}
func (Status) SwaggerDoc() map[string]string {
return map_Status
}
var map_StatusCause = map[string]string{
"": "StatusCause provides more information about an api.Status failure, including cases when multiple errors are encountered.",
"reason": "A machine-readable description of the cause of the error. If this value is empty there is no information available.",
"message": "A human-readable description of the cause of the error. This field may be presented as-is to a reader.",
"field": "The field of the resource that has caused this error, as named by its JSON serialization. May include dot and postfix notation for nested attributes. Arrays are zero-indexed. Fields may appear more than once in an array of causes due to fields having multiple errors. Optional.\n\nExamples:\n \"name\" - the field \"name\" on the current resource\n \"items[0].name\" - the field \"name\" on the first array entry in \"items\"",
}
func (StatusCause) SwaggerDoc() map[string]string {
return map_StatusCause
}
var map_StatusDetails = map[string]string{
"": "StatusDetails is a set of additional properties that MAY be set by the server to provide additional information about a response. The Reason field of a Status object defines what attributes will be set. Clients must ignore fields that do not match the defined type of each attribute, and should assume that any attribute may be empty, invalid, or under defined.",
"name": "The name attribute of the resource associated with the status StatusReason (when there is a single name which can be described).",
"group": "The group attribute of the resource associated with the status StatusReason.",
"kind": "The kind attribute of the resource associated with the status StatusReason. On some operations may differ from the requested resource Kind. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds",
"causes": "The Causes array includes more details associated with the StatusReason failure. Not all StatusReasons may provide detailed causes.",
"retryAfterSeconds": "If specified, the time in seconds before the operation should be retried.",
}
func (StatusDetails) SwaggerDoc() map[string]string {
return map_StatusDetails
}
var map_TypeMeta = map[string]string{
"": "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.",
"kind": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds",
"apiVersion": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources",
}
func (TypeMeta) SwaggerDoc() map[string]string {
return map_TypeMeta
}
// AUTO-GENERATED FUNCTIONS END HERE

View file

@ -1,67 +0,0 @@
/*
Copyright 2015 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 unversioned
const (
// If you add a new topology domain here, also consider adding it to the set of default values
// for the scheduler's --failure-domain command-line argument.
LabelHostname = "kubernetes.io/hostname"
LabelZoneFailureDomain = "failure-domain.beta.kubernetes.io/zone"
LabelZoneRegion = "failure-domain.beta.kubernetes.io/region"
LabelInstanceType = "beta.kubernetes.io/instance-type"
LabelOS = "beta.kubernetes.io/os"
LabelArch = "beta.kubernetes.io/arch"
)
// Role labels are applied to Nodes to mark their purpose. In particular, we
// usually want to distinguish the master, so that we can isolate privileged
// pods and operations.
//
// Originally we relied on not registering the master, on the fact that the
// master was Unschedulable, and on static manifests for master components.
// But we now do register masters in many environments, are generally moving
// away from static manifests (for better manageability), and working towards
// deprecating the unschedulable field (replacing it with taints & tolerations
// instead).
//
// Even with tainting, a label remains the easiest way of making a positive
// selection, so that pods can schedule only to master nodes for example, and
// thus installations will likely define a label for their master nodes.
//
// So that we can recognize master nodes in consequent places though (such as
// kubectl get nodes), we encourage installations to use the well-known labels.
// We define NodeLabelRole, which is the preferred form, but we will also recognize
// other forms that are known to be in widespread use (NodeLabelKubeadmAlphaRole).
const (
// NodeLabelRole is the preferred label applied to a Node as a hint that it has a particular purpose (defined by the value).
NodeLabelRole = "kubernetes.io/role"
// NodeLabelKubeadmAlphaRole is a label that kubeadm applies to a Node as a hint that it has a particular purpose.
// Use of NodeLabelRole is preferred.
NodeLabelKubeadmAlphaRole = "kubeadm.alpha.kubernetes.io/role"
// NodeLabelRoleMaster is the value of a NodeLabelRole or NodeLabelKubeadmAlphaRole label, indicating a master node.
// A master node typically runs kubernetes system components and will not typically run user workloads.
NodeLabelRoleMaster = "master"
// NodeLabelRoleNode is the value of a NodeLabelRole or NodeLabelKubeadmAlphaRole label, indicating a "normal" node,
// as opposed to a RoleMaster node.
NodeLabelRoleNode = "node"
)

View file

@ -1,390 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package unversioned
import (
conversion "k8s.io/client-go/pkg/conversion"
time "time"
)
func DeepCopy_unversioned_APIGroup(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*APIGroup)
out := out.(*APIGroup)
out.TypeMeta = in.TypeMeta
out.Name = in.Name
if in.Versions != nil {
in, out := &in.Versions, &out.Versions
*out = make([]GroupVersionForDiscovery, len(*in))
for i := range *in {
(*out)[i] = (*in)[i]
}
} else {
out.Versions = nil
}
out.PreferredVersion = in.PreferredVersion
if in.ServerAddressByClientCIDRs != nil {
in, out := &in.ServerAddressByClientCIDRs, &out.ServerAddressByClientCIDRs
*out = make([]ServerAddressByClientCIDR, len(*in))
for i := range *in {
(*out)[i] = (*in)[i]
}
} else {
out.ServerAddressByClientCIDRs = nil
}
return nil
}
}
func DeepCopy_unversioned_APIGroupList(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*APIGroupList)
out := out.(*APIGroupList)
out.TypeMeta = in.TypeMeta
if in.Groups != nil {
in, out := &in.Groups, &out.Groups
*out = make([]APIGroup, len(*in))
for i := range *in {
if err := DeepCopy_unversioned_APIGroup(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.Groups = nil
}
return nil
}
}
func DeepCopy_unversioned_APIResource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*APIResource)
out := out.(*APIResource)
out.Name = in.Name
out.Namespaced = in.Namespaced
out.Kind = in.Kind
return nil
}
}
func DeepCopy_unversioned_APIResourceList(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*APIResourceList)
out := out.(*APIResourceList)
out.TypeMeta = in.TypeMeta
out.GroupVersion = in.GroupVersion
if in.APIResources != nil {
in, out := &in.APIResources, &out.APIResources
*out = make([]APIResource, len(*in))
for i := range *in {
(*out)[i] = (*in)[i]
}
} else {
out.APIResources = nil
}
return nil
}
}
func DeepCopy_unversioned_APIVersions(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*APIVersions)
out := out.(*APIVersions)
out.TypeMeta = in.TypeMeta
if in.Versions != nil {
in, out := &in.Versions, &out.Versions
*out = make([]string, len(*in))
copy(*out, *in)
} else {
out.Versions = nil
}
if in.ServerAddressByClientCIDRs != nil {
in, out := &in.ServerAddressByClientCIDRs, &out.ServerAddressByClientCIDRs
*out = make([]ServerAddressByClientCIDR, len(*in))
for i := range *in {
(*out)[i] = (*in)[i]
}
} else {
out.ServerAddressByClientCIDRs = nil
}
return nil
}
}
func DeepCopy_unversioned_Duration(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*Duration)
out := out.(*Duration)
out.Duration = in.Duration
return nil
}
}
func DeepCopy_unversioned_ExportOptions(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ExportOptions)
out := out.(*ExportOptions)
out.TypeMeta = in.TypeMeta
out.Export = in.Export
out.Exact = in.Exact
return nil
}
}
func DeepCopy_unversioned_GroupKind(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*GroupKind)
out := out.(*GroupKind)
out.Group = in.Group
out.Kind = in.Kind
return nil
}
}
func DeepCopy_unversioned_GroupResource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*GroupResource)
out := out.(*GroupResource)
out.Group = in.Group
out.Resource = in.Resource
return nil
}
}
func DeepCopy_unversioned_GroupVersion(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*GroupVersion)
out := out.(*GroupVersion)
out.Group = in.Group
out.Version = in.Version
return nil
}
}
func DeepCopy_unversioned_GroupVersionForDiscovery(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*GroupVersionForDiscovery)
out := out.(*GroupVersionForDiscovery)
out.GroupVersion = in.GroupVersion
out.Version = in.Version
return nil
}
}
func DeepCopy_unversioned_GroupVersionKind(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*GroupVersionKind)
out := out.(*GroupVersionKind)
out.Group = in.Group
out.Version = in.Version
out.Kind = in.Kind
return nil
}
}
func DeepCopy_unversioned_GroupVersionResource(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*GroupVersionResource)
out := out.(*GroupVersionResource)
out.Group = in.Group
out.Version = in.Version
out.Resource = in.Resource
return nil
}
}
func DeepCopy_unversioned_LabelSelector(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*LabelSelector)
out := out.(*LabelSelector)
if in.MatchLabels != nil {
in, out := &in.MatchLabels, &out.MatchLabels
*out = make(map[string]string)
for key, val := range *in {
(*out)[key] = val
}
} else {
out.MatchLabels = nil
}
if in.MatchExpressions != nil {
in, out := &in.MatchExpressions, &out.MatchExpressions
*out = make([]LabelSelectorRequirement, len(*in))
for i := range *in {
if err := DeepCopy_unversioned_LabelSelectorRequirement(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.MatchExpressions = nil
}
return nil
}
}
func DeepCopy_unversioned_LabelSelectorRequirement(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*LabelSelectorRequirement)
out := out.(*LabelSelectorRequirement)
out.Key = in.Key
out.Operator = in.Operator
if in.Values != nil {
in, out := &in.Values, &out.Values
*out = make([]string, len(*in))
copy(*out, *in)
} else {
out.Values = nil
}
return nil
}
}
func DeepCopy_unversioned_ListMeta(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ListMeta)
out := out.(*ListMeta)
out.SelfLink = in.SelfLink
out.ResourceVersion = in.ResourceVersion
return nil
}
}
func DeepCopy_unversioned_Patch(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*Patch)
out := out.(*Patch)
_ = in
_ = out
return nil
}
}
func DeepCopy_unversioned_RootPaths(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*RootPaths)
out := out.(*RootPaths)
if in.Paths != nil {
in, out := &in.Paths, &out.Paths
*out = make([]string, len(*in))
copy(*out, *in)
} else {
out.Paths = nil
}
return nil
}
}
func DeepCopy_unversioned_ServerAddressByClientCIDR(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*ServerAddressByClientCIDR)
out := out.(*ServerAddressByClientCIDR)
out.ClientCIDR = in.ClientCIDR
out.ServerAddress = in.ServerAddress
return nil
}
}
func DeepCopy_unversioned_Status(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*Status)
out := out.(*Status)
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
out.Status = in.Status
out.Message = in.Message
out.Reason = in.Reason
if in.Details != nil {
in, out := &in.Details, &out.Details
*out = new(StatusDetails)
if err := DeepCopy_unversioned_StatusDetails(*in, *out, c); err != nil {
return err
}
} else {
out.Details = nil
}
out.Code = in.Code
return nil
}
}
func DeepCopy_unversioned_StatusCause(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*StatusCause)
out := out.(*StatusCause)
out.Type = in.Type
out.Message = in.Message
out.Field = in.Field
return nil
}
}
func DeepCopy_unversioned_StatusDetails(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*StatusDetails)
out := out.(*StatusDetails)
out.Name = in.Name
out.Group = in.Group
out.Kind = in.Kind
if in.Causes != nil {
in, out := &in.Causes, &out.Causes
*out = make([]StatusCause, len(*in))
for i := range *in {
(*out)[i] = (*in)[i]
}
} else {
out.Causes = nil
}
out.RetryAfterSeconds = in.RetryAfterSeconds
return nil
}
}
func DeepCopy_unversioned_Time(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*Time)
out := out.(*Time)
if newVal, err := c.DeepCopy(&in.Time); err != nil {
return err
} else {
out.Time = *newVal.(*time.Time)
}
return nil
}
}
func DeepCopy_unversioned_Timestamp(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*Timestamp)
out := out.(*Timestamp)
out.Seconds = in.Seconds
out.Nanos = in.Nanos
return nil
}
}
func DeepCopy_unversioned_TypeMeta(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*TypeMeta)
out := out.(*TypeMeta)
out.Kind = in.Kind
out.APIVersion = in.APIVersion
return nil
}
}

View file

@ -1,805 +0,0 @@
/*
Copyright 2015 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 v1
import (
"encoding/json"
"fmt"
"reflect"
"k8s.io/client-go/pkg/api"
"k8s.io/client-go/pkg/apis/extensions"
"k8s.io/client-go/pkg/conversion"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/util/validation/field"
"k8s.io/client-go/pkg/watch/versioned"
)
const (
// Annotation key used to identify mirror pods.
mirrorAnnotationKey = "kubernetes.io/config.mirror"
// Value used to identify mirror pods from pre-v1.1 kubelet.
mirrorAnnotationValue_1_0 = "mirror"
// annotation key prefix used to identify non-convertible json paths.
NonConvertibleAnnotationPrefix = "kubernetes.io/non-convertible"
)
// This is a "fast-path" that avoids reflection for common types. It focuses on the objects that are
// converted the most in the cluster.
// TODO: generate one of these for every external API group - this is to prove the impact
func addFastPathConversionFuncs(scheme *runtime.Scheme) error {
scheme.AddGenericConversionFunc(func(objA, objB interface{}, s conversion.Scope) (bool, error) {
switch a := objA.(type) {
case *Pod:
switch b := objB.(type) {
case *api.Pod:
return true, Convert_v1_Pod_To_api_Pod(a, b, s)
}
case *api.Pod:
switch b := objB.(type) {
case *Pod:
return true, Convert_api_Pod_To_v1_Pod(a, b, s)
}
case *Event:
switch b := objB.(type) {
case *api.Event:
return true, Convert_v1_Event_To_api_Event(a, b, s)
}
case *api.Event:
switch b := objB.(type) {
case *Event:
return true, Convert_api_Event_To_v1_Event(a, b, s)
}
case *ReplicationController:
switch b := objB.(type) {
case *api.ReplicationController:
return true, Convert_v1_ReplicationController_To_api_ReplicationController(a, b, s)
}
case *api.ReplicationController:
switch b := objB.(type) {
case *ReplicationController:
return true, Convert_api_ReplicationController_To_v1_ReplicationController(a, b, s)
}
case *Node:
switch b := objB.(type) {
case *api.Node:
return true, Convert_v1_Node_To_api_Node(a, b, s)
}
case *api.Node:
switch b := objB.(type) {
case *Node:
return true, Convert_api_Node_To_v1_Node(a, b, s)
}
case *Namespace:
switch b := objB.(type) {
case *api.Namespace:
return true, Convert_v1_Namespace_To_api_Namespace(a, b, s)
}
case *api.Namespace:
switch b := objB.(type) {
case *Namespace:
return true, Convert_api_Namespace_To_v1_Namespace(a, b, s)
}
case *Service:
switch b := objB.(type) {
case *api.Service:
return true, Convert_v1_Service_To_api_Service(a, b, s)
}
case *api.Service:
switch b := objB.(type) {
case *Service:
return true, Convert_api_Service_To_v1_Service(a, b, s)
}
case *Endpoints:
switch b := objB.(type) {
case *api.Endpoints:
return true, Convert_v1_Endpoints_To_api_Endpoints(a, b, s)
}
case *api.Endpoints:
switch b := objB.(type) {
case *Endpoints:
return true, Convert_api_Endpoints_To_v1_Endpoints(a, b, s)
}
case *versioned.Event:
switch b := objB.(type) {
case *versioned.InternalEvent:
return true, versioned.Convert_versioned_Event_to_versioned_InternalEvent(a, b, s)
}
case *versioned.InternalEvent:
switch b := objB.(type) {
case *versioned.Event:
return true, versioned.Convert_versioned_InternalEvent_to_versioned_Event(a, b, s)
}
}
return false, nil
})
return nil
}
func addConversionFuncs(scheme *runtime.Scheme) error {
// Add non-generated conversion functions
err := scheme.AddConversionFuncs(
Convert_api_Pod_To_v1_Pod,
Convert_api_PodSpec_To_v1_PodSpec,
Convert_api_ReplicationControllerSpec_To_v1_ReplicationControllerSpec,
Convert_api_ServiceSpec_To_v1_ServiceSpec,
Convert_v1_Pod_To_api_Pod,
Convert_v1_PodSpec_To_api_PodSpec,
Convert_v1_ReplicationControllerSpec_To_api_ReplicationControllerSpec,
Convert_v1_Secret_To_api_Secret,
Convert_v1_ServiceSpec_To_api_ServiceSpec,
Convert_v1_ResourceList_To_api_ResourceList,
Convert_v1_ReplicationController_to_extensions_ReplicaSet,
Convert_v1_ReplicationControllerSpec_to_extensions_ReplicaSetSpec,
Convert_v1_ReplicationControllerStatus_to_extensions_ReplicaSetStatus,
Convert_extensions_ReplicaSet_to_v1_ReplicationController,
Convert_extensions_ReplicaSetSpec_to_v1_ReplicationControllerSpec,
Convert_extensions_ReplicaSetStatus_to_v1_ReplicationControllerStatus,
)
if err != nil {
return err
}
// Add field label conversions for kinds having selectable nothing but ObjectMeta fields.
for _, k := range []string{
"Endpoints",
"ResourceQuota",
"PersistentVolumeClaim",
"Service",
"ServiceAccount",
"ConfigMap",
} {
kind := k // don't close over range variables
err = scheme.AddFieldLabelConversionFunc("v1", kind,
func(label, value string) (string, string, error) {
switch label {
case "metadata.namespace",
"metadata.name":
return label, value, nil
default:
return "", "", fmt.Errorf("field label %q not supported for %q", label, kind)
}
},
)
if err != nil {
return err
}
}
// Add field conversion funcs.
err = scheme.AddFieldLabelConversionFunc("v1", "Pod",
func(label, value string) (string, string, error) {
switch label {
case "metadata.annotations",
"metadata.labels",
"metadata.name",
"metadata.namespace",
"spec.nodeName",
"spec.restartPolicy",
"spec.serviceAccountName",
"status.phase",
"status.podIP":
return label, value, nil
// This is for backwards compatibility with old v1 clients which send spec.host
case "spec.host":
return "spec.nodeName", value, nil
default:
return "", "", fmt.Errorf("field label not supported: %s", label)
}
},
)
if err != nil {
return err
}
err = scheme.AddFieldLabelConversionFunc("v1", "Node",
func(label, value string) (string, string, error) {
switch label {
case "metadata.name":
return label, value, nil
case "spec.unschedulable":
return label, value, nil
default:
return "", "", fmt.Errorf("field label not supported: %s", label)
}
},
)
if err != nil {
return err
}
err = scheme.AddFieldLabelConversionFunc("v1", "ReplicationController",
func(label, value string) (string, string, error) {
switch label {
case "metadata.name",
"metadata.namespace",
"status.replicas":
return label, value, nil
default:
return "", "", fmt.Errorf("field label not supported: %s", label)
}
})
if err != nil {
return err
}
err = scheme.AddFieldLabelConversionFunc("v1", "PersistentVolume",
func(label, value string) (string, string, error) {
switch label {
case "metadata.name":
return label, value, nil
default:
return "", "", fmt.Errorf("field label not supported: %s", label)
}
},
)
if err != nil {
return err
}
if err := AddFieldLabelConversionsForEvent(scheme); err != nil {
return err
}
if err := AddFieldLabelConversionsForNamespace(scheme); err != nil {
return err
}
if err := AddFieldLabelConversionsForSecret(scheme); err != nil {
return err
}
return nil
}
func Convert_v1_ReplicationController_to_extensions_ReplicaSet(in *ReplicationController, out *extensions.ReplicaSet, s conversion.Scope) error {
if err := Convert_v1_ObjectMeta_To_api_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
return err
}
if err := Convert_v1_ReplicationControllerSpec_to_extensions_ReplicaSetSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_v1_ReplicationControllerStatus_to_extensions_ReplicaSetStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
func Convert_v1_ReplicationControllerSpec_to_extensions_ReplicaSetSpec(in *ReplicationControllerSpec, out *extensions.ReplicaSetSpec, s conversion.Scope) error {
out.Replicas = *in.Replicas
if in.Selector != nil {
api.Convert_map_to_unversioned_LabelSelector(&in.Selector, out.Selector, s)
}
if in.Template != nil {
if err := Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(in.Template, &out.Template, s); err != nil {
return err
}
}
return nil
}
func Convert_v1_ReplicationControllerStatus_to_extensions_ReplicaSetStatus(in *ReplicationControllerStatus, out *extensions.ReplicaSetStatus, s conversion.Scope) error {
out.Replicas = in.Replicas
out.FullyLabeledReplicas = in.FullyLabeledReplicas
out.ReadyReplicas = in.ReadyReplicas
out.AvailableReplicas = in.AvailableReplicas
out.ObservedGeneration = in.ObservedGeneration
return nil
}
func Convert_extensions_ReplicaSet_to_v1_ReplicationController(in *extensions.ReplicaSet, out *ReplicationController, s conversion.Scope) error {
if err := Convert_api_ObjectMeta_To_v1_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
return err
}
if err := Convert_extensions_ReplicaSetSpec_to_v1_ReplicationControllerSpec(&in.Spec, &out.Spec, s); err != nil {
fieldErr, ok := err.(*field.Error)
if !ok {
return err
}
if out.Annotations == nil {
out.Annotations = make(map[string]string)
}
out.Annotations[NonConvertibleAnnotationPrefix+"/"+fieldErr.Field] = reflect.ValueOf(fieldErr.BadValue).String()
}
if err := Convert_extensions_ReplicaSetStatus_to_v1_ReplicationControllerStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
func Convert_extensions_ReplicaSetSpec_to_v1_ReplicationControllerSpec(in *extensions.ReplicaSetSpec, out *ReplicationControllerSpec, s conversion.Scope) error {
out.Replicas = new(int32)
*out.Replicas = in.Replicas
out.MinReadySeconds = in.MinReadySeconds
var invalidErr error
if in.Selector != nil {
invalidErr = api.Convert_unversioned_LabelSelector_to_map(in.Selector, &out.Selector, s)
}
out.Template = new(PodTemplateSpec)
if err := Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(&in.Template, out.Template, s); err != nil {
return err
}
return invalidErr
}
func Convert_extensions_ReplicaSetStatus_to_v1_ReplicationControllerStatus(in *extensions.ReplicaSetStatus, out *ReplicationControllerStatus, s conversion.Scope) error {
out.Replicas = in.Replicas
out.FullyLabeledReplicas = in.FullyLabeledReplicas
out.ReadyReplicas = in.ReadyReplicas
out.AvailableReplicas = in.AvailableReplicas
out.ObservedGeneration = in.ObservedGeneration
return nil
}
func Convert_api_ReplicationControllerSpec_To_v1_ReplicationControllerSpec(in *api.ReplicationControllerSpec, out *ReplicationControllerSpec, s conversion.Scope) error {
out.Replicas = &in.Replicas
out.MinReadySeconds = in.MinReadySeconds
out.Selector = in.Selector
if in.Template != nil {
out.Template = new(PodTemplateSpec)
if err := Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(in.Template, out.Template, s); err != nil {
return err
}
} else {
out.Template = nil
}
return nil
}
func Convert_v1_ReplicationControllerSpec_To_api_ReplicationControllerSpec(in *ReplicationControllerSpec, out *api.ReplicationControllerSpec, s conversion.Scope) error {
if in.Replicas != nil {
out.Replicas = *in.Replicas
}
out.MinReadySeconds = in.MinReadySeconds
out.Selector = in.Selector
if in.Template != nil {
out.Template = new(api.PodTemplateSpec)
if err := Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(in.Template, out.Template, s); err != nil {
return err
}
} else {
out.Template = nil
}
return nil
}
func Convert_api_PodStatusResult_To_v1_PodStatusResult(in *api.PodStatusResult, out *PodStatusResult, s conversion.Scope) error {
if err := autoConvert_api_PodStatusResult_To_v1_PodStatusResult(in, out, s); err != nil {
return err
}
if old := out.Annotations; old != nil {
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
}
if len(out.Status.InitContainerStatuses) > 0 {
if out.Annotations == nil {
out.Annotations = make(map[string]string)
}
value, err := json.Marshal(out.Status.InitContainerStatuses)
if err != nil {
return err
}
out.Annotations[PodInitContainerStatusesAnnotationKey] = string(value)
out.Annotations[PodInitContainerStatusesBetaAnnotationKey] = string(value)
} else {
delete(out.Annotations, PodInitContainerStatusesAnnotationKey)
delete(out.Annotations, PodInitContainerStatusesBetaAnnotationKey)
}
return nil
}
func Convert_v1_PodStatusResult_To_api_PodStatusResult(in *PodStatusResult, out *api.PodStatusResult, s conversion.Scope) error {
// TODO: sometime after we move init container to stable, remove these conversions
// If there is a beta annotation, copy to alpha key.
// See commit log for PR #31026 for why we do this.
if valueBeta, okBeta := in.Annotations[PodInitContainerStatusesBetaAnnotationKey]; okBeta {
in.Annotations[PodInitContainerStatusesAnnotationKey] = valueBeta
}
// Move the annotation to the internal repr. field
if value, ok := in.Annotations[PodInitContainerStatusesAnnotationKey]; ok {
var values []ContainerStatus
if err := json.Unmarshal([]byte(value), &values); err != nil {
return err
}
// Conversion from external to internal version exists more to
// satisfy the needs of the decoder than it does to be a general
// purpose tool. And Decode always creates an intermediate object
// to decode to. Thus the caller of UnsafeConvertToVersion is
// taking responsibility to ensure mutation of in is not exposed
// back to the caller.
in.Status.InitContainerStatuses = values
}
if err := autoConvert_v1_PodStatusResult_To_api_PodStatusResult(in, out, s); err != nil {
return err
}
if len(out.Annotations) > 0 {
old := out.Annotations
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
delete(out.Annotations, PodInitContainerStatusesAnnotationKey)
delete(out.Annotations, PodInitContainerStatusesBetaAnnotationKey)
}
return nil
}
func Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(in *api.PodTemplateSpec, out *PodTemplateSpec, s conversion.Scope) error {
if err := autoConvert_api_PodTemplateSpec_To_v1_PodTemplateSpec(in, out, s); err != nil {
return err
}
// TODO: sometime after we move init container to stable, remove these conversions.
if old := out.Annotations; old != nil {
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
}
if len(out.Spec.InitContainers) > 0 {
if out.Annotations == nil {
out.Annotations = make(map[string]string)
}
value, err := json.Marshal(out.Spec.InitContainers)
if err != nil {
return err
}
out.Annotations[PodInitContainersAnnotationKey] = string(value)
out.Annotations[PodInitContainersBetaAnnotationKey] = string(value)
} else {
delete(out.Annotations, PodInitContainersAnnotationKey)
delete(out.Annotations, PodInitContainersBetaAnnotationKey)
}
return nil
}
func Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(in *PodTemplateSpec, out *api.PodTemplateSpec, s conversion.Scope) error {
// TODO: sometime after we move init container to stable, remove these conversions
// If there is a beta annotation, copy to alpha key.
// See commit log for PR #31026 for why we do this.
if valueBeta, okBeta := in.Annotations[PodInitContainersBetaAnnotationKey]; okBeta {
in.Annotations[PodInitContainersAnnotationKey] = valueBeta
}
// Move the annotation to the internal repr. field
if value, ok := in.Annotations[PodInitContainersAnnotationKey]; ok {
var values []Container
if err := json.Unmarshal([]byte(value), &values); err != nil {
return err
}
// Conversion from external to internal version exists more to
// satisfy the needs of the decoder than it does to be a general
// purpose tool. And Decode always creates an intermediate object
// to decode to. Thus the caller of UnsafeConvertToVersion is
// taking responsibility to ensure mutation of in is not exposed
// back to the caller.
in.Spec.InitContainers = values
}
if err := autoConvert_v1_PodTemplateSpec_To_api_PodTemplateSpec(in, out, s); err != nil {
return err
}
if len(out.Annotations) > 0 {
old := out.Annotations
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
delete(out.Annotations, PodInitContainersAnnotationKey)
delete(out.Annotations, PodInitContainersBetaAnnotationKey)
}
return nil
}
// The following two PodSpec conversions are done here to support ServiceAccount
// as an alias for ServiceAccountName.
func Convert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *PodSpec, s conversion.Scope) error {
if err := autoConvert_api_PodSpec_To_v1_PodSpec(in, out, s); err != nil {
return err
}
// DeprecatedServiceAccount is an alias for ServiceAccountName.
out.DeprecatedServiceAccount = in.ServiceAccountName
if in.SecurityContext != nil {
// the host namespace fields have to be handled here for backward compatibility
// with v1.0.0
out.HostPID = in.SecurityContext.HostPID
out.HostNetwork = in.SecurityContext.HostNetwork
out.HostIPC = in.SecurityContext.HostIPC
}
return nil
}
func Convert_v1_PodSpec_To_api_PodSpec(in *PodSpec, out *api.PodSpec, s conversion.Scope) error {
if err := autoConvert_v1_PodSpec_To_api_PodSpec(in, out, s); err != nil {
return err
}
// We support DeprecatedServiceAccount as an alias for ServiceAccountName.
// If both are specified, ServiceAccountName (the new field) wins.
if in.ServiceAccountName == "" {
out.ServiceAccountName = in.DeprecatedServiceAccount
}
// the host namespace fields have to be handled specially for backward compatibility
// with v1.0.0
if out.SecurityContext == nil {
out.SecurityContext = new(api.PodSecurityContext)
}
out.SecurityContext.HostNetwork = in.HostNetwork
out.SecurityContext.HostPID = in.HostPID
out.SecurityContext.HostIPC = in.HostIPC
return nil
}
func Convert_api_Pod_To_v1_Pod(in *api.Pod, out *Pod, s conversion.Scope) error {
if err := autoConvert_api_Pod_To_v1_Pod(in, out, s); err != nil {
return err
}
// TODO: sometime after we move init container to stable, remove these conversions
if len(out.Spec.InitContainers) > 0 || len(out.Status.InitContainerStatuses) > 0 {
old := out.Annotations
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
delete(out.Annotations, PodInitContainersAnnotationKey)
delete(out.Annotations, PodInitContainersBetaAnnotationKey)
delete(out.Annotations, PodInitContainerStatusesAnnotationKey)
delete(out.Annotations, PodInitContainerStatusesBetaAnnotationKey)
}
if len(out.Spec.InitContainers) > 0 {
value, err := json.Marshal(out.Spec.InitContainers)
if err != nil {
return err
}
out.Annotations[PodInitContainersAnnotationKey] = string(value)
out.Annotations[PodInitContainersBetaAnnotationKey] = string(value)
}
if len(out.Status.InitContainerStatuses) > 0 {
value, err := json.Marshal(out.Status.InitContainerStatuses)
if err != nil {
return err
}
out.Annotations[PodInitContainerStatusesAnnotationKey] = string(value)
out.Annotations[PodInitContainerStatusesBetaAnnotationKey] = string(value)
}
// We need to reset certain fields for mirror pods from pre-v1.1 kubelet
// (#15960).
// TODO: Remove this code after we drop support for v1.0 kubelets.
if value, ok := in.Annotations[mirrorAnnotationKey]; ok && value == mirrorAnnotationValue_1_0 {
// Reset the TerminationGracePeriodSeconds.
out.Spec.TerminationGracePeriodSeconds = nil
// Reset the resource requests.
for i := range out.Spec.Containers {
out.Spec.Containers[i].Resources.Requests = nil
}
}
return nil
}
func Convert_v1_Pod_To_api_Pod(in *Pod, out *api.Pod, s conversion.Scope) error {
// If there is a beta annotation, copy to alpha key.
// See commit log for PR #31026 for why we do this.
if valueBeta, okBeta := in.Annotations[PodInitContainersBetaAnnotationKey]; okBeta {
in.Annotations[PodInitContainersAnnotationKey] = valueBeta
}
// TODO: sometime after we move init container to stable, remove these conversions
// Move the annotation to the internal repr. field
if value, ok := in.Annotations[PodInitContainersAnnotationKey]; ok {
var values []Container
if err := json.Unmarshal([]byte(value), &values); err != nil {
return err
}
// Conversion from external to internal version exists more to
// satisfy the needs of the decoder than it does to be a general
// purpose tool. And Decode always creates an intermediate object
// to decode to. Thus the caller of UnsafeConvertToVersion is
// taking responsibility to ensure mutation of in is not exposed
// back to the caller.
in.Spec.InitContainers = values
// Call defaulters explicitly until annotations are removed
for i := range in.Spec.InitContainers {
c := &in.Spec.InitContainers[i]
SetDefaults_Container(c)
}
}
// If there is a beta annotation, copy to alpha key.
// See commit log for PR #31026 for why we do this.
if valueBeta, okBeta := in.Annotations[PodInitContainerStatusesBetaAnnotationKey]; okBeta {
in.Annotations[PodInitContainerStatusesAnnotationKey] = valueBeta
}
if value, ok := in.Annotations[PodInitContainerStatusesAnnotationKey]; ok {
var values []ContainerStatus
if err := json.Unmarshal([]byte(value), &values); err != nil {
return err
}
// Conversion from external to internal version exists more to
// satisfy the needs of the decoder than it does to be a general
// purpose tool. And Decode always creates an intermediate object
// to decode to. Thus the caller of UnsafeConvertToVersion is
// taking responsibility to ensure mutation of in is not exposed
// back to the caller.
in.Status.InitContainerStatuses = values
}
if err := autoConvert_v1_Pod_To_api_Pod(in, out, s); err != nil {
return err
}
if len(out.Annotations) > 0 {
old := out.Annotations
out.Annotations = make(map[string]string, len(old))
for k, v := range old {
out.Annotations[k] = v
}
delete(out.Annotations, PodInitContainersAnnotationKey)
delete(out.Annotations, PodInitContainersBetaAnnotationKey)
delete(out.Annotations, PodInitContainerStatusesAnnotationKey)
delete(out.Annotations, PodInitContainerStatusesBetaAnnotationKey)
}
return nil
}
func Convert_api_ServiceSpec_To_v1_ServiceSpec(in *api.ServiceSpec, out *ServiceSpec, s conversion.Scope) error {
if err := autoConvert_api_ServiceSpec_To_v1_ServiceSpec(in, out, s); err != nil {
return err
}
// Publish both externalIPs and deprecatedPublicIPs fields in v1.
out.DeprecatedPublicIPs = in.ExternalIPs
return nil
}
func Convert_v1_Secret_To_api_Secret(in *Secret, out *api.Secret, s conversion.Scope) error {
if err := autoConvert_v1_Secret_To_api_Secret(in, out, s); err != nil {
return err
}
// StringData overwrites Data
if len(in.StringData) > 0 {
if out.Data == nil {
out.Data = map[string][]byte{}
}
for k, v := range in.StringData {
out.Data[k] = []byte(v)
}
}
return nil
}
func Convert_v1_ServiceSpec_To_api_ServiceSpec(in *ServiceSpec, out *api.ServiceSpec, s conversion.Scope) error {
if err := autoConvert_v1_ServiceSpec_To_api_ServiceSpec(in, out, s); err != nil {
return err
}
// Prefer the legacy deprecatedPublicIPs field, if provided.
if len(in.DeprecatedPublicIPs) > 0 {
out.ExternalIPs = in.DeprecatedPublicIPs
}
return nil
}
func Convert_api_PodSecurityContext_To_v1_PodSecurityContext(in *api.PodSecurityContext, out *PodSecurityContext, s conversion.Scope) error {
out.SupplementalGroups = in.SupplementalGroups
if in.SELinuxOptions != nil {
out.SELinuxOptions = new(SELinuxOptions)
if err := Convert_api_SELinuxOptions_To_v1_SELinuxOptions(in.SELinuxOptions, out.SELinuxOptions, s); err != nil {
return err
}
} else {
out.SELinuxOptions = nil
}
out.RunAsUser = in.RunAsUser
out.RunAsNonRoot = in.RunAsNonRoot
out.FSGroup = in.FSGroup
return nil
}
func Convert_v1_PodSecurityContext_To_api_PodSecurityContext(in *PodSecurityContext, out *api.PodSecurityContext, s conversion.Scope) error {
out.SupplementalGroups = in.SupplementalGroups
if in.SELinuxOptions != nil {
out.SELinuxOptions = new(api.SELinuxOptions)
if err := Convert_v1_SELinuxOptions_To_api_SELinuxOptions(in.SELinuxOptions, out.SELinuxOptions, s); err != nil {
return err
}
} else {
out.SELinuxOptions = nil
}
out.RunAsUser = in.RunAsUser
out.RunAsNonRoot = in.RunAsNonRoot
out.FSGroup = in.FSGroup
return nil
}
// +k8s:conversion-fn=copy-only
func Convert_v1_ResourceList_To_api_ResourceList(in *ResourceList, out *api.ResourceList, s conversion.Scope) error {
if *in == nil {
return nil
}
if *out == nil {
*out = make(api.ResourceList, len(*in))
}
for key, val := range *in {
// Moved to defaults
// TODO(#18538): We round up resource values to milli scale to maintain API compatibility.
// In the future, we should instead reject values that need rounding.
// const milliScale = -3
// val.RoundUp(milliScale)
(*out)[api.ResourceName(key)] = val
}
return nil
}
func AddFieldLabelConversionsForEvent(scheme *runtime.Scheme) error {
return scheme.AddFieldLabelConversionFunc("v1", "Event",
func(label, value string) (string, string, error) {
switch label {
case "involvedObject.kind",
"involvedObject.namespace",
"involvedObject.name",
"involvedObject.uid",
"involvedObject.apiVersion",
"involvedObject.resourceVersion",
"involvedObject.fieldPath",
"reason",
"source",
"type",
"metadata.namespace",
"metadata.name":
return label, value, nil
default:
return "", "", fmt.Errorf("field label not supported: %s", label)
}
})
}
func AddFieldLabelConversionsForNamespace(scheme *runtime.Scheme) error {
return scheme.AddFieldLabelConversionFunc("v1", "Namespace",
func(label, value string) (string, string, error) {
switch label {
case "status.phase",
"metadata.name":
return label, value, nil
default:
return "", "", fmt.Errorf("field label not supported: %s", label)
}
})
}
func AddFieldLabelConversionsForSecret(scheme *runtime.Scheme) error {
return scheme.AddFieldLabelConversionFunc("v1", "Secret",
func(label, value string) (string, string, error) {
switch label {
case "type",
"metadata.namespace",
"metadata.name":
return label, value, nil
default:
return "", "", fmt.Errorf("field label not supported: %s", label)
}
})
}

View file

@ -1,349 +0,0 @@
/*
Copyright 2015 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 v1
import (
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/util"
"k8s.io/client-go/pkg/util/intstr"
"k8s.io/client-go/pkg/util/parsers"
)
func addDefaultingFuncs(scheme *runtime.Scheme) error {
RegisterDefaults(scheme)
return scheme.AddDefaultingFuncs(
SetDefaults_PodExecOptions,
SetDefaults_PodAttachOptions,
SetDefaults_ReplicationController,
SetDefaults_Volume,
SetDefaults_ContainerPort,
SetDefaults_Container,
SetDefaults_ServiceSpec,
SetDefaults_Pod,
SetDefaults_PodSpec,
SetDefaults_Probe,
SetDefaults_SecretVolumeSource,
SetDefaults_ConfigMapVolumeSource,
SetDefaults_DownwardAPIVolumeSource,
SetDefaults_Secret,
SetDefaults_PersistentVolume,
SetDefaults_PersistentVolumeClaim,
SetDefaults_ISCSIVolumeSource,
SetDefaults_Endpoints,
SetDefaults_HTTPGetAction,
SetDefaults_NamespaceStatus,
SetDefaults_Node,
SetDefaults_NodeStatus,
SetDefaults_ObjectFieldSelector,
SetDefaults_LimitRangeItem,
SetDefaults_ConfigMap,
SetDefaults_RBDVolumeSource,
SetDefaults_ResourceList,
)
}
func SetDefaults_ResourceList(obj *ResourceList) {
for key, val := range *obj {
// TODO(#18538): We round up resource values to milli scale to maintain API compatibility.
// In the future, we should instead reject values that need rounding.
const milliScale = -3
val.RoundUp(milliScale)
(*obj)[ResourceName(key)] = val
}
}
func SetDefaults_PodExecOptions(obj *PodExecOptions) {
obj.Stdout = true
obj.Stderr = true
}
func SetDefaults_PodAttachOptions(obj *PodAttachOptions) {
obj.Stdout = true
obj.Stderr = true
}
func SetDefaults_ReplicationController(obj *ReplicationController) {
var labels map[string]string
if obj.Spec.Template != nil {
labels = obj.Spec.Template.Labels
}
// TODO: support templates defined elsewhere when we support them in the API
if labels != nil {
if len(obj.Spec.Selector) == 0 {
obj.Spec.Selector = labels
}
if len(obj.Labels) == 0 {
obj.Labels = labels
}
}
if obj.Spec.Replicas == nil {
obj.Spec.Replicas = new(int32)
*obj.Spec.Replicas = 1
}
}
func SetDefaults_Volume(obj *Volume) {
if util.AllPtrFieldsNil(&obj.VolumeSource) {
obj.VolumeSource = VolumeSource{
EmptyDir: &EmptyDirVolumeSource{},
}
}
}
func SetDefaults_ContainerPort(obj *ContainerPort) {
if obj.Protocol == "" {
obj.Protocol = ProtocolTCP
}
}
func SetDefaults_Container(obj *Container) {
if obj.ImagePullPolicy == "" {
// Ignore error and assume it has been validated elsewhere
_, tag, _, _ := parsers.ParseImageName(obj.Image)
// Check image tag
if tag == "latest" {
obj.ImagePullPolicy = PullAlways
} else {
obj.ImagePullPolicy = PullIfNotPresent
}
}
if obj.TerminationMessagePath == "" {
obj.TerminationMessagePath = TerminationMessagePathDefault
}
}
func SetDefaults_ServiceSpec(obj *ServiceSpec) {
if obj.SessionAffinity == "" {
obj.SessionAffinity = ServiceAffinityNone
}
if obj.Type == "" {
obj.Type = ServiceTypeClusterIP
}
for i := range obj.Ports {
sp := &obj.Ports[i]
if sp.Protocol == "" {
sp.Protocol = ProtocolTCP
}
if sp.TargetPort == intstr.FromInt(0) || sp.TargetPort == intstr.FromString("") {
sp.TargetPort = intstr.FromInt(int(sp.Port))
}
}
}
func SetDefaults_Pod(obj *Pod) {
// If limits are specified, but requests are not, default requests to limits
// This is done here rather than a more specific defaulting pass on ResourceRequirements
// because we only want this defaulting semantic to take place on a Pod and not a PodTemplate
for i := range obj.Spec.Containers {
// set requests to limits if requests are not specified, but limits are
if obj.Spec.Containers[i].Resources.Limits != nil {
if obj.Spec.Containers[i].Resources.Requests == nil {
obj.Spec.Containers[i].Resources.Requests = make(ResourceList)
}
for key, value := range obj.Spec.Containers[i].Resources.Limits {
if _, exists := obj.Spec.Containers[i].Resources.Requests[key]; !exists {
obj.Spec.Containers[i].Resources.Requests[key] = *(value.Copy())
}
}
}
}
}
func SetDefaults_PodSpec(obj *PodSpec) {
if obj.DNSPolicy == "" {
obj.DNSPolicy = DNSClusterFirst
}
if obj.RestartPolicy == "" {
obj.RestartPolicy = RestartPolicyAlways
}
if obj.HostNetwork {
defaultHostNetworkPorts(&obj.Containers)
}
if obj.SecurityContext == nil {
obj.SecurityContext = &PodSecurityContext{}
}
if obj.TerminationGracePeriodSeconds == nil {
period := int64(DefaultTerminationGracePeriodSeconds)
obj.TerminationGracePeriodSeconds = &period
}
}
func SetDefaults_Probe(obj *Probe) {
if obj.TimeoutSeconds == 0 {
obj.TimeoutSeconds = 1
}
if obj.PeriodSeconds == 0 {
obj.PeriodSeconds = 10
}
if obj.SuccessThreshold == 0 {
obj.SuccessThreshold = 1
}
if obj.FailureThreshold == 0 {
obj.FailureThreshold = 3
}
}
func SetDefaults_SecretVolumeSource(obj *SecretVolumeSource) {
if obj.DefaultMode == nil {
perm := int32(SecretVolumeSourceDefaultMode)
obj.DefaultMode = &perm
}
}
func SetDefaults_ConfigMapVolumeSource(obj *ConfigMapVolumeSource) {
if obj.DefaultMode == nil {
perm := int32(ConfigMapVolumeSourceDefaultMode)
obj.DefaultMode = &perm
}
}
func SetDefaults_DownwardAPIVolumeSource(obj *DownwardAPIVolumeSource) {
if obj.DefaultMode == nil {
perm := int32(DownwardAPIVolumeSourceDefaultMode)
obj.DefaultMode = &perm
}
}
func SetDefaults_Secret(obj *Secret) {
if obj.Type == "" {
obj.Type = SecretTypeOpaque
}
}
func SetDefaults_PersistentVolume(obj *PersistentVolume) {
if obj.Status.Phase == "" {
obj.Status.Phase = VolumePending
}
if obj.Spec.PersistentVolumeReclaimPolicy == "" {
obj.Spec.PersistentVolumeReclaimPolicy = PersistentVolumeReclaimRetain
}
}
func SetDefaults_PersistentVolumeClaim(obj *PersistentVolumeClaim) {
if obj.Status.Phase == "" {
obj.Status.Phase = ClaimPending
}
}
func SetDefaults_ISCSIVolumeSource(obj *ISCSIVolumeSource) {
if obj.ISCSIInterface == "" {
obj.ISCSIInterface = "default"
}
}
func SetDefaults_AzureDiskVolumeSource(obj *AzureDiskVolumeSource) {
if obj.CachingMode == nil {
obj.CachingMode = new(AzureDataDiskCachingMode)
*obj.CachingMode = AzureDataDiskCachingNone
}
if obj.FSType == nil {
obj.FSType = new(string)
*obj.FSType = "ext4"
}
if obj.ReadOnly == nil {
obj.ReadOnly = new(bool)
*obj.ReadOnly = false
}
}
func SetDefaults_Endpoints(obj *Endpoints) {
for i := range obj.Subsets {
ss := &obj.Subsets[i]
for i := range ss.Ports {
ep := &ss.Ports[i]
if ep.Protocol == "" {
ep.Protocol = ProtocolTCP
}
}
}
}
func SetDefaults_HTTPGetAction(obj *HTTPGetAction) {
if obj.Path == "" {
obj.Path = "/"
}
if obj.Scheme == "" {
obj.Scheme = URISchemeHTTP
}
}
func SetDefaults_NamespaceStatus(obj *NamespaceStatus) {
if obj.Phase == "" {
obj.Phase = NamespaceActive
}
}
func SetDefaults_Node(obj *Node) {
if obj.Spec.ExternalID == "" {
obj.Spec.ExternalID = obj.Name
}
}
func SetDefaults_NodeStatus(obj *NodeStatus) {
if obj.Allocatable == nil && obj.Capacity != nil {
obj.Allocatable = make(ResourceList, len(obj.Capacity))
for key, value := range obj.Capacity {
obj.Allocatable[key] = *(value.Copy())
}
obj.Allocatable = obj.Capacity
}
}
func SetDefaults_ObjectFieldSelector(obj *ObjectFieldSelector) {
if obj.APIVersion == "" {
obj.APIVersion = "v1"
}
}
func SetDefaults_LimitRangeItem(obj *LimitRangeItem) {
// for container limits, we apply default values
if obj.Type == LimitTypeContainer {
if obj.Default == nil {
obj.Default = make(ResourceList)
}
if obj.DefaultRequest == nil {
obj.DefaultRequest = make(ResourceList)
}
// If a default limit is unspecified, but the max is specified, default the limit to the max
for key, value := range obj.Max {
if _, exists := obj.Default[key]; !exists {
obj.Default[key] = *(value.Copy())
}
}
// If a default limit is specified, but the default request is not, default request to limit
for key, value := range obj.Default {
if _, exists := obj.DefaultRequest[key]; !exists {
obj.DefaultRequest[key] = *(value.Copy())
}
}
// If a default request is not specified, but the min is provided, default request to the min
for key, value := range obj.Min {
if _, exists := obj.DefaultRequest[key]; !exists {
obj.DefaultRequest[key] = *(value.Copy())
}
}
}
}
func SetDefaults_ConfigMap(obj *ConfigMap) {
if obj.Data == nil {
obj.Data = make(map[string]string)
}
}
// With host networking default all container ports to host ports.
func defaultHostNetworkPorts(containers *[]Container) {
for i := range *containers {
for j := range (*containers)[i].Ports {
if (*containers)[i].Ports[j].HostPort == 0 {
(*containers)[i].Ports[j].HostPort = (*containers)[i].Ports[j].ContainerPort
}
}
}
}
func SetDefaults_RBDVolumeSource(obj *RBDVolumeSource) {
if obj.RBDPool == "" {
obj.RBDPool = "rbd"
}
if obj.RadosUser == "" {
obj.RadosUser = "admin"
}
if obj.Keyring == "" {
obj.Keyring = "/etc/ceph/keyring"
}
}

View file

@ -1,23 +0,0 @@
/*
Copyright 2015 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.
*/
// +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/api
// +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
// Package v1 is the v1 version of the API.
package v1

File diff suppressed because it is too large Load diff

View file

@ -1,33 +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 v1
import "k8s.io/client-go/pkg/types"
// NewDeleteOptions returns a DeleteOptions indicating the resource should
// be deleted within the specified grace period. Use zero to indicate
// immediate deletion. If you would prefer to use the default grace period,
// use &v1.DeleteOptions{} directly.
func NewDeleteOptions(grace int64) *DeleteOptions {
return &DeleteOptions{GracePeriodSeconds: &grace}
}
// NewUIDPreconditions returns a Preconditions with UID set.
func NewUIDPreconditions(uid string) *Preconditions {
u := types.UID(uid)
return &Preconditions{UID: &u}
}

View file

@ -1,92 +0,0 @@
/*
Copyright 2014 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 v1
import (
"k8s.io/client-go/pkg/api/meta"
"k8s.io/client-go/pkg/api/meta/metatypes"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/types"
)
func (obj *ObjectMeta) GetObjectMeta() meta.Object { return obj }
// Namespace implements meta.Object for any object with an ObjectMeta typed field. Allows
// fast, direct access to metadata fields for API objects.
func (meta *ObjectMeta) GetNamespace() string { return meta.Namespace }
func (meta *ObjectMeta) SetNamespace(namespace string) { meta.Namespace = namespace }
func (meta *ObjectMeta) GetName() string { return meta.Name }
func (meta *ObjectMeta) SetName(name string) { meta.Name = name }
func (meta *ObjectMeta) GetGenerateName() string { return meta.GenerateName }
func (meta *ObjectMeta) SetGenerateName(generateName string) { meta.GenerateName = generateName }
func (meta *ObjectMeta) GetUID() types.UID { return meta.UID }
func (meta *ObjectMeta) SetUID(uid types.UID) { meta.UID = uid }
func (meta *ObjectMeta) GetResourceVersion() string { return meta.ResourceVersion }
func (meta *ObjectMeta) SetResourceVersion(version string) { meta.ResourceVersion = version }
func (meta *ObjectMeta) GetSelfLink() string { return meta.SelfLink }
func (meta *ObjectMeta) SetSelfLink(selfLink string) { meta.SelfLink = selfLink }
func (meta *ObjectMeta) GetCreationTimestamp() unversioned.Time { return meta.CreationTimestamp }
func (meta *ObjectMeta) SetCreationTimestamp(creationTimestamp unversioned.Time) {
meta.CreationTimestamp = creationTimestamp
}
func (meta *ObjectMeta) GetDeletionTimestamp() *unversioned.Time { return meta.DeletionTimestamp }
func (meta *ObjectMeta) SetDeletionTimestamp(deletionTimestamp *unversioned.Time) {
meta.DeletionTimestamp = deletionTimestamp
}
func (meta *ObjectMeta) GetLabels() map[string]string { return meta.Labels }
func (meta *ObjectMeta) SetLabels(labels map[string]string) { meta.Labels = labels }
func (meta *ObjectMeta) GetAnnotations() map[string]string { return meta.Annotations }
func (meta *ObjectMeta) SetAnnotations(annotations map[string]string) { meta.Annotations = annotations }
func (meta *ObjectMeta) GetFinalizers() []string { return meta.Finalizers }
func (meta *ObjectMeta) SetFinalizers(finalizers []string) { meta.Finalizers = finalizers }
func (meta *ObjectMeta) GetOwnerReferences() []metatypes.OwnerReference {
ret := make([]metatypes.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
}
}
return ret
}
func (meta *ObjectMeta) SetOwnerReferences(references []metatypes.OwnerReference) {
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
}
}
meta.OwnerReferences = newReferences
}
func (meta *ObjectMeta) GetClusterName() string {
return meta.ClusterName
}
func (meta *ObjectMeta) SetClusterName(clusterName string) {
meta.ClusterName = clusterName
}

View file

@ -1,133 +0,0 @@
/*
Copyright 2014 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 v1
import (
"errors"
"fmt"
"k8s.io/client-go/pkg/api"
"net/url"
"strings"
"k8s.io/client-go/pkg/api/meta"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
)
var (
// Errors that could be returned by GetReference.
ErrNilObject = errors.New("can't reference a nil object")
ErrNoSelfLink = errors.New("selfLink was empty, can't make reference")
)
// GetReference returns an ObjectReference which refers to the given
// object, or an error if the object doesn't follow the conventions
// that would allow this.
// TODO: should take a meta.Interface see http://issue.k8s.io/7127
func GetReference(obj runtime.Object) (*ObjectReference, error) {
if obj == nil {
return nil, ErrNilObject
}
if ref, ok := obj.(*ObjectReference); ok {
// Don't make a reference to a reference.
return ref, nil
}
gvk := obj.GetObjectKind().GroupVersionKind()
// if the object referenced is actually persisted, we can just get kind from meta
// if we are building an object reference to something not yet persisted, we should fallback to scheme
kind := gvk.Kind
if len(kind) == 0 {
// TODO: this is wrong
gvks, _, err := api.Scheme.ObjectKinds(obj)
if err != nil {
return nil, err
}
kind = gvks[0].Kind
}
// An object that implements only List has enough metadata to build a reference
var listMeta meta.List
objectMeta, err := meta.Accessor(obj)
if err != nil {
listMeta, err = meta.ListAccessor(obj)
if err != nil {
return nil, err
}
} else {
listMeta = objectMeta
}
// if the object referenced is actually persisted, we can also get version from meta
version := gvk.GroupVersion().String()
if len(version) == 0 {
selfLink := listMeta.GetSelfLink()
if len(selfLink) == 0 {
return nil, ErrNoSelfLink
}
selfLinkUrl, err := url.Parse(selfLink)
if err != nil {
return nil, err
}
// example paths: /<prefix>/<version>/*
parts := strings.Split(selfLinkUrl.Path, "/")
if len(parts) < 3 {
return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", selfLink, version)
}
version = parts[2]
}
// only has list metadata
if objectMeta == nil {
return &ObjectReference{
Kind: kind,
APIVersion: version,
ResourceVersion: listMeta.GetResourceVersion(),
}, nil
}
return &ObjectReference{
Kind: kind,
APIVersion: version,
Name: objectMeta.GetName(),
Namespace: objectMeta.GetNamespace(),
UID: objectMeta.GetUID(),
ResourceVersion: objectMeta.GetResourceVersion(),
}, nil
}
// GetPartialReference is exactly like GetReference, but allows you to set the FieldPath.
func GetPartialReference(obj runtime.Object, fieldPath string) (*ObjectReference, error) {
ref, err := GetReference(obj)
if err != nil {
return nil, err
}
ref.FieldPath = fieldPath
return ref, nil
}
// IsAnAPIObject allows clients to preemptively get a reference to an API object and pass it to places that
// intend only to get a reference to that object. This simplifies the event recording interface.
func (obj *ObjectReference) SetGroupVersionKind(gvk unversioned.GroupVersionKind) {
obj.APIVersion, obj.Kind = gvk.ToAPIVersionAndKind()
}
func (obj *ObjectReference) GroupVersionKind() unversioned.GroupVersionKind {
return unversioned.FromAPIVersionAndKind(obj.APIVersion, obj.Kind)
}
func (obj *ObjectReference) GetObjectKind() unversioned.ObjectKind { return obj }

View file

@ -1,93 +0,0 @@
/*
Copyright 2015 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 v1
import (
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
versionedwatch "k8s.io/client-go/pkg/watch/versioned"
)
// GroupName is the group name use in this package
const GroupName = ""
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: "v1"}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addDefaultingFuncs, addConversionFuncs, addFastPathConversionFuncs)
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Pod{},
&PodList{},
&PodStatusResult{},
&PodTemplate{},
&PodTemplateList{},
&ReplicationController{},
&ReplicationControllerList{},
&Service{},
&ServiceProxyOptions{},
&ServiceList{},
&Endpoints{},
&EndpointsList{},
&Node{},
&NodeList{},
&NodeProxyOptions{},
&Binding{},
&Event{},
&EventList{},
&List{},
&LimitRange{},
&LimitRangeList{},
&ResourceQuota{},
&ResourceQuotaList{},
&Namespace{},
&NamespaceList{},
&Secret{},
&SecretList{},
&ServiceAccount{},
&ServiceAccountList{},
&PersistentVolume{},
&PersistentVolumeList{},
&PersistentVolumeClaim{},
&PersistentVolumeClaimList{},
&DeleteOptions{},
&ExportOptions{},
&ListOptions{},
&PodAttachOptions{},
&PodLogOptions{},
&PodExecOptions{},
&PodProxyOptions{},
&ComponentStatus{},
&ComponentStatusList{},
&SerializedReference{},
&RangeAllocation{},
&ConfigMap{},
&ConfigMapList{},
)
// Add common types
scheme.AddKnownTypes(SchemeGroupVersion, &unversioned.Status{})
// Add the watch version that applies
versionedwatch.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,577 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by defaulter-gen. Do not edit it manually!
package v1
import (
runtime "k8s.io/client-go/pkg/runtime"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&ConfigMap{}, func(obj interface{}) { SetObjectDefaults_ConfigMap(obj.(*ConfigMap)) })
scheme.AddTypeDefaultingFunc(&ConfigMapList{}, func(obj interface{}) { SetObjectDefaults_ConfigMapList(obj.(*ConfigMapList)) })
scheme.AddTypeDefaultingFunc(&Endpoints{}, func(obj interface{}) { SetObjectDefaults_Endpoints(obj.(*Endpoints)) })
scheme.AddTypeDefaultingFunc(&EndpointsList{}, func(obj interface{}) { SetObjectDefaults_EndpointsList(obj.(*EndpointsList)) })
scheme.AddTypeDefaultingFunc(&LimitRange{}, func(obj interface{}) { SetObjectDefaults_LimitRange(obj.(*LimitRange)) })
scheme.AddTypeDefaultingFunc(&LimitRangeList{}, func(obj interface{}) { SetObjectDefaults_LimitRangeList(obj.(*LimitRangeList)) })
scheme.AddTypeDefaultingFunc(&Namespace{}, func(obj interface{}) { SetObjectDefaults_Namespace(obj.(*Namespace)) })
scheme.AddTypeDefaultingFunc(&NamespaceList{}, func(obj interface{}) { SetObjectDefaults_NamespaceList(obj.(*NamespaceList)) })
scheme.AddTypeDefaultingFunc(&Node{}, func(obj interface{}) { SetObjectDefaults_Node(obj.(*Node)) })
scheme.AddTypeDefaultingFunc(&NodeList{}, func(obj interface{}) { SetObjectDefaults_NodeList(obj.(*NodeList)) })
scheme.AddTypeDefaultingFunc(&PersistentVolume{}, func(obj interface{}) { SetObjectDefaults_PersistentVolume(obj.(*PersistentVolume)) })
scheme.AddTypeDefaultingFunc(&PersistentVolumeClaim{}, func(obj interface{}) { SetObjectDefaults_PersistentVolumeClaim(obj.(*PersistentVolumeClaim)) })
scheme.AddTypeDefaultingFunc(&PersistentVolumeClaimList{}, func(obj interface{}) { SetObjectDefaults_PersistentVolumeClaimList(obj.(*PersistentVolumeClaimList)) })
scheme.AddTypeDefaultingFunc(&PersistentVolumeList{}, func(obj interface{}) { SetObjectDefaults_PersistentVolumeList(obj.(*PersistentVolumeList)) })
scheme.AddTypeDefaultingFunc(&Pod{}, func(obj interface{}) { SetObjectDefaults_Pod(obj.(*Pod)) })
scheme.AddTypeDefaultingFunc(&PodAttachOptions{}, func(obj interface{}) { SetObjectDefaults_PodAttachOptions(obj.(*PodAttachOptions)) })
scheme.AddTypeDefaultingFunc(&PodExecOptions{}, func(obj interface{}) { SetObjectDefaults_PodExecOptions(obj.(*PodExecOptions)) })
scheme.AddTypeDefaultingFunc(&PodList{}, func(obj interface{}) { SetObjectDefaults_PodList(obj.(*PodList)) })
scheme.AddTypeDefaultingFunc(&PodTemplate{}, func(obj interface{}) { SetObjectDefaults_PodTemplate(obj.(*PodTemplate)) })
scheme.AddTypeDefaultingFunc(&PodTemplateList{}, func(obj interface{}) { SetObjectDefaults_PodTemplateList(obj.(*PodTemplateList)) })
scheme.AddTypeDefaultingFunc(&ReplicationController{}, func(obj interface{}) { SetObjectDefaults_ReplicationController(obj.(*ReplicationController)) })
scheme.AddTypeDefaultingFunc(&ReplicationControllerList{}, func(obj interface{}) { SetObjectDefaults_ReplicationControllerList(obj.(*ReplicationControllerList)) })
scheme.AddTypeDefaultingFunc(&ResourceQuota{}, func(obj interface{}) { SetObjectDefaults_ResourceQuota(obj.(*ResourceQuota)) })
scheme.AddTypeDefaultingFunc(&ResourceQuotaList{}, func(obj interface{}) { SetObjectDefaults_ResourceQuotaList(obj.(*ResourceQuotaList)) })
scheme.AddTypeDefaultingFunc(&Secret{}, func(obj interface{}) { SetObjectDefaults_Secret(obj.(*Secret)) })
scheme.AddTypeDefaultingFunc(&SecretList{}, func(obj interface{}) { SetObjectDefaults_SecretList(obj.(*SecretList)) })
scheme.AddTypeDefaultingFunc(&Service{}, func(obj interface{}) { SetObjectDefaults_Service(obj.(*Service)) })
scheme.AddTypeDefaultingFunc(&ServiceList{}, func(obj interface{}) { SetObjectDefaults_ServiceList(obj.(*ServiceList)) })
return nil
}
func SetObjectDefaults_ConfigMap(in *ConfigMap) {
SetDefaults_ConfigMap(in)
}
func SetObjectDefaults_ConfigMapList(in *ConfigMapList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_ConfigMap(a)
}
}
func SetObjectDefaults_Endpoints(in *Endpoints) {
SetDefaults_Endpoints(in)
}
func SetObjectDefaults_EndpointsList(in *EndpointsList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_Endpoints(a)
}
}
func SetObjectDefaults_LimitRange(in *LimitRange) {
for i := range in.Spec.Limits {
a := &in.Spec.Limits[i]
SetDefaults_LimitRangeItem(a)
SetDefaults_ResourceList(&a.Max)
SetDefaults_ResourceList(&a.Min)
SetDefaults_ResourceList(&a.Default)
SetDefaults_ResourceList(&a.DefaultRequest)
SetDefaults_ResourceList(&a.MaxLimitRequestRatio)
}
}
func SetObjectDefaults_LimitRangeList(in *LimitRangeList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_LimitRange(a)
}
}
func SetObjectDefaults_Namespace(in *Namespace) {
SetDefaults_NamespaceStatus(&in.Status)
}
func SetObjectDefaults_NamespaceList(in *NamespaceList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_Namespace(a)
}
}
func SetObjectDefaults_Node(in *Node) {
SetDefaults_Node(in)
SetDefaults_NodeStatus(&in.Status)
SetDefaults_ResourceList(&in.Status.Capacity)
SetDefaults_ResourceList(&in.Status.Allocatable)
}
func SetObjectDefaults_NodeList(in *NodeList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_Node(a)
}
}
func SetObjectDefaults_PersistentVolume(in *PersistentVolume) {
SetDefaults_PersistentVolume(in)
SetDefaults_ResourceList(&in.Spec.Capacity)
if in.Spec.PersistentVolumeSource.RBD != nil {
SetDefaults_RBDVolumeSource(in.Spec.PersistentVolumeSource.RBD)
}
if in.Spec.PersistentVolumeSource.ISCSI != nil {
SetDefaults_ISCSIVolumeSource(in.Spec.PersistentVolumeSource.ISCSI)
}
if in.Spec.PersistentVolumeSource.AzureDisk != nil {
SetDefaults_AzureDiskVolumeSource(in.Spec.PersistentVolumeSource.AzureDisk)
}
}
func SetObjectDefaults_PersistentVolumeClaim(in *PersistentVolumeClaim) {
SetDefaults_PersistentVolumeClaim(in)
SetDefaults_ResourceList(&in.Spec.Resources.Limits)
SetDefaults_ResourceList(&in.Spec.Resources.Requests)
SetDefaults_ResourceList(&in.Status.Capacity)
}
func SetObjectDefaults_PersistentVolumeClaimList(in *PersistentVolumeClaimList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_PersistentVolumeClaim(a)
}
}
func SetObjectDefaults_PersistentVolumeList(in *PersistentVolumeList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_PersistentVolume(a)
}
}
func SetObjectDefaults_Pod(in *Pod) {
SetDefaults_Pod(in)
SetDefaults_PodSpec(&in.Spec)
for i := range in.Spec.Volumes {
a := &in.Spec.Volumes[i]
SetDefaults_Volume(a)
if a.VolumeSource.Secret != nil {
SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
}
if a.VolumeSource.ISCSI != nil {
SetDefaults_ISCSIVolumeSource(a.VolumeSource.ISCSI)
}
if a.VolumeSource.RBD != nil {
SetDefaults_RBDVolumeSource(a.VolumeSource.RBD)
}
if a.VolumeSource.DownwardAPI != nil {
SetDefaults_DownwardAPIVolumeSource(a.VolumeSource.DownwardAPI)
for j := range a.VolumeSource.DownwardAPI.Items {
b := &a.VolumeSource.DownwardAPI.Items[j]
if b.FieldRef != nil {
SetDefaults_ObjectFieldSelector(b.FieldRef)
}
}
}
if a.VolumeSource.ConfigMap != nil {
SetDefaults_ConfigMapVolumeSource(a.VolumeSource.ConfigMap)
}
if a.VolumeSource.AzureDisk != nil {
SetDefaults_AzureDiskVolumeSource(a.VolumeSource.AzureDisk)
}
}
for i := range in.Spec.InitContainers {
a := &in.Spec.InitContainers[i]
SetDefaults_Container(a)
for j := range a.Ports {
b := &a.Ports[j]
SetDefaults_ContainerPort(b)
}
for j := range a.Env {
b := &a.Env[j]
if b.ValueFrom != nil {
if b.ValueFrom.FieldRef != nil {
SetDefaults_ObjectFieldSelector(b.ValueFrom.FieldRef)
}
}
}
SetDefaults_ResourceList(&a.Resources.Limits)
SetDefaults_ResourceList(&a.Resources.Requests)
if a.LivenessProbe != nil {
SetDefaults_Probe(a.LivenessProbe)
if a.LivenessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.LivenessProbe.Handler.HTTPGet)
}
}
if a.ReadinessProbe != nil {
SetDefaults_Probe(a.ReadinessProbe)
if a.ReadinessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.ReadinessProbe.Handler.HTTPGet)
}
}
if a.Lifecycle != nil {
if a.Lifecycle.PostStart != nil {
if a.Lifecycle.PostStart.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PostStart.HTTPGet)
}
}
if a.Lifecycle.PreStop != nil {
if a.Lifecycle.PreStop.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PreStop.HTTPGet)
}
}
}
}
for i := range in.Spec.Containers {
a := &in.Spec.Containers[i]
SetDefaults_Container(a)
for j := range a.Ports {
b := &a.Ports[j]
SetDefaults_ContainerPort(b)
}
for j := range a.Env {
b := &a.Env[j]
if b.ValueFrom != nil {
if b.ValueFrom.FieldRef != nil {
SetDefaults_ObjectFieldSelector(b.ValueFrom.FieldRef)
}
}
}
SetDefaults_ResourceList(&a.Resources.Limits)
SetDefaults_ResourceList(&a.Resources.Requests)
if a.LivenessProbe != nil {
SetDefaults_Probe(a.LivenessProbe)
if a.LivenessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.LivenessProbe.Handler.HTTPGet)
}
}
if a.ReadinessProbe != nil {
SetDefaults_Probe(a.ReadinessProbe)
if a.ReadinessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.ReadinessProbe.Handler.HTTPGet)
}
}
if a.Lifecycle != nil {
if a.Lifecycle.PostStart != nil {
if a.Lifecycle.PostStart.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PostStart.HTTPGet)
}
}
if a.Lifecycle.PreStop != nil {
if a.Lifecycle.PreStop.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PreStop.HTTPGet)
}
}
}
}
}
func SetObjectDefaults_PodAttachOptions(in *PodAttachOptions) {
SetDefaults_PodAttachOptions(in)
}
func SetObjectDefaults_PodExecOptions(in *PodExecOptions) {
SetDefaults_PodExecOptions(in)
}
func SetObjectDefaults_PodList(in *PodList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_Pod(a)
}
}
func SetObjectDefaults_PodTemplate(in *PodTemplate) {
SetDefaults_PodSpec(&in.Template.Spec)
for i := range in.Template.Spec.Volumes {
a := &in.Template.Spec.Volumes[i]
SetDefaults_Volume(a)
if a.VolumeSource.Secret != nil {
SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
}
if a.VolumeSource.ISCSI != nil {
SetDefaults_ISCSIVolumeSource(a.VolumeSource.ISCSI)
}
if a.VolumeSource.RBD != nil {
SetDefaults_RBDVolumeSource(a.VolumeSource.RBD)
}
if a.VolumeSource.DownwardAPI != nil {
SetDefaults_DownwardAPIVolumeSource(a.VolumeSource.DownwardAPI)
for j := range a.VolumeSource.DownwardAPI.Items {
b := &a.VolumeSource.DownwardAPI.Items[j]
if b.FieldRef != nil {
SetDefaults_ObjectFieldSelector(b.FieldRef)
}
}
}
if a.VolumeSource.ConfigMap != nil {
SetDefaults_ConfigMapVolumeSource(a.VolumeSource.ConfigMap)
}
if a.VolumeSource.AzureDisk != nil {
SetDefaults_AzureDiskVolumeSource(a.VolumeSource.AzureDisk)
}
}
for i := range in.Template.Spec.InitContainers {
a := &in.Template.Spec.InitContainers[i]
SetDefaults_Container(a)
for j := range a.Ports {
b := &a.Ports[j]
SetDefaults_ContainerPort(b)
}
for j := range a.Env {
b := &a.Env[j]
if b.ValueFrom != nil {
if b.ValueFrom.FieldRef != nil {
SetDefaults_ObjectFieldSelector(b.ValueFrom.FieldRef)
}
}
}
SetDefaults_ResourceList(&a.Resources.Limits)
SetDefaults_ResourceList(&a.Resources.Requests)
if a.LivenessProbe != nil {
SetDefaults_Probe(a.LivenessProbe)
if a.LivenessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.LivenessProbe.Handler.HTTPGet)
}
}
if a.ReadinessProbe != nil {
SetDefaults_Probe(a.ReadinessProbe)
if a.ReadinessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.ReadinessProbe.Handler.HTTPGet)
}
}
if a.Lifecycle != nil {
if a.Lifecycle.PostStart != nil {
if a.Lifecycle.PostStart.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PostStart.HTTPGet)
}
}
if a.Lifecycle.PreStop != nil {
if a.Lifecycle.PreStop.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PreStop.HTTPGet)
}
}
}
}
for i := range in.Template.Spec.Containers {
a := &in.Template.Spec.Containers[i]
SetDefaults_Container(a)
for j := range a.Ports {
b := &a.Ports[j]
SetDefaults_ContainerPort(b)
}
for j := range a.Env {
b := &a.Env[j]
if b.ValueFrom != nil {
if b.ValueFrom.FieldRef != nil {
SetDefaults_ObjectFieldSelector(b.ValueFrom.FieldRef)
}
}
}
SetDefaults_ResourceList(&a.Resources.Limits)
SetDefaults_ResourceList(&a.Resources.Requests)
if a.LivenessProbe != nil {
SetDefaults_Probe(a.LivenessProbe)
if a.LivenessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.LivenessProbe.Handler.HTTPGet)
}
}
if a.ReadinessProbe != nil {
SetDefaults_Probe(a.ReadinessProbe)
if a.ReadinessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.ReadinessProbe.Handler.HTTPGet)
}
}
if a.Lifecycle != nil {
if a.Lifecycle.PostStart != nil {
if a.Lifecycle.PostStart.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PostStart.HTTPGet)
}
}
if a.Lifecycle.PreStop != nil {
if a.Lifecycle.PreStop.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PreStop.HTTPGet)
}
}
}
}
}
func SetObjectDefaults_PodTemplateList(in *PodTemplateList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_PodTemplate(a)
}
}
func SetObjectDefaults_ReplicationController(in *ReplicationController) {
SetDefaults_ReplicationController(in)
if in.Spec.Template != nil {
SetDefaults_PodSpec(&in.Spec.Template.Spec)
for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i]
SetDefaults_Volume(a)
if a.VolumeSource.Secret != nil {
SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
}
if a.VolumeSource.ISCSI != nil {
SetDefaults_ISCSIVolumeSource(a.VolumeSource.ISCSI)
}
if a.VolumeSource.RBD != nil {
SetDefaults_RBDVolumeSource(a.VolumeSource.RBD)
}
if a.VolumeSource.DownwardAPI != nil {
SetDefaults_DownwardAPIVolumeSource(a.VolumeSource.DownwardAPI)
for j := range a.VolumeSource.DownwardAPI.Items {
b := &a.VolumeSource.DownwardAPI.Items[j]
if b.FieldRef != nil {
SetDefaults_ObjectFieldSelector(b.FieldRef)
}
}
}
if a.VolumeSource.ConfigMap != nil {
SetDefaults_ConfigMapVolumeSource(a.VolumeSource.ConfigMap)
}
if a.VolumeSource.AzureDisk != nil {
SetDefaults_AzureDiskVolumeSource(a.VolumeSource.AzureDisk)
}
}
for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i]
SetDefaults_Container(a)
for j := range a.Ports {
b := &a.Ports[j]
SetDefaults_ContainerPort(b)
}
for j := range a.Env {
b := &a.Env[j]
if b.ValueFrom != nil {
if b.ValueFrom.FieldRef != nil {
SetDefaults_ObjectFieldSelector(b.ValueFrom.FieldRef)
}
}
}
SetDefaults_ResourceList(&a.Resources.Limits)
SetDefaults_ResourceList(&a.Resources.Requests)
if a.LivenessProbe != nil {
SetDefaults_Probe(a.LivenessProbe)
if a.LivenessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.LivenessProbe.Handler.HTTPGet)
}
}
if a.ReadinessProbe != nil {
SetDefaults_Probe(a.ReadinessProbe)
if a.ReadinessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.ReadinessProbe.Handler.HTTPGet)
}
}
if a.Lifecycle != nil {
if a.Lifecycle.PostStart != nil {
if a.Lifecycle.PostStart.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PostStart.HTTPGet)
}
}
if a.Lifecycle.PreStop != nil {
if a.Lifecycle.PreStop.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PreStop.HTTPGet)
}
}
}
}
for i := range in.Spec.Template.Spec.Containers {
a := &in.Spec.Template.Spec.Containers[i]
SetDefaults_Container(a)
for j := range a.Ports {
b := &a.Ports[j]
SetDefaults_ContainerPort(b)
}
for j := range a.Env {
b := &a.Env[j]
if b.ValueFrom != nil {
if b.ValueFrom.FieldRef != nil {
SetDefaults_ObjectFieldSelector(b.ValueFrom.FieldRef)
}
}
}
SetDefaults_ResourceList(&a.Resources.Limits)
SetDefaults_ResourceList(&a.Resources.Requests)
if a.LivenessProbe != nil {
SetDefaults_Probe(a.LivenessProbe)
if a.LivenessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.LivenessProbe.Handler.HTTPGet)
}
}
if a.ReadinessProbe != nil {
SetDefaults_Probe(a.ReadinessProbe)
if a.ReadinessProbe.Handler.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.ReadinessProbe.Handler.HTTPGet)
}
}
if a.Lifecycle != nil {
if a.Lifecycle.PostStart != nil {
if a.Lifecycle.PostStart.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PostStart.HTTPGet)
}
}
if a.Lifecycle.PreStop != nil {
if a.Lifecycle.PreStop.HTTPGet != nil {
SetDefaults_HTTPGetAction(a.Lifecycle.PreStop.HTTPGet)
}
}
}
}
}
}
func SetObjectDefaults_ReplicationControllerList(in *ReplicationControllerList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_ReplicationController(a)
}
}
func SetObjectDefaults_ResourceQuota(in *ResourceQuota) {
SetDefaults_ResourceList(&in.Spec.Hard)
SetDefaults_ResourceList(&in.Status.Hard)
SetDefaults_ResourceList(&in.Status.Used)
}
func SetObjectDefaults_ResourceQuotaList(in *ResourceQuotaList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_ResourceQuota(a)
}
}
func SetObjectDefaults_Secret(in *Secret) {
SetDefaults_Secret(in)
}
func SetObjectDefaults_SecretList(in *SecretList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_Secret(a)
}
}
func SetObjectDefaults_Service(in *Service) {
SetDefaults_ServiceSpec(&in.Spec)
}
func SetObjectDefaults_ServiceList(in *ServiceList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_Service(a)
}
}

View file

@ -1,66 +0,0 @@
/*
Copyright 2015 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 path
import (
"fmt"
"strings"
)
// NameMayNotBe specifies strings that cannot be used as names specified as path segments (like the REST API or etcd store)
var NameMayNotBe = []string{".", ".."}
// NameMayNotContain specifies substrings that cannot be used in names specified as path segments (like the REST API or etcd store)
var NameMayNotContain = []string{"/", "%"}
// IsValidPathSegmentName validates the name can be safely encoded as a path segment
func IsValidPathSegmentName(name string) []string {
for _, illegalName := range NameMayNotBe {
if name == illegalName {
return []string{fmt.Sprintf(`may not be '%s'`, illegalName)}
}
}
for _, illegalContent := range NameMayNotContain {
if strings.Contains(name, illegalContent) {
return []string{fmt.Sprintf(`may not contain '%s'`, illegalContent)}
}
}
return nil
}
// IsValidPathSegmentPrefix validates the name can be used as a prefix for a name which will be encoded as a path segment
// It does not check for exact matches with disallowed names, since an arbitrary suffix might make the name valid
func IsValidPathSegmentPrefix(name string) []string {
for _, illegalContent := range NameMayNotContain {
if strings.Contains(name, illegalContent) {
return []string{fmt.Sprintf(`may not contain '%s'`, illegalContent)}
}
}
return nil
}
// ValidatePathSegmentName validates the name can be safely encoded as a path segment
func ValidatePathSegmentName(name string, prefix bool) []string {
if prefix {
return IsValidPathSegmentPrefix(name)
} else {
return IsValidPathSegmentName(name)
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,107 +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 announced contains tools for announcing API group factories. This is
// distinct from registration (in the 'registered' package) in that it's safe
// to announce every possible group linked in, but only groups requested at
// runtime should be registered. This package contains both a registry, and
// factory code (which was formerly copy-pasta in every install package).
package announced
import (
"fmt"
"k8s.io/client-go/pkg/apimachinery/registered"
"k8s.io/client-go/pkg/runtime"
)
var (
DefaultGroupFactoryRegistry = make(APIGroupFactoryRegistry)
// These functions will announce your group or version.
AnnounceGroupVersion = DefaultGroupFactoryRegistry.AnnounceGroupVersion
AnnounceGroup = DefaultGroupFactoryRegistry.AnnounceGroup
)
// APIGroupFactoryRegistry allows for groups and versions to announce themselves,
// which simply makes them available and doesn't take other actions. Later,
// users of the registry can select which groups and versions they'd actually
// like to register with an APIRegistrationManager.
//
// (Right now APIRegistrationManager has separate 'registration' and 'enabled'
// concepts-- APIGroupFactory is going to take over the former function;
// they will overlap untill the refactoring is finished.)
//
// The key is the group name. After initialization, this should be treated as
// read-only. It is implemented as a map from group name to group factory, and
// it is safe to use this knowledge to manually pick out groups to register
// (e.g., for testing).
type APIGroupFactoryRegistry map[string]*GroupMetaFactory
func (gar APIGroupFactoryRegistry) group(groupName string) *GroupMetaFactory {
gmf, ok := gar[groupName]
if !ok {
gmf = &GroupMetaFactory{VersionArgs: map[string]*GroupVersionFactoryArgs{}}
gar[groupName] = gmf
}
return gmf
}
// AnnounceGroupVersion adds the particular arguments for this group version to the group factory.
func (gar APIGroupFactoryRegistry) AnnounceGroupVersion(gvf *GroupVersionFactoryArgs) error {
gmf := gar.group(gvf.GroupName)
if _, ok := gmf.VersionArgs[gvf.VersionName]; ok {
return fmt.Errorf("version %q in group %q has already been announced", gvf.VersionName, gvf.GroupName)
}
gmf.VersionArgs[gvf.VersionName] = gvf
return nil
}
// AnnounceGroup adds the group-wide arguments to the group factory.
func (gar APIGroupFactoryRegistry) AnnounceGroup(args *GroupMetaFactoryArgs) error {
gmf := gar.group(args.GroupName)
if gmf.GroupArgs != nil {
return fmt.Errorf("group %q has already been announced", args.GroupName)
}
gmf.GroupArgs = args
return nil
}
// RegisterAndEnableAll throws every factory at the specified API registration
// manager, and lets it decide which to register. (If you want to do this a la
// cart, you may look through gar itself-- it's just a map.)
func (gar APIGroupFactoryRegistry) RegisterAndEnableAll(m *registered.APIRegistrationManager, scheme *runtime.Scheme) error {
for groupName, gmf := range gar {
if err := gmf.Register(m); err != nil {
return fmt.Errorf("error registering %v: %v", groupName, err)
}
if err := gmf.Enable(m, scheme); err != nil {
return fmt.Errorf("error enabling %v: %v", groupName, err)
}
}
return nil
}
// AnnouncePreconstructedFactory announces a factory which you've manually assembled.
// You may call this instead of calling AnnounceGroup and AnnounceGroupVersion.
func (gar APIGroupFactoryRegistry) AnnouncePreconstructedFactory(gmf *GroupMetaFactory) error {
name := gmf.GroupArgs.GroupName
if _, exists := gar[name]; exists {
return fmt.Errorf("the group %q has already been announced.", name)
}
gar[name] = gmf
return nil
}

View file

@ -1,247 +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 announced
import (
"fmt"
"github.com/golang/glog"
"k8s.io/client-go/pkg/api"
"k8s.io/client-go/pkg/api/meta"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/apimachinery"
"k8s.io/client-go/pkg/apimachinery/registered"
"k8s.io/client-go/pkg/runtime"
"k8s.io/client-go/pkg/util/sets"
)
type SchemeFunc func(*runtime.Scheme) error
type VersionToSchemeFunc map[string]SchemeFunc
// GroupVersionFactoryArgs contains all the per-version parts of a GroupMetaFactory.
type GroupVersionFactoryArgs struct {
GroupName string
VersionName string
AddToScheme SchemeFunc
}
// GroupMetaFactoryArgs contains the group-level args of a GroupMetaFactory.
type GroupMetaFactoryArgs struct {
GroupName string
VersionPreferenceOrder []string
ImportPrefix string
RootScopedKinds sets.String // nil is allowed
IgnoredKinds sets.String // nil is allowed
// May be nil if there are no internal objects.
AddInternalObjectsToScheme SchemeFunc
}
// NewGroupMetaFactory builds the args for you. This is for if you're
// constructing a factory all at once and not using the registry.
func NewGroupMetaFactory(groupArgs *GroupMetaFactoryArgs, versions VersionToSchemeFunc) *GroupMetaFactory {
gmf := &GroupMetaFactory{
GroupArgs: groupArgs,
VersionArgs: map[string]*GroupVersionFactoryArgs{},
}
for v, f := range versions {
gmf.VersionArgs[v] = &GroupVersionFactoryArgs{
GroupName: groupArgs.GroupName,
VersionName: v,
AddToScheme: f,
}
}
return gmf
}
// Announce adds this Group factory to the global factory registry. It should
// only be called if you constructed the GroupMetaFactory yourself via
// NewGroupMetadFactory.
// Note that this will panic on an error, since it's expected that you'll be
// calling this at initialization time and any error is a result of a
// programmer importing the wrong set of packages. If this assumption doesn't
// work for you, just call DefaultGroupFactoryRegistry.AnnouncePreconstructedFactory
// yourself.
func (gmf *GroupMetaFactory) Announce() *GroupMetaFactory {
if err := DefaultGroupFactoryRegistry.AnnouncePreconstructedFactory(gmf); err != nil {
panic(err)
}
return gmf
}
// GroupMetaFactory has the logic for actually assembling and registering a group.
//
// There are two ways of obtaining one of these.
// 1. You can announce your group and versions separately, and then let the
// GroupFactoryRegistry assemble this object for you. (This allows group and
// versions to be imported separately, without referencing each other, to
// keep import trees small.)
// 2. You can call NewGroupMetaFactory(), which is mostly a drop-in replacement
// for the old, bad way of doing things. You can then call .Announce() to
// announce your constructed factory to any code that would like to do
// things the new, better way.
//
// Note that GroupMetaFactory actually does construct GroupMeta objects, but
// currently it does so in a way that's very entangled with an
// APIRegistrationManager. It's a TODO item to cleanly separate that interface.
type GroupMetaFactory struct {
GroupArgs *GroupMetaFactoryArgs
// map of version name to version factory
VersionArgs map[string]*GroupVersionFactoryArgs
// assembled by Register()
prioritizedVersionList []unversioned.GroupVersion
}
// Register constructs the finalized prioritized version list and sanity checks
// the announced group & versions. Then it calls register.
func (gmf *GroupMetaFactory) Register(m *registered.APIRegistrationManager) error {
if gmf.GroupArgs == nil {
return fmt.Errorf("partially announced groups are not allowed, only got versions: %#v", gmf.VersionArgs)
}
if len(gmf.VersionArgs) == 0 {
return fmt.Errorf("group %v announced but no versions announced", gmf.GroupArgs.GroupName)
}
pvSet := sets.NewString(gmf.GroupArgs.VersionPreferenceOrder...)
if pvSet.Len() != len(gmf.GroupArgs.VersionPreferenceOrder) {
return fmt.Errorf("preference order for group %v has duplicates: %v", gmf.GroupArgs.GroupName, gmf.GroupArgs.VersionPreferenceOrder)
}
prioritizedVersions := []unversioned.GroupVersion{}
for _, v := range gmf.GroupArgs.VersionPreferenceOrder {
prioritizedVersions = append(
prioritizedVersions,
unversioned.GroupVersion{
Group: gmf.GroupArgs.GroupName,
Version: v,
},
)
}
// Go through versions that weren't explicitly prioritized.
unprioritizedVersions := []unversioned.GroupVersion{}
for _, v := range gmf.VersionArgs {
if v.GroupName != gmf.GroupArgs.GroupName {
return fmt.Errorf("found %v/%v in group %v?", v.GroupName, v.VersionName, gmf.GroupArgs.GroupName)
}
if pvSet.Has(v.VersionName) {
pvSet.Delete(v.VersionName)
continue
}
unprioritizedVersions = append(unprioritizedVersions, unversioned.GroupVersion{Group: v.GroupName, Version: v.VersionName})
}
if len(unprioritizedVersions) > 1 {
glog.Warningf("group %v has multiple unprioritized versions: %#v. They will have an arbitrary preference order!", gmf.GroupArgs.GroupName, unprioritizedVersions)
}
if pvSet.Len() != 0 {
return fmt.Errorf("group %v has versions in the priority list that were never announced: %s", gmf.GroupArgs.GroupName, pvSet)
}
prioritizedVersions = append(prioritizedVersions, unprioritizedVersions...)
m.RegisterVersions(prioritizedVersions)
gmf.prioritizedVersionList = prioritizedVersions
return nil
}
func (gmf *GroupMetaFactory) newRESTMapper(scheme *runtime.Scheme, externalVersions []unversioned.GroupVersion, groupMeta *apimachinery.GroupMeta) meta.RESTMapper {
// the list of kinds that are scoped at the root of the api hierarchy
// if a kind is not enumerated here, it is assumed to have a namespace scope
rootScoped := sets.NewString()
if gmf.GroupArgs.RootScopedKinds != nil {
rootScoped = gmf.GroupArgs.RootScopedKinds
}
ignoredKinds := sets.NewString()
if gmf.GroupArgs.IgnoredKinds != nil {
ignoredKinds = gmf.GroupArgs.IgnoredKinds
}
return api.NewDefaultRESTMapperFromScheme(
externalVersions,
groupMeta.InterfacesFor,
gmf.GroupArgs.ImportPrefix,
ignoredKinds,
rootScoped,
scheme,
)
}
// Enable enables group versions that are allowed, adds methods to the scheme, etc.
func (gmf *GroupMetaFactory) Enable(m *registered.APIRegistrationManager, scheme *runtime.Scheme) error {
externalVersions := []unversioned.GroupVersion{}
for _, v := range gmf.prioritizedVersionList {
if !m.IsAllowedVersion(v) {
continue
}
externalVersions = append(externalVersions, v)
if err := m.EnableVersions(v); err != nil {
return err
}
gmf.VersionArgs[v.Version].AddToScheme(scheme)
}
if len(externalVersions) == 0 {
glog.V(4).Infof("No version is registered for group %v", gmf.GroupArgs.GroupName)
return nil
}
if gmf.GroupArgs.AddInternalObjectsToScheme != nil {
gmf.GroupArgs.AddInternalObjectsToScheme(scheme)
}
preferredExternalVersion := externalVersions[0]
accessor := meta.NewAccessor()
groupMeta := &apimachinery.GroupMeta{
GroupVersion: preferredExternalVersion,
GroupVersions: externalVersions,
SelfLinker: runtime.SelfLinker(accessor),
}
for _, v := range externalVersions {
gvf := gmf.VersionArgs[v.Version]
if err := groupMeta.AddVersionInterfaces(
unversioned.GroupVersion{Group: gvf.GroupName, Version: gvf.VersionName},
&meta.VersionInterfaces{
ObjectConvertor: scheme,
MetadataAccessor: accessor,
},
); err != nil {
return err
}
}
groupMeta.InterfacesFor = groupMeta.DefaultInterfacesFor
groupMeta.RESTMapper = gmf.newRESTMapper(scheme, externalVersions, groupMeta)
if err := m.RegisterGroup(*groupMeta); err != nil {
return err
}
return nil
}
// RegisterAndEnable is provided only to allow this code to get added in multiple steps.
// It's really bad that this is called in init() methods, but supporting this
// temporarily lets us do the change incrementally.
func (gmf *GroupMetaFactory) RegisterAndEnable() error {
if err := gmf.Register(registered.DefaultAPIRegistrationManager); err != nil {
return err
}
if err := gmf.Enable(registered.DefaultAPIRegistrationManager, api.Scheme); err != nil {
return err
}
return nil
}

View file

@ -1,20 +0,0 @@
/*
Copyright 2014 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 apimachinery contains the generic API machinery code that
// is common to both server and clients.
// This package should never import specific API objects.
package apimachinery

View file

@ -1,403 +0,0 @@
/*
Copyright 2015 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 to keep track of API Versions that can be registered and are enabled in api.Scheme.
package registered
import (
"fmt"
"os"
"sort"
"strings"
"github.com/golang/glog"
"k8s.io/client-go/pkg/api/meta"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/apimachinery"
"k8s.io/client-go/pkg/util/sets"
)
var (
DefaultAPIRegistrationManager = NewOrDie(os.Getenv("KUBE_API_VERSIONS"))
)
// APIRegistrationManager provides the concept of what API groups are enabled.
//
// TODO: currently, it also provides a "registered" concept. But it's wrong to
// have both concepts in the same object. Therefore the "announced" package is
// going to take over the registered concept. After all the install packages
// are switched to using the announce package instead of this package, then we
// can combine the registered/enabled concepts in this object. Simplifying this
// isn't easy right now because there are so many callers of this package.
type APIRegistrationManager struct {
// registeredGroupVersions stores all API group versions for which RegisterGroup is called.
registeredVersions map[unversioned.GroupVersion]struct{}
// thirdPartyGroupVersions are API versions which are dynamically
// registered (and unregistered) via API calls to the apiserver
thirdPartyGroupVersions []unversioned.GroupVersion
// enabledVersions represents all enabled API versions. It should be a
// subset of registeredVersions. Please call EnableVersions() to add
// enabled versions.
enabledVersions map[unversioned.GroupVersion]struct{}
// map of group meta for all groups.
groupMetaMap map[string]*apimachinery.GroupMeta
// envRequestedVersions represents the versions requested via the
// KUBE_API_VERSIONS environment variable. The install package of each group
// checks this list before add their versions to the latest package and
// Scheme. This list is small and order matters, so represent as a slice
envRequestedVersions []unversioned.GroupVersion
}
// NewAPIRegistrationManager constructs a new manager. The argument ought to be
// the value of the KUBE_API_VERSIONS env var, or a value of this which you
// wish to test.
func NewAPIRegistrationManager(kubeAPIVersions string) (*APIRegistrationManager, error) {
m := &APIRegistrationManager{
registeredVersions: map[unversioned.GroupVersion]struct{}{},
thirdPartyGroupVersions: []unversioned.GroupVersion{},
enabledVersions: map[unversioned.GroupVersion]struct{}{},
groupMetaMap: map[string]*apimachinery.GroupMeta{},
envRequestedVersions: []unversioned.GroupVersion{},
}
if len(kubeAPIVersions) != 0 {
for _, version := range strings.Split(kubeAPIVersions, ",") {
gv, err := unversioned.ParseGroupVersion(version)
if err != nil {
return nil, fmt.Errorf("invalid api version: %s in KUBE_API_VERSIONS: %s.",
version, kubeAPIVersions)
}
m.envRequestedVersions = append(m.envRequestedVersions, gv)
}
}
return m, nil
}
func NewOrDie(kubeAPIVersions string) *APIRegistrationManager {
m, err := NewAPIRegistrationManager(kubeAPIVersions)
if err != nil {
glog.Fatalf("Could not construct version manager: %v (KUBE_API_VERSIONS=%q)", err, kubeAPIVersions)
}
return m
}
// People are calling global functions. Let them continue to do that (for now).
var (
ValidateEnvRequestedVersions = DefaultAPIRegistrationManager.ValidateEnvRequestedVersions
AllPreferredGroupVersions = DefaultAPIRegistrationManager.AllPreferredGroupVersions
RESTMapper = DefaultAPIRegistrationManager.RESTMapper
GroupOrDie = DefaultAPIRegistrationManager.GroupOrDie
AddThirdPartyAPIGroupVersions = DefaultAPIRegistrationManager.AddThirdPartyAPIGroupVersions
IsThirdPartyAPIGroupVersion = DefaultAPIRegistrationManager.IsThirdPartyAPIGroupVersion
RegisteredGroupVersions = DefaultAPIRegistrationManager.RegisteredGroupVersions
IsRegisteredVersion = DefaultAPIRegistrationManager.IsRegisteredVersion
IsRegistered = DefaultAPIRegistrationManager.IsRegistered
Group = DefaultAPIRegistrationManager.Group
EnabledVersionsForGroup = DefaultAPIRegistrationManager.EnabledVersionsForGroup
EnabledVersions = DefaultAPIRegistrationManager.EnabledVersions
IsEnabledVersion = DefaultAPIRegistrationManager.IsEnabledVersion
IsAllowedVersion = DefaultAPIRegistrationManager.IsAllowedVersion
EnableVersions = DefaultAPIRegistrationManager.EnableVersions
RegisterGroup = DefaultAPIRegistrationManager.RegisterGroup
RegisterVersions = DefaultAPIRegistrationManager.RegisterVersions
InterfacesFor = DefaultAPIRegistrationManager.InterfacesFor
)
// RegisterVersions adds the given group versions to the list of registered group versions.
func (m *APIRegistrationManager) RegisterVersions(availableVersions []unversioned.GroupVersion) {
for _, v := range availableVersions {
m.registeredVersions[v] = struct{}{}
}
}
// RegisterGroup adds the given group to the list of registered groups.
func (m *APIRegistrationManager) RegisterGroup(groupMeta apimachinery.GroupMeta) error {
groupName := groupMeta.GroupVersion.Group
if _, found := m.groupMetaMap[groupName]; found {
return fmt.Errorf("group %v is already registered", m.groupMetaMap)
}
m.groupMetaMap[groupName] = &groupMeta
return nil
}
// EnableVersions adds the versions for the given group to the list of enabled versions.
// Note that the caller should call RegisterGroup before calling this method.
// The caller of this function is responsible to add the versions to scheme and RESTMapper.
func (m *APIRegistrationManager) EnableVersions(versions ...unversioned.GroupVersion) error {
var unregisteredVersions []unversioned.GroupVersion
for _, v := range versions {
if _, found := m.registeredVersions[v]; !found {
unregisteredVersions = append(unregisteredVersions, v)
}
m.enabledVersions[v] = struct{}{}
}
if len(unregisteredVersions) != 0 {
return fmt.Errorf("Please register versions before enabling them: %v", unregisteredVersions)
}
return nil
}
// IsAllowedVersion returns if the version is allowed by the KUBE_API_VERSIONS
// environment variable. If the environment variable is empty, then it always
// returns true.
func (m *APIRegistrationManager) IsAllowedVersion(v unversioned.GroupVersion) bool {
if len(m.envRequestedVersions) == 0 {
return true
}
for _, envGV := range m.envRequestedVersions {
if v == envGV {
return true
}
}
return false
}
// IsEnabledVersion returns if a version is enabled.
func (m *APIRegistrationManager) IsEnabledVersion(v unversioned.GroupVersion) bool {
_, found := m.enabledVersions[v]
return found
}
// EnabledVersions returns all enabled versions. Groups are randomly ordered, but versions within groups
// are priority order from best to worst
func (m *APIRegistrationManager) EnabledVersions() []unversioned.GroupVersion {
ret := []unversioned.GroupVersion{}
for _, groupMeta := range m.groupMetaMap {
for _, version := range groupMeta.GroupVersions {
if m.IsEnabledVersion(version) {
ret = append(ret, version)
}
}
}
return ret
}
// EnabledVersionsForGroup returns all enabled versions for a group in order of best to worst
func (m *APIRegistrationManager) EnabledVersionsForGroup(group string) []unversioned.GroupVersion {
groupMeta, ok := m.groupMetaMap[group]
if !ok {
return []unversioned.GroupVersion{}
}
ret := []unversioned.GroupVersion{}
for _, version := range groupMeta.GroupVersions {
if m.IsEnabledVersion(version) {
ret = append(ret, version)
}
}
return ret
}
// Group returns the metadata of a group if the group is registered, otherwise
// an error is returned.
func (m *APIRegistrationManager) Group(group string) (*apimachinery.GroupMeta, error) {
groupMeta, found := m.groupMetaMap[group]
if !found {
return nil, fmt.Errorf("group %v has not been registered", group)
}
groupMetaCopy := *groupMeta
return &groupMetaCopy, nil
}
// IsRegistered takes a string and determines if it's one of the registered groups
func (m *APIRegistrationManager) IsRegistered(group string) bool {
_, found := m.groupMetaMap[group]
return found
}
// IsRegisteredVersion returns if a version is registered.
func (m *APIRegistrationManager) IsRegisteredVersion(v unversioned.GroupVersion) bool {
_, found := m.registeredVersions[v]
return found
}
// RegisteredGroupVersions returns all registered group versions.
func (m *APIRegistrationManager) RegisteredGroupVersions() []unversioned.GroupVersion {
ret := []unversioned.GroupVersion{}
for groupVersion := range m.registeredVersions {
ret = append(ret, groupVersion)
}
return ret
}
// IsThirdPartyAPIGroupVersion returns true if the api version is a user-registered group/version.
func (m *APIRegistrationManager) IsThirdPartyAPIGroupVersion(gv unversioned.GroupVersion) bool {
for ix := range m.thirdPartyGroupVersions {
if m.thirdPartyGroupVersions[ix] == gv {
return true
}
}
return false
}
// AddThirdPartyAPIGroupVersions sets the list of third party versions,
// registers them in the API machinery and enables them.
// Skips GroupVersions that are already registered.
// Returns the list of GroupVersions that were skipped.
func (m *APIRegistrationManager) AddThirdPartyAPIGroupVersions(gvs ...unversioned.GroupVersion) []unversioned.GroupVersion {
filteredGVs := []unversioned.GroupVersion{}
skippedGVs := []unversioned.GroupVersion{}
for ix := range gvs {
if !m.IsRegisteredVersion(gvs[ix]) {
filteredGVs = append(filteredGVs, gvs[ix])
} else {
glog.V(3).Infof("Skipping %s, because its already registered", gvs[ix].String())
skippedGVs = append(skippedGVs, gvs[ix])
}
}
if len(filteredGVs) == 0 {
return skippedGVs
}
m.RegisterVersions(filteredGVs)
m.EnableVersions(filteredGVs...)
m.thirdPartyGroupVersions = append(m.thirdPartyGroupVersions, filteredGVs...)
return skippedGVs
}
// InterfacesFor is a union meta.VersionInterfacesFunc func for all registered types
func (m *APIRegistrationManager) InterfacesFor(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
groupMeta, err := m.Group(version.Group)
if err != nil {
return nil, err
}
return groupMeta.InterfacesFor(version)
}
// TODO: This is an expedient function, because we don't check if a Group is
// supported throughout the code base. We will abandon this function and
// checking the error returned by the Group() function.
func (m *APIRegistrationManager) GroupOrDie(group string) *apimachinery.GroupMeta {
groupMeta, found := m.groupMetaMap[group]
if !found {
if group == "" {
panic("The legacy v1 API is not registered.")
} else {
panic(fmt.Sprintf("Group %s is not registered.", group))
}
}
groupMetaCopy := *groupMeta
return &groupMetaCopy
}
// RESTMapper returns a union RESTMapper of all known types with priorities chosen in the following order:
// 1. if KUBE_API_VERSIONS is specified, then KUBE_API_VERSIONS in order, OR
// 1. legacy kube group preferred version, extensions preferred version, metrics perferred version, legacy
// kube any version, extensions any version, metrics any version, all other groups alphabetical preferred version,
// all other groups alphabetical.
func (m *APIRegistrationManager) RESTMapper(versionPatterns ...unversioned.GroupVersion) meta.RESTMapper {
unionMapper := meta.MultiRESTMapper{}
unionedGroups := sets.NewString()
for enabledVersion := range m.enabledVersions {
if !unionedGroups.Has(enabledVersion.Group) {
unionedGroups.Insert(enabledVersion.Group)
groupMeta := m.groupMetaMap[enabledVersion.Group]
unionMapper = append(unionMapper, groupMeta.RESTMapper)
}
}
if len(versionPatterns) != 0 {
resourcePriority := []unversioned.GroupVersionResource{}
kindPriority := []unversioned.GroupVersionKind{}
for _, versionPriority := range versionPatterns {
resourcePriority = append(resourcePriority, versionPriority.WithResource(meta.AnyResource))
kindPriority = append(kindPriority, versionPriority.WithKind(meta.AnyKind))
}
return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority}
}
if len(m.envRequestedVersions) != 0 {
resourcePriority := []unversioned.GroupVersionResource{}
kindPriority := []unversioned.GroupVersionKind{}
for _, versionPriority := range m.envRequestedVersions {
resourcePriority = append(resourcePriority, versionPriority.WithResource(meta.AnyResource))
kindPriority = append(kindPriority, versionPriority.WithKind(meta.AnyKind))
}
return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority}
}
prioritizedGroups := []string{"", "extensions", "metrics"}
resourcePriority, kindPriority := m.prioritiesForGroups(prioritizedGroups...)
prioritizedGroupsSet := sets.NewString(prioritizedGroups...)
remainingGroups := sets.String{}
for enabledVersion := range m.enabledVersions {
if !prioritizedGroupsSet.Has(enabledVersion.Group) {
remainingGroups.Insert(enabledVersion.Group)
}
}
remainingResourcePriority, remainingKindPriority := m.prioritiesForGroups(remainingGroups.List()...)
resourcePriority = append(resourcePriority, remainingResourcePriority...)
kindPriority = append(kindPriority, remainingKindPriority...)
return meta.PriorityRESTMapper{Delegate: unionMapper, ResourcePriority: resourcePriority, KindPriority: kindPriority}
}
// prioritiesForGroups returns the resource and kind priorities for a PriorityRESTMapper, preferring the preferred version of each group first,
// then any non-preferred version of the group second.
func (m *APIRegistrationManager) prioritiesForGroups(groups ...string) ([]unversioned.GroupVersionResource, []unversioned.GroupVersionKind) {
resourcePriority := []unversioned.GroupVersionResource{}
kindPriority := []unversioned.GroupVersionKind{}
for _, group := range groups {
availableVersions := m.EnabledVersionsForGroup(group)
if len(availableVersions) > 0 {
resourcePriority = append(resourcePriority, availableVersions[0].WithResource(meta.AnyResource))
kindPriority = append(kindPriority, availableVersions[0].WithKind(meta.AnyKind))
}
}
for _, group := range groups {
resourcePriority = append(resourcePriority, unversioned.GroupVersionResource{Group: group, Version: meta.AnyVersion, Resource: meta.AnyResource})
kindPriority = append(kindPriority, unversioned.GroupVersionKind{Group: group, Version: meta.AnyVersion, Kind: meta.AnyKind})
}
return resourcePriority, kindPriority
}
// AllPreferredGroupVersions returns the preferred versions of all registered
// groups in the form of "group1/version1,group2/version2,..."
func (m *APIRegistrationManager) AllPreferredGroupVersions() string {
if len(m.groupMetaMap) == 0 {
return ""
}
var defaults []string
for _, groupMeta := range m.groupMetaMap {
defaults = append(defaults, groupMeta.GroupVersion.String())
}
sort.Strings(defaults)
return strings.Join(defaults, ",")
}
// ValidateEnvRequestedVersions returns a list of versions that are requested in
// the KUBE_API_VERSIONS environment variable, but not enabled.
func (m *APIRegistrationManager) ValidateEnvRequestedVersions() []unversioned.GroupVersion {
var missingVersions []unversioned.GroupVersion
for _, v := range m.envRequestedVersions {
if _, found := m.enabledVersions[v]; !found {
missingVersions = append(missingVersions, v)
}
}
return missingVersions
}

View file

@ -1,93 +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 apimachinery
import (
"fmt"
"k8s.io/client-go/pkg/api/meta"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
)
// GroupMeta stores the metadata of a group.
type GroupMeta struct {
// GroupVersion represents the preferred version of the group.
GroupVersion unversioned.GroupVersion
// GroupVersions is Group + all versions in that group.
GroupVersions []unversioned.GroupVersion
// Codec is the default codec for serializing output that should use
// the preferred version. Use this Codec when writing to
// disk, a data store that is not dynamically versioned, or in tests.
// This codec can decode any object that the schema is aware of.
Codec runtime.Codec
// SelfLinker can set or get the SelfLink field of all API types.
// TODO: when versioning changes, make this part of each API definition.
// TODO(lavalamp): Combine SelfLinker & ResourceVersioner interfaces, force all uses
// to go through the InterfacesFor method below.
SelfLinker runtime.SelfLinker
// RESTMapper provides the default mapping between REST paths and the objects declared in api.Scheme and all known
// versions.
RESTMapper meta.RESTMapper
// InterfacesFor returns the default Codec and ResourceVersioner for a given version
// string, or an error if the version is not known.
// TODO: make this stop being a func pointer and always use the default
// function provided below once every place that populates this field has been changed.
InterfacesFor func(version unversioned.GroupVersion) (*meta.VersionInterfaces, error)
// InterfacesByVersion stores the per-version interfaces.
InterfacesByVersion map[unversioned.GroupVersion]*meta.VersionInterfaces
}
// DefaultInterfacesFor returns the default Codec and ResourceVersioner for a given version
// string, or an error if the version is not known.
// TODO: Remove the "Default" prefix.
func (gm *GroupMeta) DefaultInterfacesFor(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
if v, ok := gm.InterfacesByVersion[version]; ok {
return v, nil
}
return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, gm.GroupVersions)
}
// AddVersionInterfaces adds the given version to the group. Only call during
// init, after that GroupMeta objects should be immutable. Not thread safe.
// (If you use this, be sure to set .InterfacesFor = .DefaultInterfacesFor)
// TODO: remove the "Interfaces" suffix and make this also maintain the
// .GroupVersions member.
func (gm *GroupMeta) AddVersionInterfaces(version unversioned.GroupVersion, interfaces *meta.VersionInterfaces) error {
if e, a := gm.GroupVersion.Group, version.Group; a != e {
return fmt.Errorf("got a version in group %v, but am in group %v", a, e)
}
if gm.InterfacesByVersion == nil {
gm.InterfacesByVersion = make(map[unversioned.GroupVersion]*meta.VersionInterfaces)
}
gm.InterfacesByVersion[version] = interfaces
// TODO: refactor to make the below error not possible, this function
// should *set* GroupVersions rather than depend on it.
for _, v := range gm.GroupVersions {
if v == version {
return nil
}
}
return fmt.Errorf("added a version interface without the corresponding version %v being in the list %#v", version, gm.GroupVersions)
}

View file

@ -1,21 +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.
*/
// +k8s:deepcopy-gen=package,register
// +k8s:openapi-gen=true
// +groupName=apps.k8s.io
package apps

View file

@ -1,41 +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 install installs the apps API group, making it available as
// an option to all of the API encoding/decoding machinery.
package install
import (
"k8s.io/client-go/pkg/apimachinery/announced"
"k8s.io/client-go/pkg/apis/apps"
"k8s.io/client-go/pkg/apis/apps/v1beta1"
)
func init() {
if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{
GroupName: apps.GroupName,
VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version},
ImportPrefix: "k8s.io/client-go/pkg/apis/apps",
AddInternalObjectsToScheme: apps.AddToScheme,
},
announced.VersionToSchemeFunc{
v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme,
},
).Announce().RegisterAndEnable(); err != nil {
panic(err)
}
}

View file

@ -1,56 +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 apps
import (
"k8s.io/client-go/pkg/api"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
)
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
)
// GroupName is the group name use in this package
const GroupName = "apps"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) unversioned.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) unversioned.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
// TODO this will get cleaned up with the scheme types are fixed
scheme.AddKnownTypes(SchemeGroupVersion,
&StatefulSet{},
&StatefulSetList{},
&api.ListOptions{},
&api.DeleteOptions{},
)
return nil
}

File diff suppressed because it is too large Load diff

View file

@ -1,103 +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 apps
import (
"k8s.io/client-go/pkg/api"
"k8s.io/client-go/pkg/api/unversioned"
)
// +genclient=true
// StatefulSet represents a set of pods with consistent identities.
// Identities are defined as:
// - Network: A single stable DNS and hostname.
// - Storage: As many VolumeClaims as requested.
// The StatefulSet guarantees that a given network identity will always
// map to the same storage identity.
type StatefulSet struct {
unversioned.TypeMeta `json:",inline"`
// +optional
api.ObjectMeta `json:"metadata,omitempty"`
// Spec defines the desired identities of pods in this set.
// +optional
Spec StatefulSetSpec `json:"spec,omitempty"`
// Status is the current status of Pods in this StatefulSet. This data
// may be out of date by some window of time.
// +optional
Status StatefulSetStatus `json:"status,omitempty"`
}
// A StatefulSetSpec is the specification of a StatefulSet.
type StatefulSetSpec struct {
// Replicas is the desired number of replicas of the given Template.
// These are replicas in the sense that they are instantiations of the
// same Template, but individual replicas also have a consistent identity.
// If unspecified, defaults to 1.
// TODO: Consider a rename of this field.
// +optional
Replicas int32 `json:"replicas,omitempty"`
// Selector is a label query over pods that should match the replica count.
// If empty, defaulted to labels on the pod template.
// More info: http://kubernetes.io/docs/user-guide/labels#label-selectors
// +optional
Selector *unversioned.LabelSelector `json:"selector,omitempty"`
// Template is the object that describes the pod that will be created if
// insufficient replicas are detected. Each pod stamped out by the StatefulSet
// will fulfill this Template, but have a unique identity from the rest
// of the StatefulSet.
Template api.PodTemplateSpec `json:"template"`
// VolumeClaimTemplates is a list of claims that pods are allowed to reference.
// The StatefulSet controller is responsible for mapping network identities to
// claims in a way that maintains the identity of a pod. Every claim in
// this list must have at least one matching (by name) volumeMount in one
// container in the template. A claim in this list takes precedence over
// any volumes in the template, with the same name.
// TODO: Define the behavior if a claim already exists with the same name.
// +optional
VolumeClaimTemplates []api.PersistentVolumeClaim `json:"volumeClaimTemplates,omitempty"`
// ServiceName is the name of the service that governs this StatefulSet.
// This service must exist before the StatefulSet, and is responsible for
// the network identity of the set. Pods get DNS/hostnames that follow the
// pattern: pod-specific-string.serviceName.default.svc.cluster.local
// where "pod-specific-string" is managed by the StatefulSet controller.
ServiceName string `json:"serviceName"`
}
// StatefulSetStatus represents the current state of a StatefulSet.
type StatefulSetStatus struct {
// most recent generation observed by this autoscaler.
// +optional
ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
// Replicas is the number of actual replicas.
Replicas int32 `json:"replicas"`
}
// StatefulSetList is a collection of StatefulSets.
type StatefulSetList struct {
unversioned.TypeMeta `json:",inline"`
// +optional
unversioned.ListMeta `json:"metadata,omitempty"`
Items []StatefulSet `json:"items"`
}

View file

@ -1,114 +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 v1beta1
import (
"fmt"
"k8s.io/client-go/pkg/api"
"k8s.io/client-go/pkg/api/unversioned"
v1 "k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/pkg/apis/apps"
"k8s.io/client-go/pkg/conversion"
"k8s.io/client-go/pkg/runtime"
)
func addConversionFuncs(scheme *runtime.Scheme) error {
// Add non-generated conversion functions to handle the *int32 -> int32
// conversion. A pointer is useful in the versioned type so we can default
// it, but a plain int32 is more convenient in the internal type. These
// functions are the same as the autogenerated ones in every other way.
err := scheme.AddConversionFuncs(
Convert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec,
Convert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec,
)
if err != nil {
return err
}
return api.Scheme.AddFieldLabelConversionFunc("apps/v1beta1", "StatefulSet",
func(label, value string) (string, string, error) {
switch label {
case "metadata.name", "metadata.namespace", "status.successful":
return label, value, nil
default:
return "", "", fmt.Errorf("field label not supported: %s", label)
}
},
)
}
func Convert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec(in *StatefulSetSpec, out *apps.StatefulSetSpec, s conversion.Scope) error {
if in.Replicas != nil {
out.Replicas = *in.Replicas
}
if in.Selector != nil {
in, out := &in.Selector, &out.Selector
*out = new(unversioned.LabelSelector)
if err := s.Convert(*in, *out, 0); err != nil {
return err
}
} else {
out.Selector = nil
}
if err := s.Convert(&in.Template, &out.Template, 0); err != nil {
return err
}
if in.VolumeClaimTemplates != nil {
in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates
*out = make([]api.PersistentVolumeClaim, len(*in))
for i := range *in {
if err := s.Convert(&(*in)[i], &(*out)[i], 0); err != nil {
return err
}
}
} else {
out.VolumeClaimTemplates = nil
}
out.ServiceName = in.ServiceName
return nil
}
func Convert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec(in *apps.StatefulSetSpec, out *StatefulSetSpec, s conversion.Scope) error {
out.Replicas = new(int32)
*out.Replicas = in.Replicas
if in.Selector != nil {
in, out := &in.Selector, &out.Selector
*out = new(unversioned.LabelSelector)
if err := s.Convert(*in, *out, 0); err != nil {
return err
}
} else {
out.Selector = nil
}
if err := s.Convert(&in.Template, &out.Template, 0); err != nil {
return err
}
if in.VolumeClaimTemplates != nil {
in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates
*out = make([]v1.PersistentVolumeClaim, len(*in))
for i := range *in {
if err := s.Convert(&(*in)[i], &(*out)[i], 0); err != nil {
return err
}
}
} else {
out.VolumeClaimTemplates = nil
}
out.ServiceName = in.ServiceName
return nil
}

View file

@ -1,47 +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 v1beta1
import (
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
)
func addDefaultingFuncs(scheme *runtime.Scheme) error {
RegisterDefaults(scheme)
return scheme.AddDefaultingFuncs(
SetDefaults_StatefulSet,
)
}
func SetDefaults_StatefulSet(obj *StatefulSet) {
labels := obj.Spec.Template.Labels
if labels != nil {
if obj.Spec.Selector == nil {
obj.Spec.Selector = &unversioned.LabelSelector{
MatchLabels: labels,
}
}
if len(obj.Labels) == 0 {
obj.Labels = labels
}
}
if obj.Spec.Replicas == nil {
obj.Spec.Replicas = new(int32)
*obj.Spec.Replicas = 1
}
}

View file

@ -1,23 +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.
*/
// +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/apps
// +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
// +groupName=apps.k8s.io
package v1beta1

File diff suppressed because it is too large Load diff

View file

@ -1,51 +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 v1beta1
import (
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/pkg/runtime"
versionedwatch "k8s.io/client-go/pkg/watch/versioned"
)
// GroupName is the group name use in this package
const GroupName = "apps"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: "v1beta1"}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addDefaultingFuncs, addConversionFuncs)
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&StatefulSet{},
&StatefulSetList{},
&v1.ListOptions{},
&v1.DeleteOptions{},
&v1.ExportOptions{},
)
versionedwatch.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
func (obj *StatefulSet) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *StatefulSetList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

File diff suppressed because it is too large Load diff

View file

@ -1,103 +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 v1beta1
import (
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/api/v1"
)
// +genclient=true
// StatefulSet represents a set of pods with consistent identities.
// Identities are defined as:
// - Network: A single stable DNS and hostname.
// - Storage: As many VolumeClaims as requested.
// The StatefulSet guarantees that a given network identity will always
// map to the same storage identity.
type StatefulSet struct {
unversioned.TypeMeta `json:",inline"`
// +optional
v1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec defines the desired identities of pods in this set.
// +optional
Spec StatefulSetSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// Status is the current status of Pods in this StatefulSet. This data
// may be out of date by some window of time.
// +optional
Status StatefulSetStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// A StatefulSetSpec is the specification of a StatefulSet.
type StatefulSetSpec struct {
// Replicas is the desired number of replicas of the given Template.
// These are replicas in the sense that they are instantiations of the
// same Template, but individual replicas also have a consistent identity.
// If unspecified, defaults to 1.
// TODO: Consider a rename of this field.
// +optional
Replicas *int32 `json:"replicas,omitempty" protobuf:"varint,1,opt,name=replicas"`
// Selector is a label query over pods that should match the replica count.
// If empty, defaulted to labels on the pod template.
// More info: http://kubernetes.io/docs/user-guide/labels#label-selectors
// +optional
Selector *unversioned.LabelSelector `json:"selector,omitempty" protobuf:"bytes,2,opt,name=selector"`
// Template is the object that describes the pod that will be created if
// insufficient replicas are detected. Each pod stamped out by the StatefulSet
// will fulfill this Template, but have a unique identity from the rest
// of the StatefulSet.
Template v1.PodTemplateSpec `json:"template" protobuf:"bytes,3,opt,name=template"`
// VolumeClaimTemplates is a list of claims that pods are allowed to reference.
// The StatefulSet controller is responsible for mapping network identities to
// claims in a way that maintains the identity of a pod. Every claim in
// this list must have at least one matching (by name) volumeMount in one
// container in the template. A claim in this list takes precedence over
// any volumes in the template, with the same name.
// TODO: Define the behavior if a claim already exists with the same name.
// +optional
VolumeClaimTemplates []v1.PersistentVolumeClaim `json:"volumeClaimTemplates,omitempty" protobuf:"bytes,4,rep,name=volumeClaimTemplates"`
// ServiceName is the name of the service that governs this StatefulSet.
// This service must exist before the StatefulSet, and is responsible for
// the network identity of the set. Pods get DNS/hostnames that follow the
// pattern: pod-specific-string.serviceName.default.svc.cluster.local
// where "pod-specific-string" is managed by the StatefulSet controller.
ServiceName string `json:"serviceName" protobuf:"bytes,5,opt,name=serviceName"`
}
// StatefulSetStatus represents the current state of a StatefulSet.
type StatefulSetStatus struct {
// most recent generation observed by this autoscaler.
// +optional
ObservedGeneration *int64 `json:"observedGeneration,omitempty" protobuf:"varint,1,opt,name=observedGeneration"`
// Replicas is the number of actual replicas.
Replicas int32 `json:"replicas" protobuf:"varint,2,opt,name=replicas"`
}
// StatefulSetList is a collection of StatefulSets.
type StatefulSetList struct {
unversioned.TypeMeta `json:",inline"`
// +optional
unversioned.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Items []StatefulSet `json:"items" protobuf:"bytes,2,rep,name=items"`
}

View file

@ -1,71 +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 v1beta1
// This file contains a collection of methods that can be used from go-restful to
// generate Swagger API documentation for its models. Please read this PR for more
// information on the implementation: https://github.com/emicklei/go-restful/pull/215
//
// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if
// they are on one line! For multiple line or blocks that you want to ignore use ---.
// Any context after a --- is ignored.
//
// Those methods can be generated by using hack/update-generated-swagger-docs.sh
// AUTO-GENERATED FUNCTIONS START HERE
var map_StatefulSet = map[string]string{
"": "StatefulSet represents a set of pods with consistent identities. Identities are defined as:\n - Network: A single stable DNS and hostname.\n - Storage: As many VolumeClaims as requested.\nThe StatefulSet guarantees that a given network identity will always map to the same storage identity.",
"spec": "Spec defines the desired identities of pods in this set.",
"status": "Status is the current status of Pods in this StatefulSet. This data may be out of date by some window of time.",
}
func (StatefulSet) SwaggerDoc() map[string]string {
return map_StatefulSet
}
var map_StatefulSetList = map[string]string{
"": "StatefulSetList is a collection of StatefulSets.",
}
func (StatefulSetList) SwaggerDoc() map[string]string {
return map_StatefulSetList
}
var map_StatefulSetSpec = map[string]string{
"": "A StatefulSetSpec is the specification of a StatefulSet.",
"replicas": "Replicas is the desired number of replicas of the given Template. These are replicas in the sense that they are instantiations of the same Template, but individual replicas also have a consistent identity. If unspecified, defaults to 1.",
"selector": "Selector is a label query over pods that should match the replica count. If empty, defaulted to labels on the pod template. More info: http://kubernetes.io/docs/user-guide/labels#label-selectors",
"template": "Template is the object that describes the pod that will be created if insufficient replicas are detected. Each pod stamped out by the StatefulSet will fulfill this Template, but have a unique identity from the rest of the StatefulSet.",
"volumeClaimTemplates": "VolumeClaimTemplates is a list of claims that pods are allowed to reference. The StatefulSet controller is responsible for mapping network identities to claims in a way that maintains the identity of a pod. Every claim in this list must have at least one matching (by name) volumeMount in one container in the template. A claim in this list takes precedence over any volumes in the template, with the same name.",
"serviceName": "ServiceName is the name of the service that governs this StatefulSet. This service must exist before the StatefulSet, and is responsible for the network identity of the set. Pods get DNS/hostnames that follow the pattern: pod-specific-string.serviceName.default.svc.cluster.local where \"pod-specific-string\" is managed by the StatefulSet controller.",
}
func (StatefulSetSpec) SwaggerDoc() map[string]string {
return map_StatefulSetSpec
}
var map_StatefulSetStatus = map[string]string{
"": "StatefulSetStatus represents the current state of a StatefulSet.",
"observedGeneration": "most recent generation observed by this autoscaler.",
"replicas": "Replicas is the number of actual replicas.",
}
func (StatefulSetStatus) SwaggerDoc() map[string]string {
return map_StatefulSetStatus
}
// AUTO-GENERATED FUNCTIONS END HERE

View file

@ -1,172 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by conversion-gen. Do not edit it manually!
package v1beta1
import (
api "k8s.io/client-go/pkg/api"
unversioned "k8s.io/client-go/pkg/api/unversioned"
v1 "k8s.io/client-go/pkg/api/v1"
apps "k8s.io/client-go/pkg/apis/apps"
conversion "k8s.io/client-go/pkg/conversion"
runtime "k8s.io/client-go/pkg/runtime"
unsafe "unsafe"
)
func init() {
SchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1beta1_StatefulSet_To_apps_StatefulSet,
Convert_apps_StatefulSet_To_v1beta1_StatefulSet,
Convert_v1beta1_StatefulSetList_To_apps_StatefulSetList,
Convert_apps_StatefulSetList_To_v1beta1_StatefulSetList,
Convert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec,
Convert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec,
Convert_v1beta1_StatefulSetStatus_To_apps_StatefulSetStatus,
Convert_apps_StatefulSetStatus_To_v1beta1_StatefulSetStatus,
)
}
func autoConvert_v1beta1_StatefulSet_To_apps_StatefulSet(in *StatefulSet, out *apps.StatefulSet, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it?
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_v1beta1_StatefulSetStatus_To_apps_StatefulSetStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
func Convert_v1beta1_StatefulSet_To_apps_StatefulSet(in *StatefulSet, out *apps.StatefulSet, s conversion.Scope) error {
return autoConvert_v1beta1_StatefulSet_To_apps_StatefulSet(in, out, s)
}
func autoConvert_apps_StatefulSet_To_v1beta1_StatefulSet(in *apps.StatefulSet, out *StatefulSet, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it?
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_apps_StatefulSetStatus_To_v1beta1_StatefulSetStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
func Convert_apps_StatefulSet_To_v1beta1_StatefulSet(in *apps.StatefulSet, out *StatefulSet, s conversion.Scope) error {
return autoConvert_apps_StatefulSet_To_v1beta1_StatefulSet(in, out, s)
}
func autoConvert_v1beta1_StatefulSetList_To_apps_StatefulSetList(in *StatefulSetList, out *apps.StatefulSetList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]apps.StatefulSet, len(*in))
for i := range *in {
if err := Convert_v1beta1_StatefulSet_To_apps_StatefulSet(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
func Convert_v1beta1_StatefulSetList_To_apps_StatefulSetList(in *StatefulSetList, out *apps.StatefulSetList, s conversion.Scope) error {
return autoConvert_v1beta1_StatefulSetList_To_apps_StatefulSetList(in, out, s)
}
func autoConvert_apps_StatefulSetList_To_v1beta1_StatefulSetList(in *apps.StatefulSetList, out *StatefulSetList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]StatefulSet, len(*in))
for i := range *in {
if err := Convert_apps_StatefulSet_To_v1beta1_StatefulSet(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
func Convert_apps_StatefulSetList_To_v1beta1_StatefulSetList(in *apps.StatefulSetList, out *StatefulSetList, s conversion.Scope) error {
return autoConvert_apps_StatefulSetList_To_v1beta1_StatefulSetList(in, out, s)
}
func autoConvert_v1beta1_StatefulSetSpec_To_apps_StatefulSetSpec(in *StatefulSetSpec, out *apps.StatefulSetSpec, s conversion.Scope) error {
if err := api.Convert_Pointer_int32_To_int32(&in.Replicas, &out.Replicas, s); err != nil {
return err
}
out.Selector = (*unversioned.LabelSelector)(unsafe.Pointer(in.Selector))
if err := v1.Convert_v1_PodTemplateSpec_To_api_PodTemplateSpec(&in.Template, &out.Template, s); err != nil {
return err
}
out.VolumeClaimTemplates = *(*[]api.PersistentVolumeClaim)(unsafe.Pointer(&in.VolumeClaimTemplates))
out.ServiceName = in.ServiceName
return nil
}
func autoConvert_apps_StatefulSetSpec_To_v1beta1_StatefulSetSpec(in *apps.StatefulSetSpec, out *StatefulSetSpec, s conversion.Scope) error {
if err := api.Convert_int32_To_Pointer_int32(&in.Replicas, &out.Replicas, s); err != nil {
return err
}
out.Selector = (*unversioned.LabelSelector)(unsafe.Pointer(in.Selector))
if err := v1.Convert_api_PodTemplateSpec_To_v1_PodTemplateSpec(&in.Template, &out.Template, s); err != nil {
return err
}
out.VolumeClaimTemplates = *(*[]v1.PersistentVolumeClaim)(unsafe.Pointer(&in.VolumeClaimTemplates))
out.ServiceName = in.ServiceName
return nil
}
func autoConvert_v1beta1_StatefulSetStatus_To_apps_StatefulSetStatus(in *StatefulSetStatus, out *apps.StatefulSetStatus, s conversion.Scope) error {
out.ObservedGeneration = (*int64)(unsafe.Pointer(in.ObservedGeneration))
out.Replicas = in.Replicas
return nil
}
func Convert_v1beta1_StatefulSetStatus_To_apps_StatefulSetStatus(in *StatefulSetStatus, out *apps.StatefulSetStatus, s conversion.Scope) error {
return autoConvert_v1beta1_StatefulSetStatus_To_apps_StatefulSetStatus(in, out, s)
}
func autoConvert_apps_StatefulSetStatus_To_v1beta1_StatefulSetStatus(in *apps.StatefulSetStatus, out *StatefulSetStatus, s conversion.Scope) error {
out.ObservedGeneration = (*int64)(unsafe.Pointer(in.ObservedGeneration))
out.Replicas = in.Replicas
return nil
}
func Convert_apps_StatefulSetStatus_To_v1beta1_StatefulSetStatus(in *apps.StatefulSetStatus, out *StatefulSetStatus, s conversion.Scope) error {
return autoConvert_apps_StatefulSetStatus_To_v1beta1_StatefulSetStatus(in, out, s)
}

View file

@ -1,138 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package v1beta1
import (
unversioned "k8s.io/client-go/pkg/api/unversioned"
v1 "k8s.io/client-go/pkg/api/v1"
conversion "k8s.io/client-go/pkg/conversion"
runtime "k8s.io/client-go/pkg/runtime"
reflect "reflect"
)
func init() {
SchemeBuilder.Register(RegisterDeepCopies)
}
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
// to allow building arbitrary schemes.
func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_StatefulSet, InType: reflect.TypeOf(&StatefulSet{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_StatefulSetList, InType: reflect.TypeOf(&StatefulSetList{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_StatefulSetSpec, InType: reflect.TypeOf(&StatefulSetSpec{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1beta1_StatefulSetStatus, InType: reflect.TypeOf(&StatefulSetStatus{})},
)
}
func DeepCopy_v1beta1_StatefulSet(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*StatefulSet)
out := out.(*StatefulSet)
out.TypeMeta = in.TypeMeta
if err := v1.DeepCopy_v1_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, c); err != nil {
return err
}
if err := DeepCopy_v1beta1_StatefulSetSpec(&in.Spec, &out.Spec, c); err != nil {
return err
}
if err := DeepCopy_v1beta1_StatefulSetStatus(&in.Status, &out.Status, c); err != nil {
return err
}
return nil
}
}
func DeepCopy_v1beta1_StatefulSetList(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*StatefulSetList)
out := out.(*StatefulSetList)
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]StatefulSet, len(*in))
for i := range *in {
if err := DeepCopy_v1beta1_StatefulSet(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
}
func DeepCopy_v1beta1_StatefulSetSpec(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*StatefulSetSpec)
out := out.(*StatefulSetSpec)
if in.Replicas != nil {
in, out := &in.Replicas, &out.Replicas
*out = new(int32)
**out = **in
} else {
out.Replicas = nil
}
if in.Selector != nil {
in, out := &in.Selector, &out.Selector
*out = new(unversioned.LabelSelector)
if err := unversioned.DeepCopy_unversioned_LabelSelector(*in, *out, c); err != nil {
return err
}
} else {
out.Selector = nil
}
if err := v1.DeepCopy_v1_PodTemplateSpec(&in.Template, &out.Template, c); err != nil {
return err
}
if in.VolumeClaimTemplates != nil {
in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates
*out = make([]v1.PersistentVolumeClaim, len(*in))
for i := range *in {
if err := v1.DeepCopy_v1_PersistentVolumeClaim(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.VolumeClaimTemplates = nil
}
out.ServiceName = in.ServiceName
return nil
}
}
func DeepCopy_v1beta1_StatefulSetStatus(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*StatefulSetStatus)
out := out.(*StatefulSetStatus)
if in.ObservedGeneration != nil {
in, out := &in.ObservedGeneration, &out.ObservedGeneration
*out = new(int64)
**out = **in
} else {
out.ObservedGeneration = nil
}
out.Replicas = in.Replicas
return nil
}
}

View file

@ -1,166 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by defaulter-gen. Do not edit it manually!
package v1beta1
import (
v1 "k8s.io/client-go/pkg/api/v1"
runtime "k8s.io/client-go/pkg/runtime"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&StatefulSet{}, func(obj interface{}) { SetObjectDefaults_StatefulSet(obj.(*StatefulSet)) })
scheme.AddTypeDefaultingFunc(&StatefulSetList{}, func(obj interface{}) { SetObjectDefaults_StatefulSetList(obj.(*StatefulSetList)) })
return nil
}
func SetObjectDefaults_StatefulSet(in *StatefulSet) {
SetDefaults_StatefulSet(in)
v1.SetDefaults_PodSpec(&in.Spec.Template.Spec)
for i := range in.Spec.Template.Spec.Volumes {
a := &in.Spec.Template.Spec.Volumes[i]
v1.SetDefaults_Volume(a)
if a.VolumeSource.Secret != nil {
v1.SetDefaults_SecretVolumeSource(a.VolumeSource.Secret)
}
if a.VolumeSource.ISCSI != nil {
v1.SetDefaults_ISCSIVolumeSource(a.VolumeSource.ISCSI)
}
if a.VolumeSource.RBD != nil {
v1.SetDefaults_RBDVolumeSource(a.VolumeSource.RBD)
}
if a.VolumeSource.DownwardAPI != nil {
v1.SetDefaults_DownwardAPIVolumeSource(a.VolumeSource.DownwardAPI)
for j := range a.VolumeSource.DownwardAPI.Items {
b := &a.VolumeSource.DownwardAPI.Items[j]
if b.FieldRef != nil {
v1.SetDefaults_ObjectFieldSelector(b.FieldRef)
}
}
}
if a.VolumeSource.ConfigMap != nil {
v1.SetDefaults_ConfigMapVolumeSource(a.VolumeSource.ConfigMap)
}
if a.VolumeSource.AzureDisk != nil {
v1.SetDefaults_AzureDiskVolumeSource(a.VolumeSource.AzureDisk)
}
}
for i := range in.Spec.Template.Spec.InitContainers {
a := &in.Spec.Template.Spec.InitContainers[i]
v1.SetDefaults_Container(a)
for j := range a.Ports {
b := &a.Ports[j]
v1.SetDefaults_ContainerPort(b)
}
for j := range a.Env {
b := &a.Env[j]
if b.ValueFrom != nil {
if b.ValueFrom.FieldRef != nil {
v1.SetDefaults_ObjectFieldSelector(b.ValueFrom.FieldRef)
}
}
}
v1.SetDefaults_ResourceList(&a.Resources.Limits)
v1.SetDefaults_ResourceList(&a.Resources.Requests)
if a.LivenessProbe != nil {
v1.SetDefaults_Probe(a.LivenessProbe)
if a.LivenessProbe.Handler.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.LivenessProbe.Handler.HTTPGet)
}
}
if a.ReadinessProbe != nil {
v1.SetDefaults_Probe(a.ReadinessProbe)
if a.ReadinessProbe.Handler.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.ReadinessProbe.Handler.HTTPGet)
}
}
if a.Lifecycle != nil {
if a.Lifecycle.PostStart != nil {
if a.Lifecycle.PostStart.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.Lifecycle.PostStart.HTTPGet)
}
}
if a.Lifecycle.PreStop != nil {
if a.Lifecycle.PreStop.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.Lifecycle.PreStop.HTTPGet)
}
}
}
}
for i := range in.Spec.Template.Spec.Containers {
a := &in.Spec.Template.Spec.Containers[i]
v1.SetDefaults_Container(a)
for j := range a.Ports {
b := &a.Ports[j]
v1.SetDefaults_ContainerPort(b)
}
for j := range a.Env {
b := &a.Env[j]
if b.ValueFrom != nil {
if b.ValueFrom.FieldRef != nil {
v1.SetDefaults_ObjectFieldSelector(b.ValueFrom.FieldRef)
}
}
}
v1.SetDefaults_ResourceList(&a.Resources.Limits)
v1.SetDefaults_ResourceList(&a.Resources.Requests)
if a.LivenessProbe != nil {
v1.SetDefaults_Probe(a.LivenessProbe)
if a.LivenessProbe.Handler.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.LivenessProbe.Handler.HTTPGet)
}
}
if a.ReadinessProbe != nil {
v1.SetDefaults_Probe(a.ReadinessProbe)
if a.ReadinessProbe.Handler.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.ReadinessProbe.Handler.HTTPGet)
}
}
if a.Lifecycle != nil {
if a.Lifecycle.PostStart != nil {
if a.Lifecycle.PostStart.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.Lifecycle.PostStart.HTTPGet)
}
}
if a.Lifecycle.PreStop != nil {
if a.Lifecycle.PreStop.HTTPGet != nil {
v1.SetDefaults_HTTPGetAction(a.Lifecycle.PreStop.HTTPGet)
}
}
}
}
for i := range in.Spec.VolumeClaimTemplates {
a := &in.Spec.VolumeClaimTemplates[i]
v1.SetDefaults_PersistentVolumeClaim(a)
v1.SetDefaults_ResourceList(&a.Spec.Resources.Limits)
v1.SetDefaults_ResourceList(&a.Spec.Resources.Requests)
v1.SetDefaults_ResourceList(&a.Status.Capacity)
}
}
func SetObjectDefaults_StatefulSetList(in *StatefulSetList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_StatefulSet(a)
}
}

View file

@ -1,132 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 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.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package apps
import (
api "k8s.io/client-go/pkg/api"
unversioned "k8s.io/client-go/pkg/api/unversioned"
conversion "k8s.io/client-go/pkg/conversion"
runtime "k8s.io/client-go/pkg/runtime"
reflect "reflect"
)
func init() {
SchemeBuilder.Register(RegisterDeepCopies)
}
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
// to allow building arbitrary schemes.
func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_apps_StatefulSet, InType: reflect.TypeOf(&StatefulSet{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_apps_StatefulSetList, InType: reflect.TypeOf(&StatefulSetList{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_apps_StatefulSetSpec, InType: reflect.TypeOf(&StatefulSetSpec{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_apps_StatefulSetStatus, InType: reflect.TypeOf(&StatefulSetStatus{})},
)
}
func DeepCopy_apps_StatefulSet(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*StatefulSet)
out := out.(*StatefulSet)
out.TypeMeta = in.TypeMeta
if err := api.DeepCopy_api_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, c); err != nil {
return err
}
if err := DeepCopy_apps_StatefulSetSpec(&in.Spec, &out.Spec, c); err != nil {
return err
}
if err := DeepCopy_apps_StatefulSetStatus(&in.Status, &out.Status, c); err != nil {
return err
}
return nil
}
}
func DeepCopy_apps_StatefulSetList(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*StatefulSetList)
out := out.(*StatefulSetList)
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]StatefulSet, len(*in))
for i := range *in {
if err := DeepCopy_apps_StatefulSet(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
}
func DeepCopy_apps_StatefulSetSpec(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*StatefulSetSpec)
out := out.(*StatefulSetSpec)
out.Replicas = in.Replicas
if in.Selector != nil {
in, out := &in.Selector, &out.Selector
*out = new(unversioned.LabelSelector)
if err := unversioned.DeepCopy_unversioned_LabelSelector(*in, *out, c); err != nil {
return err
}
} else {
out.Selector = nil
}
if err := api.DeepCopy_api_PodTemplateSpec(&in.Template, &out.Template, c); err != nil {
return err
}
if in.VolumeClaimTemplates != nil {
in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates
*out = make([]api.PersistentVolumeClaim, len(*in))
for i := range *in {
if err := api.DeepCopy_api_PersistentVolumeClaim(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.VolumeClaimTemplates = nil
}
out.ServiceName = in.ServiceName
return nil
}
}
func DeepCopy_apps_StatefulSetStatus(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*StatefulSetStatus)
out := out.(*StatefulSetStatus)
if in.ObservedGeneration != nil {
in, out := &in.ObservedGeneration, &out.ObservedGeneration
*out = new(int64)
**out = **in
} else {
out.ObservedGeneration = nil
}
out.Replicas = in.Replicas
return nil
}
}

View file

@ -1,20 +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.
*/
// +k8s:deepcopy-gen=package,register
// +groupName=authentication.k8s.io
// +k8s:openapi-gen=true
package authentication

View file

@ -1,43 +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 install installs the experimental API group, making it available as
// an option to all of the API encoding/decoding machinery.
package install
import (
"k8s.io/client-go/pkg/apimachinery/announced"
"k8s.io/client-go/pkg/apis/authentication"
"k8s.io/client-go/pkg/apis/authentication/v1beta1"
"k8s.io/client-go/pkg/util/sets"
)
func init() {
if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{
GroupName: authentication.GroupName,
VersionPreferenceOrder: []string{v1beta1.SchemeGroupVersion.Version},
ImportPrefix: "k8s.io/client-go/pkg/apis/authentication",
RootScopedKinds: sets.NewString("TokenReview"),
AddInternalObjectsToScheme: authentication.AddToScheme,
},
announced.VersionToSchemeFunc{
v1beta1.SchemeGroupVersion.Version: v1beta1.AddToScheme,
},
).Announce().RegisterAndEnable(); err != nil {
panic(err)
}
}

View file

@ -1,55 +0,0 @@
/*
Copyright 2015 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 authentication
import (
"k8s.io/client-go/pkg/api"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/runtime"
)
// GroupName is the group name use in this package
const GroupName = "authentication.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) unversioned.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) unversioned.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
)
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&api.ListOptions{},
&api.DeleteOptions{},
&api.ExportOptions{},
&TokenReview{},
)
return nil
}

File diff suppressed because it is too large Load diff

View file

@ -1,90 +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 authentication
import (
"k8s.io/client-go/pkg/api"
"k8s.io/client-go/pkg/api/unversioned"
)
const (
// ImpersonateUserHeader is used to impersonate a particular user during an API server request
ImpersonateUserHeader = "Impersonate-User"
// ImpersonateGroupHeader is used to impersonate a particular group during an API server request.
// It can be repeated multiplied times for multiple groups.
ImpersonateGroupHeader = "Impersonate-Group"
// ImpersonateUserExtraHeaderPrefix is a prefix for any header used to impersonate an entry in the
// extra map[string][]string for user.Info. The key will be every after the prefix.
// It can be repeated multiplied times for multiple map keys and the same key can be repeated multiple
// times to have multiple elements in the slice under a single key
ImpersonateUserExtraHeaderPrefix = "Impersonate-Extra-"
)
// +genclient=true
// +nonNamespaced=true
// +noMethods=true
// TokenReview attempts to authenticate a token to a known user.
type TokenReview struct {
unversioned.TypeMeta
// ObjectMeta fulfills the meta.ObjectMetaAccessor interface so that the stock
// REST handler paths work
api.ObjectMeta
// Spec holds information about the request being evaluated
Spec TokenReviewSpec
// Status is filled in by the server and indicates whether the request can be authenticated.
Status TokenReviewStatus
}
// TokenReviewSpec is a description of the token authentication request.
type TokenReviewSpec struct {
// Token is the opaque bearer token.
Token string
}
// TokenReviewStatus is the result of the token authentication request.
// This type mirrors the authentication.Token interface
type TokenReviewStatus struct {
// Authenticated indicates that the token was associated with a known user.
Authenticated bool
// User is the UserInfo associated with the provided token.
User UserInfo
// Error indicates that the token couldn't be checked
Error string
}
// UserInfo holds the information about the user needed to implement the
// user.Info interface.
type UserInfo struct {
// The name that uniquely identifies this user among all active users.
Username string
// A unique value that identifies this user across time. If this user is
// deleted and another user by the same name is added, they will have
// different UIDs.
UID string
// The names of groups this user is a part of.
Groups []string
// Any additional information provided by the authenticator.
Extra map[string]ExtraValue
}
// ExtraValue masks the value so protobuf can generate
type ExtraValue []string

View file

@ -1,26 +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 v1beta1
import (
"k8s.io/client-go/pkg/runtime"
)
func addConversionFuncs(scheme *runtime.Scheme) error {
// Add non-generated conversion functions
return scheme.AddConversionFuncs()
}

View file

@ -1,25 +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 v1beta1
import (
"k8s.io/client-go/pkg/runtime"
)
func addDefaultingFuncs(scheme *runtime.Scheme) error {
return scheme.AddDefaultingFuncs()
}

View file

@ -1,22 +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.
*/
// +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/authentication
// +groupName=authentication.k8s.io
// +k8s:openapi-gen=true
// +k8s:defaulter-gen=TypeMeta
package v1beta1

File diff suppressed because it is too large Load diff

View file

@ -1,46 +0,0 @@
/*
Copyright 2015 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 v1beta1
import (
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/pkg/runtime"
)
// GroupName is the group name use in this package
const GroupName = "authentication.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: "v1beta1"}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addDefaultingFuncs, addConversionFuncs)
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&v1.ListOptions{},
&v1.DeleteOptions{},
&v1.ExportOptions{},
&TokenReview{},
)
return nil
}

File diff suppressed because it is too large Load diff

View file

@ -1,92 +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 v1beta1
import (
"fmt"
"k8s.io/client-go/pkg/api/unversioned"
"k8s.io/client-go/pkg/api/v1"
)
// +genclient=true
// +nonNamespaced=true
// +noMethods=true
// TokenReview attempts to authenticate a token to a known user.
// Note: TokenReview requests may be cached by the webhook token authenticator
// plugin in the kube-apiserver.
type TokenReview struct {
unversioned.TypeMeta `json:",inline"`
// +optional
v1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec holds information about the request being evaluated
Spec TokenReviewSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
// Status is filled in by the server and indicates whether the request can be authenticated.
// +optional
Status TokenReviewStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// TokenReviewSpec is a description of the token authentication request.
type TokenReviewSpec struct {
// Token is the opaque bearer token.
// +optional
Token string `json:"token,omitempty" protobuf:"bytes,1,opt,name=token"`
}
// TokenReviewStatus is the result of the token authentication request.
type TokenReviewStatus struct {
// Authenticated indicates that the token was associated with a known user.
// +optional
Authenticated bool `json:"authenticated,omitempty" protobuf:"varint,1,opt,name=authenticated"`
// User is the UserInfo associated with the provided token.
// +optional
User UserInfo `json:"user,omitempty" protobuf:"bytes,2,opt,name=user"`
// Error indicates that the token couldn't be checked
// +optional
Error string `json:"error,omitempty" protobuf:"bytes,3,opt,name=error"`
}
// UserInfo holds the information about the user needed to implement the
// user.Info interface.
type UserInfo struct {
// The name that uniquely identifies this user among all active users.
// +optional
Username string `json:"username,omitempty" protobuf:"bytes,1,opt,name=username"`
// A unique value that identifies this user across time. If this user is
// deleted and another user by the same name is added, they will have
// different UIDs.
// +optional
UID string `json:"uid,omitempty" protobuf:"bytes,2,opt,name=uid"`
// The names of groups this user is a part of.
// +optional
Groups []string `json:"groups,omitempty" protobuf:"bytes,3,rep,name=groups"`
// Any additional information provided by the authenticator.
// +optional
Extra map[string]ExtraValue `json:"extra,omitempty" protobuf:"bytes,4,rep,name=extra"`
}
// ExtraValue masks the value so protobuf can generate
// +protobuf.nullable=true
// +protobuf.options.(gogoproto.goproto_stringer)=false
type ExtraValue []string
func (t ExtraValue) String() string {
return fmt.Sprintf("%v", []string(t))
}

View file

@ -1,72 +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 v1beta1
// This file contains a collection of methods that can be used from go-restful to
// generate Swagger API documentation for its models. Please read this PR for more
// information on the implementation: https://github.com/emicklei/go-restful/pull/215
//
// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if
// they are on one line! For multiple line or blocks that you want to ignore use ---.
// Any context after a --- is ignored.
//
// Those methods can be generated by using hack/update-generated-swagger-docs.sh
// AUTO-GENERATED FUNCTIONS START HERE
var map_TokenReview = map[string]string{
"": "TokenReview attempts to authenticate a token to a known user. Note: TokenReview requests may be cached by the webhook token authenticator plugin in the kube-apiserver.",
"spec": "Spec holds information about the request being evaluated",
"status": "Status is filled in by the server and indicates whether the request can be authenticated.",
}
func (TokenReview) SwaggerDoc() map[string]string {
return map_TokenReview
}
var map_TokenReviewSpec = map[string]string{
"": "TokenReviewSpec is a description of the token authentication request.",
"token": "Token is the opaque bearer token.",
}
func (TokenReviewSpec) SwaggerDoc() map[string]string {
return map_TokenReviewSpec
}
var map_TokenReviewStatus = map[string]string{
"": "TokenReviewStatus is the result of the token authentication request.",
"authenticated": "Authenticated indicates that the token was associated with a known user.",
"user": "User is the UserInfo associated with the provided token.",
"error": "Error indicates that the token couldn't be checked",
}
func (TokenReviewStatus) SwaggerDoc() map[string]string {
return map_TokenReviewStatus
}
var map_UserInfo = map[string]string{
"": "UserInfo holds the information about the user needed to implement the user.Info interface.",
"username": "The name that uniquely identifies this user among all active users.",
"uid": "A unique value that identifies this user across time. If this user is deleted and another user by the same name is added, they will have different UIDs.",
"groups": "The names of groups this user is a part of.",
"extra": "Any additional information provided by the authenticator.",
}
func (UserInfo) SwaggerDoc() map[string]string {
return map_UserInfo
}
// AUTO-GENERATED FUNCTIONS END HERE

Some files were not shown because too many files have changed in this diff Show more