@Test
  public void testKill() throws Exception {
    initializeOneAgent();

    coordinator.setState(RUNNING, Predicates.<SlotStatus>alwaysTrue(), null);

    Request request =
        Request.Builder.preparePut()
            .setUri(
                coordinatorUriBuilder()
                    .appendPath("/v1/slot/lifecycle")
                    .addParameter("binary", "apple:*")
                    .build())
            .setBodyGenerator(createStaticBodyGenerator("killing", UTF_8))
            .build();
    List<SlotStatusRepresentation> actual =
        httpClient.execute(
            request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode()));

    AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId);
    SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId);
    SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId);
    SlotStatus bananaStatus = agentStatus.getSlotStatus(bananaSlotId);

    List<SlotStatusRepresentation> expected =
        ImmutableList.of(
            slotStatusRepresentationFactory.create(apple1Status),
            slotStatusRepresentationFactory.create(apple2Status));

    assertEqualsNoOrder(actual, expected);
    assertEquals(apple1Status.getState(), STOPPED);
    assertEquals(apple2Status.getState(), STOPPED);
    assertEquals(bananaStatus.getState(), RUNNING);
  }
  @Test
  public void testLifecycleUnknown() throws Exception {
    initializeOneAgent();

    Request request =
        Request.Builder.preparePut()
            .setUri(
                coordinatorUriBuilder()
                    .appendPath("/v1/slot/lifecycle")
                    .addParameter("binary", "apple:*")
                    .build())
            .setBodyGenerator(createStaticBodyGenerator("unknown", UTF_8))
            .build();
    StatusResponse response = httpClient.execute(request, createStatusResponseHandler());

    AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId);
    SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId);
    SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId);
    SlotStatus bananaStatus = agentStatus.getSlotStatus(bananaSlotId);

    assertEquals(response.getStatusCode(), Status.BAD_REQUEST.getStatusCode());
    assertEquals(apple1Status.getState(), STOPPED);
    assertEquals(apple2Status.getState(), STOPPED);
    assertEquals(bananaStatus.getState(), STOPPED);
  }
  @Test
  public void testGetAllSlots() throws Exception {
    initializeOneAgent();

    Request request =
        Request.Builder.prepareGet()
            .setUri(
                coordinatorUriBuilder().appendPath("/v1/slot").addParameter("name", "*").build())
            .build();
    List<SlotStatusRepresentation> actual =
        httpClient.execute(
            request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode()));

    AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId);

    int prefixSize =
        shortestUniquePrefix(
            asList(
                agentStatus.getSlotStatus(apple1SotId).getId().toString(),
                agentStatus.getSlotStatus(apple2SlotId).getId().toString(),
                agentStatus.getSlotStatus(bananaSlotId).getId().toString()),
            MIN_PREFIX_SIZE);

    assertEqualsNoOrder(
        actual,
        ImmutableList.of(
            SlotStatusRepresentation.from(
                agentStatus.getSlotStatus(apple1SotId), prefixSize, MOCK_REPO),
            SlotStatusRepresentation.from(
                agentStatus.getSlotStatus(apple2SlotId), prefixSize, MOCK_REPO),
            SlotStatusRepresentation.from(
                agentStatus.getSlotStatus(bananaSlotId), prefixSize, MOCK_REPO)));
  }
  @Test
  public void testTerminate() throws Exception {
    initializeOneAgent();

    AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId);
    SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId);
    SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId);

    Request request =
        Request.Builder.prepareDelete()
            .setUri(
                coordinatorUriBuilder()
                    .appendPath("/v1/slot")
                    .addParameter("host", "apple*")
                    .build())
            .build();
    List<SlotStatusRepresentation> actual =
        httpClient.execute(
            request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode()));

    apple1Status = apple1Status.changeState(TERMINATED);
    apple2Status = apple2Status.changeState(TERMINATED);
    SlotStatus bananaStatus = coordinator.getAgentByAgentId(agentId).getSlotStatus(bananaSlotId);

    List<SlotStatusRepresentation> expected =
        ImmutableList.of(
            slotStatusRepresentationFactory.create(apple1Status),
            slotStatusRepresentationFactory.create(apple2Status.changeState(TERMINATED)));

    assertEqualsNoOrder(actual, expected);

    assertEquals(apple1Status.getState(), TERMINATED);
    assertEquals(apple2Status.getState(), TERMINATED);
    assertEquals(bananaStatus.getState(), STOPPED);
  }
  @AfterClass
  public void tearDown() throws Exception {
    httpClient.close();
    httpClient = null;

    executor.shutdownNow();
    executor = null;
  }
