func register(t *testing.T, port uint16) []string { ids := make([]string, len(instances)) url := fmt.Sprintf("http://localhost:%d%s", port, amalgam8.InstanceCreateURL()) for index, inst := range instances { b, err := json.Marshal(inst) assert.NoError(t, err) req, err1 := http.NewRequest("POST", url, bytes.NewReader(b)) assert.NoError(t, err1) assert.NotNil(t, req) req.Header.Set("Content-Type", "application/json") req.Header.Set("X-Forwarded-Proto", "https") res, err2 := http.DefaultClient.Do(req) assert.NoError(t, err2) assert.NotNil(t, res) assert.EqualValues(t, 201, res.StatusCode) data, err3 := ioutil.ReadAll(res.Body) assert.NoError(t, err3) res.Body.Close() var si amalgam8.ServiceInstance err = json.Unmarshal(data, &si) assert.NoError(t, err) ids[index] = si.ID } return ids }
// instances:methods func TestInstancesMethodInvalid(t *testing.T) { const fake = "fakeid" var methods = []string{"CONNECT", "DELETE", "HEAD", "OPTIONS", "PATCH", "PUT", "TRACE"} var urls = []string{ serverURL + amalgam8.InstanceCreateURL(), serverURL + amalgam8.InstanceURL(fake), } c := defaultServerConfig() handler, err := setupServer(c) assert.Nil(t, err) assert.Nil(t, err) for _, url := range urls { for _, method := range methods { if method == "DELETE" && url == serverURL+amalgam8.InstanceURL(fake) { continue // this is a valid combination } recorder := httptest.NewRecorder() req, err := http.NewRequest(method, url, nil) assert.Nil(t, err) handler.ServeHTTP(recorder, req) assert.Equal(t, http.StatusMethodNotAllowed, recorder.Code, method+":"+url) } } }
// instances:create func TestInstancesCreate(t *testing.T) { invalidMetadata := json.RawMessage("{\"INVALID\":\"INVALID\"}") cases := []createTestCase{ newCreateTestCase("", "192.168.1.1:8081", "tcp", "UP", 0, metadata, http.StatusBadRequest), // empty service name newCreateTestCase("http", "", "tcp", "UP", 0, metadata, http.StatusBadRequest), // empty endpoint value newCreateTestCase("http", "192.168.1.1:8081", "", "UP", 0, metadata, http.StatusBadRequest), // empty endpoint type newCreateTestCase("http", "192.168.1.1:8082", "icmp", "UP", 30, metadata, http.StatusBadRequest), // invalid endpoint type newCreateTestCase("http", "192.168.1.1:8083", "tcp", "UP", 0, invalidMetadata, http.StatusBadRequest), // invalid metadata newCreateTestCase("http", "192.168.1.1:8084", "tcp", "UP", 0, []byte("1"), http.StatusCreated), // valid metadata - int newCreateTestCase("http", "192.168.1.1:8085", "tcp", "UP", 0, []byte("true"), http.StatusCreated), // valid metadata - bool newCreateTestCase("http", "192.168.1.1:8086", "tcp", "UP", 0, []byte("\"string\""), http.StatusCreated), // valid metadata - string newCreateTestCase("http", "192.168.1.1:8087", "tcp", "UP", 0, metadata, http.StatusCreated), // valid metadata - object newCreateTestCase("http", "192.168.1.1:8088", "tcp", "UP", 30, metadata, http.StatusCreated), // valid, duplicate newCreateTestCase("http", "192.168.1.1:8089", "tcp", "STARTING", 30, metadata, http.StatusCreated), // valid, STARTING status newCreateTestCase("http", "192.168.1.1:8090", "tcp", "OUT_OF_SERVICE", 30, metadata, http.StatusCreated), // valid, OUT_OF_SERVICE status newCreateTestCase("http", "192.168.1.1:8091", "tcp", "blah", 30, metadata, http.StatusBadRequest), // invalid status newCreateTestCaseWithTags("http", "192.168.1.1:8088", "tcp", "UP", 30, metadata, http.StatusCreated, []string{"a", "b"}), // valid, with tags newCreateTestCaseWithTags("http", "192.168.1.1:8088", "tcp", "UP", 30, metadata, http.StatusCreated, []string{}), // valid, with empty tags } url := serverURL + amalgam8.InstanceCreateURL() c := defaultServerConfig() handler, err := setupServer(c) assert.Nil(t, err) for _, tc := range cases { recorder := httptest.NewRecorder() b, err := json.Marshal(&tc.instance) assert.NoError(t, err) if reflect.DeepEqual(tc.instance.Metadata, invalidMetadata) { b = tc.toByteswithFaultyMetadata() } req, err := http.NewRequest("POST", url, bytes.NewReader(b)) assert.Nil(t, err) req.Header.Set("Content-Type", "application/json") handler.ServeHTTP(recorder, req) assert.Equal(t, tc.expected, recorder.Code, string(b), "\nResponse:", string(recorder.Body.Bytes())) if recorder.Code == http.StatusCreated { // verify links reply := &amalgam8.ServiceInstance{} err = json.Unmarshal(recorder.Body.Bytes(), &reply) assert.NoError(t, err) assert.Nil(t, reply.Endpoint) assert.NotNil(t, reply.Links) assert.NotEmpty(t, reply.TTL) } } }
func TestInstanceCreateMissingEndpoint(t *testing.T) { url := serverURL + amalgam8.InstanceCreateURL() c := defaultServerConfig() handler, err := setupServer(c) assert.Nil(t, err) var buggyReq = []byte(`{ "service_name": "service", "host": "whatnot.example.org", "port": 80, "ttl" : 25}`) req, err := http.NewRequest("POST", url, bytes.NewBuffer(buggyReq)) assert.Nil(t, err) recorder := httptest.NewRecorder() req.Header.Set("Content-Type", "application/json") handler.ServeHTTP(recorder, req) assert.Equal(t, http.StatusBadRequest, recorder.Code, string(buggyReq)) }
func (client *client) Register(instance *ServiceInstance) (*ServiceInstance, error) { // Record a pessimistic last heartbeat time - Better safe than sorry! lastHeartbeat := time.Now() body, err := client.doRequest("POST", amalgam8.InstanceCreateURL(), instance, http.StatusCreated) if err != nil { return nil, err } m := make(map[string]interface{}) err = json.Unmarshal(body, &m) if err != nil { return nil, newError(ErrorCodeInternalClientError, "error unmarshaling HTTP response body", err, "") } // TODO: recover type conversion panic registeredInstance := &*instance registeredInstance.ID = m["id"].(string) registeredInstance.TTL = int(m["ttl"].(float64)) registeredInstance.LastHeartbeat = lastHeartbeat return registeredInstance, nil }