content: /**
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.aurora.scheduler.http;
  
  import java.util.Map;
  import java.util.Objects;
  
  import javax.inject.Inject;
  import javax.ws.rs.GET;
  import javax.ws.rs.Path;
  import javax.ws.rs.core.MediaType;
  import javax.ws.rs.core.Response;
  
  import com.google.common.annotations.VisibleForTesting;
  import com.google.common.base.Joiner;
  import com.google.common.collect.ImmutableMap;
  import com.google.common.collect.Maps;
  
  import org.apache.aurora.common.collections.Pair;
  
  import static javax.servlet.http.HttpServletResponse.SC_BAD_GATEWAY;
  import static javax.servlet.http.HttpServletResponse.SC_OK;
  import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
  
  import static org.apache.aurora.scheduler.http.LeaderRedirect.LeaderStatus;
  import static org.apache.aurora.scheduler.http.LeaderRedirect.LeaderStatus.LEADING;
  import static org.apache.aurora.scheduler.http.LeaderRedirect.LeaderStatus.NOT_LEADING;
  import static org.apache.aurora.scheduler.http.LeaderRedirect.LeaderStatus.NO_LEADER;
  
  /**
   * Servlet that exposes the leader health. It is meant to be used by load balancers such as
   * ELB to always forward to the leading scheduler.
   */
  @Path("/leaderhealth")
  public class LeaderHealth {
  
    private static final Map<LeaderStatus, Pair<Integer, String>> RESPONSE_CODES = ImmutableMap.of(
        LEADING, Pair.of(SC_OK, "This is the leading scheduler."),
        NOT_LEADING, Pair.of(SC_SERVICE_UNAVAILABLE, "Another instance is the leading scheduler."),
        NO_LEADER, Pair.of(SC_BAD_GATEWAY, "There is no leading scheduler or the leader is unknown.")
    );
  
    private static final String HELP = generateHelpText();
  
    private final LeaderRedirect leaderRedirect;
  
    @Inject
    LeaderHealth(LeaderRedirect leaderRedirect) {
      this.leaderRedirect = Objects.requireNonNull(leaderRedirect);
    }
  
    @VisibleForTesting
    static String getHelpText(LeaderStatus status) {
      return "Current status: " + RESPONSE_CODES.get(status).getSecond()
          + "\n\n"
          + HELP;
    }
  
    /**
     * Gets the leadership status of the scheduler.
     *
     * @return HTTP response.
     */
    @GET
    public Response get() {
      LeaderStatus leaderStatus = leaderRedirect.getLeaderStatus();
      return Response.status(RESPONSE_CODES.get(leaderStatus).getFirst())
          .type(MediaType.TEXT_PLAIN_TYPE)
          .entity(getHelpText(leaderStatus))
          .build();
    }
  
    private static String generateHelpText() {
      Map<Integer, String> details = Maps.transformValues(
          Maps.uniqueIndex(RESPONSE_CODES.values(), Pair::getFirst),
          Pair::getSecond);
  
      return "This endpoint can indicate to a load balancer which among a group of schedulers "
          + "is leading.\n\nThe response codes are:\n"
          + Joiner.on("\n").withKeyValueSeparator(": ").join(details);
    }
  }
  