func runAPIVersionsTest(c *client.Client) { v, err := c.ServerAPIVersions() clientVersion := c.APIVersion() if err != nil { glog.Fatalf("failed to get api versions: %v", err) } // Verify that the server supports the API version used by the client. for _, version := range v.Versions { if version == clientVersion { glog.Infof("Version test passed") return } } glog.Fatalf("Server does not support APIVersion used by client. Server supported APIVersions: '%v', client APIVersion: '%v'", v.Versions, clientVersion) }
func runAPIVersionsTest(c *client.Client) { g, err := c.ServerGroups() clientVersion := c.APIVersion().String() if err != nil { glog.Fatalf("Failed to get api versions: %v", err) } versions := unversioned.ExtractGroupVersions(g) // Verify that the server supports the API version used by the client. for _, version := range versions { if version == clientVersion { glog.Infof("Version test passed") return } } glog.Fatalf("Server does not support APIVersion used by client. Server supported APIVersions: '%v', client APIVersion: '%v'", versions, clientVersion) }
func runReplicationControllerTest(c *client.Client) { t := time.Now() clientAPIVersion := c.APIVersion().String() data, err := ioutil.ReadFile("cmd/integration/" + clientAPIVersion + "-controller.json") if err != nil { glog.Fatalf("Unexpected error: %v", err) } glog.Infof("Done reading config file, took %v", time.Since(t)) t = time.Now() var controller api.ReplicationController if err := runtime.DecodeInto(testapi.Default.Codec(), data, &controller); err != nil { glog.Fatalf("Unexpected error: %v", err) } glog.Infof("Creating replication controllers") updated, err := c.ReplicationControllers("test").Create(&controller) if err != nil { glog.Fatalf("Unexpected error: %v", err) } glog.Infof("Done creating replication controllers, took %v", time.Since(t)) t = time.Now() // In practice the controller doesn't need 60s to create a handful of pods, but network latencies on CI // systems have been observed to vary unpredictably, so give the controller enough time to create pods. // Our e2e scalability tests will catch controllers that are *actually* slow. if err := wait.Poll(time.Second, longTestTimeout, client.ControllerHasDesiredReplicas(c, updated)); err != nil { glog.Fatalf("FAILED: pods never created %v", err) } glog.Infof("Done creating replicas, took %v", time.Since(t)) t = time.Now() // Poll till we can retrieve the status of all pods matching the given label selector from their nodes. // This involves 3 operations: // - The scheduler must assign all pods to a node // - The assignment must reflect in a `List` operation against the apiserver, for labels matching the selector // - We need to be able to query the kubelet on that node for information about the pod if err := wait.Poll( time.Second, longTestTimeout, podsOnNodes(c, "test", labels.Set(updated.Spec.Selector).AsSelector())); err != nil { glog.Fatalf("FAILED: pods never started running %v", err) } glog.Infof("Pods verified on nodes, took %v", time.Since(t)) }
func runPatchTest(c *client.Client) { name := "patchservice" resource := "services" svcBody := api.Service{ TypeMeta: api.TypeMeta{ APIVersion: c.APIVersion(), }, ObjectMeta: api.ObjectMeta{ Name: name, Labels: map[string]string{}, }, Spec: api.ServiceSpec{ // This is here because validation requires it. Selector: map[string]string{ "foo": "bar", }, Ports: []api.ServicePort{{ Port: 12345, Protocol: "TCP", }}, SessionAffinity: "None", }, } services := c.Services(api.NamespaceDefault) svc, err := services.Create(&svcBody) if err != nil { glog.Fatalf("Failed creating patchservice: %v", err) } patchBodies := map[string]map[api.PatchType]struct { AddLabelBody []byte RemoveLabelBody []byte RemoveAllLabelsBody []byte }{ "v1": { api.JSONPatchType: { []byte(`[{"op":"add","path":"/metadata/labels","value":{"foo":"bar","baz":"qux"}}]`), []byte(`[{"op":"remove","path":"/metadata/labels/foo"}]`), []byte(`[{"op":"remove","path":"/metadata/labels"}]`), }, api.MergePatchType: { []byte(`{"metadata":{"labels":{"foo":"bar","baz":"qux"}}}`), []byte(`{"metadata":{"labels":{"foo":null}}}`), []byte(`{"metadata":{"labels":null}}`), }, api.StrategicMergePatchType: { []byte(`{"metadata":{"labels":{"foo":"bar","baz":"qux"}}}`), []byte(`{"metadata":{"labels":{"foo":null}}}`), []byte(`{"metadata":{"labels":{"$patch":"replace"}}}`), }, }, } pb := patchBodies[c.APIVersion()] execPatch := func(pt api.PatchType, body []byte) error { return c.Patch(pt). Resource(resource). Namespace(api.NamespaceDefault). Name(name). Body(body). Do(). Error() } for k, v := range pb { // add label err := execPatch(k, v.AddLabelBody) if err != nil { glog.Fatalf("Failed updating patchservice with patch type %s: %v", k, err) } svc, err = services.Get(name) if err != nil { glog.Fatalf("Failed getting patchservice: %v", err) } if len(svc.Labels) != 2 || svc.Labels["foo"] != "bar" || svc.Labels["baz"] != "qux" { glog.Fatalf("Failed updating patchservice with patch type %s: labels are: %v", k, svc.Labels) } // remove one label err = execPatch(k, v.RemoveLabelBody) if err != nil { glog.Fatalf("Failed updating patchservice with patch type %s: %v", k, err) } svc, err = services.Get(name) if err != nil { glog.Fatalf("Failed getting patchservice: %v", err) } if len(svc.Labels) != 1 || svc.Labels["baz"] != "qux" { glog.Fatalf("Failed updating patchservice with patch type %s: labels are: %v", k, svc.Labels) } // remove all labels err = execPatch(k, v.RemoveAllLabelsBody) if err != nil { glog.Fatalf("Failed updating patchservice with patch type %s: %v", k, err) } svc, err = services.Get(name) if err != nil { glog.Fatalf("Failed getting patchservice: %v", err) } if svc.Labels != nil { glog.Fatalf("Failed remove all labels from patchservice with patch type %s: %v", k, svc.Labels) } } glog.Info("PATCHs work.") }
func runAtomicPutTest(c *client.Client) { svcBody := api.Service{ TypeMeta: api.TypeMeta{ APIVersion: c.APIVersion(), }, ObjectMeta: api.ObjectMeta{ Name: "atomicservice", Labels: map[string]string{ "name": "atomicService", }, }, Spec: api.ServiceSpec{ // This is here because validation requires it. Selector: map[string]string{ "foo": "bar", }, Ports: []api.ServicePort{{ Port: 12345, Protocol: "TCP", }}, SessionAffinity: "None", }, } services := c.Services(api.NamespaceDefault) svc, err := services.Create(&svcBody) if err != nil { glog.Fatalf("Failed creating atomicService: %v", err) } glog.Info("Created atomicService") testLabels := labels.Set{ "foo": "bar", } for i := 0; i < 5; i++ { // a: z, b: y, etc... testLabels[string([]byte{byte('a' + i)})] = string([]byte{byte('z' - i)}) } var wg sync.WaitGroup wg.Add(len(testLabels)) for label, value := range testLabels { go func(l, v string) { for { glog.Infof("Starting to update (%s, %s)", l, v) tmpSvc, err := services.Get(svc.Name) if err != nil { glog.Errorf("Error getting atomicService: %v", err) continue } if tmpSvc.Spec.Selector == nil { tmpSvc.Spec.Selector = map[string]string{l: v} } else { tmpSvc.Spec.Selector[l] = v } glog.Infof("Posting update (%s, %s)", l, v) tmpSvc, err = services.Update(tmpSvc) if err != nil { if apierrors.IsConflict(err) { glog.Infof("Conflict: (%s, %s)", l, v) // This is what we expect. continue } glog.Errorf("Unexpected error putting atomicService: %v", err) continue } break } glog.Infof("Done update (%s, %s)", l, v) wg.Done() }(label, value) } wg.Wait() svc, err = services.Get(svc.Name) if err != nil { glog.Fatalf("Failed getting atomicService after writers are complete: %v", err) } if !reflect.DeepEqual(testLabels, labels.Set(svc.Spec.Selector)) { glog.Fatalf("Selector PUTs were not atomic: wanted %v, got %v", testLabels, svc.Spec.Selector) } glog.Info("Atomic PUTs work.") }
func runPatchTest(c *client.Client) { name := "patchservice" resource := "services" svcBody := api.Service{ TypeMeta: unversioned.TypeMeta{ APIVersion: c.APIVersion().String(), }, ObjectMeta: api.ObjectMeta{ Name: name, Labels: map[string]string{}, }, Spec: api.ServiceSpec{ // This is here because validation requires it. Selector: map[string]string{ "foo": "bar", }, Ports: []api.ServicePort{{ Port: 12345, Protocol: "TCP", }}, SessionAffinity: "None", }, } services := c.Services(api.NamespaceDefault) svc, err := services.Create(&svcBody) if err != nil { glog.Fatalf("Failed creating patchservice: %v", err) } patchBodies := map[unversioned.GroupVersion]map[api.PatchType]struct { AddLabelBody []byte RemoveLabelBody []byte RemoveAllLabelsBody []byte }{ v1.SchemeGroupVersion: { api.JSONPatchType: { []byte(`[{"op":"add","path":"/metadata/labels","value":{"foo":"bar","baz":"qux"}}]`), []byte(`[{"op":"remove","path":"/metadata/labels/foo"}]`), []byte(`[{"op":"remove","path":"/metadata/labels"}]`), }, api.MergePatchType: { []byte(`{"metadata":{"labels":{"foo":"bar","baz":"qux"}}}`), []byte(`{"metadata":{"labels":{"foo":null}}}`), []byte(`{"metadata":{"labels":null}}`), }, api.StrategicMergePatchType: { []byte(`{"metadata":{"labels":{"foo":"bar","baz":"qux"}}}`), []byte(`{"metadata":{"labels":{"foo":null}}}`), []byte(`{"metadata":{"labels":{"$patch":"replace"}}}`), }, }, } pb := patchBodies[c.APIVersion()] execPatch := func(pt api.PatchType, body []byte) error { return c.Patch(pt). Resource(resource). Namespace(api.NamespaceDefault). Name(name). Body(body). Do(). Error() } for k, v := range pb { // add label err := execPatch(k, v.AddLabelBody) if err != nil { glog.Fatalf("Failed updating patchservice with patch type %s: %v", k, err) } svc, err = services.Get(name) if err != nil { glog.Fatalf("Failed getting patchservice: %v", err) } if len(svc.Labels) != 2 || svc.Labels["foo"] != "bar" || svc.Labels["baz"] != "qux" { glog.Fatalf("Failed updating patchservice with patch type %s: labels are: %v", k, svc.Labels) } // remove one label err = execPatch(k, v.RemoveLabelBody) if err != nil { glog.Fatalf("Failed updating patchservice with patch type %s: %v", k, err) } svc, err = services.Get(name) if err != nil { glog.Fatalf("Failed getting patchservice: %v", err) } if len(svc.Labels) != 1 || svc.Labels["baz"] != "qux" { glog.Fatalf("Failed updating patchservice with patch type %s: labels are: %v", k, svc.Labels) } // remove all labels err = execPatch(k, v.RemoveAllLabelsBody) if err != nil { glog.Fatalf("Failed updating patchservice with patch type %s: %v", k, err) } svc, err = services.Get(name) if err != nil { glog.Fatalf("Failed getting patchservice: %v", err) } if svc.Labels != nil { glog.Fatalf("Failed remove all labels from patchservice with patch type %s: %v", k, svc.Labels) } } // Test patch with a resource that allows create on update endpointTemplate := &api.Endpoints{ ObjectMeta: api.ObjectMeta{Name: "patchendpoint"}, Subsets: []api.EndpointSubset{ { Addresses: []api.EndpointAddress{{IP: "1.2.3.4"}}, Ports: []api.EndpointPort{{Port: 80, Protocol: api.ProtocolTCP}}, }, }, } patchEndpoint := func(json []byte) (runtime.Object, error) { return c.Patch(api.MergePatchType).Resource("endpoints").Namespace(api.NamespaceDefault).Name("patchendpoint").Body(json).Do().Get() } // Make sure patch doesn't get to CreateOnUpdate { endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), endpointTemplate) if err != nil { glog.Fatalf("Failed creating endpoint JSON: %v", err) } if obj, err := patchEndpoint(endpointJSON); !apierrors.IsNotFound(err) { glog.Fatalf("Expected notfound creating from patch, got error=%v and object: %#v", err, obj) } } // Create the endpoint (endpoints set AllowCreateOnUpdate=true) to get a UID and resource version createdEndpoint, err := c.Endpoints(api.NamespaceDefault).Update(endpointTemplate) if err != nil { glog.Fatalf("Failed creating endpoint: %v", err) } // Make sure identity patch is accepted { endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), createdEndpoint) if err != nil { glog.Fatalf("Failed creating endpoint JSON: %v", err) } if _, err := patchEndpoint(endpointJSON); err != nil { glog.Fatalf("Failed patching endpoint: %v", err) } } // Make sure patch complains about a mismatched resourceVersion { endpointTemplate.Name = "" endpointTemplate.UID = "" endpointTemplate.ResourceVersion = "1" endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), endpointTemplate) if err != nil { glog.Fatalf("Failed creating endpoint JSON: %v", err) } if _, err := patchEndpoint(endpointJSON); !apierrors.IsConflict(err) { glog.Fatalf("Expected error, got %#v", err) } } // Make sure patch complains about mutating the UID { endpointTemplate.Name = "" endpointTemplate.UID = "abc" endpointTemplate.ResourceVersion = "" endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), endpointTemplate) if err != nil { glog.Fatalf("Failed creating endpoint JSON: %v", err) } if _, err := patchEndpoint(endpointJSON); !apierrors.IsInvalid(err) { glog.Fatalf("Expected error, got %#v", err) } } // Make sure patch complains about a mismatched name { endpointTemplate.Name = "changedname" endpointTemplate.UID = "" endpointTemplate.ResourceVersion = "" endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), endpointTemplate) if err != nil { glog.Fatalf("Failed creating endpoint JSON: %v", err) } if _, err := patchEndpoint(endpointJSON); !apierrors.IsBadRequest(err) { glog.Fatalf("Expected error, got %#v", err) } } // Make sure patch containing originally submitted JSON is accepted { endpointTemplate.Name = "" endpointTemplate.UID = "" endpointTemplate.ResourceVersion = "" endpointJSON, err := runtime.Encode(api.Codecs.LegacyCodec(v1.SchemeGroupVersion), endpointTemplate) if err != nil { glog.Fatalf("Failed creating endpoint JSON: %v", err) } if _, err := patchEndpoint(endpointJSON); err != nil { glog.Fatalf("Failed patching endpoint: %v", err) } } glog.Info("PATCHs work.") }