github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/install/install.go (about)

     1  /*
     2  Copyright 2014 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // Package install installs the v1 monolithic api, making it available as an
    18  // option to all of the API encoding/decoding machinery.
    19  package install
    20  
    21  import (
    22  	"fmt"
    23  
    24  	"github.com/golang/glog"
    25  
    26  	"k8s.io/kubernetes/pkg/api"
    27  	"k8s.io/kubernetes/pkg/api/meta"
    28  	"k8s.io/kubernetes/pkg/api/unversioned"
    29  	"k8s.io/kubernetes/pkg/api/v1"
    30  	"k8s.io/kubernetes/pkg/apimachinery"
    31  	"k8s.io/kubernetes/pkg/apimachinery/registered"
    32  	"k8s.io/kubernetes/pkg/conversion"
    33  	"k8s.io/kubernetes/pkg/runtime"
    34  	"k8s.io/kubernetes/pkg/util/sets"
    35  )
    36  
    37  const importPrefix = "k8s.io/kubernetes/pkg/api"
    38  
    39  var accessor = meta.NewAccessor()
    40  
    41  // availableVersions lists all known external versions for this group from most preferred to least preferred
    42  var availableVersions = []unversioned.GroupVersion{v1.SchemeGroupVersion}
    43  
    44  func init() {
    45  	registered.RegisterVersions(availableVersions)
    46  	externalVersions := []unversioned.GroupVersion{}
    47  	for _, v := range availableVersions {
    48  		if registered.IsAllowedVersion(v) {
    49  			externalVersions = append(externalVersions, v)
    50  		}
    51  	}
    52  	if len(externalVersions) == 0 {
    53  		glog.V(4).Infof("No version is registered for group %v", api.GroupName)
    54  		return
    55  	}
    56  
    57  	if err := registered.EnableVersions(externalVersions...); err != nil {
    58  		glog.V(4).Infof("%v", err)
    59  		return
    60  	}
    61  	if err := enableVersions(externalVersions); err != nil {
    62  		glog.V(4).Infof("%v", err)
    63  		return
    64  	}
    65  }
    66  
    67  // TODO: enableVersions should be centralized rather than spread in each API
    68  // group.
    69  // We can combine registered.RegisterVersions, registered.EnableVersions and
    70  // registered.RegisterGroup once we have moved enableVersions there.
    71  func enableVersions(externalVersions []unversioned.GroupVersion) error {
    72  	addVersionsToScheme(externalVersions...)
    73  	preferredExternalVersion := externalVersions[0]
    74  
    75  	groupMeta := apimachinery.GroupMeta{
    76  		GroupVersion:  preferredExternalVersion,
    77  		GroupVersions: externalVersions,
    78  		RESTMapper:    newRESTMapper(externalVersions),
    79  		SelfLinker:    runtime.SelfLinker(accessor),
    80  		InterfacesFor: interfacesFor,
    81  	}
    82  
    83  	if err := registered.RegisterGroup(groupMeta); err != nil {
    84  		return err
    85  	}
    86  	api.RegisterRESTMapper(groupMeta.RESTMapper)
    87  	return nil
    88  }
    89  
    90  // userResources is a group of resources mostly used by a kubectl user
    91  var userResources = []string{"rc", "svc", "pods", "pvc"}
    92  
    93  func newRESTMapper(externalVersions []unversioned.GroupVersion) meta.RESTMapper {
    94  	// the list of kinds that are scoped at the root of the api hierarchy
    95  	// if a kind is not enumerated here, it is assumed to have a namespace scope
    96  	rootScoped := sets.NewString(
    97  		"Node",
    98  		"Namespace",
    99  		"PersistentVolume",
   100  		"ComponentStatus",
   101  	)
   102  
   103  	// these kinds should be excluded from the list of resources
   104  	ignoredKinds := sets.NewString(
   105  		"ListOptions",
   106  		"DeleteOptions",
   107  		"Status",
   108  		"PodLogOptions",
   109  		"PodExecOptions",
   110  		"PodAttachOptions",
   111  		"PodProxyOptions",
   112  		"NodeProxyOptions",
   113  		"ServiceProxyOptions",
   114  		"ThirdPartyResource",
   115  		"ThirdPartyResourceData",
   116  		"ThirdPartyResourceList")
   117  
   118  	mapper := api.NewDefaultRESTMapper(externalVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped)
   119  	// setup aliases for groups of resources
   120  	mapper.AddResourceAlias("all", userResources...)
   121  
   122  	return mapper
   123  }
   124  
   125  // InterfacesFor returns the default Codec and ResourceVersioner for a given version
   126  // string, or an error if the version is not known.
   127  func interfacesFor(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
   128  	switch version {
   129  	case v1.SchemeGroupVersion:
   130  		return &meta.VersionInterfaces{
   131  			ObjectConvertor:  api.Scheme,
   132  			MetadataAccessor: accessor,
   133  		}, nil
   134  	default:
   135  		g, _ := registered.Group(api.GroupName)
   136  		return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, g.GroupVersions)
   137  	}
   138  }
   139  
   140  func addVersionsToScheme(externalVersions ...unversioned.GroupVersion) {
   141  	// add the internal version to Scheme
   142  	api.AddToScheme(api.Scheme)
   143  	// add the enabled external versions to Scheme
   144  	for _, v := range externalVersions {
   145  		if !registered.IsEnabledVersion(v) {
   146  			glog.Errorf("Version %s is not enabled, so it will not be added to the Scheme.", v)
   147  			continue
   148  		}
   149  		switch v {
   150  		case v1.SchemeGroupVersion:
   151  			v1.AddToScheme(api.Scheme)
   152  		}
   153  	}
   154  
   155  	// This is a "fast-path" that avoids reflection for common types. It focuses on the objects that are
   156  	// converted the most in the cluster.
   157  	// TODO: generate one of these for every external API group - this is to prove the impact
   158  	api.Scheme.AddGenericConversionFunc(func(objA, objB interface{}, s conversion.Scope) (bool, error) {
   159  		switch a := objA.(type) {
   160  		case *v1.Pod:
   161  			switch b := objB.(type) {
   162  			case *api.Pod:
   163  				return true, v1.Convert_v1_Pod_To_api_Pod(a, b, s)
   164  			}
   165  		case *api.Pod:
   166  			switch b := objB.(type) {
   167  			case *v1.Pod:
   168  				return true, v1.Convert_api_Pod_To_v1_Pod(a, b, s)
   169  			}
   170  
   171  		case *v1.Event:
   172  			switch b := objB.(type) {
   173  			case *api.Event:
   174  				return true, v1.Convert_v1_Event_To_api_Event(a, b, s)
   175  			}
   176  		case *api.Event:
   177  			switch b := objB.(type) {
   178  			case *v1.Event:
   179  				return true, v1.Convert_api_Event_To_v1_Event(a, b, s)
   180  			}
   181  
   182  		case *v1.ReplicationController:
   183  			switch b := objB.(type) {
   184  			case *api.ReplicationController:
   185  				return true, v1.Convert_v1_ReplicationController_To_api_ReplicationController(a, b, s)
   186  			}
   187  		case *api.ReplicationController:
   188  			switch b := objB.(type) {
   189  			case *v1.ReplicationController:
   190  				return true, v1.Convert_api_ReplicationController_To_v1_ReplicationController(a, b, s)
   191  			}
   192  
   193  		case *v1.Node:
   194  			switch b := objB.(type) {
   195  			case *api.Node:
   196  				return true, v1.Convert_v1_Node_To_api_Node(a, b, s)
   197  			}
   198  		case *api.Node:
   199  			switch b := objB.(type) {
   200  			case *v1.Node:
   201  				return true, v1.Convert_api_Node_To_v1_Node(a, b, s)
   202  			}
   203  
   204  		case *v1.Namespace:
   205  			switch b := objB.(type) {
   206  			case *api.Namespace:
   207  				return true, v1.Convert_v1_Namespace_To_api_Namespace(a, b, s)
   208  			}
   209  		case *api.Namespace:
   210  			switch b := objB.(type) {
   211  			case *v1.Namespace:
   212  				return true, v1.Convert_api_Namespace_To_v1_Namespace(a, b, s)
   213  			}
   214  
   215  		case *v1.Service:
   216  			switch b := objB.(type) {
   217  			case *api.Service:
   218  				return true, v1.Convert_v1_Service_To_api_Service(a, b, s)
   219  			}
   220  		case *api.Service:
   221  			switch b := objB.(type) {
   222  			case *v1.Service:
   223  				return true, v1.Convert_api_Service_To_v1_Service(a, b, s)
   224  			}
   225  
   226  		case *v1.Endpoints:
   227  			switch b := objB.(type) {
   228  			case *api.Endpoints:
   229  				return true, v1.Convert_v1_Endpoints_To_api_Endpoints(a, b, s)
   230  			}
   231  		case *api.Endpoints:
   232  			switch b := objB.(type) {
   233  			case *v1.Endpoints:
   234  				return true, v1.Convert_api_Endpoints_To_v1_Endpoints(a, b, s)
   235  			}
   236  		}
   237  		return false, nil
   238  	})
   239  }