Integration test on master, not just apiserver.

Moved code from cmd/apiserver to pkg/master.

test/integration/client_test made to use a master object,
instead of an apiserver.Handle.

Subsequent PRs will move more handler-installation into
pkg/master, with the goal that every http.Handler of a
standalone apiserver process can also be tested
in a "testing"-style go test.

In particular, a subsequent PR will test
authorization.
This commit is contained in:
Eric Tune 2014-10-23 13:56:18 -07:00
parent dc7e3d6601
commit 40a5ca034d
5 changed files with 58 additions and 45 deletions

View File

@ -38,7 +38,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/master" "github.com/GoogleCloudPlatform/kubernetes/pkg/master"
"github.com/GoogleCloudPlatform/kubernetes/pkg/resources" "github.com/GoogleCloudPlatform/kubernetes/pkg/resources"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/ui"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/version/verflag" "github.com/GoogleCloudPlatform/kubernetes/pkg/version/verflag"
@ -188,7 +187,8 @@ func main() {
} }
n := net.IPNet(portalNet) n := net.IPNet(portalNet)
m := master.New(&master.Config{ mux := http.NewServeMux()
master.New(&master.Config{
Client: client, Client: client,
Cloud: cloud, Cloud: cloud,
EtcdHelper: helper, EtcdHelper: helper,
@ -204,18 +204,13 @@ func main() {
resources.Memory: util.NewIntOrStringFromInt(*nodeMemory), resources.Memory: util.NewIntOrStringFromInt(*nodeMemory),
}, },
}, },
PortalNet: &n, PortalNet: &n,
Mux: mux,
EnableLogsSupport: *enableLogsSupport,
EnableUISupport: true,
APIPrefix: *apiPrefix,
}) })
mux := http.NewServeMux()
apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(mux, *apiPrefix+"/v1beta1")
apiserver.NewAPIGroup(m.API_v1beta2()).InstallREST(mux, *apiPrefix+"/v1beta2")
apiserver.InstallSupport(mux)
if *enableLogsSupport {
apiserver.InstallLogsSupport(mux)
}
ui.InstallSupport(mux)
handler := http.Handler(mux) handler := http.Handler(mux)
if len(corsAllowedOriginList) > 0 { if len(corsAllowedOriginList) > 0 {

View File

@ -34,7 +34,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/controller" "github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
"github.com/GoogleCloudPlatform/kubernetes/pkg/health" "github.com/GoogleCloudPlatform/kubernetes/pkg/health"
@ -132,17 +131,18 @@ func startComponents(manifestURL string) (apiServerURL string) {
if err != nil { if err != nil {
glog.Fatalf("Unable to parse CIDR: %v", err) glog.Fatalf("Unable to parse CIDR: %v", err)
} }
m := master.New(&master.Config{
Client: cl,
EtcdHelper: helper,
Minions: machineList,
KubeletClient: fakeKubeletClient{},
PortalNet: portalNet,
})
mux := http.NewServeMux() mux := http.NewServeMux()
apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(mux, "/api/v1beta1") // Create a master and install handlers into mux.
apiserver.NewAPIGroup(m.API_v1beta2()).InstallREST(mux, "/api/v1beta2") master.New(&master.Config{
apiserver.InstallSupport(mux) Client: cl,
EtcdHelper: helper,
Minions: machineList,
KubeletClient: fakeKubeletClient{},
PortalNet: portalNet,
Mux: mux,
EnableLogsSupport: false,
APIPrefix: "/api",
})
handler.delegate = mux handler.delegate = mux
// Scheduler // Scheduler

View File

@ -30,7 +30,7 @@ import (
) )
// mux is an object that can register http handlers. // mux is an object that can register http handlers.
type mux interface { type Mux interface {
Handle(pattern string, handler http.Handler) Handle(pattern string, handler http.Handler)
HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
} }
@ -87,7 +87,7 @@ func NewAPIGroup(storage map[string]RESTStorage, codec runtime.Codec, canonicalP
// InstallREST registers the REST handlers (storage, watch, and operations) into a mux. // InstallREST registers the REST handlers (storage, watch, and operations) into a mux.
// It is expected that the provided prefix will serve all operations. Path MUST NOT end // It is expected that the provided prefix will serve all operations. Path MUST NOT end
// in a slash. // in a slash.
func (g *APIGroup) InstallREST(mux mux, paths ...string) { func (g *APIGroup) InstallREST(mux Mux, paths ...string) {
restHandler := &g.handler restHandler := &g.handler
watchHandler := &WatchHandler{g.handler.storage, g.handler.codec} watchHandler := &WatchHandler{g.handler.storage, g.handler.codec}
redirectHandler := &RedirectHandler{g.handler.storage, g.handler.codec} redirectHandler := &RedirectHandler{g.handler.storage, g.handler.codec}
@ -119,14 +119,14 @@ func (g *APIGroup) InstallREST(mux mux, paths ...string) {
} }
// InstallSupport registers the APIServer support functions into a mux. // InstallSupport registers the APIServer support functions into a mux.
func InstallSupport(mux mux) { func InstallSupport(mux Mux) {
healthz.InstallHandler(mux) healthz.InstallHandler(mux)
mux.HandleFunc("/version", handleVersion) mux.HandleFunc("/version", handleVersion)
mux.HandleFunc("/", handleIndex) mux.HandleFunc("/", handleIndex)
} }
// InstallLogsSupport registers the APIServer log support function into a mux. // InstallLogsSupport registers the APIServer log support function into a mux.
func InstallLogsSupport(mux mux) { func InstallLogsSupport(mux Mux) {
mux.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log/")))) mux.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log/"))))
} }

View File

@ -39,6 +39,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/service" "github.com/GoogleCloudPlatform/kubernetes/pkg/registry/service"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/tools" "github.com/GoogleCloudPlatform/kubernetes/pkg/tools"
"github.com/GoogleCloudPlatform/kubernetes/pkg/ui"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
) )
@ -55,6 +56,10 @@ type Config struct {
KubeletClient client.KubeletClient KubeletClient client.KubeletClient
NodeResources api.NodeResources NodeResources api.NodeResources
PortalNet *net.IPNet PortalNet *net.IPNet
Mux apiserver.Mux
EnableLogsSupport bool
EnableUISupport bool
APIPrefix string
} }
// Master contains state for a Kubernetes cluster master/api server. // Master contains state for a Kubernetes cluster master/api server.
@ -69,6 +74,10 @@ type Master struct {
storage map[string]apiserver.RESTStorage storage map[string]apiserver.RESTStorage
client *client.Client client *client.Client
portalNet *net.IPNet portalNet *net.IPNet
mux apiserver.Mux
enableLogsSupport bool
enableUISupport bool
apiPrefix string
} }
// NewEtcdHelper returns an EtcdHelper for the provided arguments or an error if the version // NewEtcdHelper returns an EtcdHelper for the provided arguments or an error if the version
@ -101,6 +110,10 @@ func New(c *Config) *Master {
minionRegistry: minionRegistry, minionRegistry: minionRegistry,
client: c.Client, client: c.Client,
portalNet: c.PortalNet, portalNet: c.PortalNet,
mux: c.Mux,
enableLogsSupport: c.EnableLogsSupport,
enableUISupport: c.EnableUISupport,
apiPrefix: c.APIPrefix,
} }
m.init(c) m.init(c)
return m return m
@ -148,6 +161,15 @@ func (m *Master) init(c *Config) {
// TODO: should appear only in scheduler API group. // TODO: should appear only in scheduler API group.
"bindings": binding.NewREST(m.bindingRegistry), "bindings": binding.NewREST(m.bindingRegistry),
} }
apiserver.NewAPIGroup(m.API_v1beta1()).InstallREST(m.mux, c.APIPrefix+"/v1beta1")
apiserver.NewAPIGroup(m.API_v1beta2()).InstallREST(m.mux, c.APIPrefix+"/v1beta2")
apiserver.InstallSupport(m.mux)
if c.EnableLogsSupport {
apiserver.InstallLogsSupport(m.mux)
}
if c.EnableUISupport {
ui.InstallSupport(m.mux)
}
} }
// API_v1beta1 returns the resources and codec for API version v1beta1. // API_v1beta1 returns the resources and codec for API version v1beta1.

View File

@ -19,17 +19,15 @@ limitations under the License.
package integration package integration
import ( import (
"fmt" "net/http"
"net/http/httptest" "net/http/httptest"
"reflect" "reflect"
"testing" "testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client" "github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels" "github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/master" "github.com/GoogleCloudPlatform/kubernetes/pkg/master"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/version" "github.com/GoogleCloudPlatform/kubernetes/pkg/version"
) )
@ -42,26 +40,24 @@ func TestClient(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
m := master.New(&master.Config{ mux := http.NewServeMux()
EtcdHelper: helper, master.New(&master.Config{
EtcdHelper: helper,
Mux: mux,
EnableLogsSupport: false,
EnableUISupport: false,
APIPrefix: "/api",
}) })
s1, c1, loc1, sl1 := m.API_v1beta1()
s2, c2, loc2, sl2 := m.API_v1beta2()
testCases := map[string]struct { s := httptest.NewServer(mux)
Storage map[string]apiserver.RESTStorage
Codec runtime.Codec testCases := []string{
location string "v1beta1",
selfLinker runtime.SelfLinker "v1beta2",
}{
"v1beta1": {s1, c1, loc1, sl1},
"v1beta2": {s2, c2, loc2, sl2},
} }
for _, apiVersion := range testCases {
for apiVersion, values := range testCases {
ns := api.NamespaceDefault ns := api.NamespaceDefault
deleteAllEtcdKeys() deleteAllEtcdKeys()
s := httptest.NewServer(apiserver.Handle(values.Storage, values.Codec, fmt.Sprintf("/api/%s/", apiVersion), values.selfLinker))
client := client.NewOrDie(&client.Config{Host: s.URL, Version: apiVersion}) client := client.NewOrDie(&client.Config{Host: s.URL, Version: apiVersion})
info, err := client.ServerVersion() info, err := client.ServerVersion()