Update dependencies

This commit is contained in:
Manuel de Brito Fontes 2017-10-06 17:33:32 -03:00
parent bf5616c65b
commit d6d374b28d
13962 changed files with 48226 additions and 3618880 deletions

222
vendor/k8s.io/api/Godeps/Godeps.json generated vendored
View file

@ -1,222 +0,0 @@
{
"ImportPath": "k8s.io/api",
"GoVersion": "go1.8",
"GodepVersion": "v79",
"Packages": [
"./..."
],
"Deps": [
{
"ImportPath": "github.com/PuerkitoBio/purell",
"Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4"
},
{
"ImportPath": "github.com/PuerkitoBio/urlesc",
"Rev": "5bd2802263f21d8788851d5305584c82a5c75d7e"
},
{
"ImportPath": "github.com/emicklei/go-restful",
"Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46"
},
{
"ImportPath": "github.com/emicklei/go-restful/log",
"Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46"
},
{
"ImportPath": "github.com/go-openapi/jsonpointer",
"Rev": "46af16f9f7b149af66e5d1bd010e3574dc06de98"
},
{
"ImportPath": "github.com/go-openapi/jsonreference",
"Rev": "13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272"
},
{
"ImportPath": "github.com/go-openapi/spec",
"Rev": "6aced65f8501fe1217321abf0749d354824ba2ff"
},
{
"ImportPath": "github.com/go-openapi/swag",
"Rev": "1d0bd113de87027671077d3c71eb3ac5d7dbba72"
},
{
"ImportPath": "github.com/gogo/protobuf/proto",
"Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7"
},
{
"ImportPath": "github.com/gogo/protobuf/sortkeys",
"Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7"
},
{
"ImportPath": "github.com/golang/glog",
"Rev": "44145f04b68cf362d9c4df2182967c2275eaefed"
},
{
"ImportPath": "github.com/google/gofuzz",
"Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c"
},
{
"ImportPath": "github.com/mailru/easyjson/buffer",
"Rev": "d5b7844b561a7bc640052f1b935f7b800330d7e0"
},
{
"ImportPath": "github.com/mailru/easyjson/jlexer",
"Rev": "d5b7844b561a7bc640052f1b935f7b800330d7e0"
},
{
"ImportPath": "github.com/mailru/easyjson/jwriter",
"Rev": "d5b7844b561a7bc640052f1b935f7b800330d7e0"
},
{
"ImportPath": "github.com/spf13/pflag",
"Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7"
},
{
"ImportPath": "golang.org/x/net/http2",
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/idna",
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/text/cases",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal/tag",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/language",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/runes",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/secure/precis",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/transform",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/width",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "gopkg.in/inf.v0",
"Rev": "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/conversion",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/fields",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/labels",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/selection",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/types",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/net",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/wait",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/watch",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
"Rev": "3b05bbfa0a45413bfa184edbf9af617e277962fb"
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/common",
"Rev": "868f2f29720b192240e18284659231b440f9cda5"
}
]
}

5
vendor/k8s.io/api/Godeps/Readme generated vendored
View file

@ -1,5 +0,0 @@
This directory tree is generated automatically by godep.
Please do not edit.
See https://github.com/tools/godep for more information.

View file

@ -1,42 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"generated.pb.go",
"register.go",
"types.go",
"types_swagger_doc_generated.go",
"zz_generated.deepcopy.go",
],
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/k8s.io/api/authentication/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "go_default_library_protos",
srcs = ["generated.proto"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View file

@ -1,21 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:deepcopy-gen=package,register
// +k8s:openapi-gen=false
// +groupName=admission.k8s.io
package v1alpha1 // import "k8s.io/api/admission/v1alpha1"

File diff suppressed because it is too large Load diff

View file

@ -1,95 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
syntax = 'proto2';
package k8s.io.api.admission.v1alpha1;
import "k8s.io/api/authentication/v1/generated.proto";
import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto";
import "k8s.io/apimachinery/pkg/runtime/generated.proto";
import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
import "k8s.io/apimachinery/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "v1alpha1";
// AdmissionReview describes an admission request.
message AdmissionReview {
// Spec describes the attributes for the admission request.
// Since this admission controller is non-mutating the webhook should avoid setting this in its response to avoid the
// cost of deserializing it.
// +optional
optional AdmissionReviewSpec spec = 1;
// Status is filled in by the webhook and indicates whether the admission request should be permitted.
// +optional
optional AdmissionReviewStatus status = 2;
}
// AdmissionReviewSpec describes the admission.Attributes for the admission request.
message AdmissionReviewSpec {
// Kind is the type of object being manipulated. For example: Pod
optional k8s.io.apimachinery.pkg.apis.meta.v1.GroupVersionKind kind = 1;
// Object is the object from the incoming request prior to default values being applied
optional k8s.io.apimachinery.pkg.runtime.RawExtension object = 2;
// OldObject is the existing object. Only populated for UPDATE requests.
// +optional
optional k8s.io.apimachinery.pkg.runtime.RawExtension oldObject = 3;
// Operation is the operation being performed
optional string operation = 4;
// Name is the name of the object as presented in the request. On a CREATE operation, the client may omit name and
// rely on the server to generate the name. If that is the case, this method will return the empty string.
// +optional
optional string name = 5;
// Namespace is the namespace associated with the request (if any).
// +optional
optional string namespace = 6;
// Resource is the name of the resource being requested. This is not the kind. For example: pods
optional k8s.io.apimachinery.pkg.apis.meta.v1.GroupVersionResource resource = 7;
// SubResource is the name of the subresource being requested. This is a different resource, scoped to the parent
// resource, but it may have a different kind. For instance, /pods has the resource "pods" and the kind "Pod", while
// /pods/foo/status has the resource "pods", the sub resource "status", and the kind "Pod" (because status operates on
// pods). The binding resource for a pod though may be /pods/foo/binding, which has resource "pods", subresource
// "binding", and kind "Binding".
// +optional
optional string subResource = 8;
// UserInfo is information about the requesting user
optional k8s.io.api.authentication.v1.UserInfo userInfo = 9;
}
// AdmissionReviewStatus describes the status of the admission request.
message AdmissionReviewStatus {
// Allowed indicates whether or not the admission request was permitted.
optional bool allowed = 1;
// Result contains extra details into why an admission request was denied.
// This field IS NOT consulted in any way if "Allowed" is "true".
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.Status status = 2;
}

View file

@ -1,51 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName is the group name for this API.
const GroupName = "admission.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
localSchemeBuilder = &SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&AdmissionReview{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View file

@ -1,90 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
authenticationv1 "k8s.io/api/authentication/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// AdmissionReview describes an admission request.
type AdmissionReview struct {
metav1.TypeMeta `json:",inline"`
// Spec describes the attributes for the admission request.
// Since this admission controller is non-mutating the webhook should avoid setting this in its response to avoid the
// cost of deserializing it.
// +optional
Spec AdmissionReviewSpec `json:"spec,omitempty" protobuf:"bytes,1,opt,name=spec"`
// Status is filled in by the webhook and indicates whether the admission request should be permitted.
// +optional
Status AdmissionReviewStatus `json:"status,omitempty" protobuf:"bytes,2,opt,name=status"`
}
// AdmissionReviewSpec describes the admission.Attributes for the admission request.
type AdmissionReviewSpec struct {
// Kind is the type of object being manipulated. For example: Pod
Kind metav1.GroupVersionKind `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"`
// Object is the object from the incoming request prior to default values being applied
Object runtime.RawExtension `json:"object,omitempty" protobuf:"bytes,2,opt,name=object"`
// OldObject is the existing object. Only populated for UPDATE requests.
// +optional
OldObject runtime.RawExtension `json:"oldObject,omitempty" protobuf:"bytes,3,opt,name=oldObject"`
// Operation is the operation being performed
Operation Operation `json:"operation,omitempty" protobuf:"bytes,4,opt,name=operation"`
// Name is the name of the object as presented in the request. On a CREATE operation, the client may omit name and
// rely on the server to generate the name. If that is the case, this method will return the empty string.
// +optional
Name string `json:"name,omitempty" protobuf:"bytes,5,opt,name=name"`
// Namespace is the namespace associated with the request (if any).
// +optional
Namespace string `json:"namespace,omitempty" protobuf:"bytes,6,opt,name=namespace"`
// Resource is the name of the resource being requested. This is not the kind. For example: pods
Resource metav1.GroupVersionResource `json:"resource,omitempty" protobuf:"bytes,7,opt,name=resource"`
// SubResource is the name of the subresource being requested. This is a different resource, scoped to the parent
// resource, but it may have a different kind. For instance, /pods has the resource "pods" and the kind "Pod", while
// /pods/foo/status has the resource "pods", the sub resource "status", and the kind "Pod" (because status operates on
// pods). The binding resource for a pod though may be /pods/foo/binding, which has resource "pods", subresource
// "binding", and kind "Binding".
// +optional
SubResource string `json:"subResource,omitempty" protobuf:"bytes,8,opt,name=subResource"`
// UserInfo is information about the requesting user
UserInfo authenticationv1.UserInfo `json:"userInfo,omitempty" protobuf:"bytes,9,opt,name=userInfo"`
}
// AdmissionReviewStatus describes the status of the admission request.
type AdmissionReviewStatus struct {
// Allowed indicates whether or not the admission request was permitted.
Allowed bool `json:"allowed" protobuf:"varint,1,opt,name=allowed"`
// Result contains extra details into why an admission request was denied.
// This field IS NOT consulted in any way if "Allowed" is "true".
// +optional
Result *metav1.Status `json:"status,omitempty" protobuf:"bytes,2,opt,name=status"`
}
// Operation is the type of resource operation being checked for admission control
type Operation string
// Operation constants
const (
Create Operation = "CREATE"
Update Operation = "UPDATE"
Delete Operation = "DELETE"
Connect Operation = "CONNECT"
)

View file

@ -1,67 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
// 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_AdmissionReview = map[string]string{
"": "AdmissionReview describes an admission request.",
"spec": "Spec describes the attributes for the admission request. Since this admission controller is non-mutating the webhook should avoid setting this in its response to avoid the cost of deserializing it.",
"status": "Status is filled in by the webhook and indicates whether the admission request should be permitted.",
}
func (AdmissionReview) SwaggerDoc() map[string]string {
return map_AdmissionReview
}
var map_AdmissionReviewSpec = map[string]string{
"": "AdmissionReviewSpec describes the admission.Attributes for the admission request.",
"kind": "Kind is the type of object being manipulated. For example: Pod",
"object": "Object is the object from the incoming request prior to default values being applied",
"oldObject": "OldObject is the existing object. Only populated for UPDATE requests.",
"operation": "Operation is the operation being performed",
"name": "Name is the name of the object as presented in the request. On a CREATE operation, the client may omit name and rely on the server to generate the name. If that is the case, this method will return the empty string.",
"namespace": "Namespace is the namespace associated with the request (if any).",
"resource": "Resource is the name of the resource being requested. This is not the kind. For example: pods",
"subResource": "SubResource is the name of the subresource being requested. This is a different resource, scoped to the parent resource, but it may have a different kind. For instance, /pods has the resource \"pods\" and the kind \"Pod\", while /pods/foo/status has the resource \"pods\", the sub resource \"status\", and the kind \"Pod\" (because status operates on pods). The binding resource for a pod though may be /pods/foo/binding, which has resource \"pods\", subresource \"binding\", and kind \"Binding\".",
"userInfo": "UserInfo is information about the requesting user",
}
func (AdmissionReviewSpec) SwaggerDoc() map[string]string {
return map_AdmissionReviewSpec
}
var map_AdmissionReviewStatus = map[string]string{
"": "AdmissionReviewStatus describes the status of the admission request.",
"allowed": "Allowed indicates whether or not the admission request was permitted.",
"status": "Result contains extra details into why an admission request was denied. This field IS NOT consulted in any way if \"Allowed\" is \"true\".",
}
func (AdmissionReviewStatus) SwaggerDoc() map[string]string {
return map_AdmissionReviewStatus
}
// AUTO-GENERATED FUNCTIONS END HERE

View file

@ -1,127 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package v1alpha1
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
reflect "reflect"
)
func init() {
SchemeBuilder.Register(RegisterDeepCopies)
}
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
// to allow building arbitrary schemes.
//
// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented.
func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*AdmissionReview).DeepCopyInto(out.(*AdmissionReview))
return nil
}, InType: reflect.TypeOf(&AdmissionReview{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*AdmissionReviewSpec).DeepCopyInto(out.(*AdmissionReviewSpec))
return nil
}, InType: reflect.TypeOf(&AdmissionReviewSpec{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*AdmissionReviewStatus).DeepCopyInto(out.(*AdmissionReviewStatus))
return nil
}, InType: reflect.TypeOf(&AdmissionReviewStatus{})},
)
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AdmissionReview) DeepCopyInto(out *AdmissionReview) {
*out = *in
out.TypeMeta = in.TypeMeta
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdmissionReview.
func (in *AdmissionReview) DeepCopy() *AdmissionReview {
if in == nil {
return nil
}
out := new(AdmissionReview)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AdmissionReview) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AdmissionReviewSpec) DeepCopyInto(out *AdmissionReviewSpec) {
*out = *in
out.Kind = in.Kind
in.Object.DeepCopyInto(&out.Object)
in.OldObject.DeepCopyInto(&out.OldObject)
out.Resource = in.Resource
in.UserInfo.DeepCopyInto(&out.UserInfo)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdmissionReviewSpec.
func (in *AdmissionReviewSpec) DeepCopy() *AdmissionReviewSpec {
if in == nil {
return nil
}
out := new(AdmissionReviewSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AdmissionReviewStatus) DeepCopyInto(out *AdmissionReviewStatus) {
*out = *in
if in.Result != nil {
in, out := &in.Result, &out.Result
if *in == nil {
*out = nil
} else {
*out = new(v1.Status)
(*in).DeepCopyInto(*out)
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdmissionReviewStatus.
func (in *AdmissionReviewStatus) DeepCopy() *AdmissionReviewStatus {
if in == nil {
return nil
}
out := new(AdmissionReviewStatus)
in.DeepCopyInto(out)
return out
}

View file

@ -1,4 +0,0 @@
reviewers:
- deads2k
- mbohlool
- jianhuiz

View file

@ -1,45 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"generated.pb.go",
"register.go",
"types.go",
"types_swagger_doc_generated.go",
"zz_generated.deepcopy.go",
],
deps = [
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/gogo/protobuf/sortkeys:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
filegroup(
name = "go_default_library_protos",
srcs = ["generated.proto"],
visibility = ["//visibility:public"],
)

View file

@ -1,21 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:deepcopy-gen=package,register
// +k8s:openapi-gen=true
// +groupName=imagepolicy.k8s.io
package v1alpha1 // import "k8s.io/api/imagepolicy/v1alpha1"

File diff suppressed because it is too large Load diff

View file

@ -1,80 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
syntax = 'proto2';
package k8s.io.api.imagepolicy.v1alpha1;
import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto";
import "k8s.io/apimachinery/pkg/runtime/generated.proto";
import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
import "k8s.io/apimachinery/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "v1alpha1";
// ImageReview checks if the set of images in a pod are allowed.
message ImageReview {
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
// Spec holds information about the pod being evaluated
optional ImageReviewSpec spec = 2;
// Status is filled in by the backend and indicates whether the pod should be allowed.
// +optional
optional ImageReviewStatus status = 3;
}
// ImageReviewContainerSpec is a description of a container within the pod creation request.
message ImageReviewContainerSpec {
// This can be in the form image:tag or image@SHA:012345679abcdef.
// +optional
optional string image = 1;
}
// ImageReviewSpec is a description of the pod creation request.
message ImageReviewSpec {
// Containers is a list of a subset of the information in each container of the Pod being created.
// +optional
repeated ImageReviewContainerSpec containers = 1;
// Annotations is a list of key-value pairs extracted from the Pod's annotations.
// It only includes keys which match the pattern `*.image-policy.k8s.io/*`.
// It is up to each webhook backend to determine how to interpret these annotations, if at all.
// +optional
map<string, string> annotations = 2;
// Namespace is the namespace the pod is being created in.
// +optional
optional string namespace = 3;
}
// ImageReviewStatus is the result of the token authentication request.
message ImageReviewStatus {
// Allowed indicates that all images were allowed to be run.
optional bool allowed = 1;
// Reason should be empty unless Allowed is false in which case it
// may contain a short description of what is wrong. Kubernetes
// may truncate excessively long errors when displaying to the user.
// +optional
optional string reason = 2;
}

View file

@ -1,51 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName is the group name for this API.
const GroupName = "imagepolicy.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
localSchemeBuilder = &SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&ImageReview{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View file

@ -1,74 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
// +genclient:nonNamespaced
// +genclient:noVerbs
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ImageReview checks if the set of images in a pod are allowed.
type ImageReview struct {
metav1.TypeMeta `json:",inline"`
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec holds information about the pod being evaluated
Spec ImageReviewSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
// Status is filled in by the backend and indicates whether the pod should be allowed.
// +optional
Status ImageReviewStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// ImageReviewSpec is a description of the pod creation request.
type ImageReviewSpec struct {
// Containers is a list of a subset of the information in each container of the Pod being created.
// +optional
Containers []ImageReviewContainerSpec `json:"containers,omitempty" protobuf:"bytes,1,rep,name=containers"`
// Annotations is a list of key-value pairs extracted from the Pod's annotations.
// It only includes keys which match the pattern `*.image-policy.k8s.io/*`.
// It is up to each webhook backend to determine how to interpret these annotations, if at all.
// +optional
Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,2,rep,name=annotations"`
// Namespace is the namespace the pod is being created in.
// +optional
Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"`
}
// ImageReviewContainerSpec is a description of a container within the pod creation request.
type ImageReviewContainerSpec struct {
// This can be in the form image:tag or image@SHA:012345679abcdef.
// +optional
Image string `json:"image,omitempty" protobuf:"bytes,1,opt,name=image"`
// In future, we may add command line overrides, exec health check command lines, and so on.
}
// ImageReviewStatus is the result of the token authentication request.
type ImageReviewStatus struct {
// Allowed indicates that all images were allowed to be run.
Allowed bool `json:"allowed" protobuf:"varint,1,opt,name=allowed"`
// Reason should be empty unless Allowed is false in which case it
// may contain a short description of what is wrong. Kubernetes
// may truncate excessively long errors when displaying to the user.
// +optional
Reason string `json:"reason,omitempty" protobuf:"bytes,2,opt,name=reason"`
}

View file

@ -1,70 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
// 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_ImageReview = map[string]string{
"": "ImageReview checks if the set of images in a pod are allowed.",
"spec": "Spec holds information about the pod being evaluated",
"status": "Status is filled in by the backend and indicates whether the pod should be allowed.",
}
func (ImageReview) SwaggerDoc() map[string]string {
return map_ImageReview
}
var map_ImageReviewContainerSpec = map[string]string{
"": "ImageReviewContainerSpec is a description of a container within the pod creation request.",
"image": "This can be in the form image:tag or image@SHA:012345679abcdef.",
}
func (ImageReviewContainerSpec) SwaggerDoc() map[string]string {
return map_ImageReviewContainerSpec
}
var map_ImageReviewSpec = map[string]string{
"": "ImageReviewSpec is a description of the pod creation request.",
"containers": "Containers is a list of a subset of the information in each container of the Pod being created.",
"annotations": "Annotations is a list of key-value pairs extracted from the Pod's annotations. It only includes keys which match the pattern `*.image-policy.k8s.io/*`. It is up to each webhook backend to determine how to interpret these annotations, if at all.",
"namespace": "Namespace is the namespace the pod is being created in.",
}
func (ImageReviewSpec) SwaggerDoc() map[string]string {
return map_ImageReviewSpec
}
var map_ImageReviewStatus = map[string]string{
"": "ImageReviewStatus is the result of the token authentication request.",
"allowed": "Allowed indicates that all images were allowed to be run.",
"reason": "Reason should be empty unless Allowed is false in which case it may contain a short description of what is wrong. Kubernetes may truncate excessively long errors when displaying to the user.",
}
func (ImageReviewStatus) SwaggerDoc() map[string]string {
return map_ImageReviewStatus
}
// AUTO-GENERATED FUNCTIONS END HERE

View file

@ -1,145 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package v1alpha1
import (
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
reflect "reflect"
)
func init() {
SchemeBuilder.Register(RegisterDeepCopies)
}
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
// to allow building arbitrary schemes.
//
// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented.
func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ImageReview).DeepCopyInto(out.(*ImageReview))
return nil
}, InType: reflect.TypeOf(&ImageReview{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ImageReviewContainerSpec).DeepCopyInto(out.(*ImageReviewContainerSpec))
return nil
}, InType: reflect.TypeOf(&ImageReviewContainerSpec{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ImageReviewSpec).DeepCopyInto(out.(*ImageReviewSpec))
return nil
}, InType: reflect.TypeOf(&ImageReviewSpec{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ImageReviewStatus).DeepCopyInto(out.(*ImageReviewStatus))
return nil
}, InType: reflect.TypeOf(&ImageReviewStatus{})},
)
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageReview) DeepCopyInto(out *ImageReview) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
out.Status = in.Status
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageReview.
func (in *ImageReview) DeepCopy() *ImageReview {
if in == nil {
return nil
}
out := new(ImageReview)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ImageReview) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageReviewContainerSpec) DeepCopyInto(out *ImageReviewContainerSpec) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageReviewContainerSpec.
func (in *ImageReviewContainerSpec) DeepCopy() *ImageReviewContainerSpec {
if in == nil {
return nil
}
out := new(ImageReviewContainerSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageReviewSpec) DeepCopyInto(out *ImageReviewSpec) {
*out = *in
if in.Containers != nil {
in, out := &in.Containers, &out.Containers
*out = make([]ImageReviewContainerSpec, len(*in))
copy(*out, *in)
}
if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageReviewSpec.
func (in *ImageReviewSpec) DeepCopy() *ImageReviewSpec {
if in == nil {
return nil
}
out := new(ImageReviewSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageReviewStatus) DeepCopyInto(out *ImageReviewStatus) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ImageReviewStatus.
func (in *ImageReviewStatus) DeepCopy() *ImageReviewStatus {
if in == nil {
return nil
}
out := new(ImageReviewStatus)
in.DeepCopyInto(out)
return out
}

20
vendor/k8s.io/apiextensions-apiserver/README.md generated vendored Normal file
View file

@ -0,0 +1,20 @@
# apiextensions-apiserver
Implements: https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/thirdpartyresources.md
It provides an API for registering `CustomResourceDefinitions`.
## Purpose
This API server provides the implementation for `CustomResourceDefinitions` which is included as
delegate server inside of `kube-apiserver`.
## Compatibility
HEAD of this repo will match HEAD of k8s.io/apiserver, k8s.io/apimachinery, and k8s.io/client-go.
## Where does it come from?
`apiextensions-apiserver` is synced from https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apiextensions-apiserver.
Code changes are made in that location, merged into `k8s.io/kubernetes` and later synced here.

View file

@ -1,222 +0,0 @@
{
"ImportPath": "k8s.io/apimachinery",
"GoVersion": "go1.8",
"GodepVersion": "v79",
"Packages": [
"./..."
],
"Deps": [
{
"ImportPath": "github.com/PuerkitoBio/purell",
"Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4"
},
{
"ImportPath": "github.com/PuerkitoBio/urlesc",
"Rev": "5bd2802263f21d8788851d5305584c82a5c75d7e"
},
{
"ImportPath": "github.com/davecgh/go-spew/spew",
"Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8"
},
{
"ImportPath": "github.com/docker/spdystream",
"Rev": "449fdfce4d962303d702fec724ef0ad181c92528"
},
{
"ImportPath": "github.com/docker/spdystream/spdy",
"Rev": "449fdfce4d962303d702fec724ef0ad181c92528"
},
{
"ImportPath": "github.com/elazarl/goproxy",
"Rev": "c4fc26588b6ef8af07a191fcb6476387bdd46711"
},
{
"ImportPath": "github.com/emicklei/go-restful",
"Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46"
},
{
"ImportPath": "github.com/emicklei/go-restful/log",
"Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46"
},
{
"ImportPath": "github.com/evanphx/json-patch",
"Rev": "944e07253867aacae43c04b2e6a239005443f33a"
},
{
"ImportPath": "github.com/ghodss/yaml",
"Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee"
},
{
"ImportPath": "github.com/go-openapi/jsonpointer",
"Rev": "46af16f9f7b149af66e5d1bd010e3574dc06de98"
},
{
"ImportPath": "github.com/go-openapi/jsonreference",
"Rev": "13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272"
},
{
"ImportPath": "github.com/go-openapi/spec",
"Rev": "6aced65f8501fe1217321abf0749d354824ba2ff"
},
{
"ImportPath": "github.com/go-openapi/swag",
"Rev": "1d0bd113de87027671077d3c71eb3ac5d7dbba72"
},
{
"ImportPath": "github.com/gogo/protobuf/proto",
"Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7"
},
{
"ImportPath": "github.com/gogo/protobuf/sortkeys",
"Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7"
},
{
"ImportPath": "github.com/golang/glog",
"Rev": "44145f04b68cf362d9c4df2182967c2275eaefed"
},
{
"ImportPath": "github.com/golang/groupcache/lru",
"Rev": "02826c3e79038b59d737d3b1c0a1d937f71a4433"
},
{
"ImportPath": "github.com/golang/protobuf/proto",
"Rev": "4bd1920723d7b7c925de087aa32e2187708897f7"
},
{
"ImportPath": "github.com/google/gofuzz",
"Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c"
},
{
"ImportPath": "github.com/hashicorp/golang-lru",
"Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4"
},
{
"ImportPath": "github.com/hashicorp/golang-lru/simplelru",
"Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4"
},
{
"ImportPath": "github.com/json-iterator/go",
"Rev": "36b14963da70d11297d313183d7e6388c8510e1e"
},
{
"ImportPath": "github.com/mailru/easyjson/buffer",
"Rev": "d5b7844b561a7bc640052f1b935f7b800330d7e0"
},
{
"ImportPath": "github.com/mailru/easyjson/jlexer",
"Rev": "d5b7844b561a7bc640052f1b935f7b800330d7e0"
},
{
"ImportPath": "github.com/mailru/easyjson/jwriter",
"Rev": "d5b7844b561a7bc640052f1b935f7b800330d7e0"
},
{
"ImportPath": "github.com/mxk/go-flowrate/flowrate",
"Rev": "cca7078d478f8520f85629ad7c68962d31ed7682"
},
{
"ImportPath": "github.com/pborman/uuid",
"Rev": "ca53cad383cad2479bbba7f7a1a05797ec1386e4"
},
{
"ImportPath": "github.com/pmezard/go-difflib/difflib",
"Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d"
},
{
"ImportPath": "github.com/spf13/pflag",
"Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7"
},
{
"ImportPath": "github.com/stretchr/testify/assert",
"Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a"
},
{
"ImportPath": "github.com/stretchr/testify/require",
"Rev": "f6abca593680b2315d2075e0f5e2a9751e3f431a"
},
{
"ImportPath": "golang.org/x/net/html",
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/html/atom",
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/http2",
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/idna",
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/websocket",
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/text/cases",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/internal/tag",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/language",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/runes",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/secure/bidirule",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/secure/precis",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/transform",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/unicode/bidi",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/unicode/norm",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "golang.org/x/text/width",
"Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01"
},
{
"ImportPath": "gopkg.in/inf.v0",
"Rev": "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4"
},
{
"ImportPath": "gopkg.in/yaml.v2",
"Rev": "53feefa2559fb8dfa8d81baad31be332c97d6c77"
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/common",
"Rev": "868f2f29720b192240e18284659231b440f9cda5"
}
]
}

View file

@ -1,5 +0,0 @@
This directory tree is generated automatically by godep.
Please do not edit.
See https://github.com/tools/godep for more information.

View file

@ -1,66 +0,0 @@
#!/bin/bash
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# overall flow
# 1. make a clean gopath
# 2. godep restore based on k8s.io/kuberentes provided manifest
# 3. go get anything unlisted. This handles deps from k8s.io/*
# 4. remove old vendoring data
# 5. vendor packages we need
# 6. remove anything vendored from k8s.io/* from vendor, but not manifest.
# This allows go get to work and still be able to flatten dependencies.
# 6. copy new vendored packages and save them
set -o errexit
set -o nounset
set -o pipefail
goPath=$(mktemp -d "${TMPDIR:-/tmp/}$(basename 0).XXXXXXXXXXXX")
echo ${goPath}
export GOPATH=${goPath}
mkdir -p ${goPath}/src/k8s.io/apimachinery
cp -R . ${goPath}/src/k8s.io/apimachinery
pushd ${goPath}/src/k8s.io/apimachinery
rm -rf vendor || true
# restore what we have in our new manifest that we've sync
godep restore
# the manifest doesn't include any levels of k8s.io dependencies so load them using the go get
# assume you sync all the repos at the same time, the leves you get will be correct
go get -d ./... || true
# save the new levels of dependencies
rm -rf vendor || true
rm -rf Godeps || true
godep save ./...
popd
# remove the vendor dir we have and move the one we just made
rm -rf vendor || true
rm -rf Godeps || true
git rm -rf vendor || true
git rm -rf Godeps || true
mv ${goPath}/src/k8s.io/apimachinery/vendor .
mv ${goPath}/src/k8s.io/apimachinery/Godeps .
git add vendor
git add Godeps
git commit -m "sync: resync vendor folder"

View file

@ -1,65 +0,0 @@
#!/bin/bash
# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# overall flow
# 1. fetch the current level of k8s.io/kubernetes
# 2. check out the k8s.io/kubernetes HEAD into a separate branch
# 3. rewrite the history on that branch to *only* include staging/src/k8s.io/apimachinery
# 4. locate all commits between the last time we sync'ed and now
# 5. switch back to the starting branch
# 6. for each commit, cherry-pick it (which will keep authorship) into current branch
# 7. update metadata files indicating which commits we've sync'ed to
set -e
ROOT=$(dirname "${BASH_SOURCE}")/..
dir=$(mktemp -d "${TMPDIR:-/tmp/}$(basename 0).XXXXXXXXXXXX")
git remote add upstream-kube git@github.com:kubernetes/kubernetes.git || true
git fetch upstream-kube
currBranch=$(git rev-parse --abbrev-ref HEAD)
previousKubeSHA=$(cat kubernetes-sha)
previousBranchSHA=$(cat filter-branch-sha)
git branch -D kube-sync || true
git checkout upstream-kube/master -b kube-sync
git reset --hard upstream-kube/master
newKubeSHA=$(git log --oneline --format='%H' kube-sync -1)
# this command rewrite git history to *only* include staging/src/k8s.io/apimachinery
git filter-branch -f --subdirectory-filter staging/src/k8s.io/apimachinery HEAD
newBranchSHA=$(git log --oneline --format='%H' kube-sync -1)
git log --no-merges --format='%H' --reverse ${previousBranchSHA}..HEAD > ${dir}/commits
git checkout ${currBranch}
while read commitSHA; do
echo "working ${commitSHA}"
git cherry-pick ${commitSHA}
done <${dir}/commits
# update the vendored godeps
${ROOT}/hack/godep-deps.sh
# track the k8s.io/kubernetes commit SHA so we can always determine which level of kube this repo matches
# track the filtered branch commit SHA so that we can determine which commits need to be picked
echo ${newKubeSHA} > kubernetes-sha
echo ${newBranchSHA} > filter-branch-sha
git commit -m "sync(k8s.io/kubernetes): ${newKubeSHA}" -- kubernetes-sha filter-branch-sha

View file

@ -1,34 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["codec.go"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/api/testing/fuzzer:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/api/testing/roundtrip:all-srcs",
],
tags = ["automanaged"],
)

View file

@ -1,86 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testing
import (
"fmt"
"mime"
"os"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
)
var (
testCodecMediaType string
testStorageCodecMediaType string
)
// TestCodec returns the codec for the API version to test against, as set by the
// KUBE_TEST_API_TYPE env var.
func TestCodec(codecs runtimeserializer.CodecFactory, gvs ...schema.GroupVersion) runtime.Codec {
if len(testCodecMediaType) != 0 {
serializerInfo, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), testCodecMediaType)
if !ok {
panic(fmt.Sprintf("no serializer for %s", testCodecMediaType))
}
return codecs.CodecForVersions(serializerInfo.Serializer, codecs.UniversalDeserializer(), schema.GroupVersions(gvs), nil)
}
return codecs.LegacyCodec(gvs...)
}
// TestStorageCodec returns the codec for the API version to test against used in storage, as set by the
// KUBE_TEST_API_STORAGE_TYPE env var.
func TestStorageCodec(codecs runtimeserializer.CodecFactory, gvs ...schema.GroupVersion) runtime.Codec {
if len(testStorageCodecMediaType) != 0 {
serializerInfo, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), testStorageCodecMediaType)
if !ok {
panic(fmt.Sprintf("no serializer for %s", testStorageCodecMediaType))
}
// etcd2 only supports string data - we must wrap any result before returning
// TODO: remove for etcd3 / make parameterizable
serializer := serializerInfo.Serializer
if !serializerInfo.EncodesAsText {
serializer = runtime.NewBase64Serializer(serializer, serializer)
}
decoder := recognizer.NewDecoder(serializer, codecs.UniversalDeserializer())
return codecs.CodecForVersions(serializer, decoder, schema.GroupVersions(gvs), nil)
}
return codecs.LegacyCodec(gvs...)
}
func init() {
var err error
if apiMediaType := os.Getenv("KUBE_TEST_API_TYPE"); len(apiMediaType) > 0 {
testCodecMediaType, _, err = mime.ParseMediaType(apiMediaType)
if err != nil {
panic(err)
}
}
if storageMediaType := os.Getenv("KUBE_TEST_API_STORAGE_TYPE"); len(storageMediaType) > 0 {
testStorageCodecMediaType, _, err = mime.ParseMediaType(storageMediaType)
if err != nil {
panic(err)
}
}
}

