Move Ingress godeps to vendor/

This commit is contained in:
Manuel de Brito Fontes 2016-05-10 10:30:56 -03:00
parent 0d4f49e50e
commit ca620e4074
2059 changed files with 3706 additions and 213845 deletions

6
vendor/k8s.io/kubernetes/pkg/api/OWNERS generated vendored Normal file
View file

@ -0,0 +1,6 @@
assignees:
- bgrant0607
- erictune
- lavalamp
- smarterclayton
- thockin

121
vendor/k8s.io/kubernetes/pkg/api/context.go generated vendored Normal file
View file

@ -0,0 +1,121 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/auth/user"
)
// 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
// namespaceKey is the context key for the request namespace.
const namespaceKey key = 0
// userKey is the context key for the request user.
const userKey key = 1
// 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
}

164
vendor/k8s.io/kubernetes/pkg/api/conversion.go generated vendored Normal file
View file

@ -0,0 +1,164 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/util/intstr"
)
func init() {
Scheme.AddDefaultingFuncs(
func(obj *ListOptions) {
if obj.LabelSelector == nil {
obj.LabelSelector = labels.Everything()
}
if obj.FieldSelector == nil {
obj.FieldSelector = fields.Everything()
}
},
)
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_string_To_labels_Selector,
Convert_string_To_fields_Selector,
Convert_Pointer_bool_To_bool,
Convert_bool_To_Pointer_bool,
Convert_Pointer_string_To_string,
Convert_string_To_Pointer_string,
Convert_labels_Selector_To_string,
Convert_fields_Selector_To_string,
Convert_resource_Quantity_To_resource_Quantity,
)
}
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
}
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
}
func Convert_unversioned_ListMeta_To_unversioned_ListMeta(in, out *unversioned.ListMeta, s conversion.Scope) error {
out.ResourceVersion = in.ResourceVersion
out.SelfLink = in.SelfLink
return nil
}
func Convert_intstr_IntOrString_To_intstr_IntOrString(in, out *intstr.IntOrString, s conversion.Scope) error {
out.Type = in.Type
out.IntVal = in.IntVal
out.StrVal = in.StrVal
return nil
}
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
}
func Convert_resource_Quantity_To_resource_Quantity(in *resource.Quantity, out *resource.Quantity, s conversion.Scope) error {
// Cannot deep copy these, because inf.Dec has unexported fields.
*out = *in.Copy()
return nil
}

3143
vendor/k8s.io/kubernetes/pkg/api/deep_copy_generated.go generated vendored Normal file

File diff suppressed because it is too large Load diff

22
vendor/k8s.io/kubernetes/pkg/api/doc.go generated vendored Normal file
View file

@ -0,0 +1,22 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 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

238
vendor/k8s.io/kubernetes/pkg/api/endpoints/util.go generated vendored Normal file
View file

@ -0,0 +1,238 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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 endpoints
import (
"bytes"
"crypto/md5"
"encoding/hex"
"hash"
"sort"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/types"
hashutil "k8s.io/kubernetes/pkg/util/hash"
)
const (
// TODO: to be deleted after v1.3 is released
// Its value is the json representation of map[string(IP)][HostRecord]
// example: '{"10.245.1.6":{"HostName":"my-webserver"}}'
PodHostnamesAnnotation = "endpoints.beta.kubernetes.io/hostnames-map"
)
// TODO: to be deleted after v1.3 is released
type HostRecord struct {
HostName string
}
// RepackSubsets takes a slice of EndpointSubset objects, expands it to the full
// representation, and then repacks that into the canonical layout. This
// ensures that code which operates on these objects can rely on the common
// form for things like comparison. The result is a newly allocated slice.
func RepackSubsets(subsets []api.EndpointSubset) []api.EndpointSubset {
// First map each unique port definition to the sets of hosts that
// offer it.
allAddrs := map[addressKey]*api.EndpointAddress{}
portToAddrReadyMap := map[api.EndpointPort]addressSet{}
for i := range subsets {
for _, port := range subsets[i].Ports {
for k := range subsets[i].Addresses {
mapAddressByPort(&subsets[i].Addresses[k], port, true, allAddrs, portToAddrReadyMap)
}
for k := range subsets[i].NotReadyAddresses {
mapAddressByPort(&subsets[i].NotReadyAddresses[k], port, false, allAddrs, portToAddrReadyMap)
}
}
}
// Next, map the sets of hosts to the sets of ports they offer.
// Go does not allow maps or slices as keys to maps, so we have
// to synthesize an artificial key and do a sort of 2-part
// associative entity.
type keyString string
keyToAddrReadyMap := map[keyString]addressSet{}
addrReadyMapKeyToPorts := map[keyString][]api.EndpointPort{}
for port, addrs := range portToAddrReadyMap {
key := keyString(hashAddresses(addrs))
keyToAddrReadyMap[key] = addrs
addrReadyMapKeyToPorts[key] = append(addrReadyMapKeyToPorts[key], port)
}
// Next, build the N-to-M association the API wants.
final := []api.EndpointSubset{}
for key, ports := range addrReadyMapKeyToPorts {
var readyAddrs, notReadyAddrs []api.EndpointAddress
for addr, ready := range keyToAddrReadyMap[key] {
if ready {
readyAddrs = append(readyAddrs, *addr)
} else {
notReadyAddrs = append(notReadyAddrs, *addr)
}
}
final = append(final, api.EndpointSubset{Addresses: readyAddrs, NotReadyAddresses: notReadyAddrs, Ports: ports})
}
// Finally, sort it.
return SortSubsets(final)
}
// The sets of hosts must be de-duped, using IP+UID as the key.
type addressKey struct {
ip string
uid types.UID
}
// mapAddressByPort adds an address into a map by its ports, registering the address with a unique pointer, and preserving
// any existing ready state.
func mapAddressByPort(addr *api.EndpointAddress, port api.EndpointPort, ready bool, allAddrs map[addressKey]*api.EndpointAddress, portToAddrReadyMap map[api.EndpointPort]addressSet) *api.EndpointAddress {
// use addressKey to distinguish between two endpoints that are identical addresses
// but may have come from different hosts, for attribution. For instance, Mesos
// assigns pods the node IP, but the pods are distinct.
key := addressKey{ip: addr.IP}
if addr.TargetRef != nil {
key.uid = addr.TargetRef.UID
}
// Accumulate the address. The full EndpointAddress structure is preserved for use when
// we rebuild the subsets so that the final TargetRef has all of the necessary data.
existingAddress := allAddrs[key]
if existingAddress == nil {
// Make a copy so we don't write to the
// input args of this function.
existingAddress = &api.EndpointAddress{}
*existingAddress = *addr
allAddrs[key] = existingAddress
}
// Remember that this port maps to this address.
if _, found := portToAddrReadyMap[port]; !found {
portToAddrReadyMap[port] = addressSet{}
}
// if we have not yet recorded this port for this address, or if the previous
// state was ready, write the current ready state. not ready always trumps
// ready.
if wasReady, found := portToAddrReadyMap[port][existingAddress]; !found || wasReady {
portToAddrReadyMap[port][existingAddress] = ready
}
return existingAddress
}
type addressSet map[*api.EndpointAddress]bool
type addrReady struct {
addr *api.EndpointAddress
ready bool
}
func hashAddresses(addrs addressSet) string {
// Flatten the list of addresses into a string so it can be used as a
// map key. Unfortunately, DeepHashObject is implemented in terms of
// spew, and spew does not handle non-primitive map keys well. So
// first we collapse it into a slice, sort the slice, then hash that.
slice := make([]addrReady, 0, len(addrs))
for k, ready := range addrs {
slice = append(slice, addrReady{k, ready})
}
sort.Sort(addrsReady(slice))
hasher := md5.New()
hashutil.DeepHashObject(hasher, slice)
return hex.EncodeToString(hasher.Sum(nil)[0:])
}
func lessAddrReady(a, b addrReady) bool {
// ready is not significant to hashing since we can't have duplicate addresses
return LessEndpointAddress(a.addr, b.addr)
}
type addrsReady []addrReady
func (sl addrsReady) Len() int { return len(sl) }
func (sl addrsReady) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
func (sl addrsReady) Less(i, j int) bool {
return lessAddrReady(sl[i], sl[j])
}
func LessEndpointAddress(a, b *api.EndpointAddress) bool {
ipComparison := bytes.Compare([]byte(a.IP), []byte(b.IP))
if ipComparison != 0 {
return ipComparison < 0
}
if b.TargetRef == nil {
return false
}
if a.TargetRef == nil {
return true
}
return a.TargetRef.UID < b.TargetRef.UID
}
type addrPtrsByIpAndUID []*api.EndpointAddress
func (sl addrPtrsByIpAndUID) Len() int { return len(sl) }
func (sl addrPtrsByIpAndUID) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
func (sl addrPtrsByIpAndUID) Less(i, j int) bool {
return LessEndpointAddress(sl[i], sl[j])
}
// SortSubsets sorts an array of EndpointSubset objects in place. For ease of
// use it returns the input slice.
func SortSubsets(subsets []api.EndpointSubset) []api.EndpointSubset {
for i := range subsets {
ss := &subsets[i]
sort.Sort(addrsByIpAndUID(ss.Addresses))
sort.Sort(addrsByIpAndUID(ss.NotReadyAddresses))
sort.Sort(portsByHash(ss.Ports))
}
sort.Sort(subsetsByHash(subsets))
return subsets
}
func hashObject(hasher hash.Hash, obj interface{}) []byte {
hashutil.DeepHashObject(hasher, obj)
return hasher.Sum(nil)
}
type subsetsByHash []api.EndpointSubset
func (sl subsetsByHash) Len() int { return len(sl) }
func (sl subsetsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
func (sl subsetsByHash) Less(i, j int) bool {
hasher := md5.New()
h1 := hashObject(hasher, sl[i])
h2 := hashObject(hasher, sl[j])
return bytes.Compare(h1, h2) < 0
}
type addrsByIpAndUID []api.EndpointAddress
func (sl addrsByIpAndUID) Len() int { return len(sl) }
func (sl addrsByIpAndUID) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
func (sl addrsByIpAndUID) Less(i, j int) bool {
return LessEndpointAddress(&sl[i], &sl[j])
}
type portsByHash []api.EndpointPort
func (sl portsByHash) Len() int { return len(sl) }
func (sl portsByHash) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] }
func (sl portsByHash) Less(i, j int) bool {
hasher := md5.New()
h1 := hashObject(hasher, sl[i])
h2 := hashObject(hasher, sl[j])
return bytes.Compare(h1, h2) < 0
}

18
vendor/k8s.io/kubernetes/pkg/api/errors/doc.go generated vendored Normal file
View file

@ -0,0 +1,18 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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

456
vendor/k8s.io/kubernetes/pkg/api/errors/errors.go generated vendored Normal file
View file

@ -0,0 +1,456 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/validation/field"
)
// HTTP Status codes not in the golang http package.
const (
StatusUnprocessableEntity = 422
StatusTooManyRequests = 429
// HTTP recommendations are for servers to define 5xx error codes
// for scenarios not covered by behavior. In this case, ServerTimeout
// 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) error {
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) error {
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) error {
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) error {
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) error {
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) error {
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) error {
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) error {
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) error {
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) error {
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) error {
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) error {
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) error {
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) error {
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) error {
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 = "an error on the server has prevented the request from succeeding"
}
}
switch {
case !qualifiedResource.IsEmpty() && len(name) > 0:
message = fmt.Sprintf("%s (%s %s %s)", message, strings.ToLower(verb), qualifiedResource.String(), name)
case !qualifiedResource.IsEmpty():
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
}
// 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
}

38
vendor/k8s.io/kubernetes/pkg/api/field_constants.go generated vendored Normal file
View file

@ -0,0 +1,38 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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"
)

64
vendor/k8s.io/kubernetes/pkg/api/generate.go generated vendored Normal file
View file

@ -0,0 +1,64 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/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))
}

429
vendor/k8s.io/kubernetes/pkg/api/helpers.go generated vendored Normal file
View file

@ -0,0 +1,429 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/resource"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/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.
if a.Amount == nil && b.MilliValue() == 0 {
return true
}
if b.Amount == nil && a.MilliValue() == 0 {
return true
}
if a.Amount == nil || b.Amount == nil {
return false
}
return a.Amount.Cmp(b.Amount) == 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)
}
var standardLimitRangeTypes = sets.NewString(
string(LimitTypePod),
string(LimitTypeContainer),
)
// 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(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),
)
// 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)
}
// 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 {
return service.Spec.ClusterIP == ""
}
var standardFinalizers = sets.NewString(
string(FinalizerKubernetes))
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 labels.Operator
switch expr.Operator {
case NodeSelectorOpIn:
op = labels.InOperator
case NodeSelectorOpNotIn:
op = labels.NotInOperator
case NodeSelectorOpExists:
op = labels.ExistsOperator
case NodeSelectorOpDoesNotExist:
op = labels.DoesNotExistOperator
case NodeSelectorOpGt:
op = labels.GreaterThanOperator
case NodeSelectorOpLt:
op = labels.LessThanOperator
default:
return nil, fmt.Errorf("%q is not a valid node selector operator", expr.Operator)
}
r, err := labels.NewRequirement(expr.Key, op, sets.NewString(expr.Values...))
if err != nil {
return nil, err
}
selector = selector.Add(*r)
}
return selector, nil
}
// AffinityAnnotationKey represents the key of affinity data (json serialized)
// in the Annotations of a Pod.
const AffinityAnnotationKey string = "scheduler.alpha.kubernetes.io/affinity"
// 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) {
var affinity Affinity
if len(annotations) > 0 && annotations[AffinityAnnotationKey] != "" {
err := json.Unmarshal([]byte(annotations[AffinityAnnotationKey]), &affinity)
if err != nil {
return affinity, err
}
}
return affinity, nil
}

239
vendor/k8s.io/kubernetes/pkg/api/install/install.go generated vendored Normal file
View file

@ -0,0 +1,239 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/apimachinery"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/sets"
)
const importPrefix = "k8s.io/kubernetes/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
}
api.RegisterRESTMapper(groupMeta.RESTMapper)
return nil
}
// userResources is a group of resources mostly used by a kubectl user
var userResources = []string{"rc", "svc", "pods", "pvc"}
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)
// setup aliases for groups of resources
mapper.AddResourceAlias("all", userResources...)
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
api.AddToScheme(api.Scheme)
// 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:
v1.AddToScheme(api.Scheme)
}
}
// 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
api.Scheme.AddGenericConversionFunc(func(objA, objB interface{}, s conversion.Scope) (bool, error) {
switch a := objA.(type) {
case *v1.Pod:
switch b := objB.(type) {
case *api.Pod:
return true, v1.Convert_v1_Pod_To_api_Pod(a, b, s)
}
case *api.Pod:
switch b := objB.(type) {
case *v1.Pod:
return true, v1.Convert_api_Pod_To_v1_Pod(a, b, s)
}
case *v1.Event:
switch b := objB.(type) {
case *api.Event:
return true, v1.Convert_v1_Event_To_api_Event(a, b, s)
}
case *api.Event:
switch b := objB.(type) {
case *v1.Event:
return true, v1.Convert_api_Event_To_v1_Event(a, b, s)
}
case *v1.ReplicationController:
switch b := objB.(type) {
case *api.ReplicationController:
return true, v1.Convert_v1_ReplicationController_To_api_ReplicationController(a, b, s)
}
case *api.ReplicationController:
switch b := objB.(type) {
case *v1.ReplicationController:
return true, v1.Convert_api_ReplicationController_To_v1_ReplicationController(a, b, s)
}
case *v1.Node:
switch b := objB.(type) {
case *api.Node:
return true, v1.Convert_v1_Node_To_api_Node(a, b, s)
}
case *api.Node:
switch b := objB.(type) {
case *v1.Node:
return true, v1.Convert_api_Node_To_v1_Node(a, b, s)
}
case *v1.Namespace:
switch b := objB.(type) {
case *api.Namespace:
return true, v1.Convert_v1_Namespace_To_api_Namespace(a, b, s)
}
case *api.Namespace:
switch b := objB.(type) {
case *v1.Namespace:
return true, v1.Convert_api_Namespace_To_v1_Namespace(a, b, s)
}
case *v1.Service:
switch b := objB.(type) {
case *api.Service:
return true, v1.Convert_v1_Service_To_api_Service(a, b, s)
}
case *api.Service:
switch b := objB.(type) {
case *v1.Service:
return true, v1.Convert_api_Service_To_v1_Service(a, b, s)
}
case *v1.Endpoints:
switch b := objB.(type) {
case *api.Endpoints:
return true, v1.Convert_v1_Endpoints_To_api_Endpoints(a, b, s)
}
case *api.Endpoints:
switch b := objB.(type) {
case *v1.Endpoints:
return true, v1.Convert_api_Endpoints_To_v1_Endpoints(a, b, s)
}
}
return false, nil
})
}

60
vendor/k8s.io/kubernetes/pkg/api/mapper.go generated vendored Normal file
View file

