mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-09 12:07:47 +00:00
Merge pull request #23847 from XiaoningDing/federation-apiobject-cluster
Automatic merge from submit-queue Federation apiobject cluster add federation api group add cluster api object and registry ~~generate cluster client~~ moved to #24117 update scripts to generate files for /federation #19313 #23653 #23554 @nikhiljindal @quinton-hoole, @deepak-vij, @XiaoningDing, @alfred-huangjian @mfanjie @huangyuqi @colhom
This commit is contained in:
commit
b7e4672db9
@ -49,6 +49,8 @@ func main() {
|
||||
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1",
|
||||
"k8s.io/kubernetes/pkg/apis/metrics",
|
||||
"k8s.io/kubernetes/pkg/apis/metrics/v1alpha1",
|
||||
"k8s.io/kubernetes/federation/apis/federation",
|
||||
"k8s.io/kubernetes/federation/apis/federation/v1alpha1",
|
||||
"k8s.io/kubernetes/pkg/conversion",
|
||||
"k8s.io/kubernetes/pkg/runtime",
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ func main() {
|
||||
"k8s.io/kubernetes/pkg/apis/extensions/v1beta1",
|
||||
"k8s.io/kubernetes/pkg/apis/metrics",
|
||||
"k8s.io/kubernetes/pkg/apis/metrics/v1alpha1",
|
||||
"k8s.io/kubernetes/federation/apis/federation",
|
||||
"k8s.io/kubernetes/federation/apis/federation/v1alpha1",
|
||||
}
|
||||
|
||||
if err := arguments.Execute(
|
||||
|
@ -70,6 +70,7 @@ func New() *Generator {
|
||||
`k8s.io/kubernetes/pkg/apis/autoscaling/v1`,
|
||||
`k8s.io/kubernetes/pkg/apis/batch/v1`,
|
||||
`k8s.io/kubernetes/pkg/apis/apps/v1alpha1`,
|
||||
`k8s.io/kubernetes/federation/apis/federation/v1alpha1`,
|
||||
}, ","),
|
||||
DropEmbeddedFields: "k8s.io/kubernetes/pkg/api/unversioned.TypeMeta",
|
||||
}
|
||||
|
158
federation/apis/federation/deep_copy_generated.go
Normal file
158
federation/apis/federation/deep_copy_generated.go
Normal file
@ -0,0 +1,158 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
|
||||
package federation
|
||||
|
||||
import (
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
conversion "k8s.io/kubernetes/pkg/conversion"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := api.Scheme.AddGeneratedDeepCopyFuncs(
|
||||
DeepCopy_federation_Cluster,
|
||||
DeepCopy_federation_ClusterCondition,
|
||||
DeepCopy_federation_ClusterList,
|
||||
DeepCopy_federation_ClusterMeta,
|
||||
DeepCopy_federation_ClusterSpec,
|
||||
DeepCopy_federation_ClusterStatus,
|
||||
); err != nil {
|
||||
// if one of the deep copy functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_federation_Cluster(in Cluster, out *Cluster, c *conversion.Cloner) error {
|
||||
if err := unversioned.DeepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := api.DeepCopy_api_ObjectMeta(in.ObjectMeta, &out.ObjectMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := DeepCopy_federation_ClusterSpec(in.Spec, &out.Spec, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := DeepCopy_federation_ClusterStatus(in.Status, &out.Status, c); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_federation_ClusterCondition(in ClusterCondition, out *ClusterCondition, c *conversion.Cloner) error {
|
||||
out.Type = in.Type
|
||||
out.Status = in.Status
|
||||
if err := unversioned.DeepCopy_unversioned_Time(in.LastProbeTime, &out.LastProbeTime, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := unversioned.DeepCopy_unversioned_Time(in.LastTransitionTime, &out.LastTransitionTime, c); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Reason = in.Reason
|
||||
out.Message = in.Message
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_federation_ClusterList(in ClusterList, out *ClusterList, c *conversion.Cloner) error {
|
||||
if err := unversioned.DeepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := unversioned.DeepCopy_unversioned_ListMeta(in.ListMeta, &out.ListMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Items != nil {
|
||||
in, out := in.Items, &out.Items
|
||||
*out = make([]Cluster, len(in))
|
||||
for i := range in {
|
||||
if err := DeepCopy_federation_Cluster(in[i], &(*out)[i], c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_federation_ClusterMeta(in ClusterMeta, out *ClusterMeta, c *conversion.Cloner) error {
|
||||
out.Version = in.Version
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_federation_ClusterSpec(in ClusterSpec, out *ClusterSpec, c *conversion.Cloner) error {
|
||||
if in.ServerAddressByClientCIDRs != nil {
|
||||
in, out := in.ServerAddressByClientCIDRs, &out.ServerAddressByClientCIDRs
|
||||
*out = make([]unversioned.ServerAddressByClientCIDR, len(in))
|
||||
for i := range in {
|
||||
if err := unversioned.DeepCopy_unversioned_ServerAddressByClientCIDR(in[i], &(*out)[i], c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.ServerAddressByClientCIDRs = nil
|
||||
}
|
||||
out.Credential = in.Credential
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_federation_ClusterStatus(in ClusterStatus, out *ClusterStatus, c *conversion.Cloner) error {
|
||||
if in.Conditions != nil {
|
||||
in, out := in.Conditions, &out.Conditions
|
||||
*out = make([]ClusterCondition, len(in))
|
||||
for i := range in {
|
||||
if err := DeepCopy_federation_ClusterCondition(in[i], &(*out)[i], c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Conditions = nil
|
||||
}
|
||||
if in.Capacity != nil {
|
||||
in, out := in.Capacity, &out.Capacity
|
||||
*out = make(api.ResourceList)
|
||||
for key, val := range in {
|
||||
newVal := new(resource.Quantity)
|
||||
if err := resource.DeepCopy_resource_Quantity(val, newVal, c); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Capacity = nil
|
||||
}
|
||||
if in.Allocatable != nil {
|
||||
in, out := in.Allocatable, &out.Allocatable
|
||||
*out = make(api.ResourceList)
|
||||
for key, val := range in {
|
||||
newVal := new(resource.Quantity)
|
||||
if err := resource.DeepCopy_resource_Quantity(val, newVal, c); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Allocatable = nil
|
||||
}
|
||||
if err := DeepCopy_federation_ClusterMeta(in.ClusterMeta, &out.ClusterMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
129
federation/apis/federation/install/install.go
Normal file
129
federation/apis/federation/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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/federation/apis/federation/v1alpha1"
|
||||
"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/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
|
||||
const importPrefix = "k8s.io/kubernetes/federation/apis/federation"
|
||||
|
||||
var accessor = meta.NewAccessor()
|
||||
|
||||
// availableVersions lists all known external versions for this group from most preferred to least preferred
|
||||
var availableVersions = []unversioned.GroupVersion{v1alpha1.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", federation.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(
|
||||
"Cluster",
|
||||
)
|
||||
|
||||
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 v1alpha1.SchemeGroupVersion:
|
||||
return &meta.VersionInterfaces{
|
||||
ObjectConvertor: api.Scheme,
|
||||
MetadataAccessor: accessor,
|
||||
}, nil
|
||||
default:
|
||||
g, _ := registered.Group(federation.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
|
||||
federation.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 v1alpha1.SchemeGroupVersion:
|
||||
v1alpha1.AddToScheme(api.Scheme)
|
||||
}
|
||||
}
|
||||
}
|
118
federation/apis/federation/install/install_test.go
Normal file
118
federation/apis/federation/install/install_test.go
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
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
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/federation/apis/federation/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func TestResourceVersioner(t *testing.T) {
|
||||
cluster := federation.Cluster{ObjectMeta: api.ObjectMeta{ResourceVersion: "10"}}
|
||||
version, err := accessor.ResourceVersion(&cluster)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if version != "10" {
|
||||
t.Errorf("unexpected version %v", version)
|
||||
}
|
||||
|
||||
clusterList := federation.ClusterList{ListMeta: unversioned.ListMeta{ResourceVersion: "10"}}
|
||||
version, err = accessor.ResourceVersion(&clusterList)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if version != "10" {
|
||||
t.Errorf("unexpected version %v", version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCodec(t *testing.T) {
|
||||
cluster := federation.Cluster{}
|
||||
// We do want to use package registered rather than testapi here, because we
|
||||
// want to test if the package install and package registered work as expected.
|
||||
data, err := runtime.Encode(api.Codecs.LegacyCodec(registered.GroupOrDie(federation.GroupName).GroupVersion), &cluster)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
other := federation.Cluster{}
|
||||
if err := json.Unmarshal(data, &other); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if other.APIVersion != registered.GroupOrDie(federation.GroupName).GroupVersion.String() || other.Kind != "Cluster" {
|
||||
t.Errorf("unexpected unmarshalled object %#v", other)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInterfacesFor(t *testing.T) {
|
||||
if _, err := registered.GroupOrDie(federation.GroupName).InterfacesFor(federation.SchemeGroupVersion); err == nil {
|
||||
t.Fatalf("unexpected non-error: %v", err)
|
||||
}
|
||||
for i, version := range registered.GroupOrDie(federation.GroupName).GroupVersions {
|
||||
if vi, err := registered.GroupOrDie(federation.GroupName).InterfacesFor(version); err != nil || vi == nil {
|
||||
t.Fatalf("%d: unexpected result: %v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRESTMapper(t *testing.T) {
|
||||
gv := v1alpha1.SchemeGroupVersion
|
||||
clusterGVK := gv.WithKind("Cluster")
|
||||
|
||||
if gvk, err := registered.GroupOrDie(federation.GroupName).RESTMapper.KindFor(gv.WithResource("clusters")); err != nil || gvk != clusterGVK {
|
||||
t.Errorf("unexpected version mapping: %v %v", gvk, err)
|
||||
}
|
||||
|
||||
if m, err := registered.GroupOrDie(federation.GroupName).RESTMapper.RESTMapping(clusterGVK.GroupKind(), ""); err != nil || m.GroupVersionKind != clusterGVK || m.Resource != "clusters" {
|
||||
t.Errorf("unexpected version mapping: %#v %v", m, err)
|
||||
}
|
||||
|
||||
for _, version := range registered.GroupOrDie(federation.GroupName).GroupVersions {
|
||||
mapping, err := registered.GroupOrDie(federation.GroupName).RESTMapper.RESTMapping(clusterGVK.GroupKind(), version.Version)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if mapping.Resource != "clusters" {
|
||||
t.Errorf("incorrect resource name: %#v", mapping)
|
||||
}
|
||||
if mapping.GroupVersionKind.GroupVersion() != version {
|
||||
t.Errorf("incorrect groupVersion: %v", mapping)
|
||||
}
|
||||
|
||||
interfaces, _ := registered.GroupOrDie(federation.GroupName).InterfacesFor(version)
|
||||
if mapping.ObjectConvertor != interfaces.ObjectConvertor {
|
||||
t.Errorf("unexpected: %#v, expected: %#v", mapping, interfaces)
|
||||
}
|
||||
|
||||
rc := &federation.Cluster{ObjectMeta: api.ObjectMeta{Name: "foo"}}
|
||||
name, err := mapping.MetadataAccessor.Name(rc)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if name != "foo" {
|
||||
t.Errorf("unable to retrieve object meta with: %v", mapping.MetadataAccessor)
|
||||
}
|
||||
}
|
||||
}
|
56
federation/apis/federation/register.go
Normal file
56
federation/apis/federation/register.go
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
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 federation
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "federation"
|
||||
|
||||
// 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()
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
addKnownTypes(scheme)
|
||||
}
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Cluster{},
|
||||
&ClusterList{},
|
||||
&api.ListOptions{},
|
||||
&api.DeleteOptions{},
|
||||
)
|
||||
}
|
||||
|
||||
func (obj *Cluster) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ClusterList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
2351
federation/apis/federation/types.generated.go
Normal file
2351
federation/apis/federation/types.generated.go
Normal file
File diff suppressed because it is too large
Load Diff
102
federation/apis/federation/types.go
Normal file
102
federation/apis/federation/types.go
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
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 federation
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
)
|
||||
|
||||
// ClusterSpec describes the attributes of a kubernetes cluster.
|
||||
type ClusterSpec struct {
|
||||
// A map of client CIDR to server address.
|
||||
// This is to help clients reach servers in the most network-efficient way possible.
|
||||
// Clients can use the appropriate server address as per the CIDR that they match.
|
||||
// In case of multiple matches, clients should use the longest matching CIDR.
|
||||
ServerAddressByClientCIDRs []unversioned.ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs" patchStrategy:"merge" patchMergeKey:"clientCIDR"`
|
||||
// the type (e.g. bearer token, client certificate etc) and data of the credential used to access cluster.
|
||||
// It’s used for system routines (not behalf of users)
|
||||
// TODO: string may not enough, https://github.com/kubernetes/kubernetes/pull/23847#discussion_r59301275
|
||||
Credential string `json:"credential,omitempty"`
|
||||
}
|
||||
|
||||
type ClusterConditionType string
|
||||
|
||||
// These are valid conditions of a cluster.
|
||||
const (
|
||||
// ClusterReady means the cluster is ready to accept workloads.
|
||||
ClusterReady ClusterConditionType = "Ready"
|
||||
// ClusterOffline means the cluster is temporarily down or not reachable
|
||||
ClusterOffline ClusterConditionType = "Offline"
|
||||
)
|
||||
|
||||
// ClusterCondition describes current state of a cluster.
|
||||
type ClusterCondition struct {
|
||||
// Type of cluster condition, Complete or Failed.
|
||||
Type ClusterConditionType `json:"type"`
|
||||
// Status of the condition, one of True, False, Unknown.
|
||||
Status api.ConditionStatus `json:"status"`
|
||||
// Last time the condition was checked.
|
||||
LastProbeTime unversioned.Time `json:"lastProbeTime,omitempty"`
|
||||
// Last time the condition transit from one status to another.
|
||||
LastTransitionTime unversioned.Time `json:"lastTransitionTime,omitempty"`
|
||||
// (brief) reason for the condition's last transition.
|
||||
Reason string `json:"reason,omitempty"`
|
||||
// Human readable message indicating details about last transition.
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// Cluster metadata
|
||||
type ClusterMeta struct {
|
||||
// Release version of the cluster.
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
// ClusterStatus is information about the current status of a cluster updated by cluster controller peridocally.
|
||||
type ClusterStatus struct {
|
||||
// Conditions is an array of current cluster conditions.
|
||||
Conditions []ClusterCondition `json:"conditions,omitempty"`
|
||||
// Capacity represents the total resources of the cluster
|
||||
Capacity api.ResourceList `json:"capacity,omitempty"`
|
||||
// Allocatable represents the total resources of a cluster that are available for scheduling.
|
||||
Allocatable api.ResourceList `json:"allocatable,omitempty"`
|
||||
ClusterMeta `json:",inline"`
|
||||
}
|
||||
|
||||
// Information about a registered cluster in a federated kubernetes setup. Clusters are not namespaced and have unique names in the federation.
|
||||
type Cluster struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
api.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
// Spec defines the behavior of the Cluster.
|
||||
Spec ClusterSpec `json:"spec,omitempty"`
|
||||
// Status describes the current status of a Cluster
|
||||
Status ClusterStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// A list of all the kubernetes clusters registered to the federation
|
||||
type ClusterList struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard list metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
|
||||
unversioned.ListMeta `json:"metadata,omitempty"`
|
||||
|
||||
// List of Cluster objects.
|
||||
Items []Cluster `json:"items"`
|
||||
}
|
40
federation/apis/federation/v1alpha1/conversion.go
Normal file
40
federation/apis/federation/v1alpha1/conversion.go
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func addConversionFuncs(scheme *runtime.Scheme) {
|
||||
err := api.Scheme.AddFieldLabelConversionFunc(SchemeGroupVersion.String(), "Cluster",
|
||||
func(label, value string) (string, string, error) {
|
||||
switch label {
|
||||
case "metadata.name":
|
||||
return label, value, nil
|
||||
default:
|
||||
return "", "", fmt.Errorf("field label not supported: %s", label)
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
// If one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
351
federation/apis/federation/v1alpha1/conversion_generated.go
Normal file
351
federation/apis/federation/v1alpha1/conversion_generated.go
Normal file
@ -0,0 +1,351 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by conversion-gen. Do not edit it manually!
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
federation "k8s.io/kubernetes/federation/apis/federation"
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
conversion "k8s.io/kubernetes/pkg/conversion"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := api.Scheme.AddGeneratedConversionFuncs(
|
||||
Convert_v1alpha1_Cluster_To_federation_Cluster,
|
||||
Convert_federation_Cluster_To_v1alpha1_Cluster,
|
||||
Convert_v1alpha1_ClusterCondition_To_federation_ClusterCondition,
|
||||
Convert_federation_ClusterCondition_To_v1alpha1_ClusterCondition,
|
||||
Convert_v1alpha1_ClusterList_To_federation_ClusterList,
|
||||
Convert_federation_ClusterList_To_v1alpha1_ClusterList,
|
||||
Convert_v1alpha1_ClusterMeta_To_federation_ClusterMeta,
|
||||
Convert_federation_ClusterMeta_To_v1alpha1_ClusterMeta,
|
||||
Convert_v1alpha1_ClusterSpec_To_federation_ClusterSpec,
|
||||
Convert_federation_ClusterSpec_To_v1alpha1_ClusterSpec,
|
||||
Convert_v1alpha1_ClusterStatus_To_federation_ClusterStatus,
|
||||
Convert_federation_ClusterStatus_To_v1alpha1_ClusterStatus,
|
||||
); err != nil {
|
||||
// if one of the conversion functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_Cluster_To_federation_Cluster(in *Cluster, out *federation.Cluster, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*Cluster))(in)
|
||||
}
|
||||
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Inefficient conversion - can we improve it?
|
||||
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1alpha1_ClusterSpec_To_federation_ClusterSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1alpha1_ClusterStatus_To_federation_ClusterStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha1_Cluster_To_federation_Cluster(in *Cluster, out *federation.Cluster, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_Cluster_To_federation_Cluster(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_federation_Cluster_To_v1alpha1_Cluster(in *federation.Cluster, out *Cluster, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*federation.Cluster))(in)
|
||||
}
|
||||
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Inefficient conversion - can we improve it?
|
||||
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_federation_ClusterSpec_To_v1alpha1_ClusterSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_federation_ClusterStatus_To_v1alpha1_ClusterStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_federation_Cluster_To_v1alpha1_Cluster(in *federation.Cluster, out *Cluster, s conversion.Scope) error {
|
||||
return autoConvert_federation_Cluster_To_v1alpha1_Cluster(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ClusterCondition_To_federation_ClusterCondition(in *ClusterCondition, out *federation.ClusterCondition, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*ClusterCondition))(in)
|
||||
}
|
||||
out.Type = federation.ClusterConditionType(in.Type)
|
||||
out.Status = api.ConditionStatus(in.Status)
|
||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(&in.LastProbeTime, &out.LastProbeTime, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(&in.LastTransitionTime, &out.LastTransitionTime, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Reason = in.Reason
|
||||
out.Message = in.Message
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha1_ClusterCondition_To_federation_ClusterCondition(in *ClusterCondition, out *federation.ClusterCondition, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_ClusterCondition_To_federation_ClusterCondition(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_federation_ClusterCondition_To_v1alpha1_ClusterCondition(in *federation.ClusterCondition, out *ClusterCondition, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*federation.ClusterCondition))(in)
|
||||
}
|
||||
out.Type = ClusterConditionType(in.Type)
|
||||
out.Status = v1.ConditionStatus(in.Status)
|
||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(&in.LastProbeTime, &out.LastProbeTime, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := api.Convert_unversioned_Time_To_unversioned_Time(&in.LastTransitionTime, &out.LastTransitionTime, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Reason = in.Reason
|
||||
out.Message = in.Message
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_federation_ClusterCondition_To_v1alpha1_ClusterCondition(in *federation.ClusterCondition, out *ClusterCondition, s conversion.Scope) error {
|
||||
return autoConvert_federation_ClusterCondition_To_v1alpha1_ClusterCondition(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ClusterList_To_federation_ClusterList(in *ClusterList, out *federation.ClusterList, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*ClusterList))(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 {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]federation.Cluster, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1alpha1_Cluster_To_federation_Cluster(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha1_ClusterList_To_federation_ClusterList(in *ClusterList, out *federation.ClusterList, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_ClusterList_To_federation_ClusterList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_federation_ClusterList_To_v1alpha1_ClusterList(in *federation.ClusterList, out *ClusterList, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*federation.ClusterList))(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 {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]Cluster, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_federation_Cluster_To_v1alpha1_Cluster(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_federation_ClusterList_To_v1alpha1_ClusterList(in *federation.ClusterList, out *ClusterList, s conversion.Scope) error {
|
||||
return autoConvert_federation_ClusterList_To_v1alpha1_ClusterList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ClusterMeta_To_federation_ClusterMeta(in *ClusterMeta, out *federation.ClusterMeta, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*ClusterMeta))(in)
|
||||
}
|
||||
out.Version = in.Version
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha1_ClusterMeta_To_federation_ClusterMeta(in *ClusterMeta, out *federation.ClusterMeta, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_ClusterMeta_To_federation_ClusterMeta(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_federation_ClusterMeta_To_v1alpha1_ClusterMeta(in *federation.ClusterMeta, out *ClusterMeta, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*federation.ClusterMeta))(in)
|
||||
}
|
||||
out.Version = in.Version
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_federation_ClusterMeta_To_v1alpha1_ClusterMeta(in *federation.ClusterMeta, out *ClusterMeta, s conversion.Scope) error {
|
||||
return autoConvert_federation_ClusterMeta_To_v1alpha1_ClusterMeta(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ClusterSpec_To_federation_ClusterSpec(in *ClusterSpec, out *federation.ClusterSpec, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*ClusterSpec))(in)
|
||||
}
|
||||
if in.ServerAddressByClientCIDRs != nil {
|
||||
in, out := &in.ServerAddressByClientCIDRs, &out.ServerAddressByClientCIDRs
|
||||
*out = make([]unversioned.ServerAddressByClientCIDR, len(*in))
|
||||
for i := range *in {
|
||||
// TODO: Inefficient conversion - can we improve it?
|
||||
if err := s.Convert(&(*in)[i], &(*out)[i], 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.ServerAddressByClientCIDRs = nil
|
||||
}
|
||||
out.Credential = in.Credential
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha1_ClusterSpec_To_federation_ClusterSpec(in *ClusterSpec, out *federation.ClusterSpec, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_ClusterSpec_To_federation_ClusterSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_federation_ClusterSpec_To_v1alpha1_ClusterSpec(in *federation.ClusterSpec, out *ClusterSpec, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*federation.ClusterSpec))(in)
|
||||
}
|
||||
if in.ServerAddressByClientCIDRs != nil {
|
||||
in, out := &in.ServerAddressByClientCIDRs, &out.ServerAddressByClientCIDRs
|
||||
*out = make([]unversioned.ServerAddressByClientCIDR, len(*in))
|
||||
for i := range *in {
|
||||
// TODO: Inefficient conversion - can we improve it?
|
||||
if err := s.Convert(&(*in)[i], &(*out)[i], 0); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.ServerAddressByClientCIDRs = nil
|
||||
}
|
||||
out.Credential = in.Credential
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_federation_ClusterSpec_To_v1alpha1_ClusterSpec(in *federation.ClusterSpec, out *ClusterSpec, s conversion.Scope) error {
|
||||
return autoConvert_federation_ClusterSpec_To_v1alpha1_ClusterSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ClusterStatus_To_federation_ClusterStatus(in *ClusterStatus, out *federation.ClusterStatus, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*ClusterStatus))(in)
|
||||
}
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]federation.ClusterCondition, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1alpha1_ClusterCondition_To_federation_ClusterCondition(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Conditions = nil
|
||||
}
|
||||
if err := v1.Convert_v1_ResourceList_To_api_ResourceList(&in.Capacity, &out.Capacity, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := v1.Convert_v1_ResourceList_To_api_ResourceList(&in.Allocatable, &out.Allocatable, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1alpha1_ClusterMeta_To_federation_ClusterMeta(&in.ClusterMeta, &out.ClusterMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1alpha1_ClusterStatus_To_federation_ClusterStatus(in *ClusterStatus, out *federation.ClusterStatus, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_ClusterStatus_To_federation_ClusterStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_federation_ClusterStatus_To_v1alpha1_ClusterStatus(in *federation.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
|
||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||
defaulting.(func(*federation.ClusterStatus))(in)
|
||||
}
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]ClusterCondition, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_federation_ClusterCondition_To_v1alpha1_ClusterCondition(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Conditions = nil
|
||||
}
|
||||
if in.Capacity != nil {
|
||||
in, out := &in.Capacity, &out.Capacity
|
||||
*out = make(v1.ResourceList, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(resource.Quantity)
|
||||
if err := api.Convert_resource_Quantity_To_resource_Quantity(&val, newVal, s); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[v1.ResourceName(key)] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Capacity = nil
|
||||
}
|
||||
if in.Allocatable != nil {
|
||||
in, out := &in.Allocatable, &out.Allocatable
|
||||
*out = make(v1.ResourceList, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(resource.Quantity)
|
||||
if err := api.Convert_resource_Quantity_To_resource_Quantity(&val, newVal, s); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[v1.ResourceName(key)] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Allocatable = nil
|
||||
}
|
||||
if err := Convert_federation_ClusterMeta_To_v1alpha1_ClusterMeta(&in.ClusterMeta, &out.ClusterMeta, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_federation_ClusterStatus_To_v1alpha1_ClusterStatus(in *federation.ClusterStatus, out *ClusterStatus, s conversion.Scope) error {
|
||||
return autoConvert_federation_ClusterStatus_To_v1alpha1_ClusterStatus(in, out, s)
|
||||
}
|
159
federation/apis/federation/v1alpha1/deep_copy_generated.go
Normal file
159
federation/apis/federation/v1alpha1/deep_copy_generated.go
Normal file
@ -0,0 +1,159 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
api "k8s.io/kubernetes/pkg/api"
|
||||
resource "k8s.io/kubernetes/pkg/api/resource"
|
||||
unversioned "k8s.io/kubernetes/pkg/api/unversioned"
|
||||
v1 "k8s.io/kubernetes/pkg/api/v1"
|
||||
conversion "k8s.io/kubernetes/pkg/conversion"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := api.Scheme.AddGeneratedDeepCopyFuncs(
|
||||
DeepCopy_v1alpha1_Cluster,
|
||||
DeepCopy_v1alpha1_ClusterCondition,
|
||||
DeepCopy_v1alpha1_ClusterList,
|
||||
DeepCopy_v1alpha1_ClusterMeta,
|
||||
DeepCopy_v1alpha1_ClusterSpec,
|
||||
DeepCopy_v1alpha1_ClusterStatus,
|
||||
); err != nil {
|
||||
// if one of the deep copy functions is malformed, detect it immediately.
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func DeepCopy_v1alpha1_Cluster(in Cluster, out *Cluster, c *conversion.Cloner) error {
|
||||
if err := unversioned.DeepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := v1.DeepCopy_v1_ObjectMeta(in.ObjectMeta, &out.ObjectMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := DeepCopy_v1alpha1_ClusterSpec(in.Spec, &out.Spec, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := DeepCopy_v1alpha1_ClusterStatus(in.Status, &out.Status, c); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_v1alpha1_ClusterCondition(in ClusterCondition, out *ClusterCondition, c *conversion.Cloner) error {
|
||||
out.Type = in.Type
|
||||
out.Status = in.Status
|
||||
if err := unversioned.DeepCopy_unversioned_Time(in.LastProbeTime, &out.LastProbeTime, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := unversioned.DeepCopy_unversioned_Time(in.LastTransitionTime, &out.LastTransitionTime, c); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Reason = in.Reason
|
||||
out.Message = in.Message
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_v1alpha1_ClusterList(in ClusterList, out *ClusterList, c *conversion.Cloner) error {
|
||||
if err := unversioned.DeepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := unversioned.DeepCopy_unversioned_ListMeta(in.ListMeta, &out.ListMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Items != nil {
|
||||
in, out := in.Items, &out.Items
|
||||
*out = make([]Cluster, len(in))
|
||||
for i := range in {
|
||||
if err := DeepCopy_v1alpha1_Cluster(in[i], &(*out)[i], c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_v1alpha1_ClusterMeta(in ClusterMeta, out *ClusterMeta, c *conversion.Cloner) error {
|
||||
out.Version = in.Version
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_v1alpha1_ClusterSpec(in ClusterSpec, out *ClusterSpec, c *conversion.Cloner) error {
|
||||
if in.ServerAddressByClientCIDRs != nil {
|
||||
in, out := in.ServerAddressByClientCIDRs, &out.ServerAddressByClientCIDRs
|
||||
*out = make([]unversioned.ServerAddressByClientCIDR, len(in))
|
||||
for i := range in {
|
||||
if err := unversioned.DeepCopy_unversioned_ServerAddressByClientCIDR(in[i], &(*out)[i], c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.ServerAddressByClientCIDRs = nil
|
||||
}
|
||||
out.Credential = in.Credential
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_v1alpha1_ClusterStatus(in ClusterStatus, out *ClusterStatus, c *conversion.Cloner) error {
|
||||
if in.Conditions != nil {
|
||||
in, out := in.Conditions, &out.Conditions
|
||||
*out = make([]ClusterCondition, len(in))
|
||||
for i := range in {
|
||||
if err := DeepCopy_v1alpha1_ClusterCondition(in[i], &(*out)[i], c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Conditions = nil
|
||||
}
|
||||
if in.Capacity != nil {
|
||||
in, out := in.Capacity, &out.Capacity
|
||||
*out = make(v1.ResourceList)
|
||||
for key, val := range in {
|
||||
newVal := new(resource.Quantity)
|
||||
if err := resource.DeepCopy_resource_Quantity(val, newVal, c); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Capacity = nil
|
||||
}
|
||||
if in.Allocatable != nil {
|
||||
in, out := in.Allocatable, &out.Allocatable
|
||||
*out = make(v1.ResourceList)
|
||||
for key, val := range in {
|
||||
newVal := new(resource.Quantity)
|
||||
if err := resource.DeepCopy_resource_Quantity(val, newVal, c); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Allocatable = nil
|
||||
}
|
||||
if err := DeepCopy_v1alpha1_ClusterMeta(in.ClusterMeta, &out.ClusterMeta, c); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
24
federation/apis/federation/v1alpha1/defaults.go
Normal file
24
federation/apis/federation/v1alpha1/defaults.go
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) {
|
||||
}
|
18
federation/apis/federation/v1alpha1/doc.go
Normal file
18
federation/apis/federation/v1alpha1/doc.go
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// +genconversion=true
|
||||
package v1alpha1
|
1603
federation/apis/federation/v1alpha1/generated.pb.go
Normal file
1603
federation/apis/federation/v1alpha1/generated.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
109
federation/apis/federation/v1alpha1/generated.proto
Normal file
109
federation/apis/federation/v1alpha1/generated.proto
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
|
||||
|
||||
syntax = 'proto2';
|
||||
|
||||
package k8s.io.kubernetes.federation.apis.federation.v1alpha1;
|
||||
|
||||
import "k8s.io/kubernetes/pkg/api/resource/generated.proto";
|
||||
import "k8s.io/kubernetes/pkg/api/unversioned/generated.proto";
|
||||
import "k8s.io/kubernetes/pkg/api/v1/generated.proto";
|
||||
import "k8s.io/kubernetes/pkg/util/intstr/generated.proto";
|
||||
|
||||
// Package-wide variables from generator "generated".
|
||||
option go_package = "v1alpha1";
|
||||
|
||||
// Information about a registered cluster in a federated kubernetes setup. Clusters are not namespaced and have unique names in the federation.
|
||||
message Cluster {
|
||||
// Standard object's metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
optional k8s.io.kubernetes.pkg.api.v1.ObjectMeta metadata = 1;
|
||||
|
||||
// Spec defines the behavior of the Cluster.
|
||||
optional ClusterSpec spec = 2;
|
||||
|
||||
// Status describes the current status of a Cluster
|
||||
optional ClusterStatus status = 3;
|
||||
}
|
||||
|
||||
// ClusterCondition describes current state of a cluster.
|
||||
message ClusterCondition {
|
||||
// Type of cluster condition, Complete or Failed.
|
||||
optional string type = 1;
|
||||
|
||||
// Status of the condition, one of True, False, Unknown.
|
||||
optional string status = 2;
|
||||
|
||||
// Last time the condition was checked.
|
||||
optional k8s.io.kubernetes.pkg.api.unversioned.Time lastProbeTime = 3;
|
||||
|
||||
// Last time the condition transit from one status to another.
|
||||
optional k8s.io.kubernetes.pkg.api.unversioned.Time lastTransitionTime = 4;
|
||||
|
||||
// (brief) reason for the condition's last transition.
|
||||
optional string reason = 5;
|
||||
|
||||
// Human readable message indicating details about last transition.
|
||||
optional string message = 6;
|
||||
}
|
||||
|
||||
// A list of all the kubernetes clusters registered to the federation
|
||||
message ClusterList {
|
||||
// Standard list metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
|
||||
optional k8s.io.kubernetes.pkg.api.unversioned.ListMeta metadata = 1;
|
||||
|
||||
// List of Cluster objects.
|
||||
repeated Cluster items = 2;
|
||||
}
|
||||
|
||||
// Cluster metadata
|
||||
message ClusterMeta {
|
||||
// Release version of the cluster.
|
||||
optional string version = 1;
|
||||
}
|
||||
|
||||
// ClusterSpec describes the attributes of a kubernetes cluster.
|
||||
message ClusterSpec {
|
||||
// A map of client CIDR to server address.
|
||||
// This is to help clients reach servers in the most network-efficient way possible.
|
||||
// Clients can use the appropriate server address as per the CIDR that they match.
|
||||
// In case of multiple matches, clients should use the longest matching CIDR.
|
||||
repeated k8s.io.kubernetes.pkg.api.unversioned.ServerAddressByClientCIDR serverAddressByClientCIDRs = 1;
|
||||
|
||||
// the type (e.g. bearer token, client certificate etc) and data of the credential used to access cluster.
|
||||
// It’s used for system routines (not behalf of users)
|
||||
// TODO: string may not enough, https://github.com/kubernetes/kubernetes/pull/23847#discussion_r59301275
|
||||
optional string credential = 2;
|
||||
}
|
||||
|
||||
// ClusterStatus is information about the current status of a cluster updated by cluster controller peridocally.
|
||||
message ClusterStatus {
|
||||
// Conditions is an array of current cluster conditions.
|
||||
repeated ClusterCondition conditions = 1;
|
||||
|
||||
// Capacity represents the total resources of the cluster
|
||||
map<string, k8s.io.kubernetes.pkg.api.resource.Quantity> capacity = 2;
|
||||
|
||||
// Allocatable represents the total resources of a cluster that are available for scheduling.
|
||||
map<string, k8s.io.kubernetes.pkg.api.resource.Quantity> allocatable = 3;
|
||||
|
||||
optional ClusterMeta clusterMeta = 4;
|
||||
}
|
||||
|
50
federation/apis/federation/v1alpha1/register.go
Normal file
50
federation/apis/federation/v1alpha1/register.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 v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
versionedwatch "k8s.io/kubernetes/pkg/watch/versioned"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "federation"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: "v1alpha1"}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
addKnownTypes(scheme)
|
||||
addDefaultingFuncs(scheme)
|
||||
addConversionFuncs(scheme)
|
||||
}
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Cluster{},
|
||||
&ClusterList{},
|
||||
&v1.ListOptions{},
|
||||
&v1.DeleteOptions{},
|
||||
)
|
||||
versionedwatch.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
}
|
||||
|
||||
func (obj *Cluster) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
||||
func (obj *ClusterList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
|
2351
federation/apis/federation/v1alpha1/types.generated.go
Normal file
2351
federation/apis/federation/v1alpha1/types.generated.go
Normal file
File diff suppressed because it is too large
Load Diff
102
federation/apis/federation/v1alpha1/types.go
Normal file
102
federation/apis/federation/v1alpha1/types.go
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
// ClusterSpec describes the attributes of a kubernetes cluster.
|
||||
type ClusterSpec struct {
|
||||
// A map of client CIDR to server address.
|
||||
// This is to help clients reach servers in the most network-efficient way possible.
|
||||
// Clients can use the appropriate server address as per the CIDR that they match.
|
||||
// In case of multiple matches, clients should use the longest matching CIDR.
|
||||
ServerAddressByClientCIDRs []unversioned.ServerAddressByClientCIDR `json:"serverAddressByClientCIDRs" patchStrategy:"merge" patchMergeKey:"clientCIDR" protobuf:"bytes,1,rep,name=serverAddressByClientCIDRs"`
|
||||
// the type (e.g. bearer token, client certificate etc) and data of the credential used to access cluster.
|
||||
// It’s used for system routines (not behalf of users)
|
||||
// TODO: string may not enough, https://github.com/kubernetes/kubernetes/pull/23847#discussion_r59301275
|
||||
Credential string `json:"credential,omitempty" protobuf:"bytes,2,opt,name=credential"`
|
||||
}
|
||||
|
||||
type ClusterConditionType string
|
||||
|
||||
// These are valid conditions of a cluster.
|
||||
const (
|
||||
// ClusterReady means the cluster is ready to accept workloads.
|
||||
ClusterReady ClusterConditionType = "Ready"
|
||||
// ClusterOffline means the cluster is temporarily down or not reachable
|
||||
ClusterOffline ClusterConditionType = "Offline"
|
||||
)
|
||||
|
||||
// ClusterCondition describes current state of a cluster.
|
||||
type ClusterCondition struct {
|
||||
// Type of cluster condition, Complete or Failed.
|
||||
Type ClusterConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=ClusterConditionType"`
|
||||
// Status of the condition, one of True, False, Unknown.
|
||||
Status v1.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=k8s.io/kubernetes/pkg/api/v1.ConditionStatus"`
|
||||
// Last time the condition was checked.
|
||||
LastProbeTime unversioned.Time `json:"lastProbeTime,omitempty" protobuf:"bytes,3,opt,name=lastProbeTime"`
|
||||
// Last time the condition transit from one status to another.
|
||||
LastTransitionTime unversioned.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,4,opt,name=lastTransitionTime"`
|
||||
// (brief) reason for the condition's last transition.
|
||||
Reason string `json:"reason,omitempty" protobuf:"bytes,5,opt,name=reason"`
|
||||
// Human readable message indicating details about last transition.
|
||||
Message string `json:"message,omitempty" protobuf:"bytes,6,opt,name=message"`
|
||||
}
|
||||
|
||||
// Cluster metadata
|
||||
type ClusterMeta struct {
|
||||
// Release version of the cluster.
|
||||
Version string `json:"version,omitempty" protobuf:"bytes,1,opt,name=version"`
|
||||
}
|
||||
|
||||
// ClusterStatus is information about the current status of a cluster updated by cluster controller peridocally.
|
||||
type ClusterStatus struct {
|
||||
// Conditions is an array of current cluster conditions.
|
||||
Conditions []ClusterCondition `json:"conditions,omitempty" protobuf:"bytes,1,rep,name=conditions"`
|
||||
// Capacity represents the total resources of the cluster
|
||||
Capacity v1.ResourceList `json:"capacity,omitempty" protobuf:"bytes,2,rep,name=capacity,casttype=k8s.io/kubernetes/pkg/api/v1.ResourceList,castkey=k8s.io/kubernetes/pkg/api/v1.ResourceName"`
|
||||
// Allocatable represents the total resources of a cluster that are available for scheduling.
|
||||
Allocatable v1.ResourceList `json:"allocatable,omitempty" protobuf:"bytes,3,rep,name=allocatable,casttype=k8s.io/kubernetes/pkg/api/v1.ResourceList,castkey=k8s.io/kubernetes/pkg/api/v1.ResourceName"`
|
||||
ClusterMeta `json:",inline" protobuf:"bytes,4,opt,name=clusterMeta"`
|
||||
}
|
||||
|
||||
// Information about a registered cluster in a federated kubernetes setup. Clusters are not namespaced and have unique names in the federation.
|
||||
type Cluster struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
v1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// Spec defines the behavior of the Cluster.
|
||||
Spec ClusterSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
|
||||
// Status describes the current status of a Cluster
|
||||
Status ClusterStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
|
||||
}
|
||||
|
||||
// A list of all the kubernetes clusters registered to the federation
|
||||
type ClusterList struct {
|
||||
unversioned.TypeMeta `json:",inline"`
|
||||
// Standard list metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
|
||||
unversioned.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// List of Cluster objects.
|
||||
Items []Cluster `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
56
federation/apis/federation/validation/validation.go
Normal file
56
federation/apis/federation/validation/validation.go
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
func ValidateClusterName(name string, prefix bool) (bool, string) {
|
||||
return validation.NameIsDNSSubdomain(name, prefix)
|
||||
}
|
||||
|
||||
func ValidateClusterSpec(spec *federation.ClusterSpec, fieldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
// address is required.
|
||||
if len(spec.ServerAddressByClientCIDRs) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fieldPath.Child("serverAddressByClientCIDRs"), ""))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateCluster(cluster *federation.Cluster) field.ErrorList {
|
||||
allErrs := validation.ValidateObjectMeta(&cluster.ObjectMeta, false, ValidateClusterName, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidateClusterSpec(&cluster.Spec, field.NewPath("spec"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateClusterUpdate(cluster, oldCluster *federation.Cluster) field.ErrorList {
|
||||
allErrs := validation.ValidateObjectMetaUpdate(&cluster.ObjectMeta, &oldCluster.ObjectMeta, field.NewPath("metadata"))
|
||||
if cluster.Name != oldCluster.Name {
|
||||
allErrs = append(allErrs, field.Invalid(field.NewPath("meta", "name"),
|
||||
cluster.Name+" != "+oldCluster.Name, "cannot change cluster name"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidateClusterStatusUpdate(cluster, oldCluster *federation.Cluster) field.ErrorList {
|
||||
allErrs := validation.ValidateObjectMetaUpdate(&cluster.ObjectMeta, &oldCluster.ObjectMeta, field.NewPath("metadata"))
|
||||
return allErrs
|
||||
}
|
206
federation/apis/federation/validation/validation_test.go
Normal file
206
federation/apis/federation/validation/validation_test.go
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
)
|
||||
|
||||
func TestValidateCluster(t *testing.T) {
|
||||
successCases := []federation.Cluster{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "cluster-s"},
|
||||
Spec: federation.ClusterSpec{
|
||||
ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{
|
||||
{
|
||||
ClientCIDR: "0.0.0.0/0",
|
||||
ServerAddress: "localhost:8888",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, successCase := range successCases {
|
||||
errs := ValidateCluster(&successCase)
|
||||
if len(errs) != 0 {
|
||||
t.Errorf("expect success: %v", errs)
|
||||
}
|
||||
}
|
||||
|
||||
errorCases := map[string]federation.Cluster{
|
||||
"missing cluster addresses": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "cluster-f"},
|
||||
},
|
||||
"empty cluster addresses": {
|
||||
ObjectMeta: api.ObjectMeta{Name: "cluster-f"},
|
||||
Spec: federation.ClusterSpec{
|
||||
ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{},
|
||||
}},
|
||||
"invalid_label": {
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "cluster-f",
|
||||
Labels: map[string]string{
|
||||
"NoUppercaseOrSpecialCharsLike=Equals": "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for testName, errorCase := range errorCases {
|
||||
errs := ValidateCluster(&errorCase)
|
||||
if len(errs) == 0 {
|
||||
t.Errorf("expected failur for %s", testName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateClusterUpdate(t *testing.T) {
|
||||
type clusterUpdateTest struct {
|
||||
old federation.Cluster
|
||||
update federation.Cluster
|
||||
}
|
||||
successCases := []clusterUpdateTest{
|
||||
{
|
||||
old: federation.Cluster{
|
||||
ObjectMeta: api.ObjectMeta{Name: "cluster-s"},
|
||||
Spec: federation.ClusterSpec{
|
||||
ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{
|
||||
{
|
||||
ClientCIDR: "0.0.0.0/0",
|
||||
ServerAddress: "localhost:8888",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
update: federation.Cluster{
|
||||
ObjectMeta: api.ObjectMeta{Name: "cluster-s"},
|
||||
Spec: federation.ClusterSpec{
|
||||
ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{
|
||||
{
|
||||
ClientCIDR: "0.0.0.0/0",
|
||||
ServerAddress: "localhost:8888",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, successCase := range successCases {
|
||||
successCase.old.ObjectMeta.ResourceVersion = "1"
|
||||
successCase.update.ObjectMeta.ResourceVersion = "1"
|
||||
errs := ValidateClusterUpdate(&successCase.update, &successCase.old)
|
||||
if len(errs) != 0 {
|
||||
t.Errorf("expect success: %v", errs)
|
||||
}
|
||||
}
|
||||
|
||||
errorCases := map[string]clusterUpdateTest{
|
||||
"cluster name changed": {
|
||||
old: federation.Cluster{
|
||||
ObjectMeta: api.ObjectMeta{Name: "cluster-s"},
|
||||
Spec: federation.ClusterSpec{
|
||||
ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{
|
||||
{
|
||||
ClientCIDR: "0.0.0.0/0",
|
||||
ServerAddress: "localhost:8888",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
update: federation.Cluster{
|
||||
ObjectMeta: api.ObjectMeta{Name: "cluster-newname"},
|
||||
Spec: federation.ClusterSpec{
|
||||
ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{
|
||||
{
|
||||
ClientCIDR: "0.0.0.0/0",
|
||||
ServerAddress: "localhost:8888",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for testName, errorCase := range errorCases {
|
||||
errs := ValidateClusterUpdate(&errorCase.update, &errorCase.old)
|
||||
if len(errs) == 0 {
|
||||
t.Errorf("expected failure: %s", testName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateClusterStatusUpdate(t *testing.T) {
|
||||
type clusterUpdateTest struct {
|
||||
old federation.Cluster
|
||||
update federation.Cluster
|
||||
}
|
||||
successCases := []clusterUpdateTest{
|
||||
{
|
||||
old: federation.Cluster{
|
||||
ObjectMeta: api.ObjectMeta{Name: "cluster-s"},
|
||||
Spec: federation.ClusterSpec{
|
||||
ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{
|
||||
{
|
||||
ClientCIDR: "0.0.0.0/0",
|
||||
ServerAddress: "localhost:8888",
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: federation.ClusterStatus{
|
||||
Conditions: []federation.ClusterCondition{
|
||||
{Type: federation.ClusterReady, Status: api.ConditionTrue},
|
||||
},
|
||||
},
|
||||
},
|
||||
update: federation.Cluster{
|
||||
ObjectMeta: api.ObjectMeta{Name: "cluster-s"},
|
||||
Spec: federation.ClusterSpec{
|
||||
ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{
|
||||
{
|
||||
ClientCIDR: "0.0.0.0/0",
|
||||
ServerAddress: "localhost:8888",
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: federation.ClusterStatus{
|
||||
Conditions: []federation.ClusterCondition{
|
||||
{Type: federation.ClusterReady, Status: api.ConditionTrue},
|
||||
{Type: federation.ClusterOffline, Status: api.ConditionTrue},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, successCase := range successCases {
|
||||
successCase.old.ObjectMeta.ResourceVersion = "1"
|
||||
successCase.update.ObjectMeta.ResourceVersion = "1"
|
||||
errs := ValidateClusterUpdate(&successCase.update, &successCase.old)
|
||||
if len(errs) != 0 {
|
||||
t.Errorf("expect success: %v", errs)
|
||||
}
|
||||
}
|
||||
|
||||
errorCases := map[string]clusterUpdateTest{}
|
||||
for testName, errorCase := range errorCases {
|
||||
errs := ValidateClusterStatusUpdate(&errorCase.update, &errorCase.old)
|
||||
if len(errs) == 0 {
|
||||
t.Errorf("expected failure: %s", testName)
|
||||
}
|
||||
}
|
||||
}
|
62
federation/cmd/federated-apiserver/app/federation.go
Normal file
62
federation/cmd/federated-apiserver/app/federation.go
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
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 app
|
||||
|
||||
import (
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/federation/cmd/federated-apiserver/app/options"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/rest"
|
||||
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
|
||||
_ "k8s.io/kubernetes/federation/apis/federation/install"
|
||||
clusteretcd "k8s.io/kubernetes/federation/registry/cluster/etcd"
|
||||
)
|
||||
|
||||
func installFederationAPIs(s *options.APIServer, g *genericapiserver.GenericAPIServer, f genericapiserver.StorageFactory) {
|
||||
storage, err := f.New(federation.Resource("clusters"))
|
||||
if err != nil {
|
||||
glog.Fatalf("Unable to find storage destination for %v, due to %v", "clusters", err.Error())
|
||||
}
|
||||
clusterStorage, clusterStatusStorage := clusteretcd.NewREST(generic.RESTOptions{
|
||||
Storage: storage,
|
||||
Decorator: g.StorageDecorator(),
|
||||
DeleteCollectionWorkers: s.DeleteCollectionWorkers,
|
||||
})
|
||||
federationResources := map[string]rest.Storage{
|
||||
"clusters": clusterStorage,
|
||||
"clusters/status": clusterStatusStorage,
|
||||
}
|
||||
federationGroupMeta := registered.GroupOrDie(federation.GroupName)
|
||||
apiGroupInfo := genericapiserver.APIGroupInfo{
|
||||
GroupMeta: *federationGroupMeta,
|
||||
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
|
||||
"v1alpha1": federationResources,
|
||||
},
|
||||
OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion,
|
||||
Scheme: api.Scheme,
|
||||
ParameterCodec: api.ParameterCodec,
|
||||
NegotiatedSerializer: api.Codecs,
|
||||
}
|
||||
if err := g.InstallAPIGroup(&apiGroupInfo); err != nil {
|
||||
glog.Fatalf("Error in registering group versions: %v", err)
|
||||
}
|
||||
}
|
@ -295,6 +295,8 @@ func Run(s *options.APIServer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
installFederationAPIs(s, m, storageFactory)
|
||||
|
||||
m.Run(s.ServerRunOptions)
|
||||
return nil
|
||||
}
|
||||
|
@ -20,7 +20,16 @@ import (
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io/ioutil"
|
||||
fed_v1a1 "k8s.io/kubernetes/federation/apis/federation/v1alpha1"
|
||||
"k8s.io/kubernetes/federation/cmd/federated-apiserver/app/options"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestLongRunningRequestRegexp(t *testing.T) {
|
||||
@ -63,3 +72,145 @@ func TestLongRunningRequestRegexp(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var insecurePort = 8081
|
||||
var serverIP = fmt.Sprintf("http://localhost:%v", insecurePort)
|
||||
var groupVersion = fed_v1a1.SchemeGroupVersion
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
s := options.NewAPIServer()
|
||||
s.InsecurePort = insecurePort
|
||||
_, ipNet, _ := net.ParseCIDR("10.10.10.0/24")
|
||||
s.ServiceClusterIPRange = *ipNet
|
||||
s.EtcdConfig.ServerList = []string{"http://localhost:4001"}
|
||||
go func() {
|
||||
if err := Run(s); err != nil {
|
||||
t.Fatalf("Error in bringing up the server: %v", err)
|
||||
}
|
||||
}()
|
||||
if err := waitForApiserverUp(); err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
testSwaggerSpec(t)
|
||||
testAPIGroupList(t)
|
||||
testAPIGroup(t)
|
||||
testAPIResourceList(t)
|
||||
}
|
||||
|
||||
func waitForApiserverUp() error {
|
||||
for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(5 * time.Second) {
|
||||
_, err := http.Get(serverIP)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("waiting for apiserver timed out")
|
||||
}
|
||||
|
||||
func readResponse(serverURL string) ([]byte, error) {
|
||||
response, err := http.Get(serverURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error in fetching %s: %v", serverURL, err)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status: %d for URL: %s, expected status: %d", response.StatusCode, serverURL, http.StatusOK)
|
||||
}
|
||||
contents, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error reading response from %s: %v", serverURL, err)
|
||||
}
|
||||
return contents, nil
|
||||
}
|
||||
|
||||
func testSwaggerSpec(t *testing.T) {
|
||||
serverURL := serverIP + "/swaggerapi"
|
||||
_, err := readResponse(serverURL)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func findGroup(groups []unversioned.APIGroup, groupName string) *unversioned.APIGroup {
|
||||
for _, group := range groups {
|
||||
if group.Name == groupName {
|
||||
return &group
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAPIGroupList(t *testing.T) {
|
||||
var groupVersionForDiscovery = unversioned.GroupVersionForDiscovery{
|
||||
GroupVersion: groupVersion.String(),
|
||||
Version: groupVersion.Version,
|
||||
}
|
||||
|
||||
serverURL := serverIP + "/apis"
|
||||
contents, err := readResponse(serverURL)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
var apiGroupList unversioned.APIGroupList
|
||||
err = json.Unmarshal(contents, &apiGroupList)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
|
||||
}
|
||||
|
||||
found := findGroup(apiGroupList.Groups, groupVersion.Group)
|
||||
assert.NotNil(t, found)
|
||||
assert.Equal(t, found.Name, groupVersion.Group)
|
||||
assert.Equal(t, 1, len(found.Versions))
|
||||
assert.Equal(t, found.Versions[0], groupVersionForDiscovery)
|
||||
assert.Equal(t, found.PreferredVersion, groupVersionForDiscovery)
|
||||
}
|
||||
|
||||
func testAPIGroup(t *testing.T) {
|
||||
serverURL := serverIP + "/apis/federation"
|
||||
contents, err := readResponse(serverURL)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
var apiGroup unversioned.APIGroup
|
||||
err = json.Unmarshal(contents, &apiGroup)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
|
||||
}
|
||||
assert.Equal(t, apiGroup.APIVersion, "v1")
|
||||
assert.Equal(t, apiGroup.Name, groupVersion.Group)
|
||||
assert.Equal(t, 1, len(apiGroup.Versions))
|
||||
assert.Equal(t, apiGroup.Versions[0].GroupVersion, groupVersion.String())
|
||||
assert.Equal(t, apiGroup.Versions[0].Version, groupVersion.Version)
|
||||
assert.Equal(t, apiGroup.Versions[0], apiGroup.PreferredVersion)
|
||||
}
|
||||
|
||||
func findResource(resources []unversioned.APIResource, resourceName string) *unversioned.APIResource {
|
||||
for _, resource := range resources {
|
||||
if resource.Name == resourceName {
|
||||
return &resource
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAPIResourceList(t *testing.T) {
|
||||
serverURL := serverIP + "/apis/federation/v1alpha1"
|
||||
contents, err := readResponse(serverURL)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
var apiResourceList unversioned.APIResourceList
|
||||
err = json.Unmarshal(contents, &apiResourceList)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in unmarshalling response from server %s: %v", serverURL, err)
|
||||
}
|
||||
assert.Equal(t, apiResourceList.APIVersion, "v1")
|
||||
assert.Equal(t, apiResourceList.GroupVersion, groupVersion.String())
|
||||
|
||||
found := findResource(apiResourceList.APIResources, "clusters")
|
||||
assert.NotNil(t, found)
|
||||
assert.False(t, found.Namespaced)
|
||||
found = findResource(apiResourceList.APIResources, "clusters/status")
|
||||
assert.NotNil(t, found)
|
||||
assert.False(t, found.Namespaced)
|
||||
}
|
||||
|
82
federation/registry/cluster/etcd/etcd.go
Normal file
82
federation/registry/cluster/etcd/etcd.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 etcd
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/federation/registry/cluster"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
"k8s.io/kubernetes/pkg/registry/generic/registry"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
type REST struct {
|
||||
*registry.Store
|
||||
}
|
||||
|
||||
type StatusREST struct {
|
||||
store *registry.Store
|
||||
}
|
||||
|
||||
func (r *StatusREST) New() runtime.Object {
|
||||
return &federation.Cluster{}
|
||||
}
|
||||
|
||||
// Update alters the status subset of an object.
|
||||
func (r *StatusREST) Update(ctx api.Context, obj runtime.Object) (runtime.Object, bool, error) {
|
||||
return r.store.Update(ctx, obj)
|
||||
}
|
||||
|
||||
// NewREST returns a RESTStorage object that will work against clusters.
|
||||
func NewREST(opts generic.RESTOptions) (*REST, *StatusREST) {
|
||||
prefix := "/clusters"
|
||||
|
||||
newListFunc := func() runtime.Object { return &federation.ClusterList{} }
|
||||
storageInterface := opts.Decorator(
|
||||
opts.Storage, 100, &federation.Cluster{}, prefix, cluster.Strategy, newListFunc)
|
||||
|
||||
store := ®istry.Store{
|
||||
NewFunc: func() runtime.Object { return &federation.Cluster{} },
|
||||
NewListFunc: newListFunc,
|
||||
KeyRootFunc: func(ctx api.Context) string {
|
||||
return prefix
|
||||
},
|
||||
KeyFunc: func(ctx api.Context, name string) (string, error) {
|
||||
return registry.NoNamespaceKeyFunc(ctx, prefix, name)
|
||||
},
|
||||
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||
return obj.(*federation.Cluster).Name, nil
|
||||
},
|
||||
PredicateFunc: cluster.MatchCluster,
|
||||
QualifiedResource: federation.Resource("clusters"),
|
||||
DeleteCollectionWorkers: opts.DeleteCollectionWorkers,
|
||||
|
||||
CreateStrategy: cluster.Strategy,
|
||||
UpdateStrategy: cluster.Strategy,
|
||||
DeleteStrategy: cluster.Strategy,
|
||||
|
||||
ReturnDeletedObject: true,
|
||||
|
||||
Storage: storageInterface,
|
||||
}
|
||||
|
||||
statusStore := *store
|
||||
statusStore.UpdateStrategy = cluster.StatusStrategy
|
||||
|
||||
return &REST{store}, &StatusREST{store: &statusStore}
|
||||
}
|
142
federation/registry/cluster/etcd/etcd_test.go
Normal file
142
federation/registry/cluster/etcd/etcd_test.go
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package etcd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
"k8s.io/kubernetes/pkg/registry/registrytest"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
|
||||
)
|
||||
|
||||
func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) {
|
||||
etcdStorage, server := registrytest.NewEtcdStorage(t, federation.GroupName)
|
||||
restOptions := generic.RESTOptions{
|
||||
Storage: etcdStorage,
|
||||
Decorator: generic.UndecoratedStorage,
|
||||
DeleteCollectionWorkers: 1}
|
||||
storage, _ := NewREST(restOptions)
|
||||
return storage, server
|
||||
}
|
||||
|
||||
func validNewCluster() *federation.Cluster {
|
||||
return &federation.Cluster{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
Labels: map[string]string{
|
||||
"name": "foo",
|
||||
},
|
||||
},
|
||||
Spec: federation.ClusterSpec{
|
||||
ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{
|
||||
{
|
||||
ClientCIDR: "0.0.0.0/0",
|
||||
ServerAddress: "localhost:8888",
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: federation.ClusterStatus{
|
||||
Conditions: []federation.ClusterCondition{
|
||||
{Type: federation.ClusterReady, Status: api.ConditionFalse},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
test := registrytest.New(t, storage.Store).ClusterScope()
|
||||
cluster := validNewCluster()
|
||||
cluster.ObjectMeta = api.ObjectMeta{GenerateName: "foo"}
|
||||
test.TestCreate(
|
||||
cluster,
|
||||
&federation.Cluster{
|
||||
ObjectMeta: api.ObjectMeta{Name: "-a123-a_"},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestUpdate(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
test := registrytest.New(t, storage.Store).ClusterScope()
|
||||
test.TestUpdate(
|
||||
// valid
|
||||
validNewCluster(),
|
||||
// updateFunc
|
||||
func(obj runtime.Object) runtime.Object {
|
||||
object := obj.(*federation.Cluster)
|
||||
object.Spec.Credential = "bar"
|
||||
return object
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
test := registrytest.New(t, storage.Store).ClusterScope().ReturnDeletedObject()
|
||||
test.TestDelete(validNewCluster())
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
test := registrytest.New(t, storage.Store).ClusterScope()
|
||||
test.TestGet(validNewCluster())
|
||||
}
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
test := registrytest.New(t, storage.Store).ClusterScope()
|
||||
test.TestList(validNewCluster())
|
||||
}
|
||||
|
||||
func TestWatch(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
test := registrytest.New(t, storage.Store).ClusterScope()
|
||||
test.TestWatch(
|
||||
validNewCluster(),
|
||||
// matching labels
|
||||
[]labels.Set{
|
||||
{"name": "foo"},
|
||||
},
|
||||
// not matching labels
|
||||
[]labels.Set{
|
||||
{"name": "bar"},
|
||||
{"foo": "bar"},
|
||||
},
|
||||
// matching fields
|
||||
[]fields.Set{
|
||||
{"metadata.name": "foo"},
|
||||
},
|
||||
// not matching fields
|
||||
[]fields.Set{
|
||||
{"metadata.name": "bar"},
|
||||
},
|
||||
)
|
||||
}
|
81
federation/registry/cluster/registry.go
Normal file
81
federation/registry/cluster/registry.go
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
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 cluster
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/rest"
|
||||
"k8s.io/kubernetes/pkg/watch"
|
||||
)
|
||||
|
||||
// Registry is an interface implemented by things that know how to store Cluster objects.
|
||||
type Registry interface {
|
||||
ListClusters(ctx api.Context, options *api.ListOptions) (*federation.ClusterList, error)
|
||||
WatchCluster(ctx api.Context, options *api.ListOptions) (watch.Interface, error)
|
||||
GetCluster(ctx api.Context, name string) (*federation.Cluster, error)
|
||||
CreateCluster(ctx api.Context, cluster *federation.Cluster) error
|
||||
UpdateCluster(ctx api.Context, cluster *federation.Cluster) error
|
||||
DeleteCluster(ctx api.Context, name string) error
|
||||
}
|
||||
|
||||
// storage puts strong typing around storage calls
|
||||
|
||||
type storage struct {
|
||||
rest.StandardStorage
|
||||
}
|
||||
|
||||
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
||||
// types will panic.
|
||||
func NewRegistry(s rest.StandardStorage) Registry {
|
||||
return &storage{s}
|
||||
}
|
||||
|
||||
func (s *storage) ListClusters(ctx api.Context, options *api.ListOptions) (*federation.ClusterList, error) {
|
||||
obj, err := s.List(ctx, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*federation.ClusterList), nil
|
||||
}
|
||||
|
||||
func (s *storage) WatchCluster(ctx api.Context, options *api.ListOptions) (watch.Interface, error) {
|
||||
return s.Watch(ctx, options)
|
||||
}
|
||||
|
||||
func (s *storage) GetCluster(ctx api.Context, name string) (*federation.Cluster, error) {
|
||||
obj, err := s.Get(ctx, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*federation.Cluster), nil
|
||||
}
|
||||
|
||||
func (s *storage) CreateCluster(ctx api.Context, cluster *federation.Cluster) error {
|
||||
_, err := s.Create(ctx, cluster)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *storage) UpdateCluster(ctx api.Context, cluster *federation.Cluster) error {
|
||||
_, _, err := s.Update(ctx, cluster)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *storage) DeleteCluster(ctx api.Context, name string) error {
|
||||
_, err := s.Delete(ctx, name, nil)
|
||||
return err
|
||||
}
|
115
federation/registry/cluster/strategy.go
Normal file
115
federation/registry/cluster/strategy.go
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
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 cluster
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/federation/apis/federation/validation"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
type clusterStrategy struct {
|
||||
runtime.ObjectTyper
|
||||
api.NameGenerator
|
||||
}
|
||||
|
||||
var Strategy = clusterStrategy{api.Scheme, api.SimpleNameGenerator}
|
||||
|
||||
func (clusterStrategy) NamespaceScoped() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func ClusterToSelectableFields(cluster *federation.Cluster) fields.Set {
|
||||
return generic.ObjectMetaFieldsSet(cluster.ObjectMeta, false)
|
||||
}
|
||||
|
||||
func MatchCluster(label labels.Selector, field fields.Selector) generic.Matcher {
|
||||
return &generic.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
cluster, ok := obj.(*federation.Cluster)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("given object is not a cluster.")
|
||||
}
|
||||
return labels.Set(cluster.ObjectMeta.Labels), ClusterToSelectableFields(cluster), nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
|
||||
func (clusterStrategy) PrepareForCreate(obj runtime.Object) {
|
||||
cluster := obj.(*federation.Cluster)
|
||||
cluster.Status = federation.ClusterStatus{}
|
||||
}
|
||||
|
||||
// Validate validates a new cluster.
|
||||
func (clusterStrategy) Validate(ctx api.Context, obj runtime.Object) field.ErrorList {
|
||||
cluster := obj.(*federation.Cluster)
|
||||
return validation.ValidateCluster(cluster)
|
||||
}
|
||||
|
||||
// Canonicalize normalizes the object after validation.
|
||||
func (clusterStrategy) Canonicalize(obj runtime.Object) {
|
||||
}
|
||||
|
||||
// AllowCreateOnUpdate is false for cluster.
|
||||
func (clusterStrategy) AllowCreateOnUpdate() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||
func (clusterStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||
cluster := obj.(*federation.Cluster)
|
||||
oldCluster := old.(*federation.Cluster)
|
||||
cluster.Status = oldCluster.Status
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user.
|
||||
func (clusterStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
|
||||
return validation.ValidateClusterUpdate(obj.(*federation.Cluster), old.(*federation.Cluster))
|
||||
}
|
||||
func (clusterStrategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
type clusterStatusStrategy struct {
|
||||
clusterStrategy
|
||||
}
|
||||
|
||||
var StatusStrategy = clusterStatusStrategy{Strategy}
|
||||
|
||||
func (clusterStatusStrategy) PrepareForCreate(obj runtime.Object) {
|
||||
_ = obj.(*federation.Cluster)
|
||||
}
|
||||
func (clusterStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||
cluster := obj.(*federation.Cluster)
|
||||
oldCluster := old.(*federation.Cluster)
|
||||
cluster.Spec = oldCluster.Spec
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user.
|
||||
func (clusterStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
|
||||
return validation.ValidateClusterStatusUpdate(obj.(*federation.Cluster), old.(*federation.Cluster))
|
||||
}
|
165
federation/registry/cluster/strategy_test.go
Normal file
165
federation/registry/cluster/strategy_test.go
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
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 cluster
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func validNewCluster() *federation.Cluster {
|
||||
return &federation.Cluster{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
ResourceVersion: "4",
|
||||
Labels: map[string]string{
|
||||
"name": "foo",
|
||||
},
|
||||
},
|
||||
Spec: federation.ClusterSpec{
|
||||
ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{
|
||||
{
|
||||
ClientCIDR: "0.0.0.0/0",
|
||||
ServerAddress: "localhost:8888",
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: federation.ClusterStatus{
|
||||
Conditions: []federation.ClusterCondition{
|
||||
{Type: federation.ClusterReady, Status: api.ConditionTrue},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func invalidNewCluster() *federation.Cluster {
|
||||
return &federation.Cluster{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo2",
|
||||
ResourceVersion: "5",
|
||||
},
|
||||
Spec: federation.ClusterSpec{
|
||||
Credential: "bar",
|
||||
},
|
||||
Status: federation.ClusterStatus{
|
||||
Conditions: []federation.ClusterCondition{
|
||||
{Type: federation.ClusterReady, Status: api.ConditionFalse},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestClusterStrategy(t *testing.T) {
|
||||
ctx := api.NewDefaultContext()
|
||||
if Strategy.NamespaceScoped() {
|
||||
t.Errorf("Cluster should not be namespace scoped")
|
||||
}
|
||||
if Strategy.AllowCreateOnUpdate() {
|
||||
t.Errorf("Cluster should not allow create on update")
|
||||
}
|
||||
|
||||
cluster := validNewCluster()
|
||||
Strategy.PrepareForCreate(cluster)
|
||||
if len(cluster.Status.Conditions) != 0 {
|
||||
t.Errorf("Cluster should not allow setting conditions on create")
|
||||
}
|
||||
errs := Strategy.Validate(ctx, cluster)
|
||||
if len(errs) != 0 {
|
||||
t.Errorf("Unexpected error validating %v", errs)
|
||||
}
|
||||
|
||||
invalidCluster := invalidNewCluster()
|
||||
Strategy.PrepareForUpdate(invalidCluster, cluster)
|
||||
if reflect.DeepEqual(invalidCluster.Spec, cluster.Spec) ||
|
||||
!reflect.DeepEqual(invalidCluster.Status, cluster.Status) {
|
||||
t.Error("Only spec is expected being changed")
|
||||
}
|
||||
errs = Strategy.ValidateUpdate(ctx, invalidCluster, cluster)
|
||||
if len(errs) == 0 {
|
||||
t.Errorf("Expected a validation error")
|
||||
}
|
||||
if cluster.ResourceVersion != "4" {
|
||||
t.Errorf("Incoming resource version on update should not be mutated")
|
||||
}
|
||||
}
|
||||
|
||||
func TestClusterStatusStrategy(t *testing.T) {
|
||||
ctx := api.NewDefaultContext()
|
||||
if StatusStrategy.NamespaceScoped() {
|
||||
t.Errorf("Cluster should not be namespace scoped")
|
||||
}
|
||||
if StatusStrategy.AllowCreateOnUpdate() {
|
||||
t.Errorf("Cluster should not allow create on update")
|
||||
}
|
||||
|
||||
cluster := validNewCluster()
|
||||
invalidCluster := invalidNewCluster()
|
||||
StatusStrategy.PrepareForUpdate(cluster, invalidCluster)
|
||||
if !reflect.DeepEqual(invalidCluster.Spec, cluster.Spec) ||
|
||||
reflect.DeepEqual(invalidCluster.Status, cluster.Status) {
|
||||
t.Logf("== cluster.Spec: %v\n", cluster.Spec)
|
||||
t.Logf("== cluster.Status: %v\n", cluster.Status)
|
||||
t.Logf("== invalidCluster.Spec: %v\n", cluster.Spec)
|
||||
t.Logf("== invalidCluster.Spec: %v\n", cluster.Status)
|
||||
t.Error("Only spec is expected being changed")
|
||||
}
|
||||
errs := Strategy.ValidateUpdate(ctx, invalidCluster, cluster)
|
||||
if len(errs) == 0 {
|
||||
t.Errorf("Expected a validation error")
|
||||
}
|
||||
if cluster.ResourceVersion != "4" {
|
||||
t.Errorf("Incoming resource version on update should not be mutated")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchCluster(t *testing.T) {
|
||||
testFieldMap := map[bool][]fields.Set{
|
||||
true: {
|
||||
{"metadata.name": "foo"},
|
||||
},
|
||||
false: {
|
||||
{"foo": "bar"},
|
||||
},
|
||||
}
|
||||
|
||||
for expectedResult, fieldSet := range testFieldMap {
|
||||
for _, field := range fieldSet {
|
||||
m := MatchCluster(labels.Everything(), field.AsSelector())
|
||||
_, matchesSingle := m.MatchesSingle()
|
||||
if e, a := expectedResult, matchesSingle; e != a {
|
||||
t.Errorf("%+v: expected %v, got %v", fieldSet, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectableFieldLabelConversions(t *testing.T) {
|
||||
apitesting.TestSelectableFieldLabelConversionsOfKind(t,
|
||||
testapi.Federation.GroupVersion().String(),
|
||||
"Cluster",
|
||||
labels.Set(ClusterToSelectableFields(&federation.Cluster{})),
|
||||
nil,
|
||||
)
|
||||
}
|
@ -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;v1,autoscaling/v1,batch/v1,extensions/v1beta1,apps/v1alpha1,metrics/v1alpha1"}
|
||||
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,extensions/v1beta1,metrics/v1alpha1,federation/v1alpha1;v1,autoscaling/v1,batch/v1,extensions/v1beta1,apps/v1alpha1,metrics/v1alpha1,federation/v1alpha1"}
|
||||
# once we have multiple group supports
|
||||
# Run tests with the standard (registry) and a custom etcd prefix
|
||||
# (kubernetes.io/registry).
|
||||
|
@ -42,6 +42,7 @@ function prereqs() {
|
||||
--volume "${REPO_DIR:-${KUBE_ROOT}}/Godeps/_workspace/src:/go/src/${KUBE_GO_PACKAGE}/Godeps/_workspace/src"
|
||||
--volume "${REPO_DIR:-${KUBE_ROOT}}/hack:/go/src/${KUBE_GO_PACKAGE}/hack"
|
||||
--volume "${REPO_DIR:-${KUBE_ROOT}}/pkg:/go/src/${KUBE_GO_PACKAGE}/pkg"
|
||||
--volume "${REPO_DIR:-${KUBE_ROOT}}/federation:/go/src/${KUBE_GO_PACKAGE}/federation"
|
||||
--volume "${REPO_DIR:-${KUBE_ROOT}}/third_party:/go/src/${KUBE_GO_PACKAGE}/third_party"
|
||||
--volume /etc/localtime:/etc/localtime:ro
|
||||
--volumes-from "${KUBE_BUILD_DATA_CONTAINER_NAME}"
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/federation/apis/federation"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/meta"
|
||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||
@ -33,6 +34,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
|
||||
_ "k8s.io/kubernetes/federation/apis/federation/install"
|
||||
_ "k8s.io/kubernetes/pkg/api/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/apps/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
|
||||
@ -49,6 +51,7 @@ var (
|
||||
Batch TestGroup
|
||||
Extensions TestGroup
|
||||
Apps TestGroup
|
||||
Federation TestGroup
|
||||
)
|
||||
|
||||
type TestGroup struct {
|
||||
@ -132,12 +135,20 @@ func init() {
|
||||
internalTypes: api.Scheme.KnownTypes(extensions.SchemeGroupVersion),
|
||||
}
|
||||
}
|
||||
if _, ok := Groups[federation.GroupName]; !ok {
|
||||
Groups[federation.GroupName] = TestGroup{
|
||||
externalGroupVersion: unversioned.GroupVersion{Group: federation.GroupName, Version: registered.GroupOrDie(federation.GroupName).GroupVersion.Version},
|
||||
internalGroupVersion: federation.SchemeGroupVersion,
|
||||
internalTypes: api.Scheme.KnownTypes(federation.SchemeGroupVersion),
|
||||
}
|
||||
}
|
||||
|
||||
Default = Groups[api.GroupName]
|
||||
Autoscaling = Groups[autoscaling.GroupName]
|
||||
Batch = Groups[batch.GroupName]
|
||||
Apps = Groups[apps.GroupName]
|
||||
Extensions = Groups[extensions.GroupName]
|
||||
Federation = Groups[federation.GroupName]
|
||||
}
|
||||
|
||||
func (g TestGroup) ContentConfig() (string, *unversioned.GroupVersion, runtime.Codec) {
|
||||
|
@ -105,6 +105,12 @@ func DeepCopy_unversioned_ListMeta(in ListMeta, out *ListMeta, c *conversion.Clo
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_unversioned_ServerAddressByClientCIDR(in ServerAddressByClientCIDR, out *ServerAddressByClientCIDR, c *conversion.Cloner) error {
|
||||
out.ClientCIDR = in.ClientCIDR
|
||||
out.ServerAddress = in.ServerAddress
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeepCopy_unversioned_Time(in Time, out *Time, c *conversion.Cloner) error {
|
||||
if newVal, err := c.DeepCopy(in.Time); err != nil {
|
||||
return err
|
||||
|
Loading…
Reference in New Issue
Block a user