View file

@ -1,38 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["valuefuzz_test.go"],
library = ":go_default_library",
)
go_library(
name = "go_default_library",
srcs = [
"fuzzer.go",
"valuefuzz.go",
],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,52 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fuzzer
import (
"math/rand"
"github.com/google/gofuzz"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
)
// FuzzerFuncs returns a list of func(*SomeType, c fuzz.Continue) functions.
type FuzzerFuncs func(codecs runtimeserializer.CodecFactory) []interface{}
// FuzzerFor can randomly populate api objects that are destined for version.
func FuzzerFor(funcs FuzzerFuncs, src rand.Source, codecs runtimeserializer.CodecFactory) *fuzz.Fuzzer {
f := fuzz.New().NilChance(.5).NumElements(0, 1)
if src != nil {
f.RandSource(src)
}
f.Funcs(funcs(codecs)...)
return f
}
// MergeFuzzerFuncs will merge the given funcLists, overriding early funcs with later ones if there first
// argument has the same type.
func MergeFuzzerFuncs(funcs ...FuzzerFuncs) FuzzerFuncs {
return FuzzerFuncs(func(codecs runtimeserializer.CodecFactory) []interface{} {
result := []interface{}{}
for _, f := range funcs {
if f != nil {
result = append(result, f(codecs)...)
}
}
return result
})
}

View file

@ -1,86 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fuzzer
import (
"reflect"
)
// ValueFuzz recursively changes all basic type values in an object. Any kind of references will not
// be touch, i.e. the addresses of slices, maps, pointers will stay unchanged.
func ValueFuzz(obj interface{}) {
valueFuzz(reflect.ValueOf(obj))
}
func valueFuzz(obj reflect.Value) {
switch obj.Kind() {
case reflect.Array:
for i := 0; i < obj.Len(); i++ {
valueFuzz(obj.Index(i))
}
case reflect.Slice:
if obj.IsNil() {
// TODO: set non-nil value
} else {
for i := 0; i < obj.Len(); i++ {
valueFuzz(obj.Index(i))
}
}
case reflect.Interface, reflect.Ptr:
if obj.IsNil() {
// TODO: set non-nil value
} else {
valueFuzz(obj.Elem())
}
case reflect.Struct:
for i, n := 0, obj.NumField(); i < n; i++ {
valueFuzz(obj.Field(i))
}
case reflect.Map:
if obj.IsNil() {
// TODO: set non-nil value
} else {
for _, k := range obj.MapKeys() {
// map values are not addressable. We need a copy.
v := obj.MapIndex(k)
copy := reflect.New(v.Type())
copy.Elem().Set(v)
valueFuzz(copy.Elem())
obj.SetMapIndex(k, copy.Elem())
}
// TODO: set some new value
}
case reflect.Func: // ignore, we don't have function types in our API
default:
if !obj.CanSet() {
return
}
switch obj.Kind() {
case reflect.String:
obj.SetString(obj.String() + "x")
case reflect.Bool:
obj.SetBool(!obj.Bool())
case reflect.Float32, reflect.Float64:
obj.SetFloat(obj.Float()*2.0 + 1.0)
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
obj.SetInt(obj.Int() + 1)
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
obj.SetUint(obj.Uint() + 1)
default:
}
}
}

View file

@ -1,73 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fuzzer
import "testing"
func TestValueFuzz(t *testing.T) {
type (
Y struct {
I int
B bool
F float32
U uint
}
X struct {
Ptr *X
Y Y
Map map[string]int
Slice []int
}
)
x := X{
Ptr: &X{},
Map: map[string]int{"foo": 42},
Slice: []int{1, 2, 3},
}
p := x.Ptr
m := x.Map
s := x.Slice
ValueFuzz(x)
if x.Ptr.Y.I == 0 {
t.Errorf("x.Ptr.Y.I should have changed")
}
if x.Map["foo"] == 42 {
t.Errorf("x.Map[foo] should have changed")
}
if x.Slice[0] == 1 {
t.Errorf("x.Slice[0] should have changed")
}
if x.Ptr != p {
t.Errorf("x.Ptr changed")
}
m["foo"] = 7
if x.Map["foo"] != m["foo"] {
t.Errorf("x.Map changed")
}
s[0] = 7
if x.Slice[0] != s[0] {
t.Errorf("x.Slice changed")
}
}

View file

@ -1,44 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["roundtrip.go"],
deps = [
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/golang/protobuf/proto:go_default_library",
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,409 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package roundtrip
import (
"bytes"
"encoding/hex"
"math/rand"
"reflect"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/golang/protobuf/proto"
"github.com/google/gofuzz"
flag "github.com/spf13/pflag"
apiequality "k8s.io/apimachinery/pkg/api/equality"
apimeta "k8s.io/apimachinery/pkg/api/meta"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
metafuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/sets"
)
type InstallFunc func(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme)
// RoundTripTestForAPIGroup is convenient to call from your install package to make sure that a "bare" install of your group provides
// enough information to round trip
func RoundTripTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzingFuncs fuzzer.FuzzerFuncs) {
groupFactoryRegistry := make(announced.APIGroupFactoryRegistry)
registry := registered.NewOrDie("")
scheme := runtime.NewScheme()
installFn(groupFactoryRegistry, registry, scheme)
RoundTripTestForScheme(t, scheme, fuzzingFuncs)
}
// RoundTripTestForScheme is convenient to call if you already have a scheme and want to make sure that its well-formed
func RoundTripTestForScheme(t *testing.T, scheme *runtime.Scheme, fuzzingFuncs fuzzer.FuzzerFuncs) {
codecFactory := runtimeserializer.NewCodecFactory(scheme)
f := fuzzer.FuzzerFor(
fuzzer.MergeFuzzerFuncs(metafuzzer.Funcs, fuzzingFuncs),
rand.NewSource(rand.Int63()),
codecFactory,
)
RoundTripTypesWithoutProtobuf(t, scheme, codecFactory, f, nil)
}
// RoundTripProtobufTestForAPIGroup is convenient to call from your install package to make sure that a "bare" install of your group provides
// enough information to round trip
func RoundTripProtobufTestForAPIGroup(t *testing.T, installFn InstallFunc, fuzzingFuncs fuzzer.FuzzerFuncs) {
groupFactoryRegistry := make(announced.APIGroupFactoryRegistry)
registry := registered.NewOrDie("")
scheme := runtime.NewScheme()
installFn(groupFactoryRegistry, registry, scheme)
RoundTripProtobufTestForScheme(t, scheme, fuzzingFuncs)
}
// RoundTripProtobufTestForScheme is convenient to call if you already have a scheme and want to make sure that its well-formed
func RoundTripProtobufTestForScheme(t *testing.T, scheme *runtime.Scheme, fuzzingFuncs fuzzer.FuzzerFuncs) {
codecFactory := runtimeserializer.NewCodecFactory(scheme)
fuzzer := fuzzer.FuzzerFor(
fuzzer.MergeFuzzerFuncs(metafuzzer.Funcs, fuzzingFuncs),
rand.NewSource(rand.Int63()),
codecFactory,
)
RoundTripTypes(t, scheme, codecFactory, fuzzer, nil)
}
var FuzzIters = flag.Int("fuzz-iters", 20, "How many fuzzing iterations to do.")
// globalNonRoundTrippableTypes are kinds that are effectively reserved across all GroupVersions
// They don't roundtrip
var globalNonRoundTrippableTypes = sets.NewString(
"ExportOptions",
"GetOptions",
// WatchEvent does not include kind and version and can only be deserialized
// implicitly (if the caller expects the specific object). The watch call defines
// the schema by content type, rather than via kind/version included in each
// object.
"WatchEvent",
// ListOptions is now part of the meta group
"ListOptions",
// Delete options is only read in metav1
"DeleteOptions",
)
// RoundTripTypesWithoutProtobuf applies the round-trip test to all round-trippable Kinds
// in the scheme. It will skip all the GroupVersionKinds in the skip list.
func RoundTripTypesWithoutProtobuf(t *testing.T, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
roundTripTypes(t, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, true)
}
func RoundTripTypes(t *testing.T, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
roundTripTypes(t, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, false)
}
func roundTripTypes(t *testing.T, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool, skipProtobuf bool) {
for _, group := range groupsFromScheme(scheme) {
t.Logf("starting group %q", group)
internalVersion := schema.GroupVersion{Group: group, Version: runtime.APIVersionInternal}
internalKindToGoType := scheme.KnownTypes(internalVersion)
for kind := range internalKindToGoType {
if globalNonRoundTrippableTypes.Has(kind) {
continue
}
internalGVK := internalVersion.WithKind(kind)
roundTripSpecificKind(t, internalGVK, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, skipProtobuf)
}
t.Logf("finished group %q", group)
}
}
func RoundTripSpecificKindWithoutProtobuf(t *testing.T, gvk schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
roundTripSpecificKind(t, gvk, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, true)
}
func RoundTripSpecificKind(t *testing.T, gvk schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool) {
roundTripSpecificKind(t, gvk, scheme, codecFactory, fuzzer, nonRoundTrippableTypes, false)
}
func roundTripSpecificKind(t *testing.T, gvk schema.GroupVersionKind, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, nonRoundTrippableTypes map[schema.GroupVersionKind]bool, skipProtobuf bool) {
if nonRoundTrippableTypes[gvk] {
t.Logf("skipping %v", gvk)
return
}
t.Logf("round tripping %v", gvk)
// Try a few times, since runTest uses random values.
for i := 0; i < *FuzzIters; i++ {
if gvk.Version == runtime.APIVersionInternal {
roundTripToAllExternalVersions(t, scheme, codecFactory, fuzzer, gvk, nonRoundTrippableTypes, skipProtobuf)
} else {
roundTripOfExternalType(t, scheme, codecFactory, fuzzer, gvk, skipProtobuf)
}
if t.Failed() {
break
}
}
}
// fuzzInternalObject fuzzes an arbitrary runtime object using the appropriate
// fuzzer registered with the apitesting package.
func fuzzInternalObject(t *testing.T, fuzzer *fuzz.Fuzzer, object runtime.Object) runtime.Object {
fuzzer.Fuzz(object)
j, err := apimeta.TypeAccessor(object)
if err != nil {
t.Fatalf("Unexpected error %v for %#v", err, object)
}
j.SetKind("")
j.SetAPIVersion("")
return object
}
func groupsFromScheme(scheme *runtime.Scheme) []string {
ret := sets.String{}
for gvk := range scheme.AllKnownTypes() {
ret.Insert(gvk.Group)
}
return ret.List()
}
func roundTripToAllExternalVersions(t *testing.T, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, internalGVK schema.GroupVersionKind, nonRoundTrippableTypes map[schema.GroupVersionKind]bool, skipProtobuf bool) {
object, err := scheme.New(internalGVK)
if err != nil {
t.Fatalf("Couldn't make a %v? %v", internalGVK, err)
}
if _, err := apimeta.TypeAccessor(object); err != nil {
t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableInternalTypes: %v", internalGVK, err)
}
fuzzInternalObject(t, fuzzer, object)
// find all potential serializations in the scheme.
// TODO fix this up to handle kinds that cross registered with different names.
for externalGVK, externalGoType := range scheme.AllKnownTypes() {
if externalGVK.Version == runtime.APIVersionInternal {
continue
}
if externalGVK.GroupKind() != internalGVK.GroupKind() {
continue
}
if nonRoundTrippableTypes[externalGVK] {
t.Logf("\tskipping %v %v", externalGVK, externalGoType)
continue
}
t.Logf("\tround tripping to %v %v", externalGVK, externalGoType)
roundTrip(t, scheme, apitesting.TestCodec(codecFactory, externalGVK.GroupVersion()), object)
// TODO remove this hack after we're past the intermediate steps
if !skipProtobuf && externalGVK.Group != "kubeadm.k8s.io" {
s := protobuf.NewSerializer(scheme, scheme, "application/arbitrary.content.type")
protobufCodec := codecFactory.CodecForVersions(s, s, externalGVK.GroupVersion(), nil)
roundTrip(t, scheme, protobufCodec, object)
}
}
}
func roundTripOfExternalType(t *testing.T, scheme *runtime.Scheme, codecFactory runtimeserializer.CodecFactory, fuzzer *fuzz.Fuzzer, externalGVK schema.GroupVersionKind, skipProtobuf bool) {
object, err := scheme.New(externalGVK)
if err != nil {
t.Fatalf("Couldn't make a %v? %v", externalGVK, err)
}
typeAcc, err := apimeta.TypeAccessor(object)
if err != nil {
t.Fatalf("%q is not a TypeMeta and cannot be tested - add it to nonRoundTrippableInternalTypes: %v", externalGVK, err)
}
fuzzInternalObject(t, fuzzer, object)
externalGoType := reflect.TypeOf(object).PkgPath()
t.Logf("\tround tripping external type %v %v", externalGVK, externalGoType)
typeAcc.SetKind(externalGVK.Kind)
typeAcc.SetAPIVersion(externalGVK.GroupVersion().String())
roundTrip(t, scheme, json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false), object)
// TODO remove this hack after we're past the intermediate steps
if !skipProtobuf {
roundTrip(t, scheme, protobuf.NewSerializer(scheme, scheme, "application/protobuf"), object)
}
}
// roundTrip applies a single round-trip test to the given runtime object
// using the given codec. The round-trip test ensures that an object can be
// deep-copied, converted, marshaled and back without loss of data.
//
// For internal types this means
//
// internal -> external -> json/protobuf -> external -> internal.
//
// For external types this means
//
// external -> json/protobuf -> external.
func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object runtime.Object) {
printer := spew.ConfigState{DisableMethods: true}
original := object
// deep copy the original object
object = object.DeepCopyObject()
name := reflect.TypeOf(object).Elem().Name()
if !apiequality.Semantic.DeepEqual(original, object) {
t.Errorf("%v: DeepCopy altered the object, diff: %v", name, diff.ObjectReflectDiff(original, object))
t.Errorf("%s", spew.Sdump(original))
t.Errorf("%s", spew.Sdump(object))
return
}
// catch deepcopy errors early
if !apiequality.Semantic.DeepEqual(original, object) {
t.Errorf("%v: DeepCopy did not lead to equal object, diff: %v", name, diff.ObjectReflectDiff(original, object))
return
}
// encode (serialize) the deep copy using the provided codec
data, err := runtime.Encode(codec, object)
if err != nil {
if runtime.IsNotRegisteredError(err) {
t.Logf("%v: not registered: %v (%s)", name, err, printer.Sprintf("%#v", object))
} else {
t.Errorf("%v: %v (%s)", name, err, printer.Sprintf("%#v", object))
}
return
}
// ensure that the deep copy is equal to the original; neither the deep
// copy or conversion should alter the object
// TODO eliminate this global
if !apiequality.Semantic.DeepEqual(original, object) {
t.Errorf("%v: encode altered the object, diff: %v", name, diff.ObjectReflectDiff(original, object))
return
}
// encode (serialize) a second time to verify that it was not varying
secondData, err := runtime.Encode(codec, object)
if err != nil {
if runtime.IsNotRegisteredError(err) {
t.Logf("%v: not registered: %v (%s)", name, err, printer.Sprintf("%#v", object))
} else {
t.Errorf("%v: %v (%s)", name, err, printer.Sprintf("%#v", object))
}
return
}
// serialization to the wire must be stable to ensure that we don't write twice to the DB
// when the object hasn't changed.
if !bytes.Equal(data, secondData) {
t.Errorf("%v: serialization is not stable: %s", name, printer.Sprintf("%#v", object))
}
// decode (deserialize) the encoded data back into an object
obj2, err := runtime.Decode(codec, data)
if err != nil {
t.Errorf("%v: %v\nCodec: %#v\nData: %s\nSource: %#v", name, err, codec, dataAsString(data), printer.Sprintf("%#v", object))
panic("failed")
}
// ensure that the object produced from decoding the encoded data is equal
// to the original object
if !apiequality.Semantic.DeepEqual(original, obj2) {
t.Errorf("%v: diff: %v\nCodec: %#v\nSource:\n\n%#v\n\nEncoded:\n\n%s\n\nFinal:\n\n%#v", name, diff.ObjectReflectDiff(original, obj2), codec, printer.Sprintf("%#v", original), dataAsString(data), printer.Sprintf("%#v", obj2))
return
}
// decode the encoded data into a new object (instead of letting the codec
// create a new object)
obj3 := reflect.New(reflect.TypeOf(object).Elem()).Interface().(runtime.Object)
if err := runtime.DecodeInto(codec, data, obj3); err != nil {
t.Errorf("%v: %v", name, err)
return
}
// special case for kinds which are internal and external at the same time (many in meta.k8s.io are). For those
// runtime.DecodeInto above will return the external variant and set the APIVersion and kind, while the input
// object might be internal. Hence, we clear those values for obj3 for that case to correctly compare.
intAndExt, err := internalAndExternalKind(scheme, object)
if err != nil {
t.Errorf("%v: %v", name, err)
return
}
if intAndExt {
typeAcc, err := apimeta.TypeAccessor(object)
if err != nil {
t.Fatalf("%v: error accessing TypeMeta: %v", name, err)
}
if len(typeAcc.GetAPIVersion()) == 0 {
typeAcc, err := apimeta.TypeAccessor(obj3)
if err != nil {
t.Fatalf("%v: error accessing TypeMeta: %v", name, err)
}
typeAcc.SetAPIVersion("")
typeAcc.SetKind("")
}
}
// ensure that the new runtime object is equal to the original after being
// decoded into
if !apiequality.Semantic.DeepEqual(object, obj3) {
t.Errorf("%v: diff: %v\nCodec: %#v", name, diff.ObjectReflectDiff(object, obj3), codec)
return
}
// do structure-preserving fuzzing of the deep-copied object. If it shares anything with the original,
// the deep-copy was actually only a shallow copy. Then original and obj3 will be different after fuzzing.
// NOTE: we use the encoding+decoding here as an alternative, guaranteed deep-copy to compare against.
fuzzer.ValueFuzz(object)
if !apiequality.Semantic.DeepEqual(original, obj3) {
t.Errorf("%v: fuzzing a copy altered the original, diff: %v", name, diff.ObjectReflectDiff(original, obj3))
return
}
}
func internalAndExternalKind(scheme *runtime.Scheme, object runtime.Object) (bool, error) {
kinds, _, err := scheme.ObjectKinds(object)
if err != nil {
return false, err
}
internal, external := false, false
for _, k := range kinds {
if k.Version == runtime.APIVersionInternal {
internal = true
} else {
external = true
}
}
return internal && external, nil
}
// dataAsString returns the given byte array as a string; handles detecting
// protocol buffers.
func dataAsString(data []byte) string {
dataString := string(data)
if !strings.HasPrefix(dataString, "{") {
dataString = "\n" + hex.Dump(data)
proto.NewBuffer(make([]byte, 0, 1024)).DebugPrint("decoded object", data)
}
return dataString
}

View file