@ -0,0 +1,60 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/util/sets"
)
var RESTMapper meta.RESTMapper
func init() {
RESTMapper = meta.MultiRESTMapper{}
}
func RegisterRESTMapper(m meta.RESTMapper) {
RESTMapper = append(RESTMapper.(meta.MultiRESTMapper), m)
}
func NewDefaultRESTMapper(defaultGroupVersions []unversioned.GroupVersion, interfacesFunc meta.VersionInterfacesFunc,
importPathPrefix string, ignoredKinds, rootScoped sets.String) *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
}

91
vendor/k8s.io/kubernetes/pkg/api/meta.go generated vendored Normal file
View file

@ -0,0 +1,91 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util"
)
// FillObjectMetaSystemFields populates fields that are managed by the system on ObjectMeta.
func FillObjectMetaSystemFields(ctx Context, meta *ObjectMeta) {
meta.CreationTimestamp = unversioned.Now()
meta.UID = util.NewUUID()
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
}
// 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 }

View file

@ -0,0 +1,154 @@
// +build !ignore_autogenerated
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 meta
import (
unversioned "k8s.io/kubernetes/pkg/api/unversioned"
conversion "k8s.io/kubernetes/pkg/conversion"
runtime "k8s.io/kubernetes/pkg/runtime"
)
func DeepCopy_meta_DefaultRESTMapper(in DefaultRESTMapper, out *DefaultRESTMapper, c *conversion.Cloner) error {
if in.defaultGroupVersions != nil {
in, out := in.defaultGroupVersions, &out.defaultGroupVersions
*out = make([]unversioned.GroupVersion, len(in))
for i := range in {
if err := unversioned.DeepCopy_unversioned_GroupVersion(in[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.defaultGroupVersions = nil
}
if in.resourceToKind != nil {
in, out := in.resourceToKind, &out.resourceToKind
*out = make(map[unversioned.GroupVersionResource]unversioned.GroupVersionKind)
for range in {
// FIXME: Copying unassignable keys unsupported unversioned.GroupVersionResource
}
} else {
out.resourceToKind = nil
}
if in.kindToPluralResource != nil {
in, out := in.kindToPluralResource, &out.kindToPluralResource
*out = make(map[unversioned.GroupVersionKind]unversioned.GroupVersionResource)
for range in {
// FIXME: Copying unassignable keys unsupported unversioned.GroupVersionKind
}
} else {
out.kindToPluralResource = nil
}
if in.kindToScope != nil {
in, out := in.kindToScope, &out.kindToScope
*out = make(map[unversioned.GroupVersionKind]RESTScope)
for range in {
// FIXME: Copying unassignable keys unsupported unversioned.GroupVersionKind
}
} else {
out.kindToScope = nil
}
if in.singularToPlural != nil {
in, out := in.singularToPlural, &out.singularToPlural
*out = make(map[unversioned.GroupVersionResource]unversioned.GroupVersionResource)
for range in {
// FIXME: Copying unassignable keys unsupported unversioned.GroupVersionResource
}
} else {
out.singularToPlural = nil
}
if in.pluralToSingular != nil {
in, out := in.pluralToSingular, &out.pluralToSingular
*out = make(map[unversioned.GroupVersionResource]unversioned.GroupVersionResource)
for range in {
// FIXME: Copying unassignable keys unsupported unversioned.GroupVersionResource
}
} else {
out.pluralToSingular = nil
}
if in.interfacesFunc == nil {
out.interfacesFunc = nil
} else if newVal, err := c.DeepCopy(in.interfacesFunc); err != nil {
return err
} else {
out.interfacesFunc = newVal.(VersionInterfacesFunc)
}
if in.aliasToResource != nil {
in, out := in.aliasToResource, &out.aliasToResource
*out = make(map[string][]string)
for key, val := range in {
if newVal, err := c.DeepCopy(val); err != nil {
return err
} else {
(*out)[key] = newVal.([]string)
}
}
} else {
out.aliasToResource = nil
}
return nil
}
func DeepCopy_meta_RESTMapping(in RESTMapping, out *RESTMapping, c *conversion.Cloner) error {
out.Resource = in.Resource
if err := unversioned.DeepCopy_unversioned_GroupVersionKind(in.GroupVersionKind, &out.GroupVersionKind, c); err != nil {
return err
}
if in.Scope == nil {
out.Scope = nil
} else if newVal, err := c.DeepCopy(in.Scope); err != nil {
return err
} else {
out.Scope = newVal.(RESTScope)
}
if in.ObjectConvertor == nil {
out.ObjectConvertor = nil
} else if newVal, err := c.DeepCopy(in.ObjectConvertor); err != nil {
return err
} else {
out.ObjectConvertor = newVal.(runtime.ObjectConvertor)
}
if in.MetadataAccessor == nil {
out.MetadataAccessor = nil
} else if newVal, err := c.DeepCopy(in.MetadataAccessor); err != nil {
return err
} else {
out.MetadataAccessor = newVal.(MetadataAccessor)
}
return nil
}
func DeepCopy_meta_VersionInterfaces(in VersionInterfaces, out *VersionInterfaces, c *conversion.Cloner) error {
if in.ObjectConvertor == nil {
out.ObjectConvertor = nil
} else if newVal, err := c.DeepCopy(in.ObjectConvertor); err != nil {
return err
} else {
out.ObjectConvertor = newVal.(runtime.ObjectConvertor)
}
if in.MetadataAccessor == nil {
out.MetadataAccessor = nil
} else if newVal, err := c.DeepCopy(in.MetadataAccessor); err != nil {
return err
} else {
out.MetadataAccessor = newVal.(MetadataAccessor)
}
return nil
}

19
vendor/k8s.io/kubernetes/pkg/api/meta/doc.go generated vendored Normal file
View file

@ -0,0 +1,19 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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

72
vendor/k8s.io/kubernetes/pkg/api/meta/errors.go generated vendored Normal file
View file

@ -0,0 +1,72 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/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)
}
func IsAmbiguousResourceError(err error) bool {
if err == nil {
return false
}
_, ok := err.(*AmbiguousResourceError)
return ok
}
// 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)
}
func IsNoResourceMatchError(err error) bool {
if err == nil {
return false
}
_, ok := err.(*NoResourceMatchError)
return ok
}

134
vendor/k8s.io/kubernetes/pkg/api/meta/help.go generated vendored Normal file
View file

@ -0,0 +1,134 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/runtime"
)
// IsListType returns true if the provided Object has a slice called Items
func IsListType(obj runtime.Object) bool {
_, 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())
}
}
// 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)
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
}

181
vendor/k8s.io/kubernetes/pkg/api/meta/interfaces.go generated vendored Normal file
View file

@ -0,0 +1,181 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/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)
}
// 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 interface {
GetResourceVersion() string
SetResourceVersion(version string)
GetSelfLink() string
SetSelfLink(selfLink string)
}
// Type exposes the type and APIVersion of versioned or internal API objects.
type Type interface {
GetAPIVersion() string
SetAPIVersion(version string)
GetKind() string
SetKind(kind string)
}
// 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(caesarxuchao): Add proper multi-group support so that kinds & resources are
// scoped to groups. See http://issues.k8s.io/12413 and http://issues.k8s.io/10009.
type RESTMapper interface {
// KindFor takes a partial resource and returns back 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 back the list of potential kinds in priority order
KindsFor(resource unversioned.GroupVersionResource) ([]unversioned.GroupVersionKind, error)
// ResourceFor takes a partial resource and returns back 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 back the list of potential resource in priority order
ResourcesFor(input unversioned.GroupVersionResource) ([]unversioned.GroupVersionResource, error)
RESTMapping(gk unversioned.GroupKind, versions ...string) (*RESTMapping, error)
AliasesForResource(resource string) ([]string, bool)
ResourceSingularizer(resource string) (singular string, err error)
}
var _ Object = &runtime.Unstructured{}

521
vendor/k8s.io/kubernetes/pkg/api/meta/meta.go generated vendored Normal file
View file

@ -0,0 +1,521 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/types"
"github.com/golang/glog"
)
// 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.
func Accessor(obj interface{}) (Object, error) {
if oi, ok := obj.(ObjectMetaAccessor); ok {
if om := oi.GetObjectMeta(); om != nil {
return om, nil
}
}
// we may get passed an object that is directly portable to Object
if oi, ok := obj.(Object); ok {
return oi, nil
}
glog.V(4).Infof("Calling Accessor on non-internal object: %v", reflect.TypeOf(obj))
// legacy path for objects that do not implement Object and ObjectMetaAccessor via
// reflection - very slow code path.
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)
}
objectMeta := v.FieldByName("ObjectMeta")
if objectMeta.IsValid() {
// look for the ObjectMeta fields
if err := extractFromObjectMeta(objectMeta, a); err != nil {
return nil, fmt.Errorf("unable to find object fields on %#v: %v", objectMeta, err)
}
} else {
listMeta := v.FieldByName("ListMeta")
if listMeta.IsValid() {
// look for the ListMeta fields
if err := extractFromListMeta(listMeta, a); err != nil {
return nil, fmt.Errorf("unable to find list fields on %#v: %v", listMeta, err)
}
} else {
// look for the older TypeMeta with all metadata
if err := extractFromObjectMeta(typeMeta, a); err != nil {
return nil, fmt.Errorf("unable to find object fields on %#v: %v", typeMeta, err)
}
}
}
return a, nil
}
// 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 {
if gvk := obj.GetObjectKind().GroupVersionKind(); gvk != nil {
return gvk.Kind
}
return ""
}
func (obj objectAccessor) SetKind(kind string) {
gvk := obj.GetObjectKind().GroupVersionKind()
if gvk == nil {
gvk = &unversioned.GroupVersionKind{}
}
gvk.Kind = kind
obj.GetObjectKind().SetGroupVersionKind(gvk)
}
func (obj objectAccessor) GetAPIVersion() string {
if gvk := obj.GetObjectKind().GroupVersionKind(); gvk != nil {
return gvk.GroupVersion().String()
}
return ""
}
func (obj objectAccessor) SetAPIVersion(version string) {
gvk := obj.GetObjectKind().GroupVersionKind()
if gvk == nil {
gvk = &unversioned.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 := Accessor(obj)
if err != nil {
return "", err
}
return accessor.GetSelfLink(), nil
}
func (resourceAccessor) SetSelfLink(obj runtime.Object, selfLink string) error {
accessor, err := Accessor(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 := Accessor(obj)
if err != nil {
return "", err
}
return accessor.GetResourceVersion(), nil
}
func (resourceAccessor) SetResourceVersion(obj runtime.Object, version string) error {
accessor, err := Accessor(obj)
if err != nil {
return err
}
accessor.SetResourceVersion(version)
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
}
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
}
// 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
}
// extractFromObjectMeta extracts pointers to metadata fields from an object
func extractFromObjectMeta(v reflect.Value, a *genericAccessor) error {
if err := runtime.FieldPtr(v, "Namespace", &a.namespace); err != nil {
return err
}
if err := runtime.FieldPtr(v, "Name", &a.name); err != nil {
return err
}
if err := runtime.FieldPtr(v, "GenerateName", &a.generateName); err != nil {
return err
}
if err := runtime.FieldPtr(v, "UID", &a.uid); err != nil {
return err
}
if err := runtime.FieldPtr(v, "ResourceVersion", &a.resourceVersion); err != nil {
return err
}
if err := runtime.FieldPtr(v, "SelfLink", &a.selfLink); err != nil {
return err
}
if err := runtime.FieldPtr(v, "Labels", &a.labels); err != nil {
return err
}
if err := runtime.FieldPtr(v, "Annotations", &a.annotations); err != nil {
return err
}
return nil
}
// extractFromObjectMeta extracts pointers to metadata fields from a list object
func extractFromListMeta(v reflect.Value, a *genericAccessor) error {
if err := runtime.FieldPtr(v, "ResourceVersion", &a.resourceVersion); err != nil {
return err
}
if err := runtime.FieldPtr(v, "SelfLink", &a.selfLink); err != nil {
return err
}
return nil
}

View file

@ -0,0 +1,200 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/unversioned"
utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/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 IsNoResourceMatchError(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 IsNoResourceMatchError(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 IsNoResourceMatchError(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 {
return nil, fmt.Errorf("multiple matches found for %v in %v", gk, versions)
}
if len(errors) > 0 {
return nil, utilerrors.NewAggregate(errors)
}
return nil, fmt.Errorf("no match found for %v in %v", gk, versions)
}
// 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
}

173
vendor/k8s.io/kubernetes/pkg/api/meta/priority.go generated vendored Normal file
View file

@ -0,0 +1,173 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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/kubernetes/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) {
return m.Delegate.RESTMapping(gk, versions...)
}
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)
}

520
vendor/k8s.io/kubernetes/pkg/api/meta/restmapper.go generated vendored Normal file
View file

@ -0,0 +1,520 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/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.IsEmpty() {
singular = currSingular
continue
}
if currSingular.Resource != singular.Resource {
return resourceType, fmt.Errorf("multiple possibile singular resources (%v) found for %v", resources, resourceType)
}
}
if singular.IsEmpty() {
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 {
// fully qualified. Find the exact match
case hasGroup && hasVersion:
for plural, singular := range m.pluralToSingular {
if singular == resource {
ret = append(ret, plural)
break
}
if plural == resource {
ret = append(ret, plural)
break
}
}
case hasGroup:
requestedGroupResource := resource.GroupResource()
for plural, singular := range m.pluralToSingular {
if singular.GroupResource() == requestedGroupResource {
ret = append(ret, plural)
}
if plural.GroupResource() == requestedGroupResource {
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:
requestedGroupResource := resource.GroupResource()
for currResource, currKind := range m.resourceToKind {
if currResource.GroupResource() == requestedGroupResource {
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.
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, fmt.Errorf("no kind named %q is registered in versions %q", gk, versions)
}
// 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", gvk.GroupVersion().String())
}
retVal := &RESTMapping{
Resource: resource.Resource,
GroupVersionKind: *gvk,
Scope: scope,
ObjectConvertor: interfaces.ObjectConvertor,
MetadataAccessor: interfaces.MetadataAccessor,
}
return retVal, 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
}

49
vendor/k8s.io/kubernetes/pkg/api/node_example.json generated vendored Normal file
View file

@ -0,0 +1,49 @@
{
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "e2e-test-wojtekt-minion-etd6",
"selfLink": "/api/v1/nodes/e2e-test-wojtekt-minion-etd6",
"uid": "a7e89222-e8e5-11e4-8fde-42010af09327",
"resourceVersion": "379",
"creationTimestamp": "2015-04-22T11:49:39Z"
},
"spec": {
"externalID": "15488322946290398375"
},
"status": {
"capacity": {
"cpu": "1",
"memory": "1745152Ki"
},
"conditions": [
{
"type": "Ready",
"status": "True",
"lastHeartbeatTime": "2015-04-22T11:58:17Z",
"lastTransitionTime": "2015-04-22T11:49:52Z",
"reason": "kubelet is posting ready status"
}
],
"addresses": [
{
"type": "ExternalIP",
"address": "104.197.49.213"
},
{
"type": "LegacyHostIP",
"address": "104.197.20.11"
}
],
"nodeInfo": {
"machineID": "",
"systemUUID": "D59FA3FA-7B5B-7287-5E1A-1D79F13CB577",
"bootID": "44a832f3-8cfb-4de5-b7d2-d66030b6cd95",
"kernelVersion": "3.16.0-0.bpo.4-amd64",
"osImage": "Debian GNU/Linux 7 (wheezy)",
"containerRuntimeVersion": "docker://1.5.0",
"kubeletVersion": "v0.15.0-484-g0c8ee980d705a3-dirty",
"kubeProxyVersion": "v0.15.0-484-g0c8ee980d705a3-dirty"
}
}
}

61
vendor/k8s.io/kubernetes/pkg/api/pod/util.go generated vendored Normal file
View file

@ -0,0 +1,61 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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 pod
import (
"fmt"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/util/intstr"
)
const (
// TODO: to be de!eted after v1.3 is released. PodSpec has a dedicated Hostname field.
// The annotation value is a string specifying the hostname to be used for the pod e.g 'my-webserver-1'
PodHostnameAnnotation = "pod.beta.kubernetes.io/hostname"
// TODO: to be de!eted after v1.3 is released. PodSpec has a dedicated Subdomain field.
// The annotation value is a string specifying the subdomain e.g. "my-web-service"
// If specified, on the the pod itself, "<hostname>.my-web-service.<namespace>.svc.<cluster domain>" would resolve to
// the pod's IP.
// If there is a headless service named "my-web-service" in the same namespace as the pod, then,
// <hostname>.my-web-service.<namespace>.svc.<cluster domain>" would be resolved by the cluster DNS Server.
PodSubdomainAnnotation = "pod.beta.kubernetes.io/subdomain"
)
// FindPort locates the container port for the given pod and portName. If the
// targetPort is a number, use that. If the targetPort is a string, look that
// string up in all named ports in all containers in the target pod. If no
// match is found, fail.
func FindPort(pod *api.Pod, svcPort *api.ServicePort) (int, error) {
portName := svcPort.TargetPort
switch portName.Type {
case intstr.String:
name := portName.StrVal
for _, container := range pod.Spec.Containers {
for _, port := range container.Ports {
if port.Name == name && port.Protocol == svcPort.Protocol {
return int(port.ContainerPort), nil
}
}
}
case intstr.Int:
return portName.IntValue(), nil
}
return 0, fmt.Errorf("no suitable port for manifest: %s", pod.UID)
}

102
vendor/k8s.io/kubernetes/pkg/api/pod_example.json generated vendored Normal file
View file

@ -0,0 +1,102 @@
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "etcd-server-e2e-test-wojtekt-master",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/pods/etcd-server-e2e-test-wojtekt-master",
"uid": "a671734a-e8e5-11e4-8fde-42010af09327",
"resourceVersion": "22",
"creationTimestamp": "2015-04-22T11:49:36Z",
"annotations": {
"kubernetes.io/config.mirror": "mirror",
"kubernetes.io/config.source": "file"
}
},
"spec": {
"volumes": [
{
"name": "varetcd",
"hostPath": {
"path": "/mnt/master-pd/var/etcd"
},
"emptyDir": null,
"gcePersistentDisk": null,
"awsElasticBlockStore": null,
"gitRepo": null,
"secret": null,
"nfs": null,
"iscsi": null,
"glusterfs": null
}
],
"containers": [
{
"name": "etcd-container",
"image": "gcr.io/google_containers/etcd:2.0.9",
"command": [
"/usr/local/bin/etcd",
"--addr",
"127.0.0.1:4001",
"--bind-addr",
"127.0.0.1:4001",
"--data-dir",
"/var/etcd/data"
],
"ports": [
{
"name": "serverport",
"hostPort": 2380,
"containerPort": 2380,
"protocol": "TCP"
},
{
"name": "clientport",
"hostPort": 4001,
"containerPort": 4001,
"protocol": "TCP"
}
],
"resources": {},
"volumeMounts": [
{
"name": "varetcd",
"mountPath": "/var/etcd"
}
],
"terminationMessagePath": "/dev/termination-log",
"imagePullPolicy": "IfNotPresent",
"capabilities": {}
}
],
"restartPolicy": "Always",
"dnsPolicy": "ClusterFirst",
"nodeName": "e2e-test-wojtekt-master",
"hostNetwork": true
},
"status": {
"phase": "Running",
"conditions": [
{
"type": "Ready",
"status": "True"
}
],
"containerStatuses": [
{
"name": "etcd-container",
"state": {
"running": {
"startedAt": "2015-04-22T11:49:32Z"
}
},
"lastState": {},
"ready": true,
"restartCount": 0,
"image": "gcr.io/google_containers/etcd:2.0.9",
"imageID": "docker://b6b9a86dc06aa1361357ca1b105feba961f6a4145adca6c54e142c0be0fe87b0",
"containerID": "docker://3cbbf818f1addfc252957b4504f56ef2907a313fe6afc47fc75373674255d46d"
}
]
}
}