Example #6
0
 public void execute(String query) {
   Request request = buildQueryRequest(session, query);
   StatusResponse response = httpClient.execute(request, createStatusResponseHandler());
   if (response.getStatusCode() != 200) {
     throw new RuntimeException(
         "Query failed: [" + response.getStatusCode() + "] " + response.getStatusMessage());
   }
 }
  @AfterMethod(alwaysRun = true)
  public void tearDown() throws Exception {
    if (server != null) {
      server.stop();
    }

    httpClient.close();
  }
 @AfterMethod
 public void teardown() throws Exception {
   if (lifeCycleManager != null) {
     lifeCycleManager.stop();
   }
   if (client != null) {
     client.close();
   }
 }
  private synchronized void scheduleUpdate() {
    // don't update if the task hasn't been started yet or if it is already finished
    if (!needsUpdate.get() || taskInfo.get().getState().isDone()) {
      return;
    }

    // if we have an old request outstanding, cancel it
    if (currentRequest != null
        && Duration.nanosSince(currentRequestStartNanos).compareTo(new Duration(2, SECONDS)) >= 0) {
      needsUpdate.set(true);
      currentRequest.cancel(true);
      currentRequest = null;
      currentRequestStartNanos = 0;
    }

    // if there is a request already running, wait for it to complete
    if (this.currentRequest != null && !this.currentRequest.isDone()) {
      return;
    }

    // if throttled due to error, asynchronously wait for timeout and try again
    ListenableFuture<?> errorRateLimit = updateErrorTracker.acquireRequestPermit();
    if (!errorRateLimit.isDone()) {
      errorRateLimit.addListener(this::scheduleUpdate, executor);
      return;
    }

    List<TaskSource> sources = getSources();
    TaskUpdateRequest updateRequest =
        new TaskUpdateRequest(
            session.toSessionRepresentation(), planFragment, sources, outputBuffers.get());

    Request request =
        preparePost()
            .setUri(uriBuilderFrom(taskInfo.get().getSelf()).addParameter("summarize").build())
            .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8.toString())
            .setBodyGenerator(jsonBodyGenerator(taskUpdateRequestCodec, updateRequest))
            .build();

    updateErrorTracker.startRequest();

    ListenableFuture<JsonResponse<TaskInfo>> future =
        httpClient.executeAsync(request, createFullJsonResponseHandler(taskInfoCodec));
    currentRequest = future;
    currentRequestStartNanos = System.nanoTime();

    // The needsUpdate flag needs to be set to false BEFORE adding the Future callback since
    // callback might change the flag value
    // and does so without grabbing the instance lock.
    needsUpdate.set(false);

    Futures.addCallback(
        future,
        new SimpleHttpResponseHandler<>(new UpdateResponseHandler(sources), request.getUri()),
        executor);
  }
  @Test
  public void testGetAllAgentsEmpty() {
    Request request =
        Request.Builder.prepareGet()
            .setUri(coordinatorUriBuilder().appendPath("/v1/admin/agent").build())
            .build();

    List<AgentStatusRepresentation> actual =
        httpClient.execute(
            request, createJsonResponseHandler(agentStatusesCodec, Status.OK.getStatusCode()));
    assertEquals(actual.size(), 0);
  }
 private StringResponse executeQuery(String query) {
   Request request =
       preparePost()
           .setUri(server.resolve("/v1/execute"))
           .setHeader(PrestoHeaders.PRESTO_USER, "test")
           .setHeader(PrestoHeaders.PRESTO_CATALOG, "catalog")
           .setHeader(PrestoHeaders.PRESTO_SCHEMA, "schema")
           .setHeader(PrestoHeaders.PRESTO_TIME_ZONE, "UTC")
           .setBodyGenerator(createStaticBodyGenerator(query, UTF_8))
           .build();
   return client.execute(request, createStringResponseHandler());
 }
  @Test(enabled = false)
  public void testQuery() throws Exception {
    URI location =
        client.execute(
            preparePost()
                .setUri(uriFor("/v1/query"))
                .setBodyGenerator(createStaticBodyGenerator("query", UTF_8))
                .build(),
            new CreatedResponseHandler());
    assertQueryStatus(location, QueryState.RUNNING);

    QueryInfo queryInfo =
        client.execute(
            prepareGet().setUri(location).build(),
            createJsonResponseHandler(jsonCodec(QueryInfo.class)));
    TaskInfo taskInfo = queryInfo.getOutputStage().getTasks().get(0);
    URI outputLocation = uriFor("/v1/task/" + taskInfo.getTaskId() + "/results/out");

    long sequenceId = 0;
    PagesResponse response =
        client.execute(
            prepareGet()
                .setUri(
                    uriBuilderFrom(outputLocation).appendPath(String.valueOf(sequenceId)).build())
                .build(),
            new PageResponseHandler());
    List<Page> pages = response.getPages();
    assertEquals(countPositions(pages), 220);
    assertQueryStatus(location, QueryState.RUNNING);

    sequenceId += pages.size();
    response =
        client.execute(
            prepareGet()
                .setUri(
                    uriBuilderFrom(outputLocation).appendPath(String.valueOf(sequenceId)).build())
                .build(),
            new PageResponseHandler());
    pages = response.getPages();
    assertEquals(countPositions(pages), 44 + 48);

    sequenceId += pages.size();
    response =
        client.execute(
            prepareGet()
                .setUri(
                    uriBuilderFrom(outputLocation).appendPath(String.valueOf(sequenceId)).build())
                .build(),
            new PageResponseHandler());
    pages = response.getPages();
    assertEquals(countPositions(pages), 0);

    assertQueryStatus(location, QueryState.FINISHED);

    // cancel the query
    StatusResponse cancelResponse =
        client.execute(prepareDelete().setUri(location).build(), createStatusResponseHandler());
    assertQueryStatus(location, QueryState.FINISHED);
    assertEquals(cancelResponse.getStatusCode(), HttpStatus.NO_CONTENT.code());
  }
 private void assertQueryStatus(URI location, QueryState expectedQueryState) {
   URI statusUri = uriBuilderFrom(location).build();
   JsonResponse<QueryInfo> response =
       client.execute(
           prepareGet().setUri(statusUri).build(),
           createFullJsonResponseHandler(jsonCodec(QueryInfo.class)));
   if (expectedQueryState == QueryState.FINISHED
       && response.getStatusCode() == HttpStatus.GONE.code()) {
     // when query finishes the server may delete it
     return;
   }
   QueryInfo queryInfo = response.getValue();
   assertEquals(queryInfo.getState(), expectedQueryState);
 }
  @Test
  public void testGetAllAgentsSingle() throws Exception {
    String agentId = UUID.randomUUID().toString();
    URI internalUri = URI.create("fake://agent/" + agentId + "/internal");
    URI externalUri = URI.create("fake://agent/" + agentId + "/external");
    String instanceId = "instance-id";
    String location = "/unknown/location";
    String instanceType = "instance.type";
    Map<String, Integer> resources = ImmutableMap.of("cpu", 8, "memory", 1024);

    AgentStatus status =
        new AgentStatus(
            agentId,
            AgentLifecycleState.ONLINE,
            instanceId,
            internalUri,
            externalUri,
            location,
            instanceType,
            ImmutableList.<SlotStatus>of(),
            resources);

    // add the agent
    provisioner.addAgents(status);
    coordinator.updateAllAgentsAndWait();

    Request request =
        Request.Builder.prepareGet()
            .setUri(coordinatorUriBuilder().appendPath("/v1/admin/agent").build())
            .build();

    List<AgentStatusRepresentation> agents =
        httpClient.execute(
            request, createJsonResponseHandler(agentStatusesCodec, Status.OK.getStatusCode()));
    assertEquals(agents.size(), 1);

    AgentStatusRepresentation actual = agents.get(0);
    assertEquals(actual.getAgentId(), agentId);
    assertEquals(actual.getState(), AgentLifecycleState.ONLINE);
    assertEquals(actual.getInstanceId(), instanceId);
    assertEquals(actual.getLocation(), location);
    assertEquals(actual.getInstanceType(), instanceType);
    assertEquals(actual.getSelf(), internalUri);
    assertEquals(actual.getExternalUri(), externalUri);
    assertEquals(actual.getResources(), resources);
  }
  @Test
  public void testUpgrade() throws Exception {
    initializeOneAgent();

    UpgradeVersions upgradeVersions = new UpgradeVersions("2.0", "2.0");
    Request request =
        Request.Builder.preparePost()
            .setUri(
                coordinatorUriBuilder()
                    .appendPath("/v1/slot/assignment")
                    .addParameter("host", "apple*")
                    .build())
            .setHeader(CONTENT_TYPE, APPLICATION_JSON)
            .setBodyGenerator(jsonBodyGenerator(upgradeVersionsCodec, upgradeVersions))
            .build();
    List<SlotStatusRepresentation> actual =
        httpClient.execute(
            request, createJsonResponseHandler(slotStatusesCodec, Status.OK.getStatusCode()));

    AgentStatus agentStatus = coordinator.getAgentByAgentId(agentId);
    SlotStatus apple1Status = agentStatus.getSlotStatus(apple1SotId);
    SlotStatus apple2Status = agentStatus.getSlotStatus(apple2SlotId);
    SlotStatus bananaStatus = agentStatus.getSlotStatus(bananaSlotId);

    List<SlotStatusRepresentation> expected =
        ImmutableList.of(
            slotStatusRepresentationFactory.create(apple1Status),
            slotStatusRepresentationFactory.create(apple2Status));

    assertEqualsNoOrder(actual, expected);

    assertEquals(apple1Status.getState(), STOPPED);
    assertEquals(apple2Status.getState(), STOPPED);
    assertEquals(bananaStatus.getState(), STOPPED);

    assertEquals(
        apple1Status.getAssignment(),
        upgradeVersions.upgradeAssignment(MOCK_REPO, APPLE_ASSIGNMENT));
    assertEquals(
        apple2Status.getAssignment(),
        upgradeVersions.upgradeAssignment(MOCK_REPO, APPLE_ASSIGNMENT));
    assertEquals(bananaStatus.getAssignment(), BANANA_ASSIGNMENT);
  }
  @Test
  public void testGetAllCoordinatorsSingle() throws Exception {
    // add a coordinator directly to the provisioner
    String coordinatorId = UUID.randomUUID().toString();
    String instanceId = "instance-id";
    URI internalUri = URI.create("fake://coordinator/" + instanceId + "/internal");
    URI externalUri = URI.create("fake://coordinator/" + instanceId + "/external");
    String location = "/unknown/location";
    String instanceType = "instance.type";

    CoordinatorStatus status =
        new CoordinatorStatus(
            coordinatorId,
            CoordinatorLifecycleState.ONLINE,
            instanceId,
            internalUri,
            externalUri,
            location,
            instanceType);
    provisioner.addCoordinators(status);
    coordinator.updateAllCoordinatorsAndWait();

    // verify coordinator appears
    Request request =
        Request.Builder.prepareGet()
            .setUri(coordinatorUriBuilder().appendPath("/v1/admin/coordinator").build())
            .build();

    List<CoordinatorStatusRepresentation> coordinators =
        httpClient.execute(
            request,
            createJsonResponseHandler(coordinatorStatusesCodec, Status.OK.getStatusCode()));
    CoordinatorStatusRepresentation actual = getNonMainCoordinator(coordinators);

    assertEquals(actual.getCoordinatorId(), coordinatorId);
    assertEquals(actual.getState(), CoordinatorLifecycleState.ONLINE);
    assertEquals(actual.getInstanceId(), instanceId);
    assertEquals(actual.getLocation(), location);
    assertEquals(actual.getInstanceType(), instanceType);
    assertEquals(actual.getSelf(), internalUri);
    assertEquals(actual.getExternalUri(), externalUri);
  }
