com.oneops.ecv.ws.StatusController.java Source code

Java tutorial

Introduction

Here is the source code for com.oneops.ecv.ws.StatusController.java

Source

/*******************************************************************************
 *
 *   Copyright 2015 Walmart, Inc.
 *
 *   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 com.oneops.ecv.ws;

import com.google.gson.Gson;
import com.oneops.ecv.auth.AuthUtil;
import com.oneops.ecv.auth.AuthenticationException;
import com.oneops.ecv.config.Config;
import com.oneops.ecv.config.ConfigException;
import com.oneops.ecv.health.FailedHealthCheckException;
import com.oneops.ecv.health.Health;
import com.oneops.ecv.health.HealthCheckUtils;
import com.oneops.ecv.health.IHealth;
import com.oneops.ecv.health.IHealthCheck;
import com.oneops.ecv.health.IHealthChecker;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Created by glall on 1/13/15.
 */
@Controller
@RequestMapping("/ecv")

public class StatusController {

    public static final String IPV4_LOCAL_ADDRESS = "127.0.0.1";
    public static final String IPV6_LOCAL_ADDRESS = "0:0:0:0:0:0:0:1";
    public static final String ALLOWED_IPS_PROPERTY = "ecv.localHostAddresses";
    private static final String SEPARATOR = ",";
    public static final String SEPARATED_LIST_OF_LOCAL_IPS = IPV4_LOCAL_ADDRESS + SEPARATOR + IPV6_LOCAL_ADDRESS;
    private final String allowedIps = System.getProperty(ALLOWED_IPS_PROPERTY, SEPARATED_LIST_OF_LOCAL_IPS);
    protected Logger ECV_LOGGER = Logger.getLogger(this.getClass());

    private Config config;
    private IHealthChecker healthChecker;
    private AuthUtil authUtil;
    private Gson gson = new Gson();
    @Autowired
    private Health okHealth;

    @Autowired
    private Health failedHealth;

    @Autowired
    private Health offlineHealth;

    @ExceptionHandler(FailedHealthCheckException.class)
    @ResponseBody
    public void handleExceptions(FailedHealthCheckException e, HttpServletResponse response) throws IOException {
        IHealth health = e.getHealth();
        response.setStatus(health.getStatusCode());
        response.getWriter().write(gson.toJson(health));
    }

    @ExceptionHandler(AuthenticationException.class)
    @ResponseBody
    public void handleAuthFailure(AuthenticationException e, HttpServletResponse response) throws IOException {
        ECV_LOGGER.error(e);
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().write(e.getMessage());
    }

    @ExceptionHandler(ConfigException.class)
    @ResponseBody
    public void handleConfigException(ConfigException e, HttpServletResponse response) throws IOException {
        ECV_LOGGER.error(e);
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        response.getWriter().write(e.getMessage());
    }

    @RequestMapping(value = "/status", method = RequestMethod.GET)
    @ResponseBody
    public IHealth status() {
        IHealth appHealth = failedHealth;
        String isOnline = config.getStatus();
        if (Config.ONLINE.equals(isOnline)) {
            List<IHealthCheck> healthChecks = healthChecker.getHealthChecksToRun();
            List<IHealth> results = new ArrayList<>(healthChecks.size());
            if ((healthChecks == null) || (healthChecks.isEmpty())) {
                return okHealth;
            } else {
                for (IHealthCheck healthCheck : healthChecks) {
                    if (healthCheck != null) {
                        IHealth health = healthCheck.getHealth();
                        if (ECV_LOGGER.isDebugEnabled()) {
                            ECV_LOGGER.debug("Health got by healthCheck " + healthCheck.getName() + " result :"
                                    + health.toString());
                        }
                        results.add(health);
                        if (!health.isOK()) {
                            throw new FailedHealthCheckException(health);
                        }
                    }
                }
                if (results.isEmpty()) {
                    ECV_LOGGER.info("results were empty");
                    appHealth = okHealth;
                } else {
                    //different health checks might have different status codes,one which has most weight
                    // will determine the overall status code
                    Collections.sort(results, HealthCheckUtils.STATUS_CODE_COMPARATOR);
                    IHealth healthThatMatters = results.get(0);
                    if (ECV_LOGGER.isDebugEnabled()) {
                        ECV_LOGGER.debug("over all status health got by healthCheck " + healthThatMatters.getName()
                                + " result :" + healthThatMatters.toString());
                    }
                    appHealth = healthThatMatters;
                }
            }

        } else {
            ECV_LOGGER.warn("The node is marked offline ");
            return offlineHealth;
        }
        if (ECV_LOGGER.isDebugEnabled()) {
            ECV_LOGGER.debug("over all status health got by healthCheck " + appHealth.getName() + " result :"
                    + appHealth.toString());
        }
        return appHealth;
    }

    @RequestMapping(value = "/status/offline", method = RequestMethod.PUT)
    @ResponseBody
    public IHealth offline(HttpServletRequest request) {
        checkIfAuthorized(request);
        config.setProperty(Config.OFFLINE);
        return status();
    }

    @RequestMapping(value = "/status/online", method = RequestMethod.PUT)
    @ResponseBody
    public IHealth online(HttpServletRequest request) {
        checkIfAuthorized(request);
        config.setProperty(Config.ONLINE);
        return status();
    }

    @RequestMapping(value = "/status/shutdown", method = RequestMethod.PUT)
    @ResponseBody
    public IHealth shutdown(HttpServletRequest request) {
        checkIfAuthorized(request);
        config.setTransientStatus(Config.SHUTDOWN);
        return status();
    }

    @RequestMapping(value = "/config/", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<Map<String, String>> getECVConfig() {
        return new ResponseEntity<Map<String, String>>(config.getInternalConfig(), HttpStatus.OK);
    }

    private void checkIfAuthorized(HttpServletRequest request) {
        boolean isAuthorized = isAuthorized(request);
        if (!isAuthorized) {
            throw new AuthenticationException("Failed to authorize");
        }
    }

    protected final boolean isAuthorized(HttpServletRequest req) {
        boolean isAuthorized;
        isAuthorized = authUtil.authenticate(req.getHeader("Authorization"));
        String remoteAddress = req.getRemoteAddr();
        boolean isLocalRequest = isLocal(remoteAddress);
        ECV_LOGGER.info("Authorizing validCredential :" + isAuthorized + " isLocal:" + isLocalRequest
                + " authorized:" + (isAuthorized && isLocalRequest));
        isAuthorized = isAuthorized && isLocalRequest;
        return isAuthorized;
    }

    protected boolean isLocal(String ip) {
        List<String> ips = Arrays.asList(allowedIps.split(SEPARATOR));
        if (ip != null && ip.indexOf("%") != -1) {
            ip = ip.substring(0, ip.indexOf("%"));
            ECV_LOGGER.debug(" ip to be checked " + ip);
        }
        boolean isValid = false;
        if (ips.contains(ip)) {
            isValid = true;
        }
        return isValid;
    }

    public void setConfig(Config config) {
        this.config = config;
    }

    public IHealthChecker getHealthChecker() {
        return healthChecker;
    }

    public void setHealthChecker(IHealthChecker healthChecker) {
        this.healthChecker = healthChecker;
    }

    public AuthUtil getAuthUtil() {
        return authUtil;
    }

    public void setAuthUtil(AuthUtil authUtil) {
        this.authUtil = authUtil;
    }

}