119
vendor/k8s.io/kubernetes/pkg/api/ref.go generated vendored Normal file
View file

@ -0,0 +1,119 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/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
}
meta, err := meta.Accessor(obj)
if err != nil {
return nil, err
}
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
var kind string
if gvk != nil {
kind = gvk.Kind
}
if len(kind) == 0 {
// TODO: this is wrong
gvk, err := Scheme.ObjectKind(obj)
if err != nil {
return nil, err
}
kind = gvk.Kind
}
// if the object referenced is actually persisted, we can also get version from meta
var version string
if gvk != nil {
version = gvk.GroupVersion().String()
}
if len(version) == 0 {
selfLink := meta.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]
}
return &ObjectReference{
Kind: kind,
APIVersion: version,
Name: meta.GetName(),
Namespace: meta.GetNamespace(),
UID: meta.GetUID(),
ResourceVersion: meta.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)
}

183
vendor/k8s.io/kubernetes/pkg/api/register.go generated vendored Normal file
View file

@ -0,0 +1,183 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/serializer"
)
// Scheme is the default instance of runtime.Scheme to which types in the Kubernetes API are already registered.
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}
// Unversiond 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 back a Group qualified GroupKind
func Kind(kind string) unversioned.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
func Resource(resource string) unversioned.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
func AddToScheme(scheme *runtime.Scheme) {
if err := Scheme.AddIgnoredConversionType(&unversioned.TypeMeta{}, &unversioned.TypeMeta{}); err != nil {
panic(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{},
)
}
func (obj *Pod) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *Pod) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodStatusResult) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *PodStatusResult) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodTemplate) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *PodTemplate) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodTemplateList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ReplicationController) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *ReplicationController) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ReplicationControllerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Service) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *Service) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ServiceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Endpoints) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *Endpoints) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *EndpointsList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Node) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *Node) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *NodeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *NodeProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Binding) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *Binding) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Event) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *Event) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *EventList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *List) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ListOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *LimitRange) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *LimitRange) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *LimitRangeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ResourceQuota) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *ResourceQuota) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ResourceQuotaList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Namespace) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *Namespace) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *NamespaceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ServiceAccount) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *ServiceAccount) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ServiceAccountList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Secret) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *Secret) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *SecretList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PersistentVolume) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *PersistentVolume) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PersistentVolumeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PersistentVolumeClaim) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *PersistentVolumeClaim) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PersistentVolumeClaimList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *DeleteOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodAttachOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodLogOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodExecOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ServiceProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ComponentStatus) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *ComponentStatus) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ComponentStatusList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *SerializedReference) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *RangeAllocation) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *RangeAllocation) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ObjectReference) GetObjectKind() unversioned.ObjectKind { return obj }
func (obj *ExportOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ConfigMap) GetObjectMeta() meta.Object { return &obj.ObjectMeta }
func (obj *ConfigMap) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ConfigMapList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

View file

@ -0,0 +1,82 @@
{
"kind": "ReplicationController",
"apiVersion": "v1",
"metadata": {
"name": "elasticsearch-logging-controller",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/replicationcontrollers/elasticsearch-logging-controller",
"uid": "aa76f162-e8e5-11e4-8fde-42010af09327",
"resourceVersion": "98",
"creationTimestamp": "2015-04-22T11:49:43Z",
"labels": {
"kubernetes.io/cluster-service": "true",
"name": "elasticsearch-logging"
}
},
"spec": {
"replicas": 1,
"selector": {
"name": "elasticsearch-logging"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"kubernetes.io/cluster-service": "true",
"name": "elasticsearch-logging"
}
},
"spec": {
"volumes": [
{
"name": "es-persistent-storage",
"hostPath": null,
"emptyDir": {
"medium": ""
},
"gcePersistentDisk": null,
"awsElasticBlockStore": null,
"gitRepo": null,
"secret": null,
"nfs": null,
"iscsi": null,
"glusterfs": null
}
],
"containers": [
{
"name": "elasticsearch-logging",
"image": "gcr.io/google_containers/elasticsearch:1.0",
"ports": [
{
"name": "db",
"containerPort": 9200,
"protocol": "TCP"
},
{
"name": "transport",
"containerPort": 9300,
"protocol": "TCP"
}
],
"resources": {},
"volumeMounts": [
{
"name": "es-persistent-storage",
"mountPath": "/data"
}
],
"terminationMessagePath": "/dev/termination-log",
"imagePullPolicy": "IfNotPresent",
"capabilities": {}
}
],
"restartPolicy": "Always",
"dnsPolicy": "ClusterFirst"
}
}
},
"status": {
"replicas": 1
}
}

115
vendor/k8s.io/kubernetes/pkg/api/requestcontext.go generated vendored Normal file
View file

@ -0,0 +1,115 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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"
)
// 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)
}
// NewRequestContextFilter 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 NewRequestContextFilter(mapper RequestContextMapper, handler http.Handler) (http.Handler, error) {
if mapper, ok := mapper.(*requestContextMap); ok {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if mapper.init(req, NewContext()) {
// If we were the ones to successfully initialize, pair with a remove
defer mapper.remove(req)
}
handler.ServeHTTP(w, req)
}), nil
} else {
return handler, errors.New("Unknown RequestContextMapper implementation.")
}
}
// 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

@ -0,0 +1,55 @@
// +build !ignore_autogenerated
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 resource
import (
conversion "k8s.io/kubernetes/pkg/conversion"
inf "speter.net/go/exp/math/dec/inf"
)
func DeepCopy_resource_Quantity(in Quantity, out *Quantity, c *conversion.Cloner) error {
if in.Amount != nil {
in, out := in.Amount, &out.Amount
*out = new(inf.Dec)
if newVal, err := c.DeepCopy(*in); err != nil {
return err
} else {
**out = newVal.(inf.Dec)
}
} else {
out.Amount = nil
}
out.Format = in.Format
return nil
}
func DeepCopy_resource_QuantityProto(in QuantityProto, out *QuantityProto, c *conversion.Cloner) error {
out.Format = in.Format
out.Scale = in.Scale
if in.Bigint != nil {
in, out := in.Bigint, &out.Bigint
*out = make([]byte, len(in))
copy(*out, in)
} else {
out.Bigint = nil
}
return nil
}

View file

@ -0,0 +1,371 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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
QuantityProto
*/
package resource
import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import io "io"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
func (m *Quantity) Reset() { *m = Quantity{} }
func (*Quantity) ProtoMessage() {}
func (m *QuantityProto) Reset() { *m = QuantityProto{} }
func (m *QuantityProto) String() string { return proto.CompactTextString(m) }
func (*QuantityProto) ProtoMessage() {}
func init() {
proto.RegisterType((*Quantity)(nil), "k8s.io.kubernetes.pkg.api.resource.Quantity")
proto.RegisterType((*QuantityProto)(nil), "k8s.io.kubernetes.pkg.api.resource.QuantityProto")
}
func (m *QuantityProto) 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
}
func (m *QuantityProto) MarshalTo(data []byte) (int, error) {
var i int
_ = i
var l int
_ = l
data[i] = 0xa
i++
i = encodeVarintGenerated(data, i, uint64(len(m.Format)))
i += copy(data[i:], m.Format)
data[i] = 0x10
i++
i = encodeVarintGenerated(data, i, uint64(m.Scale))
if m.Bigint != nil {
data[i] = 0x1a
i++
i = encodeVarintGenerated(data, i, uint64(len(m.Bigint)))
i += copy(data[i:], m.Bigint)
}
return i, nil
}
func encodeFixed64Generated(data []byte, offset int, v uint64) int {
data[offset] = uint8(v)
data[offset+1] = uint8(v >> 8)
data[offset+2] = uint8(v >> 16)
data[offset+3] = uint8(v >> 24)
data[offset+4] = uint8(v >> 32)
data[offset+5] = uint8(v >> 40)
data[offset+6] = uint8(v >> 48)
data[offset+7] = uint8(v >> 56)
return offset + 8
}
func encodeFixed32Generated(data []byte, offset int, v uint32) int {
data[offset] = uint8(v)
data[offset+1] = uint8(v >> 8)
data[offset+2] = uint8(v >> 16)
data[offset+3] = uint8(v >> 24)
return offset + 4
}
func encodeVarintGenerated(data []byte, offset int, v uint64) int {
for v >= 1<<7 {
data[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
data[offset] = uint8(v)
return offset + 1
}
func (m *QuantityProto) Size() (n int) {
var l int
_ = l
l = len(m.Format)
n += 1 + l + sovGenerated(uint64(l))
n += 1 + sovGenerated(uint64(m.Scale))
if m.Bigint != nil {
l = len(m.Bigint)
n += 1 + l + sovGenerated(uint64(l))
}
return n
}
func sovGenerated(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozGenerated(x uint64) (n int) {
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *QuantityProto) 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: QuantityProto: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: QuantityProto: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Format", 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
}
m.Format = Format(data[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Scale", wireType)
}
m.Scale = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
m.Scale |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Bigint", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
byteLen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + byteLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Bigint = append(m.Bigint[:0], data[iNdEx:postIndex]...)
if m.Bigint == nil {
m.Bigint = []byte{}
}
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

@ -0,0 +1,109 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 go-to-protobuf. Do not edit it manually!
syntax = 'proto2';
package k8s.io.kubernetes.pkg.api.resource;
import "k8s.io/kubernetes/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "resource";
// Quantity is a fixed-point representation of a number.
// It provides convenient marshaling/unmarshaling in JSON and YAML,
// in addition to String() and Int64() accessors.
//
// The serialization format is:
//
// <quantity> ::= <signedNumber><suffix>
// (Note that <suffix> may be empty, from the "" case in <decimalSI>.)
// <digit> ::= 0 | 1 | ... | 9
// <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=QuantityProto
// +protobuf.options.marshal=false
// +protobuf.options.(gogoproto.goproto_stringer)=false
message Quantity {
optional QuantityProto QuantityProto = 1;
}
// QuantityProto is a struct that is equivalent to Quantity, but intended for
// protobuf marshalling/unmarshalling. It is generated into a serialization
// that matches Quantity. Do not use in Go structs.
//
// +protobuf=true
message QuantityProto {
// The format of the quantity
optional string format = 1;
// The scale dimension of the value
optional int32 scale = 2;
// Bigint is serialized as a raw bytes array
optional bytes bigint = 3;
}

537
vendor/k8s.io/kubernetes/pkg/api/resource/quantity.go generated vendored Normal file
View file

@ -0,0 +1,537 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 (
"errors"
"fmt"
"math/big"
"regexp"
"strings"
flag "github.com/spf13/pflag"
"speter.net/go/exp/math/dec/inf"
)
// 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=QuantityProto
// +protobuf.options.marshal=false
// +protobuf.options.(gogoproto.goproto_stringer)=false
type Quantity struct {
// Amount is public, so you can manipulate it if the accessor
// functions are not sufficient.
Amount *inf.Dec
// Change Format at will. See the comment for Canonicalize for
// more details.
Format
}
// 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
}
// 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 int
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
)
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")
// 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 = 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)
)
// ParseQuantity turns str into a Quantity, or returns an error.
func ParseQuantity(str string) (*Quantity, error) {
parts := splitRE.FindStringSubmatch(strings.TrimSpace(str))
// regexp returns are entire match, followed by an entry for each () section.
if len(parts) != 3 {
return nil, ErrFormatWrong
}
amount := new(inf.Dec)
if _, ok := amount.SetString(parts[1]); !ok {
return nil, ErrNumeric
}
base, exponent, format, ok := quantitySuffixer.interpret(suffix(parts[2]))
if !ok {
return nil, ErrSuffix
}
// 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.
if amount.Cmp(maxAllowed) > 0 {
amount.Set(maxAllowed)
}
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{amount, format}, nil
}
// removeFactors 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 removeFactors(d, factor *big.Int) (result *big.Int, times int) {
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
}
// Canonicalize 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) Canonicalize() (string, suffix) {
if q.Amount == nil {
return "0", ""
}
// zero is zero always
if q.Amount.Cmp(&inf.Dec{}) == 0 {
return "0", ""
}
format := q.Format
switch format {
case DecimalExponent, DecimalSI:
case BinarySI:
if q.Amount.Cmp(decMinus1024) > 0 && q.Amount.Cmp(dec1024) < 0 {
// This avoids rounding and hopefully confusion, too.
format = DecimalSI
} else {
tmp := &inf.Dec{}
tmp.Round(q.Amount, 0, inf.RoundUp)
if tmp.Cmp(q.Amount) != 0 {
// 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:
mantissa := q.Amount.UnscaledBig()
exponent := int(-q.Amount.Scale())
amount := big.NewInt(0).Set(mantissa)
// move all factors of 10 into the exponent for easy reasoning
amount, times := removeFactors(amount, bigTen)
exponent += times
// make sure exponent is a multiple of 3
for exponent%3 != 0 {
amount.Mul(amount, bigTen)
exponent--
}
suffix, _ := quantitySuffixer.construct(10, exponent, format)
number := amount.String()
return number, suffix
case BinarySI:
tmp := &inf.Dec{}
tmp.Round(q.Amount, 0, inf.RoundUp)
amount, exponent := removeFactors(tmp.UnscaledBig(), big1024)
suffix, _ := quantitySuffixer.construct(2, exponent*10, format)
number := amount.String()
return number, suffix
}
return "0", ""
}
// String formats the Quantity as a string.
func (q *Quantity) String() string {
number, suffix := q.Canonicalize()
return number + string(suffix)
}
// Cmp compares q and y and returns:
//
// -1 if q < y
// 0 if q == y
// +1 if q > y
//
func (q *Quantity) Cmp(y Quantity) int {
if q.Amount == nil {
if y.Amount == nil {
return 0
}
return -y.Amount.Sign()
}
if y.Amount == nil {
return q.Amount.Sign()
}
return q.Amount.Cmp(y.Amount)
}
func (q *Quantity) Add(y Quantity) error {
switch {
case y.Amount == nil:
// Adding 0: do nothing.
case q.Amount == nil:
q.Amount = &inf.Dec{}
return q.Add(y)
default:
// we want to preserve the format of the non-zero value
zero := &inf.Dec{}
if q.Amount.Cmp(zero) == 0 && y.Amount.Cmp(zero) != 0 {
q.Format = y.Format
}
q.Amount.Add(q.Amount, y.Amount)
}
return nil
}
func (q *Quantity) Sub(y Quantity) error {
switch {
case y.Amount == nil:
// Subtracting 0: do nothing.
case q.Amount == nil:
q.Amount = &inf.Dec{}
return q.Sub(y)
default:
// we want to preserve the format of the non-zero value
zero := &inf.Dec{}
if q.Amount.Cmp(zero) == 0 && y.Amount.Cmp(zero) != 0 {
q.Format = y.Format
}
q.Amount.Sub(q.Amount, y.Amount)
}
return nil
}
// Neg sets q to the negative value of y.
// It updates the format of q to match y.
func (q *Quantity) Neg(y Quantity) error {
switch {
case y.Amount == nil:
*q = y
case q.Amount == nil:
q.Amount = &inf.Dec{}
fallthrough
default:
q.Amount.Neg(y.Amount)
q.Format = y.Format
}
return nil
}
// MarshalJSON implements the json.Marshaller interface.
func (q Quantity) MarshalJSON() ([]byte, error) {
return []byte(`"` + q.String() + `"`), nil
}
// UnmarshalJSON implements the json.Unmarshaller interface.
func (q *Quantity) UnmarshalJSON(value []byte) error {
str := string(value)
parsed, err := ParseQuantity(strings.Trim(str, `"`))
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{
Amount: inf.NewDec(value, 0),
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{
Amount: inf.NewDec(value, 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{
Amount: inf.NewDec(value, scale.infScale()),
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.Amount == nil {
return 0
}
return scaledValue(q.Amount.UnscaledBig(), int(q.Amount.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) {
if q.Amount == nil {
q.Amount = &inf.Dec{}
}
q.Amount.SetUnscaled(value)
q.Amount.SetScale(scale.infScale())
}
// 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.Amount == nil {
return NewQuantity(0, q.Format)
}
tmp := &inf.Dec{}
return &Quantity{
Amount: tmp.Set(q.Amount),
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}
}
// 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
}

View file

@ -0,0 +1,78 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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"
"speter.net/go/exp/math/dec/inf"
)
// QuantityProto is a struct that is equivalent to Quantity, but intended for
// protobuf marshalling/unmarshalling. It is generated into a serialization
// that matches Quantity. Do not use in Go structs.
//
// +protobuf=true
type QuantityProto struct {
// The format of the quantity
Format Format `protobuf:"bytes,1,opt,name=format,casttype=Format"`
// The scale dimension of the value
Scale int32 `protobuf:"varint,2,opt,name=scale"`
// Bigint is serialized as a raw bytes array
Bigint []byte `protobuf:"bytes,3,opt,name=bigint"`
}
// ProtoTime returns the Time as a new ProtoTime value.
func (q *Quantity) QuantityProto() *QuantityProto {
if q == nil {
return &QuantityProto{}
}
p := &QuantityProto{
Format: q.Format,
}
if q.Amount != nil {
p.Scale = int32(q.Amount.Scale())
p.Bigint = q.Amount.UnscaledBig().Bytes()
}
return p
}
// Size implements the protobuf marshalling interface.
func (q *Quantity) Size() (n int) { return q.QuantityProto().Size() }
// Reset implements the protobuf marshalling interface.
func (q *Quantity) Unmarshal(data []byte) error {
p := QuantityProto{}
if err := p.Unmarshal(data); err != nil {
return err
}
q.Format = p.Format
b := big.NewInt(0)
b.SetBytes(p.Bigint)
q.Amount = inf.NewDecBig(b, inf.Scale(p.Scale))
return nil
}
// Marshal implements the protobuf marshalling interface.
func (q *Quantity) Marshal() (data []byte, err error) {
return q.QuantityProto().Marshal()
}
// MarshalTo implements the protobuf marshalling interface.
func (q *Quantity) MarshalTo(data []byte) (int, error) {
return q.QuantityProto().MarshalTo(data)
}

95
vendor/k8s.io/kubernetes/pkg/api/resource/scale_int.go generated vendored Normal file
View file

@ -0,0 +1,95 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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()
}

136
vendor/k8s.io/kubernetes/pkg/api/resource/suffix.go generated vendored Normal file
View file

@ -0,0 +1,136 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 int, fmt Format, ok bool)
construct(base, exponent int, fmt Format) (s suffix, ok bool)
}
// quantitySuffixer handles suffixes for all three formats that quantity
// can handle.
var quantitySuffixer = newSuffixer()
type bePair struct {
base, exponent int
}
type listSuffixer struct {
suffixToBE map[suffix]bePair
beToSuffix map[bePair]suffix
}
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{}
}
ls.suffixToBE[s] = pair
ls.beToSuffix[pair] = s
}
func (ls *listSuffixer) lookup(s suffix) (base, exponent int, 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 int) (s suffix, ok bool) {
s, ok = ls.beToSuffix[bePair{base, exponent}]
return
}
type suffixHandler struct {
decSuffixes listSuffixer
binSuffixes listSuffixer
}
func newSuffixer() suffixer {
sh := &suffixHandler{}
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 sh
}
func (sh *suffixHandler) construct(base, exponent int, 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) interpret(suffix suffix) (base, exponent int, 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, int(parsed), DecimalExponent, true
}
return 0, 0, DecimalExponent, false
}