Example #17
0
  private synchronized void sendDelete() {
    HttpResponseFuture<StatusResponse> resultFuture =
        httpClient.executeAsync(
            prepareDelete().setUri(location).build(), createStatusResponseHandler());
    future = resultFuture;
    Futures.addCallback(
        resultFuture,
        new FutureCallback<StatusResponse>() {
          @Override
          public void onSuccess(@Nullable StatusResponse result) {
            checkNotHoldsLock();
            synchronized (HttpPageBufferClient.this) {
              closed = true;
              if (future == resultFuture) {
                future = null;
                errorDelayMillis = 0;
              }
              lastUpdate = DateTime.now();
            }
            requestsCompleted.incrementAndGet();
            clientCallback.clientFinished(HttpPageBufferClient.this);
          }

          @Override
          public void onFailure(Throwable t) {
            checkNotHoldsLock();

            log.error("Request to delete %s failed %s", location, t);
            Duration errorDuration = elapsedErrorDuration();
            if (!(t instanceof PrestoException) && errorDuration.compareTo(minErrorDuration) > 0) {
              String message =
                  format(
                      "Error closing remote buffer (%s - requests failed for %s)",
                      location, errorDuration);
              t = new PrestoException(REMOTE_BUFFER_CLOSE_FAILED, message, t);
            }
            handleFailure(t, resultFuture);
          }
        },
        executor);
  }
  private void scheduleAsyncCleanupRequest(Backoff cleanupBackoff, Request request, String action) {
    Futures.addCallback(
        httpClient.executeAsync(request, createStatusResponseHandler()),
        new FutureCallback<StatusResponse>() {
          @Override
          public void onSuccess(StatusResponse result) {
            // assume any response is good enough
          }

          @Override
          public void onFailure(Throwable t) {
            if (t instanceof RejectedExecutionException) {
              // client has been shutdown
              return;
            }

            // record failure
            if (cleanupBackoff.failure()) {
              logError(t, "Unable to %s task at %s", action, request.getUri());
              return;
            }

            // reschedule
            long delayNanos = cleanupBackoff.getBackoffDelayNanos();
            if (delayNanos == 0) {
              scheduleAsyncCleanupRequest(cleanupBackoff, request, action);
            } else {
              errorScheduledExecutor.schedule(
                  () -> scheduleAsyncCleanupRequest(cleanupBackoff, request, action),
                  delayNanos,
                  NANOSECONDS);
            }
          }
        },
        executor);
  }
