Finish implementing policy API.

Registry implementation and addition to the master.
This commit is contained in:
Matt Liggett 2016-05-06 17:03:43 -07:00
parent 24c46acd16
commit f5e8d41431
34 changed files with 3574 additions and 11 deletions

View File

@ -0,0 +1,110 @@
{
"swaggerVersion": "1.2",
"apiVersion": "",
"basePath": "https://10.10.10.10:443",
"resourcePath": "/apis/policy",
"apis": [
{
"path": "/apis/policy",
"description": "get information of a group",
"operations": [
{
"type": "unversioned.APIGroup",
"method": "GET",
"summary": "get information of a group",
"nickname": "getAPIGroup",
"parameters": [],
"produces": [
"application/json",
"application/yaml",
"application/vnd.kubernetes.protobuf"
],
"consumes": [
"application/json",
"application/yaml",
"application/vnd.kubernetes.protobuf"
]
}
]
}
],
"models": {
"unversioned.APIGroup": {
"id": "unversioned.APIGroup",
"description": "APIGroup contains the name, the supported versions, and the preferred version of a group.",
"required": [
"name",
"versions",
"serverAddressByClientCIDRs"
],
"properties": {
"kind": {
"type": "string",
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds"
},
"apiVersion": {
"type": "string",
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources"
},
"name": {
"type": "string",
"description": "name is the name of the group."
},
"versions": {
"type": "array",
"items": {
"$ref": "unversioned.GroupVersionForDiscovery"
},
"description": "versions are the versions supported in this group."
},
"preferredVersion": {
"$ref": "unversioned.GroupVersionForDiscovery",
"description": "preferredVersion is the version preferred by the API server, which probably is the storage version."
},
"serverAddressByClientCIDRs": {
"type": "array",
"items": {
"$ref": "unversioned.ServerAddressByClientCIDR"
},
"description": "a map of client CIDR to server address that is serving this group. This is to help clients reach servers in the most network-efficient way possible. Clients can use the appropriate server address as per the CIDR that they match. In case of multiple matches, clients should use the longest matching CIDR. The server returns only those CIDRs that it thinks that the client can match. For example: the master will return an internal IP CIDR only, if the client reaches the server using an internal IP. Server looks at X-Forwarded-For header or X-Real-Ip header or request.RemoteAddr (in that order) to get the client IP."
}
}
},
"unversioned.GroupVersionForDiscovery": {
"id": "unversioned.GroupVersionForDiscovery",
"description": "GroupVersion contains the \"group/version\" and \"version\" string of a version. It is made a struct to keep extensiblity.",
"required": [
"groupVersion",
"version"
],
"properties": {
"groupVersion": {
"type": "string",
"description": "groupVersion specifies the API group and version in the form \"group/version\""
},
"version": {
"type": "string",
"description": "version specifies the version in the form of \"version\". This is to save the clients the trouble of splitting the GroupVersion."
}
}
},
"unversioned.ServerAddressByClientCIDR": {
"id": "unversioned.ServerAddressByClientCIDR",
"description": "ServerAddressByClientCIDR helps the client to determine the server address that they should use, depending on the clientCIDR that they match.",
"required": [
"clientCIDR",
"serverAddress"
],
"properties": {
"clientCIDR": {
"type": "string",
"description": "The CIDR with which clients can match their IP to figure out the server address that they should use."
},
"serverAddress": {
"type": "string",
"description": "Address of this server, suitable for a client that matches the above CIDR. This can be a hostname, hostname:port, IP or IP:port."
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,14 @@
"path": "/apis/batch",
"description": "get information of a group"
},
{
"path": "/apis/policy/v1alpha1",
"description": "API at /apis/policy/v1alpha1"
},
{
"path": "/apis/policy",
"description": "get information of a group"
},
{
"path": "/apis/apps/v1alpha1",
"description": "API at /apis/apps/v1alpha1"

View File

@ -29,7 +29,7 @@ source "${KUBE_ROOT}/hack/lib/init.sh"
# "v1,compute/v1alpha1,experimental/v1alpha2;v1,compute/v2,experimental/v1alpha3"
# TODO: It's going to be:
# KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1"}
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1;v1,autoscaling/v1,batch/v1,apps/v1alpha1,extensions/v1beta1"}
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1;v1,autoscaling/v1,batch/v1,apps/v1alpha1,policy/v1alpha1,extensions/v1beta1"}
# Give integration tests longer to run
KUBE_TIMEOUT=${KUBE_TIMEOUT:--timeout 240s}

View File

@ -57,7 +57,7 @@ EOF
mv "$TMPFILE" "pkg/$(kube::util::group-version-to-pkg-path "${group_version}")/types_swagger_doc_generated.go"
}
GROUP_VERSIONS=(unversioned v1 authorization/v1beta1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 apps/v1alpha1 rbac/v1alpha1)
GROUP_VERSIONS=(unversioned v1 authorization/v1beta1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 apps/v1alpha1 policy/v1alpha1 rbac/v1alpha1)
# To avoid compile errors, remove the currently existing files.
for group_version in "${GROUP_VERSIONS[@]}"; do
rm -f "pkg/$(kube::util::group-version-to-pkg-path "${group_version}")/types_swagger_doc_generated.go"

View File

@ -74,7 +74,7 @@ APISERVER_PID=$!
kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/healthz" "apiserver: "
SWAGGER_API_PATH="http://127.0.0.1:${API_PORT}/swaggerapi/"
DEFAULT_GROUP_VERSIONS="v1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 apps/v1alpha1"
DEFAULT_GROUP_VERSIONS="v1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 apps/v1alpha1 policy/v1alpha1"
VERSIONS=${VERSIONS:-$DEFAULT_GROUP_VERSIONS}
kube::log::status "Updating " ${SWAGGER_ROOT_DIR}

View File

@ -33,6 +33,7 @@ import (
"k8s.io/kubernetes/pkg/apis/autoscaling"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/serializer/recognizer"
@ -44,6 +45,7 @@ import (
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
_ "k8s.io/kubernetes/pkg/apis/metrics/install"
_ "k8s.io/kubernetes/pkg/apis/policy/install"
)
var (
@ -53,6 +55,7 @@ var (
Batch TestGroup
Extensions TestGroup
Apps TestGroup
Policy TestGroup
Federation TestGroup
serializer runtime.SerializerInfo
@ -174,6 +177,13 @@ func init() {
internalTypes: api.Scheme.KnownTypes(extensions.SchemeGroupVersion),
}
}
if _, ok := Groups[policy.GroupName]; !ok {
Groups[policy.GroupName] = TestGroup{
externalGroupVersions: []unversioned.GroupVersion{{Group: policy.GroupName, Version: registered.GroupOrDie(policy.GroupName).GroupVersion.Version}},
internalGroupVersion: policy.SchemeGroupVersion,
internalTypes: api.Scheme.KnownTypes(policy.SchemeGroupVersion),
}
}
if _, ok := Groups[federation.GroupName]; !ok {
Groups[federation.GroupName] = TestGroup{
externalGroupVersions: []unversioned.GroupVersion{{Group: federation.GroupName, Version: registered.GroupOrDie(federation.GroupName).GroupVersion.Version}},
@ -186,6 +196,7 @@ func init() {
Autoscaling = Groups[autoscaling.GroupName]
Batch = Groups[batch.GroupName]
Apps = Groups[apps.GroupName]
Policy = Groups[policy.GroupName]
Extensions = Groups[extensions.GroupName]
Federation = Groups[federation.GroupName]
}

View File

@ -30,6 +30,7 @@ import (
func init() {
if err := api.Scheme.AddGeneratedDeepCopyFuncs(
DeepCopy_policy_PodDisruptionBudget,
DeepCopy_policy_PodDisruptionBudgetList,
DeepCopy_policy_PodDisruptionBudgetSpec,
DeepCopy_policy_PodDisruptionBudgetStatus,
); err != nil {
@ -54,6 +55,27 @@ func DeepCopy_policy_PodDisruptionBudget(in PodDisruptionBudget, out *PodDisrupt
return nil
}
func DeepCopy_policy_PodDisruptionBudgetList(in PodDisruptionBudgetList, out *PodDisruptionBudgetList, c *conversion.Cloner) error {
if err := unversioned.DeepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
return err
}
if err := unversioned.DeepCopy_unversioned_ListMeta(in.ListMeta, &out.ListMeta, c); err != nil {
return err
}
if in.Items != nil {
in, out := in.Items, &out.Items
*out = make([]PodDisruptionBudget, len(in))
for i := range in {
if err := DeepCopy_policy_PodDisruptionBudget(in[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
func DeepCopy_policy_PodDisruptionBudgetSpec(in PodDisruptionBudgetSpec, out *PodDisruptionBudgetSpec, c *conversion.Cloner) error {
if err := intstr.DeepCopy_intstr_IntOrString(in.MinAvailable, &out.MinAvailable, c); err != nil {
return err

View File

@ -47,7 +47,9 @@ func addKnownTypes(scheme *runtime.Scheme) {
// TODO this gets cleaned up when the types are fixed
scheme.AddKnownTypes(SchemeGroupVersion,
&PodDisruptionBudget{},
&PodDisruptionBudgetList{},
)
}
func (obj *PodDisruptionBudget) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodDisruptionBudget) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodDisruptionBudgetList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

View File

@ -975,3 +975,466 @@ func (x *PodDisruptionBudget) codecDecodeSelfFromArray(l int, d *codec1978.Decod
}
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
func (x *PodDisruptionBudgetList) CodecEncodeSelf(e *codec1978.Encoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperEncoder(e)
_, _, _ = h, z, r
if x == nil {
r.EncodeNil()
} else {
yym1 := z.EncBinary()
_ = yym1
if false {
} else if z.HasExtensions() && z.EncExt(x) {
} else {
yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [4]bool
_, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false
yyq2[0] = true
yyq2[2] = x.Kind != ""
yyq2[3] = x.APIVersion != ""
var yynn2 int
if yyr2 || yy2arr2 {
r.EncodeArrayStart(4)
} else {
yynn2 = 1
for _, b := range yyq2 {
if b {
yynn2++
}
}
r.EncodeMapStart(yynn2)
yynn2 = 0
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[0] {
yy4 := &x.ListMeta
yym5 := z.EncBinary()
_ = yym5
if false {
} else if z.HasExtensions() && z.EncExt(yy4) {
} else {
z.EncFallback(yy4)
}
} else {
r.EncodeNil()
}
} else {
if yyq2[0] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("metadata"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yy6 := &x.ListMeta
yym7 := z.EncBinary()
_ = yym7
if false {
} else if z.HasExtensions() && z.EncExt(yy6) {
} else {
z.EncFallback(yy6)
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if x.Items == nil {
r.EncodeNil()
} else {
yym9 := z.EncBinary()
_ = yym9
if false {
} else {
h.encSlicePodDisruptionBudget(([]PodDisruptionBudget)(x.Items), e)
}
}
} else {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("items"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
if x.Items == nil {
r.EncodeNil()
} else {
yym10 := z.EncBinary()
_ = yym10
if false {
} else {
h.encSlicePodDisruptionBudget(([]PodDisruptionBudget)(x.Items), e)
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[2] {
yym12 := z.EncBinary()
_ = yym12
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
}
} else {
r.EncodeString(codecSelferC_UTF81234, "")
}
} else {
if yyq2[2] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("kind"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym13 := z.EncBinary()
_ = yym13
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[3] {
yym15 := z.EncBinary()
_ = yym15
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
}
} else {
r.EncodeString(codecSelferC_UTF81234, "")
}
} else {
if yyq2[3] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("apiVersion"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym16 := z.EncBinary()
_ = yym16
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
z.EncSendContainerState(codecSelfer_containerMapEnd1234)
}
}
}
}
func (x *PodDisruptionBudgetList) CodecDecodeSelf(d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
yym1 := z.DecBinary()
_ = yym1
if false {
} else if z.HasExtensions() && z.DecExt(x) {
} else {
yyct2 := r.ContainerType()
if yyct2 == codecSelferValueTypeMap1234 {
yyl2 := r.ReadMapStart()
if yyl2 == 0 {
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
} else {
x.codecDecodeSelfFromMap(yyl2, d)
}
} else if yyct2 == codecSelferValueTypeArray1234 {
yyl2 := r.ReadArrayStart()
if yyl2 == 0 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
x.codecDecodeSelfFromArray(yyl2, d)
}
} else {
panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234)
}
}
}
func (x *PodDisruptionBudgetList) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yys3Slc = z.DecScratchBuffer() // default slice to decode into
_ = yys3Slc
var yyhl3 bool = l >= 0
for yyj3 := 0; ; yyj3++ {
if yyhl3 {
if yyj3 >= l {
break
}
} else {
if r.CheckBreak() {
break
}
}
z.DecSendContainerState(codecSelfer_containerMapKey1234)
yys3Slc = r.DecodeBytes(yys3Slc, true, true)
yys3 := string(yys3Slc)
z.DecSendContainerState(codecSelfer_containerMapValue1234)
switch yys3 {
case "metadata":
if r.TryDecodeAsNil() {
x.ListMeta = pkg2_unversioned.ListMeta{}
} else {
yyv4 := &x.ListMeta
yym5 := z.DecBinary()
_ = yym5
if false {
} else if z.HasExtensions() && z.DecExt(yyv4) {
} else {
z.DecFallback(yyv4, false)
}
}
case "items":
if r.TryDecodeAsNil() {
x.Items = nil
} else {
yyv6 := &x.Items
yym7 := z.DecBinary()
_ = yym7
if false {
} else {
h.decSlicePodDisruptionBudget((*[]PodDisruptionBudget)(yyv6), d)
}
}
case "kind":
if r.TryDecodeAsNil() {
x.Kind = ""
} else {
x.Kind = string(r.DecodeString())
}
case "apiVersion":
if r.TryDecodeAsNil() {
x.APIVersion = ""
} else {
x.APIVersion = string(r.DecodeString())
}
default:
z.DecStructFieldNotFound(-1, yys3)
} // end switch yys3
} // end for yyj3
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
}
func (x *PodDisruptionBudgetList) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yyj10 int
var yyb10 bool
var yyhl10 bool = l >= 0
yyj10++
if yyhl10 {
yyb10 = yyj10 > l
} else {
yyb10 = r.CheckBreak()
}
if yyb10 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.ListMeta = pkg2_unversioned.ListMeta{}
} else {
yyv11 := &x.ListMeta
yym12 := z.DecBinary()
_ = yym12
if false {
} else if z.HasExtensions() && z.DecExt(yyv11) {
} else {
z.DecFallback(yyv11, false)
}
}
yyj10++
if yyhl10 {
yyb10 = yyj10 > l
} else {
yyb10 = r.CheckBreak()
}
if yyb10 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.Items = nil
} else {
yyv13 := &x.Items
yym14 := z.DecBinary()
_ = yym14
if false {
} else {
h.decSlicePodDisruptionBudget((*[]PodDisruptionBudget)(yyv13), d)
}
}
yyj10++
if yyhl10 {
yyb10 = yyj10 > l
} else {
yyb10 = r.CheckBreak()
}
if yyb10 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.Kind = ""
} else {
x.Kind = string(r.DecodeString())
}
yyj10++
if yyhl10 {
yyb10 = yyj10 > l
} else {
yyb10 = r.CheckBreak()
}
if yyb10 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.APIVersion = ""
} else {
x.APIVersion = string(r.DecodeString())
}
for {
yyj10++
if yyhl10 {
yyb10 = yyj10 > l
} else {
yyb10 = r.CheckBreak()
}
if yyb10 {
break
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj10-1, "")
}
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
func (x codecSelfer1234) encSlicePodDisruptionBudget(v []PodDisruptionBudget, e *codec1978.Encoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperEncoder(e)
_, _, _ = h, z, r
r.EncodeArrayStart(len(v))
for _, yyv1 := range v {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
yy2 := &yyv1
yy2.CodecEncodeSelf(e)
}
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
}
func (x codecSelfer1234) decSlicePodDisruptionBudget(v *[]PodDisruptionBudget, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
yyv1 := *v
yyh1, yyl1 := z.DecSliceHelperStart()
var yyc1 bool
_ = yyc1
if yyl1 == 0 {
if yyv1 == nil {
yyv1 = []PodDisruptionBudget{}
yyc1 = true
} else if len(yyv1) != 0 {
yyv1 = yyv1[:0]
yyc1 = true
}
} else if yyl1 > 0 {
var yyrr1, yyrl1 int
var yyrt1 bool
_, _ = yyrl1, yyrt1
yyrr1 = yyl1 // len(yyv1)
if yyl1 > cap(yyv1) {
yyrg1 := len(yyv1) > 0
yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 296)
if yyrt1 {
if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1]
} else {
yyv1 = make([]PodDisruptionBudget, yyrl1)
}
} else {
yyv1 = make([]PodDisruptionBudget, yyrl1)
}
yyc1 = true
yyrr1 = len(yyv1)
if yyrg1 {
copy(yyv1, yyv21)
}
} else if yyl1 != len(yyv1) {
yyv1 = yyv1[:yyl1]
yyc1 = true
}
yyj1 := 0
for ; yyj1 < yyrr1; yyj1++ {
yyh1.ElemContainerState(yyj1)
if r.TryDecodeAsNil() {
yyv1[yyj1] = PodDisruptionBudget{}
} else {
yyv2 := &yyv1[yyj1]
yyv2.CodecDecodeSelf(d)
}
}
if yyrt1 {
for ; yyj1 < yyl1; yyj1++ {
yyv1 = append(yyv1, PodDisruptionBudget{})
yyh1.ElemContainerState(yyj1)
if r.TryDecodeAsNil() {
yyv1[yyj1] = PodDisruptionBudget{}
} else {
yyv3 := &yyv1[yyj1]
yyv3.CodecDecodeSelf(d)
}
}
}
} else {
yyj1 := 0
for ; !r.CheckBreak(); yyj1++ {
if yyj1 >= len(yyv1) {
yyv1 = append(yyv1, PodDisruptionBudget{}) // var yyz1 PodDisruptionBudget
yyc1 = true
}
yyh1.ElemContainerState(yyj1)
if yyj1 < len(yyv1) {
if r.TryDecodeAsNil() {
yyv1[yyj1] = PodDisruptionBudget{}
} else {
yyv4 := &yyv1[yyj1]
yyv4.CodecDecodeSelf(d)
}
} else {
z.DecSwallow()
}
}
if yyj1 < len(yyv1) {
yyv1 = yyv1[:yyj1]
yyc1 = true
} else if yyj1 == 0 && yyv1 == nil {
yyv1 = []PodDisruptionBudget{}
yyc1 = true
}
}
yyh1.End()
if yyc1 {
*v = yyv1
}
}

View File

@ -61,3 +61,10 @@ type PodDisruptionBudget struct {
// Most recently observed status of the PodDisruptionBudget.
Status PodDisruptionBudgetStatus `json:"status,omitempty"`
}
// PodDisruptionBudgetList is a collection of PodDisruptionBudgets.
type PodDisruptionBudgetList struct {
unversioned.TypeMeta `json:",inline"`
unversioned.ListMeta `json:"metadata,omitempty"`
Items []PodDisruptionBudget `json:"items"`
}

View File

@ -31,6 +31,8 @@ func init() {
if err := api.Scheme.AddGeneratedConversionFuncs(
Convert_v1alpha1_PodDisruptionBudget_To_policy_PodDisruptionBudget,
Convert_policy_PodDisruptionBudget_To_v1alpha1_PodDisruptionBudget,
Convert_v1alpha1_PodDisruptionBudgetList_To_policy_PodDisruptionBudgetList,
Convert_policy_PodDisruptionBudgetList_To_v1alpha1_PodDisruptionBudgetList,
Convert_v1alpha1_PodDisruptionBudgetSpec_To_policy_PodDisruptionBudgetSpec,
Convert_policy_PodDisruptionBudgetSpec_To_v1alpha1_PodDisruptionBudgetSpec,
Convert_v1alpha1_PodDisruptionBudgetStatus_To_policy_PodDisruptionBudgetStatus,
@ -83,6 +85,56 @@ func Convert_policy_PodDisruptionBudget_To_v1alpha1_PodDisruptionBudget(in *poli
return autoConvert_policy_PodDisruptionBudget_To_v1alpha1_PodDisruptionBudget(in, out, s)
}
func autoConvert_v1alpha1_PodDisruptionBudgetList_To_policy_PodDisruptionBudgetList(in *PodDisruptionBudgetList, out *policy.PodDisruptionBudgetList, s conversion.Scope) error {
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := api.Convert_unversioned_ListMeta_To_unversioned_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
return err
}
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]policy.PodDisruptionBudget, len(*in))
for i := range *in {
if err := Convert_v1alpha1_PodDisruptionBudget_To_policy_PodDisruptionBudget(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
func Convert_v1alpha1_PodDisruptionBudgetList_To_policy_PodDisruptionBudgetList(in *PodDisruptionBudgetList, out *policy.PodDisruptionBudgetList, s conversion.Scope) error {
return autoConvert_v1alpha1_PodDisruptionBudgetList_To_policy_PodDisruptionBudgetList(in, out, s)
}
func autoConvert_policy_PodDisruptionBudgetList_To_v1alpha1_PodDisruptionBudgetList(in *policy.PodDisruptionBudgetList, out *PodDisruptionBudgetList, s conversion.Scope) error {
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := api.Convert_unversioned_ListMeta_To_unversioned_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
return err
}
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]PodDisruptionBudget, len(*in))
for i := range *in {
if err := Convert_policy_PodDisruptionBudget_To_v1alpha1_PodDisruptionBudget(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
func Convert_policy_PodDisruptionBudgetList_To_v1alpha1_PodDisruptionBudgetList(in *policy.PodDisruptionBudgetList, out *PodDisruptionBudgetList, s conversion.Scope) error {
return autoConvert_policy_PodDisruptionBudgetList_To_v1alpha1_PodDisruptionBudgetList(in, out, s)
}
func autoConvert_v1alpha1_PodDisruptionBudgetSpec_To_policy_PodDisruptionBudgetSpec(in *PodDisruptionBudgetSpec, out *policy.PodDisruptionBudgetSpec, s conversion.Scope) error {
if err := api.Convert_intstr_IntOrString_To_intstr_IntOrString(&in.MinAvailable, &out.MinAvailable, s); err != nil {
return err

View File

@ -31,6 +31,7 @@ import (
func init() {
if err := api.Scheme.AddGeneratedDeepCopyFuncs(
DeepCopy_v1alpha1_PodDisruptionBudget,
DeepCopy_v1alpha1_PodDisruptionBudgetList,
DeepCopy_v1alpha1_PodDisruptionBudgetSpec,
DeepCopy_v1alpha1_PodDisruptionBudgetStatus,
); err != nil {
@ -55,6 +56,27 @@ func DeepCopy_v1alpha1_PodDisruptionBudget(in PodDisruptionBudget, out *PodDisru
return nil
}
func DeepCopy_v1alpha1_PodDisruptionBudgetList(in PodDisruptionBudgetList, out *PodDisruptionBudgetList, c *conversion.Cloner) error {
if err := unversioned.DeepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
return err
}
if err := unversioned.DeepCopy_unversioned_ListMeta(in.ListMeta, &out.ListMeta, c); err != nil {
return err
}
if in.Items != nil {
in, out := in.Items, &out.Items
*out = make([]PodDisruptionBudget, len(in))
for i := range in {
if err := DeepCopy_v1alpha1_PodDisruptionBudget(in[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
func DeepCopy_v1alpha1_PodDisruptionBudgetSpec(in PodDisruptionBudgetSpec, out *PodDisruptionBudgetSpec, c *conversion.Cloner) error {
if err := intstr.DeepCopy_intstr_IntOrString(in.MinAvailable, &out.MinAvailable, c); err != nil {
return err

View File

@ -26,6 +26,7 @@ limitations under the License.
It has these top-level messages:
PodDisruptionBudget
PodDisruptionBudgetList
PodDisruptionBudgetSpec
PodDisruptionBudgetStatus
*/
@ -48,6 +49,10 @@ func (m *PodDisruptionBudget) Reset() { *m = PodDisruptionBudget{} }
func (m *PodDisruptionBudget) String() string { return proto.CompactTextString(m) }
func (*PodDisruptionBudget) ProtoMessage() {}
func (m *PodDisruptionBudgetList) Reset() { *m = PodDisruptionBudgetList{} }
func (m *PodDisruptionBudgetList) String() string { return proto.CompactTextString(m) }
func (*PodDisruptionBudgetList) ProtoMessage() {}
func (m *PodDisruptionBudgetSpec) Reset() { *m = PodDisruptionBudgetSpec{} }
func (m *PodDisruptionBudgetSpec) String() string { return proto.CompactTextString(m) }
func (*PodDisruptionBudgetSpec) ProtoMessage() {}
@ -58,6 +63,7 @@ func (*PodDisruptionBudgetStatus) ProtoMessage() {}
func init() {
proto.RegisterType((*PodDisruptionBudget)(nil), "k8s.io.kubernetes.pkg.apis.policy.v1alpha1.PodDisruptionBudget")
proto.RegisterType((*PodDisruptionBudgetList)(nil), "k8s.io.kubernetes.pkg.apis.policy.v1alpha1.PodDisruptionBudgetList")
proto.RegisterType((*PodDisruptionBudgetSpec)(nil), "k8s.io.kubernetes.pkg.apis.policy.v1alpha1.PodDisruptionBudgetSpec")
proto.RegisterType((*PodDisruptionBudgetStatus)(nil), "k8s.io.kubernetes.pkg.apis.policy.v1alpha1.PodDisruptionBudgetStatus")
}
@ -103,6 +109,44 @@ func (m *PodDisruptionBudget) MarshalTo(data []byte) (int, error) {
return i, nil
}
func (m *PodDisruptionBudgetList) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
n, err := m.MarshalTo(data)
if err != nil {
return nil, err
}
return data[:n], nil
}
func (m *PodDisruptionBudgetList) MarshalTo(data []byte) (int, error) {
var i int
_ = i
var l int
_ = l
data[i] = 0xa
i++
i = encodeVarintGenerated(data, i, uint64(m.ListMeta.Size()))
n4, err := m.ListMeta.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n4
if len(m.Items) > 0 {
for _, msg := range m.Items {
data[i] = 0x12
i++
i = encodeVarintGenerated(data, i, uint64(msg.Size()))
n, err := msg.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n
}
}
return i, nil
}
func (m *PodDisruptionBudgetSpec) Marshal() (data []byte, err error) {
size := m.Size()
data = make([]byte, size)
@ -121,20 +165,20 @@ func (m *PodDisruptionBudgetSpec) MarshalTo(data []byte) (int, error) {
data[i] = 0xa
i++
i = encodeVarintGenerated(data, i, uint64(m.MinAvailable.Size()))
n4, err := m.MinAvailable.MarshalTo(data[i:])
n5, err := m.MinAvailable.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n4
i += n5
if m.Selector != nil {
data[i] = 0x12
i++
i = encodeVarintGenerated(data, i, uint64(m.Selector.Size()))
n5, err := m.Selector.MarshalTo(data[i:])
n6, err := m.Selector.MarshalTo(data[i:])
if err != nil {
return 0, err
}
i += n5
i += n6
}
return i, nil
}
@ -213,6 +257,20 @@ func (m *PodDisruptionBudget) Size() (n int) {
return n
}
func (m *PodDisruptionBudgetList) Size() (n int) {
var l int
_ = l
l = m.ListMeta.Size()
n += 1 + l + sovGenerated(uint64(l))
if len(m.Items) > 0 {
for _, e := range m.Items {
l = e.Size()
n += 1 + l + sovGenerated(uint64(l))
}
}
return n
}
func (m *PodDisruptionBudgetSpec) Size() (n int) {
var l int
_ = l
@ -388,6 +446,117 @@ func (m *PodDisruptionBudget) Unmarshal(data []byte) error {
}
return nil
}
func (m *PodDisruptionBudgetList) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: PodDisruptionBudgetList: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PodDisruptionBudgetList: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.ListMeta.Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := data[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Items = append(m.Items, PodDisruptionBudget{})
if err := m.Items[len(m.Items)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenerated(data[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthGenerated
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *PodDisruptionBudgetSpec) Unmarshal(data []byte) error {
l := len(data)
iNdEx := 0

View File

@ -41,6 +41,13 @@ message PodDisruptionBudget {
optional PodDisruptionBudgetStatus status = 3;
}
// PodDisruptionBudgetList is a collection of PodDisruptionBudgets.
message PodDisruptionBudgetList {
optional k8s.io.kubernetes.pkg.api.unversioned.ListMeta metadata = 1;
repeated PodDisruptionBudget items = 2;
}
// PodDisruptionBudgetSpec is a description of a PodDisruptionBudget.
message PodDisruptionBudgetSpec {
// The minimum number of pods that must be available simultaneously. This

View File

@ -40,9 +40,11 @@ func AddToScheme(scheme *runtime.Scheme) {
func addKnownTypes(scheme *runtime.Scheme) {
scheme.AddKnownTypes(SchemeGroupVersion,
&PodDisruptionBudget{},
&PodDisruptionBudgetList{},
)
// Add the watch version that applies
versionedwatch.AddToGroupVersion(scheme, SchemeGroupVersion)
}
func (obj *PodDisruptionBudget) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodDisruptionBudget) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodDisruptionBudgetList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

View File

@ -975,3 +975,466 @@ func (x *PodDisruptionBudget) codecDecodeSelfFromArray(l int, d *codec1978.Decod
}
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
func (x *PodDisruptionBudgetList) CodecEncodeSelf(e *codec1978.Encoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperEncoder(e)
_, _, _ = h, z, r
if x == nil {
r.EncodeNil()
} else {
yym1 := z.EncBinary()
_ = yym1
if false {
} else if z.HasExtensions() && z.EncExt(x) {
} else {
yysep2 := !z.EncBinary()
yy2arr2 := z.EncBasicHandle().StructToArray
var yyq2 [4]bool
_, _, _ = yysep2, yyq2, yy2arr2
const yyr2 bool = false
yyq2[0] = true
yyq2[2] = x.Kind != ""
yyq2[3] = x.APIVersion != ""
var yynn2 int
if yyr2 || yy2arr2 {
r.EncodeArrayStart(4)
} else {
yynn2 = 1
for _, b := range yyq2 {
if b {
yynn2++
}
}
r.EncodeMapStart(yynn2)
yynn2 = 0
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[0] {
yy4 := &x.ListMeta
yym5 := z.EncBinary()
_ = yym5
if false {
} else if z.HasExtensions() && z.EncExt(yy4) {
} else {
z.EncFallback(yy4)
}
} else {
r.EncodeNil()
}
} else {
if yyq2[0] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("metadata"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yy6 := &x.ListMeta
yym7 := z.EncBinary()
_ = yym7
if false {
} else if z.HasExtensions() && z.EncExt(yy6) {
} else {
z.EncFallback(yy6)
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if x.Items == nil {
r.EncodeNil()
} else {
yym9 := z.EncBinary()
_ = yym9
if false {
} else {
h.encSlicePodDisruptionBudget(([]PodDisruptionBudget)(x.Items), e)
}
}
} else {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("items"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
if x.Items == nil {
r.EncodeNil()
} else {
yym10 := z.EncBinary()
_ = yym10
if false {
} else {
h.encSlicePodDisruptionBudget(([]PodDisruptionBudget)(x.Items), e)
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[2] {
yym12 := z.EncBinary()
_ = yym12
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
}
} else {
r.EncodeString(codecSelferC_UTF81234, "")
}
} else {
if yyq2[2] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("kind"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym13 := z.EncBinary()
_ = yym13
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.Kind))
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
if yyq2[3] {
yym15 := z.EncBinary()
_ = yym15
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
}
} else {
r.EncodeString(codecSelferC_UTF81234, "")
}
} else {
if yyq2[3] {
z.EncSendContainerState(codecSelfer_containerMapKey1234)
r.EncodeString(codecSelferC_UTF81234, string("apiVersion"))
z.EncSendContainerState(codecSelfer_containerMapValue1234)
yym16 := z.EncBinary()
_ = yym16
if false {
} else {
r.EncodeString(codecSelferC_UTF81234, string(x.APIVersion))
}
}
}
if yyr2 || yy2arr2 {
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
z.EncSendContainerState(codecSelfer_containerMapEnd1234)
}
}
}
}
func (x *PodDisruptionBudgetList) CodecDecodeSelf(d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
yym1 := z.DecBinary()
_ = yym1
if false {
} else if z.HasExtensions() && z.DecExt(x) {
} else {
yyct2 := r.ContainerType()
if yyct2 == codecSelferValueTypeMap1234 {
yyl2 := r.ReadMapStart()
if yyl2 == 0 {
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
} else {
x.codecDecodeSelfFromMap(yyl2, d)
}
} else if yyct2 == codecSelferValueTypeArray1234 {
yyl2 := r.ReadArrayStart()
if yyl2 == 0 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
} else {
x.codecDecodeSelfFromArray(yyl2, d)
}
} else {
panic(codecSelferOnlyMapOrArrayEncodeToStructErr1234)
}
}
}
func (x *PodDisruptionBudgetList) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yys3Slc = z.DecScratchBuffer() // default slice to decode into
_ = yys3Slc
var yyhl3 bool = l >= 0
for yyj3 := 0; ; yyj3++ {
if yyhl3 {
if yyj3 >= l {
break
}
} else {
if r.CheckBreak() {
break
}
}
z.DecSendContainerState(codecSelfer_containerMapKey1234)
yys3Slc = r.DecodeBytes(yys3Slc, true, true)
yys3 := string(yys3Slc)
z.DecSendContainerState(codecSelfer_containerMapValue1234)
switch yys3 {
case "metadata":
if r.TryDecodeAsNil() {
x.ListMeta = pkg2_unversioned.ListMeta{}
} else {
yyv4 := &x.ListMeta
yym5 := z.DecBinary()
_ = yym5
if false {
} else if z.HasExtensions() && z.DecExt(yyv4) {
} else {
z.DecFallback(yyv4, false)
}
}
case "items":
if r.TryDecodeAsNil() {
x.Items = nil
} else {
yyv6 := &x.Items
yym7 := z.DecBinary()
_ = yym7
if false {
} else {
h.decSlicePodDisruptionBudget((*[]PodDisruptionBudget)(yyv6), d)
}
}
case "kind":
if r.TryDecodeAsNil() {
x.Kind = ""
} else {
x.Kind = string(r.DecodeString())
}
case "apiVersion":
if r.TryDecodeAsNil() {
x.APIVersion = ""
} else {
x.APIVersion = string(r.DecodeString())
}
default:
z.DecStructFieldNotFound(-1, yys3)
} // end switch yys3
} // end for yyj3
z.DecSendContainerState(codecSelfer_containerMapEnd1234)
}
func (x *PodDisruptionBudgetList) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
var yyj10 int
var yyb10 bool
var yyhl10 bool = l >= 0
yyj10++
if yyhl10 {
yyb10 = yyj10 > l
} else {
yyb10 = r.CheckBreak()
}
if yyb10 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.ListMeta = pkg2_unversioned.ListMeta{}
} else {
yyv11 := &x.ListMeta
yym12 := z.DecBinary()
_ = yym12
if false {
} else if z.HasExtensions() && z.DecExt(yyv11) {
} else {
z.DecFallback(yyv11, false)
}
}
yyj10++
if yyhl10 {
yyb10 = yyj10 > l
} else {
yyb10 = r.CheckBreak()
}
if yyb10 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.Items = nil
} else {
yyv13 := &x.Items
yym14 := z.DecBinary()
_ = yym14
if false {
} else {
h.decSlicePodDisruptionBudget((*[]PodDisruptionBudget)(yyv13), d)
}
}
yyj10++
if yyhl10 {
yyb10 = yyj10 > l
} else {
yyb10 = r.CheckBreak()
}
if yyb10 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.Kind = ""
} else {
x.Kind = string(r.DecodeString())
}
yyj10++
if yyhl10 {
yyb10 = yyj10 > l
} else {
yyb10 = r.CheckBreak()
}
if yyb10 {
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
return
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
if r.TryDecodeAsNil() {
x.APIVersion = ""
} else {
x.APIVersion = string(r.DecodeString())
}
for {
yyj10++
if yyhl10 {
yyb10 = yyj10 > l
} else {
yyb10 = r.CheckBreak()
}
if yyb10 {
break
}
z.DecSendContainerState(codecSelfer_containerArrayElem1234)
z.DecStructFieldNotFound(yyj10-1, "")
}
z.DecSendContainerState(codecSelfer_containerArrayEnd1234)
}
func (x codecSelfer1234) encSlicePodDisruptionBudget(v []PodDisruptionBudget, e *codec1978.Encoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperEncoder(e)
_, _, _ = h, z, r
r.EncodeArrayStart(len(v))
for _, yyv1 := range v {
z.EncSendContainerState(codecSelfer_containerArrayElem1234)
yy2 := &yyv1
yy2.CodecEncodeSelf(e)
}
z.EncSendContainerState(codecSelfer_containerArrayEnd1234)
}
func (x codecSelfer1234) decSlicePodDisruptionBudget(v *[]PodDisruptionBudget, d *codec1978.Decoder) {
var h codecSelfer1234
z, r := codec1978.GenHelperDecoder(d)
_, _, _ = h, z, r
yyv1 := *v
yyh1, yyl1 := z.DecSliceHelperStart()
var yyc1 bool
_ = yyc1
if yyl1 == 0 {
if yyv1 == nil {
yyv1 = []PodDisruptionBudget{}
yyc1 = true
} else if len(yyv1) != 0 {
yyv1 = yyv1[:0]
yyc1 = true
}
} else if yyl1 > 0 {
var yyrr1, yyrl1 int
var yyrt1 bool
_, _ = yyrl1, yyrt1
yyrr1 = yyl1 // len(yyv1)
if yyl1 > cap(yyv1) {
yyrg1 := len(yyv1) > 0
yyv21 := yyv1
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 296)
if yyrt1 {
if yyrl1 <= cap(yyv1) {
yyv1 = yyv1[:yyrl1]
} else {
yyv1 = make([]PodDisruptionBudget, yyrl1)
}
} else {
yyv1 = make([]PodDisruptionBudget, yyrl1)
}
yyc1 = true
yyrr1 = len(yyv1)
if yyrg1 {
copy(yyv1, yyv21)
}
} else if yyl1 != len(yyv1) {
yyv1 = yyv1[:yyl1]
yyc1 = true
}
yyj1 := 0
for ; yyj1 < yyrr1; yyj1++ {
yyh1.ElemContainerState(yyj1)
if r.TryDecodeAsNil() {
yyv1[yyj1] = PodDisruptionBudget{}
} else {
yyv2 := &yyv1[yyj1]
yyv2.CodecDecodeSelf(d)
}
}
if yyrt1 {
for ; yyj1 < yyl1; yyj1++ {
yyv1 = append(yyv1, PodDisruptionBudget{})
yyh1.ElemContainerState(yyj1)
if r.TryDecodeAsNil() {
yyv1[yyj1] = PodDisruptionBudget{}
} else {
yyv3 := &yyv1[yyj1]
yyv3.CodecDecodeSelf(d)
}
}
}
} else {
yyj1 := 0
for ; !r.CheckBreak(); yyj1++ {
if yyj1 >= len(yyv1) {
yyv1 = append(yyv1, PodDisruptionBudget{}) // var yyz1 PodDisruptionBudget
yyc1 = true
}
yyh1.ElemContainerState(yyj1)
if yyj1 < len(yyv1) {
if r.TryDecodeAsNil() {
yyv1[yyj1] = PodDisruptionBudget{}
} else {
yyv4 := &yyv1[yyj1]
yyv4.CodecDecodeSelf(d)
}
} else {
z.DecSwallow()
}
}
if yyj1 < len(yyv1) {
yyv1 = yyv1[:yyj1]
yyc1 = true
} else if yyj1 == 0 && yyv1 == nil {
yyv1 = []PodDisruptionBudget{}
yyc1 = true
}
}
yyh1.End()
if yyc1 {
*v = yyv1
}
}

View File

@ -62,3 +62,10 @@ type PodDisruptionBudget struct {
// Most recently observed status of the PodDisruptionBudget.
Status PodDisruptionBudgetStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
}
// PodDisruptionBudgetList is a collection of PodDisruptionBudgets.
type PodDisruptionBudgetList struct {
unversioned.TypeMeta `json:",inline"`
unversioned.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
Items []PodDisruptionBudget `json:"items" protobuf:"bytes,2,rep,name=items"`
}

View File

@ -0,0 +1,70 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package 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_PodDisruptionBudget = map[string]string{
"": "PodDisruptionBudget is an object to define the max disruption that can be caused to a collection of pods",
"spec": "Specification of the desired behavior of the PodDisruptionBudget.",
"status": "Most recently observed status of the PodDisruptionBudget.",
}
func (PodDisruptionBudget) SwaggerDoc() map[string]string {
return map_PodDisruptionBudget
}
var map_PodDisruptionBudgetList = map[string]string{
"": "PodDisruptionBudgetList is a collection of PodDisruptionBudgets.",
}
func (PodDisruptionBudgetList) SwaggerDoc() map[string]string {
return map_PodDisruptionBudgetList
}
var map_PodDisruptionBudgetSpec = map[string]string{
"": "PodDisruptionBudgetSpec is a description of a PodDisruptionBudget.",
"minAvailable": "The minimum number of pods that must be available simultaneously. This can be either an integer or a string specifying a percentage, e.g. \"28%\".",
"selector": "Label query over pods whose evictions are managed by the disruption budget.",
}
func (PodDisruptionBudgetSpec) SwaggerDoc() map[string]string {
return map_PodDisruptionBudgetSpec
}
var map_PodDisruptionBudgetStatus = map[string]string{
"": "PodDisruptionBudgetStatus represents information about the status of a PodDisruptionBudget. Status may trail the actual state of a system.",
"disruptionAllowed": "Whether or not a disruption is currently allowed.",
"currentHealthy": "current number of healthy pods",
"desiredHealthy": "minimum desired number of healthy pods",
"expectedPods": "total number of pods counted by this disruption budget",
}
func (PodDisruptionBudgetStatus) SwaggerDoc() map[string]string {
return map_PodDisruptionBudgetStatus
}
// AUTO-GENERATED FUNCTIONS END HERE

View File

@ -17,12 +17,33 @@ limitations under the License.
package validation
import (
"reflect"
unversionedvalidation "k8s.io/kubernetes/pkg/api/unversioned/validation"
extensionsvalidation "k8s.io/kubernetes/pkg/apis/extensions/validation"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/util/validation/field"
)
func ValidatePodDisruptionBudget(pdb *policy.PodDisruptionBudget) field.ErrorList {
allErrs := ValidatePodDisruptionBudgetSpec(pdb.Spec, field.NewPath("spec"))
return allErrs
}
func ValidatePodDisruptionBudgetUpdate(pdb, oldPdb *policy.PodDisruptionBudget) field.ErrorList {
allErrs := field.ErrorList{}
restoreGeneration := pdb.Generation
pdb.Generation = oldPdb.Generation
if !reflect.DeepEqual(pdb, oldPdb) {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "updates to poddisruptionbudget spec are forbidden."))
}
pdb.Generation = restoreGeneration
return allErrs
}
func ValidatePodDisruptionBudgetSpec(spec policy.PodDisruptionBudgetSpec, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}

View File

@ -29,6 +29,7 @@ import (
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
_ "k8s.io/kubernetes/pkg/apis/metrics/install"
_ "k8s.io/kubernetes/pkg/apis/policy/install"
)
func init() {

View File

@ -120,6 +120,7 @@ type Client struct {
*BatchClient
*ExtensionsClient
*AppsClient
*PolicyClient
*discovery.DiscoveryClient
}

View File

@ -26,6 +26,7 @@ import (
"k8s.io/kubernetes/pkg/apis/autoscaling"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/client/typed/discovery"
"k8s.io/kubernetes/pkg/util/sets"
@ -85,6 +86,15 @@ func New(c *restclient.Config) (*Client, error) {
return nil, err
}
}
var policyClient *PolicyClient
if registered.IsRegistered(policy.GroupName) {
policyConfig := *c
policyClient, err = NewPolicy(&policyConfig)
if err != nil {
return nil, err
}
}
var appsClient *AppsClient
if registered.IsRegistered(apps.GroupName) {
appsConfig := *c
@ -94,7 +104,7 @@ func New(c *restclient.Config) (*Client, error) {
}
}
return &Client{RESTClient: client, AutoscalingClient: autoscalingClient, BatchClient: batchClient, ExtensionsClient: extensionsClient, DiscoveryClient: discoveryClient, AppsClient: appsClient}, nil
return &Client{RESTClient: client, AutoscalingClient: autoscalingClient, BatchClient: batchClient, ExtensionsClient: extensionsClient, DiscoveryClient: discoveryClient, AppsClient: appsClient, PolicyClient: policyClient}, nil
}
// MatchesServerVersion queries the server to compares the build version

View File

@ -0,0 +1,100 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package unversioned
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/watch"
)
// PodDisruptionBudgetNamespacer has methods to work with PodDisruptionBudget resources in a namespace
type PodDisruptionBudgetNamespacer interface {
PodDisruptionBudgets(namespace string) PodDisruptionBudgetInterface
}
// PodDisruptionBudgetInterface exposes methods to work on PodDisruptionBudget resources.
type PodDisruptionBudgetInterface interface {
List(opts api.ListOptions) (*policy.PodDisruptionBudgetList, error)
Get(name string) (*policy.PodDisruptionBudget, error)
Create(podDisruptionBudget *policy.PodDisruptionBudget) (*policy.PodDisruptionBudget, error)
Update(podDisruptionBudget *policy.PodDisruptionBudget) (*policy.PodDisruptionBudget, error)
Delete(name string, options *api.DeleteOptions) error
Watch(opts api.ListOptions) (watch.Interface, error)
UpdateStatus(podDisruptionBudget *policy.PodDisruptionBudget) (*policy.PodDisruptionBudget, error)
}
// podDisruptionBudget implements PodDisruptionBudgetNamespacer interface
type podDisruptionBudget struct {
r *PolicyClient
ns string
}
// newPodDisruptionBudget returns a podDisruptionBudget
func newPodDisruptionBudget(c *PolicyClient, namespace string) *podDisruptionBudget {
return &podDisruptionBudget{c, namespace}
}
// List returns a list of podDisruptionBudget that match the label and field selectors.
func (c *podDisruptionBudget) List(opts api.ListOptions) (result *policy.PodDisruptionBudgetList, err error) {
result = &policy.PodDisruptionBudgetList{}
err = c.r.Get().Namespace(c.ns).Resource("poddisruptionbudgets").VersionedParams(&opts, api.ParameterCodec).Do().Into(result)
return
}
// Get returns information about a particular podDisruptionBudget.
func (c *podDisruptionBudget) Get(name string) (result *policy.PodDisruptionBudget, err error) {
result = &policy.PodDisruptionBudget{}
err = c.r.Get().Namespace(c.ns).Resource("poddisruptionbudgets").Name(name).Do().Into(result)
return
}
// Create creates a new podDisruptionBudget.
func (c *podDisruptionBudget) Create(podDisruptionBudget *policy.PodDisruptionBudget) (result *policy.PodDisruptionBudget, err error) {
result = &policy.PodDisruptionBudget{}
err = c.r.Post().Namespace(c.ns).Resource("poddisruptionbudgets").Body(podDisruptionBudget).Do().Into(result)
return
}
// Update updates an existing podDisruptionBudget.
func (c *podDisruptionBudget) Update(podDisruptionBudget *policy.PodDisruptionBudget) (result *policy.PodDisruptionBudget, err error) {
result = &policy.PodDisruptionBudget{}
err = c.r.Put().Namespace(c.ns).Resource("poddisruptionbudgets").Name(podDisruptionBudget.Name).Body(podDisruptionBudget).Do().Into(result)
return
}
// Delete deletes a podDisruptionBudget, returns error if one occurs.
func (c *podDisruptionBudget) Delete(name string, options *api.DeleteOptions) (err error) {
return c.r.Delete().Namespace(c.ns).Resource("poddisruptionbudgets").Name(name).Body(options).Do().Error()
}
// Watch returns a watch.Interface that watches the requested podDisruptionBudget.
func (c *podDisruptionBudget) Watch(opts api.ListOptions) (watch.Interface, error) {
return c.r.Get().
Prefix("watch").
Namespace(c.ns).
Resource("poddisruptionbudgets").
VersionedParams(&opts, api.ParameterCodec).
Watch()
}
// UpdateStatus takes the name of the podDisruptionBudget and the new status. Returns the server's representation of the podDisruptionBudget, and an error, if it occurs.
func (c *podDisruptionBudget) UpdateStatus(podDisruptionBudget *policy.PodDisruptionBudget) (result *policy.PodDisruptionBudget, err error) {
result = &policy.PodDisruptionBudget{}
err = c.r.Put().Namespace(c.ns).Resource("poddisruptionbudgets").Name(podDisruptionBudget.Name).SubResource("status").Body(podDisruptionBudget).Do().Into(result)
return
}

View File

@ -0,0 +1,83 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package unversioned
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/client/restclient"
)
type PolicyInterface interface {
PodDisruptionBudgetNamespacer
}
// PolicyClient is used to interact with Kubernetes batch features.
type PolicyClient struct {
*restclient.RESTClient
}
func (c *PolicyClient) PodDisruptionBudgets(namespace string) PodDisruptionBudgetInterface {
return newPodDisruptionBudget(c, namespace)
}
func NewPolicy(c *restclient.Config) (*PolicyClient, error) {
config := *c
if err := setPolicyDefaults(&config); err != nil {
return nil, err
}
client, err := restclient.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &PolicyClient{client}, nil
}
func NewPolicyOrDie(c *restclient.Config) *PolicyClient {
client, err := NewPolicy(c)
if err != nil {
panic(err)
}
return client
}
func setPolicyDefaults(config *restclient.Config) error {
g, err := registered.Group(policy.GroupName)
if err != nil {
return err
}
config.APIPath = defaultAPIPath
if config.UserAgent == "" {
config.UserAgent = restclient.DefaultKubernetesUserAgent()
}
// TODO: Unconditionally set the config.Version, until we fix the config.
//if config.Version == "" {
copyGroupVersion := g.GroupVersion
config.GroupVersion = &copyGroupVersion
//}
config.Codec = api.Codecs.LegacyCodec(*config.GroupVersion)
config.NegotiatedSerializer = api.Codecs
if config.QPS == 0 {
config.QPS = 5
}
if config.Burst == 0 {
config.Burst = 10
}
return nil
}

View File

@ -47,6 +47,7 @@ import (
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/metrics"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/client/restclient"
client "k8s.io/kubernetes/pkg/client/unversioned"
clientset "k8s.io/kubernetes/pkg/client/unversioned/adapters/internalclientset"
@ -321,6 +322,8 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
return c.AutoscalingClient.RESTClient, nil
case batch.GroupName:
return c.BatchClient.RESTClient, nil
case policy.GroupName:
return c.PolicyClient.RESTClient, nil
case apps.GroupName:
return c.AppsClient.RESTClient, nil
case extensions.GroupName:
@ -900,6 +903,12 @@ func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
}
return getSchemaAndValidate(c.c.AutoscalingClient.RESTClient, data, "apis/", gvk.GroupVersion().String(), c.cacheDir, c)
}
if gvk.Group == policy.GroupName {
if c.c.PolicyClient == nil {
return errors.New("unable to validate: no policy client")
}
return getSchemaAndValidate(c.c.PolicyClient.RESTClient, data, "apis/", gvk.GroupVersion().String(), c.cacheDir, c)
}
if gvk.Group == apps.GroupName {
if c.c.AppsClient == nil {
return errors.New("unable to validate: no autoscaling client")

View File

@ -41,6 +41,8 @@ import (
batchapiv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1"
"k8s.io/kubernetes/pkg/apis/extensions"
extensionsapiv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/apis/policy"
policyapiv1alpha1 "k8s.io/kubernetes/pkg/apis/policy/v1alpha1"
"k8s.io/kubernetes/pkg/apiserver"
apiservermetrics "k8s.io/kubernetes/pkg/apiserver/metrics"
"k8s.io/kubernetes/pkg/genericapiserver"
@ -67,6 +69,7 @@ import (
pvcetcd "k8s.io/kubernetes/pkg/registry/persistentvolumeclaim/etcd"
petsetetcd "k8s.io/kubernetes/pkg/registry/petset/etcd"
podetcd "k8s.io/kubernetes/pkg/registry/pod/etcd"
poddisruptionbudgetetcd "k8s.io/kubernetes/pkg/registry/poddisruptionbudget/etcd"
pspetcd "k8s.io/kubernetes/pkg/registry/podsecuritypolicy/etcd"
podtemplateetcd "k8s.io/kubernetes/pkg/registry/podtemplate/etcd"
replicasetetcd "k8s.io/kubernetes/pkg/registry/replicaset/etcd"
@ -344,6 +347,38 @@ func (m *Master) InstallAPIs(c *Config) {
allGroups = append(allGroups, group)
}
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(policyapiv1alpha1.SchemeGroupVersion) {
policyResources := m.getPolicyResources(c)
policyGroupMeta := registered.GroupOrDie(policy.GroupName)
// Hard code preferred group version to policy/v1alpha1
policyGroupMeta.GroupVersion = policyapiv1alpha1.SchemeGroupVersion
apiGroupInfo := genericapiserver.APIGroupInfo{
GroupMeta: *policyGroupMeta,
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
"v1alpha1": policyResources,
},
OptionsExternalVersion: &registered.GroupOrDie(api.GroupName).GroupVersion,
Scheme: api.Scheme,
ParameterCodec: api.ParameterCodec,
NegotiatedSerializer: api.Codecs,
}
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
policyGVForDiscovery := unversioned.GroupVersionForDiscovery{
GroupVersion: policyGroupMeta.GroupVersion.String(),
Version: policyGroupMeta.GroupVersion.Version,
}
group := unversioned.APIGroup{
Name: policyGroupMeta.GroupVersion.Group,
Versions: []unversioned.GroupVersionForDiscovery{policyGVForDiscovery},
PreferredVersion: policyGVForDiscovery,
}
allGroups = append(allGroups, group)
}
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(appsapi.SchemeGroupVersion) {
appsResources := m.getAppsResources(c)
appsGroupMeta := registered.GroupOrDie(apps.GroupName)
@ -839,6 +874,20 @@ func (m *Master) getBatchResources(c *Config, version unversioned.GroupVersion)
return storage
}
// getPolicyResources returns the resources for policy api
func (m *Master) getPolicyResources(c *Config) map[string]rest.Storage {
// TODO update when we support more than one version of this group
version := policyapiv1alpha1.SchemeGroupVersion
storage := map[string]rest.Storage{}
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("poddisruptionbudgets")) {
poddisruptionbudgetStorage, poddisruptionbudgetStatusStorage := poddisruptionbudgetetcd.NewREST(m.GetRESTOptionsOrDie(c, policy.Resource("poddisruptionbudgets")))
storage["poddisruptionbudgets"] = poddisruptionbudgetStorage
storage["poddisruptionbudgets/status"] = poddisruptionbudgetStatusStorage
}
return storage
}
// getPetSetResources returns the resources for apps api
func (m *Master) getAppsResources(c *Config) map[string]rest.Storage {
// TODO update when we support more than one version of this group
@ -905,7 +954,7 @@ func (m *Master) IsTunnelSyncHealthy(req *http.Request) error {
func DefaultAPIResourceConfigSource() *genericapiserver.ResourceConfig {
ret := genericapiserver.NewResourceConfig()
ret.EnableVersions(apiv1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion, batchapiv1.SchemeGroupVersion, autoscalingapiv1.SchemeGroupVersion, appsapi.SchemeGroupVersion)
ret.EnableVersions(apiv1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion, batchapiv1.SchemeGroupVersion, autoscalingapiv1.SchemeGroupVersion, appsapi.SchemeGroupVersion, policyapiv1alpha1.SchemeGroupVersion)
// all extensions resources except these are disabled by default
ret.EnableResources(

View File

@ -34,6 +34,7 @@ const (
Endpoints Resource = "endpoints"
HorizontalPodAutoscalers Resource = "horizontalpodautoscalers"
Ingress Resource = "ingress"
PodDisruptionBudget Resource = "poddisruptionbudgets"
PetSet Resource = "petset"
Jobs Resource = "jobs"
LimitRanges Resource = "limitranges"
@ -61,6 +62,7 @@ func init() {
watchCacheSizes[HorizontalPodAutoscalers] = 100
watchCacheSizes[Ingress] = 100
watchCacheSizes[PetSet] = 100
watchCacheSizes[PodDisruptionBudget] = 100
watchCacheSizes[Jobs] = 100
watchCacheSizes[LimitRanges] = 100
watchCacheSizes[Namespaces] = 100

View File

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

View File

@ -0,0 +1,96 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package etcd
import (
"k8s.io/kubernetes/pkg/api"
policyapi "k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/cachesize"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/registry/generic/registry"
"k8s.io/kubernetes/pkg/registry/poddisruptionbudget"
"k8s.io/kubernetes/pkg/runtime"
)
// rest implements a RESTStorage for pod disruption budgets against etcd
type REST struct {
*registry.Store
}
// NewREST returns a RESTStorage object that will work against pod disruption budgets.
func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
prefix := "/poddisruptionbudgets"
newListFunc := func() runtime.Object { return &policyapi.PodDisruptionBudgetList{} }
storageInterface := opts.Decorator(
opts.Storage, cachesize.GetWatchCacheSizeByResource(cachesize.PodDisruptionBudget), &policyapi.PodDisruptionBudget{}, prefix, poddisruptionbudget.Strategy, newListFunc)
store := &registry.Store{
NewFunc: func() runtime.Object { return &policyapi.PodDisruptionBudget{} },
// NewListFunc returns an object capable of storing results of an etcd list.
NewListFunc: newListFunc,
// Produces a podDisruptionBudget that etcd understands, to the root of the resource
// by combining the namespace in the context with the given prefix
KeyRootFunc: func(ctx api.Context) string {
return registry.NamespaceKeyRootFunc(ctx, prefix)
},
// Produces a podDisruptionBudget that etcd understands, to the resource by combining
// the namespace in the context with the given prefix
KeyFunc: func(ctx api.Context, name string) (string, error) {
return registry.NamespaceKeyFunc(ctx, prefix, name)
},
// Retrieve the name field of a pod disruption budget
ObjectNameFunc: func(obj runtime.Object) (string, error) {
return obj.(*policyapi.PodDisruptionBudget).Name, nil
},
// Used to match objects based on labels/fields for list and watch
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return poddisruptionbudget.MatchPodDisruptionBudget(label, field)
},
QualifiedResource: policyapi.Resource("poddisruptionbudgets"),
DeleteCollectionWorkers: opts.DeleteCollectionWorkers,
// Used to validate controller creation
CreateStrategy: poddisruptionbudget.Strategy,
// Used to validate controller updates
UpdateStrategy: poddisruptionbudget.Strategy,
DeleteStrategy: poddisruptionbudget.Strategy,
Storage: storageInterface,
}
statusStore := *store
statusStore.UpdateStrategy = poddisruptionbudget.StatusStrategy
return &REST{store}, &StatusREST{store: &statusStore}
}
// StatusREST implements the REST endpoint for changing the status of an podDisruptionBudget
type StatusREST struct {
store *registry.Store
}
func (r *StatusREST) New() runtime.Object {
return &policyapi.PodDisruptionBudget{}
}
// Update alters the status subset of an object.
func (r *StatusREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
return r.store.Update(ctx, obj)
}

View File

@ -0,0 +1,167 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package etcd
import (
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/registry/registrytest"
"k8s.io/kubernetes/pkg/storage/etcd/etcdtest"
etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
"k8s.io/kubernetes/pkg/util/intstr"
)
func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) {
etcdStorage, server := registrytest.NewEtcdStorage(t, policy.GroupName)
restOptions := generic.RESTOptions{Storage: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1}
podDisruptionBudgetStorage, statusStorage := NewREST(restOptions)
return podDisruptionBudgetStorage, statusStorage, server
}
// createPodDisruptionBudget is a helper function that returns a PodDisruptionBudget with the updated resource version.
func createPodDisruptionBudget(storage *REST, pdb policy.PodDisruptionBudget, t *testing.T) (policy.PodDisruptionBudget, error) {
ctx := api.WithNamespace(api.NewContext(), pdb.Namespace)
obj, err := storage.Create(ctx, &pdb)
if err != nil {
t.Errorf("Failed to create PodDisruptionBudget, %v", err)
}
newPS := obj.(*policy.PodDisruptionBudget)
return *newPS, nil
}
func validNewPodDisruptionBudget() *policy.PodDisruptionBudget {
return &policy.PodDisruptionBudget{
ObjectMeta: api.ObjectMeta{
Name: "foo",
Namespace: api.NamespaceDefault,
Labels: map[string]string{"a": "b"},
},
Spec: policy.PodDisruptionBudgetSpec{
Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"a": "b"}},
MinAvailable: intstr.FromInt(7),
},
Status: policy.PodDisruptionBudgetStatus{},
}
}
func TestCreate(t *testing.T) {
storage, _, server := newStorage(t)
defer server.Terminate(t)
test := registrytest.New(t, storage.Store)
pdb := validNewPodDisruptionBudget()
pdb.ObjectMeta = api.ObjectMeta{}
test.TestCreate(
// valid
pdb,
// TODO: Add an invalid case when we have validation.
)
}
// TODO: Test updates to spec when we allow them.
func TestStatusUpdate(t *testing.T) {
storage, statusStorage, server := newStorage(t)
defer server.Terminate(t)
ctx := api.WithNamespace(api.NewContext(), api.NamespaceDefault)
key := etcdtest.AddPrefix("/poddisruptionbudgets/" + api.NamespaceDefault + "/foo")
validPodDisruptionBudget := validNewPodDisruptionBudget()
if err := storage.Storage.Create(ctx, key, validPodDisruptionBudget, nil, 0); err != nil {
t.Fatalf("unexpected error: %v", err)
}
update := policy.PodDisruptionBudget{
ObjectMeta: validPodDisruptionBudget.ObjectMeta,
Spec: policy.PodDisruptionBudgetSpec{
MinAvailable: intstr.FromInt(8),
},
Status: policy.PodDisruptionBudgetStatus{
ExpectedPods: 8,
},
}
if _, _, err := statusStorage.Update(ctx, &update); err != nil {
t.Fatalf("unexpected error: %v", err)
}
obj, err := storage.Get(ctx, "foo")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
pdb := obj.(*policy.PodDisruptionBudget)
if pdb.Spec.MinAvailable.IntValue() != 7 {
t.Errorf("we expected .spec.replicas to not be updated but it was updated to %v", pdb.Spec.MinAvailable)
}
if pdb.Status.ExpectedPods != 8 {
t.Errorf("we expected .status.replicas to be updated to %d but it was %v", 7, pdb.Status.ExpectedPods)
}
}
func TestGet(t *testing.T) {
storage, _, server := newStorage(t)
defer server.Terminate(t)
test := registrytest.New(t, storage.Store)
test.TestGet(validNewPodDisruptionBudget())
}
func TestList(t *testing.T) {
storage, _, server := newStorage(t)
defer server.Terminate(t)
test := registrytest.New(t, storage.Store)
test.TestList(validNewPodDisruptionBudget())
}
func TestDelete(t *testing.T) {
storage, _, server := newStorage(t)
defer server.Terminate(t)
test := registrytest.New(t, storage.Store)
test.TestDelete(validNewPodDisruptionBudget())
}
func TestWatch(t *testing.T) {
storage, _, server := newStorage(t)
defer server.Terminate(t)
test := registrytest.New(t, storage.Store)
test.TestWatch(
validNewPodDisruptionBudget(),
// matching labels
[]labels.Set{
{"a": "b"},
},
// not matching labels
[]labels.Set{
{"a": "c"},
{"foo": "bar"},
},
// matching fields
[]fields.Set{
{"metadata.name": "foo"},
},
// not matching fields
[]fields.Set{
{"metadata.name": "bar"},
},
)
}
// TODO: Test generation number.

View File

@ -0,0 +1,138 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package poddisruptionbudget
import (
"fmt"
"reflect"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/apis/policy/validation"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/validation/field"
)
// podDisruptionBudgetStrategy implements verification logic for PodDisruptionBudgets.
type podDisruptionBudgetStrategy struct {
runtime.ObjectTyper
api.NameGenerator
}
// Strategy is the default logic that applies when creating and updating PodDisruptionBudget objects.
var Strategy = podDisruptionBudgetStrategy{api.Scheme, api.SimpleNameGenerator}
// NamespaceScoped returns true because all PodDisruptionBudget' need to be within a namespace.
func (podDisruptionBudgetStrategy) NamespaceScoped() bool {
return true
}
// PrepareForCreate clears the status of an PodDisruptionBudget before creation.
func (podDisruptionBudgetStrategy) PrepareForCreate(obj runtime.Object) {
podDisruptionBudget := obj.(*policy.PodDisruptionBudget)
// create cannot set status
podDisruptionBudget.Status = policy.PodDisruptionBudgetStatus{}
podDisruptionBudget.Generation = 1
}
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
func (podDisruptionBudgetStrategy) PrepareForUpdate(obj, old runtime.Object) {
newPodDisruptionBudget := obj.(*policy.PodDisruptionBudget)
oldPodDisruptionBudget := old.(*policy.PodDisruptionBudget)
// Update is not allowed to set status
newPodDisruptionBudget.Status = oldPodDisruptionBudget.Status
// Any changes to the spec increment the generation number, any changes to the
// status should reflect the generation number of the corresponding object.
// See api.ObjectMeta description for more information on Generation.
if !reflect.DeepEqual(oldPodDisruptionBudget.Spec, newPodDisruptionBudget.Spec) {
newPodDisruptionBudget.Generation = oldPodDisruptionBudget.Generation + 1
}
}
// Validate validates a new PodDisruptionBudget.
func (podDisruptionBudgetStrategy) Validate(ctx api.Context, obj runtime.Object) field.ErrorList {
podDisruptionBudget := obj.(*policy.PodDisruptionBudget)
return validation.ValidatePodDisruptionBudget(podDisruptionBudget)
}
// Canonicalize normalizes the object after validation.
func (podDisruptionBudgetStrategy) Canonicalize(obj runtime.Object) {
}
// AllowCreateOnUpdate is true for PodDisruptionBudget; this means you may create one with a PUT request.
func (podDisruptionBudgetStrategy) AllowCreateOnUpdate() bool {
return false
}
// ValidateUpdate is the default update validation for an end user.
func (podDisruptionBudgetStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
validationErrorList := validation.ValidatePodDisruptionBudget(obj.(*policy.PodDisruptionBudget))
updateErrorList := validation.ValidatePodDisruptionBudgetUpdate(obj.(*policy.PodDisruptionBudget), old.(*policy.PodDisruptionBudget))
return append(validationErrorList, updateErrorList...)
}
// AllowUnconditionalUpdate is the default update policy for PodDisruptionBudget objects.
func (podDisruptionBudgetStrategy) AllowUnconditionalUpdate() bool {
return true
}
// PodDisruptionBudgetToSelectableFields returns a field set that represents the object.
func PodDisruptionBudgetToSelectableFields(podDisruptionBudget *policy.PodDisruptionBudget) fields.Set {
return generic.ObjectMetaFieldsSet(podDisruptionBudget.ObjectMeta, true)
}
// MatchPodDisruptionBudget is the filter used by the generic etcd backend to watch events
// from etcd to clients of the apiserver only interested in specific labels/fields.
func MatchPodDisruptionBudget(label labels.Selector, field fields.Selector) generic.Matcher {
return &generic.SelectionPredicate{
Label: label,
Field: field,
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
podDisruptionBudget, ok := obj.(*policy.PodDisruptionBudget)
if !ok {
return nil, nil, fmt.Errorf("given object is not a PodDisruptionBudget.")
}
return labels.Set(podDisruptionBudget.ObjectMeta.Labels), PodDisruptionBudgetToSelectableFields(podDisruptionBudget), nil
},
}
}
type podDisruptionBudgetStatusStrategy struct {
podDisruptionBudgetStrategy
}
var StatusStrategy = podDisruptionBudgetStatusStrategy{Strategy}
// PrepareForUpdate clears fields that are not allowed to be set by end users on update of status
func (podDisruptionBudgetStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
newPodDisruptionBudget := obj.(*policy.PodDisruptionBudget)
oldPodDisruptionBudget := old.(*policy.PodDisruptionBudget)
// status changes are not allowed to update spec
newPodDisruptionBudget.Spec = oldPodDisruptionBudget.Spec
}
// ValidateUpdate is the default update validation for an end user updating status
func (podDisruptionBudgetStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
// TODO: Validate status updates.
return field.ErrorList{}
// return validation.ValidatePodDisruptionBudgetStatusUpdate(obj.(*policy.PodDisruptionBudget), old.(*policy.PodDisruptionBudget))
}

View File

@ -0,0 +1,134 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package poddisruptionbudget
import (
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/util/intstr"
)
func TestPodDisruptionBudgetStrategy(t *testing.T) {
ctx := api.NewDefaultContext()
if !Strategy.NamespaceScoped() {
t.Errorf("PodDisruptionBudget must be namespace scoped")
}
if Strategy.AllowCreateOnUpdate() {
t.Errorf("PodDisruptionBudget should not allow create on update")
}
validSelector := map[string]string{"a": "b"}
pdb := &policy.PodDisruptionBudget{
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault},
Spec: policy.PodDisruptionBudgetSpec{
MinAvailable: intstr.FromInt(3),
Selector: &unversioned.LabelSelector{MatchLabels: validSelector},
},
}
Strategy.PrepareForCreate(pdb)
errs := Strategy.Validate(ctx, pdb)
if len(errs) != 0 {
t.Errorf("Unexpected error validating %v", errs)
}
newPdb := &policy.PodDisruptionBudget{
ObjectMeta: api.ObjectMeta{Name: pdb.Name, Namespace: pdb.Namespace},
Spec: pdb.Spec,
Status: policy.PodDisruptionBudgetStatus{
PodDisruptionAllowed: true,
CurrentHealthy: 3,
DesiredHealthy: 3,
ExpectedPods: 3,
},
}
// Nothing in Spec changes: OK
Strategy.PrepareForUpdate(newPdb, pdb)
errs = Strategy.ValidateUpdate(ctx, newPdb, pdb)
if len(errs) != 0 {
t.Errorf("Unexpected error updating PodDisruptionBudget.")
}
// Changing the selector? No.
newPdb.Spec.Selector = &unversioned.LabelSelector{MatchLabels: map[string]string{"a": "bar"}}
Strategy.PrepareForUpdate(newPdb, pdb)
errs = Strategy.ValidateUpdate(ctx, newPdb, pdb)
if len(errs) == 0 {
t.Errorf("Expected a validation error since updates are disallowed on poddisruptionbudgets.")
}
newPdb.Spec.Selector = pdb.Spec.Selector
// Changing MinAvailable? Also no.
newPdb.Spec.MinAvailable = intstr.FromString("28%")
Strategy.PrepareForUpdate(newPdb, pdb)
errs = Strategy.ValidateUpdate(ctx, newPdb, pdb)
if len(errs) == 0 {
t.Errorf("Expected a validation error since updates are disallowed on poddisruptionbudgets.")
}
}
func TestPodDisruptionBudgetStatusStrategy(t *testing.T) {
ctx := api.NewDefaultContext()
if !StatusStrategy.NamespaceScoped() {
t.Errorf("PodDisruptionBudgetStatus must be namespace scoped")
}
if StatusStrategy.AllowCreateOnUpdate() {
t.Errorf("PodDisruptionBudgetStatus should not allow create on update")
}
validSelector := map[string]string{"a": "b"}
oldPdb := &policy.PodDisruptionBudget{
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault, ResourceVersion: "10"},
Spec: policy.PodDisruptionBudgetSpec{
Selector: &unversioned.LabelSelector{MatchLabels: validSelector},
MinAvailable: intstr.FromInt(3),
},
Status: policy.PodDisruptionBudgetStatus{
PodDisruptionAllowed: true,
CurrentHealthy: 3,
DesiredHealthy: 3,
ExpectedPods: 3,
},
}
newPdb := &policy.PodDisruptionBudget{
ObjectMeta: api.ObjectMeta{Name: "abc", Namespace: api.NamespaceDefault, ResourceVersion: "9"},
Spec: policy.PodDisruptionBudgetSpec{
Selector: &unversioned.LabelSelector{MatchLabels: validSelector},
MinAvailable: intstr.FromInt(2),
},
Status: policy.PodDisruptionBudgetStatus{
PodDisruptionAllowed: false,
CurrentHealthy: 2,
DesiredHealthy: 3,
ExpectedPods: 3,
},
}
StatusStrategy.PrepareForUpdate(newPdb, oldPdb)
if newPdb.Status.CurrentHealthy != 2 {
t.Errorf("PodDisruptionBudget status updates should allow change of CurrentHealthy: %v", newPdb.Status.CurrentHealthy)
}
if newPdb.Spec.MinAvailable.IntValue() != 3 {
t.Errorf("PodDisruptionBudget status updates should not clobber spec: %v", newPdb.Spec)
}
errs := StatusStrategy.ValidateUpdate(ctx, newPdb, oldPdb)
if len(errs) != 0 {
t.Errorf("Unexpected error %v", errs)
}
}

View File

@ -34,6 +34,7 @@ import (
"k8s.io/kubernetes/pkg/apis/autoscaling"
"k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/policy"
"k8s.io/kubernetes/pkg/apiserver"
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/record"
@ -178,6 +179,10 @@ func NewMasterConfig() *master.Config {
unversioned.GroupResource{Group: extensions.GroupName, Resource: genericapiserver.AllResources},
"",
NewSingleContentTypeSerializer(api.Scheme, testapi.Extensions.Codec(), runtime.ContentTypeJSON))
storageFactory.SetSerializer(
unversioned.GroupResource{Group: policy.GroupName, Resource: genericapiserver.AllResources},
"",
NewSingleContentTypeSerializer(api.Scheme, testapi.Policy.Codec(), runtime.ContentTypeJSON))
return &master.Config{
Config: &genericapiserver.Config{