122
vendor/k8s.io/kubernetes/pkg/api/resource_helpers.go generated vendored Normal file
View file

@ -0,0 +1,122 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/resource"
)
// 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 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{}
}
// 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 {
for i, c := range status.Conditions {
if c.Type == PodReady {
return &status.Conditions[i]
}
}
return nil
}
// 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 if err = value.Add(quantity); err != nil {
return nil, nil, err
}
}
for name, quantity := range container.Resources.Limits {
if value, ok := limits[name]; !ok {
limits[name] = *quantity.Copy()
} else if err = value.Add(quantity); err != nil {
return nil, nil, err
}
}
}
return
}

126
vendor/k8s.io/kubernetes/pkg/api/rest/create.go generated vendored Normal file
View file

@ -0,0 +1,126 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 rest
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/validation/field"
)
// RESTCreateStrategy defines the minimum validation, accepted input, and
// name generation behavior to create an object that follows Kubernetes
// API conventions.
type RESTCreateStrategy interface {
runtime.ObjectTyper
// The name generate is used when the standard GenerateName field is set.
// The NameGenerator will be invoked prior to validation.
api.NameGenerator
// NamespaceScoped returns true if the object must be within a namespace.
NamespaceScoped() bool
// PrepareForCreate is invoked on create before validation to normalize
// the object. For example: remove fields that are not to be persisted,
// sort order-insensitive list fields, etc. This should not remove fields
// whose presence would be considered a validation error.
PrepareForCreate(obj runtime.Object)
// Validate is invoked after default fields in the object have been filled in before
// the object is persisted. This method should not mutate the object.
Validate(ctx api.Context, obj runtime.Object) field.ErrorList
// Canonicalize is invoked after validation has succeeded but before the
// object has been persisted. This method may mutate the object.
Canonicalize(obj runtime.Object)
}
// BeforeCreate ensures that common operations for all resources are performed on creation. It only returns
// errors that can be converted to api.Status. It invokes PrepareForCreate, then GenerateName, then Validate.
// It returns nil if the object should be created.
func BeforeCreate(strategy RESTCreateStrategy, ctx api.Context, obj runtime.Object) error {
objectMeta, kind, kerr := objectMetaAndKind(strategy, obj)
if kerr != nil {
return kerr
}
if strategy.NamespaceScoped() {
if !api.ValidNamespace(ctx, objectMeta) {
return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
}
} else {
objectMeta.Namespace = api.NamespaceNone
}
objectMeta.DeletionTimestamp = nil
objectMeta.DeletionGracePeriodSeconds = nil
strategy.PrepareForCreate(obj)
api.FillObjectMetaSystemFields(ctx, objectMeta)
api.GenerateName(strategy, objectMeta)
if errs := strategy.Validate(ctx, obj); len(errs) > 0 {
return errors.NewInvalid(kind.GroupKind(), objectMeta.Name, errs)
}
// Custom validation (including name validation) passed
// Now run common validation on object meta
// Do this *after* custom validation so that specific error messages are shown whenever possible
if errs := validation.ValidateObjectMeta(objectMeta, strategy.NamespaceScoped(), validation.ValidatePathSegmentName, field.NewPath("metadata")); len(errs) > 0 {
return errors.NewInvalid(kind.GroupKind(), objectMeta.Name, errs)
}
strategy.Canonicalize(obj)
return nil
}
// CheckGeneratedNameError checks whether an error that occurred creating a resource is due
// to generation being unable to pick a valid name.
func CheckGeneratedNameError(strategy RESTCreateStrategy, err error, obj runtime.Object) error {
if !errors.IsAlreadyExists(err) {
return err
}
objectMeta, kind, kerr := objectMetaAndKind(strategy, obj)
if kerr != nil {
return kerr
}
if len(objectMeta.GenerateName) == 0 {
return err
}
return errors.NewServerTimeoutForKind(kind.GroupKind(), "POST", 0)
}
// objectMetaAndKind retrieves kind and ObjectMeta from a runtime object, or returns an error.
func objectMetaAndKind(typer runtime.ObjectTyper, obj runtime.Object) (*api.ObjectMeta, unversioned.GroupVersionKind, error) {
objectMeta, err := api.ObjectMetaFor(obj)
if err != nil {
return nil, unversioned.GroupVersionKind{}, errors.NewInternalError(err)
}
kind, err := typer.ObjectKind(obj)
if err != nil {
return nil, unversioned.GroupVersionKind{}, errors.NewInternalError(err)
}
return objectMeta, kind, nil
}
// NamespaceScopedStrategy has a method to tell if the object must be in a namespace.
type NamespaceScopedStrategy interface {
// NamespaceScoped returns if the object must be in a namespace.
NamespaceScoped() bool
}

93
vendor/k8s.io/kubernetes/pkg/api/rest/delete.go generated vendored Normal file
View file

@ -0,0 +1,93 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 rest
import (
"fmt"
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime"
)
// RESTDeleteStrategy defines deletion behavior on an object that follows Kubernetes
// API conventions.
type RESTDeleteStrategy interface {
runtime.ObjectTyper
}
// RESTGracefulDeleteStrategy must be implemented by the registry that supports
// graceful deletion.
type RESTGracefulDeleteStrategy interface {
// CheckGracefulDelete should return true if the object can be gracefully deleted and set
// any default values on the DeleteOptions.
CheckGracefulDelete(obj runtime.Object, options *api.DeleteOptions) bool
}
// BeforeDelete tests whether the object can be gracefully deleted. If graceful is set the object
// should be gracefully deleted, if gracefulPending is set the object has already been gracefully deleted
// (and the provided grace period is longer than the time to deletion), and an error is returned if the
// condition cannot be checked or the gracePeriodSeconds is invalid. The options argument may be updated with
// default values if graceful is true.
func BeforeDelete(strategy RESTDeleteStrategy, ctx api.Context, obj runtime.Object, options *api.DeleteOptions) (graceful, gracefulPending bool, err error) {
objectMeta, gvk, kerr := objectMetaAndKind(strategy, obj)
if kerr != nil {
return false, false, kerr
}
// Checking the Preconditions here to fail early. They'll be enforced later on when we actually do the deletion, too.
if options.Preconditions != nil && options.Preconditions.UID != nil && *options.Preconditions.UID != objectMeta.UID {
return false, false, errors.NewConflict(unversioned.GroupResource{Group: gvk.Group, Resource: gvk.Kind}, objectMeta.Name, fmt.Errorf("the UID in the precondition (%s) does not match the UID in record (%s). The object might have been deleted and then recreated", *options.Preconditions.UID, objectMeta.UID))
}
gracefulStrategy, ok := strategy.(RESTGracefulDeleteStrategy)
if !ok {
return false, false, nil
}
// if the object is already being deleted
if objectMeta.DeletionTimestamp != nil {
// if we are already being deleted, we may only shorten the deletion grace period
// this means the object was gracefully deleted previously but deletionGracePeriodSeconds was not set,
// so we force deletion immediately
if objectMeta.DeletionGracePeriodSeconds == nil {
return false, false, nil
}
// only a shorter grace period may be provided by a user
if options.GracePeriodSeconds != nil {
period := int64(*options.GracePeriodSeconds)
if period > *objectMeta.DeletionGracePeriodSeconds {
return false, true, nil
}
now := unversioned.NewTime(unversioned.Now().Add(time.Second * time.Duration(*options.GracePeriodSeconds)))
objectMeta.DeletionTimestamp = &now
objectMeta.DeletionGracePeriodSeconds = &period
options.GracePeriodSeconds = &period
return true, false, nil
}
// graceful deletion is pending, do nothing
options.GracePeriodSeconds = objectMeta.DeletionGracePeriodSeconds
return false, true, nil
}
if !gracefulStrategy.CheckGracefulDelete(obj, options) {
return false, false, nil
}
now := unversioned.NewTime(unversioned.Now().Add(time.Second * time.Duration(*options.GracePeriodSeconds)))
objectMeta.DeletionTimestamp = &now
objectMeta.DeletionGracePeriodSeconds = options.GracePeriodSeconds
return true, false, nil
}

18
vendor/k8s.io/kubernetes/pkg/api/rest/doc.go generated vendored Normal file
View file

@ -0,0 +1,18 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 rest defines common logic around changes to Kubernetes resources.
package rest

28
vendor/k8s.io/kubernetes/pkg/api/rest/export.go generated vendored Normal file
View file

@ -0,0 +1,28 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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 rest
import (
"k8s.io/kubernetes/pkg/runtime"
)
// RESTExportStrategy is the interface that defines how to export a Kubernetes object
type RESTExportStrategy interface {
// Export strips fields that can not be set by the user. If 'exact' is false
// fields specific to the cluster are also stripped
Export(obj runtime.Object, exact bool) error
}

293
vendor/k8s.io/kubernetes/pkg/api/rest/rest.go generated vendored Normal file
View file