Example #19
0
  private synchronized void sendGetResults() {
    URI uri = HttpUriBuilder.uriBuilderFrom(location).appendPath(String.valueOf(token)).build();
    HttpResponseFuture<PagesResponse> resultFuture =
        httpClient.executeAsync(
            prepareGet().setHeader(PRESTO_MAX_SIZE, maxResponseSize.toString()).setUri(uri).build(),
            new PageResponseHandler(blockEncodingSerde));

    future = resultFuture;
    Futures.addCallback(
        resultFuture,
        new FutureCallback<PagesResponse>() {
          @Override
          public void onSuccess(PagesResponse result) {
            checkNotHoldsLock();

            resetErrors();

            List<Page> pages;
            try {
              synchronized (HttpPageBufferClient.this) {
                if (taskInstanceId == null) {
                  taskInstanceId = result.getTaskInstanceId();
                }

                if (!isNullOrEmpty(taskInstanceId)
                    && !result.getTaskInstanceId().equals(taskInstanceId)) {
                  // TODO: update error message
                  throw new PrestoException(REMOTE_TASK_MISMATCH, REMOTE_TASK_MISMATCH_ERROR);
                }

                if (result.getToken() == token) {
                  pages = result.getPages();
                  token = result.getNextToken();
                } else {
                  pages = ImmutableList.of();
                }
              }
            } catch (PrestoException e) {
              handleFailure(e, resultFuture);
              return;
            }

            // add pages
            if (clientCallback.addPages(HttpPageBufferClient.this, pages)) {
              pagesReceived.addAndGet(pages.size());
              rowsReceived.addAndGet(pages.stream().mapToLong(Page::getPositionCount).sum());
            } else {
              pagesRejected.addAndGet(pages.size());
              rowsRejected.addAndGet(pages.stream().mapToLong(Page::getPositionCount).sum());
            }

            synchronized (HttpPageBufferClient.this) {
              // client is complete, acknowledge it by sending it a delete in the next request
              if (result.isClientComplete()) {
                completed = true;
              }
              if (future == resultFuture) {
                future = null;
                errorDelayMillis = 0;
              }
              lastUpdate = DateTime.now();
            }
            requestsCompleted.incrementAndGet();
            clientCallback.requestComplete(HttpPageBufferClient.this);
          }

          @Override
          public void onFailure(Throwable t) {
            log.debug("Request to %s failed %s", uri, t);
            checkNotHoldsLock();

            Duration errorDuration = elapsedErrorDuration();

            t = rewriteException(t);
            if (!(t instanceof PrestoException) && errorDuration.compareTo(minErrorDuration) > 0) {
              String message =
                  format("%s (%s - requests failed for %s)", WORKER_NODE_ERROR, uri, errorDuration);
              t = new PageTransportTimeoutException(message, t);
            }
            handleFailure(t, resultFuture);
          }
        },
        executor);
  }
