public static FleetStateStats readClusterState(final AmazonEC2 ec2, final String fleetId) {
    String token = null;
    final Set<String> instances = new HashSet<String>();
    do {
      final DescribeSpotFleetInstancesRequest req = new DescribeSpotFleetInstancesRequest();
      req.setSpotFleetRequestId(fleetId);
      req.setNextToken(token);
      final DescribeSpotFleetInstancesResult res = ec2.describeSpotFleetInstances(req);
      for (final ActiveInstance instance : res.getActiveInstances()) {
        instances.add(instance.getInstanceId());
      }

      token = res.getNextToken();
    } while (token != null);

    final DescribeSpotFleetRequestsRequest req = new DescribeSpotFleetRequestsRequest();
    req.setSpotFleetRequestIds(Collections.singleton(fleetId));
    final DescribeSpotFleetRequestsResult fleet = ec2.describeSpotFleetRequests(req);
    if (fleet.getSpotFleetRequestConfigs().isEmpty())
      throw new IllegalStateException("Fleet " + fleetId + " can't be described");

    final SpotFleetRequestConfig fleetConfig = fleet.getSpotFleetRequestConfigs().get(0);

    return new FleetStateStats(
        fleetId,
        fleetConfig.getSpotFleetRequestConfig().getTargetCapacity(),
        fleetConfig.getSpotFleetRequestState(),
        instances);
  }
  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;

    if (obj instanceof DescribeSpotFleetInstancesRequest == false) return false;
    DescribeSpotFleetInstancesRequest other = (DescribeSpotFleetInstancesRequest) obj;

    if (other.getSpotFleetRequestId() == null ^ this.getSpotFleetRequestId() == null) return false;
    if (other.getSpotFleetRequestId() != null
        && other.getSpotFleetRequestId().equals(this.getSpotFleetRequestId()) == false)
      return false;
    if (other.getNextToken() == null ^ this.getNextToken() == null) return false;
    if (other.getNextToken() != null && other.getNextToken().equals(this.getNextToken()) == false)
      return false;
    if (other.getMaxResults() == null ^ this.getMaxResults() == null) return false;
    if (other.getMaxResults() != null
        && other.getMaxResults().equals(this.getMaxResults()) == false) return false;
    return true;
  }