@ -0,0 +1,293 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 rest
import (
"io"
"net/http"
"net/url"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/watch"
)
//TODO:
// Storage interfaces need to be separated into two groups; those that operate
// on collections and those that operate on individually named items.
// Collection interfaces:
// (Method: Current -> Proposed)
// GET: Lister -> CollectionGetter
// WATCH: Watcher -> CollectionWatcher
// CREATE: Creater -> CollectionCreater
// DELETE: (n/a) -> CollectionDeleter
// UPDATE: (n/a) -> CollectionUpdater
//
// Single item interfaces:
// (Method: Current -> Proposed)
// GET: Getter -> NamedGetter
// WATCH: (n/a) -> NamedWatcher
// CREATE: (n/a) -> NamedCreater
// DELETE: Deleter -> NamedDeleter
// UPDATE: Update -> NamedUpdater
// Storage is a generic interface for RESTful storage services.
// Resources which are exported to the RESTful API of apiserver need to implement this interface. It is expected
// that objects may implement any of the below interfaces.
type Storage interface {
// New returns an empty object that can be used with Create and Update after request data has been put into it.
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
New() runtime.Object
}
// KindProvider specifies a different kind for its API than for its internal storage. This is necessary for external
// objects that are not compiled into the api server. For such objects, there is no in-memory representation for
// the object, so they must be represented as generic objects (e.g. runtime.Unknown), but when we present the object as part of
// API discovery we want to present the specific kind, not the generic internal representation.
type KindProvider interface {
Kind() string
}
// Lister is an object that can retrieve resources that match the provided field and label criteria.
type Lister interface {
// NewList returns an empty object that can be used with the List call.
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
NewList() runtime.Object
// List selects resources in the storage which match to the selector. 'options' can be nil.
List(ctx api.Context, options *api.ListOptions) (runtime.Object, error)
}
// Exporter is an object that knows how to strip a RESTful resource for export
type Exporter interface {
// Export an object. Fields that are not user specified (e.g. Status, ObjectMeta.ResourceVersion) are stripped out
// Returns the stripped object. If 'exact' is true, fields that are specific to the cluster (e.g. namespace) are
// retained, otherwise they are stripped also.
Export(ctx api.Context, name string, opts unversioned.ExportOptions) (runtime.Object, error)
}
// Getter is an object that can retrieve a named RESTful resource.
type Getter interface {
// Get finds a resource in the storage by name and returns it.
// Although it can return an arbitrary error value, IsNotFound(err) is true for the
// returned error value err when the specified resource is not found.
Get(ctx api.Context, name string) (runtime.Object, error)
}
// GetterWithOptions is an object that retrieve a named RESTful resource and takes
// additional options on the get request. It allows a caller to also receive the
// subpath of the GET request.
type GetterWithOptions interface {
// Get finds a resource in the storage by name and returns it.
// Although it can return an arbitrary error value, IsNotFound(err) is true for the
// returned error value err when the specified resource is not found.
// The options object passed to it is of the same type returned by the NewGetOptions
// method.
Get(ctx api.Context, name string, options runtime.Object) (runtime.Object, error)
// NewGetOptions returns an empty options object that will be used to pass
// options to the Get method. It may return a bool and a string, if true, the
// value of the request path below the object will be included as the named
// string in the serialization of the runtime object. E.g., returning "path"
// will convert the trailing request scheme value to "path" in the map[string][]string
// passed to the converter.
NewGetOptions() (runtime.Object, bool, string)
}
// Deleter is an object that can delete a named RESTful resource.
type Deleter interface {
// Delete finds a resource in the storage and deletes it.
// Although it can return an arbitrary error value, IsNotFound(err) is true for the
// returned error value err when the specified resource is not found.
// Delete *may* return the object that was deleted, or a status object indicating additional
// information about deletion.
Delete(ctx api.Context, name string) (runtime.Object, error)
}
// GracefulDeleter knows how to pass deletion options to allow delayed deletion of a
// RESTful object.
type GracefulDeleter interface {
// Delete finds a resource in the storage and deletes it.
// If options are provided, the resource will attempt to honor them or return an invalid
// request error.
// Although it can return an arbitrary error value, IsNotFound(err) is true for the
// returned error value err when the specified resource is not found.
// Delete *may* return the object that was deleted, or a status object indicating additional
// information about deletion.
Delete(ctx api.Context, name string, options *api.DeleteOptions) (runtime.Object, error)
}
// GracefulDeleteAdapter adapts the Deleter interface to GracefulDeleter
type GracefulDeleteAdapter struct {
Deleter
}
// Delete implements RESTGracefulDeleter in terms of Deleter
func (w GracefulDeleteAdapter) Delete(ctx api.Context, name string, options *api.DeleteOptions) (runtime.Object, error) {
return w.Deleter.Delete(ctx, name)
}
// CollectionDeleter is an object that can delete a collection
// of RESTful resources.
type CollectionDeleter interface {
// DeleteCollection selects all resources in the storage matching given 'listOptions'
// and deletes them. If 'options' are provided, the resource will attempt to honor
// them or return an invalid request error.
// DeleteCollection may not be atomic - i.e. it may delete some objects and still
// return an error after it. On success, returns a list of deleted objects.
DeleteCollection(ctx api.Context, options *api.DeleteOptions, listOptions *api.ListOptions) (runtime.Object, error)
}
// Creater is an object that can create an instance of a RESTful object.
type Creater interface {
// New returns an empty object that can be used with Create after request data has been put into it.
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
New() runtime.Object
// Create creates a new version of a resource.
Create(ctx api.Context, obj runtime.Object) (runtime.Object, error)
}
// NamedCreater is an object that can create an instance of a RESTful object using a name parameter.
type NamedCreater interface {
// New returns an empty object that can be used with Create after request data has been put into it.
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
New() runtime.Object
// Create creates a new version of a resource. It expects a name parameter from the path.
// This is needed for create operations on subresources which include the name of the parent
// resource in the path.
Create(ctx api.Context, name string, obj runtime.Object) (runtime.Object, error)
}
// Updater is an object that can update an instance of a RESTful object.
type Updater interface {
// New returns an empty object that can be used with Update after request data has been put into it.
// This object must be a pointer type for use with Codec.DecodeInto([]byte, runtime.Object)
New() runtime.Object
// Update finds a resource in the storage and updates it. Some implementations
// may allow updates creates the object - they should set the created boolean
// to true.
Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error)
}
// CreaterUpdater is a storage object that must support both create and update.
// Go prevents embedded interfaces that implement the same method.
type CreaterUpdater interface {
Creater
Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error)
}
// CreaterUpdater must satisfy the Updater interface.
var _ Updater = CreaterUpdater(nil)
// Patcher is a storage object that supports both get and update.
type Patcher interface {
Getter
Updater
}
// Watcher should be implemented by all Storage objects that
// want to offer the ability to watch for changes through the watch api.
type Watcher interface {
// 'label' selects on labels; 'field' selects on the object's fields. Not all fields
// are supported; an error should be returned if 'field' tries to select on a field that
// isn't supported. 'resourceVersion' allows for continuing/starting a watch at a
// particular version.
Watch(ctx api.Context, options *api.ListOptions) (watch.Interface, error)
}
// StandardStorage is an interface covering the common verbs. Provided for testing whether a
// resource satisfies the normal storage methods. Use Storage when passing opaque storage objects.
type StandardStorage interface {
Getter
Lister
CreaterUpdater
GracefulDeleter
CollectionDeleter
Watcher
}
// Redirector know how to return a remote resource's location.
type Redirector interface {
// ResourceLocation should return the remote location of the given resource, and an optional transport to use to request it, or an error.
ResourceLocation(ctx api.Context, id string) (remoteLocation *url.URL, transport http.RoundTripper, err error)
}
// Responder abstracts the normal response behavior for a REST method and is passed to callers that
// may wish to handle the response directly in some cases, but delegate to the normal error or object
// behavior in other cases.
type Responder interface {
// Object writes the provided object to the response. Invoking this method multiple times is undefined.
Object(statusCode int, obj runtime.Object)
// Error writes the provided error to the response. This method may only be invoked once.
Error(err error)
}
// Connecter is a storage object that responds to a connection request.
type Connecter interface {
// Connect returns an http.Handler that will handle the request/response for a given API invocation.
// The provided responder may be used for common API responses. The responder will write both status
// code and body, so the ServeHTTP method should exit after invoking the responder. The Handler will
// be used for a single API request and then discarded. The Responder is guaranteed to write to the
// same http.ResponseWriter passed to ServeHTTP.
Connect(ctx api.Context, id string, options runtime.Object, r Responder) (http.Handler, error)
// NewConnectOptions returns an empty options object that will be used to pass
// options to the Connect method. If nil, then a nil options object is passed to
// Connect. It may return a bool and a string. If true, the value of the request
// path below the object will be included as the named string in the serialization
// of the runtime object.
NewConnectOptions() (runtime.Object, bool, string)
// ConnectMethods returns the list of HTTP methods handled by Connect
ConnectMethods() []string
}
// ResourceStreamer is an interface implemented by objects that prefer to be streamed from the server
// instead of decoded directly.
type ResourceStreamer interface {
// InputStream should return an io.ReadCloser if the provided object supports streaming. The desired
// api version and a accept header (may be empty) are passed to the call. If no error occurs,
// the caller may return a flag indicating whether the result should be flushed as writes occur
// and a content type string that indicates the type of the stream.
// If a null stream is returned, a StatusNoContent response wil be generated.
InputStream(apiVersion, acceptHeader string) (stream io.ReadCloser, flush bool, mimeType string, err error)
}
// StorageMetadata is an optional interface that callers can implement to provide additional
// information about their Storage objects.
type StorageMetadata interface {
// ProducesMIMETypes returns a list of the MIME types the specified HTTP verb (GET, POST, DELETE,
// PATCH) can respond with.
ProducesMIMETypes(verb string) []string
}
// ConnectRequest is an object passed to admission control for Connect operations
type ConnectRequest struct {
// Name is the name of the object on which the connect request was made
Name string
// Options is the options object passed to the connect request. See the NewConnectOptions method on Connecter
Options runtime.Object
// ResourcePath is the path for the resource in the REST server (ie. "pods/proxy")
ResourcePath string
}
func (obj *ConnectRequest) GetObjectKind() unversioned.ObjectKind { return unversioned.EmptyObjectKind }

42
vendor/k8s.io/kubernetes/pkg/api/rest/types.go generated vendored Normal file
View file

@ -0,0 +1,42 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 rest
import (
"k8s.io/kubernetes/pkg/runtime"
)
// ObjectFunc is a function to act on a given object. An error may be returned
// if the hook cannot be completed. An ObjectFunc may transform the provided
// object.
type ObjectFunc func(obj runtime.Object) error
// AllFuncs returns an ObjectFunc that attempts to run all of the provided functions
// in order, returning early if there are any errors.
func AllFuncs(fns ...ObjectFunc) ObjectFunc {
return func(obj runtime.Object) error {
for _, fn := range fns {
if fn == nil {
continue
}
if err := fn(obj); err != nil {
return err
}
}
return nil
}
}

105
vendor/k8s.io/kubernetes/pkg/api/rest/update.go generated vendored Normal file
View file

@ -0,0 +1,105 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 rest
import (
"fmt"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/validation"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/validation/field"
)
// RESTUpdateStrategy defines the minimum validation, accepted input, and
// name generation behavior to update an object that follows Kubernetes
// API conventions. A resource may have many UpdateStrategies, depending on
// the call pattern in use.
type RESTUpdateStrategy interface {
runtime.ObjectTyper
// NamespaceScoped returns true if the object must be within a namespace.
NamespaceScoped() bool
// AllowCreateOnUpdate returns true if the object can be created by a PUT.
AllowCreateOnUpdate() bool
// PrepareForUpdate is invoked on update before validation to normalize
// the object. For example: remove fields that are not to be persisted,
// sort order-insensitive list fields, etc. This should not remove fields
// whose presence would be considered a validation error.
PrepareForUpdate(obj, old runtime.Object)
// ValidateUpdate is invoked after default fields in the object have been
// filled in before the object is persisted. This method should not mutate
// the object.
ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList
// Canonicalize is invoked after validation has succeeded but before the
// object has been persisted. This method may mutate the object.
Canonicalize(obj runtime.Object)
// AllowUnconditionalUpdate returns true if the object can be updated
// unconditionally (irrespective of the latest resource version), when
// there is no resource version specified in the object.
AllowUnconditionalUpdate() bool
}
// TODO: add other common fields that require global validation.
func validateCommonFields(obj, old runtime.Object) (field.ErrorList, error) {
allErrs := field.ErrorList{}
objectMeta, err := api.ObjectMetaFor(obj)
if err != nil {
return nil, fmt.Errorf("failed to get new object metadata: %v", err)
}
oldObjectMeta, err := api.ObjectMetaFor(old)
if err != nil {
return nil, fmt.Errorf("failed to get old object metadata: %v", err)
}
allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(objectMeta, oldObjectMeta, field.NewPath("metadata"))...)
return allErrs, nil
}
// BeforeUpdate ensures that common operations for all resources are performed on update. It only returns
// errors that can be converted to api.Status. It will invoke update validation with the provided existing
// and updated objects.
func BeforeUpdate(strategy RESTUpdateStrategy, ctx api.Context, obj, old runtime.Object) error {
objectMeta, kind, kerr := objectMetaAndKind(strategy, obj)
if kerr != nil {
return kerr
}
if strategy.NamespaceScoped() {
if !api.ValidNamespace(ctx, objectMeta) {
return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
}
} else {
objectMeta.Namespace = api.NamespaceNone
}
strategy.PrepareForUpdate(obj, old)
// Ensure some common fields, like UID, are validated for all resources.
errs, err := validateCommonFields(obj, old)
if err != nil {
return errors.NewInternalError(err)
}
errs = append(errs, strategy.ValidateUpdate(ctx, obj, old)...)
if len(errs) > 0 {
return errors.NewInvalid(kind.GroupKind(), objectMeta.Name, errs)
}
strategy.Canonicalize(obj)
return nil
}

View file

@ -0,0 +1,28 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 service
const (
// AnnotationLoadBalancerSourceRangesKey is the key of the annotation on a service to set allowed ingress ranges on their LoadBalancers
//
// It should be a comma-separated list of CIDRs, e.g. `0.0.0.0/0` to
// allow full access (the default) or `18.0.0.0/8,56.0.0.0/8` to allow
// access only from the CIDRs currently allocated to MIT & the USPS.
//
// Not all cloud providers support this annotation, though AWS & GCE do.
AnnotationLoadBalancerSourceRangesKey = "service.beta.kubernetes.io/load-balancer-source-ranges"
)

54
vendor/k8s.io/kubernetes/pkg/api/service/util.go generated vendored Normal file
View file

@ -0,0 +1,54 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 service
import (
"fmt"
"strings"
netsets "k8s.io/kubernetes/pkg/util/net/sets"
)
const (
defaultLoadBalancerSourceRanges = "0.0.0.0/0"
)
// IsAllowAll checks whether the netsets.IPNet allows traffic from 0.0.0.0/0
func IsAllowAll(ipnets netsets.IPNet) bool {
for _, s := range ipnets.StringSlice() {
if s == "0.0.0.0/0" {
return true
}
}
return false
}
// GetLoadBalancerSourceRanges verifies and parses the AnnotationLoadBalancerSourceRangesKey annotation from a service,
// extracting the source ranges to allow, and if not present returns a default (allow-all) value.
func GetLoadBalancerSourceRanges(annotations map[string]string) (netsets.IPNet, error) {
val := annotations[AnnotationLoadBalancerSourceRangesKey]
val = strings.TrimSpace(val)
if val == "" {
val = defaultLoadBalancerSourceRanges
}
specs := strings.Split(val, ",")
ipnets, err := netsets.ParseIPNets(specs...)
if err != nil {
return nil, fmt.Errorf("Service annotation %s:%s is not valid. Expecting a comma-separated list of source IP ranges. For example, 10.0.0.0/24,192.168.2.0/24", AnnotationLoadBalancerSourceRangesKey, val)
}
return ipnets, nil
}

359
vendor/k8s.io/kubernetes/pkg/api/testapi/testapi.go generated vendored Normal file
View file

