@Test
  public void testExceptionWhenIOExceptionOn200()
      throws ExecutionException, InterruptedException, TimeoutException, IOException {
    Function<HttpResponse, URI> function =
        new ParseURIFromListOrLocationHeaderIf20x(uriBuilderProvider);
    HttpResponse response = createMock(HttpResponse.class);
    Payload payload = createMock(Payload.class);

    expect(response.getStatusCode()).andReturn(200).atLeastOnce();
    expect(response.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE)).andReturn("text/uri-list");
    RuntimeException exception = new RuntimeException("bad");
    expect(response.getPayload()).andReturn(payload).atLeastOnce();
    expect(payload.getInput()).andThrow(exception);
    payload.release();

    replay(payload);
    replay(response);
    try {
      function.apply(response);
    } catch (Exception e) {
      assert e.equals(exception);
    }
    verify(payload);
    verify(response);
  }
  @Test
  void testMultipartDoesntAttemptToParseETagIntoMD5() throws Exception {
    HttpResponse http =
        HttpResponse.builder()
            .statusCode(400)
            .message("boa")
            .payload("")
            .addHeader(S3Headers.USER_METADATA_PREFIX + "foo", "bar")
            .addHeader(HttpHeaders.LAST_MODIFIED, lastModified)
            .addHeader(HttpHeaders.ETAG, "\"abcd-1\"")
            .addHeader(HttpHeaders.CACHE_CONTROL, "cacheControl")
            .build();
    http.getPayload().getContentMetadata().setContentLength(1025l);
    http.getPayload().getContentMetadata().setContentDisposition("contentDisposition");
    http.getPayload().getContentMetadata().setContentEncoding("encoding");
    http.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_OCTET_STREAM);

    MutableObjectMetadata response = parser.apply(http);

    MutableObjectMetadataImpl expects = new MutableObjectMetadataImpl();
    expects.setCacheControl("cacheControl");
    expects.getContentMetadata().setContentDisposition("contentDisposition");
    expects.getContentMetadata().setContentEncoding("encoding");
    expects.getContentMetadata().setContentType(MediaType.APPLICATION_OCTET_STREAM);
    expects.getContentMetadata().setContentLength(1025l);
    expects.setETag("\"abcd-1\"");
    expects.setKey("key");
    expects.setLastModified(now);
    expects.setOwner(null);
    expects.setStorageClass(StorageClass.STANDARD);
    expects.setUserMetadata(userMetadata);
    assertEquals(response, expects);
  }