Example #20
0
 @Override
 public void close() {
   httpClient.close();
 }
  @Test
  public void testCoordinatorProvision() throws Exception {
    // provision the coordinator and verify
    String instanceType = "instance-type";
    CoordinatorProvisioningRepresentation coordinatorProvisioningRepresentation =
        new CoordinatorProvisioningRepresentation(
            "coordinator:config:1", 1, instanceType, null, null, null, null, null);
    Request request =
        Request.Builder.preparePost()
            .setUri(coordinatorUriBuilder().appendPath("/v1/admin/coordinator").build())
            .setHeader(CONTENT_TYPE, APPLICATION_JSON)
            .setBodyGenerator(
                jsonBodyGenerator(
                    coordinatorProvisioningCodec, coordinatorProvisioningRepresentation))
            .build();
    List<CoordinatorStatusRepresentation> coordinators =
        httpClient.execute(
            request,
            createJsonResponseHandler(coordinatorStatusesCodec, Status.OK.getStatusCode()));

    assertEquals(coordinators.size(), 1);
    String instanceId = coordinators.get(0).getInstanceId();
    assertNotNull(instanceId);
    String location = coordinators.get(0).getLocation();
    assertNotNull(location);
    assertEquals(coordinators.get(0).getInstanceType(), instanceType);
    assertNull(coordinators.get(0).getCoordinatorId());
    assertNull(coordinators.get(0).getSelf());
    assertNull(coordinators.get(0).getExternalUri());
    assertEquals(coordinators.get(0).getState(), CoordinatorLifecycleState.PROVISIONING);

    // start the coordinator and verify
    CoordinatorStatus expectedCoordinatorStatus = provisioner.startCoordinator(instanceId);
    coordinator.updateAllCoordinatorsAndWait();
    assertEquals(coordinator.getCoordinators().size(), 2);
    assertEquals(coordinator.getCoordinator(instanceId).getInstanceId(), instanceId);
    assertEquals(coordinator.getCoordinator(instanceId).getInstanceType(), instanceType);
    assertEquals(coordinator.getCoordinator(instanceId).getLocation(), location);
    assertEquals(
        coordinator.getCoordinator(instanceId).getCoordinatorId(),
        expectedCoordinatorStatus.getCoordinatorId());
    assertEquals(
        coordinator.getCoordinator(instanceId).getInternalUri(),
        expectedCoordinatorStatus.getInternalUri());
    assertEquals(
        coordinator.getCoordinator(instanceId).getExternalUri(),
        expectedCoordinatorStatus.getExternalUri());
    assertEquals(
        coordinator.getCoordinator(instanceId).getState(), CoordinatorLifecycleState.ONLINE);

    request =
        Request.Builder.prepareGet()
            .setUri(coordinatorUriBuilder().appendPath("/v1/admin/coordinator").build())
            .build();

    coordinators =
        httpClient.execute(
            request,
            createJsonResponseHandler(coordinatorStatusesCodec, Status.OK.getStatusCode()));
    CoordinatorStatusRepresentation actual = getNonMainCoordinator(coordinators);

    assertEquals(actual.getInstanceId(), instanceId);
    assertEquals(actual.getInstanceType(), instanceType);
    assertEquals(actual.getLocation(), location);
    assertEquals(actual.getCoordinatorId(), expectedCoordinatorStatus.getCoordinatorId());
    assertEquals(actual.getSelf(), expectedCoordinatorStatus.getInternalUri());
    assertEquals(actual.getExternalUri(), expectedCoordinatorStatus.getExternalUri());
    assertEquals(actual.getState(), CoordinatorLifecycleState.ONLINE);
  }
  @Test
  public void testAgentProvision() throws Exception {
    // provision the agent and verify
    String instanceType = "instance-type";
    AgentProvisioningRepresentation agentProvisioningRepresentation =
        new AgentProvisioningRepresentation(
            "agent:config:1", 1, instanceType, null, null, null, null, null);
    Request request =
        Request.Builder.preparePost()
            .setUri(coordinatorUriBuilder().appendPath("/v1/admin/agent").build())
            .setHeader(CONTENT_TYPE, APPLICATION_JSON)
            .setBodyGenerator(
                jsonBodyGenerator(agentProvisioningCodec, agentProvisioningRepresentation))
            .build();
    List<AgentStatusRepresentation> agents =
        httpClient.execute(
            request, createJsonResponseHandler(agentStatusesCodec, Status.OK.getStatusCode()));

    assertEquals(agents.size(), 1);
    String instanceId = agents.get(0).getInstanceId();
    assertNotNull(instanceId);
    String location = agents.get(0).getLocation();
    assertNotNull(location);
    assertEquals(agents.get(0).getInstanceType(), instanceType);
    assertNull(agents.get(0).getAgentId());
    assertNull(agents.get(0).getSelf());
    assertNull(agents.get(0).getExternalUri());
    assertEquals(agents.get(0).getState(), AgentLifecycleState.PROVISIONING);

    // start the agent and verify
    AgentStatus expectedAgentStatus = provisioner.startAgent(instanceId);
    coordinator.updateAllAgentsAndWait();
    assertEquals(coordinator.getAgents().size(), 1);
    assertEquals(coordinator.getAgent(instanceId).getInstanceId(), instanceId);
    assertEquals(coordinator.getAgent(instanceId).getInstanceType(), instanceType);
    assertEquals(coordinator.getAgent(instanceId).getLocation(), location);
    assertEquals(coordinator.getAgent(instanceId).getAgentId(), expectedAgentStatus.getAgentId());
    assertEquals(
        coordinator.getAgent(instanceId).getInternalUri(), expectedAgentStatus.getInternalUri());
    assertEquals(
        coordinator.getAgent(instanceId).getExternalUri(), expectedAgentStatus.getExternalUri());
    assertEquals(coordinator.getAgent(instanceId).getState(), AgentLifecycleState.ONLINE);

    request =
        Request.Builder.prepareGet()
            .setUri(coordinatorUriBuilder().appendPath("/v1/admin/agent").build())
            .build();

    agents =
        httpClient.execute(
            request, createJsonResponseHandler(agentStatusesCodec, Status.OK.getStatusCode()));
    assertEquals(agents.size(), 1);

    AgentStatusRepresentation actual = agents.get(0);
    assertEquals(actual.getInstanceId(), instanceId);
    assertEquals(actual.getInstanceType(), instanceType);
    assertEquals(actual.getLocation(), location);
    assertEquals(actual.getAgentId(), expectedAgentStatus.getAgentId());
    assertEquals(actual.getSelf(), expectedAgentStatus.getInternalUri());
    assertEquals(actual.getExternalUri(), expectedAgentStatus.getExternalUri());
    assertEquals(actual.getState(), AgentLifecycleState.ONLINE);
  }