@ -0,0 +1,359 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 testapi provides a helper for retrieving the KUBE_TEST_API environment variable.
package testapi
import (
"fmt"
"mime"
"os"
"reflect"
"strings"
"k8s.io/kubernetes/federation/apis/federation"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/apps"
"k8s.io/kubernetes/pkg/apis/autoscaling"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/serializer/recognizer"
_ "k8s.io/kubernetes/federation/apis/federation/install"
_ "k8s.io/kubernetes/pkg/api/install"
_ "k8s.io/kubernetes/pkg/apis/apps/install"
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
_ "k8s.io/kubernetes/pkg/apis/batch/install"
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
_ "k8s.io/kubernetes/pkg/apis/metrics/install"
)
var (
Groups = make(map[string]TestGroup)
Default TestGroup
Autoscaling TestGroup
Batch TestGroup
Extensions TestGroup
Apps TestGroup
Federation TestGroup
serializer runtime.SerializerInfo
storageSerializer runtime.SerializerInfo
)
type TestGroup struct {
externalGroupVersion unversioned.GroupVersion
internalGroupVersion unversioned.GroupVersion
internalTypes map[string]reflect.Type
}
func init() {
if apiMediaType := os.Getenv("KUBE_TEST_API_TYPE"); len(apiMediaType) > 0 {
var ok bool
mediaType, options, err := mime.ParseMediaType(apiMediaType)
if err != nil {
panic(err)
}
serializer, ok = api.Codecs.SerializerForMediaType(mediaType, options)
if !ok {
panic(fmt.Sprintf("no serializer for %s", apiMediaType))
}
}
if storageMediaType := StorageMediaType(); len(storageMediaType) > 0 {
var ok bool
mediaType, options, err := mime.ParseMediaType(storageMediaType)
if err != nil {
panic(err)
}
storageSerializer, ok = api.Codecs.SerializerForMediaType(mediaType, options)
if !ok {
panic(fmt.Sprintf("no serializer for %s", storageMediaType))
}
}
kubeTestAPI := os.Getenv("KUBE_TEST_API")
if len(kubeTestAPI) != 0 {
testGroupVersions := strings.Split(kubeTestAPI, ",")
for _, gvString := range testGroupVersions {
groupVersion, err := unversioned.ParseGroupVersion(gvString)
if err != nil {
panic(fmt.Sprintf("Error parsing groupversion %v: %v", gvString, err))
}
internalGroupVersion := unversioned.GroupVersion{Group: groupVersion.Group, Version: runtime.APIVersionInternal}
Groups[groupVersion.Group] = TestGroup{
externalGroupVersion: groupVersion,
internalGroupVersion: internalGroupVersion,
internalTypes: api.Scheme.KnownTypes(internalGroupVersion),
}
}
}
if _, ok := Groups[api.GroupName]; !ok {
Groups[api.GroupName] = TestGroup{
externalGroupVersion: unversioned.GroupVersion{Group: api.GroupName, Version: registered.GroupOrDie(api.GroupName).GroupVersion.Version},
internalGroupVersion: api.SchemeGroupVersion,
internalTypes: api.Scheme.KnownTypes(api.SchemeGroupVersion),
}
}
if _, ok := Groups[extensions.GroupName]; !ok {
Groups[extensions.GroupName] = TestGroup{
externalGroupVersion: unversioned.GroupVersion{Group: extensions.GroupName, Version: registered.GroupOrDie(extensions.GroupName).GroupVersion.Version},
internalGroupVersion: extensions.SchemeGroupVersion,
internalTypes: api.Scheme.KnownTypes(extensions.SchemeGroupVersion),
}
}
if _, ok := Groups[autoscaling.GroupName]; !ok {
internalTypes := make(map[string]reflect.Type)
for k, t := range api.Scheme.KnownTypes(extensions.SchemeGroupVersion) {
if k == "Scale" {
continue
}
internalTypes[k] = t
}
Groups[autoscaling.GroupName] = TestGroup{
externalGroupVersion: unversioned.GroupVersion{Group: autoscaling.GroupName, Version: registered.GroupOrDie(autoscaling.GroupName).GroupVersion.Version},
internalGroupVersion: extensions.SchemeGroupVersion,
internalTypes: internalTypes,
}
}
if _, ok := Groups[autoscaling.GroupName+"IntraGroup"]; !ok {
internalTypes := make(map[string]reflect.Type)
for k, t := range api.Scheme.KnownTypes(extensions.SchemeGroupVersion) {
if k == "Scale" {
internalTypes[k] = t
break
}
}
Groups[autoscaling.GroupName] = TestGroup{
externalGroupVersion: unversioned.GroupVersion{Group: autoscaling.GroupName, Version: registered.GroupOrDie(autoscaling.GroupName).GroupVersion.Version},
internalGroupVersion: autoscaling.SchemeGroupVersion,
internalTypes: internalTypes,
}
}
if _, ok := Groups[batch.GroupName]; !ok {
Groups[batch.GroupName] = TestGroup{
externalGroupVersion: unversioned.GroupVersion{Group: batch.GroupName, Version: registered.GroupOrDie(batch.GroupName).GroupVersion.Version},
internalGroupVersion: extensions.SchemeGroupVersion,
internalTypes: api.Scheme.KnownTypes(extensions.SchemeGroupVersion),
}
}
if _, ok := Groups[apps.GroupName]; !ok {
Groups[apps.GroupName] = TestGroup{
externalGroupVersion: unversioned.GroupVersion{Group: apps.GroupName, Version: registered.GroupOrDie(apps.GroupName).GroupVersion.Version},
internalGroupVersion: extensions.SchemeGroupVersion,
internalTypes: api.Scheme.KnownTypes(extensions.SchemeGroupVersion),
}
}
if _, ok := Groups[federation.GroupName]; !ok {
Groups[federation.GroupName] = TestGroup{
externalGroupVersion: unversioned.GroupVersion{Group: federation.GroupName, Version: registered.GroupOrDie(federation.GroupName).GroupVersion.Version},
internalGroupVersion: federation.SchemeGroupVersion,
internalTypes: api.Scheme.KnownTypes(federation.SchemeGroupVersion),
}
}
Default = Groups[api.GroupName]
Autoscaling = Groups[autoscaling.GroupName]
Batch = Groups[batch.GroupName]
Apps = Groups[apps.GroupName]
Extensions = Groups[extensions.GroupName]
Federation = Groups[federation.GroupName]
}
func (g TestGroup) ContentConfig() (string, *unversioned.GroupVersion, runtime.Codec) {
return "application/json", g.GroupVersion(), g.Codec()
}
func (g TestGroup) GroupVersion() *unversioned.GroupVersion {
copyOfGroupVersion := g.externalGroupVersion
return &copyOfGroupVersion
}
// InternalGroupVersion returns the group,version used to identify the internal
// types for this API
func (g TestGroup) InternalGroupVersion() unversioned.GroupVersion {
return g.internalGroupVersion
}
// InternalTypes returns a map of internal API types' kind names to their Go types.
func (g TestGroup) InternalTypes() map[string]reflect.Type {
return g.internalTypes
}
// Codec returns the codec for the API version to test against, as set by the
// KUBE_TEST_API_TYPE env var.
func (g TestGroup) Codec() runtime.Codec {
if serializer.Serializer == nil {
return api.Codecs.LegacyCodec(g.externalGroupVersion)
}
return api.Codecs.CodecForVersions(serializer, api.Codecs.UniversalDeserializer(), []unversioned.GroupVersion{g.externalGroupVersion}, nil)
}
// NegotiatedSerializer returns the negotiated serializer for the server.
func (g TestGroup) NegotiatedSerializer() runtime.NegotiatedSerializer {
return api.Codecs
}
func StorageMediaType() string {
return os.Getenv("KUBE_TEST_API_STORAGE_TYPE")
}
// StorageCodec returns the codec for the API version to store in etcd, as set by the
// KUBE_TEST_API_STORAGE_TYPE env var.
func (g TestGroup) StorageCodec() runtime.Codec {
s := storageSerializer.Serializer
if s == nil {
return api.Codecs.LegacyCodec(g.externalGroupVersion)
}
// etcd2 only supports string data - we must wrap any result before returning
// TODO: remove for etcd3 / make parameterizable
if !storageSerializer.EncodesAsText {
s = runtime.NewBase64Serializer(s)
}
ds := recognizer.NewDecoder(s, api.Codecs.UniversalDeserializer())
return api.Codecs.CodecForVersions(s, ds, []unversioned.GroupVersion{g.externalGroupVersion}, nil)
}
// Converter returns the api.Scheme for the API version to test against, as set by the
// KUBE_TEST_API env var.
func (g TestGroup) Converter() runtime.ObjectConvertor {
interfaces, err := registered.GroupOrDie(g.externalGroupVersion.Group).InterfacesFor(g.externalGroupVersion)
if err != nil {
panic(err)
}
return interfaces.ObjectConvertor
}
// MetadataAccessor returns the MetadataAccessor for the API version to test against,
// as set by the KUBE_TEST_API env var.
func (g TestGroup) MetadataAccessor() meta.MetadataAccessor {
interfaces, err := registered.GroupOrDie(g.externalGroupVersion.Group).InterfacesFor(g.externalGroupVersion)
if err != nil {
panic(err)
}
return interfaces.MetadataAccessor
}
// SelfLink returns a self link that will appear to be for the version Version().
// 'resource' should be the resource path, e.g. "pods" for the Pod type. 'name' should be
// empty for lists.
func (g TestGroup) SelfLink(resource, name string) string {
if g.externalGroupVersion.Group == api.GroupName {
if name == "" {
return fmt.Sprintf("/api/%s/%s", g.externalGroupVersion.Version, resource)
}
return fmt.Sprintf("/api/%s/%s/%s", g.externalGroupVersion.Version, resource, name)
} else {
// TODO: will need a /apis prefix once we have proper multi-group
// support
if name == "" {
return fmt.Sprintf("/apis/%s/%s/%s", g.externalGroupVersion.Group, g.externalGroupVersion.Version, resource)
}
return fmt.Sprintf("/apis/%s/%s/%s/%s", g.externalGroupVersion.Group, g.externalGroupVersion.Version, resource, name)
}
}
// Returns the appropriate path for the given prefix (watch, proxy, redirect, etc), resource, namespace and name.
// For ex, this is of the form:
// /api/v1/watch/namespaces/foo/pods/pod0 for v1.
func (g TestGroup) ResourcePathWithPrefix(prefix, resource, namespace, name string) string {
var path string
if g.externalGroupVersion.Group == api.GroupName {
path = "/api/" + g.externalGroupVersion.Version
} else {
// TODO: switch back once we have proper multiple group support
// path = "/apis/" + g.Group + "/" + Version(group...)
path = "/apis/" + g.externalGroupVersion.Group + "/" + g.externalGroupVersion.Version
}
if prefix != "" {
path = path + "/" + prefix
}
if namespace != "" {
path = path + "/namespaces/" + namespace
}
// Resource names are lower case.
resource = strings.ToLower(resource)
if resource != "" {
path = path + "/" + resource
}
if name != "" {
path = path + "/" + name
}
return path
}
// Returns the appropriate path for the given resource, namespace and name.
// For example, this is of the form:
// /api/v1/namespaces/foo/pods/pod0 for v1.
func (g TestGroup) ResourcePath(resource, namespace, name string) string {
return g.ResourcePathWithPrefix("", resource, namespace, name)
}
func (g TestGroup) RESTMapper() meta.RESTMapper {
return registered.RESTMapper()
}
// ExternalGroupVersions returns all external group versions allowed for the server.
func ExternalGroupVersions() []unversioned.GroupVersion {
versions := []unversioned.GroupVersion{}
for _, g := range Groups {
gv := g.GroupVersion()
versions = append(versions, *gv)
}
return versions
}
// Get codec based on runtime.Object
func GetCodecForObject(obj runtime.Object) (runtime.Codec, error) {
kind, err := api.Scheme.ObjectKind(obj)
if err != nil {
return nil, fmt.Errorf("unexpected encoding error: %v", err)
}
for _, group := range Groups {
if group.GroupVersion().Group != kind.Group {
continue
}
if api.Scheme.Recognizes(kind) {
return group.Codec(), nil
}
}
// Codec used for unversioned types
if api.Scheme.Recognizes(kind) {
serializer, ok := api.Codecs.SerializerForFileExtension("json")
if !ok {
return nil, fmt.Errorf("no serializer registered for json")
}
return serializer, nil
}
return nil, fmt.Errorf("unexpected kind: %v", kind)
}
func NewTestGroup(external, internal unversioned.GroupVersion, internalTypes map[string]reflect.Type) TestGroup {
return TestGroup{external, internal, internalTypes}
}

57293
vendor/k8s.io/kubernetes/pkg/api/types.generated.go generated vendored Normal file

File diff suppressed because it is too large Load diff

2718
vendor/k8s.io/kubernetes/pkg/api/types.go generated vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,133 @@
// +build !ignore_autogenerated
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/conversion"
time "time"
)
func DeepCopy_unversioned_Duration(in Duration, out *Duration, c *conversion.Cloner) error {
out.Duration = in.Duration
return nil
}
func DeepCopy_unversioned_GroupKind(in GroupKind, out *GroupKind, c *conversion.Cloner) error {
out.Group = in.Group
out.Kind = in.Kind
return nil
}
func DeepCopy_unversioned_GroupResource(in GroupResource, out *GroupResource, c *conversion.Cloner) error {
out.Group = in.Group
out.Resource = in.Resource
return nil
}
func DeepCopy_unversioned_GroupVersion(in GroupVersion, out *GroupVersion, c *conversion.Cloner) error {
out.Group = in.Group
out.Version = in.Version
return nil
}
func DeepCopy_unversioned_GroupVersionKind(in GroupVersionKind, out *GroupVersionKind, c *conversion.Cloner) error {
out.Group = in.Group
out.Version = in.Version
out.Kind = in.Kind
return nil
}
func DeepCopy_unversioned_GroupVersionResource(in GroupVersionResource, out *GroupVersionResource, c *conversion.Cloner) error {
out.Group = in.Group
out.Version = in.Version
out.Resource = in.Resource
return nil
}
func DeepCopy_unversioned_LabelSelector(in LabelSelector, out *LabelSelector, c *conversion.Cloner) error {
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 LabelSelectorRequirement, out *LabelSelectorRequirement, c *conversion.Cloner) error {
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 ListMeta, out *ListMeta, c *conversion.Cloner) error {
out.SelfLink = in.SelfLink
out.ResourceVersion = in.ResourceVersion
return nil
}
func DeepCopy_unversioned_ServerAddressByClientCIDR(in ServerAddressByClientCIDR, out *ServerAddressByClientCIDR, c *conversion.Cloner) error {
out.ClientCIDR = in.ClientCIDR
out.ServerAddress = in.ServerAddress
return nil
}
func DeepCopy_unversioned_Time(in Time, out *Time, c *conversion.Cloner) error {
if newVal, err := c.DeepCopy(in.Time); err != nil {
return err
} else {
out.Time = newVal.(time.Time)
}
return nil
}
func DeepCopy_unversioned_Timestamp(in Timestamp, out *Timestamp, c *conversion.Cloner) error {
out.Seconds = in.Seconds
out.Nanos = in.Nanos
return nil
}
func DeepCopy_unversioned_TypeMeta(in TypeMeta, out *TypeMeta, c *conversion.Cloner) error {
out.Kind = in.Kind
out.APIVersion = in.APIVersion
return nil
}

View file

@ -0,0 +1,47 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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

@ -0,0 +1,377 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 go-to-protobuf. Do not edit it manually!
syntax = 'proto2';
package k8s.io.kubernetes.pkg.api.unversioned;
import "k8s.io/kubernetes/pkg/runtime/generated.proto";
import "k8s.io/kubernetes/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "unversioned";
// APIGroup contains the name, the supported versions, and the preferred version
// of a group.
message APIGroup {
// name is the name of the group.
optional string name = 1;
// versions are the versions supported in this group.
repeated GroupVersionForDiscovery versions = 2;
// preferredVersion is the version preferred by the API server, which
// probably is the storage version.
optional GroupVersionForDiscovery preferredVersion = 3;
// 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.
repeated ServerAddressByClientCIDR serverAddressByClientCIDRs = 4;
}
// APIGroupList is a list of APIGroup, to allow clients to discover the API at
// /apis.
message APIGroupList {
// groups is a list of APIGroup.
repeated APIGroup groups = 1;
}
// APIResource specifies the name of a resource and whether it is namespaced.
message APIResource {
// name is the name of the resource.
optional string name = 1;
// namespaced indicates if a resource is namespaced or not.
optional bool namespaced = 2;
// kind is the kind for the resource (e.g. 'Foo' is the kind for a resource 'foo')
optional string kind = 3;
}
// 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.
message APIResourceList {
// groupVersion is the group and version this APIResourceList is for.
optional string groupVersion = 1;
// resources contains the name of the resources and if they are namespaced.
repeated APIResource resources = 2;
}
// 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
message APIVersions {
// versions are the api versions that are available.
repeated string versions = 1;
// 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.
repeated ServerAddressByClientCIDR serverAddressByClientCIDRs = 2;
}
// 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.
message Duration {
optional int64 duration = 1;
}
// ExportOptions is the query options to the standard REST get call.
message ExportOptions {
// Should this value be exported. Export strips fields that a user can not specify.`
optional bool export = 1;
// Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'
optional bool exact = 2;
}
// GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying
// concepts during lookup stages without having partially valid types
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
message GroupKind {
optional string group = 1;
optional string kind = 2;
}
// GroupResource specifies a Group and a Resource, but does not force a version. This is useful for identifying
// concepts during lookup stages without having partially valid types
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
message GroupResource {
optional string group = 1;
optional string resource = 2;
}
// GroupVersion contains the "group" and the "version", which uniquely identifies the API.
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
message GroupVersion {
optional string group = 1;
optional string version = 2;
}
// GroupVersion contains the "group/version" and "version" string of a version.
// It is made a struct to keep extensiblity.
message GroupVersionForDiscovery {
// groupVersion specifies the API group and version in the form "group/version"
optional string groupVersion = 1;
// version specifies the version in the form of "version". This is to save
// the clients the trouble of splitting the GroupVersion.
optional string version = 2;
}
// GroupVersionKind unambiguously identifies a kind. It doesn't anonymously include GroupVersion
// to avoid automatic coersion. It doesn't use a GroupVersion to avoid custom marshalling
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
message GroupVersionKind {
optional string group = 1;
optional string version = 2;
optional string kind = 3;
}
// GroupVersionResource unambiguously identifies a resource. It doesn't anonymously include GroupVersion
// to avoid automatic coersion. It doesn't use a GroupVersion to avoid custom marshalling
//
// +protobuf.options.(gogoproto.goproto_stringer)=false
message GroupVersionResource {
optional string group = 1;
optional string version = 2;
optional string resource = 3;
}
// 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.
message LabelSelector {
// 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.
map<string, string> matchLabels = 1;
// matchExpressions is a list of label selector requirements. The requirements are ANDed.
repeated LabelSelectorRequirement matchExpressions = 2;
}
// A label selector requirement is a selector that contains values, a key, and an operator that
// relates the key and values.
message LabelSelectorRequirement {
// key is the label key that the selector applies to.
optional string key = 1;
// operator represents a key's relationship to a set of values.
// Valid operators ard In, NotIn, Exists and DoesNotExist.
optional string operator = 2;
// 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.
repeated string values = 3;
}
// ListMeta describes metadata that synthetic resources must have, including lists and
// various status objects. A resource may have only one of {ObjectMeta, ListMeta}.
message ListMeta {
// SelfLink is a URL representing this object.
// Populated by the system.
// Read-only.
optional string selfLink = 1;
// 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 string resourceVersion = 2;
}
// RootPaths lists the paths available at root.
// For example: "/healthz", "/apis".
message RootPaths {
// paths are the paths available at root.
repeated string paths = 1;
}
// ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match.
message ServerAddressByClientCIDR {
// The CIDR with which clients can match their IP to figure out the server address that they should use.
optional string clientCIDR = 1;
// Address of this server, suitable for a client that matches the above CIDR.
// This can be a hostname, hostname:port, IP or IP:port.
optional string serverAddress = 2;
}
// Status is a return value for calls that don't return other objects.
message Status {
// Standard list metadata.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
optional ListMeta metadata = 1;
// 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 string status = 2;
// A human-readable description of the status of this operation.
optional string message = 3;
// 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 string reason = 4;
// 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 StatusDetails details = 5;
// Suggested HTTP return code for this status, 0 if not set.
optional int32 code = 6;
}
// StatusCause provides more information about an api.Status failure, including
// cases when multiple errors are encountered.
message StatusCause {
// A machine-readable description of the cause of the error. If this value is
// empty there is no information available.
optional string reason = 1;
// A human-readable description of the cause of the error. This field may be
// presented as-is to a reader.
optional string message = 2;
// 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 string field = 3;
}
// 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.
message StatusDetails {
// The name attribute of the resource associated with the status StatusReason
// (when there is a single name which can be described).
optional string name = 1;
// The group attribute of the resource associated with the status StatusReason.
optional string group = 2;
// 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 string kind = 3;
// The Causes array includes more details associated with the StatusReason
// failure. Not all StatusReasons may provide detailed causes.
repeated StatusCause causes = 4;
// If specified, the time in seconds before the operation should be retried.
optional int32 retryAfterSeconds = 5;
}
// 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
message Time {
// 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.
optional int64 seconds = 1;
// 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.
optional int32 nanos = 2;
}
// 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.
message Timestamp {
// 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.
optional int64 seconds = 1;
// 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.
optional int32 nanos = 2;
}
// 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.
message TypeMeta {
// 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 string kind = 1;
// 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 string apiVersion = 2;
}

