add api group 'federation' and 'cluster' object

This commit is contained in:
jianhuiz 2016-03-30 18:57:02 -07:00
parent 95f2ca2ff6
commit fcb241d05c
19 changed files with 5007 additions and 0 deletions

View File

@ -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",
}

View File

@ -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(

View File

@ -0,0 +1,133 @@
// +build !ignore_autogenerated
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package 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_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_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 {
out.Phase = in.Phase
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
}

View 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)
}
}
}

View 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)
}
}
}

View 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 }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
/*
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.
// Its 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 ClusterPhase string
// These are the valid phases of a cluster.
const (
// Newly registered clusters or clusters suspended by admin for various reasons. They are not eligible for accepting workloads
ClusterPending ClusterPhase = "pending"
// Clusters in normal status that can accept workloads
ClusterRunning ClusterPhase = "running"
// Clusters temporarily down or not reachable
ClusterOffline ClusterPhase = "offline"
// Clusters removed from federation
ClusterTerminated ClusterPhase = "terminated"
)
// 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 {
// Phase is the recently observed lifecycle phase of the cluster.
Phase ClusterPhase `json:"phase,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"`
}

View File

@ -0,0 +1,41 @@
/*
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",
"status.phase":
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)
}
}

View File

@ -0,0 +1,287 @@
// +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_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_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)
}
out.Phase = federation.ClusterPhase(in.Phase)
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)
}
out.Phase = ClusterPhase(in.Phase)
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)
}

View File

@ -0,0 +1,134 @@
// +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_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_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 {
out.Phase = in.Phase
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
}

View File

@ -0,0 +1,31 @@
/*
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) {
scheme.AddDefaultingFuncs(
func(obj *Cluster) {
if obj.Status.Phase == "" {
obj.Status.Phase = ClusterPending
}
},
)
}

View 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

View 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 }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
/*
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"`
// the type (e.g. bearer token, client certificate etc) and data of the credential used to access cluster.
// Its 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 ClusterPhase string
// These are the valid phases of a cluster.
const (
// Newly registered clusters or clusters suspended by admin for various reasons. They are not eligible for accepting workloads
ClusterPending ClusterPhase = "pending"
// Clusters in normal status that can accept workloads
ClusterRunning ClusterPhase = "running"
// Clusters temporarily down or not reachable
ClusterOffline ClusterPhase = "offline"
// Clusters removed from federation
ClusterTerminated ClusterPhase = "terminated"
)
// 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 {
// Phase is the recently observed lifecycle phase of the cluster.
Phase ClusterPhase `json:"phase,omitempty"`
// Capacity represents the total resources of the cluster
Capacity v1.ResourceList `json:"capacity,omitempty"`
// Allocatable represents the total resources of a cluster that are available for scheduling.
Allocatable v1.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
v1.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"`
}

View File

@ -0,0 +1,74 @@
/*
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 phaseTransitionAllowed(from, to federation.ClusterPhase) bool {
validPhaseTransition := map[federation.ClusterPhase][]federation.ClusterPhase{
federation.ClusterPending: {federation.ClusterRunning, federation.ClusterOffline, federation.ClusterTerminated},
federation.ClusterRunning: {federation.ClusterPending, federation.ClusterOffline, federation.ClusterTerminated},
federation.ClusterOffline: {federation.ClusterRunning, federation.ClusterTerminated},
federation.ClusterTerminated: {},
}
for _, allowedPhase := range validPhaseTransition[from] {
if to == allowedPhase {
return true
}
}
return false
}
func ValidateClusterStatusUpdate(cluster, oldCluster *federation.Cluster) field.ErrorList {
allErrs := validation.ValidateObjectMetaUpdate(&cluster.ObjectMeta, &oldCluster.ObjectMeta, field.NewPath("metadata"))
if !phaseTransitionAllowed(oldCluster.Status.Phase, cluster.Status.Phase) {
allErrs = append(allErrs, field.Invalid(field.NewPath("status", "phase"),
oldCluster.Status.Phase+" => "+cluster.Status.Phase, "cluster phase transition not allowed"))
}
return allErrs
}

View File

@ -0,0 +1,232 @@
/*
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{
Phase: federation.ClusterPending,
},
},
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{
Phase: federation.ClusterRunning,
},
},
},
}
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 phase transition not allowed": {
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{
Phase: federation.ClusterOffline,
},
},
update: federation.Cluster{
ObjectMeta: api.ObjectMeta{Name: "cluster-newname"},
Spec: federation.ClusterSpec{
ServerAddressByClientCIDRs: []unversioned.ServerAddressByClientCIDR{
{
ClientCIDR: "0.0.0.0/0",
ServerAddress: "localhost:8888",
},
},
},
Status: federation.ClusterStatus{
Phase: federation.ClusterPending,
},
},
},
}
for testName, errorCase := range errorCases {
errs := ValidateClusterStatusUpdate(&errorCase.update, &errorCase.old)
if len(errs) == 0 {
t.Errorf("expected failure: %s", testName)
}
}
}

View File

@ -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