Example #3
0
  @Test
  public void test401ShouldRetry4Times() {
    HttpCommand command = createMock(HttpCommand.class);
    HttpRequest request = createMock(HttpRequest.class);
    HttpResponse response = createMock(HttpResponse.class);

    @SuppressWarnings("unchecked")
    LoadingCache<Credentials, Access> cache = createMock(LoadingCache.class);
    BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);

    expect(command.getCurrentRequest()).andReturn(request).anyTimes();
    expect(request.getHeaders()).andStubReturn(null);

    cache.invalidateAll();
    expectLastCall().anyTimes();

    expect(response.getPayload()).andReturn(Payloads.newStringPayload("")).anyTimes();
    expect(response.getStatusCode()).andReturn(401).anyTimes();

    replay(command, request, response, cache);

    RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler);

    for (int i = 0; i < RetryOnRenew.NUM_RETRIES - 1; ++i) {
      assertTrue(retry.shouldRetryRequest(command, response), "Expected retry to succeed");
    }

    assertFalse(
        retry.shouldRetryRequest(command, response),
        "Expected retry to fail on attempt " + RetryOnRenew.NUM_RETRIES);

    verify(command, response, cache);
  }
 public void handleError(HttpCommand command, HttpResponse response) {
   String content;
   try {
     content =
         response.getContent() != null ? Utils.toStringAndClose(response.getContent()) : null;
     if (content != null) {
       try {
         if (content.indexOf('<') >= 0) {
           AzureStorageError error =
               utils.parseAzureStorageErrorFromContent(command, response, content);
           command.setException(new AzureStorageResponseException(command, response, error));
         } else {
           command.setException(new HttpResponseException(command, response, content));
         }
       } catch (Exception he) {
         command.setException(new HttpResponseException(command, response, content));
         Utils.rethrowIfRuntime(he);
       }
     } else {
       command.setException(new HttpResponseException(command, response));
     }
   } catch (Exception e) {
     command.setException(new HttpResponseException(command, response));
     Utils.rethrowIfRuntime(e);
   }
 }
  private void assertCodeMakes(
      String method,
      URI uri,
      int statusCode,
      String message,
      String contentType,
      String content,
      Class<? extends Exception> expected) {

    SoftLayerErrorHandler function =
        Guice.createInjector().getInstance(SoftLayerErrorHandler.class);

    HttpCommand command = createMock(HttpCommand.class);
    HttpRequest request = HttpRequest.builder().method(method).endpoint(uri).build();
    HttpResponse response =
        HttpResponse.builder().statusCode(statusCode).message(message).payload(content).build();
    response.getPayload().getContentMetadata().setContentType(contentType);

    expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
    command.setException(classEq(expected));

    replay(command);

    function.handleError(command, response);

    verify(command);
  }
  public void testCreateZoneWhenResponseIs2xxAnd404() {
    GlobalZoneApi client =
        requestSendsResponse(
            createZone,
            HttpResponse.builder()
                .statusCode(200)
                .payload(payloadFromResource("/createzoneresponse.json"))
                .build());

    assertEquals(
        client.createZone("test-zone", NetworkType.BASIC, "8.8.8.8", "10.10.10.10"),
        Zone.builder()
            .id("6")
            .name("test-zone")
            .DNS(ImmutableList.of("8.8.8.8"))
            .internalDNS(ImmutableList.of("10.10.10.10"))
            .networkType(NetworkType.BASIC)
            .securityGroupsEnabled(true)
            .allocationState(AllocationState.ENABLED)
            .zoneToken("7b6e27df-30a6-3024-9d8b-7971a3127f64")
            .dhcpProvider("DhcpServer")
            .build());

    client = requestSendsResponse(createZone, HttpResponse.builder().statusCode(404).build());
    assertNull(client.createZone("test-zone", NetworkType.BASIC, "8.8.8.8", "10.10.10.10"));
  }
Example #7
0
  @Test
  public void test408ShouldRetry() {
    HttpCommand command = createMock(HttpCommand.class);
    HttpResponse response = createMock(HttpResponse.class);
    @SuppressWarnings("unchecked")
    LoadingCache<Credentials, Access> cache = createMock(LoadingCache.class);
    BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);

    expect(response.getPayload())
        .andReturn(
            Payloads.newStringPayload(
                "The server has waited too long for the request to be sent by the client."))
        .times(3);
    expect(backoffHandler.shouldRetryRequest(command, response)).andReturn(true).once();
    expect(response.getStatusCode()).andReturn(408).once();

    replay(command);
    replay(response);
    replay(cache);
    replay(backoffHandler);

    RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler);

    assertTrue(retry.shouldRetryRequest(command, response));

    verify(command);
    verify(response);
    verify(cache);
    verify(backoffHandler);
  }
  public void testExceptionIfNot5xx() {
    FalseOn5xx function = new FalseOn5xx();
    HttpResponse response = EasyMock.createMock(HttpResponse.class);
    HttpResponseException exception = EasyMock.createMock(HttpResponseException.class);

    // Status code is called twice
    expect(response.getStatusCode()).andReturn(600);
    expect(response.getStatusCode()).andReturn(600);
    // Get response gets called twice
    expect(exception.getResponse()).andReturn(response);
    expect(exception.getResponse()).andReturn(response);
    // Get cause is called to determine the root cause
    expect(exception.getCause()).andReturn(null);

    replay(response);
    replay(exception);

    try {
      function.createOrPropagate(exception);
    } catch (Exception ex) {
      assertEquals(ex, exception);
    }

    verify(response);
    verify(exception);
  }
 public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
   if (command.getFailureCount() > retryCountLimit) return false;
   if (response.getStatusCode() == 404
       && command.getCurrentRequest().getMethod().equals("DELETE")) {
     command.incrementFailureCount();
     return true;
   } else if (response.getStatusCode() == 409) {
     byte[] content = HttpUtils.closeClientButKeepContentStream(response);
     // Content can be null in the case of HEAD requests
     if (content != null) {
       try {
         AtmosError error =
             utils.parseAtmosErrorFromContent(command, response, new String(content));
         if (error.getCode() == 1006) {
           return backoffHandler.shouldRetryRequest(command, response);
         }
         // don't increment count before here, since backoff handler does already
         command.incrementFailureCount();
       } catch (HttpException e) {
         logger.warn(e, "error parsing response: %s", new String(content));
       }
     } else {
       command.incrementFailureCount();
     }
     return true;
   }
   return false;
 }
  private void assertCodeMakes(
      String method,
      URI uri,
      int statusCode,
      String message,
      String contentType,
      String content,
      Class<? extends Exception> expected) {

    ElasticStackErrorHandler function =
        Guice.createInjector().getInstance(ElasticStackErrorHandler.class);

    HttpCommand command = createMock(HttpCommand.class);
    HttpRequest request = new HttpRequest(method, uri);
    HttpResponse response =
        new HttpResponse(
            statusCode, message, Payloads.newInputStreamPayload(Strings2.toInputStream(content)));
    response.getPayload().getContentMetadata().setContentType(contentType);

    expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
    command.setException(classEq(expected));

    replay(command);

    function.handleError(command, response);

    verify(command);
  }
  public void handleError(HttpCommand command, HttpResponse response) {
    // it is important to always read fully and close streams
    byte[] data = closeClientButKeepContentStream(response);
    String message = data != null ? new String(data) : null;

    Exception exception =
        message != null
            ? new HttpResponseException(command, response, message)
            : new HttpResponseException(command, response);
    message =
        message != null
            ? message
            : String.format(
                "%s -> %s", command.getCurrentRequest().getRequestLine(), response.getStatusLine());
    switch (response.getStatusCode()) {
      case 400:
        break;
      case 401:
      case 403:
        exception = new AuthorizationException(message, exception);
        break;
      case 404:
        if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
          exception = new ResourceNotFoundException(message, exception);
        }
        break;
    }
    command.setException(exception);
  }