View file

@ -0,0 +1,292 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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
s := strings.SplitN(arg, ".", 3)
if len(s) == 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) IsEmpty() 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 {
s := strings.SplitN(gr, ".", 2)
if len(s) == 1 {
return GroupResource{Resource: s[0]}
}
return GroupResource{Group: s[1], Resource: s[0]}
}
// 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) IsEmpty() 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) IsEmpty() 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"`
}
// IsEmpty returns true if group, version, and kind are empty
func (gvk GroupVersionKind) IsEmpty() 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"`
}
// IsEmpty returns true if group and version are empty
func (gv GroupVersion) IsEmpty() 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.IsEmpty() {
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
}
// 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
}
s := strings.Split(gv, "/")
// "v1" is the only special case. Otherwise GroupVersion is expected to contain
// one "/" dividing the string into two parts.
switch {
case len(s) == 1 && gv == "v1":
return GroupVersion{"", "v1"}, nil
case len(s) == 1:
return GroupVersion{"", s[0]}, nil
case len(s) == 2:
return GroupVersion{s[0], s[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)
}
// 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 nil }

154
vendor/k8s.io/kubernetes/pkg/api/unversioned/helpers.go generated vendored Normal file
View file

@ -0,0 +1,154 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/util/sets"
)
// 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, labels.EqualsOperator, sets.NewString(v))
if err != nil {
return nil, err
}
selector = selector.Add(*r)
}
for _, expr := range ps.MatchExpressions {
var op labels.Operator
switch expr.Operator {
case LabelSelectorOpIn:
op = labels.InOperator
case LabelSelectorOpNotIn:
op = labels.NotInOperator
case LabelSelectorOpExists:
op = labels.ExistsOperator
case LabelSelectorOpDoesNotExist:
op = labels.DoesNotExistOperator
default:
return nil, fmt.Errorf("%q is not a valid pod selector operator", expr.Operator)
}
r, err := labels.NewRequirement(expr.Key, op, sets.NewString(expr.Values...))
if err != nil {
return nil, err
}
selector = selector.Add(*r)
}
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 labels.EqualsOperator, labels.DoubleEqualsOperator:
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 labels.InOperator:
op = LabelSelectorOpIn
case labels.NotInOperator:
op = LabelSelectorOpNotIn
case labels.ExistsOperator:
op = LabelSelectorOpExists
case labels.DoesNotExistOperator:
op = LabelSelectorOpDoesNotExist
case labels.GreaterThanOperator, labels.LessThanOperator:
// 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

@ -0,0 +1,42 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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 back a Group qualified GroupKind
func Kind(kind string) GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// 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 *Status) GetObjectKind() ObjectKind { return &obj.TypeMeta }
func (obj *APIVersions) GetObjectKind() ObjectKind { return &obj.TypeMeta }
func (obj *APIGroupList) GetObjectKind() ObjectKind { return &obj.TypeMeta }
func (obj *APIGroup) GetObjectKind() ObjectKind { return &obj.TypeMeta }
func (obj *APIResourceList) GetObjectKind() ObjectKind { return &obj.TypeMeta }
func (obj *ExportOptions) GetObjectKind() ObjectKind { return &obj.TypeMeta }

153
vendor/k8s.io/kubernetes/pkg/api/unversioned/time.go generated vendored Normal file
View file

@ -0,0 +1,153 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
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"
"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
type Time struct {
time.Time `protobuf:"-"`
}
// 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))
}
// 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

@ -0,0 +1,70 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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) { return m.ProtoTime().Size() }
// Reset implements the protobuf marshalling interface.
func (m *Time) Unmarshal(data []byte) error {
p := Timestamp{}
if err := p.Unmarshal(data); err != nil {
return err
}
m.Time = time.Unix(p.Seconds, int64(p.Nanos))
return nil
}
// Marshal implements the protobuf marshalling interface.
func (m *Time) Marshal() (data []byte, err error) {
return m.ProtoTime().Marshal()
}
// MarshalTo implements the protobuf marshalling interface.
func (m *Time) MarshalTo(data []byte) (int, error) {
return m.ProtoTime().MarshalTo(data)
}

460
vendor/k8s.io/kubernetes/pkg/api/unversioned/types.go generated vendored Normal file
View file