@ -1,31 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["name_test.go"],
library = ":go_default_library",
)
go_library(
name = "go_default_library",
srcs = ["name.go"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,68 +0,0 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package path
import (
"fmt"
"strings"
)
// NameMayNotBe specifies strings that cannot be used as names specified as path segments (like the REST API or etcd store)
var NameMayNotBe = []string{".", ".."}
// NameMayNotContain specifies substrings that cannot be used in names specified as path segments (like the REST API or etcd store)
var NameMayNotContain = []string{"/", "%"}
// IsValidPathSegmentName validates the name can be safely encoded as a path segment
func IsValidPathSegmentName(name string) []string {
for _, illegalName := range NameMayNotBe {
if name == illegalName {
return []string{fmt.Sprintf(`may not be '%s'`, illegalName)}
}
}
var errors []string
for _, illegalContent := range NameMayNotContain {
if strings.Contains(name, illegalContent) {
errors = append(errors, fmt.Sprintf(`may not contain '%s'`, illegalContent))
}
}
return errors
}
// IsValidPathSegmentPrefix validates the name can be used as a prefix for a name which will be encoded as a path segment
// It does not check for exact matches with disallowed names, since an arbitrary suffix might make the name valid
func IsValidPathSegmentPrefix(name string) []string {
var errors []string
for _, illegalContent := range NameMayNotContain {
if strings.Contains(name, illegalContent) {
errors = append(errors, fmt.Sprintf(`may not contain '%s'`, illegalContent))
}
}
return errors
}
// ValidatePathSegmentName validates the name can be safely encoded as a path segment
func ValidatePathSegmentName(name string, prefix bool) []string {
if prefix {
return IsValidPathSegmentPrefix(name)
} else {
return IsValidPathSegmentName(name)
}
}

View file

@ -1,168 +0,0 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package path
import (
"strings"
"testing"
)
func TestValidatePathSegmentName(t *testing.T) {
testcases := map[string]struct {
Name string
Prefix bool
ExpectedMsg string
}{
"empty": {
Name: "",
Prefix: false,
ExpectedMsg: "",
},
"empty,prefix": {
Name: "",
Prefix: true,
ExpectedMsg: "",
},
"valid": {
Name: "foo.bar.baz",
Prefix: false,
ExpectedMsg: "",
},
"valid,prefix": {
Name: "foo.bar.baz",
Prefix: true,
ExpectedMsg: "",
},
// Make sure mixed case, non DNS subdomain characters are tolerated
"valid complex": {
Name: "sha256:ABCDEF012345@ABCDEF012345",
Prefix: false,
ExpectedMsg: "",
},
// Make sure non-ascii characters are tolerated
"valid extended charset": {
Name: "Iñtërnâtiônàlizætiøn",
Prefix: false,
ExpectedMsg: "",
},
"dot": {
Name: ".",
Prefix: false,
ExpectedMsg: ".",
},
"dot leading": {
Name: ".test",
Prefix: false,
ExpectedMsg: "",
},
"dot,prefix": {
Name: ".",
Prefix: true,
ExpectedMsg: "",
},
"dot dot": {
Name: "..",
Prefix: false,
ExpectedMsg: "..",
},
"dot dot leading": {
Name: "..test",
Prefix: false,
ExpectedMsg: "",
},
"dot dot,prefix": {
Name: "..",
Prefix: true,
ExpectedMsg: "",
},
"slash": {
Name: "foo/bar",
Prefix: false,
ExpectedMsg: "/",
},
"slash,prefix": {
Name: "foo/bar",
Prefix: true,
ExpectedMsg: "/",
},
"percent": {
Name: "foo%bar",
Prefix: false,
ExpectedMsg: "%",
},
"percent,prefix": {
Name: "foo%bar",
Prefix: true,
ExpectedMsg: "%",
},
}
for k, tc := range testcases {
msgs := ValidatePathSegmentName(tc.Name, tc.Prefix)
if len(tc.ExpectedMsg) == 0 && len(msgs) > 0 {
t.Errorf("%s: expected no message, got %v", k, msgs)
}
if len(tc.ExpectedMsg) > 0 && len(msgs) == 0 {
t.Errorf("%s: expected error message, got none", k)
}
if len(tc.ExpectedMsg) > 0 && !strings.Contains(msgs[0], tc.ExpectedMsg) {
t.Errorf("%s: expected message containing %q, got %v", k, tc.ExpectedMsg, msgs[0])
}
}
}
func TestValidateWithMultiErrors(t *testing.T) {
testcases := map[string]struct {
Name string
Prefix bool
ExpectedMsg []string
}{
"slash,percent": {
Name: "foo//bar%",
Prefix: false,
ExpectedMsg: []string{"may not contain '/'", "may not contain '%'"},
},
"slash,percent,prefix": {
Name: "foo//bar%",
Prefix: true,
ExpectedMsg: []string{"may not contain '/'", "may not contain '%'"},
},
}
for k, tc := range testcases {
msgs := ValidatePathSegmentName(tc.Name, tc.Prefix)
if len(tc.ExpectedMsg) == 0 && len(msgs) > 0 {
t.Errorf("%s: expected no message, got %v", k, msgs)
}
if len(tc.ExpectedMsg) > 0 && len(msgs) == 0 {
t.Errorf("%s: expected error message, got none", k)
}
if len(tc.ExpectedMsg) > 0 {
for i := 0; i < len(tc.ExpectedMsg); i++ {
if msgs[i] != tc.ExpectedMsg[i] {
t.Errorf("%s: expected message containing %q, got %v", k, tc.ExpectedMsg[i], msgs[i])
}
}
}
}
}

View file

@ -1,35 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["fuzzer.go"],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1alpha1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,171 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fuzzer
import (
"fmt"
"strconv"
"github.com/google/gofuzz"
"k8s.io/apimachinery/pkg/api/resource"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1alpha1 "k8s.io/apimachinery/pkg/apis/meta/v1alpha1"
"k8s.io/apimachinery/pkg/runtime"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/types"
)
func genericFuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(q *resource.Quantity, c fuzz.Continue) {
*q = *resource.NewQuantity(c.Int63n(1000), resource.DecimalExponent)
},
func(j *int, c fuzz.Continue) {
*j = int(c.Int31())
},
func(j **int, c fuzz.Continue) {
if c.RandBool() {
i := int(c.Int31())
*j = &i
} else {
*j = nil
}
},
func(j *runtime.TypeMeta, c fuzz.Continue) {
// We have to customize the randomization of TypeMetas because their
// APIVersion and Kind must remain blank in memory.
j.APIVersion = ""
j.Kind = ""
},
func(j *runtime.Object, c fuzz.Continue) {
// TODO: uncomment when round trip starts from a versioned object
if true { //c.RandBool() {
*j = &runtime.Unknown{
// We do not set TypeMeta here because it is not carried through a round trip
Raw: []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`),
ContentType: runtime.ContentTypeJSON,
}
} else {
types := []runtime.Object{&metav1.Status{}, &metav1.APIGroup{}}
t := types[c.Rand.Intn(len(types))]
c.Fuzz(t)
*j = t
}
},
func(r *runtime.RawExtension, c fuzz.Continue) {
// Pick an arbitrary type and fuzz it
types := []runtime.Object{&metav1.Status{}, &metav1.APIGroup{}}
obj := types[c.Rand.Intn(len(types))]
c.Fuzz(obj)
// Find a codec for converting the object to raw bytes. This is necessary for the
// api version and kind to be correctly set be serialization.
var codec = apitesting.TestCodec(codecs, metav1.SchemeGroupVersion)
// Convert the object to raw bytes
bytes, err := runtime.Encode(codec, obj)
if err != nil {
panic(fmt.Sprintf("Failed to encode object: %v", err))
}
// strip trailing newlines which do not survive roundtrips
for len(bytes) >= 1 && bytes[len(bytes)-1] == 10 {
bytes = bytes[:len(bytes)-1]
}
// Set the bytes field on the RawExtension
r.Raw = bytes
},
}
}
func v1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(j *metav1.TypeMeta, c fuzz.Continue) {
// We have to customize the randomization of TypeMetas because their
// APIVersion and Kind must remain blank in memory.
j.APIVersion = ""
j.Kind = ""
},
func(j *metav1.ObjectMeta, c fuzz.Continue) {
j.Name = c.RandString()
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
j.SelfLink = c.RandString()
j.UID = types.UID(c.RandString())
j.GenerateName = c.RandString()
var sec, nsec int64
c.Fuzz(&sec)
c.Fuzz(&nsec)
j.CreationTimestamp = metav1.Unix(sec, nsec).Rfc3339Copy()
},
func(j *metav1.ListMeta, c fuzz.Continue) {
j.ResourceVersion = strconv.FormatUint(c.RandUint64(), 10)
j.SelfLink = c.RandString()
},
}
}
func v1alpha1FuzzerFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(r *metav1alpha1.TableRow, c fuzz.Continue) {
c.Fuzz(&r.Object)
c.Fuzz(&r.Conditions)
if len(r.Conditions) == 0 {
r.Conditions = nil
}
n := c.Intn(10)
if n > 0 {
r.Cells = make([]interface{}, n)
}
for i := range r.Cells {
t := c.Intn(6)
switch t {
case 0:
r.Cells[i] = c.RandString()
case 1:
r.Cells[i] = c.Uint64()
case 2:
r.Cells[i] = c.RandBool()
case 3:
x := map[string]interface{}{}
for j := c.Intn(10) + 1; j >= 0; j-- {
x[c.RandString()] = c.RandString()
}
r.Cells[i] = x
case 4:
x := make([]interface{}, c.Intn(10))
for i := range x {
x[i] = c.Uint64()
}
r.Cells[i] = x
default:
r.Cells[i] = nil
}
}
},
}
}
var Funcs = fuzzer.MergeFuzzerFuncs(
genericFuzzerFuncs,
v1FuzzerFuncs,
v1alpha1FuzzerFuncs,
)

View file

@ -1,40 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"register.go",
"types.go",
"zz_generated.deepcopy.go",
],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/fuzzer:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/install:all-srcs",
"//staging/src/k8s.io/apimachinery/pkg/apis/testapigroup/v1:all-srcs",
],
tags = ["automanaged"],
)

View file

@ -1,22 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:deepcopy-gen=package,register
// +groupName=testapigroup.apimachinery.k8s.io
//
// package testapigroup contains an testapigroup API used to demonstrate how to create api groups. Moreover, this is
// used within tests.
package testapigroup // import "k8s.io/apimachinery/pkg/apis/testapigroup"

View file

@ -1,33 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["fuzzer.go"],
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing/fuzzer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,99 +0,0 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fuzzer
import (
"fmt"
"github.com/google/gofuzz"
apitesting "k8s.io/apimachinery/pkg/api/testing"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
"k8s.io/apimachinery/pkg/apis/testapigroup"
"k8s.io/apimachinery/pkg/apis/testapigroup/v1"
"k8s.io/apimachinery/pkg/runtime"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
)
// overrideMetaFuncs override some generic fuzzer funcs from k8s.io/apimachinery in order to have more realistic
// values in a Kubernetes context.
func overrideMetaFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(j *runtime.Object, c fuzz.Continue) {
// TODO: uncomment when round trip starts from a versioned object
if true { //c.RandBool() {
*j = &runtime.Unknown{
// We do not set TypeMeta here because it is not carried through a round trip
Raw: []byte(`{"apiVersion":"unknown.group/unknown","kind":"Something","someKey":"someValue"}`),
ContentType: runtime.ContentTypeJSON,
}
} else {
types := []runtime.Object{&testapigroup.Carp{}}
t := types[c.Rand.Intn(len(types))]
c.Fuzz(t)
*j = t
}
},
func(r *runtime.RawExtension, c fuzz.Continue) {
// Pick an arbitrary type and fuzz it
types := []runtime.Object{&testapigroup.Carp{}}
obj := types[c.Rand.Intn(len(types))]
c.Fuzz(obj)
// Convert the object to raw bytes
bytes, err := runtime.Encode(apitesting.TestCodec(codecs, v1.SchemeGroupVersion), obj)
if err != nil {
panic(fmt.Sprintf("Failed to encode object: %v", err))
}
// Set the bytes field on the RawExtension
r.Raw = bytes
},
}
}
func testapigroupFuncs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{
func(s *testapigroup.CarpSpec, c fuzz.Continue) {
c.FuzzNoCustom(s)
// has a default value
ttl := int64(30)
if c.RandBool() {
ttl = int64(c.Uint32())
}
s.TerminationGracePeriodSeconds = &ttl
if s.SchedulerName == "" {
s.SchedulerName = "default-scheduler"
}
},
func(j *testapigroup.CarpPhase, c fuzz.Continue) {
statuses := []testapigroup.CarpPhase{"Pending", "Running", "Succeeded", "Failed", "Unknown"}
*j = statuses[c.Rand.Intn(len(statuses))]
},
func(rp *testapigroup.RestartPolicy, c fuzz.Continue) {
policies := []testapigroup.RestartPolicy{"Always", "Never", "OnFailure"}
*rp = policies[c.Rand.Intn(len(policies))]
},
}
}
// Funcs returns the fuzzer functions for the testapigroup.
var Funcs = fuzzer.MergeFuzzerFuncs(
overrideMetaFuncs,
testapigroupFuncs,
)

View file

@ -1,42 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = ["install.go"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apimachinery/announced:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apimachinery/registered:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["roundtrip_test.go"],
library = ":go_default_library",
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/testing/roundtrip:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup/fuzzer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,43 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package install installs the certificates API group, making it available as
// an option to all of the API encoding/decoding machinery.
package install
import (
"k8s.io/apimachinery/pkg/apimachinery/announced"
"k8s.io/apimachinery/pkg/apimachinery/registered"
"k8s.io/apimachinery/pkg/apis/testapigroup"
"k8s.io/apimachinery/pkg/apis/testapigroup/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// Install registers the API group and adds types to a scheme
func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *registered.APIRegistrationManager, scheme *runtime.Scheme) {
if err := announced.NewGroupMetaFactory(
&announced.GroupMetaFactoryArgs{
GroupName: testapigroup.GroupName,
VersionPreferenceOrder: []string{v1.SchemeGroupVersion.Version},
AddInternalObjectsToScheme: testapigroup.AddToScheme,
},
announced.VersionToSchemeFunc{
v1.SchemeGroupVersion.Version: v1.AddToScheme,
},
).Announce(groupFactoryRegistry).RegisterAndEnable(registry, scheme); err != nil {
panic(err)
}
}

View file

@ -1,28 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package install
import (
"testing"
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
testapigroupfuzzer "k8s.io/apimachinery/pkg/apis/testapigroup/fuzzer"
)
func TestRoundTrip(t *testing.T) {
roundtrip.RoundTripTestForAPIGroup(t, Install, testapigroupfuzzer.Funcs)
}

View file

@ -1,51 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testapigroup
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
AddToScheme = SchemeBuilder.AddToScheme
)
// GroupName is the group name use in this package
const GroupName = "testapigroup.apimachinery.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Carp{},
)
return nil
}

View file

@ -1,138 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testapigroup
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type (
ConditionStatus string
CarpConditionType string
CarpPhase string
RestartPolicy string
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Carp is a collection of containers, used as either input (create, update) or as output (list, get).
type Carp struct {
metav1.TypeMeta
// +optional
metav1.ObjectMeta
// Spec defines the behavior of a carp.
// +optional
Spec CarpSpec
// Status represents the current information about a carp. This data may not be up
// to date.
// +optional
Status CarpStatus
}
// CarpStatus represents information about the status of a carp. Status may trail the actual
// state of a system.
type CarpStatus struct {
// +optional
Phase CarpPhase
// +optional
Conditions []CarpCondition
// A human readable message indicating details about why the carp is in this state.
// +optional
Message string
// A brief CamelCase message indicating details about why the carp is in this state. e.g. 'OutOfDisk'
// +optional
Reason string
// +optional
HostIP string
// +optional
CarpIP string
// Date and time at which the object was acknowledged by the Kubelet.
// This is before the Kubelet pulled the container image(s) for the carp.
// +optional
StartTime *metav1.Time
}
type CarpCondition struct {
Type CarpConditionType
Status ConditionStatus
// +optional
LastProbeTime metav1.Time
// +optional
LastTransitionTime metav1.Time
// +optional
Reason string
// +optional
Message string
}
// CarpSpec is a description of a carp
type CarpSpec struct {
// +optional
RestartPolicy RestartPolicy
// Optional duration in seconds the carp needs to terminate gracefully. May be decreased in delete request.
// Value must be non-negative integer. The value zero indicates delete immediately.
// If this value is nil, the default grace period will be used instead.
// The grace period is the duration in seconds after the processes running in the carp are sent
// a termination signal and the time when the processes are forcibly halted with a kill signal.
// Set this value longer than the expected cleanup time for your process.
// +optional
TerminationGracePeriodSeconds *int64
// Optional duration in seconds relative to the StartTime that the carp may be active on a node
// before the system actively tries to terminate the carp; value must be positive integer
// +optional
ActiveDeadlineSeconds *int64
// NodeSelector is a selector which must be true for the carp to fit on a node
// +optional
NodeSelector map[string]string
// ServiceAccountName is the name of the ServiceAccount to use to run this carp
// The carp will be allowed to use secrets referenced by the ServiceAccount
ServiceAccountName string
// NodeName is a request to schedule this carp onto a specific node. If it is non-empty,
// the scheduler simply schedules this carp onto that node, assuming that it fits resource
// requirements.
// +optional
NodeName string
// Specifies the hostname of the Carp.
// If not specified, the carp's hostname will be set to a system-defined value.
// +optional
Hostname string
// If specified, the fully qualified Carp hostname will be "<hostname>.<subdomain>.<carp namespace>.svc.<cluster domain>".
// If not specified, the carp will not have a domainname at all.
// +optional
Subdomain string
// If specified, the carp will be dispatched by specified scheduler.
// If not specified, the carp will be dispatched by default scheduler.
// +optional
SchedulerName string
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CarpList is a list of Carps.
type CarpList struct {
metav1.TypeMeta
// +optional
metav1.ListMeta
Items []Carp
}

View file

@ -1,50 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"conversion.go",
"defaults.go",
"doc.go",
"generated.pb.go",
"register.go",
"types.go",
"types_swagger_doc_generated.go",
"zz_generated.conversion.go",
"zz_generated.deepcopy.go",
"zz_generated.defaults.go",
],
deps = [
"//vendor/github.com/gogo/protobuf/proto:go_default_library",
"//vendor/github.com/gogo/protobuf/sortkeys:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
filegroup(
name = "go_default_library_protos",
srcs = ["generated.proto"],
visibility = ["//visibility:public"],
)

View file

@ -1,26 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
"k8s.io/apimachinery/pkg/runtime"
)
func addConversionFuncs(scheme *runtime.Scheme) error {
// Add non-generated conversion functions here. Currently there are none.
return nil
}

View file

@ -1,26 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
"k8s.io/apimachinery/pkg/runtime"
)
func addDefaultingFuncs(scheme *runtime.Scheme) error {
// return RegisterDefaults(scheme)
return nil
}

View file

@ -1,23 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/apimachinery/pkg/apis/testapigroup
// +k8s:openapi-gen=false
// +k8s:defaulter-gen=TypeMeta
// +groupName=testapigroup.apimachinery.k8s.io
package v1 // import "k8s.io/apimachinery/pkg/apis/testapigroup/v1"

File diff suppressed because it is too large Load diff

View file

@ -1,212 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
syntax = 'proto2';
package k8s.io.apimachinery.pkg.apis.testapigroup.v1;
import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto";
import "k8s.io/apimachinery/pkg/runtime/generated.proto";
import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
import "k8s.io/apimachinery/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated".
option go_package = "v1";
// Carp is a collection of containers, used as either input (create, update) or as output (list, get).
message Carp {
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
// Specification of the desired behavior of the carp.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
// +optional
optional CarpSpec spec = 2;
// Most recently observed status of the carp.
// This data may not be up to date.
// Populated by the system.
// Read-only.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
// +optional
optional CarpStatus status = 3;
}
message CarpCondition {
// Type is the type of the condition.
// Currently only Ready.
// More info: http://kubernetes.io/docs/user-guide/carp-states#carp-conditions
optional string type = 1;
// Status is the status of the condition.
// Can be True, False, Unknown.
// More info: http://kubernetes.io/docs/user-guide/carp-states#carp-conditions
optional string status = 2;
// Last time we probed the condition.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastProbeTime = 3;
// Last time the condition transitioned from one status to another.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 4;
// Unique, one-word, CamelCase reason for the condition's last transition.
// +optional
optional string reason = 5;
// Human-readable message indicating details about last transition.
// +optional
optional string message = 6;
}
// CarpList is a list of Carps.
message CarpList {
// Standard list metadata.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
// List of carps.
// More info: http://kubernetes.io/docs/user-guide/carps
repeated Carp items = 2;
}
// CarpSpec is a description of a carp
message CarpSpec {
// Restart policy for all containers within the carp.
// One of Always, OnFailure, Never.
// Default to Always.
// More info: http://kubernetes.io/docs/user-guide/carp-states#restartpolicy
// +optional
optional string restartPolicy = 3;
// Optional duration in seconds the carp needs to terminate gracefully. May be decreased in delete request.
// Value must be non-negative integer. The value zero indicates delete immediately.
// If this value is nil, the default grace period will be used instead.
// The grace period is the duration in seconds after the processes running in the carp are sent
// a termination signal and the time when the processes are forcibly halted with a kill signal.
// Set this value longer than the expected cleanup time for your process.
// Defaults to 30 seconds.
// +optional
optional int64 terminationGracePeriodSeconds = 4;
// Optional duration in seconds the carp may be active on the node relative to
// StartTime before the system will actively try to mark it failed and kill associated containers.
// Value must be a positive integer.
// +optional
optional int64 activeDeadlineSeconds = 5;
// NodeSelector is a selector which must be true for the carp to fit on a node.
// Selector which must match a node's labels for the carp to be scheduled on that node.
// More info: http://kubernetes.io/docs/user-guide/node-selection/README
// +optional
map<string, string> nodeSelector = 7;
// ServiceAccountName is the name of the ServiceAccount to use to run this carp.
// More info: http://releases.k8s.io/HEAD/docs/design/service_accounts.md
// +optional
optional string serviceAccountName = 8;
// DeprecatedServiceAccount is a depreciated alias for ServiceAccountName.
// Deprecated: Use serviceAccountName instead.
// +k8s:conversion-gen=false
// +optional
optional string serviceAccount = 9;
// NodeName is a request to schedule this carp onto a specific node. If it is non-empty,
// the scheduler simply schedules this carp onto that node, assuming that it fits resource
// requirements.
// +optional
optional string nodeName = 10;
// Host networking requested for this carp. Use the host's network namespace.
// If this option is set, the ports that will be used must be specified.
// Default to false.
// +k8s:conversion-gen=false
// +optional
optional bool hostNetwork = 11;
// Use the host's pid namespace.
// Optional: Default to false.
// +k8s:conversion-gen=false
// +optional
optional bool hostPID = 12;
// Use the host's ipc namespace.
// Optional: Default to false.
// +k8s:conversion-gen=false
// +optional
optional bool hostIPC = 13;
// Specifies the hostname of the Carp
// If not specified, the carp's hostname will be set to a system-defined value.
// +optional
optional string hostname = 16;
// If specified, the fully qualified Carp hostname will be "<hostname>.<subdomain>.<carp namespace>.svc.<cluster domain>".
// If not specified, the carp will not have a domainname at all.
// +optional
optional string subdomain = 17;
// If specified, the carp will be dispatched by specified scheduler.
// If not specified, the carp will be dispatched by default scheduler.
// +optional
optional string schedulername = 19;
}
// CarpStatus represents information about the status of a carp. Status may trail the actual
// state of a system.
message CarpStatus {
// Current condition of the carp.
// More info: http://kubernetes.io/docs/user-guide/carp-states#carp-phase
// +optional
optional string phase = 1;
// Current service state of carp.
// More info: http://kubernetes.io/docs/user-guide/carp-states#carp-conditions
// +optional
repeated CarpCondition conditions = 2;
// A human readable message indicating details about why the carp is in this condition.
// +optional
optional string message = 3;
// A brief CamelCase message indicating details about why the carp is in this state.
// e.g. 'OutOfDisk'
// +optional
optional string reason = 4;
// IP address of the host to which the carp is assigned. Empty if not yet scheduled.
// +optional
optional string hostIP = 5;
// IP address allocated to the carp. Routable at least within the cluster.
// Empty if not yet allocated.
// +optional
optional string carpIP = 6;
// RFC 3339 date and time at which the object was acknowledged by the Kubelet.
// This is before the Kubelet pulled the container image(s) for the carp.
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time startTime = 7;
}

View file

@ -1,63 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName is the group name use in this package
const GroupName = "testapigroup.apimachinery.k8s.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"}
// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
SchemeBuilder runtime.SchemeBuilder
localSchemeBuilder = &SchemeBuilder
AddToScheme = localSchemeBuilder.AddToScheme
)
func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes, addConversionFuncs, addDefaultingFuncs)
}
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Carp{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View file

@ -1,196 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type (
ConditionStatus string
CarpConditionType string
CarpPhase string
RestartPolicy string
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Carp is a collection of containers, used as either input (create, update) or as output (list, get).
type Carp struct {
metav1.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Specification of the desired behavior of the carp.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
// +optional
Spec CarpSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
// Most recently observed status of the carp.
// This data may not be up to date.
// Populated by the system.
// Read-only.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status
// +optional
Status CarpStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// CarpStatus represents information about the status of a carp. Status may trail the actual
// state of a system.
type CarpStatus struct {
// Current condition of the carp.
// More info: http://kubernetes.io/docs/user-guide/carp-states#carp-phase
// +optional
Phase CarpPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase,casttype=CarpPhase"`
// Current service state of carp.
// More info: http://kubernetes.io/docs/user-guide/carp-states#carp-conditions
// +optional
Conditions []CarpCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,2,rep,name=conditions"`
// A human readable message indicating details about why the carp is in this condition.
// +optional
Message string `json:"message,omitempty" protobuf:"bytes,3,opt,name=message"`
// A brief CamelCase message indicating details about why the carp is in this state.
// e.g. 'OutOfDisk'
// +optional
Reason string `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"`
// IP address of the host to which the carp is assigned. Empty if not yet scheduled.
// +optional
HostIP string `json:"hostIP,omitempty" protobuf:"bytes,5,opt,name=hostIP"`
// IP address allocated to the carp. Routable at least within the cluster.
// Empty if not yet allocated.
// +optional
CarpIP string `json:"carpIP,omitempty" protobuf:"bytes,6,opt,name=carpIP"`
// RFC 3339 date and time at which the object was acknowledged by the Kubelet.
// This is before the Kubelet pulled the container image(s) for the carp.
// +optional
StartTime *metav1.Time `json:"startTime,omitempty" protobuf:"bytes,7,opt,name=startTime"`
}
type CarpCondition struct {
// Type is the type of the condition.
// Currently only Ready.
// More info: http://kubernetes.io/docs/user-guide/carp-states#carp-conditions
Type CarpConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=CarpConditionType"`
// Status is the status of the condition.
// Can be True, False, Unknown.
// More info: http://kubernetes.io/docs/user-guide/carp-states#carp-conditions
Status ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=ConditionStatus"`
// Last time we probed the condition.
// +optional
LastProbeTime metav1.Time `json:"lastProbeTime,omitempty" protobuf:"bytes,3,opt,name=lastProbeTime"`
// Last time the condition transitioned from one status to another.
// +optional
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,4,opt,name=lastTransitionTime"`
// Unique, one-word, CamelCase reason for the condition's last transition.
// +optional
Reason string `json:"reason,omitempty" protobuf:"bytes,5,opt,name=reason"`
// Human-readable message indicating details about last transition.
// +optional
Message string `json:"message,omitempty" protobuf:"bytes,6,opt,name=message"`
}
// CarpSpec is a description of a carp
type CarpSpec struct {
// Restart policy for all containers within the carp.
// One of Always, OnFailure, Never.
// Default to Always.
// More info: http://kubernetes.io/docs/user-guide/carp-states#restartpolicy
// +optional
RestartPolicy RestartPolicy `json:"restartPolicy,omitempty" protobuf:"bytes,3,opt,name=restartPolicy,casttype=RestartPolicy"`
// Optional duration in seconds the carp needs to terminate gracefully. May be decreased in delete request.
// Value must be non-negative integer. The value zero indicates delete immediately.
// If this value is nil, the default grace period will be used instead.
// The grace period is the duration in seconds after the processes running in the carp are sent
// a termination signal and the time when the processes are forcibly halted with a kill signal.
// Set this value longer than the expected cleanup time for your process.
// Defaults to 30 seconds.
// +optional
TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty" protobuf:"varint,4,opt,name=terminationGracePeriodSeconds"`
// Optional duration in seconds the carp may be active on the node relative to
// StartTime before the system will actively try to mark it failed and kill associated containers.
// Value must be a positive integer.
// +optional
ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty" protobuf:"varint,5,opt,name=activeDeadlineSeconds"`
// NodeSelector is a selector which must be true for the carp to fit on a node.
// Selector which must match a node's labels for the carp to be scheduled on that node.
// More info: http://kubernetes.io/docs/user-guide/node-selection/README
// +optional
NodeSelector map[string]string `json:"nodeSelector,omitempty" protobuf:"bytes,7,rep,name=nodeSelector"`
// ServiceAccountName is the name of the ServiceAccount to use to run this carp.
// More info: http://releases.k8s.io/HEAD/docs/design/service_accounts.md
// +optional
ServiceAccountName string `json:"serviceAccountName,omitempty" protobuf:"bytes,8,opt,name=serviceAccountName"`
// DeprecatedServiceAccount is a depreciated alias for ServiceAccountName.
// Deprecated: Use serviceAccountName instead.
// +k8s:conversion-gen=false
// +optional
DeprecatedServiceAccount string `json:"serviceAccount,omitempty" protobuf:"bytes,9,opt,name=serviceAccount"`
// NodeName is a request to schedule this carp onto a specific node. If it is non-empty,
// the scheduler simply schedules this carp onto that node, assuming that it fits resource
// requirements.
// +optional
NodeName string `json:"nodeName,omitempty" protobuf:"bytes,10,opt,name=nodeName"`
// Host networking requested for this carp. Use the host's network namespace.
// If this option is set, the ports that will be used must be specified.
// Default to false.
// +k8s:conversion-gen=false
// +optional
HostNetwork bool `json:"hostNetwork,omitempty" protobuf:"varint,11,opt,name=hostNetwork"`
// Use the host's pid namespace.
// Optional: Default to false.
// +k8s:conversion-gen=false
// +optional
HostPID bool `json:"hostPID,omitempty" protobuf:"varint,12,opt,name=hostPID"`
// Use the host's ipc namespace.
// Optional: Default to false.
// +k8s:conversion-gen=false
// +optional
HostIPC bool `json:"hostIPC,omitempty" protobuf:"varint,13,opt,name=hostIPC"`
// Specifies the hostname of the Carp
// If not specified, the carp's hostname will be set to a system-defined value.
// +optional
Hostname string `json:"hostname,omitempty" protobuf:"bytes,16,opt,name=hostname"`
// If specified, the fully qualified Carp hostname will be "<hostname>.<subdomain>.<carp namespace>.svc.<cluster domain>".
// If not specified, the carp will not have a domainname at all.
// +optional
Subdomain string `json:"subdomain,omitempty" protobuf:"bytes,17,opt,name=subdomain"`
// If specified, the carp will be dispatched by specified scheduler.
// If not specified, the carp will be dispatched by default scheduler.
// +optional
SchedulerName string `json:"schedulername,omitempty" protobuf:"bytes,19,opt,name=schedulername"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CarpList is a list of Carps.
type CarpList struct {
metav1.TypeMeta `json:",inline"`
// Standard list metadata.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// List of carps.
// More info: http://kubernetes.io/docs/user-guide/carps
Items []Carp `json:"items" protobuf:"bytes,2,rep,name=items"`
}

View file

@ -1,17 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1

View file

@ -1,226 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by conversion-gen. Do not edit it manually!
package v1
import (
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
testapigroup "k8s.io/apimachinery/pkg/apis/testapigroup"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
unsafe "unsafe"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1_Carp_To_testapigroup_Carp,
Convert_testapigroup_Carp_To_v1_Carp,
Convert_v1_CarpCondition_To_testapigroup_CarpCondition,
Convert_testapigroup_CarpCondition_To_v1_CarpCondition,
Convert_v1_CarpList_To_testapigroup_CarpList,
Convert_testapigroup_CarpList_To_v1_CarpList,
Convert_v1_CarpSpec_To_testapigroup_CarpSpec,
Convert_testapigroup_CarpSpec_To_v1_CarpSpec,
Convert_v1_CarpStatus_To_testapigroup_CarpStatus,
Convert_testapigroup_CarpStatus_To_v1_CarpStatus,
)
}
func autoConvert_v1_Carp_To_testapigroup_Carp(in *Carp, out *testapigroup.Carp, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v1_CarpSpec_To_testapigroup_CarpSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_v1_CarpStatus_To_testapigroup_CarpStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
// Convert_v1_Carp_To_testapigroup_Carp is an autogenerated conversion function.
func Convert_v1_Carp_To_testapigroup_Carp(in *Carp, out *testapigroup.Carp, s conversion.Scope) error {
return autoConvert_v1_Carp_To_testapigroup_Carp(in, out, s)
}
func autoConvert_testapigroup_Carp_To_v1_Carp(in *testapigroup.Carp, out *Carp, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_testapigroup_CarpSpec_To_v1_CarpSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_testapigroup_CarpStatus_To_v1_CarpStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
// Convert_testapigroup_Carp_To_v1_Carp is an autogenerated conversion function.
func Convert_testapigroup_Carp_To_v1_Carp(in *testapigroup.Carp, out *Carp, s conversion.Scope) error {
return autoConvert_testapigroup_Carp_To_v1_Carp(in, out, s)
}
func autoConvert_v1_CarpCondition_To_testapigroup_CarpCondition(in *CarpCondition, out *testapigroup.CarpCondition, s conversion.Scope) error {
out.Type = testapigroup.CarpConditionType(in.Type)
out.Status = testapigroup.ConditionStatus(in.Status)
out.LastProbeTime = in.LastProbeTime
out.LastTransitionTime = in.LastTransitionTime
out.Reason = in.Reason
out.Message = in.Message
return nil
}
// Convert_v1_CarpCondition_To_testapigroup_CarpCondition is an autogenerated conversion function.
func Convert_v1_CarpCondition_To_testapigroup_CarpCondition(in *CarpCondition, out *testapigroup.CarpCondition, s conversion.Scope) error {
return autoConvert_v1_CarpCondition_To_testapigroup_CarpCondition(in, out, s)
}
func autoConvert_testapigroup_CarpCondition_To_v1_CarpCondition(in *testapigroup.CarpCondition, out *CarpCondition, s conversion.Scope) error {
out.Type = CarpConditionType(in.Type)
out.Status = ConditionStatus(in.Status)
out.LastProbeTime = in.LastProbeTime
out.LastTransitionTime = in.LastTransitionTime
out.Reason = in.Reason
out.Message = in.Message
return nil
}
// Convert_testapigroup_CarpCondition_To_v1_CarpCondition is an autogenerated conversion function.
func Convert_testapigroup_CarpCondition_To_v1_CarpCondition(in *testapigroup.CarpCondition, out *CarpCondition, s conversion.Scope) error {
return autoConvert_testapigroup_CarpCondition_To_v1_CarpCondition(in, out, s)
}
func autoConvert_v1_CarpList_To_testapigroup_CarpList(in *CarpList, out *testapigroup.CarpList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]testapigroup.Carp, len(*in))
for i := range *in {
if err := Convert_v1_Carp_To_testapigroup_Carp(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
// Convert_v1_CarpList_To_testapigroup_CarpList is an autogenerated conversion function.
func Convert_v1_CarpList_To_testapigroup_CarpList(in *CarpList, out *testapigroup.CarpList, s conversion.Scope) error {
return autoConvert_v1_CarpList_To_testapigroup_CarpList(in, out, s)
}
func autoConvert_testapigroup_CarpList_To_v1_CarpList(in *testapigroup.CarpList, out *CarpList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Carp, len(*in))
for i := range *in {
if err := Convert_testapigroup_Carp_To_v1_Carp(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
// Convert_testapigroup_CarpList_To_v1_CarpList is an autogenerated conversion function.
func Convert_testapigroup_CarpList_To_v1_CarpList(in *testapigroup.CarpList, out *CarpList, s conversion.Scope) error {
return autoConvert_testapigroup_CarpList_To_v1_CarpList(in, out, s)
}
func autoConvert_v1_CarpSpec_To_testapigroup_CarpSpec(in *CarpSpec, out *testapigroup.CarpSpec, s conversion.Scope) error {
out.RestartPolicy = testapigroup.RestartPolicy(in.RestartPolicy)
out.TerminationGracePeriodSeconds = (*int64)(unsafe.Pointer(in.TerminationGracePeriodSeconds))
out.ActiveDeadlineSeconds = (*int64)(unsafe.Pointer(in.ActiveDeadlineSeconds))
out.NodeSelector = *(*map[string]string)(unsafe.Pointer(&in.NodeSelector))
out.ServiceAccountName = in.ServiceAccountName
// INFO: in.DeprecatedServiceAccount opted out of conversion generation
out.NodeName = in.NodeName
// INFO: in.HostNetwork opted out of conversion generation
// INFO: in.HostPID opted out of conversion generation
// INFO: in.HostIPC opted out of conversion generation
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
out.SchedulerName = in.SchedulerName
return nil
}
// Convert_v1_CarpSpec_To_testapigroup_CarpSpec is an autogenerated conversion function.
func Convert_v1_CarpSpec_To_testapigroup_CarpSpec(in *CarpSpec, out *testapigroup.CarpSpec, s conversion.Scope) error {
return autoConvert_v1_CarpSpec_To_testapigroup_CarpSpec(in, out, s)
}
func autoConvert_testapigroup_CarpSpec_To_v1_CarpSpec(in *testapigroup.CarpSpec, out *CarpSpec, s conversion.Scope) error {
out.RestartPolicy = RestartPolicy(in.RestartPolicy)
out.TerminationGracePeriodSeconds = (*int64)(unsafe.Pointer(in.TerminationGracePeriodSeconds))
out.ActiveDeadlineSeconds = (*int64)(unsafe.Pointer(in.ActiveDeadlineSeconds))
out.NodeSelector = *(*map[string]string)(unsafe.Pointer(&in.NodeSelector))
out.ServiceAccountName = in.ServiceAccountName
out.NodeName = in.NodeName
out.Hostname = in.Hostname
out.Subdomain = in.Subdomain
out.SchedulerName = in.SchedulerName
return nil
}
// Convert_testapigroup_CarpSpec_To_v1_CarpSpec is an autogenerated conversion function.
func Convert_testapigroup_CarpSpec_To_v1_CarpSpec(in *testapigroup.CarpSpec, out *CarpSpec, s conversion.Scope) error {
return autoConvert_testapigroup_CarpSpec_To_v1_CarpSpec(in, out, s)
}
func autoConvert_v1_CarpStatus_To_testapigroup_CarpStatus(in *CarpStatus, out *testapigroup.CarpStatus, s conversion.Scope) error {
out.Phase = testapigroup.CarpPhase(in.Phase)
out.Conditions = *(*[]testapigroup.CarpCondition)(unsafe.Pointer(&in.Conditions))
out.Message = in.Message
out.Reason = in.Reason
out.HostIP = in.HostIP
out.CarpIP = in.CarpIP
out.StartTime = (*meta_v1.Time)(unsafe.Pointer(in.StartTime))
return nil
}
// Convert_v1_CarpStatus_To_testapigroup_CarpStatus is an autogenerated conversion function.
func Convert_v1_CarpStatus_To_testapigroup_CarpStatus(in *CarpStatus, out *testapigroup.CarpStatus, s conversion.Scope) error {
return autoConvert_v1_CarpStatus_To_testapigroup_CarpStatus(in, out, s)
}
func autoConvert_testapigroup_CarpStatus_To_v1_CarpStatus(in *testapigroup.CarpStatus, out *CarpStatus, s conversion.Scope) error {
out.Phase = CarpPhase(in.Phase)
out.Conditions = *(*[]CarpCondition)(unsafe.Pointer(&in.Conditions))
out.Message = in.Message
out.Reason = in.Reason
out.HostIP = in.HostIP
out.CarpIP = in.CarpIP
out.StartTime = (*meta_v1.Time)(unsafe.Pointer(in.StartTime))
return nil
}
// Convert_testapigroup_CarpStatus_To_v1_CarpStatus is an autogenerated conversion function.
func Convert_testapigroup_CarpStatus_To_v1_CarpStatus(in *testapigroup.CarpStatus, out *CarpStatus, s conversion.Scope) error {
return autoConvert_testapigroup_CarpStatus_To_v1_CarpStatus(in, out, s)
}

View file

@ -1,215 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package v1
import (
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
reflect "reflect"
)
func init() {
SchemeBuilder.Register(RegisterDeepCopies)
}
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
// to allow building arbitrary schemes.
//
// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented.
func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*Carp).DeepCopyInto(out.(*Carp))
return nil
}, InType: reflect.TypeOf(&Carp{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*CarpCondition).DeepCopyInto(out.(*CarpCondition))
return nil
}, InType: reflect.TypeOf(&CarpCondition{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*CarpList).DeepCopyInto(out.(*CarpList))
return nil
}, InType: reflect.TypeOf(&CarpList{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*CarpSpec).DeepCopyInto(out.(*CarpSpec))
return nil
}, InType: reflect.TypeOf(&CarpSpec{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*CarpStatus).DeepCopyInto(out.(*CarpStatus))
return nil
}, InType: reflect.TypeOf(&CarpStatus{})},
)
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Carp) DeepCopyInto(out *Carp) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Carp.
func (in *Carp) DeepCopy() *Carp {
if in == nil {
return nil
}
out := new(Carp)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Carp) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CarpCondition) DeepCopyInto(out *CarpCondition) {
*out = *in
in.LastProbeTime.DeepCopyInto(&out.LastProbeTime)
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CarpCondition.
func (in *CarpCondition) DeepCopy() *CarpCondition {
if in == nil {
return nil
}
out := new(CarpCondition)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CarpList) DeepCopyInto(out *CarpList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Carp, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CarpList.
func (in *CarpList) DeepCopy() *CarpList {
if in == nil {
return nil
}
out := new(CarpList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *CarpList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CarpSpec) DeepCopyInto(out *CarpSpec) {
*out = *in
if in.TerminationGracePeriodSeconds != nil {
in, out := &in.TerminationGracePeriodSeconds, &out.TerminationGracePeriodSeconds
if *in == nil {
*out = nil
} else {
*out = new(int64)
**out = **in
}
}
if in.ActiveDeadlineSeconds != nil {
in, out := &in.ActiveDeadlineSeconds, &out.ActiveDeadlineSeconds
if *in == nil {
*out = nil
} else {
*out = new(int64)
**out = **in
}
}
if in.NodeSelector != nil {
in, out := &in.NodeSelector, &out.NodeSelector
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CarpSpec.
func (in *CarpSpec) DeepCopy() *CarpSpec {
if in == nil {
return nil
}
out := new(CarpSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CarpStatus) DeepCopyInto(out *CarpStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]CarpCondition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.StartTime != nil {
in, out := &in.StartTime, &out.StartTime
if *in == nil {
*out = nil
} else {
*out = new(meta_v1.Time)
(*in).DeepCopyInto(*out)
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CarpStatus.
func (in *CarpStatus) DeepCopy() *CarpStatus {
if in == nil {
return nil
}
out := new(CarpStatus)
in.DeepCopyInto(out)
return out
}

View file

@ -1,32 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by defaulter-gen. Do not edit it manually!
package v1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// RegisterDefaults adds defaulters functions to the given scheme.
// Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error {
return nil
}

View file

@ -1,215 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package testapigroup
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
reflect "reflect"
)
func init() {
SchemeBuilder.Register(RegisterDeepCopies)
}
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
// to allow building arbitrary schemes.
//
// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented.
func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*Carp).DeepCopyInto(out.(*Carp))
return nil
}, InType: reflect.TypeOf(&Carp{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*CarpCondition).DeepCopyInto(out.(*CarpCondition))
return nil
}, InType: reflect.TypeOf(&CarpCondition{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*CarpList).DeepCopyInto(out.(*CarpList))
return nil
}, InType: reflect.TypeOf(&CarpList{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*CarpSpec).DeepCopyInto(out.(*CarpSpec))
return nil
}, InType: reflect.TypeOf(&CarpSpec{})},
conversion.GeneratedDeepCopyFunc{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*CarpStatus).DeepCopyInto(out.(*CarpStatus))
return nil
}, InType: reflect.TypeOf(&CarpStatus{})},
)
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Carp) DeepCopyInto(out *Carp) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Carp.
func (in *Carp) DeepCopy() *Carp {
if in == nil {
return nil
}
out := new(Carp)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Carp) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CarpCondition) DeepCopyInto(out *CarpCondition) {
*out = *in
in.LastProbeTime.DeepCopyInto(&out.LastProbeTime)
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CarpCondition.
func (in *CarpCondition) DeepCopy() *CarpCondition {
if in == nil {
return nil
}
out := new(CarpCondition)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CarpList) DeepCopyInto(out *CarpList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Carp, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CarpList.
func (in *CarpList) DeepCopy() *CarpList {
if in == nil {
return nil
}
out := new(CarpList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *CarpList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CarpSpec) DeepCopyInto(out *CarpSpec) {
*out = *in
if in.TerminationGracePeriodSeconds != nil {
in, out := &in.TerminationGracePeriodSeconds, &out.TerminationGracePeriodSeconds
if *in == nil {
*out = nil
} else {
*out = new(int64)
**out = **in
}
}
if in.ActiveDeadlineSeconds != nil {
in, out := &in.ActiveDeadlineSeconds, &out.ActiveDeadlineSeconds
if *in == nil {
*out = nil
} else {
*out = new(int64)
**out = **in
}
}
if in.NodeSelector != nil {
in, out := &in.NodeSelector, &out.NodeSelector
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CarpSpec.
func (in *CarpSpec) DeepCopy() *CarpSpec {
if in == nil {
return nil
}
out := new(CarpSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CarpStatus) DeepCopyInto(out *CarpStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]CarpCondition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.StartTime != nil {
in, out := &in.StartTime, &out.StartTime
if *in == nil {
*out = nil
} else {
*out = new(v1.Time)
(*in).DeepCopyInto(*out)
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CarpStatus.
func (in *CarpStatus) DeepCopy() *CarpStatus {
if in == nil {
return nil
}
out := new(CarpStatus)
in.DeepCopyInto(out)
return out
}

View file

@ -1,28 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_test")
go_test(
name = "go_default_test",
srcs = ["converter_test.go"],
deps = [
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View file

@ -1,539 +0,0 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// These tests are in a separate package to break cyclic dependency in tests.
// Unstructured type depends on unstructured converter package but we want to test how the converter handles
// the Unstructured type so we need to import both.
package testing
import (
"fmt"
"reflect"
"strconv"
"testing"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
conversionunstructured "k8s.io/apimachinery/pkg/conversion/unstructured"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/json"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// Definte a number of test types.
type A struct {
A int `json:"aa,omitempty"`
B string `json:"ab,omitempty"`
C bool `json:"ac,omitempty"`
}
type B struct {
A A `json:"ba"`
B string `json:"bb"`
C map[string]string `json:"bc"`
D []string `json:"bd"`
}
type C struct {
A []A `json:"ca"`
B `json:",inline"`
C string `json:"cc"`
D *int64 `json:"cd"`
E map[string]int `json:"ce"`
F []bool `json:"cf"`
G []int `json:"cg"`
H float32 `json:"ch"`
I []interface{} `json:"ci"`
}
type D struct {
A []interface{} `json:"da"`
}
type E struct {
A interface{} `json:"ea"`
}
type F struct {
A string `json:"fa"`
B map[string]string `json:"fb"`
C []A `json:"fc"`
D int `json:"fd"`
E float32 `json:"fe"`
F []string `json:"ff"`
G []int `json:"fg"`
H []bool `json:"fh"`
I []float32 `json:"fi"`
}
type G struct {
CustomValue1 CustomValue `json:"customValue1"`
CustomValue2 *CustomValue `json:"customValue2"`
CustomPointer1 CustomPointer `json:"customPointer1"`
CustomPointer2 *CustomPointer `json:"customPointer2"`
}
type CustomValue struct {
data []byte
}
// MarshalJSON has a value receiver on this type.
func (c CustomValue) MarshalJSON() ([]byte, error) {
return c.data, nil
}
type CustomPointer struct {
data []byte
}
// MarshalJSON has a pointer receiver on this type.
func (c *CustomPointer) MarshalJSON() ([]byte, error) {
return c.data, nil
}
func doRoundTrip(t *testing.T, item interface{}) {
data, err := json.Marshal(item)
if err != nil {
t.Errorf("Error when marshaling object: %v", err)
return
}
unstr := make(map[string]interface{})
err = json.Unmarshal(data, &unstr)
if err != nil {
t.Errorf("Error when unmarshaling to unstructured: %v", err)
return
}
data, err = json.Marshal(unstr)
if err != nil {
t.Errorf("Error when marshaling unstructured: %v", err)
return
}
unmarshalledObj := reflect.New(reflect.TypeOf(item).Elem()).Interface()
err = json.Unmarshal(data, &unmarshalledObj)
if err != nil {
t.Errorf("Error when unmarshaling to object: %v", err)
return
}
if !reflect.DeepEqual(item, unmarshalledObj) {
t.Errorf("Object changed during JSON operations, diff: %v", diff.ObjectReflectDiff(item, unmarshalledObj))
return
}
newUnstr, err := conversionunstructured.DefaultConverter.ToUnstructured(item)
if err != nil {
t.Errorf("ToUnstructured failed: %v", err)
return
}
newObj := reflect.New(reflect.TypeOf(item).Elem()).Interface()
err = conversionunstructured.DefaultConverter.FromUnstructured(newUnstr, newObj)
if err != nil {
t.Errorf("FromUnstructured failed: %v", err)
return
}
if !reflect.DeepEqual(item, newObj) {
t.Errorf("Object changed, diff: %v", diff.ObjectReflectDiff(item, newObj))
}
}
func TestRoundTrip(t *testing.T) {
intVal := int64(42)
testCases := []struct {
obj interface{}
}{
{
obj: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Foo",
"metadata": map[string]interface{}{
"name": "foo1",
},
},
},
},
{
// This (among others) tests nil map, slice and pointer.
obj: &C{
C: "ccc",
},
},
{
// This (among others) tests empty map and slice.
obj: &C{
A: []A{},
C: "ccc",
E: map[string]int{},
I: []interface{}{},
},
},
{
obj: &C{
A: []A{
{
A: 1,
B: "11",
C: true,
},
{
A: 2,
B: "22",
C: false,
},
},
B: B{
A: A{
A: 3,
B: "33",
},
B: "bbb",
C: map[string]string{
"k1": "v1",
"k2": "v2",
},
D: []string{"s1", "s2"},
},
C: "ccc",
D: &intVal,
E: map[string]int{
"k1": 1,
"k2": 2,
},
F: []bool{true, false, false},
G: []int{1, 2, 5},
H: 3.3,
I: []interface{}{nil, nil, nil},
},
},
{
// Test slice of interface{} with empty slices.
obj: &D{
A: []interface{}{[]interface{}{}, []interface{}{}},
},
},
{
// Test slice of interface{} with different values.
obj: &D{
A: []interface{}{3.0, "3.0", nil},
},
},
}
for i := range testCases {
doRoundTrip(t, testCases[i].obj)
if t.Failed() {
break
}
}
}
// Verifies that:
// 1) serialized json -> object
// 2) serialized json -> map[string]interface{} -> object
// produces the same object.
func doUnrecognized(t *testing.T, jsonData string, item interface{}, expectedErr error) {
unmarshalledObj := reflect.New(reflect.TypeOf(item).Elem()).Interface()
err := json.Unmarshal([]byte(jsonData), &unmarshalledObj)
if (err != nil) != (expectedErr != nil) {
t.Errorf("Unexpected error when unmarshaling to object: %v, expected: %v", err, expectedErr)
return
}
unstr := make(map[string]interface{})
err = json.Unmarshal([]byte(jsonData), &unstr)
if err != nil {
t.Errorf("Error when unmarshaling to unstructured: %v", err)
return
}
newObj := reflect.New(reflect.TypeOf(item).Elem()).Interface()
err = conversionunstructured.DefaultConverter.FromUnstructured(unstr, newObj)
if (err != nil) != (expectedErr != nil) {
t.Errorf("Unexpected error in FromUnstructured: %v, expected: %v", err, expectedErr)
}
if expectedErr == nil && !reflect.DeepEqual(unmarshalledObj, newObj) {
t.Errorf("Object changed, diff: %v", diff.ObjectReflectDiff(unmarshalledObj, newObj))
}
}
func TestUnrecognized(t *testing.T) {
testCases := []struct {
data string
obj interface{}
err error
}{
{
data: "{\"da\":[3.0,\"3.0\",null]}",
obj: &D{},
},
{
data: "{\"ea\":[3.0,\"3.0\",null]}",
obj: &E{},
},
{
data: "{\"ea\":[null,null,null]}",
obj: &E{},
},
{
data: "{\"ea\":[[],[null]]}",
obj: &E{},
},
{
data: "{\"ea\":{\"a\":[],\"b\":null}}",
obj: &E{},
},
{
data: "{\"fa\":\"fa\",\"fb\":{\"a\":\"a\"}}",
obj: &F{},
},
{
data: "{\"fa\":\"fa\",\"fb\":{\"a\":null}}",
obj: &F{},
},
{
data: "{\"fc\":[null]}",
obj: &F{},
},
{
data: "{\"fc\":[{\"aa\":123,\"ab\":\"bbb\"}]}",
obj: &F{},
},
{
// Only unknown fields
data: "{\"fx\":[{\"aa\":123,\"ab\":\"bbb\"}],\"fz\":123}",
obj: &F{},
},
{
data: "{\"fc\":[{\"aa\":\"aaa\",\"ab\":\"bbb\"}]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type int"),
},
{
data: "{\"fd\":123,\"fe\":3.5}",
obj: &F{},
},
{
data: "{\"ff\":[\"abc\"],\"fg\":[123],\"fh\":[true,false]}",
obj: &F{},
},
{
// Invalid string data
data: "{\"fa\":123}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type string"),
},
{
// Invalid string data
data: "{\"fa\":13.5}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type string"),
},
{
// Invalid string data
data: "{\"fa\":true}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal bool into Go value of type string"),
},
{
// Invalid []string data
data: "{\"ff\":123}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type []string"),
},
{
// Invalid []string data
data: "{\"ff\":3.5}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type []string"),
},
{
// Invalid []string data
data: "{\"ff\":[123,345]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type string"),
},
{
// Invalid []int data
data: "{\"fg\":123}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type []int"),
},
{
// Invalid []int data
data: "{\"fg\":\"abc\"}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type []int"),
},
{
// Invalid []int data
data: "{\"fg\":[\"abc\"]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type int"),
},
{
// Invalid []int data
data: "{\"fg\":[3.5]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number 3.5 into Go value of type int"),
},
{
// Invalid []int data
data: "{\"fg\":[true,false]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number 3.5 into Go value of type int"),
},
{
// Invalid []bool data
data: "{\"fh\":123}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type []bool"),
},
{
// Invalid []bool data
data: "{\"fh\":\"abc\"}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type []bool"),
},
{
// Invalid []bool data
data: "{\"fh\":[\"abc\"]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type bool"),
},
{
// Invalid []bool data
data: "{\"fh\":[3.5]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type bool"),
},
{
// Invalid []bool data
data: "{\"fh\":[123]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type bool"),
},
{
// Invalid []float data
data: "{\"fi\":123}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal number into Go value of type []float32"),
},
{
// Invalid []float data
data: "{\"fi\":\"abc\"}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type []float32"),
},
{
// Invalid []float data
data: "{\"fi\":[\"abc\"]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal string into Go value of type float32"),
},
{
// Invalid []float data
data: "{\"fi\":[true]}",
obj: &F{},
err: fmt.Errorf("json: cannot unmarshal bool into Go value of type float32"),
},
}
for i := range testCases {
doUnrecognized(t, testCases[i].data, testCases[i].obj, testCases[i].err)
if t.Failed() {
break
}
}
}
func TestFloatIntConversion(t *testing.T) {
unstr := map[string]interface{}{"fd": float64(3)}
var obj F
if err := conversionunstructured.DefaultConverter.FromUnstructured(unstr, &obj); err != nil {
t.Errorf("Unexpected error in FromUnstructured: %v", err)
}
data, err := json.Marshal(unstr)
if err != nil {
t.Fatalf("Error when marshaling unstructured: %v", err)
}
var unmarshalled F
if err := json.Unmarshal(data, &unmarshalled); err != nil {
t.Fatalf("Error when unmarshaling to object: %v", err)
}
if !reflect.DeepEqual(obj, unmarshalled) {
t.Errorf("Incorrect conversion, diff: %v", diff.ObjectReflectDiff(obj, unmarshalled))
}
}
func TestCustomToUnstructured(t *testing.T) {
testcases := []struct {
Data string
Expected interface{}
}{
{Data: `null`, Expected: nil},
{Data: `true`, Expected: true},
{Data: `false`, Expected: false},
{Data: `[]`, Expected: []interface{}{}},
{Data: `[1]`, Expected: []interface{}{int64(1)}},
{Data: `{}`, Expected: map[string]interface{}{}},
{Data: `{"a":1}`, Expected: map[string]interface{}{"a": int64(1)}},
{Data: `0`, Expected: int64(0)},
{Data: `0.0`, Expected: float64(0)},
}
for _, tc := range testcases {
tc := tc
t.Run(tc.Data, func(t *testing.T) {
t.Parallel()
result, err := conversionunstructured.DefaultConverter.ToUnstructured(&G{
CustomValue1: CustomValue{data: []byte(tc.Data)},
CustomValue2: &CustomValue{data: []byte(tc.Data)},
CustomPointer1: CustomPointer{data: []byte(tc.Data)},
CustomPointer2: &CustomPointer{data: []byte(tc.Data)},
})
require.NoError(t, err)
for field, fieldResult := range result {
assert.Equal(t, tc.Expected, fieldResult, field)
}
})
}
}
func TestCustomToUnstructuredTopLevel(t *testing.T) {
// Only objects are supported at the top level
topLevelCases := []interface{}{
&CustomValue{data: []byte(`{"a":1}`)},
&CustomPointer{data: []byte(`{"a":1}`)},
}
expected := map[string]interface{}{"a": int64(1)}
for i, obj := range topLevelCases {
obj := obj
t.Run(strconv.Itoa(i), func(t *testing.T) {
t.Parallel()
result, err := conversionunstructured.DefaultConverter.ToUnstructured(obj)
require.NoError(t, err)
assert.Equal(t, expected, result)
})
}
}

View file

@ -1,30 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["recognizer_test.go"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/recognizer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,61 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testing
import (
"testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
)
type A struct{}
func (A) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
func (a A) DeepCopyObject() runtime.Object {
return a
}
func TestRecognizer(t *testing.T) {
s := runtime.NewScheme()
s.AddKnownTypes(schema.GroupVersion{Version: "v1"}, &A{})
d := recognizer.NewDecoder(
json.NewSerializer(json.DefaultMetaFactory, s, s, false),
json.NewYAMLSerializer(json.DefaultMetaFactory, s, s),
)
out, _, err := d.Decode([]byte(`
kind: A
apiVersion: v1
`), nil, nil)
if err != nil {
t.Fatal(err)
}
t.Logf("%#v", out)
out, _, err = d.Decode([]byte(`
{
"kind":"A",
"apiVersion":"v1"
}
`), nil, nil)
if err != nil {
t.Fatal(err)
}
t.Logf("%#v", out)
}

View file

@ -1,33 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"types.go",
"zz_generated.deepcopy.go",
],
deps = [
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,19 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:deepcopy-gen=package
package testing

View file

@ -1,114 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testing
import (
"k8s.io/apimachinery/pkg/runtime/schema"
)
// Test a weird version/kind embedding format.
// +k8s:deepcopy-gen=false
type MyWeirdCustomEmbeddedVersionKindField struct {
ID string `json:"ID,omitempty"`
APIVersion string `json:"myVersionKey,omitempty"`
ObjectKind string `json:"myKindKey,omitempty"`
Z string `json:"Z,omitempty"`
Y uint64 `json:"Y,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type TestType1 struct {
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
C int8 `json:"C,omitempty"`
D int16 `json:"D,omitempty"`
E int32 `json:"E,omitempty"`
F int64 `json:"F,omitempty"`
G uint `json:"G,omitempty"`
H uint8 `json:"H,omitempty"`
I uint16 `json:"I,omitempty"`
J uint32 `json:"J,omitempty"`
K uint64 `json:"K,omitempty"`
L bool `json:"L,omitempty"`
M map[string]int `json:"M,omitempty"`
N map[string]TestType2 `json:"N,omitempty"`
O *TestType2 `json:"O,omitempty"`
P []TestType2 `json:"Q,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type TestType2 struct {
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExternalTestType2 struct {
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExternalTestType1 struct {
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
C int8 `json:"C,omitempty"`
D int16 `json:"D,omitempty"`
E int32 `json:"E,omitempty"`
F int64 `json:"F,omitempty"`
G uint `json:"G,omitempty"`
H uint8 `json:"H,omitempty"`
I uint16 `json:"I,omitempty"`
J uint32 `json:"J,omitempty"`
K uint64 `json:"K,omitempty"`
L bool `json:"L,omitempty"`
M map[string]int `json:"M,omitempty"`
N map[string]ExternalTestType2 `json:"N,omitempty"`
O *ExternalTestType2 `json:"O,omitempty"`
P []ExternalTestType2 `json:"Q,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExternalInternalSame struct {
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
A TestType2 `json:"A,omitempty"`
}
func (obj *MyWeirdCustomEmbeddedVersionKindField) GetObjectKind() schema.ObjectKind { return obj }
func (obj *MyWeirdCustomEmbeddedVersionKindField) SetGroupVersionKind(gvk schema.GroupVersionKind) {
obj.APIVersion, obj.ObjectKind = gvk.ToAPIVersionAndKind()
}
func (obj *MyWeirdCustomEmbeddedVersionKindField) GroupVersionKind() schema.GroupVersionKind {
return schema.FromAPIVersionAndKind(obj.APIVersion, obj.ObjectKind)
}
func (obj *ExternalInternalSame) GetObjectKind() schema.ObjectKind {
return &obj.MyWeirdCustomEmbeddedVersionKindField
}
func (obj *TestType1) GetObjectKind() schema.ObjectKind {
return &obj.MyWeirdCustomEmbeddedVersionKindField
}
func (obj *ExternalTestType1) GetObjectKind() schema.ObjectKind {
return &obj.MyWeirdCustomEmbeddedVersionKindField
}
func (obj *TestType2) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
func (obj *ExternalTestType2) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }

View file

@ -1,240 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package testing
import (
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
reflect "reflect"
)
// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them.
//
// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented.
func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc {
return []conversion.GeneratedDeepCopyFunc{
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExternalInternalSame).DeepCopyInto(out.(*ExternalInternalSame))
return nil
}, InType: reflect.TypeOf(&ExternalInternalSame{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExternalTestType1).DeepCopyInto(out.(*ExternalTestType1))
return nil
}, InType: reflect.TypeOf(&ExternalTestType1{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExternalTestType2).DeepCopyInto(out.(*ExternalTestType2))
return nil
}, InType: reflect.TypeOf(&ExternalTestType2{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*TestType1).DeepCopyInto(out.(*TestType1))
return nil
}, InType: reflect.TypeOf(&TestType1{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*TestType2).DeepCopyInto(out.(*TestType2))
return nil
}, InType: reflect.TypeOf(&TestType2{})},
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalInternalSame) DeepCopyInto(out *ExternalInternalSame) {
*out = *in
out.MyWeirdCustomEmbeddedVersionKindField = in.MyWeirdCustomEmbeddedVersionKindField
out.A = in.A
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalInternalSame.
func (in *ExternalInternalSame) DeepCopy() *ExternalInternalSame {
if in == nil {
return nil
}
out := new(ExternalInternalSame)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExternalInternalSame) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalTestType1) DeepCopyInto(out *ExternalTestType1) {
*out = *in
out.MyWeirdCustomEmbeddedVersionKindField = in.MyWeirdCustomEmbeddedVersionKindField
if in.M != nil {
in, out := &in.M, &out.M
*out = make(map[string]int, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.N != nil {
in, out := &in.N, &out.N
*out = make(map[string]ExternalTestType2, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.O != nil {
in, out := &in.O, &out.O
if *in == nil {
*out = nil
} else {
*out = new(ExternalTestType2)
**out = **in
}
}
if in.P != nil {
in, out := &in.P, &out.P
*out = make([]ExternalTestType2, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalTestType1.
func (in *ExternalTestType1) DeepCopy() *ExternalTestType1 {
if in == nil {
return nil
}
out := new(ExternalTestType1)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExternalTestType1) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalTestType2) DeepCopyInto(out *ExternalTestType2) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalTestType2.
func (in *ExternalTestType2) DeepCopy() *ExternalTestType2 {
if in == nil {
return nil
}
out := new(ExternalTestType2)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExternalTestType2) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TestType1) DeepCopyInto(out *TestType1) {
*out = *in
out.MyWeirdCustomEmbeddedVersionKindField = in.MyWeirdCustomEmbeddedVersionKindField
if in.M != nil {
in, out := &in.M, &out.M
*out = make(map[string]int, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.N != nil {
in, out := &in.N, &out.N
*out = make(map[string]TestType2, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.O != nil {
in, out := &in.O, &out.O
if *in == nil {
*out = nil
} else {
*out = new(TestType2)
**out = **in
}
}
if in.P != nil {
in, out := &in.P, &out.P
*out = make([]TestType2, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestType1.
func (in *TestType1) DeepCopy() *TestType1 {
if in == nil {
return nil
}
out := new(TestType1)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *TestType1) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TestType2) DeepCopyInto(out *TestType2) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestType2.
func (in *TestType2) DeepCopy() *TestType2 {
if in == nil {
return nil
}
out := new(TestType2)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *TestType2) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}

View file

@ -1,29 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["yaml.go"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,46 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package yaml
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/yaml"
)
// yamlSerializer converts YAML passed to the Decoder methods to JSON.
type yamlSerializer struct {
// the nested serializer
runtime.Serializer
}
// yamlSerializer implements Serializer
var _ runtime.Serializer = yamlSerializer{}
// NewDecodingSerializer adds YAML decoding support to a serializer that supports JSON.
func NewDecodingSerializer(jsonSerializer runtime.Serializer) runtime.Serializer {
return &yamlSerializer{jsonSerializer}
}
func (c yamlSerializer) Decode(data []byte, gvk *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
out, err := yaml.ToJSON(data)
if err != nil {
return nil, nil, err
}
data = out
return c.Serializer.Decode(data, gvk, into)
}

View file

@ -1,33 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"types.go",
"zz_generated.deepcopy.go",
],
deps = [
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,19 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:deepcopy-gen=package
package testing

View file

@ -1,215 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testing
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type EmbeddedTest struct {
runtime.TypeMeta
ID string
Object runtime.Object
EmptyObject runtime.Object
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type EmbeddedTestExternal struct {
runtime.TypeMeta `json:",inline"`
ID string `json:"id,omitempty"`
Object runtime.RawExtension `json:"object,omitempty"`
EmptyObject runtime.RawExtension `json:"emptyObject,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ObjectTest struct {
runtime.TypeMeta
ID string
Items []runtime.Object
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ObjectTestExternal struct {
runtime.TypeMeta `yaml:",inline" json:",inline"`
ID string `json:"id,omitempty"`
Items []runtime.RawExtension `json:"items,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type InternalSimple struct {
runtime.TypeMeta `json:",inline"`
TestString string `json:"testString"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExternalSimple struct {
runtime.TypeMeta `json:",inline"`
TestString string `json:"testString"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExtensionA struct {
runtime.TypeMeta `json:",inline"`
TestString string `json:"testString"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExtensionB struct {
runtime.TypeMeta `json:",inline"`
TestString string `json:"testString"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExternalExtensionType struct {
runtime.TypeMeta `json:",inline"`
Extension runtime.RawExtension `json:"extension"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type InternalExtensionType struct {
runtime.TypeMeta `json:",inline"`
Extension runtime.Object `json:"extension"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExternalOptionalExtensionType struct {
runtime.TypeMeta `json:",inline"`
Extension runtime.RawExtension `json:"extension,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type InternalOptionalExtensionType struct {
runtime.TypeMeta `json:",inline"`
Extension runtime.Object `json:"extension,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type InternalComplex struct {
runtime.TypeMeta
String string
Integer int
Integer64 int64
Int64 int64
Bool bool
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExternalComplex struct {
runtime.TypeMeta `json:",inline"`
String string `json:"string" description:"testing"`
Integer int `json:"int"`
Integer64 int64 `json:",omitempty"`
Int64 int64
Bool bool `json:"bool"`
}
// Test a weird version/kind embedding format.
// +k8s:deepcopy-gen=false
type MyWeirdCustomEmbeddedVersionKindField struct {
ID string `json:"ID,omitempty"`
APIVersion string `json:"myVersionKey,omitempty"`
ObjectKind string `json:"myKindKey,omitempty"`
Z string `json:"Z,omitempty"`
Y uint64 `json:"Y,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type TestType1 struct {
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
C int8 `json:"C,omitempty"`
D int16 `json:"D,omitempty"`
E int32 `json:"E,omitempty"`
F int64 `json:"F,omitempty"`
G uint `json:"G,omitempty"`
H uint8 `json:"H,omitempty"`
I uint16 `json:"I,omitempty"`
J uint32 `json:"J,omitempty"`
K uint64 `json:"K,omitempty"`
L bool `json:"L,omitempty"`
M map[string]int `json:"M,omitempty"`
N map[string]TestType2 `json:"N,omitempty"`
O *TestType2 `json:"O,omitempty"`
P []TestType2 `json:"Q,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type TestType2 struct {
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExternalTestType2 struct {
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExternalTestType1 struct {
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
A string `json:"A,omitempty"`
B int `json:"B,omitempty"`
C int8 `json:"C,omitempty"`
D int16 `json:"D,omitempty"`
E int32 `json:"E,omitempty"`
F int64 `json:"F,omitempty"`
G uint `json:"G,omitempty"`
H uint8 `json:"H,omitempty"`
I uint16 `json:"I,omitempty"`
J uint32 `json:"J,omitempty"`
K uint64 `json:"K,omitempty"`
L bool `json:"L,omitempty"`
M map[string]int `json:"M,omitempty"`
N map[string]ExternalTestType2 `json:"N,omitempty"`
O *ExternalTestType2 `json:"O,omitempty"`
P []ExternalTestType2 `json:"Q,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExternalInternalSame struct {
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
A TestType2 `json:"A,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type UnversionedType struct {
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
A string `json:"A,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type UnknownType struct {
MyWeirdCustomEmbeddedVersionKindField `json:",inline"`
A string `json:"A,omitempty"`
}
func (obj *MyWeirdCustomEmbeddedVersionKindField) GetObjectKind() schema.ObjectKind { return obj }
func (obj *MyWeirdCustomEmbeddedVersionKindField) SetGroupVersionKind(gvk schema.GroupVersionKind) {
obj.APIVersion, obj.ObjectKind = gvk.ToAPIVersionAndKind()
}
func (obj *MyWeirdCustomEmbeddedVersionKindField) GroupVersionKind() schema.GroupVersionKind {
return schema.FromAPIVersionAndKind(obj.APIVersion, obj.ObjectKind)
}
func (obj *TestType2) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
func (obj *ExternalTestType2) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }

View file

@ -1,762 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package testing
import (
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
reflect "reflect"
)
// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them.
//
// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented.
func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc {
return []conversion.GeneratedDeepCopyFunc{
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*EmbeddedTest).DeepCopyInto(out.(*EmbeddedTest))
return nil
}, InType: reflect.TypeOf(&EmbeddedTest{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*EmbeddedTestExternal).DeepCopyInto(out.(*EmbeddedTestExternal))
return nil
}, InType: reflect.TypeOf(&EmbeddedTestExternal{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExtensionA).DeepCopyInto(out.(*ExtensionA))
return nil
}, InType: reflect.TypeOf(&ExtensionA{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExtensionB).DeepCopyInto(out.(*ExtensionB))
return nil
}, InType: reflect.TypeOf(&ExtensionB{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExternalComplex).DeepCopyInto(out.(*ExternalComplex))
return nil
}, InType: reflect.TypeOf(&ExternalComplex{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExternalExtensionType).DeepCopyInto(out.(*ExternalExtensionType))
return nil
}, InType: reflect.TypeOf(&ExternalExtensionType{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExternalInternalSame).DeepCopyInto(out.(*ExternalInternalSame))
return nil
}, InType: reflect.TypeOf(&ExternalInternalSame{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExternalOptionalExtensionType).DeepCopyInto(out.(*ExternalOptionalExtensionType))
return nil
}, InType: reflect.TypeOf(&ExternalOptionalExtensionType{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExternalSimple).DeepCopyInto(out.(*ExternalSimple))
return nil
}, InType: reflect.TypeOf(&ExternalSimple{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExternalTestType1).DeepCopyInto(out.(*ExternalTestType1))
return nil
}, InType: reflect.TypeOf(&ExternalTestType1{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ExternalTestType2).DeepCopyInto(out.(*ExternalTestType2))
return nil
}, InType: reflect.TypeOf(&ExternalTestType2{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*InternalComplex).DeepCopyInto(out.(*InternalComplex))
return nil
}, InType: reflect.TypeOf(&InternalComplex{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*InternalExtensionType).DeepCopyInto(out.(*InternalExtensionType))
return nil
}, InType: reflect.TypeOf(&InternalExtensionType{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*InternalOptionalExtensionType).DeepCopyInto(out.(*InternalOptionalExtensionType))
return nil
}, InType: reflect.TypeOf(&InternalOptionalExtensionType{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*InternalSimple).DeepCopyInto(out.(*InternalSimple))
return nil
}, InType: reflect.TypeOf(&InternalSimple{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ObjectTest).DeepCopyInto(out.(*ObjectTest))
return nil
}, InType: reflect.TypeOf(&ObjectTest{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ObjectTestExternal).DeepCopyInto(out.(*ObjectTestExternal))
return nil
}, InType: reflect.TypeOf(&ObjectTestExternal{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*TestType1).DeepCopyInto(out.(*TestType1))
return nil
}, InType: reflect.TypeOf(&TestType1{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*TestType2).DeepCopyInto(out.(*TestType2))
return nil
}, InType: reflect.TypeOf(&TestType2{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*UnknownType).DeepCopyInto(out.(*UnknownType))
return nil
}, InType: reflect.TypeOf(&UnknownType{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*UnversionedType).DeepCopyInto(out.(*UnversionedType))
return nil
}, InType: reflect.TypeOf(&UnversionedType{})},
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EmbeddedTest) DeepCopyInto(out *EmbeddedTest) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Object == nil {
out.Object = nil
} else {
out.Object = in.Object.DeepCopyObject()
}
if in.EmptyObject == nil {
out.EmptyObject = nil
} else {
out.EmptyObject = in.EmptyObject.DeepCopyObject()
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EmbeddedTest.
func (in *EmbeddedTest) DeepCopy() *EmbeddedTest {
if in == nil {
return nil
}
out := new(EmbeddedTest)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *EmbeddedTest) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EmbeddedTestExternal) DeepCopyInto(out *EmbeddedTestExternal) {
*out = *in
out.TypeMeta = in.TypeMeta
in.Object.DeepCopyInto(&out.Object)
in.EmptyObject.DeepCopyInto(&out.EmptyObject)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EmbeddedTestExternal.
func (in *EmbeddedTestExternal) DeepCopy() *EmbeddedTestExternal {
if in == nil {
return nil
}
out := new(EmbeddedTestExternal)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *EmbeddedTestExternal) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExtensionA) DeepCopyInto(out *ExtensionA) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionA.
func (in *ExtensionA) DeepCopy() *ExtensionA {
if in == nil {
return nil
}
out := new(ExtensionA)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExtensionA) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExtensionB) DeepCopyInto(out *ExtensionB) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionB.
func (in *ExtensionB) DeepCopy() *ExtensionB {
if in == nil {
return nil
}
out := new(ExtensionB)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExtensionB) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalComplex) DeepCopyInto(out *ExternalComplex) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalComplex.
func (in *ExternalComplex) DeepCopy() *ExternalComplex {
if in == nil {
return nil
}
out := new(ExternalComplex)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExternalComplex) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalExtensionType) DeepCopyInto(out *ExternalExtensionType) {
*out = *in
out.TypeMeta = in.TypeMeta
in.Extension.DeepCopyInto(&out.Extension)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalExtensionType.
func (in *ExternalExtensionType) DeepCopy() *ExternalExtensionType {
if in == nil {
return nil
}
out := new(ExternalExtensionType)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExternalExtensionType) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalInternalSame) DeepCopyInto(out *ExternalInternalSame) {
*out = *in
out.MyWeirdCustomEmbeddedVersionKindField = in.MyWeirdCustomEmbeddedVersionKindField
out.A = in.A
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalInternalSame.
func (in *ExternalInternalSame) DeepCopy() *ExternalInternalSame {
if in == nil {
return nil
}
out := new(ExternalInternalSame)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExternalInternalSame) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalOptionalExtensionType) DeepCopyInto(out *ExternalOptionalExtensionType) {
*out = *in
out.TypeMeta = in.TypeMeta
in.Extension.DeepCopyInto(&out.Extension)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalOptionalExtensionType.
func (in *ExternalOptionalExtensionType) DeepCopy() *ExternalOptionalExtensionType {
if in == nil {
return nil
}
out := new(ExternalOptionalExtensionType)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExternalOptionalExtensionType) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalSimple) DeepCopyInto(out *ExternalSimple) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSimple.
func (in *ExternalSimple) DeepCopy() *ExternalSimple {
if in == nil {
return nil
}
out := new(ExternalSimple)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExternalSimple) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalTestType1) DeepCopyInto(out *ExternalTestType1) {
*out = *in
out.MyWeirdCustomEmbeddedVersionKindField = in.MyWeirdCustomEmbeddedVersionKindField
if in.M != nil {
in, out := &in.M, &out.M
*out = make(map[string]int, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.N != nil {
in, out := &in.N, &out.N
*out = make(map[string]ExternalTestType2, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.O != nil {
in, out := &in.O, &out.O
if *in == nil {
*out = nil
} else {
*out = new(ExternalTestType2)
**out = **in
}
}
if in.P != nil {
in, out := &in.P, &out.P
*out = make([]ExternalTestType2, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalTestType1.
func (in *ExternalTestType1) DeepCopy() *ExternalTestType1 {
if in == nil {
return nil
}
out := new(ExternalTestType1)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExternalTestType1) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalTestType2) DeepCopyInto(out *ExternalTestType2) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalTestType2.
func (in *ExternalTestType2) DeepCopy() *ExternalTestType2 {
if in == nil {
return nil
}
out := new(ExternalTestType2)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExternalTestType2) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InternalComplex) DeepCopyInto(out *InternalComplex) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InternalComplex.
func (in *InternalComplex) DeepCopy() *InternalComplex {
if in == nil {
return nil
}
out := new(InternalComplex)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *InternalComplex) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InternalExtensionType) DeepCopyInto(out *InternalExtensionType) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Extension == nil {
out.Extension = nil
} else {
out.Extension = in.Extension.DeepCopyObject()
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InternalExtensionType.
func (in *InternalExtensionType) DeepCopy() *InternalExtensionType {
if in == nil {
return nil
}
out := new(InternalExtensionType)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *InternalExtensionType) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InternalOptionalExtensionType) DeepCopyInto(out *InternalOptionalExtensionType) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Extension == nil {
out.Extension = nil
} else {
out.Extension = in.Extension.DeepCopyObject()
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InternalOptionalExtensionType.
func (in *InternalOptionalExtensionType) DeepCopy() *InternalOptionalExtensionType {
if in == nil {
return nil
}
out := new(InternalOptionalExtensionType)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *InternalOptionalExtensionType) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InternalSimple) DeepCopyInto(out *InternalSimple) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InternalSimple.
func (in *InternalSimple) DeepCopy() *InternalSimple {
if in == nil {
return nil
}
out := new(InternalSimple)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *InternalSimple) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ObjectTest) DeepCopyInto(out *ObjectTest) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]runtime.Object, len(*in))
for i := range *in {
if (*in)[i] == nil {
(*out)[i] = nil
} else {
(*out)[i] = (*in)[i].DeepCopyObject()
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectTest.
func (in *ObjectTest) DeepCopy() *ObjectTest {
if in == nil {
return nil
}
out := new(ObjectTest)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ObjectTest) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ObjectTestExternal) DeepCopyInto(out *ObjectTestExternal) {
*out = *in
out.TypeMeta = in.TypeMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]runtime.RawExtension, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectTestExternal.
func (in *ObjectTestExternal) DeepCopy() *ObjectTestExternal {
if in == nil {
return nil
}
out := new(ObjectTestExternal)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ObjectTestExternal) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TestType1) DeepCopyInto(out *TestType1) {
*out = *in
out.MyWeirdCustomEmbeddedVersionKindField = in.MyWeirdCustomEmbeddedVersionKindField
if in.M != nil {
in, out := &in.M, &out.M
*out = make(map[string]int, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.N != nil {
in, out := &in.N, &out.N
*out = make(map[string]TestType2, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.O != nil {
in, out := &in.O, &out.O
if *in == nil {
*out = nil
} else {
*out = new(TestType2)
**out = **in
}
}
if in.P != nil {
in, out := &in.P, &out.P
*out = make([]TestType2, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestType1.
func (in *TestType1) DeepCopy() *TestType1 {
if in == nil {
return nil
}
out := new(TestType1)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *TestType1) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TestType2) DeepCopyInto(out *TestType2) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TestType2.
func (in *TestType2) DeepCopy() *TestType2 {
if in == nil {
return nil
}
out := new(TestType2)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *TestType2) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UnknownType) DeepCopyInto(out *UnknownType) {
*out = *in
out.MyWeirdCustomEmbeddedVersionKindField = in.MyWeirdCustomEmbeddedVersionKindField
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnknownType.
func (in *UnknownType) DeepCopy() *UnknownType {
if in == nil {
return nil
}
out := new(UnknownType)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *UnknownType) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UnversionedType) DeepCopyInto(out *UnversionedType) {
*out = *in
out.MyWeirdCustomEmbeddedVersionKindField = in.MyWeirdCustomEmbeddedVersionKindField
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnversionedType.
func (in *UnversionedType) DeepCopy() *UnversionedType {
if in == nil {
return nil
}
out := new(UnversionedType)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *UnversionedType) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}

View file

@ -1,65 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"api_meta_help_test.go",
"api_meta_meta_test.go",
"apis_meta_v1_unstructed_unstructure_test.go",
"runtime_helper_test.go",
"runtime_serializer_protobuf_protobuf_test.go",
"runtime_unversioned_test.go",
],
library = ":go_default_library",
deps = [
"//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/testing:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer/protobuf:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"util.go",
"zz_generated.deepcopy.go",
],
deps = [
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/testapigroup/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,331 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package test
import (
"reflect"
"testing"
fuzz "github.com/google/gofuzz"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/apis/testapigroup"
"k8s.io/apimachinery/pkg/apis/testapigroup/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"
)
func TestIsList(t *testing.T) {
tests := []struct {
obj runtime.Object
isList bool
}{
{&testapigroup.CarpList{}, true},
{&testapigroup.Carp{}, false},
}
for _, item := range tests {
if e, a := item.isList, meta.IsListType(item.obj); e != a {
t.Errorf("%v: Expected %v, got %v", reflect.TypeOf(item.obj), e, a)
}
}
}
func TestExtractList(t *testing.T) {
list1 := []runtime.Object{
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "1"}},
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "2"}},
}
list2 := &ListV1{
Items: []runtime.RawExtension{
{Raw: []byte("foo")},
{Raw: []byte("bar")},
{Object: &v1.Carp{ObjectMeta: metav1.ObjectMeta{Name: "other"}}},
},
}
list3 := &fakePtrValueList{
Items: []*testapigroup.Carp{
{ObjectMeta: metav1.ObjectMeta{Name: "1"}},
{ObjectMeta: metav1.ObjectMeta{Name: "2"}},
},
}
list4 := &testapigroup.CarpList{
Items: []testapigroup.Carp{
{ObjectMeta: metav1.ObjectMeta{Name: "1"}},
{ObjectMeta: metav1.ObjectMeta{Name: "2"}},
{ObjectMeta: metav1.ObjectMeta{Name: "3"}},
},
}
testCases := []struct {
in runtime.Object
out []interface{}
equal bool
}{
{
in: &List{},
out: []interface{}{},
},
{
in: &ListV1{},
out: []interface{}{},
},
{
in: &List{Items: list1},
out: []interface{}{list1[0], list1[1]},
},
{
in: list2,
out: []interface{}{&runtime.Unknown{Raw: list2.Items[0].Raw}, &runtime.Unknown{Raw: list2.Items[1].Raw}, list2.Items[2].Object},
equal: true,
},
{
in: list3,
out: []interface{}{list3.Items[0], list3.Items[1]},
},
{
in: list4,
out: []interface{}{&list4.Items[0], &list4.Items[1], &list4.Items[2]},
},
}
for i, test := range testCases {
list, err := meta.ExtractList(test.in)
if err != nil {
t.Fatalf("%d: extract: Unexpected error %v", i, err)
}
if e, a := len(test.out), len(list); e != a {
t.Fatalf("%d: extract: Expected %v, got %v", i, e, a)
}
for j, e := range test.out {
if e != list[j] {
if !test.equal {
t.Fatalf("%d: extract: Expected list[%d] to be %#v, but found %#v", i, j, e, list[j])
}
if !reflect.DeepEqual(e, list[j]) {
t.Fatalf("%d: extract: Expected list[%d] to be %#v, but found %#v", i, j, e, list[j])
}
}
}
}
}
func TestEachListItem(t *testing.T) {
list1 := []runtime.Object{
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "1"}},
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "2"}},
}
list2 := &ListV1{
Items: []runtime.RawExtension{
{Raw: []byte("foo")},
{Raw: []byte("bar")},
{Object: &v1.Carp{ObjectMeta: metav1.ObjectMeta{Name: "other"}}},
},
}
list3 := &fakePtrValueList{
Items: []*testapigroup.Carp{
{ObjectMeta: metav1.ObjectMeta{Name: "1"}},
{ObjectMeta: metav1.ObjectMeta{Name: "2"}},
},
}
list4 := &testapigroup.CarpList{
Items: []testapigroup.Carp{
{ObjectMeta: metav1.ObjectMeta{Name: "1"}},
{ObjectMeta: metav1.ObjectMeta{Name: "2"}},
{ObjectMeta: metav1.ObjectMeta{Name: "3"}},
},
}
testCases := []struct {
in runtime.Object
out []interface{}
}{
{
in: &List{},
out: []interface{}{},
},
{
in: &ListV1{},
out: []interface{}{},
},
{
in: &List{Items: list1},
out: []interface{}{list1[0], list1[1]},
},
{
in: list2,
out: []interface{}{nil, nil, list2.Items[2].Object},
},
{
in: list3,
out: []interface{}{list3.Items[0], list3.Items[1]},
},
{
in: list4,
out: []interface{}{&list4.Items[0], &list4.Items[1], &list4.Items[2]},
},
}
for i, test := range testCases {
list := []runtime.Object{}
err := meta.EachListItem(test.in, func(obj runtime.Object) error {
list = append(list, obj)
return nil
})
if err != nil {
t.Fatalf("%d: each: Unexpected error %v", i, err)
}
if e, a := len(test.out), len(list); e != a {
t.Fatalf("%d: each: Expected %v, got %v", i, e, a)
}
for j, e := range test.out {
if e != list[j] {
t.Fatalf("%d: each: Expected list[%d] to be %#v, but found %#v", i, j, e, list[j])
}
}
}
}
type fakePtrInterfaceList struct {
Items *[]runtime.Object
}
func (obj fakePtrInterfaceList) GetObjectKind() schema.ObjectKind {
return schema.EmptyObjectKind
}
func (obj fakePtrInterfaceList) DeepCopyObject() runtime.Object {
panic("fakePtrInterfaceList does not support DeepCopy")
}
func TestExtractListOfInterfacePtrs(t *testing.T) {
pl := &fakePtrInterfaceList{
Items: &[]runtime.Object{},
}
list, err := meta.ExtractList(pl)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if len(list) > 0 {
t.Fatalf("Expected empty list, got %#v", list)
}
}
type fakePtrValueList struct {
Items []*testapigroup.Carp
}
func (obj fakePtrValueList) GetObjectKind() schema.ObjectKind {
return schema.EmptyObjectKind
}
func (obj *fakePtrValueList) DeepCopyObject() runtime.Object {
if obj == nil {
return nil
}
clone := fakePtrValueList{
Items: make([]*testapigroup.Carp, len(obj.Items)),
}
for i, carp := range obj.Items {
clone.Items[i] = carp.DeepCopy()
}
return &clone
}
func TestSetList(t *testing.T) {
pl := &testapigroup.CarpList{}
list := []runtime.Object{
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "1"}},
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "2"}},
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "3"}},
}
err := meta.SetList(pl, list)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if e, a := list[i].(*testapigroup.Carp).Name, pl.Items[i].Name; e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
}
}
func TestSetListToRuntimeObjectArray(t *testing.T) {
pl := &List{}
list := []runtime.Object{
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "1"}},
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "2"}},
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "3"}},
}
err := meta.SetList(pl, list)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if e, a := list[i], pl.Items[i]; e != a {
t.Fatalf("%d: unmatched: %s", i, diff.ObjectDiff(e, a))
}
}
}
func TestSetListToMatchingType(t *testing.T) {
pl := &unstructured.UnstructuredList{}
list := []runtime.Object{
&unstructured.Unstructured{Object: map[string]interface{}{"foo": 1}},
&unstructured.Unstructured{Object: map[string]interface{}{"foo": 2}},
&unstructured.Unstructured{Object: map[string]interface{}{"foo": 3}},
}
err := meta.SetList(pl, list)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}
if e, a := len(list), len(pl.Items); e != a {
t.Fatalf("Expected %v, got %v", e, a)
}
for i := range list {
if e, a := list[i], &pl.Items[i]; !reflect.DeepEqual(e, a) {
t.Fatalf("%d: unmatched: %s", i, diff.ObjectDiff(e, a))
}
}
}
func TestSetExtractListRoundTrip(t *testing.T) {
fuzzer := fuzz.New().NilChance(0).NumElements(1, 5)
for i := 0; i < 5; i++ {
start := &testapigroup.CarpList{}
fuzzer.Fuzz(&start.Items)
list, err := meta.ExtractList(start)
if err != nil {
t.Errorf("Unexpected error %v", err)
continue
}
got := &testapigroup.CarpList{}
err = meta.SetList(got, list)
if err != nil {
t.Errorf("Unexpected error %v", err)
continue
}
if e, a := start, got; !reflect.DeepEqual(e, a) {
t.Fatalf("Expected %#v, got %#v", e, a)
}
}
}

View file

@ -1,429 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package test
import (
"reflect"
"testing"
"github.com/google/gofuzz"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/testapigroup"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
)
func TestAPIObjectMeta(t *testing.T) {
j := &testapigroup.Carp{
TypeMeta: metav1.TypeMeta{APIVersion: "/a", Kind: "b"},
ObjectMeta: metav1.ObjectMeta{
Namespace: "bar",
Name: "foo",
GenerateName: "prefix",
UID: "uid",
ResourceVersion: "1",
SelfLink: "some/place/only/we/know",
Labels: map[string]string{"foo": "bar"},
Annotations: map[string]string{"x": "y"},
Finalizers: []string{
"finalizer.1",
"finalizer.2",
},
},
}
var _ metav1.Object = &j.ObjectMeta
var _ metav1.ObjectMetaAccessor = j
accessor, err := meta.Accessor(j)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if accessor != metav1.Object(j) {
t.Fatalf("should have returned the same pointer: %#v\n\n%#v", accessor, j)
}
if e, a := "bar", accessor.GetNamespace(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "foo", accessor.GetName(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "prefix", accessor.GetGenerateName(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "uid", string(accessor.GetUID()); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "1", accessor.GetResourceVersion(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "some/place/only/we/know", accessor.GetSelfLink(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := []string{"finalizer.1", "finalizer.2"}, accessor.GetFinalizers(); !reflect.DeepEqual(e, a) {
t.Errorf("expected %v, got %v", e, a)
}
typeAccessor, err := meta.TypeAccessor(j)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if e, a := "a", typeAccessor.GetAPIVersion(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "b", typeAccessor.GetKind(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
accessor.SetNamespace("baz")
accessor.SetName("bar")
accessor.SetGenerateName("generate")
accessor.SetUID("other")
typeAccessor.SetAPIVersion("c")
typeAccessor.SetKind("d")
accessor.SetResourceVersion("2")
accessor.SetSelfLink("google.com")
accessor.SetFinalizers([]string{"finalizer.3"})
// Prove that accessor changes the original object.
if e, a := "baz", j.Namespace; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "bar", j.Name; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "generate", j.GenerateName; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := types.UID("other"), j.UID; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "c", j.APIVersion; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "d", j.Kind; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "2", j.ResourceVersion; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "google.com", j.SelfLink; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := []string{"finalizer.3"}, j.Finalizers; !reflect.DeepEqual(e, a) {
t.Errorf("expected %v, got %v", e, a)
}
typeAccessor.SetAPIVersion("d")
typeAccessor.SetKind("e")
if e, a := "d", j.APIVersion; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "e", j.Kind; e != a {
t.Errorf("expected %v, got %v", e, a)
}
}
func TestGenericTypeMeta(t *testing.T) {
type TypeMeta struct {
Kind string `json:"kind,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
GenerateName string `json:"generateName,omitempty"`
UID string `json:"uid,omitempty"`
CreationTimestamp metav1.Time `json:"creationTimestamp,omitempty"`
SelfLink string `json:"selfLink,omitempty"`
ResourceVersion string `json:"resourceVersion,omitempty"`
APIVersion string `json:"apiVersion,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
OwnerReferences []metav1.OwnerReference `json:"ownerReferences,omitempty"`
Finalizers []string `json:"finalizers,omitempty"`
}
j := struct{ TypeMeta }{TypeMeta{APIVersion: "a", Kind: "b"}}
typeAccessor, err := meta.TypeAccessor(&j)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if e, a := "a", typeAccessor.GetAPIVersion(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "b", typeAccessor.GetKind(); e != a {
t.Errorf("expected %v, got %v", e, a)
}
typeAccessor.SetAPIVersion("c")
typeAccessor.SetKind("d")
if e, a := "c", j.APIVersion; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "d", j.Kind; e != a {
t.Errorf("expected %v, got %v", e, a)
}
typeAccessor.SetAPIVersion("d")
typeAccessor.SetKind("e")
if e, a := "d", j.APIVersion; e != a {
t.Errorf("expected %v, got %v", e, a)
}
if e, a := "e", j.Kind; e != a {
t.Errorf("expected %v, got %v", e, a)
}
}
type InternalTypeMeta struct {
Kind string `json:"kind,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
GenerateName string `json:"generateName,omitempty"`
UID string `json:"uid,omitempty"`
CreationTimestamp metav1.Time `json:"creationTimestamp,omitempty"`
SelfLink string `json:"selfLink,omitempty"`
ResourceVersion string `json:"resourceVersion,omitempty"`
Continue string `json:"next,omitempty"`
APIVersion string `json:"apiVersion,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
Finalizers []string `json:"finalizers,omitempty"`
OwnerReferences []metav1.OwnerReference `json:"ownerReferences,omitempty"`
}
func (m *InternalTypeMeta) GetResourceVersion() string { return m.ResourceVersion }
func (m *InternalTypeMeta) SetResourceVersion(rv string) { m.ResourceVersion = rv }
func (m *InternalTypeMeta) GetSelfLink() string { return m.SelfLink }
func (m *InternalTypeMeta) SetSelfLink(link string) { m.SelfLink = link }
func (m *InternalTypeMeta) GetContinue() string { return m.Continue }
func (m *InternalTypeMeta) SetContinue(c string) { m.Continue = c }
type MyAPIObject struct {
TypeMeta InternalTypeMeta `json:",inline"`
}
func (obj *MyAPIObject) GetListMeta() metav1.ListInterface { return &obj.TypeMeta }
func (obj *MyAPIObject) GetObjectKind() schema.ObjectKind { return obj }
func (obj *MyAPIObject) SetGroupVersionKind(gvk schema.GroupVersionKind) {
obj.TypeMeta.APIVersion, obj.TypeMeta.Kind = gvk.ToAPIVersionAndKind()
}
func (obj *MyAPIObject) GroupVersionKind() schema.GroupVersionKind {
return schema.FromAPIVersionAndKind(obj.TypeMeta.APIVersion, obj.TypeMeta.Kind)
}
func (obj *MyAPIObject) DeepCopyObject() runtime.Object {
panic("MyAPIObject does not support DeepCopy")
}
type MyIncorrectlyMarkedAsAPIObject struct{}
func (obj *MyIncorrectlyMarkedAsAPIObject) GetObjectKind() schema.ObjectKind {
return schema.EmptyObjectKind
}
func (obj *MyIncorrectlyMarkedAsAPIObject) DeepCopyObject() runtime.Object {
panic("MyIncorrectlyMarkedAsAPIObject does not support DeepCopy")
}
func TestResourceVersionerOfAPI(t *testing.T) {
type T struct {
runtime.Object
Expected string
}
testCases := map[string]T{
"empty api object": {&MyAPIObject{}, ""},
"api object with version": {&MyAPIObject{TypeMeta: InternalTypeMeta{ResourceVersion: "1"}}, "1"},
"pointer to api object with version": {&MyAPIObject{TypeMeta: InternalTypeMeta{ResourceVersion: "1"}}, "1"},
}
versioning := meta.NewAccessor()
for key, testCase := range testCases {
actual, err := versioning.ResourceVersion(testCase.Object)
if err != nil {
t.Errorf("%s: unexpected error %#v", key, err)
}
if actual != testCase.Expected {
t.Errorf("%s: expected %v, got %v", key, testCase.Expected, actual)
}
}
failingCases := map[string]struct {
runtime.Object
Expected string
}{
"not a valid object to try": {&MyIncorrectlyMarkedAsAPIObject{}, "1"},
}
for key, testCase := range failingCases {
_, err := versioning.ResourceVersion(testCase.Object)
if err == nil {
t.Errorf("%s: expected error, got nil", key)
}
}
setCases := map[string]struct {
runtime.Object
Expected string
}{
"pointer to api object with version": {&MyAPIObject{TypeMeta: InternalTypeMeta{ResourceVersion: "1"}}, "1"},
}
for key, testCase := range setCases {
if err := versioning.SetResourceVersion(testCase.Object, "5"); err != nil {
t.Errorf("%s: unexpected error %#v", key, err)
}
actual, err := versioning.ResourceVersion(testCase.Object)
if err != nil {
t.Errorf("%s: unexpected error %#v", key, err)
}
if actual != "5" {
t.Errorf("%s: expected %v, got %v", key, "5", actual)
}
}
}
func TestTypeMetaSelfLinker(t *testing.T) {
table := map[string]struct {
obj runtime.Object
expect string
try string
succeed bool
}{
"normal": {
obj: &MyAPIObject{TypeMeta: InternalTypeMeta{SelfLink: "foobar"}},
expect: "foobar",
try: "newbar",
succeed: true,
},
"fail": {
obj: &MyIncorrectlyMarkedAsAPIObject{},
succeed: false,
},
}
linker := runtime.SelfLinker(meta.NewAccessor())
for name, item := range table {
got, err := linker.SelfLink(item.obj)
if e, a := item.succeed, err == nil; e != a {
t.Errorf("%v: expected %v, got %v", name, e, a)
}
if e, a := item.expect, got; item.succeed && e != a {
t.Errorf("%v: expected %v, got %v", name, e, a)
}
err = linker.SetSelfLink(item.obj, item.try)
if e, a := item.succeed, err == nil; e != a {
t.Errorf("%v: expected %v, got %v", name, e, a)
}
if item.succeed {
got, err := linker.SelfLink(item.obj)
if err != nil {
t.Errorf("%v: expected no err, got %v", name, err)
}
if e, a := item.try, got; e != a {
t.Errorf("%v: expected %v, got %v", name, e, a)
}
}
}
}
type MyAPIObject2 struct {
metav1.TypeMeta
metav1.ObjectMeta
}
func getObjectMetaAndOwnerReferences() (myAPIObject2 MyAPIObject2, metaOwnerReferences []metav1.OwnerReference) {
fuzz.New().NilChance(.5).NumElements(1, 5).Fuzz(&myAPIObject2)
references := myAPIObject2.ObjectMeta.OwnerReferences
// This is necessary for the test to pass because the getter will return a
// non-nil slice.
metaOwnerReferences = make([]metav1.OwnerReference, 0)
for i := 0; i < len(references); i++ {
metaOwnerReferences = append(metaOwnerReferences, metav1.OwnerReference{
Kind: references[i].Kind,
Name: references[i].Name,
UID: references[i].UID,
APIVersion: references[i].APIVersion,
Controller: references[i].Controller,
BlockOwnerDeletion: references[i].BlockOwnerDeletion,
})
}
if len(references) == 0 {
// This is necessary for the test to pass because the setter will make a
// non-nil slice.
myAPIObject2.ObjectMeta.OwnerReferences = make([]metav1.OwnerReference, 0)
}
return myAPIObject2, metaOwnerReferences
}
func testGetOwnerReferences(t *testing.T) {
obj, expected := getObjectMetaAndOwnerReferences()
accessor, err := meta.Accessor(&obj)
if err != nil {
t.Error(err)
}
references := accessor.GetOwnerReferences()
if !reflect.DeepEqual(references, expected) {
t.Errorf("expect %#v\n got %#v", expected, references)
}
}
func testSetOwnerReferences(t *testing.T) {
expected, references := getObjectMetaAndOwnerReferences()
obj := MyAPIObject2{}
accessor, err := meta.Accessor(&obj)
if err != nil {
t.Error(err)
}
accessor.SetOwnerReferences(references)
if e, a := expected.ObjectMeta.OwnerReferences, obj.ObjectMeta.OwnerReferences; !reflect.DeepEqual(e, a) {
t.Errorf("expect %#v\n got %#v", e, a)
}
}
func TestAccessOwnerReferences(t *testing.T) {
fuzzIter := 5
for i := 0; i < fuzzIter; i++ {
testGetOwnerReferences(t)
testSetOwnerReferences(t)
}
}
// BenchmarkAccessorSetFastPath shows the interface fast path
func BenchmarkAccessorSetFastPath(b *testing.B) {
obj := &testapigroup.Carp{
TypeMeta: metav1.TypeMeta{APIVersion: "/a", Kind: "b"},
ObjectMeta: metav1.ObjectMeta{
Namespace: "bar",
Name: "foo",
GenerateName: "prefix",
UID: "uid",
ResourceVersion: "1",
SelfLink: "some/place/only/we/know",
Labels: map[string]string{"foo": "bar"},
Annotations: map[string]string{"x": "y"},
},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
acc, err := meta.Accessor(obj)
if err != nil {
b.Fatal(err)
}
acc.SetNamespace("something")
}
b.StopTimer()
}

View file

@ -1,570 +0,0 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package test
import (
"fmt"
"reflect"
"strconv"
"strings"
"testing"
"time"
apitesting "k8s.io/apimachinery/pkg/api/testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/apis/testapigroup"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
)
func TestDecodeUnstructured(t *testing.T) {
groupVersionString := "v1"
rawJson := fmt.Sprintf(`{"kind":"Pod","apiVersion":"%s","metadata":{"name":"test"}}`, groupVersionString)
pl := &List{
Items: []runtime.Object{
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "1"}},
&runtime.Unknown{
TypeMeta: runtime.TypeMeta{Kind: "Pod", APIVersion: groupVersionString},
Raw: []byte(rawJson),
ContentType: runtime.ContentTypeJSON,
},
&runtime.Unknown{
TypeMeta: runtime.TypeMeta{Kind: "", APIVersion: groupVersionString},
Raw: []byte(rawJson),
ContentType: runtime.ContentTypeJSON,
},
&unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "Foo",
"apiVersion": "Bar",
"test": "value",
},
},
},
}
if errs := runtime.DecodeList(pl.Items, unstructured.UnstructuredJSONScheme); len(errs) == 1 {
t.Fatalf("unexpected error %v", errs)
}
if pod, ok := pl.Items[1].(*unstructured.Unstructured); !ok || pod.Object["kind"] != "Pod" || pod.Object["metadata"].(map[string]interface{})["name"] != "test" {
t.Errorf("object not converted: %#v", pl.Items[1])
}
if pod, ok := pl.Items[2].(*unstructured.Unstructured); !ok || pod.Object["kind"] != "Pod" || pod.Object["metadata"].(map[string]interface{})["name"] != "test" {
t.Errorf("object not converted: %#v", pl.Items[2])
}
}
func TestDecode(t *testing.T) {
tcs := []struct {
json []byte
want runtime.Object
}{
{
json: []byte(`{"apiVersion": "test", "kind": "test_kind"}`),
want: &unstructured.Unstructured{
Object: map[string]interface{}{"apiVersion": "test", "kind": "test_kind"},
},
},
{
json: []byte(`{"apiVersion": "test", "kind": "test_list", "items": []}`),
want: &unstructured.UnstructuredList{
Object: map[string]interface{}{"apiVersion": "test", "kind": "test_list"},
},
},
{
json: []byte(`{"items": [{"metadata": {"name": "object1", "deletionGracePeriodSeconds": 10}, "apiVersion": "test", "kind": "test_kind"}, {"metadata": {"name": "object2"}, "apiVersion": "test", "kind": "test_kind"}], "apiVersion": "test", "kind": "test_list"}`),
want: &unstructured.UnstructuredList{
Object: map[string]interface{}{"apiVersion": "test", "kind": "test_list"},
Items: []unstructured.Unstructured{
{
Object: map[string]interface{}{
"metadata": map[string]interface{}{"name": "object1", "deletionGracePeriodSeconds": int64(10)},
"apiVersion": "test",
"kind": "test_kind",
},
},
{
Object: map[string]interface{}{
"metadata": map[string]interface{}{"name": "object2"},
"apiVersion": "test",
"kind": "test_kind",
},
},
},
},
},
}
for _, tc := range tcs {
got, _, err := unstructured.UnstructuredJSONScheme.Decode(tc.json, nil, nil)
if err != nil {
t.Errorf("Unexpected error for %q: %v", string(tc.json), err)
continue
}
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("Decode(%q) want: %v\ngot: %v", string(tc.json), tc.want, got)
}
}
}
func TestUnstructuredGetters(t *testing.T) {
trueVar := true
ten := int64(10)
unstruct := unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "test_kind",
"apiVersion": "test_version",
"metadata": map[string]interface{}{
"name": "test_name",
"namespace": "test_namespace",
"generateName": "test_generateName",
"uid": "test_uid",
"resourceVersion": "test_resourceVersion",
"generation": ten,
"deletionGracePeriodSeconds": ten,
"selfLink": "test_selfLink",
"creationTimestamp": "2009-11-10T23:00:00Z",
"deletionTimestamp": "2010-11-10T23:00:00Z",
"labels": map[string]interface{}{
"test_label": "test_value",
},
"annotations": map[string]interface{}{
"test_annotation": "test_value",
},
"ownerReferences": []map[string]interface{}{
{
"kind": "Pod",
"name": "poda",
"apiVersion": "v1",
"uid": "1",
},
{
"kind": "Pod",
"name": "podb",
"apiVersion": "v1",
"uid": "2",
// though these fields are of type *bool, but when
// decoded from JSON, they are unmarshalled as bool.
"controller": true,
"blockOwnerDeletion": true,
},
},
"finalizers": []interface{}{
"finalizer.1",
"finalizer.2",
},
"clusterName": "cluster123",
},
},
}
if got, want := unstruct.GetAPIVersion(), "test_version"; got != want {
t.Errorf("GetAPIVersions() = %s, want %s", got, want)
}
if got, want := unstruct.GetKind(), "test_kind"; got != want {
t.Errorf("GetKind() = %s, want %s", got, want)
}
if got, want := unstruct.GetNamespace(), "test_namespace"; got != want {
t.Errorf("GetNamespace() = %s, want %s", got, want)
}
if got, want := unstruct.GetName(), "test_name"; got != want {
t.Errorf("GetName() = %s, want %s", got, want)
}
if got, want := unstruct.GetGenerateName(), "test_generateName"; got != want {
t.Errorf("GetGenerateName() = %s, want %s", got, want)
}
if got, want := unstruct.GetUID(), types.UID("test_uid"); got != want {
t.Errorf("GetUID() = %s, want %s", got, want)
}
if got, want := unstruct.GetResourceVersion(), "test_resourceVersion"; got != want {
t.Errorf("GetResourceVersion() = %s, want %s", got, want)
}
if got, want := unstruct.GetSelfLink(), "test_selfLink"; got != want {
t.Errorf("GetSelfLink() = %s, want %s", got, want)
}
if got, want := unstruct.GetCreationTimestamp(), metav1.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC); !got.Equal(&want) {
t.Errorf("GetCreationTimestamp() = %s, want %s", got, want)
}
if got, want := unstruct.GetDeletionTimestamp(), metav1.Date(2010, time.November, 10, 23, 0, 0, 0, time.UTC); got == nil || !got.Equal(&want) {
t.Errorf("GetDeletionTimestamp() = %s, want %s", got, want)
}
if got, want := unstruct.GetLabels(), map[string]string{"test_label": "test_value"}; !reflect.DeepEqual(got, want) {
t.Errorf("GetLabels() = %s, want %s", got, want)
}
if got, want := unstruct.GetAnnotations(), map[string]string{"test_annotation": "test_value"}; !reflect.DeepEqual(got, want) {
t.Errorf("GetAnnotations() = %s, want %s", got, want)
}
refs := unstruct.GetOwnerReferences()
expectedOwnerReferences := []metav1.OwnerReference{
{
Kind: "Pod",
Name: "poda",
APIVersion: "v1",
UID: "1",
},
{
Kind: "Pod",
Name: "podb",
APIVersion: "v1",
UID: "2",
Controller: &trueVar,
BlockOwnerDeletion: &trueVar,
},
}
if got, want := refs, expectedOwnerReferences; !reflect.DeepEqual(got, want) {
t.Errorf("GetOwnerReferences()=%v, want %v", got, want)
}
if got, want := unstruct.GetFinalizers(), []string{"finalizer.1", "finalizer.2"}; !reflect.DeepEqual(got, want) {
t.Errorf("GetFinalizers()=%v, want %v", got, want)
}
if got, want := unstruct.GetClusterName(), "cluster123"; got != want {
t.Errorf("GetClusterName()=%v, want %v", got, want)
}
if got, want := unstruct.GetDeletionGracePeriodSeconds(), &ten; !reflect.DeepEqual(got, want) {
t.Errorf("GetDeletionGracePeriodSeconds()=%v, want %v", got, want)
}
if got, want := unstruct.GetGeneration(), ten; !reflect.DeepEqual(got, want) {
t.Errorf("GetGeneration()=%v, want %v", got, want)
}
}
func TestUnstructuredSetters(t *testing.T) {
unstruct := unstructured.Unstructured{}
trueVar := true
ten := int64(10)
want := unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "test_kind",
"apiVersion": "test_version",
"metadata": map[string]interface{}{
"name": "test_name",
"namespace": "test_namespace",
"generateName": "test_generateName",
"uid": "test_uid",
"resourceVersion": "test_resourceVersion",
"selfLink": "test_selfLink",
"creationTimestamp": "2009-11-10T23:00:00Z",
"deletionTimestamp": "2010-11-10T23:00:00Z",
"deletionGracePeriodSeconds": &ten,
"generation": ten,
"labels": map[string]interface{}{
"test_label": "test_value",
},
"annotations": map[string]interface{}{
"test_annotation": "test_value",
},
"ownerReferences": []map[string]interface{}{
{
"kind": "Pod",
"name": "poda",
"apiVersion": "v1",
"uid": "1",
},
{
"kind": "Pod",
"name": "podb",
"apiVersion": "v1",
"uid": "2",
"controller": true,
"blockOwnerDeletion": true,
},
},
"finalizers": []interface{}{
"finalizer.1",
"finalizer.2",
},
"clusterName": "cluster123",
},
},
}
unstruct.SetAPIVersion("test_version")
unstruct.SetKind("test_kind")
unstruct.SetNamespace("test_namespace")
unstruct.SetName("test_name")
unstruct.SetGenerateName("test_generateName")
unstruct.SetUID(types.UID("test_uid"))
unstruct.SetResourceVersion("test_resourceVersion")
unstruct.SetSelfLink("test_selfLink")
unstruct.SetCreationTimestamp(metav1.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC))
date := metav1.Date(2010, time.November, 10, 23, 0, 0, 0, time.UTC)
unstruct.SetDeletionTimestamp(&date)
unstruct.SetLabels(map[string]string{"test_label": "test_value"})
unstruct.SetAnnotations(map[string]string{"test_annotation": "test_value"})
newOwnerReferences := []metav1.OwnerReference{
{
Kind: "Pod",
Name: "poda",
APIVersion: "v1",
UID: "1",
},
{
Kind: "Pod",
Name: "podb",
APIVersion: "v1",
UID: "2",
Controller: &trueVar,
BlockOwnerDeletion: &trueVar,
},
}
unstruct.SetOwnerReferences(newOwnerReferences)
unstruct.SetFinalizers([]string{"finalizer.1", "finalizer.2"})
unstruct.SetClusterName("cluster123")
unstruct.SetDeletionGracePeriodSeconds(&ten)
unstruct.SetGeneration(ten)
if !reflect.DeepEqual(unstruct, want) {
t.Errorf("Wanted: \n%s\n Got:\n%s", want, unstruct)
}
}
func TestOwnerReferences(t *testing.T) {
t.Parallel()
trueVar := true
falseVar := false
refs := []metav1.OwnerReference{
{
APIVersion: "v2",
Kind: "K2",
Name: "n2",
UID: types.UID("abc1"),
},
{
APIVersion: "v1",
Kind: "K1",
Name: "n1",
UID: types.UID("abc2"),
Controller: &trueVar,
BlockOwnerDeletion: &falseVar,
},
{
APIVersion: "v3",
Kind: "K3",
Name: "n3",
UID: types.UID("abc3"),
Controller: &falseVar,
BlockOwnerDeletion: &trueVar,
},
}
for i, ref := range refs {
ref := ref
t.Run(strconv.Itoa(i), func(t *testing.T) {
t.Parallel()
u1 := unstructured.Unstructured{
Object: make(map[string]interface{}),
}
refsX := []metav1.OwnerReference{ref}
u1.SetOwnerReferences(refsX)
have := u1.GetOwnerReferences()
if !reflect.DeepEqual(have, refsX) {
t.Errorf("Object references are not the same: %#v != %#v", have, refsX)
}
})
}
}
func TestUnstructuredListGetters(t *testing.T) {
unstruct := unstructured.UnstructuredList{
Object: map[string]interface{}{
"kind": "test_kind",
"apiVersion": "test_version",
"metadata": map[string]interface{}{
"resourceVersion": "test_resourceVersion",
"selfLink": "test_selfLink",
},
},
}
if got, want := unstruct.GetAPIVersion(), "test_version"; got != want {
t.Errorf("GetAPIVersions() = %s, want %s", got, want)
}
if got, want := unstruct.GetKind(), "test_kind"; got != want {
t.Errorf("GetKind() = %s, want %s", got, want)
}
if got, want := unstruct.GetResourceVersion(), "test_resourceVersion"; got != want {
t.Errorf("GetResourceVersion() = %s, want %s", got, want)
}
if got, want := unstruct.GetSelfLink(), "test_selfLink"; got != want {
t.Errorf("GetSelfLink() = %s, want %s", got, want)
}
}
func TestUnstructuredListSetters(t *testing.T) {
unstruct := unstructured.UnstructuredList{}
want := unstructured.UnstructuredList{
Object: map[string]interface{}{
"kind": "test_kind",
"apiVersion": "test_version",
"metadata": map[string]interface{}{
"resourceVersion": "test_resourceVersion",
"selfLink": "test_selfLink",
},
},
}
unstruct.SetAPIVersion("test_version")
unstruct.SetKind("test_kind")
unstruct.SetResourceVersion("test_resourceVersion")
unstruct.SetSelfLink("test_selfLink")
if !reflect.DeepEqual(unstruct, want) {
t.Errorf("Wanted: \n%s\n Got:\n%s", unstruct, want)
}
}
func TestDecodeNumbers(t *testing.T) {
// Start with a valid pod
originalJSON := []byte(`{
"kind":"Carp",
"apiVersion":"v1",
"metadata":{"name":"pod","namespace":"foo"},
"spec":{
"containers":[{"name":"container","image":"container"}],
"activeDeadlineSeconds":1000030003
}
}`)
pod := &testapigroup.Carp{}
_, codecs := TestScheme()
codec := apitesting.TestCodec(codecs, schema.GroupVersion{Group: "", Version: runtime.APIVersionInternal})
err := runtime.DecodeInto(codec, originalJSON, pod)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// Round-trip with unstructured codec
unstructuredObj, err := runtime.Decode(unstructured.UnstructuredJSONScheme, originalJSON)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
roundtripJSON, err := runtime.Encode(unstructured.UnstructuredJSONScheme, unstructuredObj)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// Make sure we serialize back out in int form
if !strings.Contains(string(roundtripJSON), `"activeDeadlineSeconds":1000030003`) {
t.Errorf("Expected %s, got %s", `"activeDeadlineSeconds":1000030003`, string(roundtripJSON))
}
// Decode with structured codec again
obj2, err := runtime.Decode(codec, roundtripJSON)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
// ensure pod is still valid
pod2, ok := obj2.(*testapigroup.Carp)
if !ok {
t.Fatalf("expected an *api.Pod, got %#v", obj2)
}
// ensure round-trip preserved large integers
if !reflect.DeepEqual(pod, pod2) {
t.Fatalf("Expected\n\t%#v, got \n\t%#v", pod, pod2)
}
}
// TestAccessorMethods does opaque roundtrip testing against an Unstructured
// instance's Object methods to ensure that what is "Set" matches what you
// subsequently "Get" without any assertions against internal state.
func TestAccessorMethods(t *testing.T) {
int64p := func(i int) *int64 {
v := int64(i)
return &v
}
tests := []struct {
accessor string
val interface{}
nilVal reflect.Value
}{
{accessor: "Namespace", val: "foo"},
{accessor: "Name", val: "bar"},
{accessor: "GenerateName", val: "baz"},
{accessor: "UID", val: types.UID("uid")},
{accessor: "ResourceVersion", val: "1"},
{accessor: "Generation", val: int64(5)},
{accessor: "SelfLink", val: "/foo"},
// TODO: Handle timestamps, which are being marshalled as UTC and
// unmarshalled as Local.
// https://github.com/kubernetes/kubernetes/issues/21402
// {accessor: "CreationTimestamp", val: someTime},
// {accessor: "DeletionTimestamp", val: someTimeP},
{accessor: "DeletionTimestamp", nilVal: reflect.ValueOf((*metav1.Time)(nil))},
{accessor: "DeletionGracePeriodSeconds", val: int64p(10)},
{accessor: "DeletionGracePeriodSeconds", val: int64p(0)},
{accessor: "DeletionGracePeriodSeconds", nilVal: reflect.ValueOf((*int64)(nil))},
{accessor: "Labels", val: map[string]string{"foo": "bar"}},
{accessor: "Annotations", val: map[string]string{"foo": "bar"}},
{accessor: "Initializers", val: &metav1.Initializers{Pending: []metav1.Initializer{{Name: "foo"}}}},
{accessor: "Initializers", val: &metav1.Initializers{}},
{accessor: "Initializers", nilVal: reflect.ValueOf((*metav1.Initializers)(nil))},
{accessor: "Finalizers", val: []string{"foo"}},
{accessor: "OwnerReferences", val: []metav1.OwnerReference{{Name: "foo"}}},
{accessor: "ClusterName", val: "foo"},
}
for i, test := range tests {
t.Logf("evaluating test %d (%s)", i, test.accessor)
u := &unstructured.Unstructured{}
setter := reflect.ValueOf(u).MethodByName("Set" + test.accessor)
getter := reflect.ValueOf(u).MethodByName("Get" + test.accessor)
args := []reflect.Value{}
if test.val != nil {
args = append(args, reflect.ValueOf(test.val))
} else {
args = append(args, test.nilVal)
}
setter.Call(args)
ret := getter.Call([]reflect.Value{})
actual := ret[0].Interface()
var expected interface{}
if test.val != nil {
expected = test.val
} else {
expected = test.nilVal.Interface()
}
if e, a := expected, actual; !reflect.DeepEqual(e, a) {
t.Fatalf("%s: expected %v (%T), got %v (%T)", test.accessor, e, e, a, a)
}
}
}

View file

@ -1,49 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package test
import (
"testing"
apitesting "k8s.io/apimachinery/pkg/api/testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/testapigroup"
"k8s.io/apimachinery/pkg/runtime"
)
func TestDecodeList(t *testing.T) {
pl := List{
Items: []runtime.Object{
&testapigroup.Carp{ObjectMeta: metav1.ObjectMeta{Name: "1"}},
&runtime.Unknown{
TypeMeta: runtime.TypeMeta{Kind: "Carp", APIVersion: "v1"},
Raw: []byte(`{"kind":"Carp","apiVersion":"` + "v1" + `","metadata":{"name":"test"}}`),
ContentType: runtime.ContentTypeJSON,
},
},
}
_, codecs := TestScheme()
Codec := apitesting.TestCodec(codecs, testapigroup.SchemeGroupVersion)
if errs := runtime.DecodeList(pl.Items, Codec); len(errs) != 0 {
t.Fatalf("unexpected error %v", errs)
}
if pod, ok := pl.Items[1].(*testapigroup.Carp); !ok || pod.Name != "test" {
t.Errorf("object not converted: %#v", pl.Items[1])
}
}

View file

@ -1,360 +0,0 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package test
import (
"bytes"
"encoding/hex"
"fmt"
"reflect"
"strings"
"testing"
apiequality "k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/testapigroup/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
"k8s.io/apimachinery/pkg/util/diff"
)
type testObject struct {
gvk schema.GroupVersionKind
}
func (d *testObject) GetObjectKind() schema.ObjectKind { return d }
func (d *testObject) SetGroupVersionKind(gvk schema.GroupVersionKind) { d.gvk = gvk }
func (d *testObject) GroupVersionKind() schema.GroupVersionKind { return d.gvk }
func (d *testObject) DeepCopyObject() runtime.Object {
panic("testObject does not support DeepCopy")
}
type testMarshalable struct {
testObject
data []byte
err error
}
func (d *testMarshalable) Marshal() ([]byte, error) {
return d.data, d.err
}
func (d *testMarshalable) DeepCopyObject() runtime.Object {
panic("testMarshalable does not support DeepCopy")
}
type testBufferedMarshalable struct {
testObject
data []byte
err error
}
func (d *testBufferedMarshalable) Marshal() ([]byte, error) {
return nil, fmt.Errorf("not invokable")
}
func (d *testBufferedMarshalable) MarshalTo(data []byte) (int, error) {
copy(data, d.data)
return len(d.data), d.err
}
func (d *testBufferedMarshalable) Size() int {
return len(d.data)
}
func (d *testBufferedMarshalable) DeepCopyObject() runtime.Object {
panic("testBufferedMarshalable does not support DeepCopy")
}
func TestRecognize(t *testing.T) {
s := protobuf.NewSerializer(nil, nil, "application/protobuf")
ignores := [][]byte{
nil,
{},
[]byte("k8s"),
{0x6b, 0x38, 0x73, 0x01},
}
for i, data := range ignores {
if ok, _, err := s.RecognizesData(bytes.NewBuffer(data)); err != nil || ok {
t.Errorf("%d: should not recognize data: %v", i, err)
}
}
recognizes := [][]byte{
{0x6b, 0x38, 0x73, 0x00},
{0x6b, 0x38, 0x73, 0x00, 0x01},
}
for i, data := range recognizes {
if ok, _, err := s.RecognizesData(bytes.NewBuffer(data)); err != nil || !ok {
t.Errorf("%d: should recognize data: %v", i, err)
}
}
}
func TestEncode(t *testing.T) {
obj1 := &testMarshalable{testObject: testObject{}, data: []byte{}}
wire1 := []byte{
0x6b, 0x38, 0x73, 0x00, // prefix
0x0a, 0x04,
0x0a, 0x00, // apiversion
0x12, 0x00, // kind
0x12, 0x00, // data
0x1a, 0x00, // content-type
0x22, 0x00, // content-encoding
}
obj2 := &testMarshalable{
testObject: testObject{gvk: schema.GroupVersionKind{Kind: "test", Group: "other", Version: "version"}},
data: []byte{0x01, 0x02, 0x03},
}
wire2 := []byte{
0x6b, 0x38, 0x73, 0x00, // prefix
0x0a, 0x15,
0x0a, 0x0d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, // apiversion
0x12, 0x04, 0x74, 0x65, 0x73, 0x74, // kind
0x12, 0x03, 0x01, 0x02, 0x03, // data
0x1a, 0x00, // content-type
0x22, 0x00, // content-encoding
}
err1 := fmt.Errorf("a test error")
testCases := []struct {
obj runtime.Object
data []byte
errFn func(error) bool
}{
{
obj: &testObject{},
errFn: protobuf.IsNotMarshalable,
},
{
obj: obj1,
data: wire1,
},
{
obj: &testMarshalable{testObject: obj1.testObject, err: err1},
errFn: func(err error) bool { return err == err1 },
},
{
// if this test fails, writing the "fast path" marshal is not the same as the "slow path"
obj: &testBufferedMarshalable{testObject: obj1.testObject, data: obj1.data},
data: wire1,
},
{
obj: obj2,
data: wire2,
},
{
// if this test fails, writing the "fast path" marshal is not the same as the "slow path"
obj: &testBufferedMarshalable{testObject: obj2.testObject, data: obj2.data},
data: wire2,
},
{
obj: &testBufferedMarshalable{testObject: obj1.testObject, err: err1},
errFn: func(err error) bool { return err == err1 },
},
}
for i, test := range testCases {
s := protobuf.NewSerializer(nil, nil, "application/protobuf")
data, err := runtime.Encode(s, test.obj)
switch {
case err == nil && test.errFn != nil:
t.Errorf("%d: failed: %v", i, err)
continue
case err != nil && test.errFn == nil:
t.Errorf("%d: failed: %v", i, err)
continue
case err != nil:
if !test.errFn(err) {
t.Errorf("%d: failed: %v", i, err)
}
if data != nil {
t.Errorf("%d: should not have returned nil data", i)
}
continue
}
if test.data != nil && !bytes.Equal(test.data, data) {
t.Errorf("%d: unexpected data:\n%s", i, hex.Dump(data))
continue
}
if ok, _, err := s.RecognizesData(bytes.NewBuffer(data)); !ok || err != nil {
t.Errorf("%d: did not recognize data generated by call: %v", i, err)
}
}
}
func TestProtobufDecode(t *testing.T) {
wire1 := []byte{
0x6b, 0x38, 0x73, 0x00, // prefix
0x0a, 0x04,
0x0a, 0x00, // apiversion
0x12, 0x00, // kind
0x12, 0x00, // data
0x1a, 0x00, // content-type
0x22, 0x00, // content-encoding
}
wire2 := []byte{
0x6b, 0x38, 0x73, 0x00, // prefix
0x0a, 0x15,
0x0a, 0x0d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, // apiversion
0x12, 0x04, 0x74, 0x65, 0x73, 0x74, // kind
0x12, 0x07, 0x6b, 0x38, 0x73, 0x00, 0x01, 0x02, 0x03, // data
0x1a, 0x00, // content-type
0x22, 0x00, // content-encoding
}
//err1 := fmt.Errorf("a test error")
testCases := []struct {
obj runtime.Object
data []byte
errFn func(error) bool
}{
{
obj: &runtime.Unknown{},
errFn: func(err error) bool { return err.Error() == "empty data" },
},
{
data: []byte{0x6b},
errFn: func(err error) bool { return strings.Contains(err.Error(), "does not appear to be a protobuf message") },
},
{
obj: &runtime.Unknown{
Raw: []byte{},
},
data: wire1,
},
{
obj: &runtime.Unknown{
TypeMeta: runtime.TypeMeta{
APIVersion: "other/version",
Kind: "test",
},
// content type is set because the prefix matches the content
ContentType: "application/protobuf",
Raw: []byte{0x6b, 0x38, 0x73, 0x00, 0x01, 0x02, 0x03},
},
data: wire2,
},
}
for i, test := range testCases {
s := protobuf.NewSerializer(nil, nil, "application/protobuf")
unk := &runtime.Unknown{}
err := runtime.DecodeInto(s, test.data, unk)
switch {
case err == nil && test.errFn != nil:
t.Errorf("%d: failed: %v", i, err)
continue
case err != nil && test.errFn == nil:
t.Errorf("%d: failed: %v", i, err)
continue
case err != nil:
if !test.errFn(err) {
t.Errorf("%d: failed: %v", i, err)
}
continue
}
if !reflect.DeepEqual(unk, test.obj) {
t.Errorf("%d: unexpected object:\n%#v", i, unk)
continue
}
}
}
func TestDecodeObjects(t *testing.T) {
obj1 := &v1.Carp{
ObjectMeta: metav1.ObjectMeta{
Name: "cool",
},
Spec: v1.CarpSpec{
Hostname: "coolhost",
},
}
obj1wire, err := obj1.Marshal()
if err != nil {
t.Fatal(err)
}
wire1, err := (&runtime.Unknown{
TypeMeta: runtime.TypeMeta{Kind: "Carp", APIVersion: "v1"},
Raw: obj1wire,
}).Marshal()
if err != nil {
t.Fatal(err)
}
unk2 := &runtime.Unknown{
TypeMeta: runtime.TypeMeta{Kind: "Carp", APIVersion: "v1"},
}
wire2 := make([]byte, len(wire1)*2)
n, err := unk2.NestedMarshalTo(wire2, obj1, uint64(obj1.Size()))
if err != nil {
t.Fatal(err)
}
if n != len(wire1) || !bytes.Equal(wire1, wire2[:n]) {
t.Fatalf("unexpected wire:\n%s", hex.Dump(wire2[:n]))
}
wire1 = append([]byte{0x6b, 0x38, 0x73, 0x00}, wire1...)
testCases := []struct {
obj runtime.Object
data []byte
errFn func(error) bool
}{
{
obj: obj1,
data: wire1,
},
}
scheme := runtime.NewScheme()
for i, test := range testCases {
scheme.AddKnownTypes(schema.GroupVersion{Version: "v1"}, &v1.Carp{})
v1.AddToScheme(scheme)
s := protobuf.NewSerializer(scheme, scheme, "application/protobuf")
obj, err := runtime.Decode(s, test.data)
switch {
case err == nil && test.errFn != nil:
t.Errorf("%d: failed: %v", i, err)
continue
case err != nil && test.errFn == nil:
t.Errorf("%d: failed: %v", i, err)
continue
case err != nil:
if !test.errFn(err) {
t.Errorf("%d: failed: %v", i, err)
}
if obj != nil {
t.Errorf("%d: should not have returned an object", i)
}
continue
}
if !apiequality.Semantic.DeepEqual(obj, test.obj) {
t.Errorf("%d: unexpected object:\n%s", i, diff.ObjectGoPrintDiff(test.obj, obj))
continue
}
}
}

View file

@ -1,99 +0,0 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package test
import (
"encoding/json"
"reflect"
"testing"
// TODO: Ideally we should create the necessary package structure in e.g.,
// pkg/conversion/test/... instead of importing pkg/api here.
apitesting "k8s.io/apimachinery/pkg/api/testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func TestV1EncodeDecodeStatus(t *testing.T) {
status := &metav1.Status{
Status: metav1.StatusFailure,
Code: 200,
Reason: metav1.StatusReasonUnknown,
Message: "",
}
_, codecs := TestScheme()
codec := apitesting.TestCodec(codecs, schema.GroupVersion{Group: "", Version: runtime.APIVersionInternal})
encoded, err := runtime.Encode(codec, status)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
typeMeta := metav1.TypeMeta{}
if err := json.Unmarshal(encoded, &typeMeta); err != nil {
t.Errorf("unexpected error: %v", err)
}
if typeMeta.Kind != "Status" {
t.Errorf("Kind is not set to \"Status\". Got %v", string(encoded))
}
if typeMeta.APIVersion != "v1" {
t.Errorf("APIVersion is not set to \"v1\". Got %v", string(encoded))
}
decoded, err := runtime.Decode(codec, encoded)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(status, decoded) {
t.Errorf("expected: %v, got: %v", status, decoded)
}
}
func TestExperimentalEncodeDecodeStatus(t *testing.T) {
status := &metav1.Status{
Status: metav1.StatusFailure,
Code: 200,
Reason: metav1.StatusReasonUnknown,
Message: "",
}
// TODO: caesarxuchao: use the testapi.Extensions.Codec() once the PR that
// moves experimental from v1 to v1beta1 got merged.
_, codecs := TestScheme()
expCodec := apitesting.TestCodec(codecs, schema.GroupVersion{Group: "", Version: runtime.APIVersionInternal})
encoded, err := runtime.Encode(expCodec, status)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
typeMeta := metav1.TypeMeta{}
if err := json.Unmarshal(encoded, &typeMeta); err != nil {
t.Errorf("unexpected error: %v", err)
}
if typeMeta.Kind != "Status" {
t.Errorf("Kind is not set to \"Status\". Got %s", encoded)
}
if typeMeta.APIVersion != "v1" {
t.Errorf("APIVersion is not set to \"\". Got %s", encoded)
}
decoded, err := runtime.Decode(expCodec, encoded)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !reflect.DeepEqual(status, decoded) {
t.Errorf("expected: %v, got: %v", status, decoded)
}
}

View file

@ -1,69 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package test
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/testapigroup"
"k8s.io/apimachinery/pkg/apis/testapigroup/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
apiserializer "k8s.io/apimachinery/pkg/runtime/serializer"
)
// List and ListV1 should be kept in sync with k8s.io/kubernetes/pkg/api#List
// and k8s.io/api/core/v1#List.
//
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type List struct {
metav1.TypeMeta
metav1.ListMeta
Items []runtime.Object
}
// +k8s:deepcopy-gen=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ListV1 struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Items []runtime.RawExtension `json:"items" protobuf:"bytes,2,rep,name=items"`
}
func TestScheme() (*runtime.Scheme, apiserializer.CodecFactory) {
internalGV := schema.GroupVersion{Group: "", Version: runtime.APIVersionInternal}
externalGV := schema.GroupVersion{Group: "", Version: "v1"}
scheme := runtime.NewScheme()
scheme.AddKnownTypes(internalGV,
&testapigroup.Carp{},
&testapigroup.CarpList{},
&List{},
)
scheme.AddKnownTypes(externalGV,
&v1.Carp{},
&v1.CarpList{},
&List{},
)
testapigroup.AddToScheme(scheme)
v1.AddToScheme(scheme)
codecs := apiserializer.NewCodecFactory(scheme)
return scheme, codecs
}

View file

@ -1,115 +0,0 @@
// +build !ignore_autogenerated
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package test
import (
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
reflect "reflect"
)
// GetGeneratedDeepCopyFuncs returns the generated funcs, since we aren't registering them.
//
// Deprecated: deepcopy registration will go away when static deepcopy is fully implemented.
func GetGeneratedDeepCopyFuncs() []conversion.GeneratedDeepCopyFunc {
return []conversion.GeneratedDeepCopyFunc{
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*List).DeepCopyInto(out.(*List))
return nil
}, InType: reflect.TypeOf(&List{})},
{Fn: func(in interface{}, out interface{}, c *conversion.Cloner) error {
in.(*ListV1).DeepCopyInto(out.(*ListV1))
return nil
}, InType: reflect.TypeOf(&ListV1{})},
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *List) DeepCopyInto(out *List) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]runtime.Object, len(*in))
for i := range *in {
if (*in)[i] == nil {
(*out)[i] = nil
} else {
(*out)[i] = (*in)[i].DeepCopyObject()
}
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new List.
func (in *List) DeepCopy() *List {
if in == nil {
return nil
}
out := new(List)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *List) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ListV1) DeepCopyInto(out *ListV1) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]runtime.RawExtension, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListV1.
func (in *ListV1) DeepCopy() *ListV1 {
if in == nil {
return nil
}
out := new(ListV1)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ListV1) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
} else {
return nil
}
}

View file

@ -1,26 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["initialization.go"],
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View file

@ -1,48 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package initialization
import (
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// IsInitialized returns if the initializers indicates means initialized.
func IsInitialized(initializers *metav1.Initializers) bool {
if initializers == nil {
return true
}
// Persisted objects will never be in this state. The initializer admission
// plugin will override metadata.initializers to nil. If the initializer
// admissio plugin is disabled, the generic registry always set
// metadata.initializers to nil. However, this function
// might be called before the object persisted, thus the check.
if len(initializers.Pending) == 0 && initializers.Result == nil {
return true
}
return false
}
// IsObjectInitialized returns if the object is initialized.
func IsObjectInitialized(obj runtime.Object) (bool, error) {
accessor, err := meta.Accessor(obj)
if err != nil {
return false, err
}
return IsInitialized(accessor.GetInitializers()), nil
}

View file

@ -1,42 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["patch_test.go"],
library = ":go_default_library",
deps = [
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
"//vendor/github.com/evanphx/json-patch:go_default_library",
"//vendor/github.com/ghodss/yaml:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["patch.go"],
deps = [
"//vendor/github.com/evanphx/json-patch:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/mergepatch:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,144 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package jsonmergepatch
import (
"fmt"
"reflect"
"github.com/evanphx/json-patch"
"k8s.io/apimachinery/pkg/util/json"
"k8s.io/apimachinery/pkg/util/mergepatch"
)
// Create a 3-way merge patch based-on JSON merge patch.
// Calculate addition-and-change patch between current and modified.
// Calculate deletion patch between original and modified.
func CreateThreeWayJSONMergePatch(original, modified, current []byte, fns ...mergepatch.PreconditionFunc) ([]byte, error) {
if len(original) == 0 {
original = []byte(`{}`)
}
if len(modified) == 0 {
modified = []byte(`{}`)
}
if len(current) == 0 {
current = []byte(`{}`)
}
addAndChangePatch, err := jsonpatch.CreateMergePatch(current, modified)
if err != nil {
return nil, err
}
// Only keep addition and changes
addAndChangePatch, addAndChangePatchObj, err := keepOrDeleteNullInJsonPatch(addAndChangePatch, false)
if err != nil {
return nil, err
}
deletePatch, err := jsonpatch.CreateMergePatch(original, modified)
if err != nil {
return nil, err
}
// Only keep deletion
deletePatch, deletePatchObj, err := keepOrDeleteNullInJsonPatch(deletePatch, true)
if err != nil {
return nil, err
}
hasConflicts, err := mergepatch.HasConflicts(addAndChangePatchObj, deletePatchObj)
if err != nil {
return nil, err
}
if hasConflicts {
return nil, mergepatch.NewErrConflict(mergepatch.ToYAMLOrError(addAndChangePatchObj), mergepatch.ToYAMLOrError(deletePatchObj))
}
patch, err := jsonpatch.MergePatch(deletePatch, addAndChangePatch)
if err != nil {
return nil, err
}
var patchMap map[string]interface{}
err = json.Unmarshal(patch, &patchMap)
if err != nil {
return nil, fmt.Errorf("Failed to unmarshal patch for precondition check: %s", patch)
}
meetPreconditions, err := meetPreconditions(patchMap, fns...)
if err != nil {
return nil, err
}
if !meetPreconditions {
return nil, mergepatch.NewErrPreconditionFailed(patchMap)
}
return patch, nil
}
// keepOrDeleteNullInJsonPatch takes a json-encoded byte array and a boolean.
// It returns a filtered object and its corresponding json-encoded byte array.
// It is a wrapper of func keepOrDeleteNullInObj
func keepOrDeleteNullInJsonPatch(patch []byte, keepNull bool) ([]byte, map[string]interface{}, error) {
var patchMap map[string]interface{}
err := json.Unmarshal(patch, &patchMap)
if err != nil {
return nil, nil, err
}
filteredMap, err := keepOrDeleteNullInObj(patchMap, keepNull)
if err != nil {
return nil, nil, err
}
o, err := json.Marshal(filteredMap)
return o, filteredMap, err
}
// keepOrDeleteNullInObj will keep only the null value and delete all the others,
// if keepNull is true. Otherwise, it will delete all the null value and keep the others.
func keepOrDeleteNullInObj(m map[string]interface{}, keepNull bool) (map[string]interface{}, error) {
filteredMap := make(map[string]interface{})
var err error
for key, val := range m {
switch {
case keepNull && val == nil:
filteredMap[key] = nil
case val != nil:
switch typedVal := val.(type) {
case map[string]interface{}:
filteredMap[key], err = keepOrDeleteNullInObj(typedVal, keepNull)
if err != nil {
return nil, err
}
case []interface{}, string, float64, bool, int, int64, nil:
// Lists are always replaced in Json, no need to check each entry in the list.
if !keepNull {
filteredMap[key] = val
}
default:
return nil, fmt.Errorf("unknown type: %v", reflect.TypeOf(typedVal))
}
}
}
return filteredMap, nil
}
func meetPreconditions(patchObj map[string]interface{}, fns ...mergepatch.PreconditionFunc) (bool, error) {
// Apply the preconditions to the patch, and return an error if any of them fail.
for _, fn := range fns {
if !fn(patchObj) {
return false, fmt.Errorf("precondition failed for: %v", patchObj)
}
}
return true, nil
}

View file

@ -1,663 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package jsonmergepatch
import (
"fmt"
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/evanphx/json-patch"
"github.com/ghodss/yaml"
"k8s.io/apimachinery/pkg/util/json"
)
type FilterNullTestCases struct {
TestCases []FilterNullTestCase
}
type FilterNullTestCase struct {
Description string
OriginalObj map[string]interface{}
ExpectedWithNull map[string]interface{}
ExpectedWithoutNull map[string]interface{}
}
var filterNullTestCaseData = []byte(`
testCases:
- description: nil original
originalObj: {}
expectedWithNull: {}
expectedWithoutNull: {}
- description: simple map
originalObj:
nilKey: null
nonNilKey: foo
expectedWithNull:
nilKey: null
expectedWithoutNull:
nonNilKey: foo
- description: simple map with all nil values
originalObj:
nilKey1: null
nilKey2: null
expectedWithNull:
nilKey1: null
nilKey2: null
expectedWithoutNull: {}
- description: simple map with all non-nil values
originalObj:
nonNilKey: foo
nonNilKey: bar
expectedWithNull: {}
expectedWithoutNull:
nonNilKey: foo
nonNilKey: bar
- description: nested map
originalObj:
mapKey:
nilKey: null
nonNilKey: foo
expectedWithNull:
mapKey:
nilKey: null
expectedWithoutNull:
mapKey:
nonNilKey: foo
- description: nested map that all subkeys are nil
originalObj:
mapKey:
nilKey1: null
nilKey2: null
expectedWithNull:
mapKey:
nilKey1: null
nilKey2: null
expectedWithoutNull:
mapKey: {}
- description: nested map that all subkeys are non-nil
originalObj:
mapKey:
nonNilKey: foo
nonNilKey: bar
expectedWithNull:
mapKey: {}
expectedWithoutNull:
mapKey:
nonNilKey: foo
nonNilKey: bar
- description: empty list
originalObj:
listKey: []
expectedWithNull: {}
expectedWithoutNull:
listKey: []
- description: list of primitives
originalObj:
listKey:
- 1
- 2
expectedWithNull: {}
expectedWithoutNull:
listKey:
- 1
- 2
- description: list of maps
originalObj:
listKey:
- k1: v1
- k2: null
- k3: v3
k4: null
expectedWithNull: {}
expectedWithoutNull:
listKey:
- k1: v1
- k2: null
- k3: v3
k4: null
- description: list of different types
originalObj:
listKey:
- k1: v1
- k2: null
- v3
expectedWithNull: {}
expectedWithoutNull:
listKey:
- k1: v1
- k2: null
- v3
`)
func TestKeepOrDeleteNullInObj(t *testing.T) {
tc := FilterNullTestCases{}
err := yaml.Unmarshal(filterNullTestCaseData, &tc)
if err != nil {
t.Fatalf("can't unmarshal test cases: %s\n", err)
}
for _, test := range tc.TestCases {
resultWithNull, err := keepOrDeleteNullInObj(test.OriginalObj, true)
if err != nil {
t.Errorf("Failed in test case %q when trying to keep null values: %s", test.Description, err)
}
if !reflect.DeepEqual(test.ExpectedWithNull, resultWithNull) {
t.Errorf("Failed in test case %q when trying to keep null values:\nexpected expectedWithNull:\n%+v\nbut got:\n%+v\n", test.Description, test.ExpectedWithNull, resultWithNull)
}
resultWithoutNull, err := keepOrDeleteNullInObj(test.OriginalObj, false)
if err != nil {
t.Errorf("Failed in test case %q when trying to keep non-null values: %s", test.Description, err)
}
if !reflect.DeepEqual(test.ExpectedWithoutNull, resultWithoutNull) {
t.Errorf("Failed in test case %q when trying to keep non-null values:\n expected expectedWithoutNull:\n%+v\nbut got:\n%+v\n", test.Description, test.ExpectedWithoutNull, resultWithoutNull)
}
}
}
type JSONMergePatchTestCases struct {
TestCases []JSONMergePatchTestCase
}
type JSONMergePatchTestCase struct {
Description string
JSONMergePatchTestCaseData
}
type JSONMergePatchTestCaseData struct {
// Original is the original object (last-applied config in annotation)
Original map[string]interface{}
// Modified is the modified object (new config we want)
Modified map[string]interface{}
// Current is the current object (live config in the server)
Current map[string]interface{}
// ThreeWay is the expected three-way merge patch
ThreeWay map[string]interface{}
// Result is the expected object after applying the three-way patch on current object.
Result map[string]interface{}
}
var createJSONMergePatchTestCaseData = []byte(`
testCases:
- description: nil original
modified:
name: 1
value: 1
current:
name: 1
other: a
threeWay:
value: 1
result:
name: 1
value: 1
other: a
- description: nil patch
original:
name: 1
modified:
name: 1
current:
name: 1
threeWay:
{}
result:
name: 1
- description: add field to map
original:
name: 1
modified:
name: 1
value: 1
current:
name: 1
other: a
threeWay:
value: 1
result:
name: 1
value: 1
other: a
- description: add field to map with conflict
original:
name: 1
modified:
name: 1
value: 1
current:
name: a
other: a
threeWay:
name: 1
value: 1
result:
name: 1
value: 1
other: a
- description: add field and delete field from map
original:
name: 1
modified:
value: 1
current:
name: 1
other: a
threeWay:
name: null
value: 1
result:
value: 1
other: a
- description: add field and delete field from map with conflict
original:
name: 1
modified:
value: 1
current:
name: a
other: a
threeWay:
name: null
value: 1
result:
value: 1
other: a
- description: delete field from nested map
original:
simpleMap:
key1: 1
key2: 1
modified:
simpleMap:
key1: 1
current:
simpleMap:
key1: 1
key2: 1
other: a
threeWay:
simpleMap:
key2: null
result:
simpleMap:
key1: 1
other: a
- description: delete field from nested map with conflict
original:
simpleMap:
key1: 1
key2: 1
modified:
simpleMap:
key1: 1
current:
simpleMap:
key1: a
key2: 1
other: a
threeWay:
simpleMap:
key1: 1
key2: null
result:
simpleMap:
key1: 1
other: a
- description: delete all fields from map
original:
name: 1
value: 1
modified: {}
current:
name: 1
value: 1
other: a
threeWay:
name: null
value: null
result:
other: a
- description: delete all fields from map with conflict
original:
name: 1
value: 1
modified: {}
current:
name: 1
value: a
other: a
threeWay:
name: null
value: null
result:
other: a
- description: add field and delete all fields from map
original:
name: 1
value: 1
modified:
other: a
current:
name: 1
value: 1
other: a
threeWay:
name: null
value: null
result:
other: a
- description: add field and delete all fields from map with conflict
original:
name: 1
value: 1
modified:
other: a
current:
name: 1
value: 1
other: b
threeWay:
name: null
value: null
other: a
result:
other: a
- description: replace list of scalars
original:
intList:
- 1
- 2
modified:
intList:
- 2
- 3
current:
intList:
- 1
- 2
threeWay:
intList:
- 2
- 3
result:
intList:
- 2
- 3
- description: replace list of scalars with conflict
original:
intList:
- 1
- 2
modified:
intList:
- 2
- 3
current:
intList:
- 1
- 4
threeWay:
intList:
- 2
- 3
result:
intList:
- 2
- 3
- description: patch with different scalar type
original:
foo: 1
modified:
foo: true
current:
foo: 1
bar: 2
threeWay:
foo: true
result:
foo: true
bar: 2
- description: patch from scalar to list
original:
foo: 0
modified:
foo:
- 1
- 2
current:
foo: 0
bar: 2
threeWay:
foo:
- 1
- 2
result:
foo:
- 1
- 2
bar: 2
- description: patch from list to scalar
original:
foo:
- 1
- 2
modified:
foo: 0
current:
foo:
- 1
- 2
bar: 2
threeWay:
foo: 0
result:
foo: 0
bar: 2
- description: patch from scalar to map
original:
foo: 0
modified:
foo:
baz: 1
current:
foo: 0
bar: 2
threeWay:
foo:
baz: 1
result:
foo:
baz: 1
bar: 2
- description: patch from map to scalar
original:
foo:
baz: 1
modified:
foo: 0
current:
foo:
baz: 1
bar: 2
threeWay:
foo: 0
result:
foo: 0
bar: 2
- description: patch from map to list
original:
foo:
baz: 1
modified:
foo:
- 1
- 2
current:
foo:
baz: 1
bar: 2
threeWay:
foo:
- 1
- 2
result:
foo:
- 1
- 2
bar: 2
- description: patch from list to map
original:
foo:
- 1
- 2
modified:
foo:
baz: 0
current:
foo:
- 1
- 2
bar: 2
threeWay:
foo:
baz: 0
result:
foo:
baz: 0
bar: 2
- description: patch with different nested types
original:
foo:
- a: true
- 2
- false
modified:
foo:
- 1
- false
- b: 1
current:
foo:
- a: true
- 2
- false
bar: 0
threeWay:
foo:
- 1
- false
- b: 1
result:
foo:
- 1
- false
- b: 1
bar: 0
`)
func TestCreateThreeWayJSONMergePatch(t *testing.T) {
tc := JSONMergePatchTestCases{}
err := yaml.Unmarshal(createJSONMergePatchTestCaseData, &tc)
if err != nil {
t.Errorf("can't unmarshal test cases: %s\n", err)
return
}
for _, c := range tc.TestCases {
testThreeWayPatch(t, c)
}
}
func testThreeWayPatch(t *testing.T, c JSONMergePatchTestCase) {
original, modified, current, expected, result := threeWayTestCaseToJSONOrFail(t, c)
actual, err := CreateThreeWayJSONMergePatch(original, modified, current)
if err != nil {
t.Fatalf("error: %s", err)
}
testPatchCreation(t, expected, actual, c.Description)
testPatchApplication(t, current, actual, result, c.Description)
}
func testPatchCreation(t *testing.T, expected, actual []byte, description string) {
if !reflect.DeepEqual(actual, expected) {
t.Errorf("error in test case: %s\nexpected patch:\n%s\ngot:\n%s\n",
description, jsonToYAMLOrError(expected), jsonToYAMLOrError(actual))
return
}
}
func testPatchApplication(t *testing.T, original, patch, expected []byte, description string) {
result, err := jsonpatch.MergePatch(original, patch)
if err != nil {
t.Errorf("error: %s\nin test case: %s\ncannot apply patch:\n%s\nto original:\n%s\n",
err, description, jsonToYAMLOrError(patch), jsonToYAMLOrError(original))
return
}
if !reflect.DeepEqual(result, expected) {
format := "error in test case: %s\npatch application failed:\noriginal:\n%s\npatch:\n%s\nexpected:\n%s\ngot:\n%s\n"
t.Errorf(format, description,
jsonToYAMLOrError(original), jsonToYAMLOrError(patch),
jsonToYAMLOrError(expected), jsonToYAMLOrError(result))
return
}
}
func threeWayTestCaseToJSONOrFail(t *testing.T, c JSONMergePatchTestCase) ([]byte, []byte, []byte, []byte, []byte) {
return testObjectToJSONOrFail(t, c.Original),
testObjectToJSONOrFail(t, c.Modified),
testObjectToJSONOrFail(t, c.Current),
testObjectToJSONOrFail(t, c.ThreeWay),
testObjectToJSONOrFail(t, c.Result)
}
func testObjectToJSONOrFail(t *testing.T, o map[string]interface{}) []byte {
if o == nil {
return nil
}
j, err := toJSON(o)
if err != nil {
t.Error(err)
}
return j
}
func jsonToYAMLOrError(j []byte) string {
y, err := jsonToYAML(j)
if err != nil {
return err.Error()
}
return string(y)
}
func toJSON(v interface{}) ([]byte, error) {
j, err := json.Marshal(v)
if err != nil {
return nil, fmt.Errorf("json marshal failed: %v\n%v\n", err, spew.Sdump(v))
}
return j, nil
}
func jsonToYAML(j []byte) ([]byte, error) {
y, err := yaml.JSONToYAML(j)
if err != nil {
return nil, fmt.Errorf("json to yaml failed: %v\n%v\n", err, j)
}
return y, nil
}

View file

@ -1,60 +0,0 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"dial_test.go",
"transport_test.go",
"upgradeaware_test.go",
],
library = ":go_default_library",
deps = [
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/github.com/stretchr/testify/require:go_default_library",
"//vendor/golang.org/x/net/websocket:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dial.go",
"doc.go",
"transport.go",
"upgradeaware.go",
],
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/mxk/go-flowrate/flowrate:go_default_library",
"//vendor/golang.org/x/net/html:go_default_library",
"//vendor/golang.org/x/net/html/atom:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/httpstream:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/third_party/forked/golang/netutil:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

View file

@ -1,115 +0,0 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package proxy
import (
"crypto/tls"
"fmt"
"net"
"net/http"
"net/url"
"github.com/golang/glog"
utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/third_party/forked/golang/netutil"
)
func DialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) {
dialAddr := netutil.CanonicalAddr(url)
dialer, err := utilnet.DialerFor(transport)
if err != nil {
glog.V(5).Infof("Unable to unwrap transport %T to get dialer: %v", transport, err)
}
switch url.Scheme {
case "http":
if dialer != nil {
return dialer("tcp", dialAddr)
}
return net.Dial("tcp", dialAddr)
case "https":
// Get the tls config from the transport if we recognize it
var tlsConfig *tls.Config
var tlsConn *tls.Conn
var err error
tlsConfig, err = utilnet.TLSClientConfig(transport)
if err != nil {
glog.V(5).Infof("Unable to unwrap transport %T to get at TLS config: %v", transport, err)
}
if dialer != nil {
// We have a dialer; use it to open the connection, then
// create a tls client using the connection.
netConn, err := dialer("tcp", dialAddr)
if err != nil {
return nil, err
}
if tlsConfig == nil {
// tls.Client requires non-nil config
glog.Warningf("using custom dialer with no TLSClientConfig. Defaulting to InsecureSkipVerify")
// tls.Handshake() requires ServerName or InsecureSkipVerify
tlsConfig = &tls.Config{
InsecureSkipVerify: true,
}
} else if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify {
// tls.Handshake() requires ServerName or InsecureSkipVerify
// infer the ServerName from the hostname we're connecting to.
inferredHost := dialAddr
if host, _, err := net.SplitHostPort(dialAddr); err == nil {
inferredHost = host
}
// Make a copy to avoid polluting the provided config
tlsConfigCopy := tlsConfig.Clone()
tlsConfigCopy.ServerName = inferredHost
tlsConfig = tlsConfigCopy
}
tlsConn = tls.Client(netConn, tlsConfig)
if err := tlsConn.Handshake(); err != nil {
netConn.Close()
return nil, err
}
} else {
// Dial
tlsConn, err = tls.Dial("tcp", dialAddr, tlsConfig)
if err != nil {
return nil, err
}
}
// Return if we were configured to skip validation
if tlsConfig != nil && tlsConfig.InsecureSkipVerify {
return tlsConn, nil
}
// Verify
host, _, _ := net.SplitHostPort(dialAddr)
if tlsConfig != nil && len(tlsConfig.ServerName) > 0 {
host = tlsConfig.ServerName
}
if err := tlsConn.VerifyHostname(host); err != nil {
tlsConn.Close()
return nil, err
}
return tlsConn, nil
default:
return nil, fmt.Errorf("Unknown scheme: %s", url.Scheme)
}
}

View file

@ -1,176 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package proxy
import (
"crypto/tls"
"crypto/x509"
"fmt"
"net"
"net/http"
"net/http/httptest"
"net/url"
"reflect"
"strings"
"testing"
"k8s.io/apimachinery/pkg/util/diff"
utilnet "k8s.io/apimachinery/pkg/util/net"
)
func TestDialURL(t *testing.T) {
roots := x509.NewCertPool()
if !roots.AppendCertsFromPEM(localhostCert) {
t.Fatal("error setting up localhostCert pool")
}
cert, err := tls.X509KeyPair(localhostCert, localhostKey)
if err != nil {
t.Fatal(err)
}
testcases := map[string]struct {
TLSConfig *tls.Config
Dial utilnet.DialFunc
ExpectError string
}{
"insecure": {
TLSConfig: &tls.Config{InsecureSkipVerify: true},
},
"secure, no roots": {
TLSConfig: &tls.Config{InsecureSkipVerify: false},
ExpectError: "unknown authority",
},
"secure with roots": {
TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots},
},
"secure with mismatched server": {
TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots, ServerName: "bogus.com"},
ExpectError: "not bogus.com",
},
"secure with matched server": {
TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots, ServerName: "example.com"},
},
"insecure, custom dial": {
TLSConfig: &tls.Config{InsecureSkipVerify: true},
Dial: net.Dial,
},
"secure, no roots, custom dial": {
TLSConfig: &tls.Config{InsecureSkipVerify: false},
Dial: net.Dial,
ExpectError: "unknown authority",
},
"secure with roots, custom dial": {
TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots},
Dial: net.Dial,
},
"secure with mismatched server, custom dial": {
TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots, ServerName: "bogus.com"},
Dial: net.Dial,
ExpectError: "not bogus.com",
},
"secure with matched server, custom dial": {
TLSConfig: &tls.Config{InsecureSkipVerify: false, RootCAs: roots, ServerName: "example.com"},
Dial: net.Dial,
},
}
for k, tc := range testcases {
func() {
ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {}))
defer ts.Close()
ts.TLS = &tls.Config{Certificates: []tls.Certificate{cert}}
ts.StartTLS()
// Make a copy of the config
tlsConfigCopy := tc.TLSConfig.Clone()
// Clone() mutates the receiver (!), so also call it on the copy
tlsConfigCopy.Clone()
transport := &http.Transport{
Dial: tc.Dial,
TLSClientConfig: tlsConfigCopy,
}
extractedDial, err := utilnet.DialerFor(transport)
if err != nil {
t.Fatal(err)
}
if fmt.Sprintf("%p", extractedDial) != fmt.Sprintf("%p", tc.Dial) {
t.Fatalf("%s: Unexpected dial", k)
}
extractedTLSConfig, err := utilnet.TLSClientConfig(transport)
if err != nil {
t.Fatal(err)
}
if extractedTLSConfig == nil {
t.Fatalf("%s: Expected tlsConfig", k)
}
u, _ := url.Parse(ts.URL)
_, p, _ := net.SplitHostPort(u.Host)
u.Host = net.JoinHostPort("127.0.0.1", p)
conn, err := DialURL(u, transport)
// Make sure dialing doesn't mutate the transport's TLSConfig
if !reflect.DeepEqual(tc.TLSConfig, tlsConfigCopy) {
t.Errorf("%s: transport's copy of TLSConfig was mutated\n%s", k, diff.ObjectReflectDiff(tc.TLSConfig, tlsConfigCopy))
}
if err != nil {
if tc.ExpectError == "" {
t.Errorf("%s: expected no error, got %q", k, err.Error())
}
if !strings.Contains(err.Error(), tc.ExpectError) {
t.Errorf("%s: expected error containing %q, got %q", k, tc.ExpectError, err.Error())
}
return
}
conn.Close()
if tc.ExpectError != "" {
t.Errorf("%s: expected error %q, got none", k, tc.ExpectError)
}
}()
}
}
// localhostCert was generated from crypto/tls/generate_cert.go with the following command:
// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
MIIBjzCCATmgAwIBAgIRAKpi2WmTcFrVjxrl5n5YDUEwDQYJKoZIhvcNAQELBQAw
EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2
MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgC
QQC9fEbRszP3t14Gr4oahV7zFObBI4TfA5i7YnlMXeLinb7MnvT4bkfOJzE6zktn
59zP7UiHs3l4YOuqrjiwM413AgMBAAGjaDBmMA4GA1UdDwEB/wQEAwICpDATBgNV
HSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MC4GA1UdEQQnMCWCC2V4
YW1wbGUuY29thwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEBCwUA
A0EAUsVE6KMnza/ZbodLlyeMzdo7EM/5nb5ywyOxgIOCf0OOLHsPS9ueGLQX9HEG
//yjTXuhNcUugExIjM/AIwAZPQ==
-----END CERTIFICATE-----`)
// localhostKey is the private key for localhostCert.
var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBAL18RtGzM/e3XgavihqFXvMU5sEjhN8DmLtieUxd4uKdvsye9Phu
R84nMTrOS2fn3M/tSIezeXhg66quOLAzjXcCAwEAAQJBAKcRxH9wuglYLBdI/0OT
BLzfWPZCEw1vZmMR2FF1Fm8nkNOVDPleeVGTWoOEcYYlQbpTmkGSxJ6ya+hqRi6x
goECIQDx3+X49fwpL6B5qpJIJMyZBSCuMhH4B7JevhGGFENi3wIhAMiNJN5Q3UkL
IuSvv03kaPR5XVQ99/UeEetUgGvBcABpAiBJSBzVITIVCGkGc7d+RCf49KTCIklv
bGWObufAR8Ni4QIgWpILjW8dkGg8GOUZ0zaNA6Nvt6TIv2UWGJ4v5PoV98kCIQDx
rIiZs5QbKdycsv9gQJzwQAogC8o04X3Zz3dsoX+h4A==
-----END RSA PRIVATE KEY-----`)

View file

@ -1,18 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package proxy provides transport and upgrade support for proxies.
package proxy // import "k8s.io/apimachinery/pkg/util/proxy"

View file

@ -1,241 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package proxy
import (
"bytes"
"compress/gzip"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"path"
"strings"
"github.com/golang/glog"
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
"k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/pkg/util/sets"
)
// atomsToAttrs states which attributes of which tags require URL substitution.
// Sources: http://www.w3.org/TR/REC-html40/index/attributes.html
// http://www.w3.org/html/wg/drafts/html/master/index.html#attributes-1
var atomsToAttrs = map[atom.Atom]sets.String{
atom.A: sets.NewString("href"),
atom.Applet: sets.NewString("codebase"),
atom.Area: sets.NewString("href"),
atom.Audio: sets.NewString("src"),
atom.Base: sets.NewString("href"),
atom.Blockquote: sets.NewString("cite"),
atom.Body: sets.NewString("background"),
atom.Button: sets.NewString("formaction"),
atom.Command: sets.NewString("icon"),
atom.Del: sets.NewString("cite"),
atom.Embed: sets.NewString("src"),
atom.Form: sets.NewString("action"),
atom.Frame: sets.NewString("longdesc", "src"),
atom.Head: sets.NewString("profile"),
atom.Html: sets.NewString("manifest"),
atom.Iframe: sets.NewString("longdesc", "src"),
atom.Img: sets.NewString("longdesc", "src", "usemap"),
atom.Input: sets.NewString("src", "usemap", "formaction"),
atom.Ins: sets.NewString("cite"),
atom.Link: sets.NewString("href"),
atom.Object: sets.NewString("classid", "codebase", "data", "usemap"),
atom.Q: sets.NewString("cite"),
atom.Script: sets.NewString("src"),
atom.Source: sets.NewString("src"),
atom.Video: sets.NewString("poster", "src"),
// TODO: css URLs hidden in style elements.
}
// Transport is a transport for text/html content that replaces URLs in html
// content with the prefix of the proxy server
type Transport struct {
Scheme string
Host string
PathPrepend string
http.RoundTripper
}
// RoundTrip implements the http.RoundTripper interface
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
// Add reverse proxy headers.
forwardedURI := path.Join(t.PathPrepend, req.URL.Path)
if strings.HasSuffix(req.URL.Path, "/") {
forwardedURI = forwardedURI + "/"
}
req.Header.Set("X-Forwarded-Uri", forwardedURI)
if len(t.Host) > 0 {
req.Header.Set("X-Forwarded-Host", t.Host)
}
if len(t.Scheme) > 0 {
req.Header.Set("X-Forwarded-Proto", t.Scheme)
}
rt := t.RoundTripper
if rt == nil {
rt = http.DefaultTransport
}
resp, err := rt.RoundTrip(req)
if err != nil {
message := fmt.Sprintf("Error: '%s'\nTrying to reach: '%v'", err.Error(), req.URL.String())
resp = &http.Response{
StatusCode: http.StatusServiceUnavailable,
Body: ioutil.NopCloser(strings.NewReader(message)),
}
return resp, nil
}
if redirect := resp.Header.Get("Location"); redirect != "" {
resp.Header.Set("Location", t.rewriteURL(redirect, req.URL))
return resp, nil
}
cType := resp.Header.Get("Content-Type")
cType = strings.TrimSpace(strings.SplitN(cType, ";", 2)[0])
if cType != "text/html" {
// Do nothing, simply pass through
return resp, nil
}
return t.rewriteResponse(req, resp)
}
var _ = net.RoundTripperWrapper(&Transport{})
func (rt *Transport) WrappedRoundTripper() http.RoundTripper {
return rt.RoundTripper
}
// rewriteURL rewrites a single URL to go through the proxy, if the URL refers
// to the same host as sourceURL, which is the page on which the target URL
// occurred. If any error occurs (e.g. parsing), it returns targetURL.
func (t *Transport) rewriteURL(targetURL string, sourceURL *url.URL) string {
url, err := url.Parse(targetURL)
if err != nil {
return targetURL
}
isDifferentHost := url.Host != "" && url.Host != sourceURL.Host
isRelative := !strings.HasPrefix(url.Path, "/")
if isDifferentHost || isRelative {
return targetURL
}
url.Scheme = t.Scheme
url.Host = t.Host
origPath := url.Path
// Do not rewrite URL if the sourceURL already contains the necessary prefix.
if strings.HasPrefix(url.Path, t.PathPrepend) {
return url.String()
}
url.Path = path.Join(t.PathPrepend, url.Path)
if strings.HasSuffix(origPath, "/") {
// Add back the trailing slash, which was stripped by path.Join().
url.Path += "/"
}
return url.String()
}
// rewriteHTML scans the HTML for tags with url-valued attributes, and updates
// those values with the urlRewriter function. The updated HTML is output to the
// writer.
func rewriteHTML(reader io.Reader, writer io.Writer, urlRewriter func(string) string) error {
// Note: This assumes the content is UTF-8.
tokenizer := html.NewTokenizer(reader)
var err error
for err == nil {
tokenType := tokenizer.Next()
switch tokenType {
case html.ErrorToken:
err = tokenizer.Err()
case html.StartTagToken, html.SelfClosingTagToken:
token := tokenizer.Token()
if urlAttrs, ok := atomsToAttrs[token.DataAtom]; ok {
for i, attr := range token.Attr {
if urlAttrs.Has(attr.Key) {
token.Attr[i].Val = urlRewriter(attr.Val)
}
}
}
_, err = writer.Write([]byte(token.String()))
default:
_, err = writer.Write(tokenizer.Raw())
}
}
if err != io.EOF {
return err
}
return nil
}
// rewriteResponse modifies an HTML response by updating absolute links referring
// to the original host to instead refer to the proxy transport.
func (t *Transport) rewriteResponse(req *http.Request, resp *http.Response) (*http.Response, error) {
origBody := resp.Body
defer origBody.Close()
newContent := &bytes.Buffer{}
var reader io.Reader = origBody
var writer io.Writer = newContent
encoding := resp.Header.Get("Content-Encoding")
switch encoding {
case "gzip":
var err error
reader, err = gzip.NewReader(reader)
if err != nil {
return nil, fmt.Errorf("errorf making gzip reader: %v", err)
}
gzw := gzip.NewWriter(writer)
defer gzw.Close()
writer = gzw
// TODO: support flate, other encodings.
case "":
// This is fine
default:
// Some encoding we don't understand-- don't try to parse this
glog.Errorf("Proxy encountered encoding %v for text/html; can't understand this so not fixing links.", encoding)
return resp, nil
}
urlRewriter := func(targetUrl string) string {
return t.rewriteURL(targetUrl, req.URL)
}
err := rewriteHTML(reader, writer, urlRewriter)
if err != nil {
glog.Errorf("Failed to rewrite URLs: %v", err)
return resp, err
}
resp.Body = ioutil.NopCloser(newContent)
// Update header node with new content-length
// TODO: Remove any hash/signature headers here?
resp.Header.Del("Content-Length")
resp.ContentLength = int64(newContent.Len())
return resp, err
}

View file

@ -1,261 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package proxy
import (
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
)
func parseURLOrDie(inURL string) *url.URL {
parsed, err := url.Parse(inURL)
if err != nil {
panic(err)
}
return parsed
}
func TestProxyTransport(t *testing.T) {
testTransport := &Transport{
Scheme: "http",
Host: "foo.com",
PathPrepend: "/proxy/node/node1:10250",
}
testTransport2 := &Transport{
Scheme: "https",
Host: "foo.com",
PathPrepend: "/proxy/node/node1:8080",
}
emptyHostTransport := &Transport{
Scheme: "https",
PathPrepend: "/proxy/node/node1:10250",
}
emptySchemeTransport := &Transport{
Host: "foo.com",
PathPrepend: "/proxy/node/node1:10250",
}
type Item struct {
input string
sourceURL string
transport *Transport
output string
contentType string
forwardedURI string
redirect string
redirectWant string
}
table := map[string]Item{
"normal": {
input: `<pre><a href="kubelet.log">kubelet.log</a><a href="/google.log">google.log</a></pre>`,
sourceURL: "http://mynode.com/logs/log.log",
transport: testTransport,
output: `<pre><a href="kubelet.log">kubelet.log</a><a href="http://foo.com/proxy/node/node1:10250/google.log">google.log</a></pre>`,
contentType: "text/html",
forwardedURI: "/proxy/node/node1:10250/logs/log.log",
},
"full document": {
input: `<html><header></header><body><pre><a href="kubelet.log">kubelet.log</a><a href="/google.log">google.log</a></pre></body></html>`,
sourceURL: "http://mynode.com/logs/log.log",
transport: testTransport,
output: `<html><header></header><body><pre><a href="kubelet.log">kubelet.log</a><a href="http://foo.com/proxy/node/node1:10250/google.log">google.log</a></pre></body></html>`,
contentType: "text/html",
forwardedURI: "/proxy/node/node1:10250/logs/log.log",
},
"trailing slash": {
input: `<pre><a href="kubelet.log">kubelet.log</a><a href="/google.log/">google.log</a></pre>`,
sourceURL: "http://mynode.com/logs/log.log",
transport: testTransport,
output: `<pre><a href="kubelet.log">kubelet.log</a><a href="http://foo.com/proxy/node/node1:10250/google.log/">google.log</a></pre>`,
contentType: "text/html",
forwardedURI: "/proxy/node/node1:10250/logs/log.log",
},
"content-type charset": {
input: `<pre><a href="kubelet.log">kubelet.log</a><a href="/google.log">google.log</a></pre>`,
sourceURL: "http://mynode.com/logs/log.log",
transport: testTransport,
output: `<pre><a href="kubelet.log">kubelet.log</a><a href="http://foo.com/proxy/node/node1:10250/google.log">google.log</a></pre>`,
contentType: "text/html; charset=utf-8",
forwardedURI: "/proxy/node/node1:10250/logs/log.log",
},
"content-type passthrough": {
input: `<pre><a href="kubelet.log">kubelet.log</a><a href="/google.log">google.log</a></pre>`,
sourceURL: "http://mynode.com/logs/log.log",
transport: testTransport,
output: `<pre><a href="kubelet.log">kubelet.log</a><a href="/google.log">google.log</a></pre>`,
contentType: "text/plain",
forwardedURI: "/proxy/node/node1:10250/logs/log.log",
},
"subdir": {
input: `<a href="kubelet.log">kubelet.log</a><a href="/google.log">google.log</a>`,
sourceURL: "http://mynode.com/whatever/apt/somelog.log",
transport: testTransport2,
output: `<a href="kubelet.log">kubelet.log</a><a href="https://foo.com/proxy/node/node1:8080/google.log">google.log</a>`,
contentType: "text/html",
forwardedURI: "/proxy/node/node1:8080/whatever/apt/somelog.log",
},
"image": {
input: `<pre><img src="kubernetes.jpg"/><img src="/kubernetes_abs.jpg"/></pre>`,
sourceURL: "http://mynode.com/",
transport: testTransport,
output: `<pre><img src="kubernetes.jpg"/><img src="http://foo.com/proxy/node/node1:10250/kubernetes_abs.jpg"/></pre>`,
contentType: "text/html",
forwardedURI: "/proxy/node/node1:10250/",
},
"abs": {
input: `<script src="http://google.com/kubernetes.js"/>`,
sourceURL: "http://mynode.com/any/path/",
transport: testTransport,
output: `<script src="http://google.com/kubernetes.js"/>`,
contentType: "text/html",
forwardedURI: "/proxy/node/node1:10250/any/path/",
},
"abs but same host": {
input: `<script src="http://mynode.com/kubernetes.js"/>`,
sourceURL: "http://mynode.com/any/path/",
transport: testTransport,
output: `<script src="http://foo.com/proxy/node/node1:10250/kubernetes.js"/>`,
contentType: "text/html",
forwardedURI: "/proxy/node/node1:10250/any/path/",
},
"redirect rel": {
sourceURL: "http://mynode.com/redirect",
transport: testTransport,
redirect: "/redirected/target/",
redirectWant: "http://foo.com/proxy/node/node1:10250/redirected/target/",
forwardedURI: "/proxy/node/node1:10250/redirect",
},
"redirect abs same host": {
sourceURL: "http://mynode.com/redirect",
transport: testTransport,
redirect: "http://mynode.com/redirected/target/",
redirectWant: "http://foo.com/proxy/node/node1:10250/redirected/target/",
forwardedURI: "/proxy/node/node1:10250/redirect",
},
"redirect abs other host": {
sourceURL: "http://mynode.com/redirect",
transport: testTransport,
redirect: "http://example.com/redirected/target/",
redirectWant: "http://example.com/redirected/target/",
forwardedURI: "/proxy/node/node1:10250/redirect",
},
"source contains the redirect already": {
input: `<pre><a href="kubelet.log">kubelet.log</a><a href="http://foo.com/proxy/node/node1:10250/google.log">google.log</a></pre>`,
sourceURL: "http://foo.com/logs/log.log",
transport: testTransport,
output: `<pre><a href="kubelet.log">kubelet.log</a><a href="http://foo.com/proxy/node/node1:10250/google.log">google.log</a></pre>`,
contentType: "text/html",
forwardedURI: "/proxy/node/node1:10250/logs/log.log",
},
"no host": {
input: "<html></html>",
sourceURL: "http://mynode.com/logs/log.log",
transport: emptyHostTransport,
output: "<html></html>",
contentType: "text/html",
forwardedURI: "/proxy/node/node1:10250/logs/log.log",
},
"no scheme": {
input: "<html></html>",
sourceURL: "http://mynode.com/logs/log.log",
transport: emptySchemeTransport,
output: "<html></html>",
contentType: "text/html",
forwardedURI: "/proxy/node/node1:10250/logs/log.log",
},
}
testItem := func(name string, item *Item) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Check request headers.
if got, want := r.Header.Get("X-Forwarded-Uri"), item.forwardedURI; got != want {
t.Errorf("%v: X-Forwarded-Uri = %q, want %q", name, got, want)
}
if len(item.transport.Host) == 0 {
_, present := r.Header["X-Forwarded-Host"]
if present {
t.Errorf("%v: X-Forwarded-Host header should not be present", name)
}
} else {
if got, want := r.Header.Get("X-Forwarded-Host"), item.transport.Host; got != want {
t.Errorf("%v: X-Forwarded-Host = %q, want %q", name, got, want)
}
}
if len(item.transport.Scheme) == 0 {
_, present := r.Header["X-Forwarded-Proto"]
if present {
t.Errorf("%v: X-Forwarded-Proto header should not be present", name)
}
} else {
if got, want := r.Header.Get("X-Forwarded-Proto"), item.transport.Scheme; got != want {
t.Errorf("%v: X-Forwarded-Proto = %q, want %q", name, got, want)
}
}
// Send response.
if item.redirect != "" {
http.Redirect(w, r, item.redirect, http.StatusMovedPermanently)
return
}
w.Header().Set("Content-Type", item.contentType)
fmt.Fprint(w, item.input)
}))
defer server.Close()
// Replace source URL with our test server address.
sourceURL := parseURLOrDie(item.sourceURL)
serverURL := parseURLOrDie(server.URL)
item.input = strings.Replace(item.input, sourceURL.Host, serverURL.Host, -1)
item.redirect = strings.Replace(item.redirect, sourceURL.Host, serverURL.Host, -1)
sourceURL.Host = serverURL.Host
req, err := http.NewRequest("GET", sourceURL.String(), nil)
if err != nil {
t.Errorf("%v: Unexpected error: %v", name, err)
return
}
resp, err := item.transport.RoundTrip(req)
if err != nil {
t.Errorf("%v: Unexpected error: %v", name, err)
return
}
if item.redirect != "" {
// Check that redirect URLs get rewritten properly.
if got, want := resp.Header.Get("Location"), item.redirectWant; got != want {
t.Errorf("%v: Location header = %q, want %q", name, got, want)
}
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Errorf("%v: Unexpected error: %v", name, err)
return
}
if e, a := item.output, string(body); e != a {
t.Errorf("%v: expected %v, but got %v", name, e, a)
}
}
for name, item := range table {
testItem(name, &item)
}
}

View file

@ -1,413 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package proxy
import (
"bytes"
"context"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"sync"
"time"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/util/httpstream"
utilnet "k8s.io/apimachinery/pkg/util/net"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"github.com/golang/glog"
"github.com/mxk/go-flowrate/flowrate"
)
// UpgradeRequestRoundTripper provides an additional method to decorate a request
// with any authentication or other protocol level information prior to performing
// an upgrade on the server. Any response will be handled by the intercepting
// proxy.
type UpgradeRequestRoundTripper interface {
http.RoundTripper
// WrapRequest takes a valid HTTP request and returns a suitably altered version
// of request with any HTTP level values required to complete the request half of
// an upgrade on the server. It does not get a chance to see the response and
// should bypass any request side logic that expects to see the response.
WrapRequest(*http.Request) (*http.Request, error)
}
// UpgradeAwareHandler is a handler for proxy requests that may require an upgrade
type UpgradeAwareHandler struct {
// UpgradeRequired will reject non-upgrade connections if true.
UpgradeRequired bool
// Location is the location of the upstream proxy. It is used as the location to Dial on the upstream server
// for upgrade requests unless UseRequestLocationOnUpgrade is true.
Location *url.URL
// Transport provides an optional round tripper to use to proxy. If nil, the default proxy transport is used
Transport http.RoundTripper
// UpgradeTransport, if specified, will be used as the backend transport when upgrade requests are provided.
// This allows clients to disable HTTP/2.
UpgradeTransport UpgradeRequestRoundTripper
// WrapTransport indicates whether the provided Transport should be wrapped with default proxy transport behavior (URL rewriting, X-Forwarded-* header setting)
WrapTransport bool
// InterceptRedirects determines whether the proxy should sniff backend responses for redirects,
// following them as necessary.
InterceptRedirects bool
// UseRequestLocation will use the incoming request URL when talking to the backend server.
UseRequestLocation bool
// FlushInterval controls how often the standard HTTP proxy will flush content from the upstream.
FlushInterval time.Duration
// MaxBytesPerSec controls the maximum rate for an upstream connection. No rate is imposed if the value is zero.
MaxBytesPerSec int64
// Responder is passed errors that occur while setting up proxying.
Responder ErrorResponder
}
const defaultFlushInterval = 200 * time.Millisecond
// ErrorResponder abstracts error reporting to the proxy handler to remove the need to hardcode a particular
// error format.
type ErrorResponder interface {
Error(w http.ResponseWriter, req *http.Request, err error)
}
// SimpleErrorResponder is the legacy implementation of ErrorResponder for callers that only
// service a single request/response per proxy.
type SimpleErrorResponder interface {
Error(err error)
}
func NewErrorResponder(r SimpleErrorResponder) ErrorResponder {
return simpleResponder{r}
}
type simpleResponder struct {
responder SimpleErrorResponder
}
func (r simpleResponder) Error(w http.ResponseWriter, req *http.Request, err error) {
r.responder.Error(err)
}
// upgradeRequestRoundTripper implements proxy.UpgradeRequestRoundTripper.
type upgradeRequestRoundTripper struct {
http.RoundTripper
upgrader http.RoundTripper
}
var (
_ UpgradeRequestRoundTripper = &upgradeRequestRoundTripper{}
_ utilnet.RoundTripperWrapper = &upgradeRequestRoundTripper{}
)
// WrappedRoundTripper returns the round tripper that a caller would use.
func (rt *upgradeRequestRoundTripper) WrappedRoundTripper() http.RoundTripper {
return rt.RoundTripper
}
// WriteToRequest calls the nested upgrader and then copies the returned request
// fields onto the passed request.
func (rt *upgradeRequestRoundTripper) WrapRequest(req *http.Request) (*http.Request, error) {
resp, err := rt.upgrader.RoundTrip(req)
if err != nil {
return nil, err
}
return resp.Request, nil
}
// onewayRoundTripper captures the provided request - which is assumed to have
// been modified by other round trippers - and then returns a fake response.
type onewayRoundTripper struct{}
// RoundTrip returns a simple 200 OK response that captures the provided request.
func (onewayRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
return &http.Response{
Status: "200 OK",
StatusCode: http.StatusOK,
Body: ioutil.NopCloser(&bytes.Buffer{}),
Request: req,
}, nil
}
// MirrorRequest is a round tripper that can be called to get back the calling request as
// the core round tripper in a chain.
var MirrorRequest http.RoundTripper = onewayRoundTripper{}
// NewUpgradeRequestRoundTripper takes two round trippers - one for the underlying TCP connection, and
// one that is able to write headers to an HTTP request. The request rt is used to set the request headers
// and that is written to the underlying connection rt.
func NewUpgradeRequestRoundTripper(connection, request http.RoundTripper) UpgradeRequestRoundTripper {
return &upgradeRequestRoundTripper{
RoundTripper: connection,
upgrader: request,
}
}
// normalizeLocation returns the result of parsing the full URL, with scheme set to http if missing
func normalizeLocation(location *url.URL) *url.URL {
normalized, _ := url.Parse(location.String())
if len(normalized.Scheme) == 0 {
normalized.Scheme = "http"
}
return normalized
}
// NewUpgradeAwareHandler creates a new proxy handler with a default flush interval. Responder is required for returning
// errors to the caller.
func NewUpgradeAwareHandler(location *url.URL, transport http.RoundTripper, wrapTransport, upgradeRequired bool, responder ErrorResponder) *UpgradeAwareHandler {
return &UpgradeAwareHandler{
Location: normalizeLocation(location),
Transport: transport,
WrapTransport: wrapTransport,
UpgradeRequired: upgradeRequired,
FlushInterval: defaultFlushInterval,
Responder: responder,
}
}
// ServeHTTP handles the proxy request
func (h *UpgradeAwareHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if h.tryUpgrade(w, req) {
return
}
if h.UpgradeRequired {
h.Responder.Error(w, req, errors.NewBadRequest("Upgrade request required"))
return
}
loc := *h.Location
loc.RawQuery = req.URL.RawQuery
// If original request URL ended in '/', append a '/' at the end of the
// of the proxy URL
if !strings.HasSuffix(loc.Path, "/") && strings.HasSuffix(req.URL.Path, "/") {
loc.Path += "/"
}
// From pkg/genericapiserver/endpoints/handlers/proxy.go#ServeHTTP:
// Redirect requests with an empty path to a location that ends with a '/'
// This is essentially a hack for http://issue.k8s.io/4958.
// Note: Keep this code after tryUpgrade to not break that flow.
if len(loc.Path) == 0 {
var queryPart string
if len(req.URL.RawQuery) > 0 {
queryPart = "?" + req.URL.RawQuery
}
w.Header().Set("Location", req.URL.Path+"/"+queryPart)
w.WriteHeader(http.StatusMovedPermanently)
return
}
if h.Transport == nil || h.WrapTransport {
h.Transport = h.defaultProxyTransport(req.URL, h.Transport)
}
// WithContext creates a shallow clone of the request with the new context.
newReq := req.WithContext(context.Background())
newReq.Header = utilnet.CloneHeader(req.Header)
if !h.UseRequestLocation {
newReq.URL = &loc
}
proxy := httputil.NewSingleHostReverseProxy(&url.URL{Scheme: h.Location.Scheme, Host: h.Location.Host})
proxy.Transport = h.Transport
proxy.FlushInterval = h.FlushInterval
proxy.ServeHTTP(w, newReq)
}
// tryUpgrade returns true if the request was handled.
func (h *UpgradeAwareHandler) tryUpgrade(w http.ResponseWriter, req *http.Request) bool {
if !httpstream.IsUpgradeRequest(req) {
glog.V(6).Infof("Request was not an upgrade")
return false
}
var (
backendConn net.Conn
rawResponse []byte
err error
)
location := *h.Location
if h.UseRequestLocation {
location = *req.URL
location.Scheme = h.Location.Scheme
location.Host = h.Location.Host
}
clone := utilnet.CloneRequest(req)
// Only append X-Forwarded-For in the upgrade path, since httputil.NewSingleHostReverseProxy
// handles this in the non-upgrade path.
utilnet.AppendForwardedForHeader(clone)
if h.InterceptRedirects {
glog.V(6).Infof("Connecting to backend proxy (intercepting redirects) %s\n Headers: %v", &location, clone.Header)
backendConn, rawResponse, err = utilnet.ConnectWithRedirects(req.Method, &location, clone.Header, req.Body, utilnet.DialerFunc(h.DialForUpgrade))
} else {
glog.V(6).Infof("Connecting to backend proxy (direct dial) %s\n Headers: %v", &location, clone.Header)
clone.URL = &location
backendConn, err = h.DialForUpgrade(clone)
}
if err != nil {
glog.V(6).Infof("Proxy connection error: %v", err)
h.Responder.Error(w, req, err)
return true
}
defer backendConn.Close()
// Once the connection is hijacked, the ErrorResponder will no longer work, so
// hijacking should be the last step in the upgrade.
requestHijacker, ok := w.(http.Hijacker)
if !ok {
glog.V(6).Infof("Unable to hijack response writer: %T", w)
h.Responder.Error(w, req, fmt.Errorf("request connection cannot be hijacked: %T", w))
return true
}
requestHijackedConn, _, err := requestHijacker.Hijack()
if err != nil {
glog.V(6).Infof("Unable to hijack response: %v", err)
h.Responder.Error(w, req, fmt.Errorf("error hijacking connection: %v", err))
return true
}
defer requestHijackedConn.Close()
// Forward raw response bytes back to client.
if len(rawResponse) > 0 {
glog.V(6).Infof("Writing %d bytes to hijacked connection", len(rawResponse))
if _, err = requestHijackedConn.Write(rawResponse); err != nil {
utilruntime.HandleError(fmt.Errorf("Error proxying response from backend to client: %v", err))
}
}
// Proxy the connection.
wg := &sync.WaitGroup{}
wg.Add(2)
go func() {
var writer io.WriteCloser
if h.MaxBytesPerSec > 0 {
writer = flowrate.NewWriter(backendConn, h.MaxBytesPerSec)
} else {
writer = backendConn
}
_, err := io.Copy(writer, requestHijackedConn)
if err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
glog.Errorf("Error proxying data from client to backend: %v", err)
}
wg.Done()
}()
go func() {
var reader io.ReadCloser
if h.MaxBytesPerSec > 0 {
reader = flowrate.NewReader(backendConn, h.MaxBytesPerSec)
} else {
reader = backendConn
}
_, err := io.Copy(requestHijackedConn, reader)
if err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
glog.Errorf("Error proxying data from backend to client: %v", err)
}
wg.Done()
}()
wg.Wait()
return true
}
func (h *UpgradeAwareHandler) Dial(req *http.Request) (net.Conn, error) {
return dial(req, h.Transport)
}
func (h *UpgradeAwareHandler) DialForUpgrade(req *http.Request) (net.Conn, error) {
if h.UpgradeTransport == nil {
return dial(req, h.Transport)
}
updatedReq, err := h.UpgradeTransport.WrapRequest(req)
if err != nil {
return nil, err
}
return dial(updatedReq, h.UpgradeTransport)
}
// dial dials the backend at req.URL and writes req to it.
func dial(req *http.Request, transport http.RoundTripper) (net.Conn, error) {
conn, err := DialURL(req.URL, transport)
if err != nil {
return nil, fmt.Errorf("error dialing backend: %v", err)
}
if err = req.Write(conn); err != nil {
conn.Close()
return nil, fmt.Errorf("error sending request: %v", err)
}
return conn, err
}
var _ utilnet.Dialer = &UpgradeAwareHandler{}
func (h *UpgradeAwareHandler) defaultProxyTransport(url *url.URL, internalTransport http.RoundTripper) http.RoundTripper {
scheme := url.Scheme
host := url.Host
suffix := h.Location.Path
if strings.HasSuffix(url.Path, "/") && !strings.HasSuffix(suffix, "/") {
suffix += "/"
}
pathPrepend := strings.TrimSuffix(url.Path, suffix)
rewritingTransport := &Transport{
Scheme: scheme,
Host: host,
PathPrepend: pathPrepend,
RoundTripper: internalTransport,
}
return &corsRemovingTransport{
RoundTripper: rewritingTransport,
}
}
// corsRemovingTransport is a wrapper for an internal transport. It removes CORS headers
// from the internal response.
// Implements pkg/util/net.RoundTripperWrapper
type corsRemovingTransport struct {
http.RoundTripper
}
var _ = utilnet.RoundTripperWrapper(&corsRemovingTransport{})
func (rt *corsRemovingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
resp, err := rt.RoundTripper.RoundTrip(req)
if err != nil {
return nil, err
}
removeCORSHeaders(resp)
return resp, nil
}
func (rt *corsRemovingTransport) WrappedRoundTripper() http.RoundTripper {
return rt.RoundTripper
}
// removeCORSHeaders strip CORS headers sent from the backend
// This should be called on all responses before returning
func removeCORSHeaders(resp *http.Response) {
resp.Header.Del("Access-Control-Allow-Credentials")
resp.Header.Del("Access-Control-Allow-Headers")
resp.Header.Del("Access-Control-Allow-Methods")
resp.Header.Del("Access-Control-Allow-Origin")
}

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