Example #12
0
  @Test
  public void test401ShouldRetry() {
    HttpCommand command = createMock(HttpCommand.class);
    HttpRequest request = createMock(HttpRequest.class);
    HttpResponse response = createMock(HttpResponse.class);
    @SuppressWarnings("unchecked")
    LoadingCache<Credentials, Access> cache = createMock(LoadingCache.class);
    BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);

    expect(command.getCurrentRequest()).andReturn(request);

    cache.invalidateAll();
    expectLastCall();

    expect(response.getPayload()).andReturn(Payloads.newStringPayload("")).anyTimes();
    expect(response.getStatusCode()).andReturn(401).atLeastOnce();

    replay(command);
    replay(response);
    replay(cache);
    replay(backoffHandler);

    RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler);

    assertTrue(retry.shouldRetryRequest(command, response));

    verify(command);
    verify(response);
    verify(cache);
  }
  @Override
  public ListenableFuture<HttpResponse> submit(HttpCommand command) {
    try {
      for (; ; ) {
        Future<Response> responseF =
            client.executeRequest(convertToNingRequest.apply(command.getRequest()));
        final HttpResponse httpResponse = convertToJCloudsResponse.apply(responseF.get());
        int statusCode = httpResponse.getStatusCode();
        if (statusCode >= 300) {
          if (retryHandler.shouldRetryRequest(command, httpResponse)) {
            continue;
          } else {
            errorHandler.handleError(command, httpResponse);
            return wrapAsFuture(httpResponse);
          }
        } else {
          return wrapAsFuture(httpResponse);
        }
      }

    } catch (IOException e) {
      throw Throwables.propagate(e);
    } catch (InterruptedException e) {
      throw Throwables.propagate(e);
    } catch (ExecutionException e) {
      throw Throwables.propagate(e);
    }
  }
    public HttpResponse call() throws Exception {

      HttpResponse response = null;
      for (; ; ) {
        HttpRequest request = command.getCurrentRequest();
        Q nativeRequest = null;
        try {
          for (HttpRequestFilter filter : request.getFilters()) {
            request = filter.filter(request);
          }
          checkRequestHasContentLengthOrChunkedEncoding(
              request,
              "After filtering, the request has neither chunked encoding nor content length: "
                  + request);
          logger.debug("Sending request %s: %s", request.hashCode(), request.getRequestLine());
          wirePayloadIfEnabled(wire, request);
          utils.logRequest(headerLog, request, ">>");
          nativeRequest = convert(request);
          response = invoke(nativeRequest);

          logger.debug("Receiving response %s: %s", request.hashCode(), response.getStatusLine());
          utils.logResponse(headerLog, response, "<<");
          if (response.getPayload() != null && wire.enabled()) wire.input(response);
          int statusCode = response.getStatusCode();
          if (statusCode >= 300) {
            if (shouldContinue(response)) continue;
            else break;
          } else {
            break;
          }
        } catch (Exception e) {
          IOException ioe = Throwables2.getFirstThrowableOfType(e, IOException.class);
          if (ioe != null) {
            if (ioe instanceof SSLException) {
              command.setException(
                  new AuthorizationException(
                      e.getMessage()
                          + " connecting to "
                          + command.getCurrentRequest().getRequestLine(),
                      e));
              break;
            } else if (ioRetryHandler.shouldRetryRequest(command, ioe)) {
              continue;
            }
          }
          command.setException(
              new HttpResponseException(
                  e.getMessage() + " connecting to " + command.getCurrentRequest().getRequestLine(),
                  command,
                  null,
                  e));
          break;
        } finally {
          cleanup(nativeRequest);
        }
      }
      if (command.getException() != null) throw command.getException();
      return response;
    }
 public String parseMessage(final HttpResponse response) {
   if (response.getPayload() == null) {
     return null;
   }
   try {
     return Strings2.toStringAndClose(response.getPayload().openStream());
   } catch (IOException e) {
     throw new RuntimeException(e);
   }
 }
 /**
  * parses the http response headers to create a new {@link
  * org.jclouds.aws.s3.domain.internal.MutableObjectMetadata} object.
  */
 public MutableObjectMetadata apply(HttpResponse from) {
   BlobMetadata base = blobMetadataParser.apply(from);
   MutableObjectMetadata to = blobToObjectMetadata.apply(base);
   addETagTo(from, to);
   to.setContentMD5(HttpUtils.fromHexString(to.getETag().replaceAll("\"", "")));
   to.setCacheControl(from.getFirstHeaderOrNull(HttpHeaders.CACHE_CONTROL));
   to.setContentDisposition(from.getFirstHeaderOrNull("Content-Disposition"));
   to.setContentEncoding(from.getFirstHeaderOrNull(HttpHeaders.CONTENT_ENCODING));
   return to;
 }
 public Task apply(HttpResponse from) {
   String location = from.getFirstHeaderOrNull(HttpHeaders.LOCATION);
   if (location == null) location = from.getFirstHeaderOrNull("location");
   if (location != null) {
     return new TaskImpl(
         URI.create(location), null, TaskStatus.QUEUED, new Date(), null, null, null, null);
   } else {
     throw new HttpResponseException("no uri in headers or content", null, from);
   }
 }
 AtmosStorageError parseErrorFromContentOrNull(HttpCommand command, HttpResponse response) {
   if (response.getContent() != null) {
     try {
       String content = Utils.toStringAndClose(response.getContent());
       if (content != null && content.indexOf('<') >= 0)
         return utils.parseAtmosStorageErrorFromContent(
             command, response, Utils.toInputStream(content));
     } catch (IOException e) {
       logger.warn(e, "exception reading error from response", response);
     }
   }
   return null;
 }
  @Test(enabled = true)
  public void testReboot() {

    URI vAppRebootUri = URI.create(endpoint + "/vApp/" + vAppId + "/power/action/reboot");

    HttpRequest vAppEntityRequest =
        HttpRequest.builder()
            .method("GET")
            .endpoint(URI.create(endpoint + "/entity/" + vAppUrn))
            .addHeader("Accept", "*/*")
            .addHeader("x-vcloud-authorization", token)
            .addHeader(HttpHeaders.COOKIE, "vcloud-token=" + token)
            .build();

    HttpResponse vAppEntityResponse =
        HttpResponse.builder()
            .payload(
                payloadFromResourceWithContentType(
                    "/vapp/vAppEntity.xml", VCloudDirectorMediaType.ENTITY))
            .statusCode(200)
            .build();

    HttpRequest vAppRebootRequest =
        HttpRequest.builder()
            .method("POST")
            .endpoint(vAppRebootUri)
            .addHeader("Accept", "application/vnd.vmware.vcloud.task+xml")
            .addHeader("x-vcloud-authorization", token)
            .addHeader(HttpHeaders.COOKIE, "vcloud-token=" + token)
            .build();

    HttpResponse vAppRebootResponse =
        HttpResponse.builder()
            .payload(
                payloadFromResourceWithContentType(
                    "/vapp/vAppRebootTask.xml", VCloudDirectorMediaType.TASK))
            .statusCode(200)
            .build();

    VCloudDirectorApi vCloudDirectorApi =
        requestsSendResponses(
            loginRequest, sessionResponse,
            vAppEntityRequest, vAppEntityResponse,
            vAppRebootRequest, vAppRebootResponse);

    Task actual = vCloudDirectorApi.getVAppApi().reboot(vAppUrn);
    Task expected = rebootTask();

    assertEquals(actual, expected);
  }
 @Override
 public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
   if (response.getStatusCode() == 503) {
     // Content can be null in the case of HEAD requests
     if (response.getPayload() != null) {
       closeClientButKeepContentStream(response);
       AWSError error = utils.parseAWSErrorFromContent(command.getCurrentRequest(), response);
       if (error != null) {
         return shouldRetryRequestOnError(command, response, error);
       }
     }
   }
   return false;
 }
 @Override
 public Container apply(HttpResponse from) {
   String bytesUsed = from.getFirstHeaderOrNull(CONTAINER_BYTES_USED);
   String objectCount = from.getFirstHeaderOrNull(CONTAINER_OBJECT_COUNT);
   Container c =
       Container.builder()
           .name(name)
           .bytesUsed(bytesUsed != null ? Long.valueOf(bytesUsed) : null)
           .objectCount(objectCount != null ? Long.valueOf(objectCount) : null)
           .anybodyRead(
               CONTAINER_ACL_ANYBODY_READ.equals(from.getFirstHeaderOrNull(CONTAINER_READ)))
           .metadata(EntriesWithoutMetaPrefix.INSTANCE.apply(from.getHeaders()))
           .build();
   return c;
 }
  @Override
  public ListenableFuture<Object> create(Throwable t) {
    if (!(t instanceof HttpResponseException)) throw propagate(t);
    HttpResponse response = HttpResponseException.class.cast(t).getResponse();
    if (response == null) return immediateFuture(null);

    // https://tools.ietf.org/html/rfc2616#section-14.37
    String retryAfter = response.getFirstHeaderOrNull(HttpHeaders.RETRY_AFTER);
    if (retryAfter != null) {
      Optional<RetryAfterException> retryException = tryCreateRetryAfterException(t, retryAfter);
      if (retryException.isPresent()) throw retryException.get();
    }

    return immediateFuture(null);
  }
 public void handleError(HttpCommand command, HttpResponse response) {
   Exception exception = new HttpResponseException(command, response);
   try {
     AtmosStorageError error = parseErrorFromContentOrNull(command, response);
     if (error != null && error.getCode() == 1016) {
       File file = new File(command.getRequest().getEndpoint().getPath());
       exception =
           new KeyAlreadyExistsException(file.getParentFile().getAbsolutePath(), file.getName());
     } else {
       switch (response.getStatusCode()) {
         case 401:
           exception =
               new AuthorizationException(
                   command.getRequest(),
                   error != null ? error.getMessage() : response.getStatusLine());
           break;
         case 404:
           if (!command.getRequest().getMethod().equals("DELETE")) {
             String message =
                 error != null
                     ? error.getMessage()
                     : String.format(
                         "%s -> %s",
                         command.getRequest().getRequestLine(), response.getStatusLine());
             String path = command.getRequest().getEndpoint().getPath();
             Matcher matcher = DIRECTORY_PATH.matcher(path);
             if (matcher.find()) {
               exception = new ContainerNotFoundException(matcher.group(1), message);
             } else {
               matcher = DIRECTORY_KEY_PATH.matcher(path);
               if (matcher.find()) {
                 exception = new KeyNotFoundException(matcher.group(1), matcher.group(2), message);
               }
             }
           }
           break;
         default:
           exception =
               error != null
                   ? new AtmosStorageResponseException(command, response, error)
                   : new HttpResponseException(command, response);
       }
     }
   } finally {
     Closeables.closeQuietly(response.getContent());
     command.setException(exception);
   }
 }
  public void testDescribeVolumesWithNovaEC2Status() {
    ElasticBlockStoreApi client =
        requestsSendResponses(
                describeAvailabilityZonesRequest,
                describeAvailabilityZonesResponse,
                HttpRequest.builder()
                    .method("POST")
                    .endpoint("http://localhost:8773/services/Cloud/")
                    .addHeader("Host", "localhost:8773")
                    .payload(
                        payloadFromStringWithContentType(
                            "Action=DescribeVolumes&Signature=AvRznSzGExM%2Buaj2JJj66wq4v4f%2BakicyLooRDtC0t0%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity",
                            "application/x-www-form-urlencoded"))
                    .build(),
                HttpResponse.builder()
                    .statusCode(200)
                    .payload(payloadFromResource("/nova_ec2_describe_volumes.xml"))
                    .build())
            .getElasticBlockStoreApi()
            .get();

    Set<Volume> expected =
        ImmutableSet.of(
            Volume.builder()
                .status(Volume.Status.AVAILABLE)
                .availabilityZone("nova")
                .region("nova")
                .id("vol-00000007")
                .size(1)
                .attachments(Attachment.builder().region("nova").build())
                .createTime(dateService.iso8601SecondsDateParse("2012-04-10T10:39:52Z"))
                .build());

    assertEquals(client.describeVolumesInRegion("nova"), expected);
  }
  @Test(expectedExceptions = ResourceNotFoundException.class)
  public void testCreateInstanceFail() {
    URI endpoint = URI.create("http://172.16.0.1:8776/v1/3456/instances");
    InstanceApi api =
        requestsSendResponses(
                keystoneAuthWithUsernameAndPasswordAndTenantName,
                responseWithKeystoneAccess,
                authenticatedGET()
                    .endpoint(
                        endpoint) // bad naming convention, you should not be able to change the
                                  // method to POST
                    .method("POST")
                    .payload(
                        payloadFromResourceWithContentType(
                            "/instance_create_request.json", MediaType.APPLICATION_JSON))
                    .build(),
                HttpResponse.builder()
                    .statusCode(404)
                    .payload(payloadFromResource("/instance_create.json"))
                    .build() // response
                )
            .getInstanceApi("RegionOne");

    api.create("1", 2, "json_rack_instance");
  }
  public void testListServersWhenResponseIs2xx() throws Exception {
    HttpRequest listServers =
        HttpRequest.builder()
            .method("GET")
            .endpoint("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/servers")
            .addHeader("Accept", "application/json")
            .addHeader("X-Auth-Token", authToken)
            .build();

    HttpResponse listServersResponse =
        HttpResponse.builder()
            .statusCode(200)
            .payload(payloadFromResource("/server_list.json"))
            .build();

    NovaApi apiWhenServersExist =
        requestsSendResponses(
            keystoneAuthWithAccessKeyAndSecretKeyAndTenantId,
            responseWithKeystoneAccess,
            listServers,
            listServersResponse);

    assertEquals(
        apiWhenServersExist.getConfiguredZones(),
        ImmutableSet.of("az-1.region-a.geo-1", "az-2.region-a.geo-1", "az-3.region-a.geo-1"));

    assertEquals(
        apiWhenServersExist.getServerApiForZone("az-1.region-a.geo-1").list().concat().toString(),
        new ParseServerListTest().expected().toString());
  }
  public void testListTypesByNamesWhenResponseIs2xx() throws Exception {
    HttpRequest listWithOptions =
        HttpRequest.builder()
            .method("POST")
            .endpoint("https://elasticloadbalancing.us-east-1.amazonaws.com/")
            .addHeader("Host", "elasticloadbalancing.us-east-1.amazonaws.com")
            .payload(
                payloadFromStringWithContentType(
                    "Action=DescribeLoadBalancerPolicyTypes"
                        + "&PolicyTypeNames.member.1=moo"
                        + "&Signature=cX8twwn2E6%2B7V3CGZ4ac69NhyolJLsV1nzpQl3wQXW8%3D"
                        + "&SignatureMethod=HmacSHA256"
                        + "&SignatureVersion=2"
                        + "&Timestamp=2009-11-08T15%3A54%3A08.897Z"
                        + "&Version=2012-06-01"
                        + "&AWSAccessKeyId=identity",
                    "application/x-www-form-urlencoded"))
            .build();

    HttpResponse listWithOptionsResponse =
        HttpResponse.builder()
            .statusCode(200)
            .payload(payloadFromResourceWithContentType("/describe_policy_types.xml", "text/xml"))
            .build();

    ELBApi apiWhenWithOptionsExist = requestSendsResponse(listWithOptions, listWithOptionsResponse);

    assertEquals(
        apiWhenWithOptionsExist.getPolicyApi().listTypes(ImmutableSet.of("moo")).toString(),
        new DescribeLoadBalancerPolicyTypesResponseTest().expected().toString());
  }
  public void testListWithOptionsWhenResponseIs2xx() throws Exception {
    HttpRequest listWithOptions =
        HttpRequest.builder()
            .method("POST")
            .endpoint("https://elasticloadbalancing.us-east-1.amazonaws.com/")
            .addHeader("Host", "elasticloadbalancing.us-east-1.amazonaws.com")
            .payload(
                payloadFromStringWithContentType(
                    "Action=DescribeLoadBalancerPolicies"
                        + "&LoadBalancerName=moo"
                        + "&Signature=c8PG1b5wI5YMU0motVEo5Mz7d5w8gy8u51kfCR6SnRI%3D"
                        + "&SignatureMethod=HmacSHA256"
                        + "&SignatureVersion=2"
                        + "&Timestamp=2009-11-08T15%3A54%3A08.897Z"
                        + "&Version=2012-06-01"
                        + "&AWSAccessKeyId=identity",
                    "application/x-www-form-urlencoded"))
            .build();

    HttpResponse listWithOptionsResponse =
        HttpResponse.builder()
            .statusCode(200)
            .payload(payloadFromResourceWithContentType("/describe_policies.xml", "text/xml"))
            .build();

    ELBApi apiWhenWithOptionsExist = requestSendsResponse(listWithOptions, listWithOptionsResponse);

    assertEquals(
        apiWhenWithOptionsExist.getPolicyApi().list(loadBalancerName("moo")).toString(),
        new DescribeLoadBalancerPoliciesResponseTest().expected().toString());
  }
  public void testDeleteAndSaveSnapshotWhenResponseIs2xx() throws Exception {
    HttpRequest delete =
        HttpRequest.builder()
            .method("POST")
            .endpoint("https://rds.us-east-1.amazonaws.com/")
            .addHeader("Host", "rds.us-east-1.amazonaws.com")
            .payload(
                payloadFromStringWithContentType(
                    "Action=DeleteDBInstance"
                        + "&DBInstanceIdentifier=id"
                        + "&FinalDBSnapshotIdentifier=snap"
                        + "&Signature=aKuG1%2FYbZAzUFdAZTjke1LYRfR5JU86UxDt%2BtwdPJwE%3D"
                        + "&SignatureMethod=HmacSHA256"
                        + "&SignatureVersion=2"
                        + "&Timestamp=2009-11-08T15%3A54%3A08.897Z"
                        + "&Version=2012-04-23"
                        + "&AWSAccessKeyId=identity",
                    "application/x-www-form-urlencoded"))
            .build();
    HttpResponse deleteResponse =
        HttpResponse.builder()
            .statusCode(200)
            .payload(payloadFromResourceWithContentType("/delete_instance.xml", "text/xml"))
            .build();

    RDSApi apiWhenExist = requestSendsResponse(delete, deleteResponse);

    apiWhenExist.getInstanceApi().deleteAndSaveSnapshot("id", "snap");
  }
  public void testListWithOptionsWhenResponseIs2xx() throws Exception {
    HttpRequest listWithOptions =
        HttpRequest.builder()
            .method("POST")
            .endpoint("https://rds.us-east-1.amazonaws.com/")
            .addHeader("Host", "rds.us-east-1.amazonaws.com")
            .payload(
                payloadFromStringWithContentType(
                    "Action=DescribeDBInstances"
                        + "&Marker=MARKER"
                        + "&Signature=TFW8vaU2IppmBey0ZHttbWz4rMFh%2F5ACWl6Xyt58sQU%3D"
                        + "&SignatureMethod=HmacSHA256"
                        + "&SignatureVersion=2"
                        + "&Timestamp=2009-11-08T15%3A54%3A08.897Z"
                        + "&Version=2012-04-23"
                        + "&AWSAccessKeyId=identity",
                    "application/x-www-form-urlencoded"))
            .build();

    HttpResponse listWithOptionsResponse =
        HttpResponse.builder()
            .statusCode(200)
            .payload(payloadFromResourceWithContentType("/describe_instances.xml", "text/xml"))
            .build();

    RDSApi apiWhenWithOptionsExist = requestSendsResponse(listWithOptions, listWithOptionsResponse);

    assertEquals(
        apiWhenWithOptionsExist.getInstanceApi().list(afterMarker("MARKER")).toString(),
        new DescribeDBInstancesResponseTest().expected().toString());
  }