@ -0,0 +1,460 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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
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
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.
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
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
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
Status string `json:"status,omitempty" protobuf:"bytes,2,opt,name=status"`
// A human-readable description of the status of this operation.
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.
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.
Details *StatusDetails `json:"details,omitempty" protobuf:"bytes,5,opt,name=details"`
// Suggested HTTP return code for this status, 0 if not set.
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).
Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`
// The group attribute of the resource associated with the status StatusReason.
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
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.
Causes []StatusCause `json:"causes,omitempty" protobuf:"bytes,4,rep,name=causes"`
// If specified, the time in seconds before the operation should be retried.
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.
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.
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"
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.
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 extensiblity.
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.
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.
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.
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

@ -0,0 +1,208 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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 extensiblity.",
"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

@ -0,0 +1,81 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
"fmt"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/util/validation"
"k8s.io/kubernetes/pkg/util/validation/field"
)
var (
labelValueErrorMsg string = fmt.Sprintf(`must have at most %d characters, matching regex %s: e.g. "MyValue" or ""`, validation.LabelValueMaxLength, validation.LabelValueFmt)
qualifiedNameErrorMsg string = fmt.Sprintf(`must be a qualified name (at most %d characters, matching regex %s), with an optional DNS subdomain prefix (at most %d characters, matching regex %s) and slash (/): e.g. "MyName" or "example.com/MyName"`, validation.QualifiedNameMaxLength, validation.QualifiedNameFmt, validation.DNS1123SubdomainMaxLength, validation.DNS1123SubdomainFmt)
)
func ValidateLabelSelector(ps *unversioned.LabelSelector, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if ps == nil {
return allErrs
}
allErrs = append(allErrs, ValidateLabels(ps.MatchLabels, fldPath.Child("matchLabels"))...)
for i, expr := range ps.MatchExpressions {
allErrs = append(allErrs, ValidateLabelSelectorRequirement(expr, fldPath.Child("matchExpressions").Index(i))...)
}
return allErrs
}
func ValidateLabelSelectorRequirement(sr unversioned.LabelSelectorRequirement, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
switch sr.Operator {
case unversioned.LabelSelectorOpIn, unversioned.LabelSelectorOpNotIn:
if len(sr.Values) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("values"), "must be specified when `operator` is 'In' or 'NotIn'"))
}
case unversioned.LabelSelectorOpExists, unversioned.LabelSelectorOpDoesNotExist:
if len(sr.Values) > 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("values"), "may not be specified when `operator` is 'Exists' or 'DoesNotExist'"))
}
default:
allErrs = append(allErrs, field.Invalid(fldPath.Child("operator"), sr.Operator, "not a valid selector operator"))
}
allErrs = append(allErrs, ValidateLabelName(sr.Key, fldPath.Child("key"))...)
return allErrs
}
// ValidateLabelName validates that the label name is correctly defined.
func ValidateLabelName(labelName string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if !validation.IsQualifiedName(labelName) {
allErrs = append(allErrs, field.Invalid(fldPath, labelName, qualifiedNameErrorMsg))
}
return allErrs
}
// ValidateLabels validates that a set of labels are correctly defined.
func ValidateLabels(labels map[string]string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
for k, v := range labels {
allErrs = append(allErrs, ValidateLabelName(k, fldPath)...)
if !validation.IsValidLabelValue(v) {
allErrs = append(allErrs, field.Invalid(fldPath, v, labelValueErrorMsg))
}
}
return allErrs
}

View file

@ -0,0 +1,27 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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"
)

48
vendor/k8s.io/kubernetes/pkg/api/util/group_version.go generated vendored Normal file
View file

@ -0,0 +1,48 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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: This GetVersion/GetGroup arrangement is temporary and will be replaced
// with a GroupAndVersion type.
package util
import "strings"
func GetVersion(groupVersion string) string {
s := strings.Split(groupVersion, "/")
if len(s) != 2 {
// e.g. return "v1" for groupVersion="v1"
return s[len(s)-1]
}
return s[1]
}
func GetGroup(groupVersion string) string {
s := strings.Split(groupVersion, "/")
if len(s) == 1 {
// e.g. return "" for groupVersion="v1"
return ""
}
return s[0]
}
// GetGroupVersion returns the "group/version". It returns "version" is if group
// is empty. It returns "group/" if version is empty.
func GetGroupVersion(group, version string) string {
if len(group) == 0 {
return version
}
return group + "/" + version
}

545
vendor/k8s.io/kubernetes/pkg/api/v1/conversion.go generated vendored Normal file
View file

@ -0,0 +1,545 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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 (
"fmt"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/conversion"
"k8s.io/kubernetes/pkg/runtime"
"speter.net/go/exp/math/dec/inf"
)
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"
)
func addConversionFuncs(scheme *runtime.Scheme) {
// 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_ServiceSpec_To_api_ServiceSpec,
Convert_v1_ResourceList_To_api_ResourceList,
)
if err != nil {
// If one of the conversion functions is malformed, detect it immediately.
panic(err)
}
// Add field label conversions for kinds having selectable nothing but ObjectMeta fields.
for _, kind := range []string{
"Endpoints",
"ResourceQuota",
"PersistentVolumeClaim",
"Service",
"ServiceAccount",
"ConfigMap",
} {
err = api.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 {
// If one of the conversion functions is malformed, detect it immediately.
panic(err)
}
}
// Add field conversion funcs.
err = api.Scheme.AddFieldLabelConversionFunc("v1", "Pod",
func(label, value string) (string, string, error) {
switch label {
case "metadata.name",
"metadata.namespace",
"metadata.labels",
"metadata.annotations",
"status.phase",
"status.podIP",
"spec.nodeName",
"spec.restartPolicy":
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 {
// If one of the conversion functions is malformed, detect it immediately.
panic(err)
}
err = api.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 {
// If one of the conversion functions is malformed, detect it immediately.
panic(err)
}
err = api.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 {
// If one of the conversion functions is malformed, detect it immediately.
panic(err)
}
err = api.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)
}
})
if err != nil {
// If one of the conversion functions is malformed, detect it immediately.
panic(err)
}
err = api.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)
}
})
if err != nil {
// If one of the conversion functions is malformed, detect it immediately.
panic(err)
}
err = api.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 {
// If one of the conversion functions is malformed, detect it immediately.
panic(err)
}
err = api.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)
}
})
if err != nil {
// If one of the conversion functions is malformed, detect it immediately.
panic(err)
}
}
func Convert_api_ReplicationControllerSpec_To_v1_ReplicationControllerSpec(in *api.ReplicationControllerSpec, out *ReplicationControllerSpec, s conversion.Scope) error {
out.Replicas = new(int32)
*out.Replicas = int32(in.Replicas)
if in.Selector != nil {
out.Selector = make(map[string]string)
for key, val := range in.Selector {
out.Selector[key] = val
}
} else {
out.Selector = nil
}
//if in.TemplateRef != nil {
// out.TemplateRef = new(ObjectReference)
// if err := Convert_api_ObjectReference_To_v1_ObjectReference(in.TemplateRef, out.TemplateRef, s); err != nil {
// return err
// }
//} else {
// out.TemplateRef = nil
//}
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 {
out.Replicas = *in.Replicas
if in.Selector != nil {
out.Selector = make(map[string]string)
for key, val := range in.Selector {
out.Selector[key] = val
}
} else {
out.Selector = nil
}
//if in.TemplateRef != nil {
// out.TemplateRef = new(api.ObjectReference)
// if err := Convert_v1_ObjectReference_To_api_ObjectReference(in.TemplateRef, out.TemplateRef, s); err != nil {
// return err
// }
//} else {
// out.TemplateRef = nil
//}
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
}
// 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 in.Volumes != nil {
out.Volumes = make([]Volume, len(in.Volumes))
for i := range in.Volumes {
if err := Convert_api_Volume_To_v1_Volume(&in.Volumes[i], &out.Volumes[i], s); err != nil {
return err
}
}
} else {
out.Volumes = nil
}
if in.Containers != nil {
out.Containers = make([]Container, len(in.Containers))
for i := range in.Containers {
if err := Convert_api_Container_To_v1_Container(&in.Containers[i], &out.Containers[i], s); err != nil {
return err
}
}
} else {
out.Containers = nil
}
out.RestartPolicy = RestartPolicy(in.RestartPolicy)
if in.TerminationGracePeriodSeconds != nil {
out.TerminationGracePeriodSeconds = new(int64)
*out.TerminationGracePeriodSeconds = *in.TerminationGracePeriodSeconds
} else {
out.TerminationGracePeriodSeconds = nil
}
if in.ActiveDeadlineSeconds != nil {
out.ActiveDeadlineSeconds = new(int64)
*out.ActiveDeadlineSeconds = *in.ActiveDeadlineSeconds
} else {
out.ActiveDeadlineSeconds = nil
}
out.DNSPolicy = DNSPolicy(in.DNSPolicy)
if in.NodeSelector != nil {
out.NodeSelector = make(map[string]string)
for key, val := range in.NodeSelector {
out.NodeSelector[key] = val
}
} else {
out.NodeSelector = nil
}
out.ServiceAccountName = in.ServiceAccountName
// DeprecatedServiceAccount is an alias for ServiceAccountName.
out.DeprecatedServiceAccount = in.ServiceAccountName
out.NodeName = in.NodeName
if in.SecurityContext != nil {
out.SecurityContext = new(PodSecurityContext)
if err := Convert_api_PodSecurityContext_To_v1_PodSecurityContext(in.SecurityContext, out.SecurityContext, s); err != nil {
return err
}
// 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
}
if in.ImagePullSecrets != nil {
out.ImagePullSecrets = make([]LocalObjectReference, len(in.ImagePullSecrets))
for i := range in.ImagePullSecrets {
if err := Convert_api_LocalObjectReference_To_v1_LocalObjectReference(&in.ImagePullSecrets[i], &out.ImagePullSecrets[i], s); err != nil {
return err
}
}
} else {
out.ImagePullSecrets = nil
}
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
return nil
}
func Convert_v1_PodSpec_To_api_PodSpec(in *PodSpec, out *api.PodSpec, s conversion.Scope) error {
SetDefaults_PodSpec(in)
if in.Volumes != nil {
out.Volumes = make([]api.Volume, len(in.Volumes))
for i := range in.Volumes {
if err := Convert_v1_Volume_To_api_Volume(&in.Volumes[i], &out.Volumes[i], s); err != nil {
return err
}
}
} else {
out.Volumes = nil
}
if in.Containers != nil {
out.Containers = make([]api.Container, len(in.Containers))
for i := range in.Containers {
if err := Convert_v1_Container_To_api_Container(&in.Containers[i], &out.Containers[i], s); err != nil {
return err
}
}
} else {
out.Containers = nil
}
out.RestartPolicy = api.RestartPolicy(in.RestartPolicy)
if in.TerminationGracePeriodSeconds != nil {
out.TerminationGracePeriodSeconds = new(int64)
*out.TerminationGracePeriodSeconds = *in.TerminationGracePeriodSeconds
} else {
out.TerminationGracePeriodSeconds = nil
}
if in.ActiveDeadlineSeconds != nil {
out.ActiveDeadlineSeconds = new(int64)
*out.ActiveDeadlineSeconds = *in.ActiveDeadlineSeconds
} else {
out.ActiveDeadlineSeconds = nil
}
out.DNSPolicy = api.DNSPolicy(in.DNSPolicy)
if in.NodeSelector != nil {
out.NodeSelector = make(map[string]string)
for key, val := range in.NodeSelector {
out.NodeSelector[key] = val
}
} else {
out.NodeSelector = nil
}
// We support DeprecatedServiceAccount as an alias for ServiceAccountName.
// If both are specified, ServiceAccountName (the new field) wins.
out.ServiceAccountName = in.ServiceAccountName
if in.ServiceAccountName == "" {
out.ServiceAccountName = in.DeprecatedServiceAccount
}
out.NodeName = in.NodeName
if in.SecurityContext != nil {
out.SecurityContext = new(api.PodSecurityContext)
if err := Convert_v1_PodSecurityContext_To_api_PodSecurityContext(in.SecurityContext, out.SecurityContext, s); err != nil {
return err
}
}
// 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
if in.ImagePullSecrets != nil {
out.ImagePullSecrets = make([]api.LocalObjectReference, len(in.ImagePullSecrets))
for i := range in.ImagePullSecrets {
if err := Convert_v1_LocalObjectReference_To_api_LocalObjectReference(&in.ImagePullSecrets[i], &out.ImagePullSecrets[i], s); err != nil {
return err
}
}
} else {
out.ImagePullSecrets = nil
}
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
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
}
// 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 {
return autoConvert_v1_Pod_To_api_Pod(in, out, s)
}
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.
for _, ip := range in.ExternalIPs {
out.DeprecatedPublicIPs = append(out.DeprecatedPublicIPs, ip)
}
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 = nil
for _, ip := range in.DeprecatedPublicIPs {
out.ExternalIPs = append(out.ExternalIPs, ip)
}
}
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
}
if in.RunAsUser != nil {
out.RunAsUser = new(int64)
*out.RunAsUser = *in.RunAsUser
} else {
out.RunAsUser = nil
}
if in.RunAsNonRoot != nil {
out.RunAsNonRoot = new(bool)
*out.RunAsNonRoot = *in.RunAsNonRoot
} else {
out.RunAsNonRoot = nil
}
if in.FSGroup != nil {
out.FSGroup = new(int64)
*out.FSGroup = *in.FSGroup
} else {
out.FSGroup = nil
}
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
}
if in.RunAsUser != nil {
out.RunAsUser = new(int64)
*out.RunAsUser = *in.RunAsUser
} else {
out.RunAsUser = nil
}
if in.RunAsNonRoot != nil {
out.RunAsNonRoot = new(bool)
*out.RunAsNonRoot = *in.RunAsNonRoot
} else {
out.RunAsNonRoot = nil
}
if in.FSGroup != nil {
out.FSGroup = new(int64)
*out.FSGroup = *in.FSGroup
} else {
out.FSGroup = nil
}
return nil
}
func Convert_v1_ResourceList_To_api_ResourceList(in *ResourceList, out *api.ResourceList, s conversion.Scope) error {
if *in == nil {
return nil
}
converted := make(api.ResourceList)
for key, val := range *in {
value := val.Copy()
// 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
value.Amount.Round(value.Amount, milliScale, inf.RoundUp)
converted[api.ResourceName(key)] = *value
}
*out = converted
return nil
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

288
vendor/k8s.io/kubernetes/pkg/api/v1/defaults.go generated vendored Normal file
View file

@ -0,0 +1,288 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/intstr"
"k8s.io/kubernetes/pkg/util/parsers"
)
func addDefaultingFuncs(scheme *runtime.Scheme) {
scheme.AddDefaultingFuncs(
SetDefaults_PodExecOptions,
SetDefaults_PodAttachOptions,
SetDefaults_ReplicationController,
SetDefaults_Volume,
SetDefaults_ContainerPort,
SetDefaults_Container,
SetDefaults_ServiceSpec,
SetDefaults_Pod,
SetDefaults_PodSpec,
SetDefaults_Probe,
SetDefaults_Secret,
SetDefaults_PersistentVolume,
SetDefaults_PersistentVolumeClaim,
SetDefaults_ISCSIVolumeSource,
SetDefaults_Endpoints,
SetDefaults_HTTPGetAction,
SetDefaults_NamespaceStatus,
SetDefaults_Node,
SetDefaults_NodeStatus,
SetDefaults_ObjectFieldSelector,
SetDefaults_LimitRangeItem,
SetDefaults_ConfigMap,
)
}
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_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_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
}
}
}
}

19
vendor/k8s.io/kubernetes/pkg/api/v1/doc.go generated vendored Normal file
View file

@ -0,0 +1,19 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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 is the v1 version of the API.
// +genconversion=true
package v1

33220
vendor/k8s.io/kubernetes/pkg/api/v1/generated.pb.go generated vendored Normal file

File diff suppressed because it is too large Load diff

2807
vendor/k8s.io/kubernetes/pkg/api/v1/generated.proto generated vendored Normal file

File diff suppressed because it is too large Load diff

141
vendor/k8s.io/kubernetes/pkg/api/v1/register.go generated vendored Normal file
View file

@ -0,0 +1,141 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
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/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime"
versionedwatch "k8s.io/kubernetes/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"}
func AddToScheme(scheme *runtime.Scheme) {
// Add the API to Scheme.
addKnownTypes(scheme)
addConversionFuncs(scheme)
addDefaultingFuncs(scheme)
}
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) {
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)
}
func (obj *Pod) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodStatusResult) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodTemplate) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodTemplateList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ReplicationController) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ReplicationControllerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Service) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ServiceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Endpoints) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *EndpointsList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Node) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *NodeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *NodeProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Binding) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Event) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *EventList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *List) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *LimitRange) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *LimitRangeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ResourceQuota) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ResourceQuotaList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Namespace) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *NamespaceList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *Secret) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *SecretList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ServiceAccount) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ServiceAccountList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PersistentVolume) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PersistentVolumeList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PersistentVolumeClaim) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PersistentVolumeClaimList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *DeleteOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ListOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodAttachOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodLogOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodExecOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ServiceProxyOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ComponentStatus) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ComponentStatusList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *SerializedReference) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *RangeAllocation) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ExportOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ConfigMap) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ConfigMapList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

57470
vendor/k8s.io/kubernetes/pkg/api/v1/types.generated.go generated vendored Normal file

File diff suppressed because it is too large Load diff

3129
vendor/k8s.io/kubernetes/pkg/api/v1/types.go generated vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

19
vendor/k8s.io/kubernetes/pkg/api/validation/doc.go generated vendored Normal file
View file

@ -0,0 +1,19 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package validation has functions for validating the correctness of api
// objects and explaining what is wrong with them when they aren't valid.
package validation

44
vendor/k8s.io/kubernetes/pkg/api/validation/events.go generated vendored Normal file
View file

@ -0,0 +1,44 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/util/validation"
"k8s.io/kubernetes/pkg/util/validation/field"
)
// ValidateEvent makes sure that the event makes sense.
func ValidateEvent(event *api.Event) field.ErrorList {
allErrs := field.ErrorList{}
// There is no namespace required for node.
// However, older client code accidentally sets event.Namespace
// to api.NamespaceDefault, so we accept that too, but "" is preferred.
if event.InvolvedObject.Kind == "Node" &&
event.Namespace != api.NamespaceDefault &&
event.Namespace != "" {
allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "not allowed for node"))
}
if event.InvolvedObject.Kind != "Node" &&
event.Namespace != event.InvolvedObject.Namespace {
allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match involvedObject"))
}
if !validation.IsDNS1123Subdomain(event.Namespace) {
allErrs = append(allErrs, field.Invalid(field.NewPath("namespace"), event.Namespace, ""))
}
return allErrs
}

66
vendor/k8s.io/kubernetes/pkg/api/validation/name.go generated vendored Normal file
View file

@ -0,0 +1,66 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
"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) (bool, string) {
for _, illegalName := range NameMayNotBe {
if name == illegalName {
return false, fmt.Sprintf(`name may not be %q`, illegalName)
}
}
for _, illegalContent := range NameMayNotContain {
if strings.Contains(name, illegalContent) {
return false, fmt.Sprintf(`name may not contain %q`, illegalContent)
}
}
return true, ""
}
// 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) (bool, string) {
for _, illegalContent := range NameMayNotContain {
if strings.Contains(name, illegalContent) {
return false, fmt.Sprintf(`name may not contain %q`, illegalContent)
}
}
return true, ""
}
// ValidatePathSegmentName validates the name can be safely encoded as a path segment
func ValidatePathSegmentName(name string, prefix bool) (bool, string) {
if prefix {
return IsValidPathSegmentPrefix(name)
} else {
return IsValidPathSegmentName(name)
}
}

293
vendor/k8s.io/kubernetes/pkg/api/validation/schema.go generated vendored Normal file
View file

@ -0,0 +1,293 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package validation
import (
"encoding/json"
"fmt"
"reflect"
"regexp"
"strings"
"github.com/emicklei/go-restful/swagger"
"github.com/golang/glog"
apiutil "k8s.io/kubernetes/pkg/api/util"
utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/yaml"
)
type InvalidTypeError struct {
ExpectedKind reflect.Kind
ObservedKind reflect.Kind
FieldName string
}
func (i *InvalidTypeError) Error() string {
return fmt.Sprintf("expected type %s, for field %s, got %s", i.ExpectedKind.String(), i.FieldName, i.ObservedKind.String())
}
func NewInvalidTypeError(expected reflect.Kind, observed reflect.Kind, fieldName string) error {
return &InvalidTypeError{expected, observed, fieldName}
}
// TypeNotFoundError is returned when specified type
// can not found in schema
type TypeNotFoundError string
func (tnfe TypeNotFoundError) Error() string {
return fmt.Sprintf("couldn't find type: %s", string(tnfe))
}
// Schema is an interface that knows how to validate an API object serialized to a byte array.
type Schema interface {
ValidateBytes(data []byte) error
}
type NullSchema struct{}
func (NullSchema) ValidateBytes(data []byte) error { return nil }
type SwaggerSchema struct {
api swagger.ApiDeclaration
}
func NewSwaggerSchemaFromBytes(data []byte) (Schema, error) {
schema := &SwaggerSchema{}
err := json.Unmarshal(data, &schema.api)
if err != nil {
return nil, err
}
return schema, nil
}
// validateList unpacks a list and validate every item in the list.
// It return nil if every item is ok.
// Otherwise it return an error list contain errors of every item.
func (s *SwaggerSchema) validateList(obj map[string]interface{}) []error {
allErrs := []error{}
items, exists := obj["items"]
if !exists {
return append(allErrs, fmt.Errorf("no items field in %#v", obj))
}
itemList, ok := items.([]interface{})
if !ok {
return append(allErrs, fmt.Errorf("items isn't a slice"))
}
for i, item := range itemList {
fields, ok := item.(map[string]interface{})
if !ok {
allErrs = append(allErrs, fmt.Errorf("items[%d] isn't a map[string]interface{}", i))
continue
}
groupVersion := fields["apiVersion"]
if groupVersion == nil {
allErrs = append(allErrs, fmt.Errorf("items[%d].apiVersion not set", i))
continue
}
itemVersion, ok := groupVersion.(string)
if !ok {
allErrs = append(allErrs, fmt.Errorf("items[%d].apiVersion isn't string type", i))
continue
}
if len(itemVersion) == 0 {
allErrs = append(allErrs, fmt.Errorf("items[%d].apiVersion is empty", i))
}
kind := fields["kind"]
if kind == nil {
allErrs = append(allErrs, fmt.Errorf("items[%d].kind not set", i))
continue
}
itemKind, ok := kind.(string)
if !ok {
allErrs = append(allErrs, fmt.Errorf("items[%d].kind isn't string type", i))
continue
}
if len(itemKind) == 0 {
allErrs = append(allErrs, fmt.Errorf("items[%d].kind is empty", i))
}
version := apiutil.GetVersion(itemVersion)
errs := s.ValidateObject(item, "", version+"."+itemKind)
if len(errs) >= 1 {
allErrs = append(allErrs, errs...)
}
}
return allErrs
}
func (s *SwaggerSchema) ValidateBytes(data []byte) error {
var obj interface{}
out, err := yaml.ToJSON(data)
if err != nil {
return err
}
data = out
if err := json.Unmarshal(data, &obj); err != nil {
return err
}
fields, ok := obj.(map[string]interface{})
if !ok {
return fmt.Errorf("error in unmarshaling data %s", string(data))
}
groupVersion := fields["apiVersion"]
if groupVersion == nil {
return fmt.Errorf("apiVersion not set")
}
if _, ok := groupVersion.(string); !ok {
return fmt.Errorf("apiVersion isn't string type")
}
kind := fields["kind"]
if kind == nil {
return fmt.Errorf("kind not set")
}
if _, ok := kind.(string); !ok {
return fmt.Errorf("kind isn't string type")
}
if strings.HasSuffix(kind.(string), "List") {
return utilerrors.NewAggregate(s.validateList(fields))
}
version := apiutil.GetVersion(groupVersion.(string))
allErrs := s.ValidateObject(obj, "", version+"."+kind.(string))
if len(allErrs) == 1 {
return allErrs[0]
}
return utilerrors.NewAggregate(allErrs)
}
func (s *SwaggerSchema) ValidateObject(obj interface{}, fieldName, typeName string) []error {
allErrs := []error{}
models := s.api.Models
model, ok := models.At(typeName)
if !ok {
return append(allErrs, TypeNotFoundError(typeName))
}
properties := model.Properties
if len(properties.List) == 0 {
// The object does not have any sub-fields.
return nil
}
fields, ok := obj.(map[string]interface{})
if !ok {
return append(allErrs, fmt.Errorf("field %s: expected object of type map[string]interface{}, but the actual type is %T", fieldName, obj))
}
if len(fieldName) > 0 {
fieldName = fieldName + "."
}
// handle required fields
for _, requiredKey := range model.Required {
if _, ok := fields[requiredKey]; !ok {
allErrs = append(allErrs, fmt.Errorf("field %s: is required", requiredKey))
}
}
for key, value := range fields {
details, ok := properties.At(key)
if !ok {
allErrs = append(allErrs, fmt.Errorf("found invalid field %s for %s", key, typeName))
continue
}
if details.Type == nil && details.Ref == nil {
allErrs = append(allErrs, fmt.Errorf("could not find the type of %s from object: %v", key, details))
}
var fieldType string
if details.Type != nil {
fieldType = *details.Type
} else {
fieldType = *details.Ref
}
if value == nil {
glog.V(2).Infof("Skipping nil field: %s", key)
continue
}
errs := s.validateField(value, fieldName+key, fieldType, &details)
if len(errs) > 0 {
allErrs = append(allErrs, errs...)
}
}
return allErrs
}
// This matches type name in the swagger spec, such as "v1.Binding".
var versionRegexp = regexp.MustCompile(`^v.+\..*`)
func (s *SwaggerSchema) validateField(value interface{}, fieldName, fieldType string, fieldDetails *swagger.ModelProperty) []error {
// TODO: caesarxuchao: because we have multiple group/versions and objects
// may reference objects in other group, the commented out way of checking
// if a filedType is a type defined by us is outdated. We use a hacky way
// for now.
// TODO: the type name in the swagger spec is something like "v1.Binding",
// and the "v1" is generated from the package name, not the groupVersion of
// the type. We need to fix go-restful to embed the group name in the type
// name, otherwise we couldn't handle identically named types in different
// groups correctly.
if versionRegexp.MatchString(fieldType) {
// if strings.HasPrefix(fieldType, apiVersion) {
return s.ValidateObject(value, fieldName, fieldType)
}
allErrs := []error{}
switch fieldType {
case "string":
// Be loose about what we accept for 'string' since we use IntOrString in a couple of places
_, isString := value.(string)
_, isNumber := value.(float64)
_, isInteger := value.(int)
if !isString && !isNumber && !isInteger {
return append(allErrs, NewInvalidTypeError(reflect.String, reflect.TypeOf(value).Kind(), fieldName))
}
case "array":
arr, ok := value.([]interface{})
if !ok {
return append(allErrs, NewInvalidTypeError(reflect.Array, reflect.TypeOf(value).Kind(), fieldName))
}
var arrType string
if fieldDetails.Items.Ref == nil && fieldDetails.Items.Type == nil {
return append(allErrs, NewInvalidTypeError(reflect.Array, reflect.TypeOf(value).Kind(), fieldName))
}
if fieldDetails.Items.Ref != nil {
arrType = *fieldDetails.Items.Ref
} else {
arrType = *fieldDetails.Items.Type
}
for ix := range arr {
errs := s.validateField(arr[ix], fmt.Sprintf("%s[%d]", fieldName, ix), arrType, nil)
if len(errs) > 0 {
allErrs = append(allErrs, errs...)
}
}
case "uint64":
case "int64":
case "integer":
_, isNumber := value.(float64)
_, isInteger := value.(int)
if !isNumber && !isInteger {
return append(allErrs, NewInvalidTypeError(reflect.Int, reflect.TypeOf(value).Kind(), fieldName))
}
case "float64":
if _, ok := value.(float64); !ok {
return append(allErrs, NewInvalidTypeError(reflect.Float64, reflect.TypeOf(value).Kind(), fieldName))
}
case "boolean":
if _, ok := value.(bool); !ok {
return append(allErrs, NewInvalidTypeError(reflect.Bool, reflect.TypeOf(value).Kind(), fieldName))
}
// API servers before release 1.3 produce swagger spec with `type: "any"` as the fallback type, while newer servers produce spec with `type: "object"`.
// We have both here so that kubectl can work with both old and new api servers.
case "object":
case "any":
default:
return append(allErrs, fmt.Errorf("unexpected type: %v", fieldType))
}
return allErrs
}

2893
vendor/k8s.io/kubernetes/pkg/api/validation/validation.go generated vendored Normal file

File diff suppressed because it is too large Load diff