예제 #1
0
func (client *client) ListInstances(filter InstanceFilter) ([]*ServiceInstance, error) {
	path := amalgam8.InstancesURL()
	queryParams := filter.asQueryParams()
	if len(queryParams) > 0 {
		path = fmt.Sprintf("%s?%s", path, queryParams.Encode())
	}

	body, err := client.doRequest("GET", path, nil, http.StatusOK)
	if err != nil {
		return nil, err
	}

	s := struct {
		Instances []*ServiceInstance `json:"instances"`
	}{}
	err = json.Unmarshal(body, &s)
	if err != nil {
		return nil, newError(ErrorCodeInternalClientError, "error unmarshaling HTTP response body", err, "")
	}
	return s.Instances, nil
}
예제 #2
0
func TestServiceInstancesFiltering(t *testing.T) {
	tc := struct {
		sname    string // input service name
		expected int    // expected result
	}{"http-1", http.StatusOK}

	c := defaultServerConfig()
	c.Registry.(*mockCatalog).prepopulateServices(services)
	serviceInstance := store.ServiceInstance{ID: "http-1", ServiceName: "http-1", Protocol: protocol.Amalgam8,
		Endpoint: &store.Endpoint{Value: "192.168.0.1:80", Type: "tcp"}, Status: "UP", TTL: 30 * time.Second, Metadata: metadata}
	c.Registry.(*mockCatalog).prepopulateInstances([]mockInstance{{serviceInstance}})

	handler, err := setupServer(c)
	assert.Nil(t, err)

	filterParams := []string{"?fields=status,ttl,status", // duplicate field name in request
		"?fields=status,ttl,status,endpoint", "?fields=", // an empty fields query
		"?fields=endpoint,ttl,metadata,status"} // a "sunny day" test

	assert1 := func(inst *amalgam8.ServiceInstance) {
		assert.Equal(t, uint32(30), inst.TTL)
		assert.EqualValues(t, "UP", inst.Status)
		// make sure we don't get back Last Heartbeat
		assert.Nil(t, inst.LastHeartbeat)
		// make sure we don't get back the metadata
		assert.NotEqual(t, metadata, inst.Metadata)
		// make sure endpoint and id are sent in spite of not being supplied
		assert.Equal(t, "192.168.0.1:80", inst.Endpoint.Value, "Endpoint wasn't sent back")
	}

	assert2 := func(inst *amalgam8.ServiceInstance) {
		assert.Nil(t, inst.LastHeartbeat)
		assert.NotEqual(t, metadata, inst.Metadata)
		assert.Equal(t, "192.168.0.1:80", inst.Endpoint.Value, "Endpoint wasn't sent back")
		assert.Equal(t, "", inst.Status)
	}

	sunnyDayAssert := func(inst *amalgam8.ServiceInstance) {
		assert.Equal(t, serviceInstance.Endpoint.Value, inst.Endpoint.Value)
		assert.Equal(t, int(serviceInstance.TTL), int(inst.TTL)*int(time.Second))
		assert.EqualValues(t, metadata, inst.Metadata)
		assert.Equal(t, serviceInstance.Status, inst.Status)
	}

	asserts := []func(*amalgam8.ServiceInstance){
		assert1, assert1, assert2, sunnyDayAssert,
	}

	for i := range asserts {
		recorder := httptest.NewRecorder()
		req, err := http.NewRequest("GET", serverURL+amalgam8.InstancesURL()+filterParams[i]+"&service_name="+tc.sname, nil)
		assert.Nil(t, err)
		req.Header.Set("Content-Type", "application/json")
		handler.ServeHTTP(recorder, req)
		assert.Equal(t, tc.expected, recorder.Code, string(tc.sname))
		if tc.expected == http.StatusOK {
			insts := amalgam8.InstancesList{}
			err = json.Unmarshal(recorder.Body.Bytes(), &insts)
			assert.Equal(t, 1, len(insts.Instances))
			assert.NoError(t, err)
			inst := insts.Instances[0]
			asserts[i](inst)
		}
	}
}
예제 #3
0
func TestServiceInstancesFilteringByFieldValues(t *testing.T) {
	c := defaultServerConfig()
	c.Registry.(*mockCatalog).prepopulateServices(services)
	serviceInstance1 := store.ServiceInstance{ID: "http-1", ServiceName: "http-1", Protocol: protocol.Amalgam8,
		Endpoint: &store.Endpoint{Value: "192.168.0.1", Type: "tcp"}, Status: "UP", TTL: 30 * time.Second, Metadata: metadata, Tags: []string{"DB", "NoSQL"}}
	serviceInstance2 := store.ServiceInstance{ID: "http-2", ServiceName: "http-1", Protocol: protocol.Amalgam8,
		Endpoint: &store.Endpoint{Value: "192.168.0.1", Type: "tcp"}, Status: "UP", TTL: 30 * time.Second, Metadata: metadata, Tags: []string{"DB"}}
	serviceInstance3 := store.ServiceInstance{ID: "http-3", ServiceName: "http-1", Protocol: protocol.Amalgam8,
		Endpoint: &store.Endpoint{Value: "192.168.0.1", Type: "tcp"}, Status: "STARTING", TTL: 30 * time.Second, Metadata: metadata, Tags: []string{"DB"}}
	serviceInstance4 := store.ServiceInstance{ID: "http-4", ServiceName: "http-1", Protocol: protocol.Amalgam8,
		Endpoint: &store.Endpoint{Value: "192.168.0.1", Type: "tcp"}, Status: "OUT_OF_SERVICE", TTL: 30 * time.Second, Metadata: metadata, Tags: []string{"DB", "NoSQL"}}
	serviceInstance5 := store.ServiceInstance{ID: "http-5", ServiceName: "http-1", Protocol: protocol.Amalgam8,
		Endpoint: &store.Endpoint{Value: "192.168.0.1", Type: "tcp"}, Status: "user_defined", TTL: 30 * time.Second, Metadata: metadata, Tags: []string{"DB", "NoSQL"}}
	c.Registry.(*mockCatalog).prepopulateInstances([]mockInstance{
		mockInstance{serviceInstance1},
		mockInstance{serviceInstance2},
		mockInstance{serviceInstance3},
		mockInstance{serviceInstance4},
		mockInstance{serviceInstance5},
	})

	handler, err := setupServer(c)
	assert.Nil(t, err)

	filterParams := []string{
		"?tags=DB,NoSQL",             // 2 tags                                                     // 0
		"?tags=DB",                   // just 1 tag                                                 // 1
		"?tags=DB,MySQL",             // filter out, because we do an AND			    // 2
		"?status=UP",                 // status is up, should be included                           // 3
		"?status=DOWN",               // status is down, should not be included                     // 4
		"?tags=DB,NoSQL&status=UP",   // check multiple field values true                           // 5
		"?tags=DB,NoSQL&status=DOWN", // check multiple field values false                          // 6
		"?ttl=5",                     // check fields of non string/[]string types are bad request  // 7
		"?BLABLA=5",                  // check invalid field is bad request                         // 8
		"?status=up",                 // check status ignore case                                   // 9
		"?status=ALL",                // all the instances with any status                          // 10
		"?status=STARTING",           // all the instances with STARTING status                     // 11
		"?status=OUT_OF_SERVICE",     // all the instances with OUT_OF_SERVICE status               // 12
		"?status=ALL&tags=DB",        // all the instances with any status and DB tag               // 13
		"?status=STARTING&tags=DB",   // all the instances with STARTING status and DB tag          // 14
		"?tags=DB&status=STARTING",   // all the instances with STARTING status and DB tag          // 15
		"?status=user_defined",       // all the instances with user_defined status                 // 16
	}

	assert0 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 3, len(instances))
	}

	assert1 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 5, len(instances))
	}

	assert2 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 0, len(instances))
	}

	assert3 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 2, len(instances))
	}

	assert4 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 0, len(instances))
	}

	assert5 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 1, len(instances))
	}
	assert6 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 0, len(instances))
	}

	assert7 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusBadRequest, responseStatus)
	}

	assert8 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusBadRequest, responseStatus)
	}

	assert9 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 2, len(instances))
	}

	assert10 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 5, len(instances))
	}

	assert11 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 1, len(instances))
	}

	assert12 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 1, len(instances))
	}

	assert13 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 5, len(instances))
	}

	assert14 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 1, len(instances))
	}

	assert15 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 1, len(instances))
	}

	assert16 := func(instances []*amalgam8.ServiceInstance, responseStatus int) {
		assert.Equal(t, http.StatusOK, responseStatus)
		assert.Equal(t, 1, len(instances))
	}

	asserts := []func([]*amalgam8.ServiceInstance, int){
		assert0,
		assert1,
		assert2,
		assert3,
		assert4,
		assert5,
		assert6,
		assert7,
		assert8,
		assert9,
		assert10,
		assert11,
		assert12,
		assert13,
		assert14,
		assert15,
		assert16,
	}

	for i := range asserts {
		recorder := httptest.NewRecorder()
		req, err := http.NewRequest("GET", serverURL+amalgam8.InstancesURL()+filterParams[i]+"&service_name=http-1", nil)
		assert.Nil(t, err)
		req.Header.Set("Content-Type", "application/json")
		handler.ServeHTTP(recorder, req)
		insts := amalgam8.InstancesList{}
		err = json.Unmarshal(recorder.Body.Bytes(), &insts)
		asserts[i](insts.Instances, recorder.Code)
	}
}