Update go dependencies
This commit is contained in:
parent
15ffb51394
commit
bb4d483837
1621 changed files with 86368 additions and 284392 deletions
223
vendor/k8s.io/kubernetes/pkg/master/client_ca_hook_test.go
generated
vendored
223
vendor/k8s.io/kubernetes/pkg/master/client_ca_hook_test.go
generated
vendored
|
|
@ -1,223 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
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 master
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
clienttesting "k8s.io/client-go/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
)
|
||||
|
||||
func TestWriteClientCAs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
hook ClientCARegistrationHook
|
||||
preexistingObjs []runtime.Object
|
||||
expectedConfigMaps map[string]*api.ConfigMap
|
||||
expectUpdate bool
|
||||
}{
|
||||
{
|
||||
name: "basic",
|
||||
hook: ClientCARegistrationHook{
|
||||
ClientCA: []byte("foo"),
|
||||
RequestHeaderUsernameHeaders: []string{"alfa", "bravo", "charlie"},
|
||||
RequestHeaderGroupHeaders: []string{"delta"},
|
||||
RequestHeaderExtraHeaderPrefixes: []string{"echo", "foxtrot"},
|
||||
RequestHeaderCA: []byte("bar"),
|
||||
RequestHeaderAllowedNames: []string{"first", "second"},
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"client-ca-file": "foo",
|
||||
"requestheader-username-headers": `["alfa","bravo","charlie"]`,
|
||||
"requestheader-group-headers": `["delta"]`,
|
||||
"requestheader-extra-headers-prefix": `["echo","foxtrot"]`,
|
||||
"requestheader-client-ca-file": "bar",
|
||||
"requestheader-allowed-names": `["first","second"]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "skip extension-apiserver-authentication",
|
||||
hook: ClientCARegistrationHook{
|
||||
RequestHeaderCA: []byte("bar"),
|
||||
RequestHeaderAllowedNames: []string{"first", "second"},
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"requestheader-username-headers": `null`,
|
||||
"requestheader-group-headers": `null`,
|
||||
"requestheader-extra-headers-prefix": `null`,
|
||||
"requestheader-client-ca-file": "bar",
|
||||
"requestheader-allowed-names": `["first","second"]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "skip extension-apiserver-authentication",
|
||||
hook: ClientCARegistrationHook{
|
||||
ClientCA: []byte("foo"),
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"client-ca-file": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty allowed names",
|
||||
hook: ClientCARegistrationHook{
|
||||
RequestHeaderCA: []byte("bar"),
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"requestheader-username-headers": `null`,
|
||||
"requestheader-group-headers": `null`,
|
||||
"requestheader-extra-headers-prefix": `null`,
|
||||
"requestheader-client-ca-file": "bar",
|
||||
"requestheader-allowed-names": `null`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "overwrite extension-apiserver-authentication",
|
||||
hook: ClientCARegistrationHook{
|
||||
ClientCA: []byte("foo"),
|
||||
},
|
||||
preexistingObjs: []runtime.Object{
|
||||
&api.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"client-ca-file": "other",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"client-ca-file": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectUpdate: true,
|
||||
},
|
||||
{
|
||||
name: "overwrite extension-apiserver-authentication requestheader",
|
||||
hook: ClientCARegistrationHook{
|
||||
RequestHeaderUsernameHeaders: []string{},
|
||||
RequestHeaderGroupHeaders: []string{},
|
||||
RequestHeaderExtraHeaderPrefixes: []string{},
|
||||
RequestHeaderCA: []byte("bar"),
|
||||
RequestHeaderAllowedNames: []string{},
|
||||
},
|
||||
preexistingObjs: []runtime.Object{
|
||||
&api.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"requestheader-username-headers": `null`,
|
||||
"requestheader-group-headers": `null`,
|
||||
"requestheader-extra-headers-prefix": `null`,
|
||||
"requestheader-client-ca-file": "something",
|
||||
"requestheader-allowed-names": `null`,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"requestheader-username-headers": `[]`,
|
||||
"requestheader-group-headers": `[]`,
|
||||
"requestheader-extra-headers-prefix": `[]`,
|
||||
"requestheader-client-ca-file": "bar",
|
||||
"requestheader-allowed-names": `[]`,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectUpdate: true,
|
||||
},
|
||||
{
|
||||
name: "namespace exists",
|
||||
hook: ClientCARegistrationHook{
|
||||
ClientCA: []byte("foo"),
|
||||
},
|
||||
preexistingObjs: []runtime.Object{
|
||||
&api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: metav1.NamespaceSystem}},
|
||||
},
|
||||
expectedConfigMaps: map[string]*api.ConfigMap{
|
||||
"extension-apiserver-authentication": {
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceSystem, Name: "extension-apiserver-authentication"},
|
||||
Data: map[string]string{
|
||||
"client-ca-file": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
client := fake.NewSimpleClientset(test.preexistingObjs...)
|
||||
test.hook.tryToWriteClientCAs(client.Core())
|
||||
|
||||
actualConfigMaps, updated := getFinalConfiMaps(client)
|
||||
if !reflect.DeepEqual(test.expectedConfigMaps, actualConfigMaps) {
|
||||
t.Errorf("%s: %v", test.name, diff.ObjectReflectDiff(test.expectedConfigMaps, actualConfigMaps))
|
||||
continue
|
||||
}
|
||||
if test.expectUpdate != updated {
|
||||
t.Errorf("%s: expected %v, got %v", test.name, test.expectUpdate, updated)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getFinalConfiMaps(client *fake.Clientset) (map[string]*api.ConfigMap, bool) {
|
||||
ret := map[string]*api.ConfigMap{}
|
||||
updated := false
|
||||
|
||||
for _, action := range client.Actions() {
|
||||
if action.Matches("create", "configmaps") {
|
||||
obj := action.(clienttesting.CreateAction).GetObject().(*api.ConfigMap)
|
||||
ret[obj.Name] = obj
|
||||
}
|
||||
if action.Matches("update", "configmaps") {
|
||||
updated = true
|
||||
obj := action.(clienttesting.UpdateAction).GetObject().(*api.ConfigMap)
|
||||
ret[obj.Name] = obj
|
||||
}
|
||||
}
|
||||
return ret, updated
|
||||
}
|
||||
948
vendor/k8s.io/kubernetes/pkg/master/controller_test.go
generated
vendored
948
vendor/k8s.io/kubernetes/pkg/master/controller_test.go
generated
vendored
|
|
@ -1,948 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
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 master
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
core "k8s.io/client-go/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
"k8s.io/kubernetes/pkg/master/reconcilers"
|
||||
)
|
||||
|
||||
func TestReconcileEndpoints(t *testing.T) {
|
||||
ns := metav1.NamespaceDefault
|
||||
om := func(name string) metav1.ObjectMeta {
|
||||
return metav1.ObjectMeta{Namespace: ns, Name: name}
|
||||
}
|
||||
reconcile_tests := []struct {
|
||||
testName string
|
||||
serviceName string
|
||||
ip string
|
||||
endpointPorts []api.EndpointPort
|
||||
additionalMasters int
|
||||
endpoints *api.EndpointsList
|
||||
expectUpdate *api.Endpoints // nil means none expected
|
||||
expectCreate *api.Endpoints // nil means none expected
|
||||
}{
|
||||
{
|
||||
testName: "no existing endpoints",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: nil,
|
||||
expectCreate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints satisfy",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints satisfy but too many",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}, {IP: "4.3.2.1"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints satisfy but too many + extra masters",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
additionalMasters: 3,
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "4.3.2.1"},
|
||||
{IP: "4.3.2.2"},
|
||||
{IP: "4.3.2.3"},
|
||||
{IP: "4.3.2.4"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "4.3.2.2"},
|
||||
{IP: "4.3.2.3"},
|
||||
{IP: "4.3.2.4"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints satisfy but too many + extra masters + delete first",
|
||||
serviceName: "foo",
|
||||
ip: "4.3.2.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
additionalMasters: 3,
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "1.2.3.4"},
|
||||
{IP: "4.3.2.1"},
|
||||
{IP: "4.3.2.2"},
|
||||
{IP: "4.3.2.3"},
|
||||
{IP: "4.3.2.4"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "4.3.2.1"},
|
||||
{IP: "4.3.2.2"},
|
||||
{IP: "4.3.2.3"},
|
||||
{IP: "4.3.2.4"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints satisfy and endpoint addresses length less than master count",
|
||||
serviceName: "foo",
|
||||
ip: "4.3.2.2",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
additionalMasters: 3,
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "4.3.2.1"},
|
||||
{IP: "4.3.2.2"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: nil,
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints current IP missing and address length less than master count",
|
||||
serviceName: "foo",
|
||||
ip: "4.3.2.2",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
additionalMasters: 3,
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "4.3.2.1"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{
|
||||
{IP: "4.3.2.1"},
|
||||
{IP: "4.3.2.2"},
|
||||
},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints wrong name",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("bar"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectCreate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints wrong IP",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "4.3.2.1"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints wrong port",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 9090, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints wrong protocol",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "UDP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints wrong port name",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "baz", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "baz", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints extra service ports satisfy",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
{Name: "baz", Port: 1010, Protocol: "TCP"},
|
||||
},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
{Name: "baz", Port: 1010, Protocol: "TCP"},
|
||||
},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints extra service ports missing port",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range reconcile_tests {
|
||||
fakeClient := fake.NewSimpleClientset()
|
||||
if test.endpoints != nil {
|
||||
fakeClient = fake.NewSimpleClientset(test.endpoints)
|
||||
}
|
||||
reconciler := reconcilers.NewMasterCountEndpointReconciler(test.additionalMasters+1, fakeClient.Core())
|
||||
err := reconciler.ReconcileEndpoints(test.serviceName, net.ParseIP(test.ip), test.endpointPorts, true)
|
||||
if err != nil {
|
||||
t.Errorf("case %q: unexpected error: %v", test.testName, err)
|
||||
}
|
||||
|
||||
updates := []core.UpdateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() != "update" {
|
||||
continue
|
||||
}
|
||||
updates = append(updates, action.(core.UpdateAction))
|
||||
}
|
||||
if test.expectUpdate != nil {
|
||||
if len(updates) != 1 {
|
||||
t.Errorf("case %q: unexpected updates: %v", test.testName, updates)
|
||||
} else if e, a := test.expectUpdate, updates[0].GetObject(); !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
if test.expectUpdate == nil && len(updates) > 0 {
|
||||
t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates)
|
||||
}
|
||||
|
||||
creates := []core.CreateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() != "create" {
|
||||
continue
|
||||
}
|
||||
creates = append(creates, action.(core.CreateAction))
|
||||
}
|
||||
if test.expectCreate != nil {
|
||||
if len(creates) != 1 {
|
||||
t.Errorf("case %q: unexpected creates: %v", test.testName, creates)
|
||||
} else if e, a := test.expectCreate, creates[0].GetObject(); !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected create:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
if test.expectCreate == nil && len(creates) > 0 {
|
||||
t.Errorf("case %q: no create expected, yet saw: %v", test.testName, creates)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
non_reconcile_tests := []struct {
|
||||
testName string
|
||||
serviceName string
|
||||
ip string
|
||||
endpointPorts []api.EndpointPort
|
||||
additionalMasters int
|
||||
endpoints *api.EndpointsList
|
||||
expectUpdate *api.Endpoints // nil means none expected
|
||||
expectCreate *api.Endpoints // nil means none expected
|
||||
}{
|
||||
{
|
||||
testName: "existing endpoints extra service ports missing port no update",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: nil,
|
||||
},
|
||||
{
|
||||
testName: "existing endpoints extra service ports, wrong ports, wrong IP",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP"},
|
||||
{Name: "bar", Port: 1000, Protocol: "TCP"},
|
||||
},
|
||||
endpoints: &api.EndpointsList{
|
||||
Items: []api.Endpoints{{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "4.3.2.1"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
expectUpdate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "no existing endpoints",
|
||||
serviceName: "foo",
|
||||
ip: "1.2.3.4",
|
||||
endpointPorts: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
endpoints: nil,
|
||||
expectCreate: &api.Endpoints{
|
||||
ObjectMeta: om("foo"),
|
||||
Subsets: []api.EndpointSubset{{
|
||||
Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}},
|
||||
Ports: []api.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
|
||||
}},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range non_reconcile_tests {
|
||||
fakeClient := fake.NewSimpleClientset()
|
||||
if test.endpoints != nil {
|
||||
fakeClient = fake.NewSimpleClientset(test.endpoints)
|
||||
}
|
||||
reconciler := reconcilers.NewMasterCountEndpointReconciler(test.additionalMasters+1, fakeClient.Core())
|
||||
err := reconciler.ReconcileEndpoints(test.serviceName, net.ParseIP(test.ip), test.endpointPorts, false)
|
||||
if err != nil {
|
||||
t.Errorf("case %q: unexpected error: %v", test.testName, err)
|
||||
}
|
||||
|
||||
updates := []core.UpdateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() != "update" {
|
||||
continue
|
||||
}
|
||||
updates = append(updates, action.(core.UpdateAction))
|
||||
}
|
||||
if test.expectUpdate != nil {
|
||||
if len(updates) != 1 {
|
||||
t.Errorf("case %q: unexpected updates: %v", test.testName, updates)
|
||||
} else if e, a := test.expectUpdate, updates[0].GetObject(); !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
if test.expectUpdate == nil && len(updates) > 0 {
|
||||
t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates)
|
||||
}
|
||||
|
||||
creates := []core.CreateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() != "create" {
|
||||
continue
|
||||
}
|
||||
creates = append(creates, action.(core.CreateAction))
|
||||
}
|
||||
if test.expectCreate != nil {
|
||||
if len(creates) != 1 {
|
||||
t.Errorf("case %q: unexpected creates: %v", test.testName, creates)
|
||||
} else if e, a := test.expectCreate, creates[0].GetObject(); !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected create:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
if test.expectCreate == nil && len(creates) > 0 {
|
||||
t.Errorf("case %q: no create expected, yet saw: %v", test.testName, creates)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestCreateOrUpdateMasterService(t *testing.T) {
|
||||
ns := metav1.NamespaceDefault
|
||||
om := func(name string) metav1.ObjectMeta {
|
||||
return metav1.ObjectMeta{Namespace: ns, Name: name}
|
||||
}
|
||||
|
||||
create_tests := []struct {
|
||||
testName string
|
||||
serviceName string
|
||||
servicePorts []api.ServicePort
|
||||
serviceType api.ServiceType
|
||||
expectCreate *api.Service // nil means none expected
|
||||
}{
|
||||
{
|
||||
testName: "service does not exist",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
expectCreate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range create_tests {
|
||||
master := Controller{}
|
||||
fakeClient := fake.NewSimpleClientset()
|
||||
master.ServiceClient = fakeClient.Core()
|
||||
master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, net.ParseIP("1.2.3.4"), test.servicePorts, test.serviceType, false)
|
||||
creates := []core.CreateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() == "create" {
|
||||
creates = append(creates, action.(core.CreateAction))
|
||||
}
|
||||
}
|
||||
if test.expectCreate != nil {
|
||||
if len(creates) != 1 {
|
||||
t.Errorf("case %q: unexpected creations: %v", test.testName, creates)
|
||||
} else {
|
||||
obj := creates[0].GetObject()
|
||||
if e, a := test.expectCreate.Spec, obj.(*api.Service).Spec; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected create:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
if test.expectCreate == nil && len(creates) > 1 {
|
||||
t.Errorf("case %q: no create expected, yet saw: %v", test.testName, creates)
|
||||
}
|
||||
}
|
||||
|
||||
reconcile_tests := []struct {
|
||||
testName string
|
||||
serviceName string
|
||||
servicePorts []api.ServicePort
|
||||
serviceType api.ServiceType
|
||||
service *api.Service
|
||||
expectUpdate *api.Service // nil means none expected
|
||||
}{
|
||||
{
|
||||
testName: "service definition wrong port",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8000, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition missing port",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
{Name: "baz", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
{Name: "baz", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition incorrect port",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "bar", Port: 1000, Protocol: "UDP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition incorrect port name",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 1000, Protocol: "UDP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition incorrect target port",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition incorrect protocol",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "UDP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition has incorrect type",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeNodePort,
|
||||
},
|
||||
},
|
||||
expectUpdate: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
testName: "service definition satisfies",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: nil,
|
||||
},
|
||||
}
|
||||
for _, test := range reconcile_tests {
|
||||
master := Controller{}
|
||||
fakeClient := fake.NewSimpleClientset(test.service)
|
||||
master.ServiceClient = fakeClient.Core()
|
||||
err := master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, net.ParseIP("1.2.3.4"), test.servicePorts, test.serviceType, true)
|
||||
if err != nil {
|
||||
t.Errorf("case %q: unexpected error: %v", test.testName, err)
|
||||
}
|
||||
updates := []core.UpdateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() == "update" {
|
||||
updates = append(updates, action.(core.UpdateAction))
|
||||
}
|
||||
}
|
||||
if test.expectUpdate != nil {
|
||||
if len(updates) != 1 {
|
||||
t.Errorf("case %q: unexpected updates: %v", test.testName, updates)
|
||||
} else {
|
||||
obj := updates[0].GetObject()
|
||||
if e, a := test.expectUpdate.Spec, obj.(*api.Service).Spec; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
if test.expectUpdate == nil && len(updates) > 0 {
|
||||
t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates)
|
||||
}
|
||||
}
|
||||
|
||||
non_reconcile_tests := []struct {
|
||||
testName string
|
||||
serviceName string
|
||||
servicePorts []api.ServicePort
|
||||
serviceType api.ServiceType
|
||||
service *api.Service
|
||||
expectUpdate *api.Service // nil means none expected
|
||||
}{
|
||||
{
|
||||
testName: "service definition wrong port, no expected update",
|
||||
serviceName: "foo",
|
||||
servicePorts: []api.ServicePort{
|
||||
{Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt(8080)},
|
||||
},
|
||||
serviceType: api.ServiceTypeClusterIP,
|
||||
service: &api.Service{
|
||||
ObjectMeta: om("foo"),
|
||||
Spec: api.ServiceSpec{
|
||||
Ports: []api.ServicePort{
|
||||
{Name: "foo", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt(1000)},
|
||||
},
|
||||
Selector: nil,
|
||||
ClusterIP: "1.2.3.4",
|
||||
SessionAffinity: api.ServiceAffinityClientIP,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
},
|
||||
},
|
||||
expectUpdate: nil,
|
||||
},
|
||||
}
|
||||
for _, test := range non_reconcile_tests {
|
||||
master := Controller{}
|
||||
fakeClient := fake.NewSimpleClientset(test.service)
|
||||
master.ServiceClient = fakeClient.Core()
|
||||
err := master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, net.ParseIP("1.2.3.4"), test.servicePorts, test.serviceType, false)
|
||||
if err != nil {
|
||||
t.Errorf("case %q: unexpected error: %v", test.testName, err)
|
||||
}
|
||||
updates := []core.UpdateAction{}
|
||||
for _, action := range fakeClient.Actions() {
|
||||
if action.GetVerb() == "update" {
|
||||
updates = append(updates, action.(core.UpdateAction))
|
||||
}
|
||||
}
|
||||
if test.expectUpdate != nil {
|
||||
if len(updates) != 1 {
|
||||
t.Errorf("case %q: unexpected updates: %v", test.testName, updates)
|
||||
} else {
|
||||
obj := updates[0].GetObject()
|
||||
if e, a := test.expectUpdate.Spec, obj.(*api.Service).Spec; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
if test.expectUpdate == nil && len(updates) > 0 {
|
||||
t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates)
|
||||
}
|
||||
}
|
||||
}
|
||||
187
vendor/k8s.io/kubernetes/pkg/master/import_known_versions_test.go
generated
vendored
187
vendor/k8s.io/kubernetes/pkg/master/import_known_versions_test.go
generated
vendored
|
|
@ -1,187 +0,0 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
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 master
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
)
|
||||
|
||||
func TestGroupVersions(t *testing.T) {
|
||||
// legacyUnsuffixedGroups contains the groups released prior to deciding that kubernetes API groups should be dns-suffixed
|
||||
// new groups should be suffixed with ".k8s.io" (https://github.com/kubernetes/kubernetes/pull/31887#issuecomment-244462396)
|
||||
legacyUnsuffixedGroups := sets.NewString(
|
||||
"",
|
||||
"apps",
|
||||
"autoscaling",
|
||||
"batch",
|
||||
"componentconfig",
|
||||
"extensions",
|
||||
"policy",
|
||||
)
|
||||
|
||||
// No new groups should be added to the legacyUnsuffixedGroups exclusion list
|
||||
if len(legacyUnsuffixedGroups) != 7 {
|
||||
t.Errorf("No additional unnamespaced groups should be created")
|
||||
}
|
||||
|
||||
for _, gv := range legacyscheme.Registry.RegisteredGroupVersions() {
|
||||
if !strings.HasSuffix(gv.Group, ".k8s.io") && !legacyUnsuffixedGroups.Has(gv.Group) {
|
||||
t.Errorf("Group %s does not have the standard kubernetes API group suffix of .k8s.io", gv.Group)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTypeTags(t *testing.T) {
|
||||
for gvk, knownType := range legacyscheme.Scheme.AllKnownTypes() {
|
||||
if gvk.Version == runtime.APIVersionInternal {
|
||||
ensureNoTags(t, gvk, knownType, nil)
|
||||
} else {
|
||||
ensureTags(t, gvk, knownType, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These types are registered in external versions, and therefore include json tags,
|
||||
// but are also registered in internal versions (or referenced from internal types),
|
||||
// so we explicitly allow tags for them
|
||||
var typesAllowedTags = map[reflect.Type]bool{
|
||||
reflect.TypeOf(intstr.IntOrString{}): true,
|
||||
reflect.TypeOf(metav1.Time{}): true,
|
||||
reflect.TypeOf(metav1.MicroTime{}): true,
|
||||
reflect.TypeOf(metav1.Duration{}): true,
|
||||
reflect.TypeOf(metav1.TypeMeta{}): true,
|
||||
reflect.TypeOf(metav1.ListMeta{}): true,
|
||||
reflect.TypeOf(metav1.ObjectMeta{}): true,
|
||||
reflect.TypeOf(metav1.OwnerReference{}): true,
|
||||
reflect.TypeOf(metav1.LabelSelector{}): true,
|
||||
reflect.TypeOf(metav1.GetOptions{}): true,
|
||||
reflect.TypeOf(metav1.ExportOptions{}): true,
|
||||
reflect.TypeOf(metav1.ListOptions{}): true,
|
||||
reflect.TypeOf(metav1.DeleteOptions{}): true,
|
||||
reflect.TypeOf(metav1.GroupVersionKind{}): true,
|
||||
reflect.TypeOf(metav1.GroupVersionResource{}): true,
|
||||
reflect.TypeOf(metav1.Status{}): true,
|
||||
}
|
||||
|
||||
func ensureNoTags(t *testing.T, gvk schema.GroupVersionKind, tp reflect.Type, parents []reflect.Type) {
|
||||
if _, ok := typesAllowedTags[tp]; ok {
|
||||
return
|
||||
}
|
||||
|
||||
parents = append(parents, tp)
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.Map, reflect.Slice, reflect.Ptr:
|
||||
ensureNoTags(t, gvk, tp.Elem(), parents)
|
||||
|
||||
case reflect.String, reflect.Bool, reflect.Float32, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uintptr, reflect.Uint32, reflect.Uint64, reflect.Interface:
|
||||
// no-op
|
||||
|
||||
case reflect.Struct:
|
||||
for i := 0; i < tp.NumField(); i++ {
|
||||
f := tp.Field(i)
|
||||
if f.PkgPath != "" {
|
||||
continue // Ignore unexported fields
|
||||
}
|
||||
jsonTag := f.Tag.Get("json")
|
||||
protoTag := f.Tag.Get("protobuf")
|
||||
if len(jsonTag) > 0 || len(protoTag) > 0 {
|
||||
t.Errorf("Internal types should not have json or protobuf tags. %#v has tag on field %v: %v", gvk, f.Name, f.Tag)
|
||||
for i, tp := range parents {
|
||||
t.Logf("%s%v:", strings.Repeat(" ", i), tp)
|
||||
}
|
||||
}
|
||||
|
||||
ensureNoTags(t, gvk, f.Type, parents)
|
||||
}
|
||||
|
||||
default:
|
||||
t.Errorf("Unexpected type %v in %#v", tp.Kind(), gvk)
|
||||
for i, tp := range parents {
|
||||
t.Logf("%s%v:", strings.Repeat(" ", i), tp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
|
||||
)
|
||||
|
||||
// These fields are limited exceptions to the standard JSON naming structure.
|
||||
// Additions should only be made if a non-standard field name was released and cannot be changed for compatibility reasons.
|
||||
var allowedNonstandardJSONNames = map[reflect.Type]string{
|
||||
reflect.TypeOf(v1.DaemonEndpoint{}): "Port",
|
||||
}
|
||||
|
||||
func ensureTags(t *testing.T, gvk schema.GroupVersionKind, tp reflect.Type, parents []reflect.Type) {
|
||||
// This type handles its own encoding/decoding and doesn't need json tags
|
||||
if tp.Implements(marshalerType) && (tp.Implements(unmarshalerType) || reflect.PtrTo(tp).Implements(unmarshalerType)) {
|
||||
return
|
||||
}
|
||||
|
||||
parents = append(parents, tp)
|
||||
|
||||
switch tp.Kind() {
|
||||
case reflect.Map, reflect.Slice, reflect.Ptr:
|
||||
ensureTags(t, gvk, tp.Elem(), parents)
|
||||
|
||||
case reflect.String, reflect.Bool, reflect.Float32, reflect.Int, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uintptr, reflect.Uint32, reflect.Uint64, reflect.Interface:
|
||||
// no-op
|
||||
|
||||
case reflect.Struct:
|
||||
for i := 0; i < tp.NumField(); i++ {
|
||||
f := tp.Field(i)
|
||||
jsonTag := f.Tag.Get("json")
|
||||
if len(jsonTag) == 0 {
|
||||
t.Errorf("External types should have json tags. %#v tags on field %v are: %s", gvk, f.Name, f.Tag)
|
||||
for i, tp := range parents {
|
||||
t.Logf("%s%v", strings.Repeat(" ", i), tp)
|
||||
}
|
||||
}
|
||||
|
||||
jsonTagName := strings.Split(jsonTag, ",")[0]
|
||||
if len(jsonTagName) > 0 && (jsonTagName[0] < 'a' || jsonTagName[0] > 'z') && jsonTagName != "-" && allowedNonstandardJSONNames[tp] != jsonTagName {
|
||||
t.Errorf("External types should have json names starting with lowercase letter. %#v has json tag on field %v with name %s", gvk, f.Name, jsonTagName)
|
||||
t.Log(tp)
|
||||
t.Log(allowedNonstandardJSONNames[tp])
|
||||
for i, tp := range parents {
|
||||
t.Logf("%s%v", strings.Repeat(" ", i), tp)
|
||||
}
|
||||
}
|
||||
|
||||
ensureTags(t, gvk, f.Type, parents)
|
||||
}
|
||||
|
||||
default:
|
||||
t.Errorf("Unexpected type %v in %#v", tp.Kind(), gvk)
|
||||
for i, tp := range parents {
|
||||
t.Logf("%s%v:", strings.Repeat(" ", i), tp)
|
||||
}
|
||||
}
|
||||
}
|
||||
97
vendor/k8s.io/kubernetes/pkg/master/master_openapi_test.go
generated
vendored
97
vendor/k8s.io/kubernetes/pkg/master/master_openapi_test.go
generated
vendored
|
|
@ -1,97 +0,0 @@
|
|||
// +build !race
|
||||
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
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 master
|
||||
|
||||
// This test file is separated from master_test.go so we would be able to disable
|
||||
// race check for it. TestValidOpenAPISpec will became extremely slow if -race
|
||||
// flag exists, and will cause the tests to timeout.
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
apirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
openapigen "k8s.io/kubernetes/pkg/generated/openapi"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// TestValidOpenAPISpec verifies that the open api is added
|
||||
// at the proper endpoint and the spec is valid.
|
||||
func TestValidOpenAPISpec(t *testing.T) {
|
||||
etcdserver, config, sharedInformers, assert := setUp(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
config.GenericConfig.EnableIndex = true
|
||||
config.GenericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapigen.GetOpenAPIDefinitions, legacyscheme.Scheme)
|
||||
config.GenericConfig.OpenAPIConfig.Info = &spec.Info{
|
||||
InfoProps: spec.InfoProps{
|
||||
Title: "Kubernetes",
|
||||
Version: "unversioned",
|
||||
},
|
||||
}
|
||||
config.GenericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig()
|
||||
|
||||
master, err := config.Complete(sharedInformers).New(genericapiserver.EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the master: %v", err)
|
||||
}
|
||||
|
||||
// make sure swagger.json is not registered before calling PrepareRun.
|
||||
server := httptest.NewServer(apirequest.WithRequestContext(master.GenericAPIServer.Handler.Director, master.GenericAPIServer.RequestContextMapper()))
|
||||
defer server.Close()
|
||||
resp, err := http.Get(server.URL + "/swagger.json")
|
||||
if !assert.NoError(err) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
assert.Equal(http.StatusNotFound, resp.StatusCode)
|
||||
|
||||
master.GenericAPIServer.PrepareRun()
|
||||
|
||||
resp, err = http.Get(server.URL + "/swagger.json")
|
||||
if !assert.NoError(err) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
assert.Equal(http.StatusOK, resp.StatusCode)
|
||||
|
||||
// as json schema
|
||||
var sch spec.Schema
|
||||
if assert.NoError(decodeResponse(resp, &sch)) {
|
||||
validator := validate.NewSchemaValidator(spec.MustLoadSwagger20Schema(), nil, "", strfmt.Default)
|
||||
res := validator.Validate(&sch)
|
||||
assert.NoError(res.AsError())
|
||||
}
|
||||
|
||||
// Validate OpenApi spec
|
||||
doc, err := loads.Spec(server.URL + "/swagger.json")
|
||||
if assert.NoError(err) {
|
||||
validator := validate.NewSpecValidator(doc.Schema(), strfmt.Default)
|
||||
res, warns := validator.Validate(doc)
|
||||
assert.NoError(res.AsError())
|
||||
if !warns.IsValid() {
|
||||
t.Logf("Open API spec on root has some warnings : %v", warns)
|
||||
}
|
||||
}
|
||||
}
|
||||
360
vendor/k8s.io/kubernetes/pkg/master/master_test.go
generated
vendored
360
vendor/k8s.io/kubernetes/pkg/master/master_test.go
generated
vendored
|
|
@ -1,360 +0,0 @@
|
|||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
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 master
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/options"
|
||||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
"k8s.io/kubernetes/pkg/apis/certificates"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
|
||||
"k8s.io/kubernetes/pkg/master/reconcilers"
|
||||
certificatesrest "k8s.io/kubernetes/pkg/registry/certificates/rest"
|
||||
corerest "k8s.io/kubernetes/pkg/registry/core/rest"
|
||||
"k8s.io/kubernetes/pkg/registry/registrytest"
|
||||
kubeversion "k8s.io/kubernetes/pkg/version"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// setUp is a convience function for setting up for (most) tests.
|
||||
func setUp(t *testing.T) (*etcdtesting.EtcdTestServer, Config, informers.SharedInformerFactory, *assert.Assertions) {
|
||||
server, storageConfig := etcdtesting.NewUnsecuredEtcd3TestClientServer(t)
|
||||
|
||||
config := &Config{
|
||||
GenericConfig: genericapiserver.NewConfig(legacyscheme.Codecs),
|
||||
ExtraConfig: ExtraConfig{
|
||||
APIResourceConfigSource: DefaultAPIResourceConfigSource(),
|
||||
APIServerServicePort: 443,
|
||||
MasterCount: 1,
|
||||
EndpointReconcilerType: reconcilers.MasterCountReconcilerType,
|
||||
},
|
||||
}
|
||||
|
||||
resourceEncoding := serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Registry)
|
||||
resourceEncoding.SetVersionEncoding(api.GroupName, legacyscheme.Registry.GroupOrDie(api.GroupName).GroupVersion, schema.GroupVersion{Group: api.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetVersionEncoding(autoscaling.GroupName, *testapi.Autoscaling.GroupVersion(), schema.GroupVersion{Group: autoscaling.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetVersionEncoding(batch.GroupName, *testapi.Batch.GroupVersion(), schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal})
|
||||
// FIXME (soltysh): this GroupVersionResource override should be configurable
|
||||
resourceEncoding.SetResourceEncoding(schema.GroupResource{Group: "batch", Resource: "cronjobs"}, schema.GroupVersion{Group: batch.GroupName, Version: "v1beta1"}, schema.GroupVersion{Group: batch.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetResourceEncoding(schema.GroupResource{Group: "storage.k8s.io", Resource: "volumeattachments"}, schema.GroupVersion{Group: storage.GroupName, Version: "v1beta1"}, schema.GroupVersion{Group: storage.GroupName, Version: runtime.APIVersionInternal})
|
||||
|
||||
resourceEncoding.SetVersionEncoding(apps.GroupName, *testapi.Apps.GroupVersion(), schema.GroupVersion{Group: apps.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetVersionEncoding(extensions.GroupName, *testapi.Extensions.GroupVersion(), schema.GroupVersion{Group: extensions.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetVersionEncoding(rbac.GroupName, *testapi.Rbac.GroupVersion(), schema.GroupVersion{Group: rbac.GroupName, Version: runtime.APIVersionInternal})
|
||||
resourceEncoding.SetVersionEncoding(certificates.GroupName, *testapi.Certificates.GroupVersion(), schema.GroupVersion{Group: certificates.GroupName, Version: runtime.APIVersionInternal})
|
||||
storageFactory := serverstorage.NewDefaultStorageFactory(*storageConfig, testapi.StorageMediaType(), legacyscheme.Codecs, resourceEncoding, DefaultAPIResourceConfigSource(), nil)
|
||||
|
||||
etcdOptions := options.NewEtcdOptions(storageConfig)
|
||||
// unit tests don't need watch cache and it leaks lots of goroutines with etcd testing functions during unit tests
|
||||
etcdOptions.EnableWatchCache = false
|
||||
err := etcdOptions.ApplyWithStorageFactoryTo(storageFactory, config.GenericConfig)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
kubeVersion := kubeversion.Get()
|
||||
config.GenericConfig.Version = &kubeVersion
|
||||
config.ExtraConfig.StorageFactory = storageFactory
|
||||
config.GenericConfig.LoopbackClientConfig = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs}}
|
||||
config.GenericConfig.PublicAddress = net.ParseIP("192.168.10.4")
|
||||
config.GenericConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
|
||||
config.GenericConfig.RequestContextMapper = genericapirequest.NewRequestContextMapper()
|
||||
config.GenericConfig.LoopbackClientConfig = &restclient.Config{APIPath: "/api", ContentConfig: restclient.ContentConfig{NegotiatedSerializer: legacyscheme.Codecs}}
|
||||
config.GenericConfig.EnableMetrics = true
|
||||
config.ExtraConfig.EnableCoreControllers = false
|
||||
config.ExtraConfig.KubeletClientConfig = kubeletclient.KubeletClientConfig{Port: 10250}
|
||||
config.ExtraConfig.ProxyTransport = utilnet.SetTransportDefaults(&http.Transport{
|
||||
Dial: func(network, addr string) (net.Conn, error) { return nil, nil },
|
||||
TLSClientConfig: &tls.Config{},
|
||||
})
|
||||
|
||||
clientset, err := kubernetes.NewForConfig(config.GenericConfig.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create client set due to %v", err)
|
||||
}
|
||||
sharedInformers := informers.NewSharedInformerFactory(clientset, config.GenericConfig.LoopbackClientConfig.Timeout)
|
||||
|
||||
return server, *config, sharedInformers, assert.New(t)
|
||||
}
|
||||
|
||||
// TestLegacyRestStorageStrategies ensures that all Storage objects which are using the generic registry Store have
|
||||
// their various strategies properly wired up. This surfaced as a bug where strategies defined Export functions, but
|
||||
// they were never used outside of unit tests because the export strategies were not assigned inside the Store.
|
||||
func TestLegacyRestStorageStrategies(t *testing.T) {
|
||||
_, etcdserver, masterCfg, _ := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
storageProvider := corerest.LegacyRESTStorageProvider{
|
||||
StorageFactory: masterCfg.ExtraConfig.StorageFactory,
|
||||
ProxyTransport: masterCfg.ExtraConfig.ProxyTransport,
|
||||
KubeletClientConfig: masterCfg.ExtraConfig.KubeletClientConfig,
|
||||
EventTTL: masterCfg.ExtraConfig.EventTTL,
|
||||
ServiceIPRange: masterCfg.ExtraConfig.ServiceIPRange,
|
||||
ServiceNodePortRange: masterCfg.ExtraConfig.ServiceNodePortRange,
|
||||
LoopbackClientConfig: masterCfg.GenericConfig.LoopbackClientConfig,
|
||||
}
|
||||
|
||||
_, apiGroupInfo, err := storageProvider.NewLegacyRESTStorage(masterCfg.GenericConfig.RESTOptionsGetter)
|
||||
if err != nil {
|
||||
t.Errorf("failed to create legacy REST storage: %v", err)
|
||||
}
|
||||
|
||||
// Any new stores with export logic will need to be added here:
|
||||
exceptions := registrytest.StrategyExceptions{
|
||||
// Only these stores should have an export strategy defined:
|
||||
HasExportStrategy: []string{
|
||||
"secrets",
|
||||
"limitRanges",
|
||||
"nodes",
|
||||
"podTemplates",
|
||||
},
|
||||
}
|
||||
|
||||
strategyErrors := registrytest.ValidateStorageStrategies(apiGroupInfo.VersionedResourcesStorageMap["v1"], exceptions)
|
||||
for _, err := range strategyErrors {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCertificatesRestStorageStrategies(t *testing.T) {
|
||||
_, etcdserver, masterCfg, _ := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
certStorageProvider := certificatesrest.RESTStorageProvider{}
|
||||
apiGroupInfo, _ := certStorageProvider.NewRESTStorage(masterCfg.ExtraConfig.APIResourceConfigSource, masterCfg.GenericConfig.RESTOptionsGetter)
|
||||
|
||||
exceptions := registrytest.StrategyExceptions{
|
||||
HasExportStrategy: []string{
|
||||
"certificatesigningrequests",
|
||||
},
|
||||
}
|
||||
|
||||
strategyErrors := registrytest.ValidateStorageStrategies(
|
||||
apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1beta1.SchemeGroupVersion.Version], exceptions)
|
||||
for _, err := range strategyErrors {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func newMaster(t *testing.T) (*Master, *etcdtesting.EtcdTestServer, Config, *assert.Assertions) {
|
||||
etcdserver, config, sharedInformers, assert := setUp(t)
|
||||
|
||||
master, err := config.Complete(sharedInformers).New(genericapiserver.EmptyDelegate)
|
||||
if err != nil {
|
||||
t.Fatalf("Error in bringing up the master: %v", err)
|
||||
}
|
||||
|
||||
return master, etcdserver, config, assert
|
||||
}
|
||||
|
||||
// TestVersion tests /version
|
||||
func TestVersion(t *testing.T) {
|
||||
s, etcdserver, _, _ := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
req, _ := http.NewRequest("GET", "/version", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
s.GenericAPIServer.Handler.ServeHTTP(resp, req)
|
||||
if resp.Code != 200 {
|
||||
t.Fatalf("expected http 200, got: %d", resp.Code)
|
||||
}
|
||||
|
||||
var info version.Info
|
||||
err := json.NewDecoder(resp.Body).Decode(&info)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(kubeversion.Get(), info) {
|
||||
t.Errorf("Expected %#v, Got %#v", kubeversion.Get(), info)
|
||||
}
|
||||
}
|
||||
|
||||
type fakeEndpointReconciler struct{}
|
||||
|
||||
func (*fakeEndpointReconciler) ReconcileEndpoints(serviceName string, ip net.IP, endpointPorts []api.EndpointPort, reconcilePorts bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeNodeList(nodes []string, nodeResources apiv1.NodeResources) *apiv1.NodeList {
|
||||
list := apiv1.NodeList{
|
||||
Items: make([]apiv1.Node, len(nodes)),
|
||||
}
|
||||
for i := range nodes {
|
||||
list.Items[i].Name = nodes[i]
|
||||
list.Items[i].Status.Capacity = nodeResources.Capacity
|
||||
}
|
||||
return &list
|
||||
}
|
||||
|
||||
// TestGetNodeAddresses verifies that proper results are returned
|
||||
// when requesting node addresses.
|
||||
func TestGetNodeAddresses(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
fakeNodeClient := fake.NewSimpleClientset(makeNodeList([]string{"node1", "node2"}, apiv1.NodeResources{})).Core().Nodes()
|
||||
addressProvider := nodeAddressProvider{fakeNodeClient}
|
||||
|
||||
// Fail case (no addresses associated with nodes)
|
||||
nodes, _ := fakeNodeClient.List(metav1.ListOptions{})
|
||||
addrs, err := addressProvider.externalAddresses()
|
||||
|
||||
assert.Error(err, "addresses should have caused an error as there are no addresses.")
|
||||
assert.Equal([]string(nil), addrs)
|
||||
|
||||
// Pass case with External type IP
|
||||
nodes, _ = fakeNodeClient.List(metav1.ListOptions{})
|
||||
for index := range nodes.Items {
|
||||
nodes.Items[index].Status.Addresses = []apiv1.NodeAddress{{Type: apiv1.NodeExternalIP, Address: "127.0.0.1"}}
|
||||
fakeNodeClient.Update(&nodes.Items[index])
|
||||
}
|
||||
addrs, err = addressProvider.externalAddresses()
|
||||
assert.NoError(err, "addresses should not have returned an error.")
|
||||
assert.Equal([]string{"127.0.0.1", "127.0.0.1"}, addrs)
|
||||
}
|
||||
|
||||
func decodeResponse(resp *http.Response, obj interface{}) error {
|
||||
defer resp.Body.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(data, obj); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Because we need to be backwards compatible with release 1.1, at endpoints
|
||||
// that exist in release 1.1, the responses should have empty APIVersion.
|
||||
func TestAPIVersionOfDiscoveryEndpoints(t *testing.T) {
|
||||
master, etcdserver, _, assert := newMaster(t)
|
||||
defer etcdserver.Terminate(t)
|
||||
|
||||
server := httptest.NewServer(genericapirequest.WithRequestContext(master.GenericAPIServer.Handler.GoRestfulContainer.ServeMux, master.GenericAPIServer.RequestContextMapper()))
|
||||
|
||||
// /api exists in release-1.1
|
||||
resp, err := http.Get(server.URL + "/api")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
apiVersions := metav1.APIVersions{}
|
||||
assert.NoError(decodeResponse(resp, &apiVersions))
|
||||
assert.Equal(apiVersions.APIVersion, "")
|
||||
|
||||
// /api/v1 exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/api/v1")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
resourceList := metav1.APIResourceList{}
|
||||
assert.NoError(decodeResponse(resp, &resourceList))
|
||||
assert.Equal(resourceList.APIVersion, "")
|
||||
|
||||
// /apis exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/apis")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
groupList := metav1.APIGroupList{}
|
||||
assert.NoError(decodeResponse(resp, &groupList))
|
||||
assert.Equal(groupList.APIVersion, "")
|
||||
|
||||
// /apis/extensions exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/apis/extensions")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
group := metav1.APIGroup{}
|
||||
assert.NoError(decodeResponse(resp, &group))
|
||||
assert.Equal(group.APIVersion, "")
|
||||
|
||||
// /apis/extensions/v1beta1 exists in release-1.1
|
||||
resp, err = http.Get(server.URL + "/apis/extensions/v1beta1")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
resourceList = metav1.APIResourceList{}
|
||||
assert.NoError(decodeResponse(resp, &resourceList))
|
||||
assert.Equal(resourceList.APIVersion, "")
|
||||
|
||||
// /apis/autoscaling doesn't exist in release-1.1, so the APIVersion field
|
||||
// should be non-empty in the results returned by the server.
|
||||
resp, err = http.Get(server.URL + "/apis/autoscaling")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
group = metav1.APIGroup{}
|
||||
assert.NoError(decodeResponse(resp, &group))
|
||||
assert.Equal(group.APIVersion, "v1")
|
||||
|
||||
// apis/autoscaling/v1 doesn't exist in release-1.1, so the APIVersion field
|
||||
// should be non-empty in the results returned by the server.
|
||||
|
||||
resp, err = http.Get(server.URL + "/apis/autoscaling/v1")
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
resourceList = metav1.APIResourceList{}
|
||||
assert.NoError(decodeResponse(resp, &resourceList))
|
||||
assert.Equal(resourceList.APIVersion, "v1")
|
||||
|
||||
}
|
||||
|
||||
func TestNoAlphaVersionsEnabledByDefault(t *testing.T) {
|
||||
config := DefaultAPIResourceConfigSource()
|
||||
for gv, enable := range config.GroupVersionConfigs {
|
||||
if enable && strings.Contains(gv.Version, "alpha") {
|
||||
t.Errorf("Alpha API version %s enabled by default", gv.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue