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", runtime.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 = runtime.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 = runtime.DecodeInto([]byte(resp.Node.Value), &manifests) if len(manifests.Items) != 1 || manifests.Items[0].ID != "foo" { t.Errorf("Unexpected manifest list: %#v", manifests) } }
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 := runtime.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 := runtime.Encode(expectedType) if err != nil { t.Errorf("Could not encode object: %v", err) continue } t.Logf("Found pod %s\n%s", json, encoded) } }
func TestEtcdUpdateEndpoints(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) fakeClient.TestIndex = true registry := NewTestEtcdRegistry(fakeClient) endpoints := api.Endpoints{ JSONBase: api.JSONBase{ID: "foo"}, Endpoints: []string{"baz", "bar"}, } fakeClient.Set("/registry/services/endpoints/foo", runtime.EncodeOrDie(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 = runtime.DecodeInto([]byte(response.Node.Value), &endpointsOut) if !reflect.DeepEqual(endpoints, endpointsOut) { t.Errorf("Unexpected endpoints: %#v, expected %#v", endpointsOut, endpoints) } }
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 = runtime.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 TestEtcdCreateController(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) registry := NewTestEtcdRegistry(fakeClient) 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 = runtime.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 TestEtcdDeletePod(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) fakeClient.TestIndex = true key := "/registry/pods/foo" fakeClient.Set(key, runtime.EncodeOrDie(api.Pod{ JSONBase: api.JSONBase{ID: "foo"}, DesiredState: api.PodState{Host: "machine"}, }), 0) fakeClient.Set("/registry/hosts/machine/kubelet", runtime.EncodeOrDie(&api.ContainerManifestList{ Items: []api.ContainerManifest{ {ID: "foo"}, }, }), 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) } 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 runtime.DecodeInto([]byte(response.Node.Value), &manifests) if len(manifests.Items) != 0 { t.Errorf("Unexpected container set: %s, expected empty", response.Node.Value) } }
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 := runtime.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) } }
// 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 := runtime.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 := runtime.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 = runtime.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 := runtime.DecodeInto(data, obj) if err != nil { return nil, err } return runtime.Encode(obj) }
func TestEtcdCreateImageRepository(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) fakeClient.TestIndex = true fakeClient.Data["/imageRepositories/foo"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: nil, }, E: tools.EtcdErrorNotFound, } registry := NewTestEtcdRegistry(fakeClient) err := registry.CreateImageRepository(&api.ImageRepository{ JSONBase: kubeapi.JSONBase{ ID: "foo", }, Labels: map[string]string{"a": "b"}, DockerImageRepository: "c/d", Tags: map[string]string{"t1": "v1"}, }) if err != nil { t.Fatalf("unexpected error: %v", err) } resp, err := fakeClient.Get("/imageRepositories/foo", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var repo api.ImageRepository err = runtime.DecodeInto([]byte(resp.Node.Value), &repo) if err != nil { t.Errorf("unexpected error: %v", err) } if repo.ID != "foo" { t.Errorf("Unexpected repo: %#v %s", repo, resp.Node.Value) } if len(repo.Labels) != 1 || repo.Labels["a"] != "b" { t.Errorf("Unexpected labels: %#v", repo.Labels) } if repo.DockerImageRepository != "c/d" { t.Errorf("Unexpected docker image repo: %s", repo.DockerImageRepository) } if len(repo.Tags) != 1 || repo.Tags["t1"] != "v1" { t.Errorf("Unexpected tags: %#v", repo.Tags) } }
func TestEtcdCreateImage(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) fakeClient.TestIndex = true fakeClient.Data["/images/foo"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: nil, }, E: tools.EtcdErrorNotFound, } registry := NewTestEtcdRegistry(fakeClient) err := registry.CreateImage(&api.Image{ JSONBase: kubeapi.JSONBase{ ID: "foo", }, DockerImageReference: "openshift/ruby-19-centos", Metadata: docker.Image{ ID: "abc123", }, }) if err != nil { t.Fatalf("unexpected error: %v", err) } resp, err := fakeClient.Get("/images/foo", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var image api.Image err = runtime.DecodeInto([]byte(resp.Node.Value), &image) if err != nil { t.Errorf("unexpected error: %v", err) } if image.ID != "foo" { t.Errorf("Unexpected image: %#v %s", image, resp.Node.Value) } if e, a := "openshift/ruby-19-centos", image.DockerImageReference; e != a { t.Errorf("Expected %v, got %v", e, a) } if e, a := "abc123", image.Metadata.ID; e != a { t.Errorf("Expected %v, got %v", e, a) } }
func TestEtcdCreateBuild(t *testing.T) { fakeClient := tools.NewFakeEtcdClient(t) fakeClient.TestIndex = true fakeClient.Data["/registry/builds/foo"] = tools.EtcdResponseWithError{ R: &etcd.Response{ Node: nil, }, E: tools.EtcdErrorNotFound, } registry := NewTestEtcdRegistry(fakeClient) err := registry.CreateBuild(&api.Build{ JSONBase: kubeapi.JSONBase{ ID: "foo", }, Input: api.BuildInput{ Type: api.DockerBuildType, SourceURI: "http://my.build.com/the/build/Dockerfile", ImageTag: "repository/dataBuild", }, Status: api.BuildPending, PodID: "-the-pod-id", Labels: map[string]string{ "name": "dataBuild", }, }) if err != nil { t.Fatalf("unexpected error: %v", err) } resp, err := fakeClient.Get("/registry/builds/foo", false, false) if err != nil { t.Fatalf("Unexpected error %v", err) } var build api.Build err = runtime.DecodeInto([]byte(resp.Node.Value), &build) if err != nil { t.Errorf("unexpected error: %v", err) } if build.ID != "foo" { t.Errorf("Unexpected build: %#v %s", build, resp.Node.Value) } }
// doRequest executes 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 := runtime.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 runTest(t *testing.T, source interface{}) { name := reflect.TypeOf(source).Elem().Name() apiObjectFuzzer.Fuzz(source) j, err := runtime.FindJSONBase(source) if err != nil { t.Fatalf("Unexpected error %v for %#v", err, source) } j.SetKind("") j.SetAPIVersion("") data, err := runtime.Encode(source) if err != nil { t.Errorf("%v: %v (%#v)", name, err, source) return } obj2, err := runtime.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 = runtime.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 } } }
// 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.V(1).Infof("Failed to get the key %s: %v", registryRoot, err) if tools.IsEtcdNotFound(err) { return []api.Service{}, []api.Endpoints{}, 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 = runtime.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 { if tools.IsEtcdNotFound(err) { glog.V(1).Infof("Unable to get endpoints for %s : %v", svc.ID, err) } glog.Errorf("Couldn't get endpoints for %s : %v skipping", svc.ID, err) endpoints = api.Endpoints{} } else { 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 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 := runtime.Encode(binding) if err != nil { t.Fatalf("Unexpected encode error %v", err) } obj := b.New() err = runtime.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 TestControllerDecode(t *testing.T) { mockRegistry := registrytest.ControllerRegistry{} storage := RegistryStorage{ registry: &mockRegistry, } controller := &api.ReplicationController{ JSONBase: api.JSONBase{ ID: "foo", }, } body, err := runtime.Encode(controller) if err != nil { t.Errorf("unexpected error: %v", err) } controllerOut := storage.New() if err := runtime.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 TestPodDecode(t *testing.T) { podRegistry := registrytest.NewPodRegistry(nil) storage := RegistryStorage{ registry: podRegistry, } expected := &api.Pod{ JSONBase: api.JSONBase{ ID: "foo", }, } body, err := runtime.Encode(expected) if err != nil { t.Errorf("unexpected error: %v", err) } actual := storage.New() if err := runtime.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 TestBuildDecode(t *testing.T) { mockRegistry := test.BuildRegistry{} storage := Storage{ registry: &mockRegistry, } build := &api.Build{ JSONBase: kubeapi.JSONBase{ ID: "foo", }, } body, err := runtime.Encode(build) if err != nil { t.Errorf("unexpected error: %v", err) } buildOut := storage.New() if err := runtime.DecodeInto(body, buildOut); err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(build, buildOut) { t.Errorf("Expected %#v, found %#v", build, buildOut) } }
// Into stores the result into obj, if possible. func (r Result) Into(obj interface{}) error { if r.err != nil { return r.err } return runtime.DecodeInto(r.body, obj) }
// Extract deserializes user provided data into an api.Build. func (storage *Storage) Extract(body []byte) (interface{}, error) { result := api.Build{} err := runtime.DecodeInto(body, &result) return result, err }