func TestRCManagerNotReady(t *testing.T) { client := client.NewOrDie(&client.Config{Host: "", Version: testapi.Version()}) fakePodControl := FakePodControl{} manager := NewReplicationManager(client, 2) manager.podControl = &fakePodControl manager.podStoreSynced = func() bool { return false } // Simulates the rc reflector running before the pod reflector. We don't // want to end up creating replicas in this case until the pod reflector // has synced, so the rc manager should just requeue the rc. controllerSpec := newReplicationController(1) manager.rcStore.Store.Add(controllerSpec) rcKey := getKey(controllerSpec, t) manager.syncReplicationController(rcKey) validateSyncReplication(t, &fakePodControl, 0, 0) queueRC, _ := manager.queue.Get() if queueRC != rcKey { t.Fatalf("Expected to find key %v in queue, found %v", rcKey, queueRC) } manager.podStoreSynced = alwaysReady manager.syncReplicationController(rcKey) validateSyncReplication(t, &fakePodControl, 1, 0) }
func TestDeleteFinalStateUnknown(t *testing.T) { client := client.NewOrDie(&client.Config{Host: "", Version: testapi.Version()}) fakePodControl := FakePodControl{} manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady manager.podControl = &fakePodControl received := make(chan string) manager.syncHandler = func(key string) error { received <- key return nil } // The DeletedFinalStateUnknown object should cause the rc manager to insert // the controller matching the selectors of the deleted pod into the work queue. controllerSpec := newReplicationController(1) manager.rcStore.Store.Add(controllerSpec) pods := newPodList(nil, 1, api.PodRunning, controllerSpec) manager.deletePod(cache.DeletedFinalStateUnknown{Key: "foo", Obj: &pods.Items[0]}) go manager.worker() expected := getKey(controllerSpec, t) select { case key := <-received: if key != expected { t.Errorf("Unexpected sync all for rc %v, expected %v", key, expected) } case <-time.After(100 * time.Millisecond): t.Errorf("Processing DeleteFinalStateUnknown took longer than expected") } }
func TestOverlappingRCs(t *testing.T) { client := client.NewOrDie(&client.Config{Host: "", Version: testapi.Version()}) for i := 0; i < 5; i++ { manager := NewReplicationManager(client, 10) manager.podStoreSynced = alwaysReady // Create 10 rcs, shuffled them randomly and insert them into the rc manager's store var controllers []*api.ReplicationController for j := 1; j < 10; j++ { controllerSpec := newReplicationController(1) controllerSpec.CreationTimestamp = util.Date(2014, time.December, j, 0, 0, 0, 0, time.Local) controllerSpec.Name = string(util.NewUUID()) controllers = append(controllers, controllerSpec) } shuffledControllers := shuffle(controllers) for j := range shuffledControllers { manager.rcStore.Store.Add(shuffledControllers[j]) } // Add a pod and make sure only the oldest rc is synced pods := newPodList(nil, 1, api.PodPending, controllers[0]) rcKey := getKey(controllers[0], t) manager.addPod(&pods.Items[0]) queueRC, _ := manager.queue.Get() if queueRC != rcKey { t.Fatalf("Expected to find key %v in queue, found %v", rcKey, queueRC) } } }
func TestCheckLeftoverEndpoints(t *testing.T) { ns := api.NamespaceDefault // Note that this requests *all* endpoints, therefore the NamespaceAll // below. testServer, _ := makeTestServer(t, api.NamespaceAll, serverResponse{http.StatusOK, &api.EndpointsList{ ListMeta: api.ListMeta{ ResourceVersion: "1", }, Items: []api.Endpoints{{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, ResourceVersion: "1", }, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "6.7.8.9"}}, Ports: []api.EndpointPort{{Port: 1000}}, }}, }}, }}) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) endpoints := NewEndpointController(client) endpoints.checkLeftoverEndpoints() if e, a := 1, endpoints.queue.Len(); e != a { t.Fatalf("Expected %v, got %v", e, a) } got, _ := endpoints.queue.Get() if e, a := ns+"/foo", got; e != a { t.Errorf("Expected %v, got %v", e, a) } }
func TestBind(t *testing.T) { table := []struct { binding *api.Binding }{ {binding: &api.Binding{ ObjectMeta: api.ObjectMeta{ Namespace: api.NamespaceDefault, Name: "foo", }, Target: api.ObjectReference{ Name: "foohost.kubernetes.mydomain.com", }, }}, } for _, item := range table { handler := util.FakeHandler{ StatusCode: 200, ResponseBody: "", T: t, } server := httptest.NewServer(&handler) defer server.Close() client := client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Version()}) b := binder{client} if err := b.Bind(item.binding); err != nil { t.Errorf("Unexpected error: %v", err) continue } expectedBody := runtime.EncodeOrDie(testapi.Codec(), item.binding) handler.ValidateRequest(t, testapi.ResourcePath("bindings", api.NamespaceDefault, ""), "POST", &expectedBody) } }
func TestSyncEndpointsProtocolUDP(t *testing.T) { ns := "other" testServer, endpointsHandler := makeTestServer(t, ns, serverResponse{http.StatusOK, &api.Endpoints{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, ResourceVersion: "1", }, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "6.7.8.9"}}, Ports: []api.EndpointPort{{Port: 1000, Protocol: "UDP"}}, }}, }}) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) endpoints := NewEndpointController(client) endpoints.serviceStore.Store.Add(&api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: ns}, Spec: api.ServiceSpec{ Selector: map[string]string{}, Ports: []api.ServicePort{{Port: 80}}, }, }) endpoints.syncService(ns + "/foo") endpointsHandler.ValidateRequestCount(t, 0) }
func TestSyncEndpointsItemsPreexistingIdentical(t *testing.T) { ns := api.NamespaceDefault testServer, endpointsHandler := makeTestServer(t, api.NamespaceDefault, serverResponse{http.StatusOK, &api.Endpoints{ ObjectMeta: api.ObjectMeta{ ResourceVersion: "1", Name: "foo", Namespace: ns, }, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, }}, }}) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) endpoints := NewEndpointController(client) addPods(endpoints.podStore.Store, api.NamespaceDefault, 1, 1) endpoints.serviceStore.Store.Add(&api.Service{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: api.NamespaceDefault}, Spec: api.ServiceSpec{ Selector: map[string]string{"foo": "bar"}, Ports: []api.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(8080)}}, }, }) endpoints.syncService(ns + "/foo") endpointsHandler.ValidateRequest(t, testapi.ResourcePath("endpoints", api.NamespaceDefault, "foo"), "GET", nil) }
// TestSecrets tests apiserver-side behavior of creation of secret objects and their use by pods. func TestSecrets(t *testing.T) { etcdStorage, err := framework.NewEtcdStorage() if err != nil { t.Fatalf("unexpected error: %v", err) } var m *master.Master s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { m.Handler.ServeHTTP(w, req) })) defer s.Close() m = master.New(&master.Config{ DatabaseStorage: etcdStorage, KubeletClient: client.FakeKubeletClient{}, EnableCoreControllers: true, EnableLogsSupport: false, EnableUISupport: false, EnableIndex: true, APIPrefix: "/api", Authorizer: apiserver.NewAlwaysAllowAuthorizer(), AdmissionControl: admit.NewAlwaysAdmit(), }) framework.DeleteAllEtcdKeys() client := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Version()}) DoTestSecrets(t, client, testapi.Version()) }
// NewMasterComponents creates, initializes and starts master components based on the given config. func NewMasterComponents(c *Config) *MasterComponents { m, s, e := startMasterOrDie(c.MasterConfig) // TODO: Allow callers to pipe through a different master url and create a client/start components using it. glog.Infof("Master %+v", s.URL) if c.DeleteEtcdKeys { DeleteAllEtcdKeys() } restClient := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Version(), QPS: c.QPS, Burst: c.Burst}) rcStopCh := make(chan struct{}) controllerManager := replicationcontroller.NewReplicationManager(restClient, c.Burst) // TODO: Support events once we can cleanly shutdown an event recorder. controllerManager.SetEventRecorder(&record.FakeRecorder{}) if c.StartReplicationManager { go controllerManager.Run(runtime.NumCPU(), rcStopCh) } var once sync.Once return &MasterComponents{ ApiServer: s, KubeMaster: m, RestClient: restClient, ControllerManager: controllerManager, rcStopCh: rcStopCh, EtcdStorage: e, once: once, } }
func TestPodControllerLookup(t *testing.T) { manager := NewReplicationManager(client.NewOrDie(&client.Config{Host: "", Version: testapi.Version()}), BurstReplicas) manager.podStoreSynced = alwaysReady testCases := []struct { inRCs []*api.ReplicationController pod *api.Pod outRCName string }{ // pods without labels don't match any rcs { inRCs: []*api.ReplicationController{ {ObjectMeta: api.ObjectMeta{Name: "basic"}}}, pod: &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo1", Namespace: api.NamespaceAll}}, outRCName: "", }, // Matching labels, not namespace { inRCs: []*api.ReplicationController{ { ObjectMeta: api.ObjectMeta{Name: "foo"}, Spec: api.ReplicationControllerSpec{ Selector: map[string]string{"foo": "bar"}, }, }, }, pod: &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo2", Namespace: "ns", Labels: map[string]string{"foo": "bar"}}}, outRCName: "", }, // Matching ns and labels returns the key to the rc, not the rc name { inRCs: []*api.ReplicationController{ { ObjectMeta: api.ObjectMeta{Name: "bar", Namespace: "ns"}, Spec: api.ReplicationControllerSpec{ Selector: map[string]string{"foo": "bar"}, }, }, }, pod: &api.Pod{ ObjectMeta: api.ObjectMeta{ Name: "foo3", Namespace: "ns", Labels: map[string]string{"foo": "bar"}}}, outRCName: "bar", }, } for _, c := range testCases { for _, r := range c.inRCs { manager.rcStore.Add(r) } if rc := manager.getPodController(c.pod); rc != nil { if c.outRCName != rc.Name { t.Errorf("Got controller %+v expected %+v", rc.Name, c.outRCName) } } else if c.outRCName != "" { t.Errorf("Expected a controller %v pod %v, found none", c.outRCName, c.pod.Name) } } }
func TestSyncReplicationControllerDormancy(t *testing.T) { // Setup a test server so we can lie about the current state of pods fakeHandler := util.FakeHandler{ StatusCode: 200, ResponseBody: "", } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) fakePodControl := FakePodControl{} manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady manager.podControl = &fakePodControl controllerSpec := newReplicationController(2) manager.rcStore.Store.Add(controllerSpec) newPodList(manager.podStore.Store, 1, api.PodRunning, controllerSpec) // Creates a replica and sets expectations controllerSpec.Status.Replicas = 1 manager.syncReplicationController(getKey(controllerSpec, t)) validateSyncReplication(t, &fakePodControl, 1, 0) // Expectations prevents replicas but not an update on status controllerSpec.Status.Replicas = 0 fakePodControl.clear() manager.syncReplicationController(getKey(controllerSpec, t)) validateSyncReplication(t, &fakePodControl, 0, 0) // Get the key for the controller rcKey, err := controller.KeyFunc(controllerSpec) if err != nil { t.Errorf("Couldn't get key for object %+v: %v", controllerSpec, err) } // Lowering expectations should lead to a sync that creates a replica, however the // fakePodControl error will prevent this, leaving expectations at 0, 0 manager.expectations.CreationObserved(rcKey) controllerSpec.Status.Replicas = 1 fakePodControl.clear() fakePodControl.err = fmt.Errorf("Fake Error") manager.syncReplicationController(getKey(controllerSpec, t)) validateSyncReplication(t, &fakePodControl, 0, 0) // This replica should not need a Lowering of expectations, since the previous create failed fakePodControl.err = nil manager.syncReplicationController(getKey(controllerSpec, t)) validateSyncReplication(t, &fakePodControl, 1, 0) // 1 PUT for the rc status during dormancy window. // Note that the pod creates go through pod control so they're not recorded. fakeHandler.ValidateRequestCount(t, 1) }
func TestNodes(t *testing.T) { // TODO(vishh): Get this test to work. t.Skip("skipping watch nodes test.") expectedNodeList := &api.NodeList{ Items: []api.Node{ { ObjectMeta: api.ObjectMeta{ Name: "test-machine-a", }, Status: api.NodeStatus{ Addresses: []api.NodeAddress{ { Type: api.NodeExternalIP, Address: "1.2.3.5", }, }, }, }, { ObjectMeta: api.ObjectMeta{ Name: "test-machine-b", }, Status: api.NodeStatus{ Addresses: []api.NodeAddress{ { Type: api.NodeExternalIP, Address: "1.2.3.4", }, }, }, }, }, } handler := util.FakeHandler{ StatusCode: 200, RequestBody: "", ResponseBody: body(expectedNodeList), T: t, } server := httptest.NewServer(&handler) defer server.Close() kubeClient := client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Version()}) kubeNodes, err := NewKubeNodes(kubeClient) require.NoError(t, err) nodeList, err := kubeNodes.List() require.NoError(t, err) fmt.Printf("%+v\n", nodeList) for _, expectedNode := range expectedNodeList.Items { node, ok := nodeList.Items[Host(expectedNode.Name)] assert.True(t, ok) assert.Equal(t, node.PublicIP, expectedNode.Status.Addresses[0].Address) } }
func TestCreate(t *testing.T) { handler := util.FakeHandler{ StatusCode: 500, ResponseBody: "", T: t, } server := httptest.NewServer(&handler) defer server.Close() client := client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Version()}) factory := NewConfigFactory(client) factory.Create() }
func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) { t := &testFactory{ Validator: validation.NullSchema{}, } generators := map[string]kubectl.Generator{ "run/v1": kubectl.BasicReplicationController{}, "run-pod/v1": kubectl.BasicPod{}, "service/v1": kubectl.ServiceGeneratorV1{}, "service/v2": kubectl.ServiceGeneratorV2{}, "service/test": testServiceGenerator{}, } f := &cmdutil.Factory{ Object: func() (meta.RESTMapper, runtime.ObjectTyper) { return latest.RESTMapper, api.Scheme }, Client: func() (*client.Client, error) { // Swap out the HTTP client out of the client with the fake's version. fakeClient := t.Client.(*client.FakeRESTClient) c := client.NewOrDie(t.ClientConfig) c.Client = fakeClient.Client return c, t.Err }, RESTClient: func(*meta.RESTMapping) (resource.RESTClient, error) { return t.Client, t.Err }, Describer: func(*meta.RESTMapping) (kubectl.Describer, error) { return t.Describer, t.Err }, Printer: func(mapping *meta.RESTMapping, noHeaders, withNamespace bool, wide bool, columnLabels []string) (kubectl.ResourcePrinter, error) { return t.Printer, t.Err }, Validator: func() (validation.Schema, error) { return t.Validator, t.Err }, DefaultNamespace: func() (string, bool, error) { return t.Namespace, false, t.Err }, ClientConfig: func() (*client.Config, error) { return t.ClientConfig, t.Err }, Generator: func(name string) (kubectl.Generator, bool) { generator, ok := generators[name] return generator, ok }, } rf := cmdutil.NewFactory(nil) f.PodSelectorForObject = rf.PodSelectorForObject return f, t, testapi.Codec() }
func TestCreate(t *testing.T) { handler := util.FakeHandler{ StatusCode: 500, ResponseBody: "", T: t, } server := httptest.NewServer(&handler) defer server.Close() client := client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Version()}) kubeNodes, err := NewKubeNodes(client) require.NoError(t, err) _, err = kubeNodes.List() require.NoError(t, err) }
func TestPodsApiCreation(t *testing.T) { handler := util.FakeHandler{ StatusCode: 200, RequestBody: "something", ResponseBody: body(&kube_api.PodList{}), T: t, } server := httptest.NewServer(&handler) defer server.Close() client := client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Version()}) podsApi := newPodsApi(client) _, err := podsApi.List(&nodes.NodeList{}) require.NoError(t, err) }
func TestSyncReplicationControllerCreates(t *testing.T) { client := client.NewOrDie(&client.Config{Host: "", Version: testapi.Version()}) manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady // A controller with 2 replicas and no pods in the store, 2 creates expected controller := newReplicationController(2) manager.rcStore.Store.Add(controller) fakePodControl := FakePodControl{} manager.podControl = &fakePodControl manager.syncReplicationController(getKey(controller, t)) validateSyncReplication(t, &fakePodControl, 2, 0) }
func TestListWatchesCanList(t *testing.T) { fieldSelectorQueryParamName := api.FieldSelectorQueryParam(testapi.Version()) table := []struct { location string resource string namespace string fieldSelector fields.Selector }{ // Minion { location: testapi.ResourcePath("minions", api.NamespaceAll, ""), resource: "minions", namespace: api.NamespaceAll, fieldSelector: parseSelectorOrDie(""), }, // pod with "assigned" field selector. { location: buildLocation( testapi.ResourcePath("pods", api.NamespaceAll, ""), buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}})), resource: "pods", namespace: api.NamespaceAll, fieldSelector: fields.Set{"spec.host": ""}.AsSelector(), }, // pod in namespace "foo" { location: buildLocation( testapi.ResourcePath("pods", "foo", ""), buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}})), resource: "pods", namespace: "foo", fieldSelector: fields.Set{"spec.host": ""}.AsSelector(), }, } for _, item := range table { handler := util.FakeHandler{ StatusCode: 500, ResponseBody: "", T: t, } server := httptest.NewServer(&handler) defer server.Close() client := client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Version()}) lw := NewListWatchFromClient(client, item.resource, item.namespace, item.fieldSelector) // This test merely tests that the correct request is made. lw.List() handler.ValidateRequest(t, item.location, "GET", nil) } }
func TestSyncReplicationControllerDoesNothing(t *testing.T) { client := client.NewOrDie(&client.Config{Host: "", Version: testapi.Version()}) fakePodControl := FakePodControl{} manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady // 2 running pods, a controller with 2 replicas, sync is a no-op controllerSpec := newReplicationController(2) manager.rcStore.Store.Add(controllerSpec) newPodList(manager.podStore.Store, 2, api.PodRunning, controllerSpec) manager.podControl = &fakePodControl manager.syncReplicationController(getKey(controllerSpec, t)) validateSyncReplication(t, &fakePodControl, 0, 0) }
func TestSyncReplicationControllerDeletes(t *testing.T) { client := client.NewOrDie(&client.Config{Host: "", Version: testapi.Version()}) fakePodControl := FakePodControl{} manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady manager.podControl = &fakePodControl // 2 running pods and a controller with 1 replica, one pod delete expected controllerSpec := newReplicationController(1) manager.rcStore.Store.Add(controllerSpec) newPodList(manager.podStore.Store, 2, api.PodRunning, controllerSpec) manager.syncReplicationController(getKey(controllerSpec, t)) validateSyncReplication(t, &fakePodControl, 0, 1) }
func TestSyncEndpointsItemsPreexistingLabelsChange(t *testing.T) { ns := "bar" testServer, endpointsHandler := makeTestServer(t, ns, serverResponse{http.StatusOK, &api.Endpoints{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, ResourceVersion: "1", Labels: map[string]string{ "foo": "bar", }, }, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "6.7.8.9"}}, Ports: []api.EndpointPort{{Port: 1000}}, }}, }}) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) endpoints := NewEndpointController(client) addPods(endpoints.podStore.Store, ns, 1, 1) serviceLabels := map[string]string{"baz": "blah"} endpoints.serviceStore.Store.Add(&api.Service{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, Labels: serviceLabels, }, Spec: api.ServiceSpec{ Selector: map[string]string{"foo": "bar"}, Ports: []api.ServicePort{{Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(8080)}}, }, }) endpoints.syncService(ns + "/foo") data := runtime.EncodeOrDie(testapi.Codec(), &api.Endpoints{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, ResourceVersion: "1", Labels: serviceLabels, }, Subsets: []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}}, Ports: []api.EndpointPort{{Port: 8080, Protocol: "TCP"}}, }}, }) endpointsHandler.ValidateRequest(t, testapi.ResourcePath("endpoints", ns, "foo"), "PUT", &data) }
func TestEventsBasic(t *testing.T) { handler := util.FakeHandler{ StatusCode: 200, RequestBody: "something", ResponseBody: body(&kube_api.EventList{}), T: t, } server := httptest.NewServer(&handler) defer server.Close() client := client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Version()}) cache := cache.NewCache(time.Hour, time.Hour) source := NewKubeEvents(client, cache) _, err := source.GetInfo(time.Now(), time.Now().Add(time.Minute), time.Second) require.NoError(t, err) require.NotEmpty(t, source.DebugInfo()) }
func TestSyncEndpointsItemsWithLabels(t *testing.T) { ns := "other" testServer, endpointsHandler := makeTestServer(t, ns, serverResponse{http.StatusOK, &api.Endpoints{}}) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) endpoints := NewEndpointController(client) addPods(endpoints.podStore.Store, ns, 3, 2) serviceLabels := map[string]string{"foo": "bar"} endpoints.serviceStore.Store.Add(&api.Service{ ObjectMeta: api.ObjectMeta{ Name: "foo", Namespace: ns, Labels: serviceLabels, }, Spec: api.ServiceSpec{ Selector: map[string]string{"foo": "bar"}, Ports: []api.ServicePort{ {Name: "port0", Port: 80, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(8080)}, {Name: "port1", Port: 88, Protocol: "TCP", TargetPort: util.NewIntOrStringFromInt(8088)}, }, }, }) endpoints.syncService(ns + "/foo") expectedSubsets := []api.EndpointSubset{{ Addresses: []api.EndpointAddress{ {IP: "1.2.3.4", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod0", Namespace: ns}}, {IP: "1.2.3.5", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod1", Namespace: ns}}, {IP: "1.2.3.6", TargetRef: &api.ObjectReference{Kind: "Pod", Name: "pod2", Namespace: ns}}, }, Ports: []api.EndpointPort{ {Name: "port0", Port: 8080, Protocol: "TCP"}, {Name: "port1", Port: 8088, Protocol: "TCP"}, }, }} data := runtime.EncodeOrDie(testapi.Codec(), &api.Endpoints{ ObjectMeta: api.ObjectMeta{ ResourceVersion: "", Labels: serviceLabels, }, Subsets: endptspkg.SortSubsets(expectedSubsets), }) // endpointsHandler should get 2 requests - one for "GET" and the next for "POST". endpointsHandler.ValidateRequestCount(t, 2) endpointsHandler.ValidateRequest(t, testapi.ResourcePath("endpoints", ns, ""), "POST", &data) }
func TestDefaultErrorFunc(t *testing.T) { testPod := &api.Pod{ ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: api.PodSpec{ RestartPolicy: api.RestartPolicyAlways, DNSPolicy: api.DNSClusterFirst, }, } handler := util.FakeHandler{ StatusCode: 200, ResponseBody: runtime.EncodeOrDie(latest.Codec, testPod), T: t, } mux := http.NewServeMux() // FakeHandler musn't be sent requests other than the one you want to test. mux.Handle(testapi.ResourcePath("pods", "bar", "foo"), &handler) server := httptest.NewServer(mux) defer server.Close() factory := NewConfigFactory(client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Version()})) queue := cache.NewFIFO(cache.MetaNamespaceKeyFunc) podBackoff := podBackoff{ perPodBackoff: map[string]*backoffEntry{}, clock: &fakeClock{}, defaultDuration: 1 * time.Millisecond, maxDuration: 1 * time.Second, } errFunc := factory.makeDefaultErrorFunc(&podBackoff, queue) errFunc(testPod, nil) for { // This is a terrible way to do this but I plan on replacing this // whole error handling system in the future. The test will time // out if something doesn't work. time.Sleep(10 * time.Millisecond) got, exists, _ := queue.Get(testPod) if !exists { continue } handler.ValidateRequest(t, testapi.ResourcePath("pods", "bar", "foo"), "GET", nil) if e, a := testPod, got; !reflect.DeepEqual(e, a) { t.Errorf("Expected %v, got %v", e, a) } break } }
func TestApiserverMetrics(t *testing.T) { _, s := framework.RunAMaster(t) defer s.Close() // Make a request to the apiserver to ensure there's at least one data point // for the metrics we're expecting -- otherwise, they won't be exported. client := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Version()}) if _, err := client.Pods(api.NamespaceDefault).List(labels.Everything(), fields.Everything()); err != nil { t.Fatalf("unexpected error getting pods: %v", err) } metrics, err := scrapeMetrics(s) if err != nil { t.Fatal(err) } checkForExpectedMetrics(t, metrics, []string{ "apiserver_request_count", "apiserver_request_latencies", }) }
func TestDeleteControllerAndExpectations(t *testing.T) { client := client.NewOrDie(&client.Config{Host: "", Version: testapi.Version()}) manager := NewReplicationManager(client, 10) manager.podStoreSynced = alwaysReady rc := newReplicationController(1) manager.rcStore.Store.Add(rc) fakePodControl := FakePodControl{} manager.podControl = &fakePodControl // This should set expectations for the rc manager.syncReplicationController(getKey(rc, t)) validateSyncReplication(t, &fakePodControl, 1, 0) fakePodControl.clear() // Get the RC key rcKey, err := controller.KeyFunc(rc) if err != nil { t.Errorf("Couldn't get key for object %+v: %v", rc, err) } // This is to simulate a concurrent addPod, that has a handle on the expectations // as the controller deletes it. podExp, exists, err := manager.expectations.GetExpectations(rcKey) if !exists || err != nil { t.Errorf("No expectations found for rc") } manager.rcStore.Delete(rc) manager.syncReplicationController(getKey(rc, t)) if _, exists, err = manager.expectations.GetExpectations(rcKey); exists { t.Errorf("Found expectaions, expected none since the rc has been deleted.") } // This should have no effect, since we've deleted the rc. podExp.Seen(1, 0) manager.podStore.Store.Replace(make([]interface{}, 0)) manager.syncReplicationController(getKey(rc, t)) validateSyncReplication(t, &fakePodControl, 0, 0) }
// Test configures a scheduler from a policies defined in a file // It combines some configurable predicate/priorities with some pre-defined ones func TestCreateFromConfig(t *testing.T) { var configData []byte var policy schedulerapi.Policy handler := util.FakeHandler{ StatusCode: 500, ResponseBody: "", T: t, } server := httptest.NewServer(&handler) defer server.Close() client := client.NewOrDie(&client.Config{Host: server.URL, Version: testapi.Version()}) factory := NewConfigFactory(client) // Pre-register some predicate and priority functions RegisterFitPredicate("PredicateOne", PredicateOne) RegisterFitPredicate("PredicateTwo", PredicateTwo) RegisterPriorityFunction("PriorityOne", PriorityOne, 1) RegisterPriorityFunction("PriorityTwo", PriorityTwo, 1) configData = []byte(`{ "kind" : "Policy", "apiVersion" : "v1", "predicates" : [ {"name" : "TestZoneAffinity", "argument" : {"serviceAffinity" : {"labels" : ["zone"]}}}, {"name" : "TestRequireZone", "argument" : {"labelsPresence" : {"labels" : ["zone"], "presence" : true}}}, {"name" : "PredicateOne"}, {"name" : "PredicateTwo"} ], "priorities" : [ {"name" : "RackSpread", "weight" : 3, "argument" : {"serviceAntiAffinity" : {"label" : "rack"}}}, {"name" : "PriorityOne", "weight" : 2}, {"name" : "PriorityTwo", "weight" : 1} ] }`) err := latestschedulerapi.Codec.DecodeInto(configData, &policy) if err != nil { t.Errorf("Invalid configuration: %v", err) } factory.CreateFromConfig(policy) }
func TestUnschedulableNodes(t *testing.T) { etcdStorage, err := framework.NewEtcdStorage() if err != nil { t.Fatalf("Couldn't create etcd storage: %v", err) } framework.DeleteAllEtcdKeys() var m *master.Master s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { m.Handler.ServeHTTP(w, req) })) defer s.Close() m = master.New(&master.Config{ DatabaseStorage: etcdStorage, KubeletClient: client.FakeKubeletClient{}, EnableCoreControllers: true, EnableLogsSupport: false, EnableUISupport: false, EnableIndex: true, APIPrefix: "/api", Authorizer: apiserver.NewAlwaysAllowAuthorizer(), AdmissionControl: admit.NewAlwaysAdmit(), }) restClient := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Version()}) schedulerConfigFactory := factory.NewConfigFactory(restClient, nil) schedulerConfig, err := schedulerConfigFactory.Create() if err != nil { t.Fatalf("Couldn't create scheduler config: %v", err) } eventBroadcaster := record.NewBroadcaster() schedulerConfig.Recorder = eventBroadcaster.NewRecorder(api.EventSource{Component: "scheduler"}) eventBroadcaster.StartRecordingToSink(restClient.Events("")) scheduler.New(schedulerConfig).Run() defer close(schedulerConfig.StopEverything) DoTestUnschedulableNodes(t, restClient, schedulerConfigFactory.NodeLister.Store) }
func TestControllerUpdateRequeue(t *testing.T) { // This server should force a requeue of the controller because it fails to update status.Replicas. fakeHandler := util.FakeHandler{ StatusCode: 500, ResponseBody: "", } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady rc := newReplicationController(1) manager.rcStore.Store.Add(rc) rc.Status = api.ReplicationControllerStatus{Replicas: 2} newPodList(manager.podStore.Store, 1, api.PodRunning, rc) fakePodControl := FakePodControl{} manager.podControl = &fakePodControl manager.syncReplicationController(getKey(rc, t)) ch := make(chan interface{}) go func() { item, _ := manager.queue.Get() ch <- item }() select { case key := <-ch: expectedKey := getKey(rc, t) if key != expectedKey { t.Errorf("Expected requeue of controller with key %s got %s", expectedKey, key) } case <-time.After(controllerTimeout): manager.queue.ShutDown() t.Errorf("Expected to find an rc in the queue, found none.") } // 1 Update and 1 GET, both of which fail fakeHandler.ValidateRequestCount(t, 2) }
func TestStatusUpdatesWithoutReplicasChange(t *testing.T) { // Setup a fake server to listen for requests, and run the rc manager in steady state fakeHandler := util.FakeHandler{ StatusCode: 200, ResponseBody: "", } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() client := client.NewOrDie(&client.Config{Host: testServer.URL, Version: testapi.Version()}) manager := NewReplicationManager(client, BurstReplicas) manager.podStoreSynced = alwaysReady // Steady state for the replication controller, no Status.Replicas updates expected activePods := 5 rc := newReplicationController(activePods) manager.rcStore.Store.Add(rc) rc.Status = api.ReplicationControllerStatus{Replicas: activePods} newPodList(manager.podStore.Store, activePods, api.PodRunning, rc) fakePodControl := FakePodControl{} manager.podControl = &fakePodControl manager.syncReplicationController(getKey(rc, t)) validateSyncReplication(t, &fakePodControl, 0, 0) if fakeHandler.RequestReceived != nil { t.Errorf("Unexpected update when pods and rcs are in a steady state") } // This response body is just so we don't err out decoding the http response, all // we care about is the request body sent below. response := runtime.EncodeOrDie(testapi.Codec(), &api.ReplicationController{}) fakeHandler.ResponseBody = response rc.Generation = rc.Generation + 1 manager.syncReplicationController(getKey(rc, t)) rc.Status.ObservedGeneration = rc.Generation updatedRc := runtime.EncodeOrDie(testapi.Codec(), rc) fakeHandler.ValidateRequest(t, testapi.ResourcePath(replicationControllerResourceName(), rc.Namespace, rc.Name), "PUT", &updatedRc) }