Updating test/integration to use testapi.Version everywhere
This commit is contained in:
@@ -20,6 +20,7 @@ package testapi
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||||
@@ -76,14 +77,21 @@ func SelfLink(resource, name string) string {
|
|||||||
return fmt.Sprintf("/api/%s/%s/%s", Version(), resource, name)
|
return fmt.Sprintf("/api/%s/%s/%s", Version(), resource, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the appropriate path for the given resource, namespace and name.
|
// Returns the appropriate path for the given prefix (watch, proxy, redirect, etc), resource, namespace and name.
|
||||||
// For ex, this is of the form:
|
// For ex, this is of the form:
|
||||||
// /api/v1beta1/pods/pod0 for v1beta1 and
|
// /api/v1beta1/watch/pods/pod0 for v1beta1 and
|
||||||
// /api/v1beta3/namespaces/foo/pods/pod0 for v1beta3.
|
// /api/v1beta3/watch/namespaces/foo/pods/pod0 for v1beta3.
|
||||||
func ResourcePath(resource, namespace, name string) string {
|
func ResourcePathWithPrefix(prefix, resource, namespace, name string) string {
|
||||||
path := "/api/" + Version()
|
path := "/api/" + Version()
|
||||||
if !api.PreV1Beta3(Version()) && namespace != "" {
|
if prefix != "" {
|
||||||
path = path + "/namespaces/" + namespace
|
path = path + "/" + prefix
|
||||||
|
}
|
||||||
|
if !api.PreV1Beta3(Version()) {
|
||||||
|
if namespace != "" {
|
||||||
|
path = path + "/namespaces/" + namespace
|
||||||
|
}
|
||||||
|
// Resource names in v1beta3 are lower case.
|
||||||
|
resource = strings.ToLower(resource)
|
||||||
}
|
}
|
||||||
if resource != "" {
|
if resource != "" {
|
||||||
path = path + "/" + resource
|
path = path + "/" + resource
|
||||||
@@ -94,6 +102,14 @@ func ResourcePath(resource, namespace, name string) string {
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the appropriate path for the given resource, namespace and name.
|
||||||
|
// For ex, this is of the form:
|
||||||
|
// /api/v1beta1/pods/pod0 for v1beta1 and
|
||||||
|
// /api/v1beta3/namespaces/foo/pods/pod0 for v1beta3.
|
||||||
|
func ResourcePath(resource, namespace, name string) string {
|
||||||
|
return ResourcePathWithPrefix("", resource, namespace, name)
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the appropriate path along with the query params for the given resource, namespace and name.
|
// Returns the appropriate path along with the query params for the given resource, namespace and name.
|
||||||
// For ex, this is of the form:
|
// For ex, this is of the form:
|
||||||
// /api/v1beta1/pods/pod0?namespace=foo for v1beta1 and
|
// /api/v1beta1/pods/pod0?namespace=foo for v1beta1 and
|
||||||
@@ -101,7 +117,7 @@ func ResourcePath(resource, namespace, name string) string {
|
|||||||
func ResourcePathWithQueryParams(resource, namespace, name string) string {
|
func ResourcePathWithQueryParams(resource, namespace, name string) string {
|
||||||
path := ResourcePath(resource, namespace, name)
|
path := ResourcePath(resource, namespace, name)
|
||||||
// Add namespace as query param for pre v1beta3.
|
// Add namespace as query param for pre v1beta3.
|
||||||
if api.PreV1Beta3(Version()) {
|
if api.PreV1Beta3(Version()) && namespace != "" {
|
||||||
path = path + "?namespace=" + namespace
|
path = path + "?namespace=" + namespace
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
|
169
pkg/api/testapi/testapi_test.go
Normal file
169
pkg/api/testapi/testapi_test.go
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015 Google Inc. 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 testapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestResourcePathWithPrefixForV1Beta3(t *testing.T) {
|
||||||
|
if Version() != "v1beta3" {
|
||||||
|
// Skip the test if we are not testing v1beta3.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
prefix string
|
||||||
|
resource string
|
||||||
|
namespace string
|
||||||
|
name string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"prefix", "resource", "mynamespace", "myresource", "/api/v1beta3/prefix/namespaces/mynamespace/resource/myresource"},
|
||||||
|
{"prefix", "resource", "", "myresource", "/api/v1beta3/prefix/resource/myresource"},
|
||||||
|
{"prefix", "resource", "mynamespace", "", "/api/v1beta3/prefix/namespaces/mynamespace/resource"},
|
||||||
|
{"prefix", "resource", "", "", "/api/v1beta3/prefix/resource"},
|
||||||
|
{"", "resource", "mynamespace", "myresource", "/api/v1beta3/namespaces/mynamespace/resource/myresource"},
|
||||||
|
}
|
||||||
|
for _, item := range testCases {
|
||||||
|
if actual := ResourcePathWithPrefix(item.prefix, item.resource, item.namespace, item.name); actual != item.expected {
|
||||||
|
t.Errorf("Expected: %s, got: %s for prefix: %s, resource: %s, namespace: %s and name: %s", item.expected, actual, item.prefix, item.resource, item.namespace, item.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResourcePathWithPrefixForV1Beta1(t *testing.T) {
|
||||||
|
if Version() != "v1beta1" {
|
||||||
|
// Skip the test if we are not testing v1beta1.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
prefix string
|
||||||
|
resource string
|
||||||
|
namespace string
|
||||||
|
name string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"prefix", "resource", "mynamespace", "myresource", "/api/v1beta1/prefix/resource/myresource"},
|
||||||
|
{"prefix", "resource", "", "myresource", "/api/v1beta1/prefix/resource/myresource"},
|
||||||
|
{"prefix", "resource", "mynamespace", "", "/api/v1beta1/prefix/resource"},
|
||||||
|
{"prefix", "resource", "", "", "/api/v1beta1/prefix/resource"},
|
||||||
|
{"", "resource", "mynamespace", "myresource", "/api/v1beta1/resource/myresource"},
|
||||||
|
}
|
||||||
|
for _, item := range testCases {
|
||||||
|
if actual := ResourcePathWithPrefix(item.prefix, item.resource, item.namespace, item.name); actual != item.expected {
|
||||||
|
t.Errorf("Expected: %s, got: %s for prefix: %s, resource: %s, namespace: %s and name: %s", item.expected, actual, item.prefix, item.resource, item.namespace, item.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResourcePathForV1Beta3(t *testing.T) {
|
||||||
|
if Version() != "v1beta3" {
|
||||||
|
// Skip the test if we are not testing v1beta3.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
resource string
|
||||||
|
namespace string
|
||||||
|
name string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"resource", "mynamespace", "myresource", "/api/v1beta3/namespaces/mynamespace/resource/myresource"},
|
||||||
|
{"resource", "", "myresource", "/api/v1beta3/resource/myresource"},
|
||||||
|
{"resource", "mynamespace", "", "/api/v1beta3/namespaces/mynamespace/resource"},
|
||||||
|
{"resource", "", "", "/api/v1beta3/resource"},
|
||||||
|
}
|
||||||
|
for _, item := range testCases {
|
||||||
|
if actual := ResourcePath(item.resource, item.namespace, item.name); actual != item.expected {
|
||||||
|
t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResourcePathForV1Beta1(t *testing.T) {
|
||||||
|
if Version() != "v1beta1" {
|
||||||
|
// Skip the test if we are not testing v1beta1.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
resource string
|
||||||
|
namespace string
|
||||||
|
name string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"resource", "mynamespace", "myresource", "/api/v1beta1/resource/myresource"},
|
||||||
|
{"resource", "", "myresource", "/api/v1beta1/resource/myresource"},
|
||||||
|
{"resource", "mynamespace", "", "/api/v1beta1/resource"},
|
||||||
|
{"resource", "", "", "/api/v1beta1/resource"},
|
||||||
|
}
|
||||||
|
for _, item := range testCases {
|
||||||
|
if actual := ResourcePath(item.resource, item.namespace, item.name); actual != item.expected {
|
||||||
|
t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResourcePathWithQueryParamsForV1Beta3(t *testing.T) {
|
||||||
|
if Version() != "v1beta3" {
|
||||||
|
// Skip the test if we are not testing v1beta3.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
resource string
|
||||||
|
namespace string
|
||||||
|
name string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"resource", "mynamespace", "myresource", "/api/v1beta3/namespaces/mynamespace/resource/myresource"},
|
||||||
|
{"resource", "", "myresource", "/api/v1beta3/resource/myresource"},
|
||||||
|
{"resource", "mynamespace", "", "/api/v1beta3/namespaces/mynamespace/resource"},
|
||||||
|
{"resource", "", "", "/api/v1beta3/resource"},
|
||||||
|
}
|
||||||
|
for _, item := range testCases {
|
||||||
|
if actual := ResourcePathWithQueryParams(item.resource, item.namespace, item.name); actual != item.expected {
|
||||||
|
t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResourcePathWithQueryParamsForV1Beta1(t *testing.T) {
|
||||||
|
if Version() != "v1beta1" {
|
||||||
|
// Skip the test if we are not testing v1beta1.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
resource string
|
||||||
|
namespace string
|
||||||
|
name string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"resource", "mynamespace", "myresource", "/api/v1beta1/resource/myresource?namespace=mynamespace"},
|
||||||
|
{"resource", "", "myresource", "/api/v1beta1/resource/myresource"},
|
||||||
|
{"resource", "mynamespace", "", "/api/v1beta1/resource?namespace=mynamespace"},
|
||||||
|
{"resource", "", "", "/api/v1beta1/resource"},
|
||||||
|
}
|
||||||
|
for _, item := range testCases {
|
||||||
|
if actual := ResourcePathWithQueryParams(item.resource, item.namespace, item.name); actual != item.expected {
|
||||||
|
t.Errorf("Expected: %s, got: %s for resource: %s, namespace: %s and name: %s", item.expected, actual, item.resource, item.namespace, item.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -30,10 +30,14 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/auth/authenticator"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/auth/authenticator"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/auth/authenticator/bearertoken"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/auth/authenticator/bearertoken"
|
||||||
@@ -46,8 +50,15 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/auth/authenticator/token/tokentest"
|
"github.com/GoogleCloudPlatform/kubernetes/plugin/pkg/auth/authenticator/token/tokentest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var nodeResourceName string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
requireEtcd()
|
requireEtcd()
|
||||||
|
if api.PreV1Beta3(testapi.Version()) {
|
||||||
|
nodeResourceName = "minions"
|
||||||
|
} else {
|
||||||
|
nodeResourceName = "nodes"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -63,114 +74,176 @@ func getTestTokenAuth() authenticator.Request {
|
|||||||
return bearertoken.New(tokenAuthenticator)
|
return bearertoken.New(tokenAuthenticator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func path(resource, namespace, name string) string {
|
||||||
|
return testapi.ResourcePath(resource, namespace, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pathWithQuery(resource, namespace, name string) string {
|
||||||
|
return testapi.ResourcePathWithQueryParams(resource, namespace, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pathWithPrefix(prefix, resource, namespace, name string) string {
|
||||||
|
return testapi.ResourcePathWithPrefix(prefix, resource, namespace, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeoutPath(resource, namespace, name string) string {
|
||||||
|
return addTimeoutFlag(testapi.ResourcePath(resource, namespace, name))
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeoutPathWithQuery(resource, namespace, name string) string {
|
||||||
|
return addTimeoutFlag(testapi.ResourcePathWithQueryParams(resource, namespace, name))
|
||||||
|
}
|
||||||
|
|
||||||
// Bodies for requests used in subsequent tests.
|
// Bodies for requests used in subsequent tests.
|
||||||
var aPod string = `
|
var aPod string = `
|
||||||
{
|
{
|
||||||
"kind": "Pod",
|
"kind": "Pod",
|
||||||
"apiVersion": "v1beta1",
|
"apiVersion": "v1beta3",
|
||||||
"id": "a",
|
"metadata": {
|
||||||
"desiredState": {
|
"name": "a",
|
||||||
"manifest": {
|
"creationTimestamp": null%s
|
||||||
"version": "v1beta1",
|
},
|
||||||
"id": "a",
|
"spec": {
|
||||||
"containers": [{ "name": "foo", "image": "bar/foo" }]
|
"containers": [
|
||||||
}
|
{
|
||||||
}%s
|
"name": "foo",
|
||||||
|
"image": "bar/foo"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
var aRC string = `
|
var aRC string = `
|
||||||
{
|
{
|
||||||
"kind": "ReplicationController",
|
"kind": "ReplicationController",
|
||||||
"apiVersion": "v1beta1",
|
"apiVersion": "v1beta3",
|
||||||
"id": "a",
|
"metadata": {
|
||||||
"desiredState": {
|
"name": "a",
|
||||||
|
"labels": {
|
||||||
|
"name": "a"
|
||||||
|
}%s
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
"replicas": 2,
|
"replicas": 2,
|
||||||
"replicaSelector": {"name": "a"},
|
"selector": {
|
||||||
"podTemplate": {
|
"name": "a"
|
||||||
"desiredState": {
|
},
|
||||||
"manifest": {
|
"template": {
|
||||||
"version": "v1beta1",
|
"metadata": {
|
||||||
"id": "a",
|
"labels": {
|
||||||
"containers": [{
|
"name": "a"
|
||||||
"name": "foo",
|
|
||||||
"image": "bar/foo"
|
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"labels": {"name": "a"}
|
"spec": {
|
||||||
|
"containers": [
|
||||||
|
{
|
||||||
|
"name": "foo",
|
||||||
|
"image": "bar/foo"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"labels": {"name": "a"}%s
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
var aService string = `
|
var aService string = `
|
||||||
{
|
{
|
||||||
"kind": "Service",
|
"kind": "Service",
|
||||||
"apiVersion": "v1beta1",
|
"apiVersion": "v1beta3",
|
||||||
"id": "a",
|
"metadata": {
|
||||||
"port": 8000,
|
"name": "a",
|
||||||
"portalIP": "10.0.0.100",
|
"labels": {
|
||||||
"labels": { "name": "a" },
|
"name": "a"
|
||||||
"selector": { "name": "a" }%s
|
}%s
|
||||||
}
|
|
||||||
`
|
|
||||||
var aMinion string = `
|
|
||||||
{
|
|
||||||
"kind": "Minion",
|
|
||||||
"apiVersion": "v1beta1",
|
|
||||||
"id": "a",
|
|
||||||
"resources": {
|
|
||||||
"capacity": { "memory": "10", "cpu": "10"}
|
|
||||||
},
|
},
|
||||||
"externalID": "external",
|
"spec": {
|
||||||
"hostIP": "10.10.10.10"%s
|
"ports": [
|
||||||
|
{
|
||||||
|
"protocol": "TCP",
|
||||||
|
"port": 8000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"selector": {
|
||||||
|
"name": "a"
|
||||||
|
},
|
||||||
|
"portalIP": "10.0.0.100"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
var aNode string = `
|
||||||
|
{
|
||||||
|
"kind": "Node",
|
||||||
|
"apiVersion": "v1beta3",
|
||||||
|
"metadata": {
|
||||||
|
"name": "a"%s
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"externalID": "external"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
var aEvent string = `
|
var aEvent string = `
|
||||||
{
|
{
|
||||||
"kind": "Event",
|
"kind": "Event",
|
||||||
"apiVersion": "v1beta1",
|
"apiVersion": "v1beta3",
|
||||||
"id": "a",
|
"metadata": {
|
||||||
|
"name": "a"%s
|
||||||
|
},
|
||||||
"involvedObject": {
|
"involvedObject": {
|
||||||
"kind": "Minion",
|
"kind": "Node",
|
||||||
"name": "a",
|
|
||||||
"namespace": "default",
|
"namespace": "default",
|
||||||
"apiVersion": "v1beta1"
|
"name": "a",
|
||||||
}%s
|
"apiVersion": "v1beta3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
var aBinding string = `
|
var aBinding string = `
|
||||||
{
|
{
|
||||||
"kind": "Binding",
|
"kind": "Binding",
|
||||||
"apiVersion": "v1beta1",
|
"apiVersion": "v1beta3",
|
||||||
"id": "a",
|
"metadata": {
|
||||||
"host": "10.10.10.10",
|
"name": "a"%s
|
||||||
"podID": "a"%s
|
},
|
||||||
|
"target": {
|
||||||
|
"name": "10.10.10.10"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
var aEndpoints string = `
|
var aEndpoints string = `
|
||||||
{
|
{
|
||||||
"kind": "Endpoints",
|
"kind": "Endpoints",
|
||||||
"apiVersion": "v1beta1",
|
"apiVersion": "v1beta3",
|
||||||
"id": "a",
|
"metadata": {
|
||||||
"endpoints": ["10.10.1.1:1909"]%s
|
"name": "a"%s
|
||||||
|
},
|
||||||
|
"subsets": [
|
||||||
|
{
|
||||||
|
"addresses": [
|
||||||
|
{
|
||||||
|
"IP": "10.10.1.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ports": [
|
||||||
|
{
|
||||||
|
"port": 1909,
|
||||||
|
"protocol": "TCP"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
var deleteNow string = `
|
var deleteNow string = `
|
||||||
{
|
{
|
||||||
"kind": "DeleteOptions",
|
"kind": "DeleteOptions",
|
||||||
"apiVersion": "v1beta1",
|
"apiVersion": "v1beta3",
|
||||||
"gracePeriod": 0%s
|
"gracePeriodSeconds": null%s
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
// To ensure that a POST completes before a dependent GET, set a timeout.
|
|
||||||
var timeoutFlag = "?timeout=60s"
|
|
||||||
|
|
||||||
// Requests to try. Each one should be forbidden or not forbidden
|
// Requests to try. Each one should be forbidden or not forbidden
|
||||||
// depending on the authentication and authorization setup of the master.
|
// depending on the authentication and authorization setup of the master.
|
||||||
var code200 = map[int]bool{200: true}
|
var code200 = map[int]bool{200: true}
|
||||||
@@ -183,6 +256,15 @@ var code409 = map[int]bool{409: true}
|
|||||||
var code422 = map[int]bool{422: true}
|
var code422 = map[int]bool{422: true}
|
||||||
var code500 = map[int]bool{500: true}
|
var code500 = map[int]bool{500: true}
|
||||||
|
|
||||||
|
// To ensure that a POST completes before a dependent GET, set a timeout.
|
||||||
|
func addTimeoutFlag(URLString string) string {
|
||||||
|
u, _ := url.Parse(URLString)
|
||||||
|
values := u.Query()
|
||||||
|
values.Set("timeout", "60s")
|
||||||
|
u.RawQuery = values.Encode()
|
||||||
|
return u.String()
|
||||||
|
}
|
||||||
|
|
||||||
func getTestRequests() []struct {
|
func getTestRequests() []struct {
|
||||||
verb string
|
verb string
|
||||||
URL string
|
URL string
|
||||||
@@ -196,86 +278,82 @@ func getTestRequests() []struct {
|
|||||||
statusCodes map[int]bool // Set of expected resp.StatusCode if all goes well.
|
statusCodes map[int]bool // Set of expected resp.StatusCode if all goes well.
|
||||||
}{
|
}{
|
||||||
// Normal methods on pods
|
// Normal methods on pods
|
||||||
{"GET", "/api/v1beta1/pods", "", code200},
|
{"GET", path("pods", "", ""), "", code200},
|
||||||
{"POST", "/api/v1beta1/pods" + timeoutFlag, aPod, code201},
|
{"GET", path("pods", api.NamespaceDefault, ""), "", code200},
|
||||||
{"PUT", "/api/v1beta1/pods/a" + timeoutFlag, aPod, code200},
|
{"POST", timeoutPath("pods", api.NamespaceDefault, ""), aPod, code201},
|
||||||
{"GET", "/api/v1beta1/pods", "", code200},
|
{"PUT", timeoutPath("pods", api.NamespaceDefault, "a"), aPod, code200},
|
||||||
{"GET", "/api/v1beta1/pods/a", "", code200},
|
{"GET", path("pods", api.NamespaceDefault, "a"), "", code200},
|
||||||
{"PATCH", "/api/v1beta1/pods/a", "{%v}", code200},
|
{"PATCH", path("pods", api.NamespaceDefault, "a"), "{%v}", code200},
|
||||||
{"DELETE", "/api/v1beta1/pods/a" + timeoutFlag, deleteNow, code200},
|
{"DELETE", timeoutPath("pods", api.NamespaceDefault, "a"), deleteNow, code200},
|
||||||
|
|
||||||
// Non-standard methods (not expected to work,
|
// Non-standard methods (not expected to work,
|
||||||
// but expected to pass/fail authorization prior to
|
// but expected to pass/fail authorization prior to
|
||||||
// failing validation.
|
// failing validation.
|
||||||
{"OPTIONS", "/api/v1beta1/pods", "", code405},
|
{"OPTIONS", path("pods", api.NamespaceDefault, ""), "", code405},
|
||||||
{"OPTIONS", "/api/v1beta1/pods/a", "", code405},
|
{"OPTIONS", path("pods", api.NamespaceDefault, "a"), "", code405},
|
||||||
{"HEAD", "/api/v1beta1/pods", "", code405},
|
{"HEAD", path("pods", api.NamespaceDefault, ""), "", code405},
|
||||||
{"HEAD", "/api/v1beta1/pods/a", "", code405},
|
{"HEAD", path("pods", api.NamespaceDefault, "a"), "", code405},
|
||||||
{"TRACE", "/api/v1beta1/pods", "", code405},
|
{"TRACE", path("pods", api.NamespaceDefault, ""), "", code405},
|
||||||
{"TRACE", "/api/v1beta1/pods/a", "", code405},
|
{"TRACE", path("pods", api.NamespaceDefault, "a"), "", code405},
|
||||||
{"NOSUCHVERB", "/api/v1beta1/pods", "", code405},
|
{"NOSUCHVERB", path("pods", api.NamespaceDefault, ""), "", code405},
|
||||||
|
|
||||||
// Normal methods on services
|
// Normal methods on services
|
||||||
{"GET", "/api/v1beta1/services", "", code200},
|
{"GET", path("services", "", ""), "", code200},
|
||||||
{"POST", "/api/v1beta1/services" + timeoutFlag, aService, code201},
|
{"GET", path("services", api.NamespaceDefault, ""), "", code200},
|
||||||
{"PUT", "/api/v1beta1/services/a" + timeoutFlag, aService, code200},
|
{"POST", timeoutPath("services", api.NamespaceDefault, ""), aService, code201},
|
||||||
{"GET", "/api/v1beta1/services", "", code200},
|
{"PUT", timeoutPath("services", api.NamespaceDefault, "a"), aService, code200},
|
||||||
{"GET", "/api/v1beta1/services/a", "", code200},
|
{"GET", path("services", api.NamespaceDefault, "a"), "", code200},
|
||||||
{"DELETE", "/api/v1beta1/services/a" + timeoutFlag, "", code200},
|
{"DELETE", timeoutPath("services", api.NamespaceDefault, "a"), "", code200},
|
||||||
|
|
||||||
// Normal methods on replicationControllers
|
// Normal methods on replicationControllers
|
||||||
{"GET", "/api/v1beta1/replicationControllers", "", code200},
|
{"GET", path("replicationControllers", "", ""), "", code200},
|
||||||
{"POST", "/api/v1beta1/replicationControllers" + timeoutFlag, aRC, code201},
|
{"GET", path("replicationControllers", api.NamespaceDefault, ""), "", code200},
|
||||||
{"PUT", "/api/v1beta1/replicationControllers/a" + timeoutFlag, aRC, code200},
|
{"POST", timeoutPath("replicationControllers", api.NamespaceDefault, ""), aRC, code201},
|
||||||
{"GET", "/api/v1beta1/replicationControllers", "", code200},
|
{"PUT", timeoutPath("replicationControllers", api.NamespaceDefault, "a"), aRC, code200},
|
||||||
{"GET", "/api/v1beta1/replicationControllers/a", "", code200},
|
{"GET", path("replicationControllers", api.NamespaceDefault, "a"), "", code200},
|
||||||
{"DELETE", "/api/v1beta1/replicationControllers/a" + timeoutFlag, "", code200},
|
{"DELETE", timeoutPath("replicationControllers", api.NamespaceDefault, "a"), "", code200},
|
||||||
|
|
||||||
// Normal methods on endpoints
|
// Normal methods on endpoints
|
||||||
{"GET", "/api/v1beta1/endpoints", "", code200},
|
{"GET", path("endpoints", "", ""), "", code200},
|
||||||
{"POST", "/api/v1beta1/endpoints" + timeoutFlag, aEndpoints, code201},
|
{"GET", path("endpoints", api.NamespaceDefault, ""), "", code200},
|
||||||
{"PUT", "/api/v1beta1/endpoints/a" + timeoutFlag, aEndpoints, code200},
|
{"POST", timeoutPath("endpoints", api.NamespaceDefault, ""), aEndpoints, code201},
|
||||||
{"GET", "/api/v1beta1/endpoints", "", code200},
|
{"PUT", timeoutPath("endpoints", api.NamespaceDefault, "a"), aEndpoints, code200},
|
||||||
{"GET", "/api/v1beta1/endpoints/a", "", code200},
|
{"GET", path("endpoints", api.NamespaceDefault, "a"), "", code200},
|
||||||
{"DELETE", "/api/v1beta1/endpoints/a" + timeoutFlag, "", code200},
|
{"DELETE", timeoutPath("endpoints", api.NamespaceDefault, "a"), "", code200},
|
||||||
|
|
||||||
// Normal methods on minions
|
// Normal methods on minions
|
||||||
{"GET", "/api/v1beta1/minions", "", code200},
|
{"GET", path(nodeResourceName, "", ""), "", code200},
|
||||||
{"POST", "/api/v1beta1/minions" + timeoutFlag, aMinion, code201},
|
{"POST", timeoutPath(nodeResourceName, "", ""), aNode, code201},
|
||||||
{"PUT", "/api/v1beta1/minions/a" + timeoutFlag, aMinion, code200},
|
{"PUT", timeoutPath(nodeResourceName, "", "a"), aNode, code200},
|
||||||
{"GET", "/api/v1beta1/minions", "", code200},
|
{"GET", path(nodeResourceName, "", "a"), "", code200},
|
||||||
{"GET", "/api/v1beta1/minions/a", "", code200},
|
{"DELETE", timeoutPath(nodeResourceName, "", "a"), "", code200},
|
||||||
{"DELETE", "/api/v1beta1/minions/a" + timeoutFlag, "", code200},
|
|
||||||
|
|
||||||
// Normal methods on events
|
// Normal methods on events
|
||||||
{"GET", "/api/v1beta1/events", "", code200},
|
{"GET", path("events", "", ""), "", code200},
|
||||||
{"POST", "/api/v1beta1/events" + timeoutFlag, aEvent, code201},
|
{"GET", path("events", api.NamespaceDefault, ""), "", code200},
|
||||||
{"PUT", "/api/v1beta1/events/a" + timeoutFlag, aEvent, code200},
|
{"POST", timeoutPath("events", api.NamespaceDefault, ""), aEvent, code201},
|
||||||
{"GET", "/api/v1beta1/events", "", code200},
|
{"PUT", timeoutPath("events", api.NamespaceDefault, "a"), aEvent, code200},
|
||||||
{"GET", "/api/v1beta1/events", "", code200},
|
{"GET", path("events", api.NamespaceDefault, "a"), "", code200},
|
||||||
{"GET", "/api/v1beta1/events/a", "", code200},
|
{"DELETE", timeoutPath("events", api.NamespaceDefault, "a"), "", code200},
|
||||||
{"DELETE", "/api/v1beta1/events/a" + timeoutFlag, "", code200},
|
|
||||||
|
|
||||||
// Normal methods on bindings
|
// Normal methods on bindings
|
||||||
{"GET", "/api/v1beta1/bindings", "", code405}, // Bindings are write-only
|
{"GET", path("bindings", api.NamespaceDefault, ""), "", code405},
|
||||||
{"POST", "/api/v1beta1/pods" + timeoutFlag, aPod, code201}, // Need a pod to bind or you get a 404
|
{"POST", timeoutPath("pods", api.NamespaceDefault, ""), aPod, code201}, // Need a pod to bind or you get a 404
|
||||||
{"POST", "/api/v1beta1/bindings" + timeoutFlag, aBinding, code201},
|
{"POST", timeoutPath("bindings", api.NamespaceDefault, ""), aBinding, code201},
|
||||||
{"PUT", "/api/v1beta1/bindings/a" + timeoutFlag, aBinding, code404},
|
{"PUT", timeoutPath("bindings", api.NamespaceDefault, "a"), aBinding, code404},
|
||||||
{"GET", "/api/v1beta1/bindings", "", code405},
|
{"GET", path("bindings", api.NamespaceDefault, "a"), "", code404}, // No bindings instances
|
||||||
{"GET", "/api/v1beta1/bindings/a", "", code404}, // No bindings instances
|
{"DELETE", timeoutPath("bindings", api.NamespaceDefault, "a"), "", code404},
|
||||||
{"DELETE", "/api/v1beta1/bindings/a" + timeoutFlag, "", code404},
|
|
||||||
|
|
||||||
// Non-existent object type.
|
// Non-existent object type.
|
||||||
{"GET", "/api/v1beta1/foo", "", code404},
|
{"GET", path("foo", "", ""), "", code404},
|
||||||
{"POST", "/api/v1beta1/foo", `{"foo": "foo"}`, code404},
|
{"POST", path("foo", api.NamespaceDefault, ""), `{"foo": "foo"}`, code404},
|
||||||
{"PUT", "/api/v1beta1/foo/a", `{"foo": "foo"}`, code404},
|
{"PUT", path("foo", api.NamespaceDefault, "a"), `{"foo": "foo"}`, code404},
|
||||||
{"GET", "/api/v1beta1/foo", "", code404},
|
{"GET", path("foo", api.NamespaceDefault, "a"), "", code404},
|
||||||
{"GET", "/api/v1beta1/foo/a", "", code404},
|
{"DELETE", timeoutPath("foo", api.NamespaceDefault, ""), "", code404},
|
||||||
{"DELETE", "/api/v1beta1/foo" + timeoutFlag, "", code404},
|
|
||||||
|
|
||||||
// Special verbs on nodes
|
// Special verbs on nodes
|
||||||
{"GET", "/api/v1beta1/proxy/minions/a", "", code404},
|
{"GET", pathWithPrefix("proxy", nodeResourceName, api.NamespaceDefault, "a"), "", code404},
|
||||||
{"GET", "/api/v1beta1/redirect/minions/a", "", code404},
|
{"GET", pathWithPrefix("redirect", nodeResourceName, api.NamespaceDefault, "a"), "", code404},
|
||||||
// TODO: test .../watch/..., which doesn't end before the test timeout.
|
// TODO: test .../watch/..., which doesn't end before the test timeout.
|
||||||
// TODO: figure out how to create a minion so that it can successfully proxy/redirect.
|
// TODO: figure out how to create a minion so that it can successfully proxy/redirect.
|
||||||
|
|
||||||
@@ -299,7 +377,7 @@ func TestAuthModeAlwaysAllow(t *testing.T) {
|
|||||||
|
|
||||||
// Set up a master
|
// Set up a master
|
||||||
|
|
||||||
helper, err := master.NewEtcdHelper(newEtcdClient(), "v1beta1")
|
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -331,7 +409,7 @@ func TestAuthModeAlwaysAllow(t *testing.T) {
|
|||||||
if r.verb == "PUT" {
|
if r.verb == "PUT" {
|
||||||
// For update operations, insert previous resource version
|
// For update operations, insert previous resource version
|
||||||
if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 {
|
if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 {
|
||||||
sub += fmt.Sprintf(",\r\n\"resourceVersion\": %v", resVersion)
|
sub += fmt.Sprintf(",\r\n\"resourceVersion\": \"%v\"", resVersion)
|
||||||
}
|
}
|
||||||
namespace := "default"
|
namespace := "default"
|
||||||
sub += fmt.Sprintf(",\r\n\"namespace\": %q", namespace)
|
sub += fmt.Sprintf(",\r\n\"namespace\": %q", namespace)
|
||||||
@@ -367,6 +445,8 @@ func TestAuthModeAlwaysAllow(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
key := getPreviousResourceVersionKey(r.URL, id)
|
key := getPreviousResourceVersionKey(r.URL, id)
|
||||||
previousResourceVersion[key] = currentResourceVersion
|
previousResourceVersion[key] = currentResourceVersion
|
||||||
|
} else {
|
||||||
|
t.Logf("error in trying to extract resource version: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -380,10 +460,42 @@ func parseResourceVersion(response []byte) (string, float64, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, fmt.Errorf("unexpected error unmarshaling resultBody: %v", err)
|
return "", 0, fmt.Errorf("unexpected error unmarshaling resultBody: %v", err)
|
||||||
}
|
}
|
||||||
|
apiVersion, ok := resultBodyMap["apiVersion"].(string)
|
||||||
|
if !ok {
|
||||||
|
return "", 0, fmt.Errorf("unexpected error, apiVersion not found in JSON response: %v", string(response))
|
||||||
|
}
|
||||||
|
if api.PreV1Beta3(apiVersion) {
|
||||||
|
return parsePreV1Beta3ResourceVersion(resultBodyMap, response)
|
||||||
|
}
|
||||||
|
return parseV1Beta3ResourceVersion(resultBodyMap, response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseV1Beta3ResourceVersion(resultBodyMap map[string]interface{}, response []byte) (string, float64, error) {
|
||||||
|
metadata, ok := resultBodyMap["metadata"].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return "", 0, fmt.Errorf("unexpected error, metadata not found in JSON response: %v", string(response))
|
||||||
|
}
|
||||||
|
id, ok := metadata["name"].(string)
|
||||||
|
if !ok {
|
||||||
|
return "", 0, fmt.Errorf("unexpected error, id not found in JSON response: %v", string(response))
|
||||||
|
}
|
||||||
|
resourceVersionString, ok := metadata["resourceVersion"].(string)
|
||||||
|
if !ok {
|
||||||
|
return "", 0, fmt.Errorf("unexpected error, resourceVersion not found in JSON response: %v", string(response))
|
||||||
|
}
|
||||||
|
resourceVersion, err := strconv.ParseFloat(resourceVersionString, 64)
|
||||||
|
if err != nil {
|
||||||
|
return "", 0, fmt.Errorf("unexpected error, could not parse resourceVersion as float64, err: %s. JSON response: %v", err, string(response))
|
||||||
|
}
|
||||||
|
return id, resourceVersion, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parsePreV1Beta3ResourceVersion(resultBodyMap map[string]interface{}, response []byte) (string, float64, error) {
|
||||||
id, ok := resultBodyMap["id"].(string)
|
id, ok := resultBodyMap["id"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", 0, fmt.Errorf("unexpected error, id not found in JSON response: %v", string(response))
|
return "", 0, fmt.Errorf("unexpected error, id not found in JSON response: %v", string(response))
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceVersion, ok := resultBodyMap["resourceVersion"].(float64)
|
resourceVersion, ok := resultBodyMap["resourceVersion"].(float64)
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", 0, fmt.Errorf("unexpected error, resourceVersion not found in JSON response: %v", string(response))
|
return "", 0, fmt.Errorf("unexpected error, resourceVersion not found in JSON response: %v", string(response))
|
||||||
@@ -405,7 +517,7 @@ func TestAuthModeAlwaysDeny(t *testing.T) {
|
|||||||
|
|
||||||
// Set up a master
|
// Set up a master
|
||||||
|
|
||||||
helper, err := master.NewEtcdHelper(newEtcdClient(), "v1beta1")
|
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -472,7 +584,7 @@ func TestAliceNotForbiddenOrUnauthorized(t *testing.T) {
|
|||||||
|
|
||||||
// Set up a master
|
// Set up a master
|
||||||
|
|
||||||
helper, err := master.NewEtcdHelper(newEtcdClient(), "v1beta1")
|
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -506,7 +618,7 @@ func TestAliceNotForbiddenOrUnauthorized(t *testing.T) {
|
|||||||
if r.verb == "PUT" {
|
if r.verb == "PUT" {
|
||||||
// For update operations, insert previous resource version
|
// For update operations, insert previous resource version
|
||||||
if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 {
|
if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 {
|
||||||
sub += fmt.Sprintf(",\r\n\"resourceVersion\": %v", resVersion)
|
sub += fmt.Sprintf(",\r\n\"resourceVersion\": \"%v\"", resVersion)
|
||||||
}
|
}
|
||||||
namespace := "default"
|
namespace := "default"
|
||||||
sub += fmt.Sprintf(",\r\n\"namespace\": %q", namespace)
|
sub += fmt.Sprintf(",\r\n\"namespace\": %q", namespace)
|
||||||
@@ -561,7 +673,7 @@ func TestBobIsForbidden(t *testing.T) {
|
|||||||
|
|
||||||
// Set up a master
|
// Set up a master
|
||||||
|
|
||||||
helper, err := master.NewEtcdHelper(newEtcdClient(), "v1beta1")
|
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -622,7 +734,7 @@ func TestUnknownUserIsUnauthorized(t *testing.T) {
|
|||||||
|
|
||||||
// Set up a master
|
// Set up a master
|
||||||
|
|
||||||
helper, err := master.NewEtcdHelper(newEtcdClient(), "v1beta1")
|
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -699,7 +811,7 @@ func TestNamespaceAuthorization(t *testing.T) {
|
|||||||
|
|
||||||
// This file has alice and bob in it.
|
// This file has alice and bob in it.
|
||||||
|
|
||||||
helper, err := master.NewEtcdHelper(newEtcdClient(), "v1beta1")
|
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -736,20 +848,20 @@ func TestNamespaceAuthorization(t *testing.T) {
|
|||||||
statusCodes map[int]bool // allowed status codes.
|
statusCodes map[int]bool // allowed status codes.
|
||||||
}{
|
}{
|
||||||
|
|
||||||
{"POST", "/api/v1beta1/pods" + timeoutFlag + "&namespace=foo", "foo", aPod, code201},
|
{"POST", timeoutPathWithQuery("pods", "foo", ""), "foo", aPod, code201},
|
||||||
{"GET", "/api/v1beta1/pods?namespace=foo", "foo", "", code200},
|
{"GET", pathWithQuery("pods", "foo", ""), "foo", "", code200},
|
||||||
{"GET", "/api/v1beta1/pods/a?namespace=foo", "foo", "", code200},
|
{"GET", pathWithQuery("pods", "foo", "a"), "foo", "", code200},
|
||||||
{"DELETE", "/api/v1beta1/pods/a" + timeoutFlag + "&namespace=foo", "foo", "", code200},
|
{"DELETE", timeoutPathWithQuery("pods", "foo", "a"), "foo", "", code200},
|
||||||
|
|
||||||
{"POST", "/api/v1beta1/pods" + timeoutFlag + "&namespace=bar", "bar", aPod, code403},
|
{"POST", timeoutPath("pods", "bar", ""), "bar", aPod, code403},
|
||||||
{"GET", "/api/v1beta1/pods?namespace=bar", "bar", "", code403},
|
{"GET", pathWithQuery("pods", "bar", ""), "bar", "", code403},
|
||||||
{"GET", "/api/v1beta1/pods/a?namespace=bar", "bar", "", code403},
|
{"GET", pathWithQuery("pods", "bar", "a"), "bar", "", code403},
|
||||||
{"DELETE", "/api/v1beta1/pods/a" + timeoutFlag + "&namespace=bar", "bar", "", code403},
|
{"DELETE", timeoutPathWithQuery("pods", "bar", "a"), "bar", "", code403},
|
||||||
|
|
||||||
{"POST", "/api/v1beta1/pods" + timeoutFlag, "", aPod, code403},
|
{"POST", timeoutPath("pods", api.NamespaceDefault, ""), "", aPod, code403},
|
||||||
{"GET", "/api/v1beta1/pods", "", "", code403},
|
{"GET", path("pods", "", ""), "", "", code403},
|
||||||
{"GET", "/api/v1beta1/pods/a", "", "", code403},
|
{"GET", path("pods", api.NamespaceDefault, "a"), "", "", code403},
|
||||||
{"DELETE", "/api/v1beta1/pods/a" + timeoutFlag, "", "", code403},
|
{"DELETE", timeoutPath("pods", api.NamespaceDefault, "a"), "", "", code403},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range requests {
|
for _, r := range requests {
|
||||||
@@ -760,7 +872,7 @@ func TestNamespaceAuthorization(t *testing.T) {
|
|||||||
if r.verb == "PUT" && r.body != "" {
|
if r.verb == "PUT" && r.body != "" {
|
||||||
// For update operations, insert previous resource version
|
// For update operations, insert previous resource version
|
||||||
if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 {
|
if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 {
|
||||||
sub += fmt.Sprintf(",\r\n\"resourceVersion\": %v", resVersion)
|
sub += fmt.Sprintf(",\r\n\"resourceVersion\": \"%v\"", resVersion)
|
||||||
}
|
}
|
||||||
namespace := r.namespace
|
namespace := r.namespace
|
||||||
if len(namespace) == 0 {
|
if len(namespace) == 0 {
|
||||||
@@ -814,7 +926,7 @@ func TestKindAuthorization(t *testing.T) {
|
|||||||
|
|
||||||
// Set up a master
|
// Set up a master
|
||||||
|
|
||||||
helper, err := master.NewEtcdHelper(newEtcdClient(), "v1beta1")
|
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -849,15 +961,15 @@ func TestKindAuthorization(t *testing.T) {
|
|||||||
body string
|
body string
|
||||||
statusCodes map[int]bool // allowed status codes.
|
statusCodes map[int]bool // allowed status codes.
|
||||||
}{
|
}{
|
||||||
{"POST", "/api/v1beta1/services" + timeoutFlag, aService, code201},
|
{"POST", timeoutPath("services", api.NamespaceDefault, ""), aService, code201},
|
||||||
{"GET", "/api/v1beta1/services", "", code200},
|
{"GET", path("services", api.NamespaceDefault, ""), "", code200},
|
||||||
{"GET", "/api/v1beta1/services/a", "", code200},
|
{"GET", path("services", api.NamespaceDefault, "a"), "", code200},
|
||||||
{"DELETE", "/api/v1beta1/services/a" + timeoutFlag, "", code200},
|
{"DELETE", timeoutPath("services", api.NamespaceDefault, "a"), "", code200},
|
||||||
|
|
||||||
{"POST", "/api/v1beta1/pods" + timeoutFlag, aPod, code403},
|
{"POST", timeoutPath("pods", api.NamespaceDefault, ""), aPod, code403},
|
||||||
{"GET", "/api/v1beta1/pods", "", code403},
|
{"GET", path("pods", "", ""), "", code403},
|
||||||
{"GET", "/api/v1beta1/pods/a", "", code403},
|
{"GET", path("pods", api.NamespaceDefault, "a"), "", code403},
|
||||||
{"DELETE", "/api/v1beta1/pods/a" + timeoutFlag, "", code403},
|
{"DELETE", timeoutPath("pods", api.NamespaceDefault, "a"), "", code403},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range requests {
|
for _, r := range requests {
|
||||||
@@ -868,7 +980,7 @@ func TestKindAuthorization(t *testing.T) {
|
|||||||
if r.verb == "PUT" && r.body != "" {
|
if r.verb == "PUT" && r.body != "" {
|
||||||
// For update operations, insert previous resource version
|
// For update operations, insert previous resource version
|
||||||
if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 {
|
if resVersion := previousResourceVersion[getPreviousResourceVersionKey(r.URL, "")]; resVersion != 0 {
|
||||||
resourceVersionJson := fmt.Sprintf(",\r\n\"resourceVersion\": %v", resVersion)
|
resourceVersionJson := fmt.Sprintf(",\r\n\"resourceVersion\": \"%v\"", resVersion)
|
||||||
bodyStr = fmt.Sprintf(r.body, resourceVersionJson)
|
bodyStr = fmt.Sprintf(r.body, resourceVersionJson)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -917,13 +1029,12 @@ func TestReadOnlyAuthorization(t *testing.T) {
|
|||||||
|
|
||||||
// Set up a master
|
// Set up a master
|
||||||
|
|
||||||
helper, err := master.NewEtcdHelper(newEtcdClient(), "v1beta1")
|
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
a := newAuthorizerWithContents(t, `{"readonly": true}
|
a := newAuthorizerWithContents(t, `{"readonly": true}`)
|
||||||
`)
|
|
||||||
|
|
||||||
var m *master.Master
|
var m *master.Master
|
||||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
@@ -951,9 +1062,9 @@ func TestReadOnlyAuthorization(t *testing.T) {
|
|||||||
body string
|
body string
|
||||||
statusCodes map[int]bool // allowed status codes.
|
statusCodes map[int]bool // allowed status codes.
|
||||||
}{
|
}{
|
||||||
{"POST", "/api/v1beta1/pods", aPod, code403},
|
{"POST", path("pods", "", ""), aPod, code403},
|
||||||
{"GET", "/api/v1beta1/pods", "", code200},
|
{"GET", path("pods", "", ""), "", code200},
|
||||||
{"GET", "/api/v1beta1/pods/a", "", code404},
|
{"GET", path("pods", api.NamespaceDefault, "a"), "", code404},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range requests {
|
for _, r := range requests {
|
||||||
|
@@ -30,6 +30,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
|
||||||
@@ -45,7 +46,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RunAMaster(t *testing.T) (*master.Master, *httptest.Server) {
|
func RunAMaster(t *testing.T) (*master.Master, *httptest.Server) {
|
||||||
helper, err := master.NewEtcdHelper(newEtcdClient(), "v1beta1")
|
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -73,76 +74,69 @@ func TestClient(t *testing.T) {
|
|||||||
_, s := RunAMaster(t)
|
_, s := RunAMaster(t)
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
testCases := []string{
|
ns := api.NamespaceDefault
|
||||||
"v1beta1",
|
deleteAllEtcdKeys()
|
||||||
"v1beta2",
|
client := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Version()})
|
||||||
"v1beta3",
|
|
||||||
|
info, err := client.ServerVersion()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if e, a := version.Get(), *info; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("expected %#v, got %#v", e, a)
|
||||||
}
|
}
|
||||||
for _, apiVersion := range testCases {
|
|
||||||
ns := api.NamespaceDefault
|
|
||||||
deleteAllEtcdKeys()
|
|
||||||
client := client.NewOrDie(&client.Config{Host: s.URL, Version: apiVersion})
|
|
||||||
|
|
||||||
info, err := client.ServerVersion()
|
pods, err := client.Pods(ns).List(labels.Everything())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
if e, a := version.Get(), *info; !reflect.DeepEqual(e, a) {
|
if len(pods.Items) != 0 {
|
||||||
t.Errorf("expected %#v, got %#v", e, a)
|
t.Errorf("expected no pods, got %#v", pods)
|
||||||
}
|
}
|
||||||
|
|
||||||
pods, err := client.Pods(ns).List(labels.Everything())
|
// get a validation error
|
||||||
if err != nil {
|
pod := &api.Pod{
|
||||||
t.Fatalf("unexpected error: %v", err)
|
ObjectMeta: api.ObjectMeta{
|
||||||
}
|
GenerateName: "test",
|
||||||
if len(pods.Items) != 0 {
|
},
|
||||||
t.Errorf("expected no pods, got %#v", pods)
|
Spec: api.PodSpec{
|
||||||
}
|
Containers: []api.Container{
|
||||||
|
{
|
||||||
// get a validation error
|
Name: "test",
|
||||||
pod := &api.Pod{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
GenerateName: "test",
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{
|
|
||||||
Name: "test",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
}
|
||||||
|
|
||||||
got, err := client.Pods(ns).Create(pod)
|
got, err := client.Pods(ns).Create(pod)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("unexpected non-error: %v", got)
|
t.Fatalf("unexpected non-error: %v", got)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get a created pod
|
// get a created pod
|
||||||
pod.Spec.Containers[0].Image = "an-image"
|
pod.Spec.Containers[0].Image = "an-image"
|
||||||
got, err = client.Pods(ns).Create(pod)
|
got, err = client.Pods(ns).Create(pod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
if got.Name == "" {
|
if got.Name == "" {
|
||||||
t.Errorf("unexpected empty pod Name %v", got)
|
t.Errorf("unexpected empty pod Name %v", got)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pod is shown, but not scheduled
|
// pod is shown, but not scheduled
|
||||||
pods, err = client.Pods(ns).List(labels.Everything())
|
pods, err = client.Pods(ns).List(labels.Everything())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
if len(pods.Items) != 1 {
|
if len(pods.Items) != 1 {
|
||||||
t.Errorf("expected one pod, got %#v", pods)
|
t.Errorf("expected one pod, got %#v", pods)
|
||||||
}
|
}
|
||||||
actual := pods.Items[0]
|
actual := pods.Items[0]
|
||||||
if actual.Name != got.Name {
|
if actual.Name != got.Name {
|
||||||
t.Errorf("expected pod %#v, got %#v", got, actual)
|
t.Errorf("expected pod %#v, got %#v", got, actual)
|
||||||
}
|
}
|
||||||
if actual.Spec.Host != "" {
|
if actual.Spec.Host != "" {
|
||||||
t.Errorf("expected pod to be unscheduled, got %#v", actual)
|
t.Errorf("expected pod to be unscheduled, got %#v", actual)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +153,7 @@ func TestMultiWatch(t *testing.T) {
|
|||||||
defer s.Close()
|
defer s.Close()
|
||||||
|
|
||||||
ns := api.NamespaceDefault
|
ns := api.NamespaceDefault
|
||||||
client := client.NewOrDie(&client.Config{Host: s.URL, Version: "v1beta1"})
|
client := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Version()})
|
||||||
|
|
||||||
dummyEvent := func(i int) *api.Event {
|
dummyEvent := func(i int) *api.Event {
|
||||||
name := fmt.Sprintf("unrelated-%v", i)
|
name := fmt.Sprintf("unrelated-%v", i)
|
||||||
|
@@ -23,8 +23,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/v1beta1"
|
|
||||||
"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/watch"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||||
@@ -93,9 +92,9 @@ func TestExtractObj(t *testing.T) {
|
|||||||
|
|
||||||
func TestWatch(t *testing.T) {
|
func TestWatch(t *testing.T) {
|
||||||
client := newEtcdClient()
|
client := newEtcdClient()
|
||||||
helper := tools.NewEtcdHelper(client, latest.Codec)
|
helper := tools.NewEtcdHelper(client, testapi.Codec())
|
||||||
withEtcdKey(func(key string) {
|
withEtcdKey(func(key string) {
|
||||||
resp, err := client.Set(key, runtime.EncodeOrDie(v1beta1.Codec, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
|
resp, err := client.Set(key, runtime.EncodeOrDie(testapi.Codec(), &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}), 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/testapi"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/apiserver"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/master"
|
||||||
@@ -49,7 +50,7 @@ func deleteSecretOrErrorf(t *testing.T, c *client.Client, ns, name string) {
|
|||||||
|
|
||||||
// TestSecrets tests apiserver-side behavior of creation of secret objects and their use by pods.
|
// TestSecrets tests apiserver-side behavior of creation of secret objects and their use by pods.
|
||||||
func TestSecrets(t *testing.T) {
|
func TestSecrets(t *testing.T) {
|
||||||
helper, err := master.NewEtcdHelper(newEtcdClient(), "v1beta1")
|
helper, err := master.NewEtcdHelper(newEtcdClient(), testapi.Version())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -71,16 +72,9 @@ func TestSecrets(t *testing.T) {
|
|||||||
AdmissionControl: admit.NewAlwaysAdmit(),
|
AdmissionControl: admit.NewAlwaysAdmit(),
|
||||||
})
|
})
|
||||||
|
|
||||||
testCases := []string{
|
deleteAllEtcdKeys()
|
||||||
"v1beta1",
|
client := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Version()})
|
||||||
"v1beta2",
|
DoTestSecrets(t, client, testapi.Version())
|
||||||
}
|
|
||||||
|
|
||||||
for _, apiVersion := range testCases {
|
|
||||||
deleteAllEtcdKeys()
|
|
||||||
client := client.NewOrDie(&client.Config{Host: s.URL, Version: apiVersion})
|
|
||||||
DoTestSecrets(t, client, apiVersion)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoTestSecrets test secrets for one api version.
|
// DoTestSecrets test secrets for one api version.
|
||||||
|
Reference in New Issue
Block a user