Merge pull request #20513 from nikhiljindal/apiserverExampleTest

Adding test for apiserver example
This commit is contained in:
Nikhil Jindal 2016-02-04 11:28:58 -08:00
commit 59820827d4
17 changed files with 269 additions and 36 deletions

View File

@ -171,7 +171,10 @@ func startComponents(firstManifestURL, secondManifestURL string) (string, string
masterConfig.CacheTimeout = 2 * time.Second
// Create a master and install handlers into mux.
m := master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
glog.Fatalf("Error in bringing up the master: %v", err)
}
handler.delegate = m.Handler
// Scheduler

View File

@ -401,7 +401,10 @@ func Run(s *options.APIServer) error {
Tunneler: tunneler,
}
m := master.New(config)
m, err := master.New(config)
if err != nil {
return err
}
m.Run(s.ServerRunOptions)
return nil
}

View File

@ -39,6 +39,12 @@ API objects. Some relevant issues:
This code here is to examplify what it takes to write your own API server.
To start this example api server, run:
```
$ go run examples/apiserver/server/main.go
```
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/apiserver/README.md?pixel)]()

View File

@ -14,12 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package main
package apiserver
import (
"github.com/golang/glog"
"fmt"
"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testdata/apis/testgroup/v1"
testgroupetcd "k8s.io/kubernetes/examples/apiserver/rest"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/rest"
"k8s.io/kubernetes/pkg/apimachinery"
"k8s.io/kubernetes/pkg/apimachinery/registered"
@ -44,23 +46,27 @@ func newStorageDestinations(groupName string, groupMeta *apimachinery.GroupMeta)
return &storageDestinations, nil
}
func main() {
func Run() error {
config := genericapiserver.Config{
EnableIndex: true,
APIPrefix: "/api",
APIGroupPrefix: "/apis",
Serializer: api.Codecs,
}
s, err := genericapiserver.New(&config)
if err != nil {
return fmt.Errorf("Error in bringing up the server: %v", err)
}
s := genericapiserver.New(&config)
groupVersion := v1.SchemeGroupVersion
groupName := groupVersion.Group
groupMeta, err := registered.Group(groupName)
if err != nil {
glog.Fatalf("%v", err)
return fmt.Errorf("%v", err)
}
storageDestinations, err := newStorageDestinations(groupName, groupMeta)
if err != nil {
glog.Fatalf("Unable to init etcd: %v", err)
return fmt.Errorf("Unable to init etcd: %v", err)
}
restStorageMap := map[string]rest.Storage{
"testtypes": testgroupetcd.NewREST(storageDestinations.Get(groupName, "testtype"), s.StorageDecorator()),
@ -70,9 +76,12 @@ func main() {
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
groupVersion.Version: restStorageMap,
},
Scheme: api.Scheme,
NegotiatedSerializer: api.Codecs,
}
if err := s.InstallAPIGroups([]genericapiserver.APIGroupInfo{apiGroupInfo}); err != nil {
glog.Fatalf("Error in installing API: %v", err)
return fmt.Errorf("Error in installing API: %v", err)
}
s.Run(genericapiserver.NewServerRunOptions())
return nil
}

View File

@ -0,0 +1,108 @@
/*
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 apiserver
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"testing"
"time"
"k8s.io/kubernetes/cmd/libs/go2idl/client-gen/testdata/apis/testgroup/v1"
"github.com/stretchr/testify/assert"
"k8s.io/kubernetes/pkg/api/unversioned"
)
var serverIP = "http://localhost:8080"
var groupVersion = v1.SchemeGroupVersion
func TestRun(t *testing.T) {
go func() {
if err := Run(); err != nil {
t.Fatalf("Error in bringing up the server: %v", err)
}
}()
if err := waitForApiserverUp(); err != nil {
t.Fatalf("%v", err)
}
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()
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 testAPIGroup(t *testing.T) {
serverURL := serverIP + "/apis/testgroup"
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, groupVersion.Version)
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 testAPIResourceList(t *testing.T) {
serverURL := serverIP + "/apis/testgroup/v1"
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, groupVersion.Version)
assert.Equal(t, apiResourceList.GroupVersion, groupVersion.String())
assert.Equal(t, 1, len(apiResourceList.APIResources))
assert.Equal(t, apiResourceList.APIResources[0].Name, "testtypes")
assert.True(t, apiResourceList.APIResources[0].Namespaced)
}

View File

@ -0,0 +1,29 @@
/*
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 main
import (
"k8s.io/kubernetes/examples/apiserver"
"github.com/golang/glog"
)
func main() {
if err := apiserver.Run(); err != nil {
glog.Fatalf("Error in bringing up the server: %v", err)
}
}

View File

@ -379,7 +379,10 @@ func setDefaults(c *Config) {
// If the caller wants to add additional endpoints not using the GenericAPIServer's
// auth, then the caller should create a handler for those endpoints, which delegates the
// any unhandled paths to "Handler".
func New(c *Config) *GenericAPIServer {
func New(c *Config) (*GenericAPIServer, error) {
if c.Serializer == nil {
return nil, fmt.Errorf("Genericapiserver.New() called with config.Serializer == nil")
}
setDefaults(c)
s := &GenericAPIServer{
@ -433,7 +436,7 @@ func New(c *Config) *GenericAPIServer {
s.init(c)
return s
return s, nil
}
func (s *GenericAPIServer) NewRequestInfoResolver() *apiserver.RequestInfoResolver {

View File

@ -54,8 +54,12 @@ func TestNew(t *testing.T) {
config.ProxyDialer = func(network, addr string) (net.Conn, error) { return nil, nil }
config.ProxyTLSClientConfig = &tls.Config{}
config.Serializer = api.Codecs
s := New(&config)
s, err := New(&config)
if err != nil {
t.Fatalf("Error in bringing up the server: %v", err)
}
// Verify many of the variables match their config counterparts
assert.Equal(s.enableLogsSupport, config.EnableLogsSupport)
@ -96,7 +100,11 @@ func TestInstallAPIGroups(t *testing.T) {
config.APIGroupPrefix = "/apiGroupPrefix"
config.Serializer = api.Codecs
s := New(&config)
s, err := New(&config)
if err != nil {
t.Fatalf("Error in bringing up the server: %v", err)
}
apiGroupMeta := registered.GroupOrDie(api.GroupName)
extensionsGroupMeta := registered.GroupOrDie(extensions.GroupName)
apiGroupsInfo := []APIGroupInfo{

View File

@ -134,12 +134,15 @@ type thirdPartyEntry struct {
// Certain config fields will be set to a default value if unset.
// Certain config fields must be specified, including:
// KubeletClient
func New(c *Config) *Master {
func New(c *Config) (*Master, error) {
if c.KubeletClient == nil {
glog.Fatalf("Master.New() called with config.KubeletClient == nil")
return nil, fmt.Errorf("Master.New() called with config.KubeletClient == nil")
}
s := genericapiserver.New(c.Config)
s, err := genericapiserver.New(c.Config)
if err != nil {
return nil, err
}
m := &Master{
GenericAPIServer: s,
@ -158,7 +161,7 @@ func New(c *Config) *Master {
m.NewBootstrapController().Start()
}
return m
return m, nil
}
func resetMetrics(w http.ResponseWriter, req *http.Request) {

View File

@ -89,7 +89,11 @@ func newMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *ass
config.ProxyDialer = func(network, addr string) (net.Conn, error) { return nil, nil }
config.ProxyTLSClientConfig = &tls.Config{}
master := New(&config)
master, err := New(&config)
if err != nil {
t.Fatalf("Error in bringing up the master: %v", err)
}
return master, etcdserver, config, assert
}

View File

@ -45,7 +45,10 @@ func mustSetupScheduler() (schedulerConfigFactory *factory.ConfigFactory, destro
var m *master.Master
masterConfig := framework.NewIntegrationTestMasterConfig()
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
panic("error in brining up the master: " + err.Error())
}
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
m.Handler.ServeHTTP(w, req)
}))

View File

@ -394,7 +394,10 @@ func TestAuthModeAlwaysAllow(t *testing.T) {
// defer s.Close()
masterConfig := framework.NewIntegrationTestMasterConfig()
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("error in bringing up the master: %v", err)
}
transport := http.DefaultTransport
previousResourceVersion := make(map[string]float64)
@ -498,7 +501,10 @@ func TestAuthModeAlwaysDeny(t *testing.T) {
masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.Authorizer = apiserver.NewAlwaysDenyAuthorizer()
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("error in bringing up the master: %v", err)
}
transport := http.DefaultTransport
@ -555,7 +561,10 @@ func TestAliceNotForbiddenOrUnauthorized(t *testing.T) {
masterConfig.Authenticator = getTestTokenAuth()
masterConfig.Authorizer = allowAliceAuthorizer{}
masterConfig.AdmissionControl = admit.NewAlwaysAdmit()
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("error in bringing up the master: %v", err)
}
previousResourceVersion := make(map[string]float64)
transport := http.DefaultTransport
@ -630,7 +639,10 @@ func TestBobIsForbidden(t *testing.T) {
masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.Authenticator = getTestTokenAuth()
masterConfig.Authorizer = allowAliceAuthorizer{}
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("error in bringing up the master: %v", err)
}
transport := http.DefaultTransport
@ -679,7 +691,10 @@ func TestUnknownUserIsUnauthorized(t *testing.T) {
masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.Authenticator = getTestTokenAuth()
masterConfig.Authorizer = allowAliceAuthorizer{}
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("error in bringing up the master: %v", err)
}
transport := http.DefaultTransport
@ -753,7 +768,10 @@ func TestAuthorizationAttributeDetermination(t *testing.T) {
masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.Authenticator = getTestTokenAuth()
masterConfig.Authorizer = trackingAuthorizer
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("error in bringing up the master: %v", err)
}
transport := http.DefaultTransport
@ -822,7 +840,10 @@ func TestNamespaceAuthorization(t *testing.T) {
masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.Authenticator = getTestTokenAuth()
masterConfig.Authorizer = a
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("error in bringing up the master: %v", err)
}
previousResourceVersion := make(map[string]float64)
transport := http.DefaultTransport
@ -925,7 +946,10 @@ func TestKindAuthorization(t *testing.T) {
masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.Authenticator = getTestTokenAuth()
masterConfig.Authorizer = a
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("error in bringing up the master: %v", err)
}
previousResourceVersion := make(map[string]float64)
transport := http.DefaultTransport
@ -1016,7 +1040,10 @@ func TestReadOnlyAuthorization(t *testing.T) {
masterConfig.Authenticator = getTestTokenAuth()
masterConfig.Authorizer = a
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("error in bringing up the master: %v", err)
}
transport := http.DefaultTransport

View File

@ -195,7 +195,10 @@ func TestSchedulerExtender(t *testing.T) {
// defer s.Close()
masterConfig := framework.NewIntegrationTestMasterConfig()
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("error in bringing up the master: %v", err)
}
restClient := client.NewOrDie(&client.Config{Host: s.URL, ContentConfig: client.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}})

View File

@ -135,7 +135,11 @@ func startMasterOrDie(masterConfig *master.Config) (*master.Master, *httptest.Se
masterConfig.EnableProfiling = true
masterConfig.EnableSwaggerSupport = true
}
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
glog.Fatalf("error in bringing up the master: %v", err)
}
return m, s
}
@ -289,7 +293,11 @@ func StartPods(numPods int, host string, restClient *client.Client) error {
func RunAMaster(t *testing.T) (*master.Master, *httptest.Server) {
masterConfig := NewMasterConfig()
masterConfig.EnableProfiling = true
m := master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
// TODO: Return error.
glog.Fatalf("error in bringing up the master: %v", err)
}
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
m.Handler.ServeHTTP(w, req)

View File

@ -62,7 +62,10 @@ func TestUnschedulableNodes(t *testing.T) {
// defer s.Close()
masterConfig := framework.NewIntegrationTestMasterConfig()
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("Error in bringing up the master: %v", err)
}
restClient := client.NewOrDie(&client.Config{Host: s.URL, ContentConfig: client.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}})
@ -286,7 +289,11 @@ func TestMultiScheduler(t *testing.T) {
// defer s.Close()
masterConfig := framework.NewIntegrationTestMasterConfig()
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("Error in bringing up the master: %v", err)
}
/*
This integration tests the multi-scheduler feature in the following way:
1. create a default scheduler
@ -461,7 +468,10 @@ func TestAllocatable(t *testing.T) {
defer s.Close()
masterConfig := framework.NewIntegrationTestMasterConfig()
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("Error in bringing up the master: %v", err)
}
// 1. create and start default-scheduler
restClient := client.NewOrDie(&client.Config{Host: s.URL, ContentConfig: client.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}})

View File

@ -53,7 +53,10 @@ func TestSecrets(t *testing.T) {
// defer s.Close()
masterConfig := framework.NewIntegrationTestMasterConfig()
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("Error in bringing up the master: %v", err)
}
framework.DeleteAllEtcdKeys()
client := client.NewOrDie(&client.Config{Host: s.URL, ContentConfig: client.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}})

View File

@ -409,7 +409,10 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, client.C
masterConfig.AdmissionControl = serviceAccountAdmission
// Create a master and install handlers into mux.
m = master.New(masterConfig)
m, err := master.New(masterConfig)
if err != nil {
t.Fatalf("Error in bringing up the master: %v", err)
}
// Start the service account and service account token controllers
tokenController := serviceaccountcontroller.NewTokensController(rootClientset, serviceaccountcontroller.TokensControllerOptions{TokenGenerator: serviceaccount.JWTTokenGenerator(serviceAccountKey)})