github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/testapi/testapi.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 testapi provides a helper for retrieving the KUBE_TEST_API environment variable.
    18  package testapi
    19  
    20  import (
    21  	"fmt"
    22  	"os"
    23  	"strings"
    24  
    25  	"k8s.io/kubernetes/pkg/api"
    26  	_ "k8s.io/kubernetes/pkg/api/install"
    27  	"k8s.io/kubernetes/pkg/api/unversioned"
    28  	_ "k8s.io/kubernetes/pkg/apis/extensions/install"
    29  	_ "k8s.io/kubernetes/pkg/apis/metrics/install"
    30  
    31  	"k8s.io/kubernetes/pkg/api/latest"
    32  	"k8s.io/kubernetes/pkg/api/meta"
    33  	apiutil "k8s.io/kubernetes/pkg/api/util"
    34  	"k8s.io/kubernetes/pkg/runtime"
    35  )
    36  
    37  var (
    38  	Groups     = make(map[string]TestGroup)
    39  	Default    TestGroup
    40  	Extensions TestGroup
    41  )
    42  
    43  type TestGroup struct {
    44  	// Name of the group
    45  	Group string
    46  	// Version of the group Group under test
    47  	VersionUnderTest string
    48  	// Group and Version. In most cases equals to Group + "/" + VersionUnverTest
    49  	GroupVersionUnderTest string
    50  }
    51  
    52  func init() {
    53  	kubeTestAPI := os.Getenv("KUBE_TEST_API")
    54  	if kubeTestAPI != "" {
    55  		testGroupVersions := strings.Split(kubeTestAPI, ",")
    56  		for _, groupVersion := range testGroupVersions {
    57  			// TODO: caesarxuchao: the apiutil package is hacky, it will be replaced
    58  			// by a following PR.
    59  			Groups[apiutil.GetGroup(groupVersion)] =
    60  				TestGroup{apiutil.GetGroup(groupVersion), apiutil.GetVersion(groupVersion), groupVersion}
    61  		}
    62  	}
    63  
    64  	// TODO: caesarxuchao: we need a central place to store all available API
    65  	// groups and their metadata.
    66  	if _, ok := Groups[""]; !ok {
    67  		// TODO: The second latest.GroupOrDie("").Version will be latest.GroupVersion after we
    68  		// have multiple group support
    69  		Groups[""] = TestGroup{"", latest.GroupOrDie("").Version, latest.GroupOrDie("").GroupVersion}
    70  	}
    71  	if _, ok := Groups["extensions"]; !ok {
    72  		Groups["extensions"] = TestGroup{"extensions", latest.GroupOrDie("extensions").Version, latest.GroupOrDie("extensions").GroupVersion}
    73  	}
    74  
    75  	Default = Groups[""]
    76  	Extensions = Groups["extensions"]
    77  }
    78  
    79  // Version returns the API version to test against, as set by the KUBE_TEST_API env var.
    80  func (g TestGroup) Version() string {
    81  	return g.VersionUnderTest
    82  }
    83  
    84  // GroupAndVersion returns the API version to test against for a group, as set
    85  // by the KUBE_TEST_API env var.
    86  // Return value is in the form of "group/version".
    87  func (g TestGroup) GroupAndVersion() string {
    88  	return g.GroupVersionUnderTest
    89  }
    90  
    91  func (g TestGroup) GroupVersion() *unversioned.GroupVersion {
    92  	gv, err := unversioned.ParseGroupVersion(g.GroupVersionUnderTest)
    93  	if err != nil {
    94  		panic(err)
    95  	}
    96  	return &gv
    97  }
    98  
    99  // Codec returns the codec for the API version to test against, as set by the
   100  // KUBE_TEST_API env var.
   101  func (g TestGroup) Codec() runtime.Codec {
   102  	// TODO: caesarxuchao: Restructure the body once we have a central `latest`.
   103  	interfaces, err := latest.GroupOrDie(g.Group).InterfacesFor(g.GroupVersionUnderTest)
   104  	if err != nil {
   105  		panic(err)
   106  	}
   107  	return interfaces.Codec
   108  }
   109  
   110  // Converter returns the api.Scheme for the API version to test against, as set by the
   111  // KUBE_TEST_API env var.
   112  func (g TestGroup) Converter() runtime.ObjectConvertor {
   113  	// TODO: caesarxuchao: Restructure the body once we have a central `latest`.
   114  	if g.Group == "" {
   115  		interfaces, err := latest.GroupOrDie("").InterfacesFor(g.VersionUnderTest)
   116  		if err != nil {
   117  			panic(err)
   118  		}
   119  		return interfaces.ObjectConvertor
   120  	}
   121  	if g.Group == "extensions" {
   122  		interfaces, err := latest.GroupOrDie("extensions").InterfacesFor(g.VersionUnderTest)
   123  		if err != nil {
   124  			panic(err)
   125  		}
   126  		return interfaces.ObjectConvertor
   127  	}
   128  	panic(fmt.Errorf("cannot test group %s", g.Group))
   129  
   130  }
   131  
   132  // MetadataAccessor returns the MetadataAccessor for the API version to test against,
   133  // as set by the KUBE_TEST_API env var.
   134  func (g TestGroup) MetadataAccessor() meta.MetadataAccessor {
   135  	// TODO: caesarxuchao: Restructure the body once we have a central `latest`.
   136  	if g.Group == "" {
   137  		interfaces, err := latest.GroupOrDie("").InterfacesFor(g.VersionUnderTest)
   138  		if err != nil {
   139  			panic(err)
   140  		}
   141  		return interfaces.MetadataAccessor
   142  	}
   143  	if g.Group == "extensions" {
   144  		interfaces, err := latest.GroupOrDie("extensions").InterfacesFor(g.VersionUnderTest)
   145  		if err != nil {
   146  			panic(err)
   147  		}
   148  		return interfaces.MetadataAccessor
   149  	}
   150  	panic(fmt.Errorf("cannot test group %s", g.Group))
   151  }
   152  
   153  // SelfLink returns a self link that will appear to be for the version Version().
   154  // 'resource' should be the resource path, e.g. "pods" for the Pod type. 'name' should be
   155  // empty for lists.
   156  func (g TestGroup) SelfLink(resource, name string) string {
   157  	if g.Group == "" {
   158  		if name == "" {
   159  			return fmt.Sprintf("/api/%s/%s", g.Version(), resource)
   160  		}
   161  		return fmt.Sprintf("/api/%s/%s/%s", g.Version(), resource, name)
   162  	} else {
   163  		// TODO: will need a /apis prefix once we have proper multi-group
   164  		// support
   165  		if name == "" {
   166  			return fmt.Sprintf("/apis/%s/%s/%s", g.Group, g.Version(), resource)
   167  		}
   168  		return fmt.Sprintf("/apis/%s/%s/%s/%s", g.Group, g.Version(), resource, name)
   169  	}
   170  }
   171  
   172  // Returns the appropriate path for the given prefix (watch, proxy, redirect, etc), resource, namespace and name.
   173  // For ex, this is of the form:
   174  // /api/v1/watch/namespaces/foo/pods/pod0 for v1.
   175  func (g TestGroup) ResourcePathWithPrefix(prefix, resource, namespace, name string) string {
   176  	var path string
   177  	if len(g.Group) == 0 {
   178  		path = "/api/" + g.Version()
   179  	} else {
   180  		// TODO: switch back once we have proper multiple group support
   181  		// path = "/apis/" + g.Group + "/" + Version(group...)
   182  		path = "/apis/" + g.Group + "/" + g.Version()
   183  	}
   184  
   185  	if prefix != "" {
   186  		path = path + "/" + prefix
   187  	}
   188  	if namespace != "" {
   189  		path = path + "/namespaces/" + namespace
   190  	}
   191  	// Resource names are lower case.
   192  	resource = strings.ToLower(resource)
   193  	if resource != "" {
   194  		path = path + "/" + resource
   195  	}
   196  	if name != "" {
   197  		path = path + "/" + name
   198  	}
   199  	return path
   200  }
   201  
   202  // Returns the appropriate path for the given resource, namespace and name.
   203  // For example, this is of the form:
   204  // /api/v1/namespaces/foo/pods/pod0 for v1.
   205  func (g TestGroup) ResourcePath(resource, namespace, name string) string {
   206  	return g.ResourcePathWithPrefix("", resource, namespace, name)
   207  }
   208  
   209  func (g TestGroup) RESTMapper() meta.RESTMapper {
   210  	return latest.GroupOrDie(g.Group).RESTMapper
   211  }
   212  
   213  // Get codec based on runtime.Object
   214  func GetCodecForObject(obj runtime.Object) (runtime.Codec, error) {
   215  	_, kind, err := api.Scheme.ObjectVersionAndKind(obj)
   216  	if err != nil {
   217  		return nil, fmt.Errorf("unexpected encoding error: %v", err)
   218  	}
   219  	// TODO: caesarxuchao: we should detect which group an object belongs to
   220  	// by using the version returned by Schem.ObjectVersionAndKind() once we
   221  	// split the schemes for internal objects.
   222  	// TODO: caesarxuchao: we should add a map from kind to group in Scheme.
   223  	for _, group := range Groups {
   224  		if api.Scheme.Recognizes(group.GroupAndVersion(), kind) {
   225  			return group.Codec(), nil
   226  		}
   227  	}
   228  	// Codec used for unversioned types
   229  	if api.Scheme.Recognizes("", kind) {
   230  		return api.Codec, nil
   231  	}
   232  	return nil, fmt.Errorf("unexpected kind: %v", kind)
   233  }