func TestEtcdCreatePodWithContainersNotFound(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.TestIndex = true fakeClient.Data["/registry/pods/foo"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: nil, }, E: tools.EtcdErrorNotFound, } fakeClient.Data["/registry/hosts/machine/kubelet"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: nil, }, E: tools.EtcdErrorNotFound, } registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) err := registry.CreatePod("machine", api.Pod{ JSONBase: api.JSONBase{ ID: "foo", }, DesiredState: api.PodState{ Manifest: api.ContainerManifest{ ID: "foo", Containers: []api.Container{ { Name: "foo", }, }, }, }, }) if err != nil { t.Fatalf("unexpected error: %v", err) } resp, err := fakeClient.Get("/registry/pods/foo", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var pod api.Pod err = api.DecodeInto([]byte(resp.Node.Value), &pod) if err != nil { t.Errorf("unexpected error: %v", err) } if pod.ID != "foo" { t.Errorf("Unexpected pod: %#v %s", pod, resp.Node.Value) } var manifests api.ContainerManifestList resp, err = fakeClient.Get("/registry/hosts/machine/kubelet", false, false) if err != nil { t.Errorf("unexpected error: %v", err) } err = api.DecodeInto([]byte(resp.Node.Value), &manifests) if len(manifests.Items) != 1 || manifests.Items[0].ID != "foo" { t.Errorf("Unexpected manifest list: %#v", manifests) } }
func TestEtcdCreatePod(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) fakeClient.TestIndex = true fakeClient.Data["/registry/pods/foo"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: nil, }, E: tools.EtcdErrorNotFound, } fakeClient.Set("/registry/hosts/machine/kubelet", api.EncodeOrDie(&api.ContainerManifestList{}), 0) registry := NewTestEtcdRegistry(fakeClient) err := registry.CreatePod(api.Pod{ JSONBase: api.JSONBase{ ID: "foo", }, DesiredState: api.PodState{ Manifest: api.ContainerManifest{ Containers: []api.Container{ { Name: "foo", }, }, }, }, }) if err != nil { t.Fatalf("unexpected error: %v", err) } // Suddenly, a wild scheduler appears: err = registry.ApplyBinding(&api.Binding{PodID: "foo", Host: "machine"}) if err != nil { t.Fatalf("unexpected error: %v", err) } resp, err := fakeClient.Get("/registry/pods/foo", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var pod api.Pod err = api.DecodeInto([]byte(resp.Node.Value), &pod) if err != nil { t.Errorf("unexpected error: %v", err) } if pod.ID != "foo" { t.Errorf("Unexpected pod: %#v %s", pod, resp.Node.Value) } var manifests api.ContainerManifestList resp, err = fakeClient.Get("/registry/hosts/machine/kubelet", false, false) if err != nil { t.Errorf("unexpected error: %v", err) } err = api.DecodeInto([]byte(resp.Node.Value), &manifests) if len(manifests.Items) != 1 || manifests.Items[0].ID != "foo" { t.Errorf("Unexpected manifest list: %#v", manifests) } }
// Execute a request, adds authentication (if auth != nil), and HTTPS cert ignoring. func (c *Client) doRequest(request *http.Request) ([]byte, error) { if c.auth != nil { request.SetBasicAuth(c.auth.User, c.auth.Password) } response, err := c.httpClient.Do(request) if err != nil { return nil, err } defer response.Body.Close() body, err := ioutil.ReadAll(response.Body) if err != nil { return body, err } if response.StatusCode < http.StatusOK || response.StatusCode > http.StatusPartialContent { return nil, fmt.Errorf("request [%#v] failed (%d) %s: %s", request, response.StatusCode, response.Status, string(body)) } if response.StatusCode == http.StatusAccepted { var status api.Status if err := api.DecodeInto(body, &status); err == nil { if status.Status == api.StatusSuccess { return body, nil } else { return nil, &StatusErr{status} } } // Sometimes the server returns 202 even though it completely handled the request. } return body, err }
func TestApiExamples(t *testing.T) { expected := map[string]interface{}{ "controller": &api.ReplicationController{}, "controller-list": &api.ReplicationControllerList{}, "pod": &api.Pod{}, "pod-list": &api.PodList{}, "service": &api.Service{}, "external-service": &api.Service{}, "service-list": &api.ServiceList{}, } tested := 0 err := walkJSONFiles("../api/examples", func(name, path string, data []byte) { expectedType, found := expected[name] if !found { t.Errorf("%s does not have a test case defined", path) return } tested += 1 if err := api.DecodeInto(data, expectedType); err != nil { t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data)) return } if errors := validateObject(expectedType); len(errors) > 0 { t.Errorf("%s did not validate correctly: %v", path, errors) } }) if err != nil { t.Errorf("Expected no error, Got %v", err) } if tested != len(expected) { t.Errorf("Expected %d examples, Got %d", len(expected), tested) } }
func TestReadme(t *testing.T) { path := "../README.md" data, err := ioutil.ReadFile(path) if err != nil { t.Fatalf("Unable to read file: %v", err) } match := jsonRegexp.FindStringSubmatch(string(data)) if match == nil { return } for _, json := range match[1:] { expectedType := &api.Pod{} if err := api.DecodeInto([]byte(json), expectedType); err != nil { t.Errorf("%s did not decode correctly: %v\n%s", path, err, string(data)) return } if errors := validateObject(expectedType); len(errors) > 0 { t.Errorf("%s did not validate correctly: %v", path, errors) } encoded, err := api.Encode(expectedType) if err != nil { t.Errorf("Could not encode object: %v", err) continue } t.Logf("Found pod %s\n%s", json, encoded) } }
func TestEtcdDeletePod(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.TestIndex = true key := "/registry/hosts/machine/pods/foo" fakeClient.Set(key, util.MakeJSONString(api.Pod{JSONBase: api.JSONBase{ID: "foo"}}), 0) fakeClient.Set("/registry/hosts/machine/kubelet", api.EncodeOrDie(&api.ContainerManifestList{ Items: []api.ContainerManifest{ {ID: "foo"}, }, }), 0) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) err := registry.DeletePod("foo") if err != nil { t.Errorf("unexpected error: %v", err) } if len(fakeClient.DeletedKeys) != 1 { t.Errorf("Expected 1 delete, found %#v", fakeClient.DeletedKeys) } else if fakeClient.DeletedKeys[0] != key { t.Errorf("Unexpected key: %s, expected %s", fakeClient.DeletedKeys[0], key) } response, err := fakeClient.Get("/registry/hosts/machine/kubelet", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var manifests api.ContainerManifestList api.DecodeInto([]byte(response.Node.Value), &manifests) if len(manifests.Items) != 0 { t.Errorf("Unexpected container set: %s, expected empty", response.Node.Value) } }
// GetServices finds the list of services and their endpoints from etcd. // This operation is akin to a set a known good at regular intervals. func (s ConfigSourceEtcd) GetServices() ([]api.Service, []api.Endpoints, error) { response, err := s.client.Get(registryRoot+"/specs", true, false) if err != nil { glog.Errorf("Failed to get the key %s: %v", registryRoot, err) return make([]api.Service, 0), make([]api.Endpoints, 0), err } if response.Node.Dir == true { retServices := make([]api.Service, len(response.Node.Nodes)) retEndpoints := make([]api.Endpoints, len(response.Node.Nodes)) // Ok, so we have directories, this list should be the list // of services. Find the local port to listen on and remote endpoints // and create a Service entry for it. for i, node := range response.Node.Nodes { var svc api.Service err = api.DecodeInto([]byte(node.Value), &svc) if err != nil { glog.Errorf("Failed to load Service: %s (%#v)", node.Value, err) continue } retServices[i] = svc endpoints, err := s.GetEndpoints(svc.ID) if err != nil { glog.Errorf("Couldn't get endpoints for %s : %v skipping", svc.ID, err) } glog.Infof("Got service: %s on localport %d mapping to: %s", svc.ID, svc.Port, endpoints) retEndpoints[i] = endpoints } return retServices, retEndpoints, err } return nil, nil, fmt.Errorf("did not get the root of the registry %s", registryRoot) }
func (h *EtcdHelper) bodyAndExtractObj(key string, objPtr interface{}, ignoreNotFound bool) (body string, modifiedIndex uint64, err error) { response, err := h.Client.Get(key, false, false) if err != nil && !IsEtcdNotFound(err) { return "", 0, err } if err != nil || response.Node == nil || len(response.Node.Value) == 0 { if ignoreNotFound { pv := reflect.ValueOf(objPtr) pv.Elem().Set(reflect.Zero(pv.Type().Elem())) return "", 0, nil } else if err != nil { return "", 0, err } return "", 0, fmt.Errorf("key '%v' found no nodes field: %#v", key, response) } body = response.Node.Value err = api.DecodeInto([]byte(body), objPtr) if jsonBase, err := api.FindJSONBase(objPtr); err == nil { jsonBase.SetResourceVersion(response.Node.ModifiedIndex) // Note that err shadows the err returned below, so we won't // return an error just because we failed to find a JSONBase. // This is intentional. } return body, response.Node.ModifiedIndex, err }
func TestEtcdCreateController(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) err := registry.CreateController(api.ReplicationController{ JSONBase: api.JSONBase{ ID: "foo", }, }) if err != nil { t.Errorf("unexpected error: %v", err) } resp, err := fakeClient.Get("/registry/controllers/foo", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var ctrl api.ReplicationController err = api.DecodeInto([]byte(resp.Node.Value), &ctrl) if err != nil { t.Errorf("unexpected error: %v", err) } if ctrl.ID != "foo" { t.Errorf("Unexpected pod: %#v %s", ctrl, resp.Node.Value) } }
func TestEtcdCreateService(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.Data["/registry/services/specs/foo"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: nil, }, E: tools.EtcdErrorNotFound, } registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) err := registry.CreateService(api.Service{ JSONBase: api.JSONBase{ID: "foo"}, }) if err != nil { t.Errorf("unexpected error: %v", err) } resp, err := fakeClient.Get("/registry/services/specs/foo", false, false) if err != nil { t.Errorf("unexpected error: %v", err) } var service api.Service err = api.DecodeInto([]byte(resp.Node.Value), &service) if err != nil { t.Errorf("unexpected error: %v", err) } if service.ID != "foo" { t.Errorf("Unexpected service: %#v %s", service, resp.Node.Value) } }
func TestEtcdCreateService(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) registry := NewTestEtcdRegistry(fakeClient) err := registry.CreateService(api.Service{ JSONBase: api.JSONBase{ID: "foo"}, }) if err != nil { t.Errorf("unexpected error: %v", err) } resp, err := fakeClient.Get("/registry/services/specs/foo", false, false) if err != nil { t.Errorf("unexpected error: %v", err) } var service api.Service err = api.DecodeInto([]byte(resp.Node.Value), &service) if err != nil { t.Errorf("unexpected error: %v", err) } if service.ID != "foo" { t.Errorf("Unexpected service: %#v %s", service, resp.Node.Value) } }
func TestEtcdUpdateEndpoints(t *testing.T) { fakeClient := tools.MakeFakeEtcdClient(t) fakeClient.TestIndex = true registry := MakeTestEtcdRegistry(fakeClient, []string{"machine"}) endpoints := api.Endpoints{ JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"baz", "bar"}, } fakeClient.Set("/registry/services/endpoints/foo", util.MakeJSONString(api.Endpoints{}), 0) err := registry.UpdateEndpoints(endpoints) if err != nil { t.Errorf("unexpected error: %v", err) } response, err := fakeClient.Get("/registry/services/endpoints/foo", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var endpointsOut api.Endpoints err = api.DecodeInto([]byte(response.Node.Value), &endpointsOut) if !reflect.DeepEqual(endpoints, endpointsOut) { t.Errorf("Unexpected endpoints: %#v, expected %#v", endpointsOut, endpoints) } }
func extractBody(response *http.Response, object interface{}) (string, error) { defer response.Body.Close() body, err := ioutil.ReadAll(response.Body) if err != nil { return string(body), err } err = api.DecodeInto(body, object) return string(body), err }
// etcdResponseToService takes an etcd response and pulls it apart to find service. func etcdResponseToService(response *etcd.Response) (*api.Service, error) { if response.Node == nil { return nil, fmt.Errorf("invalid response from etcd: %#v", response) } var svc api.Service err := api.DecodeInto([]byte(response.Node.Value), &svc) if err != nil { return nil, err } return &svc, err }
func (s ConfigSourceEtcd) ProcessEndpointResponse(response *etcd.Response) { glog.Infof("Processing a change in endpoint configuration... %s", *response) var endpoints api.Endpoints err := api.DecodeInto([]byte(response.Node.Value), &endpoints) if err != nil { glog.Errorf("Failed to parse service out of etcd key: %v : %+v", response.Node.Value, err) return } endpointsUpdate := EndpointsUpdate{Op: ADD, Endpoints: []api.Endpoints{endpoints}} s.endpointsChannel <- endpointsUpdate }
// GetEndpoints finds the list of endpoints of the service from etcd. func (s ConfigSourceEtcd) GetEndpoints(service string) (api.Endpoints, error) { key := fmt.Sprintf(registryRoot + "/endpoints/" + service) response, err := s.client.Get(key, true, false) if err != nil { glog.Errorf("Failed to get the key: %s %v", key, err) return api.Endpoints{}, err } // Parse all the endpoint specifications in this value. var e api.Endpoints err = api.DecodeInto([]byte(response.Node.Value), &e) return e, err }
// ToWireFormat takes input 'data' as either json or yaml, checks that it parses as the // appropriate object type, and returns json for sending to the API or an error. func (p *Parser) ToWireFormat(data []byte, storage string) ([]byte, error) { prototypeType, found := p.storageToType[storage] if !found { return nil, fmt.Errorf("unknown storage type: %v", storage) } obj := reflect.New(prototypeType).Interface() err := api.DecodeInto(data, obj) if err != nil { return nil, err } return api.Encode(obj) }
// Underlying base implementation of performing a request. // method is the HTTP method (e.g. "GET") // path is the path on the host to hit // requestBody is the body of the request. Can be nil. // target the interface to marshal the JSON response into. Can be nil. func (c *RESTClient) rawRequest(method, path string, requestBody io.Reader, target interface{}) ([]byte, error) { request, err := http.NewRequest(method, c.makeURL(path), requestBody) if err != nil { return nil, err } body, err := c.doRequest(request) if err != nil { return body, err } if target != nil { err = api.DecodeInto(body, target) } if err != nil { glog.Infof("Failed to parse: %s\n", string(body)) // FIXME: no need to return err here? } return body, err }
func TestBindingStorage_Extract(t *testing.T) { b := &BindingStorage{} binding := &api.Binding{ PodID: "foo", Host: "bar", } body, err := api.Encode(binding) if err != nil { t.Fatalf("Unexpected encode error %v", err) } obj := b.New() err = api.DecodeInto(body, obj) if err != nil { t.Fatalf("Unexpected error %v", err) } if e, a := binding, obj; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, but got %#v", e, a) } }
// Extract a go object per etcd node into a slice. func (h *EtcdHelper) ExtractList(key string, slicePtr interface{}) error { nodes, err := h.listEtcdNode(key) if err != nil { return err } pv := reflect.ValueOf(slicePtr) if pv.Type().Kind() != reflect.Ptr || pv.Type().Elem().Kind() != reflect.Slice { // This should not happen at runtime. panic("need ptr to slice") } v := pv.Elem() for _, node := range nodes { obj := reflect.New(v.Type().Elem()) err = api.DecodeInto([]byte(node.Value), obj.Interface()) if err != nil { return err } v.Set(reflect.Append(v, obj.Elem())) } return nil }
// Execute a request, adds authentication (if auth != nil), and HTTPS cert ignoring. func (c *RESTClient) doRequest(request *http.Request) ([]byte, error) { if c.auth != nil { request.SetBasicAuth(c.auth.User, c.auth.Password) } response, err := c.httpClient.Do(request) if err != nil { return nil, err } defer response.Body.Close() body, err := ioutil.ReadAll(response.Body) if err != nil { return body, err } // Did the server give us a status response? isStatusResponse := false var status api.Status if err := api.DecodeInto(body, &status); err == nil && status.Status != "" { isStatusResponse = true } switch { case response.StatusCode == http.StatusConflict: // Return error given by server, if there was one. if isStatusResponse { return nil, &StatusErr{status} } fallthrough case response.StatusCode < http.StatusOK || response.StatusCode > http.StatusPartialContent: return nil, fmt.Errorf("request [%#v] failed (%d) %s: %s", request, response.StatusCode, response.Status, string(body)) } // If the server gave us a status back, look at what it was. if isStatusResponse && status.Status != api.StatusSuccess { // "Working" requests need to be handled specially. // "Failed" requests are clearly just an error and it makes sense to return them as such. return nil, &StatusErr{status} } return body, err }
func TestEtcdDeletePodMultipleContainers(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) fakeClient.TestIndex = true key := "/registry/pods/foo" fakeClient.Set(key, api.EncodeOrDie(api.Pod{ JSONBase: api.JSONBase{ID: "foo"}, DesiredState: api.PodState{Host: "machine"}, }), 0) fakeClient.Set("/registry/hosts/machine/kubelet", api.EncodeOrDie(&api.ContainerManifestList{ Items: []api.ContainerManifest{ {ID: "foo"}, {ID: "bar"}, }, }), 0) registry := NewTestEtcdRegistry(fakeClient) err := registry.DeletePod("foo") if err != nil { t.Errorf("unexpected error: %v", err) } if len(fakeClient.DeletedKeys) != 1 { t.Errorf("Expected 1 delete, found %#v", fakeClient.DeletedKeys) } if fakeClient.DeletedKeys[0] != key { t.Errorf("Unexpected key: %s, expected %s", fakeClient.DeletedKeys[0], key) } response, err := fakeClient.Get("/registry/hosts/machine/kubelet", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var manifests api.ContainerManifestList api.DecodeInto([]byte(response.Node.Value), &manifests) if len(manifests.Items) != 1 { t.Fatalf("Unexpected manifest set: %#v, expected empty", manifests) } if manifests.Items[0].ID != "bar" { t.Errorf("Deleted wrong manifest: %#v", manifests) } }
func runTest(t *testing.T, source interface{}) { name := reflect.TypeOf(source).Elem().Name() apiObjectFuzzer.Fuzz(source) j, err := api.FindJSONBase(source) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, source) } j.SetKind("") j.SetAPIVersion("") data, err := api.Encode(source) if err != nil { t.Errorf("%v: %v (%#v)", name, err, source) return } obj2, err := api.Decode(data) if err != nil { t.Errorf("%v: %v", name, err) return } else { if !reflect.DeepEqual(source, obj2) { t.Errorf("1: %v: diff: %v", name, objDiff(source, obj2)) return } } obj3 := reflect.New(reflect.TypeOf(source).Elem()).Interface() err = api.DecodeInto(data, obj3) if err != nil { t.Errorf("2: %v: %v", name, err) return } else { if !reflect.DeepEqual(source, obj3) { t.Errorf("3: %v: diff: %v", name, objDiff(source, obj3)) return } } }
func TestNewBindingStorage(t *testing.T) { mockRegistry := MockRegistry{ OnApplyBinding: func(b *api.Binding) error { return nil }, } b := NewBindingStorage(mockRegistry) binding := &api.Binding{ PodID: "foo", Host: "bar", } body, err := api.Encode(binding) if err != nil { t.Fatalf("Unexpected encode error %v", err) } obj := b.New() err = api.DecodeInto(body, obj) if err != nil { t.Fatalf("Unexpected error %v", err) } if e, a := binding, obj; !reflect.DeepEqual(e, a) { t.Errorf("Expected %#v, but got %#v", e, a) } }
func TestPodDecode(t *testing.T) { mockRegistry := MockPodRegistry{} storage := PodRegistryStorage{ registry: &mockRegistry, } expected := &api.Pod{ JSONBase: api.JSONBase{ ID: "foo", }, } body, err := api.Encode(expected) if err != nil { t.Errorf("unexpected error: %v", err) } actual := storage.New() if err := api.DecodeInto(body, actual); err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(expected, actual) { t.Errorf("Expected %#v, Got %#v", expected, actual) } }
func TestControllerDecode(t *testing.T) { mockRegistry := registrytest.ControllerRegistry{} storage := RegistryStorage{ registry: &mockRegistry, } controller := &api.ReplicationController{ JSONBase: api.JSONBase{ ID: "foo", }, } body, err := api.Encode(controller) if err != nil { t.Errorf("unexpected error: %v", err) } controllerOut := storage.New() if err := api.DecodeInto(body, controllerOut); err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(controller, controllerOut) { t.Errorf("Expected %#v, found %#v", controller, controllerOut) } }
func (sr *ServiceRegistryStorage) Extract(body []byte) (interface{}, error) { var svc api.Service err := api.DecodeInto(body, &svc) return svc, err }
func (storage *PodRegistryStorage) Extract(body []byte) (interface{}, error) { pod := api.Pod{} err := api.DecodeInto(body, &pod) return pod, err }
func (storage *SimpleRESTStorage) Extract(body []byte) (interface{}, error) { var item Simple api.DecodeInto(body, &item) return item, storage.errors["extract"] }
func (storage *ControllerRegistryStorage) Extract(body []byte) (interface{}, error) { result := api.ReplicationController{} err := api.DecodeInto(body, &result) return result, err }