mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 06:54:01 +00:00
Merge pull request #20501 from piosz/hpa-ga
Auto commit by PR queue bot
This commit is contained in:
commit
17325ef6ef
30
api/swagger-spec/autoscaling.json
Normal file
30
api/swagger-spec/autoscaling.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"swaggerVersion": "1.2",
|
||||
"apiVersion": "",
|
||||
"basePath": "https://10.10.10.10:6443",
|
||||
"resourcePath": "/apis/autoscaling",
|
||||
"apis": [
|
||||
{
|
||||
"path": "/apis/autoscaling",
|
||||
"description": "get information of a group",
|
||||
"operations": [
|
||||
{
|
||||
"type": "void",
|
||||
"method": "GET",
|
||||
"summary": "get information of a group",
|
||||
"nickname": "getAPIGroup",
|
||||
"parameters": [],
|
||||
"produces": [
|
||||
"application/json",
|
||||
"application/yaml"
|
||||
],
|
||||
"consumes": [
|
||||
"application/json",
|
||||
"application/yaml"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"models": {}
|
||||
}
|
1192
api/swagger-spec/autoscaling_v1.json
Normal file
1192
api/swagger-spec/autoscaling_v1.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -24,6 +24,14 @@
|
||||
{
|
||||
"path": "/apis/extensions",
|
||||
"description": "get information of a group"
|
||||
},
|
||||
{
|
||||
"path": "/apis/autoscaling/v1",
|
||||
"description": "API at /apis/autoscaling/v1"
|
||||
},
|
||||
{
|
||||
"path": "/apis/autoscaling",
|
||||
"description": "get information of a group"
|
||||
}
|
||||
],
|
||||
"apiVersion": "",
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/metrics/install"
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/metrics/install"
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/admission"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
apiutil "k8s.io/kubernetes/pkg/api/util"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apiserver"
|
||||
@ -80,8 +81,12 @@ type APIServer struct {
|
||||
ServiceClusterIPRange net.IPNet // TODO: make this a list
|
||||
ServiceNodePortRange utilnet.PortRange
|
||||
StorageVersions string
|
||||
TokenAuthFile string
|
||||
WatchCacheSizes []string
|
||||
// The default values for StorageVersions. StorageVersions overrides
|
||||
// these; you can change this if you want to change the defaults (e.g.,
|
||||
// for testing). This is not actually exposed as a flag.
|
||||
DefaultStorageVersions string
|
||||
TokenAuthFile string
|
||||
WatchCacheSizes []string
|
||||
}
|
||||
|
||||
// NewAPIServer creates a new APIServer object with default parameters
|
||||
@ -99,6 +104,7 @@ func NewAPIServer() *APIServer {
|
||||
MasterServiceNamespace: api.NamespaceDefault,
|
||||
RuntimeConfig: make(util.ConfigurationMap),
|
||||
StorageVersions: registered.AllPreferredGroupVersions(),
|
||||
DefaultStorageVersions: registered.AllPreferredGroupVersions(),
|
||||
KubeletConfig: kubeletclient.KubeletClientConfig{
|
||||
Port: ports.KubeletPort,
|
||||
EnableHttps: true,
|
||||
@ -109,6 +115,42 @@ func NewAPIServer() *APIServer {
|
||||
return &s
|
||||
}
|
||||
|
||||
// dest must be a map of group to groupVersion.
|
||||
func gvToMap(gvList string, dest map[string]string) {
|
||||
for _, gv := range strings.Split(gvList, ",") {
|
||||
if gv == "" {
|
||||
continue
|
||||
}
|
||||
// We accept two formats. "group/version" OR
|
||||
// "group=group/version". The latter is used when types
|
||||
// move between groups.
|
||||
if !strings.Contains(gv, "=") {
|
||||
dest[apiutil.GetGroup(gv)] = gv
|
||||
} else {
|
||||
parts := strings.SplitN(gv, "=", 2)
|
||||
// TODO: error checking.
|
||||
dest[parts[0]] = parts[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// StorageGroupsToGroupVersions returns a map from group name to group version,
|
||||
// computed from the s.DeprecatedStorageVersion and s.StorageVersions flags.
|
||||
// TODO: can we move the whole storage version concept to the generic apiserver?
|
||||
func (s *APIServer) StorageGroupsToGroupVersions() map[string]string {
|
||||
storageVersionMap := map[string]string{}
|
||||
if s.DeprecatedStorageVersion != "" {
|
||||
storageVersionMap[""] = s.DeprecatedStorageVersion
|
||||
}
|
||||
|
||||
// First, get the defaults.
|
||||
gvToMap(s.DefaultStorageVersions, storageVersionMap)
|
||||
// Override any defaults with the user settings.
|
||||
gvToMap(s.StorageVersions, storageVersionMap)
|
||||
|
||||
return storageVersionMap
|
||||
}
|
||||
|
||||
// AddFlags adds flags for a specific APIServer to the specified FlagSet
|
||||
func (s *APIServer) AddFlags(fs *pflag.FlagSet) {
|
||||
// Note: the weird ""+ in below lines seems to be the only way to get gofmt to
|
||||
@ -150,9 +192,10 @@ func (s *APIServer) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.MarkDeprecated("api-prefix", "--api-prefix is deprecated and will be removed when the v1 API is retired.")
|
||||
fs.StringVar(&s.DeprecatedStorageVersion, "storage-version", s.DeprecatedStorageVersion, "The version to store the legacy v1 resources with. Defaults to server preferred")
|
||||
fs.MarkDeprecated("storage-version", "--storage-version is deprecated and will be removed when the v1 API is retired. See --storage-versions instead.")
|
||||
fs.StringVar(&s.StorageVersions, "storage-versions", s.StorageVersions, "The versions to store resources with. "+
|
||||
"Different groups may be stored in different versions. Specified in the format \"group1/version1,group2/version2...\". "+
|
||||
"This flag expects a complete list of storage versions of ALL groups registered in the server. "+
|
||||
fs.StringVar(&s.StorageVersions, "storage-versions", s.StorageVersions, "The per-group version to store resources in. "+
|
||||
"Specified in the format \"group1/version1,group2/version2,...\". "+
|
||||
"In the case where objects are moved from one group to the other, you may specify the format \"group1=group2/v1beta1,group3/v1beta1,...\". "+
|
||||
"You only need to pass the groups you wish to change from the defaults. "+
|
||||
"It defaults to a list of preferred versions of all registered groups, which is derived from the KUBE_API_VERSIONS environment variable.")
|
||||
fs.StringVar(&s.CloudProvider, "cloud-provider", s.CloudProvider, "The provider for cloud services. Empty string for no provider.")
|
||||
fs.StringVar(&s.CloudConfigFile, "cloud-config", s.CloudConfigFile, "The path to the cloud provider configuration file. Empty string for no configuration file.")
|
||||
|
78
cmd/kube-apiserver/app/options/options_test.go
Normal file
78
cmd/kube-apiserver/app/options/options_test.go
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
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 options
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
)
|
||||
|
||||
func TestGenerateStorageVersionMap(t *testing.T) {
|
||||
testCases := []struct {
|
||||
legacyVersion string
|
||||
storageVersions string
|
||||
defaultVersions string
|
||||
expectedMap map[string]string
|
||||
}{
|
||||
{
|
||||
legacyVersion: "v1",
|
||||
storageVersions: "v1,extensions/v1beta1",
|
||||
expectedMap: map[string]string{
|
||||
api.GroupName: "v1",
|
||||
extensions.GroupName: "extensions/v1beta1",
|
||||
},
|
||||
},
|
||||
{
|
||||
legacyVersion: "",
|
||||
storageVersions: "extensions/v1beta1,v1",
|
||||
expectedMap: map[string]string{
|
||||
api.GroupName: "v1",
|
||||
extensions.GroupName: "extensions/v1beta1",
|
||||
},
|
||||
},
|
||||
{
|
||||
legacyVersion: "",
|
||||
storageVersions: "autoscaling=extensions/v1beta1,v1",
|
||||
defaultVersions: "extensions/v1beta1,v1,autoscaling/v1",
|
||||
expectedMap: map[string]string{
|
||||
api.GroupName: "v1",
|
||||
autoscaling.GroupName: "extensions/v1beta1",
|
||||
extensions.GroupName: "extensions/v1beta1",
|
||||
},
|
||||
},
|
||||
{
|
||||
legacyVersion: "",
|
||||
storageVersions: "",
|
||||
expectedMap: map[string]string{},
|
||||
},
|
||||
}
|
||||
for i, test := range testCases {
|
||||
s := APIServer{
|
||||
DeprecatedStorageVersion: test.legacyVersion,
|
||||
StorageVersions: test.storageVersions,
|
||||
DefaultStorageVersions: test.defaultVersions,
|
||||
}
|
||||
output := s.StorageGroupsToGroupVersions()
|
||||
if !reflect.DeepEqual(test.expectedMap, output) {
|
||||
t.Errorf("%v: unexpected error. expect: %v, got: %v", i, test.expectedMap, output)
|
||||
}
|
||||
}
|
||||
}
|
@ -36,8 +36,8 @@ import (
|
||||
"k8s.io/kubernetes/pkg/admission"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
apiutil "k8s.io/kubernetes/pkg/api/util"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apiserver"
|
||||
"k8s.io/kubernetes/pkg/apiserver/authenticator"
|
||||
@ -51,6 +51,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/master"
|
||||
"k8s.io/kubernetes/pkg/registry/cachesize"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/runtime/serializer/versioning"
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
"k8s.io/kubernetes/pkg/storage"
|
||||
etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
|
||||
@ -85,15 +86,20 @@ func verifyClusterIPFlags(s *options.APIServer) {
|
||||
}
|
||||
}
|
||||
|
||||
type newEtcdFunc func([]string, runtime.NegotiatedSerializer, string, string, bool) (storage.Interface, error)
|
||||
// For testing.
|
||||
type newEtcdFunc func([]string, runtime.NegotiatedSerializer, string, string, string, bool) (storage.Interface, error)
|
||||
|
||||
func newEtcd(etcdServerList []string, ns runtime.NegotiatedSerializer, storageGroupVersionString, pathPrefix string, quorum bool) (etcdStorage storage.Interface, err error) {
|
||||
func newEtcd(etcdServerList []string, ns runtime.NegotiatedSerializer, storageGroupVersionString, memoryGroupVersionString, pathPrefix string, quorum bool) (etcdStorage storage.Interface, err error) {
|
||||
if storageGroupVersionString == "" {
|
||||
return etcdStorage, fmt.Errorf("storageVersion is required to create a etcd storage")
|
||||
}
|
||||
storageVersion, err := unversioned.ParseGroupVersion(storageGroupVersionString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("couldn't understand storage version %v: %v", storageGroupVersionString, err)
|
||||
}
|
||||
memoryVersion, err := unversioned.ParseGroupVersion(memoryGroupVersionString)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't understand memory version %v: %v", memoryGroupVersionString, err)
|
||||
}
|
||||
|
||||
var storageConfig etcdstorage.EtcdConfig
|
||||
@ -104,23 +110,20 @@ func newEtcd(etcdServerList []string, ns runtime.NegotiatedSerializer, storageGr
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to find serializer for JSON")
|
||||
}
|
||||
storageConfig.Codec = runtime.NewCodec(ns.EncoderForVersion(s, storageVersion), ns.DecoderToVersion(s, unversioned.GroupVersion{Group: storageVersion.Group, Version: runtime.APIVersionInternal}))
|
||||
return storageConfig.NewStorage()
|
||||
}
|
||||
|
||||
// convert to a map between group and groupVersions.
|
||||
func generateStorageVersionMap(legacyVersion string, storageVersions string) map[string]string {
|
||||
storageVersionMap := map[string]string{}
|
||||
if legacyVersion != "" {
|
||||
storageVersionMap[""] = legacyVersion
|
||||
}
|
||||
if storageVersions != "" {
|
||||
groupVersions := strings.Split(storageVersions, ",")
|
||||
for _, gv := range groupVersions {
|
||||
storageVersionMap[apiutil.GetGroup(gv)] = gv
|
||||
glog.Infof("constructing etcd storage interface.\n sv: %v\n mv: %v\n", storageVersion, memoryVersion)
|
||||
encoder := ns.EncoderForVersion(s, storageVersion)
|
||||
decoder := ns.DecoderToVersion(s, memoryVersion)
|
||||
if memoryVersion.Group != storageVersion.Group {
|
||||
// Allow this codec to translate between groups.
|
||||
if err = versioning.EnableCrossGroupEncoding(encoder, memoryVersion.Group, storageVersion.Group); err != nil {
|
||||
return nil, fmt.Errorf("error setting up encoder for %v: %v", storageGroupVersionString, err)
|
||||
}
|
||||
if err = versioning.EnableCrossGroupDecoding(decoder, storageVersion.Group, memoryVersion.Group); err != nil {
|
||||
return nil, fmt.Errorf("error setting up decoder for %v: %v", storageGroupVersionString, err)
|
||||
}
|
||||
}
|
||||
return storageVersionMap
|
||||
storageConfig.Codec = runtime.NewCodec(encoder, decoder)
|
||||
return storageConfig.NewStorage()
|
||||
}
|
||||
|
||||
// parse the value of --etcd-servers-overrides and update given storageDestinations.
|
||||
@ -153,7 +156,11 @@ func updateEtcdOverrides(overrides []string, storageVersions map[string]string,
|
||||
}
|
||||
|
||||
servers := strings.Split(tokens[1], ";")
|
||||
etcdOverrideStorage, err := newEtcdFn(servers, api.Codecs, storageVersions[apigroup.GroupVersion.Group], prefix, quorum)
|
||||
// Note, internalGV will be wrong for things like batch or
|
||||
// autoscalers, but they shouldn't be using the override
|
||||
// storage.
|
||||
internalGV := apigroup.GroupVersion.Group + "/__internal"
|
||||
etcdOverrideStorage, err := newEtcdFn(servers, api.Codecs, storageVersions[apigroup.GroupVersion.Group], internalGV, prefix, quorum)
|
||||
if err != nil {
|
||||
glog.Fatalf("Invalid storage version or misconfigured etcd for %s: %v", tokens[0], err)
|
||||
}
|
||||
@ -269,17 +276,18 @@ func Run(s *options.APIServer) error {
|
||||
|
||||
storageDestinations := genericapiserver.NewStorageDestinations()
|
||||
|
||||
storageVersions := generateStorageVersionMap(s.DeprecatedStorageVersion, s.StorageVersions)
|
||||
storageVersions := s.StorageGroupsToGroupVersions()
|
||||
if _, found := storageVersions[legacyV1Group.GroupVersion.Group]; !found {
|
||||
glog.Fatalf("Couldn't find the storage version for group: %q in storageVersions: %v", legacyV1Group.GroupVersion.Group, storageVersions)
|
||||
}
|
||||
etcdStorage, err := newEtcd(s.EtcdServerList, api.Codecs, storageVersions[legacyV1Group.GroupVersion.Group], s.EtcdPathPrefix, s.EtcdQuorumRead)
|
||||
etcdStorage, err := newEtcd(s.EtcdServerList, api.Codecs, storageVersions[legacyV1Group.GroupVersion.Group], "/__internal", s.EtcdPathPrefix, s.EtcdQuorumRead)
|
||||
if err != nil {
|
||||
glog.Fatalf("Invalid storage version or misconfigured etcd: %v", err)
|
||||
}
|
||||
storageDestinations.AddAPIGroup("", etcdStorage)
|
||||
|
||||
if !apiGroupVersionOverrides["extensions/v1beta1"].Disable {
|
||||
glog.Infof("Configuring extensions/v1beta1 storage destination")
|
||||
expGroup, err := registered.Group(extensions.GroupName)
|
||||
if err != nil {
|
||||
glog.Fatalf("Extensions API is enabled in runtime config, but not enabled in the environment variable KUBE_API_VERSIONS. Error: %v", err)
|
||||
@ -287,11 +295,42 @@ func Run(s *options.APIServer) error {
|
||||
if _, found := storageVersions[expGroup.GroupVersion.Group]; !found {
|
||||
glog.Fatalf("Couldn't find the storage version for group: %q in storageVersions: %v", expGroup.GroupVersion.Group, storageVersions)
|
||||
}
|
||||
expEtcdStorage, err := newEtcd(s.EtcdServerList, api.Codecs, storageVersions[expGroup.GroupVersion.Group], s.EtcdPathPrefix, s.EtcdQuorumRead)
|
||||
expEtcdStorage, err := newEtcd(s.EtcdServerList, api.Codecs, storageVersions[expGroup.GroupVersion.Group], "extensions/__internal", s.EtcdPathPrefix, s.EtcdQuorumRead)
|
||||
if err != nil {
|
||||
glog.Fatalf("Invalid extensions storage version or misconfigured etcd: %v", err)
|
||||
}
|
||||
storageDestinations.AddAPIGroup(extensions.GroupName, expEtcdStorage)
|
||||
|
||||
// Since HPA has been moved to the autoscaling group, we need to make
|
||||
// sure autoscaling has a storage destination. If the autoscaling group
|
||||
// itself is on, it will overwrite this decision below.
|
||||
storageDestinations.AddAPIGroup(autoscaling.GroupName, expEtcdStorage)
|
||||
}
|
||||
|
||||
// autoscaling/v1/horizontalpodautoscalers is a move from extensions/v1beta1/horizontalpodautoscalers.
|
||||
// The storage version needs to be either extensions/v1beta1 or autoscaling/v1.
|
||||
// Users must roll forward while using 1.2, because we will require the latter for 1.3.
|
||||
if !apiGroupVersionOverrides["autoscaling/v1"].Disable {
|
||||
glog.Infof("Configuring autoscaling/v1 storage destination")
|
||||
autoscalingGroup, err := registered.Group(autoscaling.GroupName)
|
||||
if err != nil {
|
||||
glog.Fatalf("Autoscaling API is enabled in runtime config, but not enabled in the environment variable KUBE_API_VERSIONS. Error: %v", err)
|
||||
}
|
||||
// Figure out what storage group/version we should use.
|
||||
storageGroupVersion, found := storageVersions[autoscalingGroup.GroupVersion.Group]
|
||||
if !found {
|
||||
glog.Fatalf("Couldn't find the storage version for group: %q in storageVersions: %v", autoscalingGroup.GroupVersion.Group, storageVersions)
|
||||
}
|
||||
|
||||
if storageGroupVersion != "autoscaling/v1" && storageGroupVersion != "extensions/v1beta1" {
|
||||
glog.Fatalf("The storage version for autoscaling must be either 'autoscaling/v1' or 'extensions/v1beta1'")
|
||||
}
|
||||
glog.Infof("Using %v for autoscaling group storage version", storageGroupVersion)
|
||||
autoscalingEtcdStorage, err := newEtcd(s.EtcdServerList, api.Codecs, storageGroupVersion, "extensions/__internal", s.EtcdPathPrefix, s.EtcdQuorumRead)
|
||||
if err != nil {
|
||||
glog.Fatalf("Invalid extensions storage version or misconfigured etcd: %v", err)
|
||||
}
|
||||
storageDestinations.AddAPIGroup(autoscaling.GroupName, autoscalingEtcdStorage)
|
||||
}
|
||||
|
||||
updateEtcdOverrides(s.EtcdServersOverrides, storageVersions, s.EtcdPathPrefix, s.EtcdQuorumRead, &storageDestinations, newEtcd)
|
||||
@ -473,6 +512,15 @@ func parseRuntimeConfig(s *options.APIServer) (map[string]genericapiserver.APIGr
|
||||
}
|
||||
}
|
||||
|
||||
disableAutoscaling := disableAllAPIs
|
||||
autoscalingGroupVersion := "autoscaling/v1"
|
||||
disableAutoscaling = !getRuntimeConfigValue(s, autoscalingGroupVersion, !disableAutoscaling)
|
||||
if disableAutoscaling {
|
||||
apiGroupVersionOverrides[autoscalingGroupVersion] = genericapiserver.APIGroupVersionOverride{
|
||||
Disable: true,
|
||||
}
|
||||
}
|
||||
|
||||
for key := range s.RuntimeConfig {
|
||||
if strings.HasPrefix(key, v1GroupVersion+"/") {
|
||||
return nil, fmt.Errorf("api/v1 resources cannot be enabled/disabled individually")
|
||||
|
@ -71,44 +71,11 @@ func TestLongRunningRequestRegexp(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateStorageVersionMap(t *testing.T) {
|
||||
testCases := []struct {
|
||||
legacyVersion string
|
||||
storageVersions string
|
||||
expectedMap map[string]string
|
||||
}{
|
||||
{
|
||||
legacyVersion: "v1",
|
||||
storageVersions: "v1,extensions/v1beta1",
|
||||
expectedMap: map[string]string{
|
||||
api.GroupName: "v1",
|
||||
extensions.GroupName: "extensions/v1beta1",
|
||||
},
|
||||
},
|
||||
{
|
||||
legacyVersion: "",
|
||||
storageVersions: "extensions/v1beta1,v1",
|
||||
expectedMap: map[string]string{
|
||||
api.GroupName: "v1",
|
||||
extensions.GroupName: "extensions/v1beta1",
|
||||
},
|
||||
},
|
||||
{
|
||||
legacyVersion: "",
|
||||
storageVersions: "",
|
||||
expectedMap: map[string]string{},
|
||||
},
|
||||
}
|
||||
for _, test := range testCases {
|
||||
output := generateStorageVersionMap(test.legacyVersion, test.storageVersions)
|
||||
if !reflect.DeepEqual(test.expectedMap, output) {
|
||||
t.Errorf("unexpected error. expect: %v, got: %v", test.expectedMap, output)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateEtcdOverrides(t *testing.T) {
|
||||
storageVersions := generateStorageVersionMap("", "v1,extensions/v1beta1")
|
||||
storageVersions := map[string]string{
|
||||
"": "v1",
|
||||
"extensions": "extensions/v1beta1",
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
apigroup string
|
||||
@ -133,7 +100,7 @@ func TestUpdateEtcdOverrides(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
newEtcd := func(serverList []string, _ runtime.NegotiatedSerializer, _, _ string, _ bool) (storage.Interface, error) {
|
||||
newEtcd := func(serverList []string, _ runtime.NegotiatedSerializer, _, _, _ string, _ bool) (storage.Interface, error) {
|
||||
if !reflect.DeepEqual(test.servers, serverList) {
|
||||
t.Errorf("unexpected server list, expected: %#v, got: %#v", test.servers, serverList)
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ kube-apiserver
|
||||
--service-node-port-range=: A port range to reserve for services with NodePort visibility. Example: '30000-32767'. Inclusive at both ends of the range.
|
||||
--ssh-keyfile="": If non-empty, use secure SSH proxy to the nodes, using this user keyfile
|
||||
--ssh-user="": If non-empty, use secure SSH proxy to the nodes, using this user name
|
||||
--storage-versions="authorization.k8s.io/v1beta1,componentconfig/v1alpha1,extensions/v1beta1,metrics/v1alpha1,v1": The versions to store resources with. Different groups may be stored in different versions. Specified in the format "group1/version1,group2/version2...". This flag expects a complete list of storage versions of ALL groups registered in the server. It defaults to a list of preferred versions of all registered groups, which is derived from the KUBE_API_VERSIONS environment variable.
|
||||
--storage-versions="authorization.k8s.io/v1beta1,autoscaling/v1,componentconfig/v1alpha1,extensions/v1beta1,metrics/v1alpha1,v1": The per-group version to store resources in. Specified in the format "group1/version1,group2/version2,...". In the case where objects are moved from one group to the other, you may specify the format "group1=group2/v1beta1,group3/v1beta1,...". You only need to pass the groups you wish to change from the defaults. It defaults to a list of preferred versions of all registered groups, which is derived from the KUBE_API_VERSIONS environment variable.
|
||||
--tls-cert-file="": File containing x509 Certificate for HTTPS. (CA cert, if any, concatenated after server cert). If HTTPS serving is enabled, and --tls-cert-file and --tls-private-key-file are not provided, a self-signed certificate and key are generated for the public address and saved to /var/run/kubernetes.
|
||||
--tls-private-key-file="": File containing x509 private key matching --tls-cert-file.
|
||||
--token-auth-file="": If set, the file that will be used to secure the secure port of the API server via token authentication.
|
||||
@ -110,7 +110,7 @@ kube-apiserver
|
||||
--watch-cache-sizes=[]: List of watch cache sizes for every resource (pods, nodes, etc.), comma separated. The individual override format: resource#size, where size is a number. It takes effect when watch-cache is enabled.
|
||||
```
|
||||
|
||||
###### Auto generated by spf13/cobra on 10-Feb-2016
|
||||
###### Auto generated by spf13/cobra on 15-Feb-2016
|
||||
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
|
@ -43,7 +43,7 @@ EOF
|
||||
}
|
||||
|
||||
# TODO(lavalamp): get this list by listing the pkg/apis/ directory?
|
||||
DEFAULT_GROUP_VERSIONS="v1 authorization/v1beta1 extensions/v1beta1 componentconfig/v1alpha1 metrics/v1alpha1"
|
||||
DEFAULT_GROUP_VERSIONS="v1 authorization/v1beta1 autoscaling/v1 extensions/v1beta1 componentconfig/v1alpha1 metrics/v1alpha1"
|
||||
VERSIONS=${VERSIONS:-$DEFAULT_GROUP_VERSIONS}
|
||||
for ver in $VERSIONS; do
|
||||
# Ensure that the version being processed is registered by setting
|
||||
|
@ -62,6 +62,6 @@ function generate_deep_copies() {
|
||||
# Currently pkg/api/deep_copy_generated.go is generated by the new go2idl generator.
|
||||
# All others (mentioned above) are still generated by the old reflection-based generator.
|
||||
# TODO: Migrate these to the new generator.
|
||||
DEFAULT_VERSIONS="v1 authorization/__internal authorization/v1beta1 extensions/__internal extensions/v1beta1 componentconfig/__internal componentconfig/v1alpha1 metrics/__internal metrics/v1alpha1"
|
||||
DEFAULT_VERSIONS="v1 authorization/__internal authorization/v1beta1 autoscaling/__internal autoscaling/v1 extensions/__internal extensions/v1beta1 componentconfig/__internal componentconfig/v1alpha1 metrics/__internal metrics/v1alpha1"
|
||||
VERSIONS=${VERSIONS:-$DEFAULT_VERSIONS}
|
||||
generate_deep_copies "$VERSIONS"
|
||||
|
@ -50,7 +50,7 @@ kube::etcd::start
|
||||
|
||||
# Start kube-apiserver
|
||||
kube::log::status "Starting kube-apiserver"
|
||||
KUBE_API_VERSIONS="v1,extensions/v1beta1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \
|
||||
--address="127.0.0.1" \
|
||||
--public-address-override="127.0.0.1" \
|
||||
--port="${API_PORT}" \
|
||||
@ -64,7 +64,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 extensions/v1beta1"
|
||||
DEFAULT_GROUP_VERSIONS="v1 autoscaling/v1 extensions/v1beta1"
|
||||
VERSIONS=${VERSIONS:-$DEFAULT_GROUP_VERSIONS}
|
||||
|
||||
kube::log::status "Updating " ${SWAGGER_ROOT_DIR}
|
||||
|
@ -23,7 +23,7 @@ source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||
|
||||
kube::golang::setup_env
|
||||
|
||||
APIROOTS=${APIROOTS:-pkg/api pkg/apis/authorization pkg/apis/extensions pkg/apis/metrics}
|
||||
APIROOTS=${APIROOTS:-pkg/api pkg/apis/authorization pkg/apis/autoscaling pkg/apis/extensions pkg/apis/metrics}
|
||||
_tmp="${KUBE_ROOT}/_tmp"
|
||||
|
||||
cleanup() {
|
||||
|
@ -25,7 +25,7 @@ kube::golang::setup_env
|
||||
|
||||
gendeepcopy=$(kube::util::find-binary "gendeepcopy")
|
||||
|
||||
APIROOTS=${APIROOTS:-pkg/api pkg/apis/authorization pkg/apis/extensions pkg/apis/metrics}
|
||||
APIROOTS=${APIROOTS:-pkg/api pkg/apis/authorization pkg/apis/autoscaling pkg/apis/extensions pkg/apis/metrics}
|
||||
_tmp="${KUBE_ROOT}/_tmp"
|
||||
|
||||
cleanup() {
|
||||
|
@ -178,7 +178,7 @@ kube::log::status "Starting kube-apiserver"
|
||||
# Admission Controllers to invoke prior to persisting objects in cluster
|
||||
ADMISSION_CONTROL="NamespaceLifecycle,LimitRanger,ResourceQuota"
|
||||
|
||||
KUBE_API_VERSIONS="v1,extensions/v1beta1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \
|
||||
--address="127.0.0.1" \
|
||||
--public-address-override="127.0.0.1" \
|
||||
--port="${API_PORT}" \
|
||||
@ -1581,7 +1581,7 @@ kube_api_versions=(
|
||||
v1
|
||||
)
|
||||
for version in "${kube_api_versions[@]}"; do
|
||||
KUBE_API_VERSIONS="v1,extensions/v1beta1" runTests "${version}"
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" runTests "${version}"
|
||||
done
|
||||
|
||||
kube::log::status "TEST PASSED"
|
||||
|
@ -58,7 +58,7 @@ KUBE_GOVERALLS_BIN=${KUBE_GOVERALLS_BIN:-}
|
||||
# Lists of API Versions of each groups that should be tested, groups are
|
||||
# separated by comma, lists are separated by semicolon. e.g.,
|
||||
# "v1,compute/v1alpha1,experimental/v1alpha2;v1,compute/v2,experimental/v1alpha3"
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1,metrics/v1alpha1"}
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1,metrics/v1alpha1;v1,autoscaling/v1,extensions/v1beta1,metrics/v1alpha1"}
|
||||
# once we have multiple group supports
|
||||
# Run tests with the standard (registry) and a custom etcd prefix
|
||||
# (kubernetes.io/registry).
|
||||
@ -315,7 +315,7 @@ for (( i=0, j=0; ; )); do
|
||||
# KUBE_TEST_API sets the version of each group to be tested. KUBE_API_VERSIONS
|
||||
# register the groups/versions as supported by k8s. So KUBE_API_VERSIONS
|
||||
# needs to be the superset of KUBE_TEST_API.
|
||||
KUBE_TEST_API="${apiVersion}" KUBE_API_VERSIONS="v1,extensions/v1beta1,componentconfig/v1alpha1,metrics/v1alpha1" ETCD_PREFIX=${etcdPrefix} runTests "$@"
|
||||
KUBE_TEST_API="${apiVersion}" KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1,componentconfig/v1alpha1,metrics/v1alpha1" ETCD_PREFIX=${etcdPrefix} runTests "$@"
|
||||
i=${i}+1
|
||||
j=${j}+1
|
||||
if [[ i -eq ${apiVersionsCount} ]] && [[ j -eq ${etcdPrefixesCount} ]]; then
|
||||
|
@ -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"}
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1;v1,autoscaling/v1,extensions/v1beta1"}
|
||||
|
||||
# Give integration tests longer to run
|
||||
KUBE_TIMEOUT=${KUBE_TIMEOUT:--timeout 240s}
|
||||
@ -52,22 +52,21 @@ runTests() {
|
||||
KUBE_RACE="" \
|
||||
KUBE_TIMEOUT="${KUBE_TIMEOUT}" \
|
||||
KUBE_TEST_API_VERSIONS="$1" \
|
||||
KUBE_API_VERSIONS="v1,extensions/v1beta1" \
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" \
|
||||
"${KUBE_ROOT}/hack/test-go.sh" test/integration
|
||||
|
||||
kube::log::status "Running integration test scenario with watch cache on"
|
||||
KUBE_API_VERSIONS="v1,extensions/v1beta1" KUBE_TEST_API_VERSIONS="$1" "${KUBE_OUTPUT_HOSTBIN}/integration" --v=${LOG_LEVEL} \
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" KUBE_TEST_API_VERSIONS="$1" "${KUBE_OUTPUT_HOSTBIN}/integration" --v=${LOG_LEVEL} \
|
||||
--max-concurrency="${KUBE_INTEGRATION_TEST_MAX_CONCURRENCY}" --watch-cache=true
|
||||
|
||||
kube::log::status "Running integration test scenario with watch cache off"
|
||||
KUBE_API_VERSIONS="v1,extensions/v1beta1" KUBE_TEST_API_VERSIONS="$1" "${KUBE_OUTPUT_HOSTBIN}/integration" --v=${LOG_LEVEL} \
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" KUBE_TEST_API_VERSIONS="$1" "${KUBE_OUTPUT_HOSTBIN}/integration" --v=${LOG_LEVEL} \
|
||||
--max-concurrency="${KUBE_INTEGRATION_TEST_MAX_CONCURRENCY}" --watch-cache=false
|
||||
|
||||
|
||||
cleanup
|
||||
}
|
||||
|
||||
KUBE_API_VERSIONS="v1,extensions/v1beta1" "${KUBE_ROOT}/hack/build-go.sh" "$@" cmd/integration
|
||||
KUBE_API_VERSIONS="v1,autoscaling/v1,extensions/v1beta1" "${KUBE_ROOT}/hack/build-go.sh" "$@" cmd/integration
|
||||
|
||||
# Run cleanup to stop etcd on interrupt or other kill signal.
|
||||
trap cleanup EXIT
|
||||
|
@ -56,7 +56,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 extensions/v1beta1)
|
||||
GROUP_VERSIONS=(unversioned v1 authorization/v1beta1 autoscaling/v1 extensions/v1beta1)
|
||||
# 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"
|
||||
|
@ -180,7 +180,7 @@ func doRoundTripTest(group testapi.TestGroup, kind string, t *testing.T) {
|
||||
if api.Scheme.Recognizes(group.GroupVersion().WithKind(kind)) {
|
||||
roundTripSame(t, group, item, nonRoundTrippableTypesByVersion[kind]...)
|
||||
}
|
||||
if !nonInternalRoundTrippableTypes.Has(kind) {
|
||||
if !nonInternalRoundTrippableTypes.Has(kind) && api.Scheme.Recognizes(group.GroupVersion().WithKind(kind)) {
|
||||
roundTrip(t, group.Codec(), fuzzInternalObject(t, group.InternalGroupVersion(), item, rand.Int63()))
|
||||
}
|
||||
}
|
||||
|
@ -26,19 +26,22 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/metrics/install"
|
||||
)
|
||||
|
||||
var (
|
||||
Groups = make(map[string]TestGroup)
|
||||
Default TestGroup
|
||||
Extensions TestGroup
|
||||
Groups = make(map[string]TestGroup)
|
||||
Default TestGroup
|
||||
Autoscaling TestGroup
|
||||
Extensions TestGroup
|
||||
)
|
||||
|
||||
type TestGroup struct {
|
||||
@ -69,6 +72,12 @@ func init() {
|
||||
internalGroupVersion: api.SchemeGroupVersion,
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[autoscaling.GroupName]; !ok {
|
||||
Groups[autoscaling.GroupName] = TestGroup{
|
||||
externalGroupVersion: unversioned.GroupVersion{Group: autoscaling.GroupName, Version: registered.GroupOrDie(autoscaling.GroupName).GroupVersion.Version},
|
||||
internalGroupVersion: extensions.SchemeGroupVersion,
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[extensions.GroupName]; !ok {
|
||||
Groups[extensions.GroupName] = TestGroup{
|
||||
externalGroupVersion: unversioned.GroupVersion{Group: extensions.GroupName, Version: registered.GroupOrDie(extensions.GroupName).GroupVersion.Version},
|
||||
@ -77,6 +86,7 @@ func init() {
|
||||
}
|
||||
|
||||
Default = Groups[api.GroupName]
|
||||
Autoscaling = Groups[autoscaling.GroupName]
|
||||
Extensions = Groups[extensions.GroupName]
|
||||
}
|
||||
|
||||
|
@ -100,9 +100,8 @@ func TestV1EncodeDecodeStatus(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestExperimentalEncodeDecodeStatus(t *testing.T) {
|
||||
extensionCodec := Extensions.Codec()
|
||||
encoded, err := runtime.Encode(extensionCodec, status)
|
||||
func testEncodeDecodeStatus(t *testing.T, codec runtime.Codec) {
|
||||
encoded, err := runtime.Encode(codec, status)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@ -116,7 +115,7 @@ func TestExperimentalEncodeDecodeStatus(t *testing.T) {
|
||||
if typeMeta.APIVersion != "v1" {
|
||||
t.Errorf("APIVersion is not set to \"\". Got %s", encoded)
|
||||
}
|
||||
decoded, err := runtime.Decode(extensionCodec, encoded)
|
||||
decoded, err := runtime.Decode(codec, encoded)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@ -124,3 +123,11 @@ func TestExperimentalEncodeDecodeStatus(t *testing.T) {
|
||||
t.Errorf("expected: %v, got: %v", status, decoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoscalingEncodeDecodeStatus(t *testing.T) {
|
||||
testEncodeDecodeStatus(t, Autoscaling.Codec())
|
||||
}
|
||||
|
||||
func TestExperimentalEncodeDecodeStatus(t *testing.T) {
|
||||
testEncodeDecodeStatus(t, Extensions.Codec())
|
||||
}
|
||||
|
@ -397,6 +397,10 @@ func FuzzerFor(t *testing.T, version unversioned.GroupVersion, src rand.Source)
|
||||
s.MinReplicas = &minReplicas
|
||||
s.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: int(int32(c.RandUint64()))}
|
||||
},
|
||||
func(s *extensions.SubresourceReference, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(s) // fuzz self without calling this function again
|
||||
s.Subresource = "scale"
|
||||
},
|
||||
func(psp *extensions.PodSecurityPolicySpec, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(psp) // fuzz self without calling this function again
|
||||
userTypes := []extensions.RunAsUserStrategy{extensions.RunAsUserStrategyMustRunAsNonRoot, extensions.RunAsUserStrategyMustRunAs, extensions.RunAsUserStrategyRunAsAny}
|
||||
|
29
pkg/apis/autoscaling/deep_copy_generated.go
Normal file
29
pkg/apis/autoscaling/deep_copy_generated.go
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS AUTO-GENERATED BY $KUBEROOT/hack/update-generated-deep-copies.sh.
|
||||
|
||||
package autoscaling
|
||||
|
||||
import api "k8s.io/kubernetes/pkg/api"
|
||||
|
||||
func init() {
|
||||
err := api.Scheme.AddGeneratedDeepCopyFuncs()
|
||||
if err != nil {
|
||||
// if one of the deep copy functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
129
pkg/apis/autoscaling/install/install.go
Normal file
129
pkg/apis/autoscaling/install/install.go
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
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 install installs the experimental API group, making it available as
|
||||
// an option to all of the API encoding/decoding machinery.
|
||||
package install
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apimachinery"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
|
||||
const importPrefix = "k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
|
||||
var accessor = meta.NewAccessor()
|
||||
|
||||
// availableVersions lists all known external versions for this group from most preferred to least preferred
|
||||
var availableVersions = []unversioned.GroupVersion{v1.SchemeGroupVersion}
|
||||
|
||||
func init() {
|
||||
registered.RegisterVersions(availableVersions)
|
||||
externalVersions := []unversioned.GroupVersion{}
|
||||
for _, v := range availableVersions {
|
||||
if registered.IsAllowedVersion(v) {
|
||||
externalVersions = append(externalVersions, v)
|
||||
}
|
||||
}
|
||||
if len(externalVersions) == 0 {
|
||||
glog.V(4).Infof("No version is registered for group %v", autoscaling.GroupName)
|
||||
return
|
||||
}
|
||||
|
||||
if err := registered.EnableVersions(externalVersions...); err != nil {
|
||||
glog.V(4).Infof("%v", err)
|
||||
return
|
||||
}
|
||||
if err := enableVersions(externalVersions); err != nil {
|
||||
glog.V(4).Infof("%v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: enableVersions should be centralized rather than spread in each API
|
||||
// group.
|
||||
// We can combine registered.RegisterVersions, registered.EnableVersions and
|
||||
// registered.RegisterGroup once we have moved enableVersions there.
|
||||
func enableVersions(externalVersions []unversioned.GroupVersion) error {
|
||||
addVersionsToScheme(externalVersions...)
|
||||
preferredExternalVersion := externalVersions[0]
|
||||
|
||||
groupMeta := apimachinery.GroupMeta{
|
||||
GroupVersion: preferredExternalVersion,
|
||||
GroupVersions: externalVersions,
|
||||
RESTMapper: newRESTMapper(externalVersions),
|
||||
SelfLinker: runtime.SelfLinker(accessor),
|
||||
InterfacesFor: interfacesFor,
|
||||
}
|
||||
|
||||
if err := registered.RegisterGroup(groupMeta); err != nil {
|
||||
return err
|
||||
}
|
||||
api.RegisterRESTMapper(groupMeta.RESTMapper)
|
||||
return nil
|
||||
}
|
||||
|
||||
func newRESTMapper(externalVersions []unversioned.GroupVersion) meta.RESTMapper {
|
||||
// the list of kinds that are scoped at the root of the api hierarchy
|
||||
// if a kind is not enumerated here, it is assumed to have a namespace scope
|
||||
rootScoped := sets.NewString()
|
||||
|
||||
ignoredKinds := sets.NewString()
|
||||
|
||||
return api.NewDefaultRESTMapper(externalVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped)
|
||||
}
|
||||
|
||||
// interfacesFor returns the default Codec and ResourceVersioner for a given version
|
||||
// string, or an error if the version is not known.
|
||||
func interfacesFor(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
|
||||
switch version {
|
||||
case v1.SchemeGroupVersion:
|
||||
return &meta.VersionInterfaces{
|
||||
ObjectConvertor: api.Scheme,
|
||||
MetadataAccessor: accessor,
|
||||
}, nil
|
||||
default:
|
||||
g, _ := registered.Group(autoscaling.GroupName)
|
||||
return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, g.GroupVersions)
|
||||
}
|
||||
}
|
||||
|
||||
func addVersionsToScheme(externalVersions ...unversioned.GroupVersion) {
|
||||
// add the internal version to Scheme
|
||||
autoscaling.AddToScheme(api.Scheme)
|
||||
// add the enabled external versions to Scheme
|
||||
for _, v := range externalVersions {
|
||||
if !registered.IsEnabledVersion(v) {
|
||||
glog.Errorf("Version %s is not enabled, so it will not be added to the Scheme.", v)
|
||||
continue
|
||||
}
|
||||
switch v {
|
||||
case v1.SchemeGroupVersion:
|
||||
v1.AddToScheme(api.Scheme)
|
||||
}
|
||||
}
|
||||
}
|
54
pkg/apis/autoscaling/register.go
Normal file
54
pkg/apis/autoscaling/register.go
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package autoscaling
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "autoscaling"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
|
||||
|
||||
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
|
||||
func Kind(kind string) unversioned.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
|
||||
func Resource(resource string) unversioned.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
// Add the API to Scheme.
|
||||
addKnownTypes(scheme)
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&extensions.HorizontalPodAutoscaler{},
|
||||
&extensions.HorizontalPodAutoscalerList{},
|
||||
&api.ListOptions{},
|
||||
)
|
||||
}
|
101
pkg/apis/autoscaling/v1/conversion.go
Normal file
101
pkg/apis/autoscaling/v1/conversion.go
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func addConversionFuncs(scheme *runtime.Scheme) {
|
||||
// Add non-generated conversion functions
|
||||
err := scheme.AddConversionFuncs(
|
||||
Convert_extensions_SubresourceReference_To_v1_CrossVersionObjectReference,
|
||||
Convert_v1_CrossVersionObjectReference_To_extensions_SubresourceReference,
|
||||
Convert_extensions_HorizontalPodAutoscalerSpec_To_v1_HorizontalPodAutoscalerSpec,
|
||||
Convert_v1_HorizontalPodAutoscalerSpec_To_extensions_HorizontalPodAutoscalerSpec,
|
||||
)
|
||||
if err != nil {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func Convert_extensions_SubresourceReference_To_v1_CrossVersionObjectReference(in *extensions.SubresourceReference, out *CrossVersionObjectReference, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*extensions.SubresourceReference))(in)
|
||||
}
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
out.APIVersion = in.APIVersion
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_CrossVersionObjectReference_To_extensions_SubresourceReference(in *CrossVersionObjectReference, out *extensions.SubresourceReference, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*CrossVersionObjectReference))(in)
|
||||
}
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
out.APIVersion = in.APIVersion
|
||||
out.Subresource = "scale"
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_extensions_HorizontalPodAutoscalerSpec_To_v1_HorizontalPodAutoscalerSpec(in *extensions.HorizontalPodAutoscalerSpec, out *HorizontalPodAutoscalerSpec, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*extensions.HorizontalPodAutoscalerSpec))(in)
|
||||
}
|
||||
if err := Convert_extensions_SubresourceReference_To_v1_CrossVersionObjectReference(&in.ScaleRef, &out.ScaleTargetRef, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.MinReplicas != nil {
|
||||
out.MinReplicas = new(int32)
|
||||
*out.MinReplicas = int32(*in.MinReplicas)
|
||||
} else {
|
||||
out.MinReplicas = nil
|
||||
}
|
||||
out.MaxReplicas = int32(in.MaxReplicas)
|
||||
if in.CPUUtilization != nil {
|
||||
out.TargetCPUUtilizationPercentage = new(int32)
|
||||
*out.TargetCPUUtilizationPercentage = int32(in.CPUUtilization.TargetPercentage)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_HorizontalPodAutoscalerSpec_To_extensions_HorizontalPodAutoscalerSpec(in *HorizontalPodAutoscalerSpec, out *extensions.HorizontalPodAutoscalerSpec, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*HorizontalPodAutoscalerSpec))(in)
|
||||
}
|
||||
if err := Convert_v1_CrossVersionObjectReference_To_extensions_SubresourceReference(&in.ScaleTargetRef, &out.ScaleRef, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.MinReplicas != nil {
|
||||
out.MinReplicas = new(int)
|
||||
*out.MinReplicas = int(*in.MinReplicas)
|
||||
} else {
|
||||
out.MinReplicas = nil
|
||||
}
|
||||
out.MaxReplicas = int(in.MaxReplicas)
|
||||
if in.TargetCPUUtilizationPercentage != nil {
|
||||
out.CPUUtilization = &extensions.CPUTargetUtilization{TargetPercentage: int(*in.TargetCPUUtilizationPercentage)}
|
||||
}
|
||||
return nil
|
||||
}
|
352
pkg/apis/autoscaling/v1/conversion_generated.go
Normal file
352
pkg/apis/autoscaling/v1/conversion_generated.go
Normal file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS AUTO-GENERATED BY $KUBEROOT/hack/update-generated-conversions.sh
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
extensions "k8s.io/kubernetes/pkg/apis/extensions"
|
||||
conversion "k8s.io/kubernetes/pkg/conversion"
|
||||
)
|
||||
|
||||
func autoConvert_api_ObjectMeta_To_v1_ObjectMeta(in *api.ObjectMeta, out *v1.ObjectMeta, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*api.ObjectMeta))(in)
|
||||
}
|
||||
out.Name = in.Name
|
||||
out.GenerateName = in.GenerateName
|
||||
out.Namespace = in.Namespace
|
||||
out.SelfLink = in.SelfLink
|
||||
out.UID = in.UID
|
||||
out.ResourceVersion = in.ResourceVersion
|
||||
out.Generation = in.Generation
|
||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(&in.CreationTimestamp, &out.CreationTimestamp, s); err != nil {
|
||||
return err
|
||||
}
|
||||
// unable to generate simple pointer conversion for unversioned.Time -> unversioned.Time
|
||||
if in.DeletionTimestamp != nil {
|
||||
out.DeletionTimestamp = new(unversioned.Time)
|
||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(in.DeletionTimestamp, out.DeletionTimestamp, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.DeletionTimestamp = nil
|
||||
}
|
||||
if in.DeletionGracePeriodSeconds != nil {
|
||||
out.DeletionGracePeriodSeconds = new(int64)
|
||||
*out.DeletionGracePeriodSeconds = *in.DeletionGracePeriodSeconds
|
||||
} else {
|
||||
out.DeletionGracePeriodSeconds = nil
|
||||
}
|
||||
if in.Labels != nil {
|
||||
out.Labels = make(map[string]string)
|
||||
for key, val := range in.Labels {
|
||||
out.Labels[key] = val
|
||||
}
|
||||
} else {
|
||||
out.Labels = nil
|
||||
}
|
||||
if in.Annotations != nil {
|
||||
out.Annotations = make(map[string]string)
|
||||
for key, val := range in.Annotations {
|
||||
out.Annotations[key] = val
|
||||
}
|
||||
} else {
|
||||
out.Annotations = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_api_ObjectMeta_To_v1_ObjectMeta(in *api.ObjectMeta, out *v1.ObjectMeta, s conversion.Scope) error {
|
||||
return autoConvert_api_ObjectMeta_To_v1_ObjectMeta(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_ObjectMeta_To_api_ObjectMeta(in *v1.ObjectMeta, out *api.ObjectMeta, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*v1.ObjectMeta))(in)
|
||||
}
|
||||
out.Name = in.Name
|
||||
out.GenerateName = in.GenerateName
|
||||
out.Namespace = in.Namespace
|
||||
out.SelfLink = in.SelfLink
|
||||
out.UID = in.UID
|
||||
out.ResourceVersion = in.ResourceVersion
|
||||
out.Generation = in.Generation
|
||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(&in.CreationTimestamp, &out.CreationTimestamp, s); err != nil {
|
||||
return err
|
||||
}
|
||||
// unable to generate simple pointer conversion for unversioned.Time -> unversioned.Time
|
||||
if in.DeletionTimestamp != nil {
|
||||
out.DeletionTimestamp = new(unversioned.Time)
|
||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(in.DeletionTimestamp, out.DeletionTimestamp, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.DeletionTimestamp = nil
|
||||
}
|
||||
if in.DeletionGracePeriodSeconds != nil {
|
||||
out.DeletionGracePeriodSeconds = new(int64)
|
||||
*out.DeletionGracePeriodSeconds = *in.DeletionGracePeriodSeconds
|
||||
} else {
|
||||
out.DeletionGracePeriodSeconds = nil
|
||||
}
|
||||
if in.Labels != nil {
|
||||
out.Labels = make(map[string]string)
|
||||
for key, val := range in.Labels {
|
||||
out.Labels[key] = val
|
||||
}
|
||||
} else {
|
||||
out.Labels = nil
|
||||
}
|
||||
if in.Annotations != nil {
|
||||
out.Annotations = make(map[string]string)
|
||||
for key, val := range in.Annotations {
|
||||
out.Annotations[key] = val
|
||||
}
|
||||
} else {
|
||||
out.Annotations = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_ObjectMeta_To_api_ObjectMeta(in *v1.ObjectMeta, out *api.ObjectMeta, s conversion.Scope) error {
|
||||
return autoConvert_v1_ObjectMeta_To_api_ObjectMeta(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_HorizontalPodAutoscaler_To_extensions_HorizontalPodAutoscaler(in *HorizontalPodAutoscaler, out *extensions.HorizontalPodAutoscaler, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*HorizontalPodAutoscaler))(in)
|
||||
}
|
||||
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1_ObjectMeta_To_api_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1_HorizontalPodAutoscalerSpec_To_extensions_HorizontalPodAutoscalerSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1_HorizontalPodAutoscalerStatus_To_extensions_HorizontalPodAutoscalerStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_HorizontalPodAutoscaler_To_extensions_HorizontalPodAutoscaler(in *HorizontalPodAutoscaler, out *extensions.HorizontalPodAutoscaler, s conversion.Scope) error {
|
||||
return autoConvert_v1_HorizontalPodAutoscaler_To_extensions_HorizontalPodAutoscaler(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_HorizontalPodAutoscalerList_To_extensions_HorizontalPodAutoscalerList(in *HorizontalPodAutoscalerList, out *extensions.HorizontalPodAutoscalerList, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*HorizontalPodAutoscalerList))(in)
|
||||
}
|
||||
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 {
|
||||
out.Items = make([]extensions.HorizontalPodAutoscaler, len(in.Items))
|
||||
for i := range in.Items {
|
||||
if err := Convert_v1_HorizontalPodAutoscaler_To_extensions_HorizontalPodAutoscaler(&in.Items[i], &out.Items[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_HorizontalPodAutoscalerList_To_extensions_HorizontalPodAutoscalerList(in *HorizontalPodAutoscalerList, out *extensions.HorizontalPodAutoscalerList, s conversion.Scope) error {
|
||||
return autoConvert_v1_HorizontalPodAutoscalerList_To_extensions_HorizontalPodAutoscalerList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_HorizontalPodAutoscalerSpec_To_extensions_HorizontalPodAutoscalerSpec(in *HorizontalPodAutoscalerSpec, out *extensions.HorizontalPodAutoscalerSpec, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*HorizontalPodAutoscalerSpec))(in)
|
||||
}
|
||||
// in.ScaleTargetRef has no peer in out
|
||||
if in.MinReplicas != nil {
|
||||
out.MinReplicas = new(int)
|
||||
*out.MinReplicas = int(*in.MinReplicas)
|
||||
} else {
|
||||
out.MinReplicas = nil
|
||||
}
|
||||
out.MaxReplicas = int(in.MaxReplicas)
|
||||
// in.TargetCPUUtilizationPercentage has no peer in out
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1_HorizontalPodAutoscalerStatus_To_extensions_HorizontalPodAutoscalerStatus(in *HorizontalPodAutoscalerStatus, out *extensions.HorizontalPodAutoscalerStatus, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*HorizontalPodAutoscalerStatus))(in)
|
||||
}
|
||||
if in.ObservedGeneration != nil {
|
||||
out.ObservedGeneration = new(int64)
|
||||
*out.ObservedGeneration = *in.ObservedGeneration
|
||||
} else {
|
||||
out.ObservedGeneration = nil
|
||||
}
|
||||
// unable to generate simple pointer conversion for unversioned.Time -> unversioned.Time
|
||||
if in.LastScaleTime != nil {
|
||||
out.LastScaleTime = new(unversioned.Time)
|
||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(in.LastScaleTime, out.LastScaleTime, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.LastScaleTime = nil
|
||||
}
|
||||
out.CurrentReplicas = int(in.CurrentReplicas)
|
||||
out.DesiredReplicas = int(in.DesiredReplicas)
|
||||
if in.CurrentCPUUtilizationPercentage != nil {
|
||||
out.CurrentCPUUtilizationPercentage = new(int)
|
||||
*out.CurrentCPUUtilizationPercentage = int(*in.CurrentCPUUtilizationPercentage)
|
||||
} else {
|
||||
out.CurrentCPUUtilizationPercentage = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1_HorizontalPodAutoscalerStatus_To_extensions_HorizontalPodAutoscalerStatus(in *HorizontalPodAutoscalerStatus, out *extensions.HorizontalPodAutoscalerStatus, s conversion.Scope) error {
|
||||
return autoConvert_v1_HorizontalPodAutoscalerStatus_To_extensions_HorizontalPodAutoscalerStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_extensions_HorizontalPodAutoscaler_To_v1_HorizontalPodAutoscaler(in *extensions.HorizontalPodAutoscaler, out *HorizontalPodAutoscaler, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*extensions.HorizontalPodAutoscaler))(in)
|
||||
}
|
||||
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_api_ObjectMeta_To_v1_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_extensions_HorizontalPodAutoscalerSpec_To_v1_HorizontalPodAutoscalerSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_extensions_HorizontalPodAutoscalerStatus_To_v1_HorizontalPodAutoscalerStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_extensions_HorizontalPodAutoscaler_To_v1_HorizontalPodAutoscaler(in *extensions.HorizontalPodAutoscaler, out *HorizontalPodAutoscaler, s conversion.Scope) error {
|
||||
return autoConvert_extensions_HorizontalPodAutoscaler_To_v1_HorizontalPodAutoscaler(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_extensions_HorizontalPodAutoscalerList_To_v1_HorizontalPodAutoscalerList(in *extensions.HorizontalPodAutoscalerList, out *HorizontalPodAutoscalerList, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*extensions.HorizontalPodAutoscalerList))(in)
|
||||
}
|
||||
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 {
|
||||
out.Items = make([]HorizontalPodAutoscaler, len(in.Items))
|
||||
for i := range in.Items {
|
||||
if err := Convert_extensions_HorizontalPodAutoscaler_To_v1_HorizontalPodAutoscaler(&in.Items[i], &out.Items[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_extensions_HorizontalPodAutoscalerList_To_v1_HorizontalPodAutoscalerList(in *extensions.HorizontalPodAutoscalerList, out *HorizontalPodAutoscalerList, s conversion.Scope) error {
|
||||
return autoConvert_extensions_HorizontalPodAutoscalerList_To_v1_HorizontalPodAutoscalerList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_extensions_HorizontalPodAutoscalerSpec_To_v1_HorizontalPodAutoscalerSpec(in *extensions.HorizontalPodAutoscalerSpec, out *HorizontalPodAutoscalerSpec, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*extensions.HorizontalPodAutoscalerSpec))(in)
|
||||
}
|
||||
// in.ScaleRef has no peer in out
|
||||
if in.MinReplicas != nil {
|
||||
out.MinReplicas = new(int32)
|
||||
*out.MinReplicas = int32(*in.MinReplicas)
|
||||
} else {
|
||||
out.MinReplicas = nil
|
||||
}
|
||||
out.MaxReplicas = int32(in.MaxReplicas)
|
||||
// in.CPUUtilization has no peer in out
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_extensions_HorizontalPodAutoscalerStatus_To_v1_HorizontalPodAutoscalerStatus(in *extensions.HorizontalPodAutoscalerStatus, out *HorizontalPodAutoscalerStatus, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*extensions.HorizontalPodAutoscalerStatus))(in)
|
||||
}
|
||||
if in.ObservedGeneration != nil {
|
||||
out.ObservedGeneration = new(int64)
|
||||
*out.ObservedGeneration = *in.ObservedGeneration
|
||||
} else {
|
||||
out.ObservedGeneration = nil
|
||||
}
|
||||
// unable to generate simple pointer conversion for unversioned.Time -> unversioned.Time
|
||||
if in.LastScaleTime != nil {
|
||||
out.LastScaleTime = new(unversioned.Time)
|
||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(in.LastScaleTime, out.LastScaleTime, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.LastScaleTime = nil
|
||||
}
|
||||
out.CurrentReplicas = int32(in.CurrentReplicas)
|
||||
out.DesiredReplicas = int32(in.DesiredReplicas)
|
||||
if in.CurrentCPUUtilizationPercentage != nil {
|
||||
out.CurrentCPUUtilizationPercentage = new(int32)
|
||||
*out.CurrentCPUUtilizationPercentage = int32(*in.CurrentCPUUtilizationPercentage)
|
||||
} else {
|
||||
out.CurrentCPUUtilizationPercentage = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_extensions_HorizontalPodAutoscalerStatus_To_v1_HorizontalPodAutoscalerStatus(in *extensions.HorizontalPodAutoscalerStatus, out *HorizontalPodAutoscalerStatus, s conversion.Scope) error {
|
||||
return autoConvert_extensions_HorizontalPodAutoscalerStatus_To_v1_HorizontalPodAutoscalerStatus(in, out, s)
|
||||
}
|
||||
|
||||
func init() {
|
||||
err := api.Scheme.AddGeneratedConversionFuncs(
|
||||
autoConvert_api_ObjectMeta_To_v1_ObjectMeta,
|
||||
autoConvert_extensions_HorizontalPodAutoscalerList_To_v1_HorizontalPodAutoscalerList,
|
||||
autoConvert_extensions_HorizontalPodAutoscalerSpec_To_v1_HorizontalPodAutoscalerSpec,
|
||||
autoConvert_extensions_HorizontalPodAutoscalerStatus_To_v1_HorizontalPodAutoscalerStatus,
|
||||
autoConvert_extensions_HorizontalPodAutoscaler_To_v1_HorizontalPodAutoscaler,
|
||||
autoConvert_v1_HorizontalPodAutoscalerList_To_extensions_HorizontalPodAutoscalerList,
|
||||
autoConvert_v1_HorizontalPodAutoscalerSpec_To_extensions_HorizontalPodAutoscalerSpec,
|
||||
autoConvert_v1_HorizontalPodAutoscalerStatus_To_extensions_HorizontalPodAutoscalerStatus,
|
||||
autoConvert_v1_HorizontalPodAutoscaler_To_extensions_HorizontalPodAutoscaler,
|
||||
autoConvert_v1_ObjectMeta_To_api_ObjectMeta,
|
||||
)
|
||||
if err != nil {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
200
pkg/apis/autoscaling/v1/deep_copy_generated.go
Normal file
200
pkg/apis/autoscaling/v1/deep_copy_generated.go
Normal file
@ -0,0 +1,200 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// DO NOT EDIT. THIS FILE IS AUTO-GENERATED BY $KUBEROOT/hack/update-generated-deep-copies.sh.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
conversion "k8s.io/kubernetes/pkg/conversion"
|
||||
)
|
||||
|
||||
func deepCopy_unversioned_ListMeta(in unversioned.ListMeta, out *unversioned.ListMeta, c *conversion.Cloner) error {
|
||||
out.SelfLink = in.SelfLink
|
||||
out.ResourceVersion = in.ResourceVersion
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_unversioned_Time(in unversioned.Time, out *unversioned.Time, c *conversion.Cloner) error {
|
||||
if newVal, err := c.DeepCopy(in.Time); err != nil {
|
||||
return err
|
||||
} else {
|
||||
out.Time = newVal.(time.Time)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_unversioned_TypeMeta(in unversioned.TypeMeta, out *unversioned.TypeMeta, c *conversion.Cloner) error {
|
||||
out.Kind = in.Kind
|
||||
out.APIVersion = in.APIVersion
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_v1_ObjectMeta(in v1.ObjectMeta, out *v1.ObjectMeta, c *conversion.Cloner) error {
|
||||
out.Name = in.Name
|
||||
out.GenerateName = in.GenerateName
|
||||
out.Namespace = in.Namespace
|
||||
out.SelfLink = in.SelfLink
|
||||
out.UID = in.UID
|
||||
out.ResourceVersion = in.ResourceVersion
|
||||
out.Generation = in.Generation
|
||||
if err := deepCopy_unversioned_Time(in.CreationTimestamp, &out.CreationTimestamp, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.DeletionTimestamp != nil {
|
||||
out.DeletionTimestamp = new(unversioned.Time)
|
||||
if err := deepCopy_unversioned_Time(*in.DeletionTimestamp, out.DeletionTimestamp, c); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.DeletionTimestamp = nil
|
||||
}
|
||||
if in.DeletionGracePeriodSeconds != nil {
|
||||
out.DeletionGracePeriodSeconds = new(int64)
|
||||
*out.DeletionGracePeriodSeconds = *in.DeletionGracePeriodSeconds
|
||||
} else {
|
||||
out.DeletionGracePeriodSeconds = nil
|
||||
}
|
||||
if in.Labels != nil {
|
||||
out.Labels = make(map[string]string)
|
||||
for key, val := range in.Labels {
|
||||
out.Labels[key] = val
|
||||
}
|
||||
} else {
|
||||
out.Labels = nil
|
||||
}
|
||||
if in.Annotations != nil {
|
||||
out.Annotations = make(map[string]string)
|
||||
for key, val := range in.Annotations {
|
||||
out.Annotations[key] = val
|
||||
}
|
||||
} else {
|
||||
out.Annotations = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_v1_CrossVersionObjectReference(in CrossVersionObjectReference, out *CrossVersionObjectReference, c *conversion.Cloner) error {
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
out.APIVersion = in.APIVersion
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_v1_HorizontalPodAutoscaler(in HorizontalPodAutoscaler, out *HorizontalPodAutoscaler, c *conversion.Cloner) error {
|
||||
if err := deepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := deepCopy_v1_ObjectMeta(in.ObjectMeta, &out.ObjectMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := deepCopy_v1_HorizontalPodAutoscalerSpec(in.Spec, &out.Spec, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := deepCopy_v1_HorizontalPodAutoscalerStatus(in.Status, &out.Status, c); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_v1_HorizontalPodAutoscalerList(in HorizontalPodAutoscalerList, out *HorizontalPodAutoscalerList, c *conversion.Cloner) error {
|
||||
if err := deepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := deepCopy_unversioned_ListMeta(in.ListMeta, &out.ListMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Items != nil {
|
||||
out.Items = make([]HorizontalPodAutoscaler, len(in.Items))
|
||||
for i := range in.Items {
|
||||
if err := deepCopy_v1_HorizontalPodAutoscaler(in.Items[i], &out.Items[i], c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_v1_HorizontalPodAutoscalerSpec(in HorizontalPodAutoscalerSpec, out *HorizontalPodAutoscalerSpec, c *conversion.Cloner) error {
|
||||
if err := deepCopy_v1_CrossVersionObjectReference(in.ScaleTargetRef, &out.ScaleTargetRef, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.MinReplicas != nil {
|
||||
out.MinReplicas = new(int32)
|
||||
*out.MinReplicas = *in.MinReplicas
|
||||
} else {
|
||||
out.MinReplicas = nil
|
||||
}
|
||||
out.MaxReplicas = in.MaxReplicas
|
||||
if in.TargetCPUUtilizationPercentage != nil {
|
||||
out.TargetCPUUtilizationPercentage = new(int32)
|
||||
*out.TargetCPUUtilizationPercentage = *in.TargetCPUUtilizationPercentage
|
||||
} else {
|
||||
out.TargetCPUUtilizationPercentage = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deepCopy_v1_HorizontalPodAutoscalerStatus(in HorizontalPodAutoscalerStatus, out *HorizontalPodAutoscalerStatus, c *conversion.Cloner) error {
|
||||
if in.ObservedGeneration != nil {
|
||||
out.ObservedGeneration = new(int64)
|
||||
*out.ObservedGeneration = *in.ObservedGeneration
|
||||
} else {
|
||||
out.ObservedGeneration = nil
|
||||
}
|
||||
if in.LastScaleTime != nil {
|
||||
out.LastScaleTime = new(unversioned.Time)
|
||||
if err := deepCopy_unversioned_Time(*in.LastScaleTime, out.LastScaleTime, c); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.LastScaleTime = nil
|
||||
}
|
||||
out.CurrentReplicas = in.CurrentReplicas
|
||||
out.DesiredReplicas = in.DesiredReplicas
|
||||
if in.CurrentCPUUtilizationPercentage != nil {
|
||||
out.CurrentCPUUtilizationPercentage = new(int32)
|
||||
*out.CurrentCPUUtilizationPercentage = *in.CurrentCPUUtilizationPercentage
|
||||
} else {
|
||||
out.CurrentCPUUtilizationPercentage = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
err := api.Scheme.AddGeneratedDeepCopyFuncs(
|
||||
deepCopy_unversioned_ListMeta,
|
||||
deepCopy_unversioned_Time,
|
||||
deepCopy_unversioned_TypeMeta,
|
||||
deepCopy_v1_ObjectMeta,
|
||||
deepCopy_v1_CrossVersionObjectReference,
|
||||
deepCopy_v1_HorizontalPodAutoscaler,
|
||||
deepCopy_v1_HorizontalPodAutoscalerList,
|
||||
deepCopy_v1_HorizontalPodAutoscalerSpec,
|
||||
deepCopy_v1_HorizontalPodAutoscalerStatus,
|
||||
)
|
||||
if err != nil {
|
||||
// if one of the deep copy functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
32
pkg/apis/autoscaling/v1/defaults.go
Normal file
32
pkg/apis/autoscaling/v1/defaults.go
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) {
|
||||
scheme.AddDefaultingFuncs(
|
||||
func(obj *HorizontalPodAutoscaler) {
|
||||
if obj.Spec.MinReplicas == nil {
|
||||
minReplicas := int32(1)
|
||||
obj.Spec.MinReplicas = &minReplicas
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
47
pkg/apis/autoscaling/v1/register.go
Normal file
47
pkg/apis/autoscaling/v1/register.go
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "autoscaling"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: "v1"}
|
||||
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
addKnownTypes(scheme)
|
||||
addDefaultingFuncs(scheme)
|
||||
addConversionFuncs(scheme)
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&HorizontalPodAutoscaler{},
|
||||
&HorizontalPodAutoscalerList{},
|
||||
&v1.ListOptions{},
|
||||
)
|
||||
}
|
||||
|
||||
func (obj *HorizontalPodAutoscaler) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *HorizontalPodAutoscalerList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
1937
pkg/apis/autoscaling/v1/types.generated.go
Normal file
1937
pkg/apis/autoscaling/v1/types.generated.go
Normal file
File diff suppressed because it is too large
Load Diff
88
pkg/apis/autoscaling/v1/types.go
Normal file
88
pkg/apis/autoscaling/v1/types.go
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
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 v1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
// CrossVersionObjectReference contains enough information to let you identify the referred resource.
|
||||
type CrossVersionObjectReference struct {
|
||||
// Kind of the referent; More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds"
|
||||
Kind string `json:"kind"`
|
||||
// Name of the referent; More info: http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names
|
||||
Name string `json:"name"`
|
||||
// API version of the referent
|
||||
APIVersion string `json:"apiVersion,omitempty"`
|
||||
}
|
||||
|
||||
// specification of a horizontal pod autoscaler.
|
||||
type HorizontalPodAutoscalerSpec struct {
|
||||
// reference to scaled resource; horizontal pod autoscaler will learn the current resource consumption
|
||||
// and will set the desired number of pods by using its Scale subresource.
|
||||
ScaleTargetRef CrossVersionObjectReference `json:"scaleTargetRef"`
|
||||
// lower limit for the number of pods that can be set by the autoscaler, default 1.
|
||||
MinReplicas *int32 `json:"minReplicas,omitempty"`
|
||||
// upper limit for the number of pods that can be set by the autoscaler; cannot be smaller than MinReplicas.
|
||||
MaxReplicas int32 `json:"maxReplicas"`
|
||||
// target average CPU utilization (represented as a percentage of requested CPU) over all the pods;
|
||||
TargetCPUUtilizationPercentage *int32 `json:"targetCPUUtilizationPercentage,omitempty"`
|
||||
}
|
||||
|
||||
// current status of a horizontal pod autoscaler
|
||||
type HorizontalPodAutoscalerStatus struct {
|
||||
// most recent generation observed by this autoscaler.
|
||||
ObservedGeneration *int64 `json:"observedGeneration,omitempty"`
|
||||
|
||||
// last time the HorizontalPodAutoscaler scaled the number of pods;
|
||||
// used by the autoscaler to control how often the number of pods is changed.
|
||||
LastScaleTime *unversioned.Time `json:"lastScaleTime,omitempty"`
|
||||
|
||||
// current number of replicas of pods managed by this autoscaler.
|
||||
CurrentReplicas int32 `json:"currentReplicas"`
|
||||
|
||||
// desired number of replicas of pods managed by this autoscaler.
|
||||
DesiredReplicas int32 `json:"desiredReplicas"`
|
||||
|
||||
// current average CPU utilization over all pods, represented as a percentage of requested CPU,
|
||||
// e.g. 70 means that an average pod is using now 70% of its requested CPU.
|
||||
CurrentCPUUtilizationPercentage *int32 `json:"currentCPUUtilizationPercentage,omitempty"`
|
||||
}
|
||||
|
||||
// configuration of a horizontal pod autoscaler.
|
||||
type HorizontalPodAutoscaler struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard object metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
v1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// behaviour of autoscaler. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status.
|
||||
Spec HorizontalPodAutoscalerSpec `json:"spec,omitempty"`
|
||||
|
||||
// current information about the autoscaler.
|
||||
Status HorizontalPodAutoscalerStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// list of horizontal pod autoscaler objects.
|
||||
type HorizontalPodAutoscalerList struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard list metadata.
|
||||
unversioned.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
// list of horizontal pod autoscaler objects.
|
||||
Items []HorizontalPodAutoscaler `json:"items"`
|
||||
}
|
87
pkg/apis/autoscaling/v1/types_swagger_doc_generated.go
Normal file
87
pkg/apis/autoscaling/v1/types_swagger_doc_generated.go
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1
|
||||
|
||||
// This file contains a collection of methods that can be used from go-resful 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_CrossVersionObjectReference = map[string]string{
|
||||
"": "CrossVersionObjectReference contains enough information to let you identify the referred resource.",
|
||||
"kind": "Kind of the referent; More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds\"",
|
||||
"name": "Name of the referent; More info: http://releases.k8s.io/HEAD/docs/user-guide/identifiers.md#names",
|
||||
"apiVersion": "API version of the referent",
|
||||
}
|
||||
|
||||
func (CrossVersionObjectReference) SwaggerDoc() map[string]string {
|
||||
return map_CrossVersionObjectReference
|
||||
}
|
||||
|
||||
var map_HorizontalPodAutoscaler = map[string]string{
|
||||
"": "configuration of a horizontal pod autoscaler.",
|
||||
"metadata": "Standard object metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
|
||||
"spec": "behaviour of autoscaler. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status.",
|
||||
"status": "current information about the autoscaler.",
|
||||
}
|
||||
|
||||
func (HorizontalPodAutoscaler) SwaggerDoc() map[string]string {
|
||||
return map_HorizontalPodAutoscaler
|
||||
}
|
||||
|
||||
var map_HorizontalPodAutoscalerList = map[string]string{
|
||||
"": "list of horizontal pod autoscaler objects.",
|
||||
"metadata": "Standard list metadata.",
|
||||
"items": "list of horizontal pod autoscaler objects.",
|
||||
}
|
||||
|
||||
func (HorizontalPodAutoscalerList) SwaggerDoc() map[string]string {
|
||||
return map_HorizontalPodAutoscalerList
|
||||
}
|
||||
|
||||
var map_HorizontalPodAutoscalerSpec = map[string]string{
|
||||
"": "specification of a horizontal pod autoscaler.",
|
||||
"scaleTargetRef": "reference to scaled resource; horizontal pod autoscaler will learn the current resource consumption and will set the desired number of pods by using its Scale subresource.",
|
||||
"minReplicas": "lower limit for the number of pods that can be set by the autoscaler, default 1.",
|
||||
"maxReplicas": "upper limit for the number of pods that can be set by the autoscaler; cannot be smaller than MinReplicas.",
|
||||
"targetCPUUtilizationPercentage": "target average CPU utilization (represented as a percentage of requested CPU) over all the pods;",
|
||||
}
|
||||
|
||||
func (HorizontalPodAutoscalerSpec) SwaggerDoc() map[string]string {
|
||||
return map_HorizontalPodAutoscalerSpec
|
||||
}
|
||||
|
||||
var map_HorizontalPodAutoscalerStatus = map[string]string{
|
||||
"": "current status of a horizontal pod autoscaler",
|
||||
"observedGeneration": "most recent generation observed by this autoscaler.",
|
||||
"lastScaleTime": "last time the HorizontalPodAutoscaler scaled the number of pods; used by the autoscaler to control how often the number of pods is changed.",
|
||||
"currentReplicas": "current number of replicas of pods managed by this autoscaler.",
|
||||
"desiredReplicas": "desired number of replicas of pods managed by this autoscaler.",
|
||||
"currentCPUUtilizationPercentage": "current average CPU utilization over all pods, represented as a percentage of requested CPU, e.g. 70 means that an average pod is using now 70% of its requested CPU.",
|
||||
}
|
||||
|
||||
func (HorizontalPodAutoscalerStatus) SwaggerDoc() map[string]string {
|
||||
return map_HorizontalPodAutoscalerStatus
|
||||
}
|
||||
|
||||
// AUTO-GENERATED FUNCTIONS END HERE
|
82
pkg/client/unversioned/autoscaling.go
Normal file
82
pkg/client/unversioned/autoscaling.go
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package unversioned
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
)
|
||||
|
||||
type AutoscalingInterface interface {
|
||||
HorizontalPodAutoscalersNamespacer
|
||||
}
|
||||
|
||||
// AutoscalingClient is used to interact with Kubernetes autoscaling features.
|
||||
type AutoscalingClient struct {
|
||||
*RESTClient
|
||||
}
|
||||
|
||||
func (c *AutoscalingClient) HorizontalPodAutoscalers(namespace string) HorizontalPodAutoscalerInterface {
|
||||
return newHorizontalPodAutoscalersV1(c, namespace)
|
||||
}
|
||||
|
||||
func NewAutoscaling(c *Config) (*AutoscalingClient, error) {
|
||||
config := *c
|
||||
if err := setAutoscalingDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &AutoscalingClient{client}, nil
|
||||
}
|
||||
|
||||
func NewAutoscalingOrDie(c *Config) *AutoscalingClient {
|
||||
client, err := NewAutoscaling(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func setAutoscalingDefaults(config *Config) error {
|
||||
// if autoscaling group is not registered, return an error
|
||||
g, err := registered.Group(autoscaling.GroupName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
config.APIPath = defaultAPIPath
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = DefaultKubernetesUserAgent()
|
||||
}
|
||||
// TODO: Unconditionally set the config.Version, until we fix the config.
|
||||
//if config.Version == "" {
|
||||
copyGroupVersion := g.GroupVersion
|
||||
config.GroupVersion = ©GroupVersion
|
||||
//}
|
||||
|
||||
config.Codec = api.Codecs.LegacyCodec(*config.GroupVersion)
|
||||
if config.QPS == 0 {
|
||||
config.QPS = 5
|
||||
}
|
||||
if config.Burst == 0 {
|
||||
config.Burst = 10
|
||||
}
|
||||
return nil
|
||||
}
|
@ -41,6 +41,7 @@ type Interface interface {
|
||||
PersistentVolumeClaimsNamespacer
|
||||
ComponentStatusesInterface
|
||||
ConfigMapsNamespacer
|
||||
Autoscaling() AutoscalingInterface
|
||||
Extensions() ExtensionsInterface
|
||||
Discovery() DiscoveryInterface
|
||||
}
|
||||
@ -111,6 +112,7 @@ func (c *Client) ConfigMaps(namespace string) ConfigMapsInterface {
|
||||
// Client is the implementation of a Kubernetes client.
|
||||
type Client struct {
|
||||
*RESTClient
|
||||
*AutoscalingClient
|
||||
*ExtensionsClient
|
||||
*DiscoveryClient
|
||||
}
|
||||
@ -146,6 +148,10 @@ func IsTimeout(err error) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Client) Autoscaling() AutoscalingInterface {
|
||||
return c.AutoscalingClient
|
||||
}
|
||||
|
||||
func (c *Client) Extensions() ExtensionsInterface {
|
||||
return c.ExtensionsClient
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util"
|
||||
@ -155,16 +156,25 @@ func New(c *Config) (*Client, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := registered.Group(extensions.GroupName); err != nil {
|
||||
return &Client{RESTClient: client, ExtensionsClient: nil, DiscoveryClient: discoveryClient}, nil
|
||||
}
|
||||
experimentalConfig := *c
|
||||
experimentalClient, err := NewExtensions(&experimentalConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var autoscalingClient *AutoscalingClient
|
||||
if registered.IsRegistered(autoscaling.GroupName) {
|
||||
autoscalingConfig := *c
|
||||
autoscalingClient, err = NewAutoscaling(&autoscalingConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &Client{RESTClient: client, ExtensionsClient: experimentalClient, DiscoveryClient: discoveryClient}, nil
|
||||
var extensionsClient *ExtensionsClient
|
||||
if registered.IsRegistered(extensions.GroupName) {
|
||||
extensionsConfig := *c
|
||||
extensionsClient, err = NewExtensions(&extensionsConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &Client{RESTClient: client, AutoscalingClient: autoscalingClient, ExtensionsClient: extensionsClient, DiscoveryClient: discoveryClient}, nil
|
||||
}
|
||||
|
||||
// MatchesServerVersion queries the server to compares the build version
|
||||
|
@ -101,3 +101,68 @@ func (c *horizontalPodAutoscalers) Watch(opts api.ListOptions) (watch.Interface,
|
||||
VersionedParams(&opts, api.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// horizontalPodAutoscalersV1 implements HorizontalPodAutoscalersNamespacer interface using AutoscalingClient internally
|
||||
// TODO(piosz): get back to one client implementation once HPA will be graduated to GA completely
|
||||
type horizontalPodAutoscalersV1 struct {
|
||||
client *AutoscalingClient
|
||||
ns string
|
||||
}
|
||||
|
||||
// newHorizontalPodAutoscalers returns a horizontalPodAutoscalers
|
||||
func newHorizontalPodAutoscalersV1(c *AutoscalingClient, namespace string) *horizontalPodAutoscalersV1 {
|
||||
return &horizontalPodAutoscalersV1{
|
||||
client: c,
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of horizontalPodAutoscalers that match those selectors.
|
||||
func (c *horizontalPodAutoscalersV1) List(opts api.ListOptions) (result *extensions.HorizontalPodAutoscalerList, err error) {
|
||||
result = &extensions.HorizontalPodAutoscalerList{}
|
||||
err = c.client.Get().Namespace(c.ns).Resource("horizontalPodAutoscalers").VersionedParams(&opts, api.ParameterCodec).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Get takes the name of the horizontalPodAutoscaler, and returns the corresponding HorizontalPodAutoscaler object, and an error if it occurs
|
||||
func (c *horizontalPodAutoscalersV1) Get(name string) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
err = c.client.Get().Namespace(c.ns).Resource("horizontalPodAutoscalers").Name(name).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes the name of the horizontalPodAutoscaler and deletes it. Returns an error if one occurs.
|
||||
func (c *horizontalPodAutoscalersV1) Delete(name string, options *api.DeleteOptions) error {
|
||||
return c.client.Delete().Namespace(c.ns).Resource("horizontalPodAutoscalers").Name(name).Body(options).Do().Error()
|
||||
}
|
||||
|
||||
// Create takes the representation of a horizontalPodAutoscaler and creates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if it occurs.
|
||||
func (c *horizontalPodAutoscalersV1) Create(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
err = c.client.Post().Namespace(c.ns).Resource("horizontalPodAutoscalers").Body(horizontalPodAutoscaler).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a horizontalPodAutoscaler and updates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if it occurs.
|
||||
func (c *horizontalPodAutoscalersV1) Update(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
err = c.client.Put().Namespace(c.ns).Resource("horizontalPodAutoscalers").Name(horizontalPodAutoscaler.Name).Body(horizontalPodAutoscaler).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus takes the representation of a horizontalPodAutoscaler and updates it. Returns the server's representation of the horizontalPodAutoscaler, and an error, if it occurs.
|
||||
func (c *horizontalPodAutoscalersV1) UpdateStatus(horizontalPodAutoscaler *extensions.HorizontalPodAutoscaler) (result *extensions.HorizontalPodAutoscaler, err error) {
|
||||
result = &extensions.HorizontalPodAutoscaler{}
|
||||
err = c.client.Put().Namespace(c.ns).Resource("horizontalPodAutoscalers").Name(horizontalPodAutoscaler.Name).SubResource("status").Body(horizontalPodAutoscaler).Do().Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested horizontalPodAutoscalers.
|
||||
func (c *horizontalPodAutoscalersV1) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||
return c.client.Get().
|
||||
Prefix("watch").
|
||||
Namespace(c.ns).
|
||||
Resource("horizontalPodAutoscalers").
|
||||
VersionedParams(&opts, api.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
)
|
||||
|
||||
@ -34,7 +35,19 @@ func getHorizontalPodAutoscalersResoureName() string {
|
||||
return "horizontalpodautoscalers"
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerCreate(t *testing.T) {
|
||||
func getClient(t *testing.T, c *simple.Client, ns, resourceGroup string) HorizontalPodAutoscalerInterface {
|
||||
switch resourceGroup {
|
||||
case autoscaling.GroupName:
|
||||
return c.Setup(t).Autoscaling().HorizontalPodAutoscalers(ns)
|
||||
case extensions.GroupName:
|
||||
return c.Setup(t).Extensions().HorizontalPodAutoscalers(ns)
|
||||
default:
|
||||
t.Fatalf("Unknown group %v", resourceGroup)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerCreate(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
horizontalPodAutoscaler := extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
@ -45,14 +58,15 @@ func TestHorizontalPodAutoscalerCreate(t *testing.T) {
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "POST",
|
||||
Path: testapi.Extensions.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, ""),
|
||||
Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, ""),
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
Body: &horizontalPodAutoscaler,
|
||||
},
|
||||
Response: simple.Response{StatusCode: 200, Body: &horizontalPodAutoscaler},
|
||||
Response: simple.Response{StatusCode: 200, Body: &horizontalPodAutoscaler},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
|
||||
response, err := c.Setup(t).Extensions().HorizontalPodAutoscalers(ns).Create(&horizontalPodAutoscaler)
|
||||
response, err := getClient(t, c, ns, resourceGroup).Create(&horizontalPodAutoscaler)
|
||||
defer c.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@ -60,7 +74,12 @@ func TestHorizontalPodAutoscalerCreate(t *testing.T) {
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerGet(t *testing.T) {
|
||||
func TestHorizontalPodAutoscalerCreate(t *testing.T) {
|
||||
testHorizontalPodAutoscalerCreate(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerCreate(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerGet(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
horizontalPodAutoscaler := &extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
@ -71,19 +90,25 @@ func TestHorizontalPodAutoscalerGet(t *testing.T) {
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "GET",
|
||||
Path: testapi.Extensions.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc"),
|
||||
Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc"),
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
Body: nil,
|
||||
},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
|
||||
response, err := c.Setup(t).Extensions().HorizontalPodAutoscalers(ns).Get("abc")
|
||||
response, err := getClient(t, c, ns, resourceGroup).Get("abc")
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerList(t *testing.T) {
|
||||
func TestHorizontalPodAutoscalerGet(t *testing.T) {
|
||||
testHorizontalPodAutoscalerGet(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerGet(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerList(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
horizontalPodAutoscalerList := &extensions.HorizontalPodAutoscalerList{
|
||||
Items: []extensions.HorizontalPodAutoscaler{
|
||||
@ -98,18 +123,48 @@ func TestHorizontalPodAutoscalerList(t *testing.T) {
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "GET",
|
||||
Path: testapi.Extensions.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, ""),
|
||||
Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, ""),
|
||||
Query: simple.BuildQueryValues(nil),
|
||||
Body: nil,
|
||||
},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscalerList},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscalerList},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
response, err := c.Setup(t).Extensions().HorizontalPodAutoscalers(ns).List(api.ListOptions{})
|
||||
response, err := getClient(t, c, ns, resourceGroup).List(api.ListOptions{})
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerList(t *testing.T) {
|
||||
testHorizontalPodAutoscalerList(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerList(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerUpdate(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
horizontalPodAutoscaler := &extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "abc",
|
||||
Namespace: ns,
|
||||
ResourceVersion: "1",
|
||||
},
|
||||
}
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "PUT", Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc"), Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
response, err := getClient(t, c, ns, resourceGroup).Update(horizontalPodAutoscaler)
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerUpdate(t *testing.T) {
|
||||
testHorizontalPodAutoscalerUpdate(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerUpdate(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerUpdateStatus(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
horizontalPodAutoscaler := &extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
@ -119,52 +174,52 @@ func TestHorizontalPodAutoscalerUpdate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "PUT", Path: testapi.Extensions.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc"), Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
Request: simple.Request{Method: "PUT", Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc") + "/status", Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
response, err := c.Setup(t).Extensions().HorizontalPodAutoscalers(ns).Update(horizontalPodAutoscaler)
|
||||
response, err := getClient(t, c, ns, resourceGroup).UpdateStatus(horizontalPodAutoscaler)
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerUpdateStatus(t *testing.T) {
|
||||
testHorizontalPodAutoscalerUpdateStatus(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerUpdateStatus(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerDelete(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
ns := api.NamespaceDefault
|
||||
horizontalPodAutoscaler := &extensions.HorizontalPodAutoscaler{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "abc",
|
||||
Namespace: ns,
|
||||
ResourceVersion: "1",
|
||||
},
|
||||
}
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "PUT", Path: testapi.Extensions.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "abc") + "/status", Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200, Body: horizontalPodAutoscaler},
|
||||
Request: simple.Request{Method: "DELETE", Path: group.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "foo"), Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
response, err := c.Setup(t).Extensions().HorizontalPodAutoscalers(ns).UpdateStatus(horizontalPodAutoscaler)
|
||||
err := getClient(t, c, ns, resourceGroup).Delete("foo", nil)
|
||||
defer c.Close()
|
||||
c.Validate(t, response, err)
|
||||
c.Validate(t, nil, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerDelete(t *testing.T) {
|
||||
ns := api.NamespaceDefault
|
||||
testHorizontalPodAutoscalerDelete(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerDelete(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
||||
func testHorizontalPodAutoscalerWatch(t *testing.T, group testapi.TestGroup, resourceGroup string) {
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{Method: "DELETE", Path: testapi.Extensions.ResourcePath(getHorizontalPodAutoscalersResoureName(), ns, "foo"), Query: simple.BuildQueryValues(nil)},
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
Request: simple.Request{
|
||||
Method: "GET",
|
||||
Path: group.ResourcePathWithPrefix("watch", getHorizontalPodAutoscalersResoureName(), "", ""),
|
||||
Query: url.Values{"resourceVersion": []string{}}},
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
ResourceGroup: resourceGroup,
|
||||
}
|
||||
err := c.Setup(t).Extensions().HorizontalPodAutoscalers(ns).Delete("foo", nil)
|
||||
_, err := getClient(t, c, api.NamespaceAll, resourceGroup).Watch(api.ListOptions{})
|
||||
defer c.Close()
|
||||
c.Validate(t, nil, err)
|
||||
}
|
||||
|
||||
func TestHorizontalPodAutoscalerWatch(t *testing.T) {
|
||||
c := &simple.Client{
|
||||
Request: simple.Request{
|
||||
Method: "GET",
|
||||
Path: testapi.Extensions.ResourcePathWithPrefix("watch", getHorizontalPodAutoscalersResoureName(), "", ""),
|
||||
Query: url.Values{"resourceVersion": []string{}}},
|
||||
Response: simple.Response{StatusCode: 200},
|
||||
}
|
||||
_, err := c.Setup(t).Extensions().HorizontalPodAutoscalers(api.NamespaceAll).Watch(api.ListOptions{})
|
||||
defer c.Close()
|
||||
c.Validate(t, nil, err)
|
||||
testHorizontalPodAutoscalerWatch(t, testapi.Extensions, extensions.GroupName)
|
||||
testHorizontalPodAutoscalerWatch(t, testapi.Autoscaling, autoscaling.GroupName)
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
_ "k8s.io/kubernetes/pkg/apis/authorization/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/metrics/install"
|
||||
|
@ -91,3 +91,74 @@ func (c *FakeHorizontalPodAutoscalers) Delete(name string, options *api.DeleteOp
|
||||
func (c *FakeHorizontalPodAutoscalers) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.InvokesWatch(NewWatchAction("horizontalpodautoscalers", c.Namespace, opts))
|
||||
}
|
||||
|
||||
// FakeHorizontalPodAutoscalers implements HorizontalPodAutoscalerInterface. Meant to be embedded into a struct to get a default
|
||||
// implementation. This makes faking out just the methods you want to test easier.
|
||||
// This is a test implementation of HorizontalPodAutoscalersV1
|
||||
// TODO(piosz): get back to one client implementation once HPA will be graduated to GA completely
|
||||
type FakeHorizontalPodAutoscalersV1 struct {
|
||||
Fake *FakeAutoscaling
|
||||
Namespace string
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) Get(name string) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewGetAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) List(opts api.ListOptions) (*extensions.HorizontalPodAutoscalerList, error) {
|
||||
obj, err := c.Fake.Invokes(NewListAction("horizontalpodautoscalers", c.Namespace, opts), &extensions.HorizontalPodAutoscalerList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
label := opts.LabelSelector
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &extensions.HorizontalPodAutoscalerList{}
|
||||
for _, a := range obj.(*extensions.HorizontalPodAutoscalerList).Items {
|
||||
if label.Matches(labels.Set(a.Labels)) {
|
||||
list.Items = append(list.Items, a)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) Create(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewCreateAction("horizontalpodautoscalers", c.Namespace, a), a)
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) Update(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewUpdateAction("horizontalpodautoscalers", c.Namespace, a), a)
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) UpdateStatus(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) {
|
||||
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("horizontalpodautoscalers", "status", c.Namespace, a), &extensions.HorizontalPodAutoscaler{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*extensions.HorizontalPodAutoscaler), err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) Delete(name string, options *api.DeleteOptions) error {
|
||||
_, err := c.Fake.Invokes(NewDeleteAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *FakeHorizontalPodAutoscalersV1) Watch(opts api.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.InvokesWatch(NewWatchAction("horizontalpodautoscalers", c.Namespace, opts))
|
||||
}
|
||||
|
@ -66,13 +66,17 @@ type Client struct {
|
||||
// Maps from query arg key to validator.
|
||||
// If no validator is present, string equality is used.
|
||||
QueryValidator map[string]func(string, string) bool
|
||||
|
||||
// If your object could exist in multiple groups, set this to
|
||||
// correspond to the URL you're testing it with.
|
||||
ResourceGroup string
|
||||
}
|
||||
|
||||
func (c *Client) Setup(t *testing.T) *Client {
|
||||
c.handler = &utiltesting.FakeHandler{
|
||||
StatusCode: c.Response.StatusCode,
|
||||
}
|
||||
if responseBody := body(t, c.Response.Body, c.Response.RawBody); responseBody != nil {
|
||||
if responseBody := c.body(t, c.Response.Body, c.Response.RawBody); responseBody != nil {
|
||||
c.handler.ResponseBody = *responseBody
|
||||
}
|
||||
c.server = httptest.NewServer(c.handler)
|
||||
@ -84,6 +88,10 @@ func (c *Client) Setup(t *testing.T) *Client {
|
||||
|
||||
// TODO: caesarxuchao: hacky way to specify version of Experimental client.
|
||||
// We will fix this by supporting multiple group versions in Config
|
||||
c.AutoscalingClient = client.NewAutoscalingOrDie(&client.Config{
|
||||
Host: c.server.URL,
|
||||
ContentConfig: client.ContentConfig{GroupVersion: testapi.Autoscaling.GroupVersion()},
|
||||
})
|
||||
c.ExtensionsClient = client.NewExtensionsOrDie(&client.Config{
|
||||
Host: c.server.URL,
|
||||
ContentConfig: client.ContentConfig{GroupVersion: testapi.Extensions.GroupVersion()},
|
||||
@ -138,7 +146,7 @@ func (c *Client) ValidateCommon(t *testing.T, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
requestBody := body(t, c.Request.Body, c.Request.RawBody)
|
||||
requestBody := c.body(t, c.Request.Body, c.Request.RawBody)
|
||||
actualQuery := c.handler.RequestReceived.URL.Query()
|
||||
t.Logf("got query: %v", actualQuery)
|
||||
t.Logf("path: %v", c.Request.Path)
|
||||
@ -206,16 +214,20 @@ func validateFields(a, b string) bool {
|
||||
return sA.String() == sB.String()
|
||||
}
|
||||
|
||||
func body(t *testing.T, obj runtime.Object, raw *string) *string {
|
||||
func (c *Client) body(t *testing.T, obj runtime.Object, raw *string) *string {
|
||||
if obj != nil {
|
||||
fqKind, err := api.Scheme.ObjectKind(obj)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected encoding error: %v", err)
|
||||
}
|
||||
groupName := fqKind.GroupVersion().Group
|
||||
if c.ResourceGroup != "" {
|
||||
groupName = c.ResourceGroup
|
||||
}
|
||||
var bs []byte
|
||||
g, found := testapi.Groups[fqKind.GroupVersion().Group]
|
||||
g, found := testapi.Groups[groupName]
|
||||
if !found {
|
||||
t.Errorf("Group %s is not registered in testapi", fqKind.GroupVersion().Group)
|
||||
t.Errorf("Group %s is not registered in testapi", groupName)
|
||||
}
|
||||
bs, err = runtime.Encode(g.Codec(), obj)
|
||||
if err != nil {
|
||||
|
@ -274,6 +274,10 @@ func (c *Fake) Namespaces() client.NamespaceInterface {
|
||||
return &FakeNamespaces{Fake: c}
|
||||
}
|
||||
|
||||
func (c *Fake) Autoscaling() client.AutoscalingInterface {
|
||||
return &FakeAutoscaling{c}
|
||||
}
|
||||
|
||||
func (c *Fake) Extensions() client.ExtensionsInterface {
|
||||
return &FakeExperimental{c}
|
||||
}
|
||||
@ -304,6 +308,19 @@ func (c *Fake) SwaggerSchema(version unversioned.GroupVersion) (*swagger.ApiDecl
|
||||
return &swagger.ApiDeclaration{}, nil
|
||||
}
|
||||
|
||||
// NewSimpleFakeAutoscaling returns a client that will respond with the provided objects
|
||||
func NewSimpleFakeAutoscaling(objects ...runtime.Object) *FakeAutoscaling {
|
||||
return &FakeAutoscaling{Fake: NewSimpleFake(objects...)}
|
||||
}
|
||||
|
||||
type FakeAutoscaling struct {
|
||||
*Fake
|
||||
}
|
||||
|
||||
func (c *FakeAutoscaling) HorizontalPodAutoscalers(namespace string) client.HorizontalPodAutoscalerInterface {
|
||||
return &FakeHorizontalPodAutoscalersV1{Fake: c, Namespace: namespace}
|
||||
}
|
||||
|
||||
// NewSimpleFakeExp returns a client that will respond with the provided objects
|
||||
func NewSimpleFakeExp(objects ...runtime.Object) *FakeExperimental {
|
||||
return &FakeExperimental{Fake: NewSimpleFake(objects...)}
|
||||
|
@ -77,7 +77,9 @@ func NewStorageDestinations() StorageDestinations {
|
||||
}
|
||||
}
|
||||
|
||||
// AddAPIGroup replaces 'group' if it's already registered.
|
||||
func (s *StorageDestinations) AddAPIGroup(group string, defaultStorage storage.Interface) {
|
||||
glog.Infof("Adding storage destination for group %v", group)
|
||||
s.APIGroups[group] = &StorageDestinationsForAPIGroup{
|
||||
Default: defaultStorage,
|
||||
Overrides: map[string]storage.Interface{},
|
||||
@ -94,10 +96,16 @@ func (s *StorageDestinations) AddStorageOverride(group, resource string, overrid
|
||||
s.APIGroups[group].Overrides[resource] = override
|
||||
}
|
||||
|
||||
// Get finds the storage destination for the given group and resource. It will
|
||||
// Fatalf if the group has no storage destination configured.
|
||||
func (s *StorageDestinations) Get(group, resource string) storage.Interface {
|
||||
apigroup, ok := s.APIGroups[group]
|
||||
if !ok {
|
||||
glog.Errorf("No storage defined for API group: '%s'", apigroup)
|
||||
// TODO: return an error like a normal function. For now,
|
||||
// Fatalf is better than just logging an error, because this
|
||||
// condition guarantees future problems and this is a less
|
||||
// mysterious failure point.
|
||||
glog.Fatalf("No storage defined for API group: '%s'. Defined groups: %#v", group, s.APIGroups)
|
||||
return nil
|
||||
}
|
||||
if apigroup.Overrides != nil {
|
||||
@ -108,6 +116,30 @@ func (s *StorageDestinations) Get(group, resource string) storage.Interface {
|
||||
return apigroup.Default
|
||||
}
|
||||
|
||||
// Search is like Get, but can be used to search a list of groups. It tries the
|
||||
// groups in order (and Fatalf's if none of them exist). The intention is for
|
||||
// this to be used for resources that move between groups.
|
||||
func (s *StorageDestinations) Search(groups []string, resource string) storage.Interface {
|
||||
for _, group := range groups {
|
||||
apigroup, ok := s.APIGroups[group]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if apigroup.Overrides != nil {
|
||||
if client, exists := apigroup.Overrides[resource]; exists {
|
||||
return client
|
||||
}
|
||||
}
|
||||
return apigroup.Default
|
||||
}
|
||||
// TODO: return an error like a normal function. For now,
|
||||
// Fatalf is better than just logging an error, because this
|
||||
// condition guarantees future problems and this is a less
|
||||
// mysterious failure point.
|
||||
glog.Fatalf("No storage defined for any of the groups: %v. Defined groups: %#v", groups, s.APIGroups)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get all backends for all registered storage destinations.
|
||||
// Used for getting all instances for health validations.
|
||||
func (s *StorageDestinations) Backends() []string {
|
||||
|
@ -39,6 +39,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
@ -217,6 +218,8 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
||||
switch mapping.GroupVersionKind.Group {
|
||||
case api.GroupName:
|
||||
return client.RESTClient, nil
|
||||
case autoscaling.GroupName:
|
||||
return client.AutoscalingClient.RESTClient, nil
|
||||
case extensions.GroupName:
|
||||
return client.ExtensionsClient.RESTClient, nil
|
||||
}
|
||||
@ -700,6 +703,12 @@ func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
|
||||
if ok := registered.IsEnabledVersion(gvk.GroupVersion()); !ok {
|
||||
return fmt.Errorf("API version %q isn't supported, only supports API versions %q", gvk.GroupVersion().String(), registered.EnabledVersions())
|
||||
}
|
||||
if gvk.Group == autoscaling.GroupName {
|
||||
if c.c.AutoscalingClient == nil {
|
||||
return errors.New("unable to validate: no autoscaling client")
|
||||
}
|
||||
return getSchemaAndValidate(c.c.AutoscalingClient.RESTClient, data, "apis/", gvk.GroupVersion().String(), c.cacheDir)
|
||||
}
|
||||
if gvk.Group == extensions.GroupName {
|
||||
if c.c.ExtensionsClient == nil {
|
||||
return errors.New("unable to validate: no experimental client")
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
_ "k8s.io/kubernetes/pkg/apis/authorization/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/componentconfig/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/extensions/install"
|
||||
)
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/api/rest"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apiserver"
|
||||
apiservermetrics "k8s.io/kubernetes/pkg/apiserver/metrics"
|
||||
@ -209,6 +210,7 @@ func (m *Master) InstallAPIs(c *Config) {
|
||||
|
||||
// allGroups records all supported groups at /apis
|
||||
allGroups := []unversioned.APIGroup{}
|
||||
|
||||
// Install extensions unless disabled.
|
||||
if !m.ApiGroupVersionOverrides["extensions/v1beta1"].Disable {
|
||||
m.thirdPartyStorage = c.StorageDestinations.APIGroups[extensions.GroupName].Default
|
||||
@ -250,6 +252,39 @@ func (m *Master) InstallAPIs(c *Config) {
|
||||
}
|
||||
allGroups = append(allGroups, group)
|
||||
}
|
||||
|
||||
// Install autoscaling unless disabled.
|
||||
if !m.ApiGroupVersionOverrides["autoscaling/v1"].Disable {
|
||||
autoscalingResources := m.getAutoscalingResources(c)
|
||||
autoscalingGroupMeta := registered.GroupOrDie(autoscaling.GroupName)
|
||||
|
||||
// Hard code preferred group version to autoscaling/v1
|
||||
autoscalingGroupMeta.GroupVersion = unversioned.GroupVersion{Group: "autoscaling", Version: "v1"}
|
||||
|
||||
apiGroupInfo := genericapiserver.APIGroupInfo{
|
||||
GroupMeta: *autoscalingGroupMeta,
|
||||
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
|
||||
"v1": autoscalingResources,
|
||||
},
|
||||
OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion,
|
||||
Scheme: api.Scheme,
|
||||
ParameterCodec: api.ParameterCodec,
|
||||
NegotiatedSerializer: api.Codecs,
|
||||
}
|
||||
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
|
||||
|
||||
autoscalingGVForDiscovery := unversioned.GroupVersionForDiscovery{
|
||||
GroupVersion: autoscalingGroupMeta.GroupVersion.String(),
|
||||
Version: autoscalingGroupMeta.GroupVersion.Version,
|
||||
}
|
||||
group := unversioned.APIGroup{
|
||||
Name: autoscalingGroupMeta.GroupVersion.Group,
|
||||
Versions: []unversioned.GroupVersionForDiscovery{autoscalingGVForDiscovery},
|
||||
PreferredVersion: autoscalingGVForDiscovery,
|
||||
}
|
||||
allGroups = append(allGroups, group)
|
||||
}
|
||||
|
||||
if err := m.InstallAPIGroups(apiGroupsInfo); err != nil {
|
||||
glog.Fatalf("Error in registering group versions: %v", err)
|
||||
}
|
||||
@ -587,9 +622,7 @@ func (m *Master) getExtensionResources(c *Config) map[string]rest.Storage {
|
||||
|
||||
storage := map[string]rest.Storage{}
|
||||
if isEnabled("horizontalpodautoscalers") {
|
||||
autoscalerStorage, autoscalerStatusStorage := horizontalpodautoscaleretcd.NewREST(dbClient("horizontalpodautoscalers"), storageDecorator)
|
||||
storage["horizontalpodautoscalers"] = autoscalerStorage
|
||||
storage["horizontalpodautoscalers/status"] = autoscalerStatusStorage
|
||||
m.constructHPAResources(c, storage)
|
||||
controllerStorage := expcontrolleretcd.NewStorage(c.StorageDestinations.Get("", "replicationControllers"), storageDecorator)
|
||||
storage["replicationcontrollers"] = controllerStorage.ReplicationController
|
||||
storage["replicationcontrollers/scale"] = controllerStorage.Scale
|
||||
@ -647,6 +680,40 @@ func (m *Master) getExtensionResources(c *Config) map[string]rest.Storage {
|
||||
return storage
|
||||
}
|
||||
|
||||
// constructHPAResources makes HPA resources and adds them to the storage map.
|
||||
// They're installed in both autoscaling and extensions. It's assumed that
|
||||
// you've already done the check that they should be on.
|
||||
func (m *Master) constructHPAResources(c *Config, restStorage map[string]rest.Storage) {
|
||||
// Note that hpa's storage settings are changed by changing the autoscaling
|
||||
// group. Clearly we want all hpas to be stored in the same place no
|
||||
// matter where they're accessed from.
|
||||
storageDecorator := m.StorageDecorator()
|
||||
dbClient := func(resource string) storage.Interface {
|
||||
return c.StorageDestinations.Search([]string{autoscaling.GroupName, extensions.GroupName}, resource)
|
||||
}
|
||||
autoscalerStorage, autoscalerStatusStorage := horizontalpodautoscaleretcd.NewREST(dbClient("horizontalpodautoscalers"), storageDecorator)
|
||||
restStorage["horizontalpodautoscalers"] = autoscalerStorage
|
||||
restStorage["horizontalpodautoscalers/status"] = autoscalerStatusStorage
|
||||
}
|
||||
|
||||
// getAutoscalingResources returns the resources for autoscaling api
|
||||
func (m *Master) getAutoscalingResources(c *Config) map[string]rest.Storage {
|
||||
resourceOverrides := m.ApiGroupVersionOverrides["autoscaling/v1"].ResourceOverrides
|
||||
isEnabled := func(resource string) bool {
|
||||
// Check if the resource has been overriden.
|
||||
if enabled, ok := resourceOverrides[resource]; ok {
|
||||
return enabled
|
||||
}
|
||||
return !m.ApiGroupVersionOverrides["autoscaling/v1"].Disable
|
||||
}
|
||||
|
||||
storage := map[string]rest.Storage{}
|
||||
if isEnabled("horizontalpodautoscalers") {
|
||||
m.constructHPAResources(c, storage)
|
||||
}
|
||||
return storage
|
||||
}
|
||||
|
||||
// findExternalAddress returns ExternalIP of provided node with fallback to LegacyHostIP.
|
||||
func findExternalAddress(node *api.Node) (string, error) {
|
||||
var fallback string
|
||||
|
@ -35,6 +35,7 @@ import (
|
||||
apiutil "k8s.io/kubernetes/pkg/api/util"
|
||||
utilnet "k8s.io/kubernetes/pkg/util/net"
|
||||
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||
"k8s.io/kubernetes/pkg/kubelet/client"
|
||||
@ -66,11 +67,14 @@ func setUp(t *testing.T) (Master, *etcdtesting.EtcdTestServer, Config, *assert.A
|
||||
storageDestinations := genericapiserver.NewStorageDestinations()
|
||||
storageDestinations.AddAPIGroup(
|
||||
api.GroupName, etcdstorage.NewEtcdStorage(server.Client, testapi.Default.Codec(), etcdtest.PathPrefix(), false))
|
||||
storageDestinations.AddAPIGroup(
|
||||
autoscaling.GroupName, etcdstorage.NewEtcdStorage(server.Client, testapi.Autoscaling.Codec(), etcdtest.PathPrefix(), false))
|
||||
storageDestinations.AddAPIGroup(
|
||||
extensions.GroupName, etcdstorage.NewEtcdStorage(server.Client, testapi.Extensions.Codec(), etcdtest.PathPrefix(), false))
|
||||
|
||||
config.StorageDestinations = storageDestinations
|
||||
storageVersions[api.GroupName] = testapi.Default.GroupVersion().String()
|
||||
storageVersions[autoscaling.GroupName] = testapi.Autoscaling.GroupVersion().String()
|
||||
storageVersions[extensions.GroupName] = testapi.Extensions.GroupVersion().String()
|
||||
config.StorageVersions = storageVersions
|
||||
config.PublicAddress = net.ParseIP("192.168.10.4")
|
||||
@ -274,20 +278,40 @@ func TestDiscoveryAtAPIS(t *testing.T) {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
extensionsGroupName := extensions.GroupName
|
||||
extensionsVersions := []unversioned.GroupVersionForDiscovery{
|
||||
expectGroupNames := []string{autoscaling.GroupName, extensions.GroupName}
|
||||
expectVersions := [][]unversioned.GroupVersionForDiscovery{
|
||||
{
|
||||
GroupVersion: testapi.Extensions.GroupVersion().String(),
|
||||
Version: testapi.Extensions.GroupVersion().Version,
|
||||
{
|
||||
GroupVersion: testapi.Autoscaling.GroupVersion().String(),
|
||||
Version: testapi.Autoscaling.GroupVersion().Version,
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
GroupVersion: testapi.Extensions.GroupVersion().String(),
|
||||
Version: testapi.Extensions.GroupVersion().Version,
|
||||
},
|
||||
},
|
||||
}
|
||||
extensionsPreferredVersion := unversioned.GroupVersionForDiscovery{
|
||||
GroupVersion: config.StorageVersions[extensions.GroupName],
|
||||
Version: apiutil.GetVersion(config.StorageVersions[extensions.GroupName]),
|
||||
expectPreferredVersion := []unversioned.GroupVersionForDiscovery{
|
||||
{
|
||||
GroupVersion: config.StorageVersions[autoscaling.GroupName],
|
||||
Version: apiutil.GetVersion(config.StorageVersions[autoscaling.GroupName]),
|
||||
},
|
||||
{
|
||||
GroupVersion: config.StorageVersions[extensions.GroupName],
|
||||
Version: apiutil.GetVersion(config.StorageVersions[extensions.GroupName]),
|
||||
},
|
||||
}
|
||||
assert.Equal(extensionsGroupName, groupList.Groups[0].Name)
|
||||
assert.Equal(extensionsVersions, groupList.Groups[0].Versions)
|
||||
assert.Equal(extensionsPreferredVersion, groupList.Groups[0].PreferredVersion)
|
||||
|
||||
assert.Equal(expectGroupNames[0], groupList.Groups[0].Name)
|
||||
assert.Equal(expectGroupNames[1], groupList.Groups[1].Name)
|
||||
|
||||
assert.Equal(expectVersions[0], groupList.Groups[0].Versions)
|
||||
assert.Equal(expectVersions[1], groupList.Groups[1].Versions)
|
||||
|
||||
assert.Equal(expectPreferredVersion[0], groupList.Groups[0].PreferredVersion)
|
||||
assert.Equal(expectPreferredVersion[1], groupList.Groups[1].PreferredVersion)
|
||||
|
||||
thirdPartyGV := unversioned.GroupVersionForDiscovery{GroupVersion: "company.com/v1", Version: "v1"}
|
||||
master.addThirdPartyResourceStorage("/apis/company.com/v1", nil,
|
||||
@ -312,13 +336,19 @@ func TestDiscoveryAtAPIS(t *testing.T) {
|
||||
thirdPartyGroupName := "company.com"
|
||||
thirdPartyExpectVersions := []unversioned.GroupVersionForDiscovery{thirdPartyGV}
|
||||
|
||||
assert.Equal(2, len(groupList.Groups))
|
||||
assert.Equal(thirdPartyGroupName, groupList.Groups[0].Name)
|
||||
assert.Equal(thirdPartyExpectVersions, groupList.Groups[0].Versions)
|
||||
assert.Equal(thirdPartyGV, groupList.Groups[0].PreferredVersion)
|
||||
assert.Equal(extensionsGroupName, groupList.Groups[1].Name)
|
||||
assert.Equal(extensionsVersions, groupList.Groups[1].Versions)
|
||||
assert.Equal(extensionsPreferredVersion, groupList.Groups[1].PreferredVersion)
|
||||
assert.Equal(3, len(groupList.Groups))
|
||||
// autoscaling group
|
||||
assert.Equal(expectGroupNames[0], groupList.Groups[0].Name)
|
||||
assert.Equal(expectVersions[0], groupList.Groups[0].Versions)
|
||||
assert.Equal(expectPreferredVersion[0], groupList.Groups[0].PreferredVersion)
|
||||
// third party
|
||||
assert.Equal(thirdPartyGroupName, groupList.Groups[1].Name)
|
||||
assert.Equal(thirdPartyExpectVersions, groupList.Groups[1].Versions)
|
||||
assert.Equal(thirdPartyGV, groupList.Groups[1].PreferredVersion)
|
||||
// extensions group
|
||||
assert.Equal(expectGroupNames[1], groupList.Groups[2].Name)
|
||||
assert.Equal(expectVersions[1], groupList.Groups[2].Versions)
|
||||
assert.Equal(expectPreferredVersion[1], groupList.Groups[2].PreferredVersion)
|
||||
}
|
||||
|
||||
var versionsToTest = []string{"v1", "v3"}
|
||||
|
50
pkg/runtime/codec_check.go
Normal file
50
pkg/runtime/codec_check.go
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
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 runtime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
)
|
||||
|
||||
// CheckCodec makes sure that the codec can encode objects like internalType,
|
||||
// decode all of the external types listed, and also decode them into the given
|
||||
// object. (Will modify internalObject.) (Assumes JSON serialization.)
|
||||
// TODO: verify that the correct external version is chosen on encode...
|
||||
func CheckCodec(c Codec, internalType Object, externalTypes ...unversioned.GroupVersionKind) error {
|
||||
_, err := Encode(c, internalType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Internal type not encodable: %v", err)
|
||||
}
|
||||
for _, et := range externalTypes {
|
||||
exBytes := []byte(fmt.Sprintf(`{"kind":"%v","apiVersion":"%v"}`, et.Kind, et.GroupVersion().String()))
|
||||
obj, err := Decode(c, exBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("external type %s not interpretable: %v", et, err)
|
||||
}
|
||||
if reflect.TypeOf(obj) != reflect.TypeOf(internalType) {
|
||||
return fmt.Errorf("decode of external type %s produced: %#v", et, obj)
|
||||
}
|
||||
err = DecodeInto(c, exBytes, internalType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("external type %s not convertable to internal type: %v", et, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@ -24,6 +24,42 @@ import (
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// EnableCrossGroupDecoding modifies the given decoder in place, if it is a codec
|
||||
// from this package. It allows objects from one group to be auto-decoded into
|
||||
// another group. 'destGroup' must already exist in the codec.
|
||||
func EnableCrossGroupDecoding(d runtime.Decoder, sourceGroup, destGroup string) error {
|
||||
internal, ok := d.(*codec)
|
||||
if !ok {
|
||||
return fmt.Errorf("unsupported decoder type")
|
||||
}
|
||||
|
||||
dest, ok := internal.decodeVersion[destGroup]
|
||||
if !ok {
|
||||
return fmt.Errorf("group %q is not a possible destination group in the given codec", destGroup)
|
||||
}
|
||||
internal.decodeVersion[sourceGroup] = dest
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnableCrossGroupEncoding modifies the given encoder in place, if it is a codec
|
||||
// from this package. It allows objects from one group to be auto-decoded into
|
||||
// another group. 'destGroup' must already exist in the codec.
|
||||
func EnableCrossGroupEncoding(e runtime.Encoder, sourceGroup, destGroup string) error {
|
||||
internal, ok := e.(*codec)
|
||||
if !ok {
|
||||
return fmt.Errorf("unsupported encoder type")
|
||||
}
|
||||
|
||||
dest, ok := internal.encodeVersion[destGroup]
|
||||
if !ok {
|
||||
return fmt.Errorf("group %q is not a possible destination group in the given codec", destGroup)
|
||||
}
|
||||
internal.encodeVersion[sourceGroup] = dest
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewCodecForScheme is a convenience method for callers that are using a scheme.
|
||||
func NewCodecForScheme(
|
||||
// TODO: I should be a scheme interface?
|
||||
|
@ -145,6 +145,14 @@ func NewCacherFromConfig(config CacherConfig) *Cacher {
|
||||
watchCache := newWatchCache(config.CacheCapacity)
|
||||
listerWatcher := newCacherListerWatcher(config.Storage, config.ResourcePrefix, config.NewListFunc)
|
||||
|
||||
// Give this error when it is constructed rather than when you get the
|
||||
// first watch item, because it's much easier to track down that way.
|
||||
if obj, ok := config.Type.(runtime.Object); ok {
|
||||
if err := runtime.CheckCodec(config.Storage.Codec(), obj); err != nil {
|
||||
panic("storage codec doesn't seem to match given type: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
cacher := &Cacher{
|
||||
usable: sync.RWMutex{},
|
||||
storage: config.Storage,
|
||||
|
@ -38,6 +38,7 @@ import (
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apiserver"
|
||||
"k8s.io/kubernetes/pkg/auth/authenticator"
|
||||
@ -780,8 +781,9 @@ func TestAuthorizationAttributeDetermination(t *testing.T) {
|
||||
URL string
|
||||
expectedAttributes authorizer.Attributes
|
||||
}{
|
||||
"prefix/version/resource": {"GET", "/api/v1/pods", authorizer.AttributesRecord{APIGroup: api.GroupName, Resource: "pods"}},
|
||||
"prefix/group/version/resource": {"GET", "/apis/extensions/v1/pods", authorizer.AttributesRecord{APIGroup: extensions.GroupName, Resource: "pods"}},
|
||||
"prefix/version/resource": {"GET", "/api/v1/pods", authorizer.AttributesRecord{APIGroup: api.GroupName, Resource: "pods"}},
|
||||
"prefix/group/version/resource": {"GET", "/apis/extensions/v1/pods", authorizer.AttributesRecord{APIGroup: extensions.GroupName, Resource: "pods"}},
|
||||
"prefix/group/version/resource2": {"GET", "/apis/autoscaling/v1/horizontalpodautoscalers", authorizer.AttributesRecord{APIGroup: autoscaling.GroupName, Resource: "horizontalpodautoscalers"}},
|
||||
}
|
||||
|
||||
currentAuthorizationAttributesIndex := 0
|
||||
|
@ -52,6 +52,13 @@ func NewEtcdStorage() storage.Interface {
|
||||
return etcdstorage.NewEtcdStorage(NewEtcdClient(), testapi.Default.Codec(), etcdtest.PathPrefix(), false)
|
||||
}
|
||||
|
||||
func NewAutoscalingEtcdStorage(client etcd.Client) storage.Interface {
|
||||
if client == nil {
|
||||
client = NewEtcdClient()
|
||||
}
|
||||
return etcdstorage.NewEtcdStorage(client, testapi.Autoscaling.Codec(), etcdtest.PathPrefix(), false)
|
||||
}
|
||||
|
||||
func NewExtensionsEtcdStorage(client etcd.Client) storage.Interface {
|
||||
if client == nil {
|
||||
client = NewEtcdClient()
|
||||
|
@ -29,6 +29,7 @@ import (
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apiserver"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
@ -150,11 +151,14 @@ func NewMasterConfig() *master.Config {
|
||||
|
||||
etcdStorage := etcdstorage.NewEtcdStorage(etcdClient, testapi.Default.Codec(), etcdtest.PathPrefix(), false)
|
||||
storageVersions[api.GroupName] = testapi.Default.GroupVersion().String()
|
||||
autoscalingEtcdStorage := NewAutoscalingEtcdStorage(etcdClient)
|
||||
storageVersions[autoscaling.GroupName] = testapi.Autoscaling.GroupVersion().String()
|
||||
expEtcdStorage := NewExtensionsEtcdStorage(etcdClient)
|
||||
storageVersions[extensions.GroupName] = testapi.Extensions.GroupVersion().String()
|
||||
|
||||
storageDestinations := genericapiserver.NewStorageDestinations()
|
||||
storageDestinations.AddAPIGroup(api.GroupName, etcdStorage)
|
||||
storageDestinations.AddAPIGroup(autoscaling.GroupName, autoscalingEtcdStorage)
|
||||
storageDestinations.AddAPIGroup(extensions.GroupName, expEtcdStorage)
|
||||
|
||||
return &master.Config{
|
||||
|
@ -19,30 +19,42 @@ limitations under the License.
|
||||
package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/test/integration/framework"
|
||||
)
|
||||
|
||||
func TestExperimentalPrefix(t *testing.T) {
|
||||
func testPrefix(t *testing.T, prefix string) {
|
||||
_, s := framework.RunAMaster(t)
|
||||
// TODO: Uncomment when fix #19254
|
||||
// defer s.Close()
|
||||
|
||||
resp, err := http.Get(s.URL + "/apis/extensions/")
|
||||
resp, err := http.Get(s.URL + prefix)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting experimental prefix: %v", err)
|
||||
t.Fatalf("unexpected error getting %s prefix: %v", prefix, err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("got status %v instead of 200 OK", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoscalingPrefix(t *testing.T) {
|
||||
testPrefix(t, "/apis/autoscaling/")
|
||||
}
|
||||
|
||||
func TestExtensionsPrefix(t *testing.T) {
|
||||
testPrefix(t, "/apis/extensions/")
|
||||
}
|
||||
|
||||
func TestWatchSucceedsWithoutArgs(t *testing.T) {
|
||||
_, s := framework.RunAMaster(t)
|
||||
// TODO: Uncomment when fix #19254
|
||||
@ -58,6 +70,81 @@ func TestWatchSucceedsWithoutArgs(t *testing.T) {
|
||||
resp.Body.Close()
|
||||
}
|
||||
|
||||
var hpaV1 string = `
|
||||
{
|
||||
"apiVersion": "autoscaling/v1",
|
||||
"kind": "HorizontalPodAutoscaler",
|
||||
"metadata": {
|
||||
"name": "test-hpa",
|
||||
"namespace": "default"
|
||||
},
|
||||
"spec": {
|
||||
"scaleTargetRef": {
|
||||
"kind": "ReplicationController",
|
||||
"name": "test-hpa",
|
||||
"namespace": "default"
|
||||
},
|
||||
"minReplicas": 1,
|
||||
"maxReplicas": 10,
|
||||
"targetCPUUtilizationPercentage": 50
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
func autoscalingPath(resource, namespace, name string) string {
|
||||
return testapi.Autoscaling.ResourcePath(resource, namespace, name)
|
||||
}
|
||||
|
||||
func extensionsPath(resource, namespace, name string) string {
|
||||
return testapi.Extensions.ResourcePath(resource, namespace, name)
|
||||
}
|
||||
|
||||
func TestAutoscalingGroupBackwardCompatibility(t *testing.T) {
|
||||
_, s := framework.RunAMaster(t)
|
||||
defer s.Close()
|
||||
transport := http.DefaultTransport
|
||||
|
||||
requests := []struct {
|
||||
verb string
|
||||
URL string
|
||||
body string
|
||||
expectedStatusCodes map[int]bool
|
||||
expectedVersion string
|
||||
}{
|
||||
{"POST", autoscalingPath("horizontalpodautoscalers", api.NamespaceDefault, ""), hpaV1, code201, ""},
|
||||
{"GET", autoscalingPath("horizontalpodautoscalers", api.NamespaceDefault, ""), "", code200, testapi.Autoscaling.GroupVersion().String()},
|
||||
{"GET", extensionsPath("horizontalpodautoscalers", api.NamespaceDefault, ""), "", code200, testapi.Extensions.GroupVersion().String()},
|
||||
}
|
||||
|
||||
for _, r := range requests {
|
||||
bodyBytes := bytes.NewReader([]byte(r.body))
|
||||
req, err := http.NewRequest(r.verb, s.URL+r.URL, bodyBytes)
|
||||
if err != nil {
|
||||
t.Logf("case %v", r)
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
func() {
|
||||
resp, err := transport.RoundTrip(req)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
t.Logf("case %v", r)
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
b, _ := ioutil.ReadAll(resp.Body)
|
||||
body := string(b)
|
||||
if _, ok := r.expectedStatusCodes[resp.StatusCode]; !ok {
|
||||
t.Logf("case %v", r)
|
||||
t.Errorf("Expected status one of %v, but got %v", r.expectedStatusCodes, resp.StatusCode)
|
||||
t.Errorf("Body: %v", body)
|
||||
}
|
||||
if !strings.Contains(body, "\"apiVersion\":\""+r.expectedVersion) {
|
||||
t.Logf("case %v", r)
|
||||
t.Errorf("Expected version %v, got body %v", r.expectedVersion, body)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccept(t *testing.T) {
|
||||
_, s := framework.RunAMaster(t)
|
||||
// TODO: Uncomment when fix #19254
|
||||
|
Loading…
Reference in New Issue
Block a user