com.pinterest.teletraan.resource.Groups.java Source code

Java tutorial

Introduction

Here is the source code for com.pinterest.teletraan.resource.Groups.java

Source

/**
 * Copyright 2016 Pinterest, 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.pinterest.teletraan.resource;

import com.google.common.base.Optional;
import com.pinterest.arcee.bean.GroupBean;
import com.pinterest.arcee.bean.HealthCheckBean;
import com.pinterest.arcee.bean.HealthCheckErrorBean;
import com.pinterest.arcee.handler.GroupHandler;
import com.pinterest.arcee.handler.HealthCheckHandler;
import com.pinterest.arcee.handler.ProvisionHandler;
import com.pinterest.deployservice.bean.ConfigHistoryBean;
import com.pinterest.deployservice.bean.HostBean;
import com.pinterest.deployservice.bean.Role;
import com.pinterest.deployservice.common.Constants;
import com.pinterest.deployservice.dao.EnvironDAO;
import com.pinterest.deployservice.handler.ConfigHistoryHandler;
import com.pinterest.teletraan.TeletraanServiceContext;
import com.pinterest.teletraan.exception.TeletaanInternalException;
import com.pinterest.teletraan.security.Authorizer;

import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.Valid;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import java.util.List;

@Path("/v1/groups")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class Groups {
    public enum ActionType {
        ROLLBACK
    }

    public enum HealthCheckActionType {
        ENABLE, DISABLE
    }

    private static final Logger LOG = LoggerFactory.getLogger(Groups.class);
    private final static int DEFAULT_SIZE = 100;
    private GroupHandler groupHandler;
    private ConfigHistoryHandler configHistoryHandler;
    private ProvisionHandler provisionHandler;
    private EnvironDAO environDAO;
    private HealthCheckHandler healthCheckHandler;
    private final Authorizer authorizer;

    public Groups(TeletraanServiceContext context) {
        groupHandler = new GroupHandler(context);
        configHistoryHandler = new ConfigHistoryHandler(context);
        provisionHandler = new ProvisionHandler(context);
        healthCheckHandler = new HealthCheckHandler(context);
        environDAO = context.getEnvironDAO();
        authorizer = context.getAuthorizer();
    }

    @GET
    @Path("/names")
    public List<String> getGroupNames(@QueryParam("start") Optional<Integer> start,
            @QueryParam("size") Optional<Integer> size) throws Exception {
        return groupHandler.getEnvGroupNames(start.or(1), size.or(DEFAULT_SIZE));
    }

    @POST
    @Path("/{groupName: [a-zA-Z0-9\\-_]+}")
    public void createGroup(@Context SecurityContext sc, @PathParam("groupName") String groupName,
            GroupBean groupBean) throws Exception {
        Utils.authorizeGroup(environDAO, groupName, sc, authorizer, Role.OPERATOR);
        String operator = sc.getUserPrincipal().getName();
        groupHandler.createGroup(groupName, groupBean);
        configHistoryHandler.updateConfigHistory(groupName, Constants.TYPE_ASG_GENERAL, groupBean, operator);
        LOG.info("Successfully created group {} with config {} by {}", groupName, groupBean, operator);
    }

    @PUT
    @Path("/{groupName: [a-zA-Z0-9\\-_]+}")
    public void updateGroupLaunchConfig(@Context SecurityContext sc, @PathParam("groupName") String groupName,
            GroupBean groupBean) throws Exception {
        Utils.authorizeGroup(environDAO, groupName, sc, authorizer, Role.OPERATOR);
        String operator = sc.getUserPrincipal().getName();
        groupHandler.updateLaunchConfig(groupName, groupBean);
        configHistoryHandler.updateConfigHistory(groupName, Constants.TYPE_ASG_GENERAL, groupBean, operator);
        configHistoryHandler.updateChangeFeed(Constants.CONFIG_TYPE_GROUP, groupName, Constants.TYPE_ASG_GENERAL,
                operator);
        LOG.info("Successfully updated group {} with config {} by {}", groupName, groupBean, operator);
    }

    @GET
    @Path("/{groupName: [a-zA-Z0-9\\-_]+}")
    public GroupBean get(@PathParam("groupName") String groupName) throws Exception {
        return groupHandler.getLaunchConfig(groupName);
    }

    @GET
    @Path("/{groupName: [a-zA-Z0-9\\-_]+}/instances")
    public List<HostBean> getHostsByGroup(@PathParam("groupName") String groupName) throws Exception {
        return groupHandler.getHostsByGroupName(groupName);
    }

    @PUT
    @Path("/{groupName: [a-zA-Z0-9\\-_]+}/instances")
    public List<String> launchNewInstances(@Context SecurityContext sc, @PathParam("groupName") String groupName,
            @QueryParam("instanceCount") Optional<Integer> instanceCnt,
            @NotEmpty @QueryParam("subnet") String subnet) throws Exception {
        Utils.authorizeGroup(environDAO, groupName, sc, authorizer, Role.OPERATOR);
        String operator = sc.getUserPrincipal().getName();
        List<String> instanceIds = provisionHandler.launchNewInstances(groupName, instanceCnt.or(1), subnet,
                operator);
        if (!instanceIds.isEmpty()) {
            String configChange = String.format("%s", instanceIds);
            configHistoryHandler.updateConfigHistory(groupName, Constants.TYPE_HOST_LAUNCH, configChange, operator);
        }
        return instanceIds;
    }

    @DELETE
    @Path("/instances/{hostId: [a-zA-Z0-9\\-_]+}")
    public void terminateInstance(@Context SecurityContext sc, @PathParam("hostId") String hostId,
            @QueryParam("decreaseSize") Boolean decreaseSize, @QueryParam("groupName") String groupName)
            throws Exception {
        // TODO we need env name or group for this one!
        // Utils.authorizeGroup(environDAO, groupName, sc, authorizer, Role.OPERATOR);
        String operator = sc.getUserPrincipal().getName();
        List<String> groupNames = provisionHandler.terminateHost(hostId, decreaseSize, operator);
        String configChange = String.format("Instance Id : %s", hostId);
        for (String name : groupNames) {
            configHistoryHandler.updateConfigHistory(name, Constants.TYPE_HOST_TERMINATE, configChange, operator);
        }
    }

    @GET
    @Path("/{groupName: [a-zA-Z0-9\\-_]+}/configs/history")
    public List<ConfigHistoryBean> getConfigHistory(@PathParam("groupName") String groupName,
            @QueryParam("pageIndex") Optional<Integer> pageIndex,
            @QueryParam("pageSize") Optional<Integer> pageSize) throws Exception {
        return configHistoryHandler.getConfigHistoryByName(groupName, pageIndex.or(1), pageSize.or(DEFAULT_SIZE));
    }

    @PUT
    @Path("/{groupName: [a-zA-Z0-9\\-_]+}/configs/actions")
    public void rollbackConfig(@Context SecurityContext sc, @PathParam("groupName") String groupName,
            @NotEmpty @QueryParam("actionType") ActionType actionType, @QueryParam("changeId") String changeId)
            throws Exception {
        Utils.authorizeGroup(environDAO, groupName, sc, authorizer, Role.OPERATOR);
        String operator = sc.getUserPrincipal().getName();
        switch (actionType) {
        case ROLLBACK:
            configHistoryHandler.rollbackConfig(Constants.CONFIG_TYPE_GROUP, changeId, operator);
            LOG.info("{} rollbacked group {} config to config id = {}", operator, groupName, changeId);
            break;
        default:
            throw new TeletaanInternalException(Response.Status.BAD_REQUEST, "No action found.");
        }
    }

    @GET
    @Path("/{groupName: [a-zA-Z0-9\\-_]+}/healthchecks")
    public List<HealthCheckBean> getHealthChecks(@PathParam("groupName") String groupName,
            @QueryParam("pageIndex") Optional<Integer> pageIndex,
            @QueryParam("pageSize") Optional<Integer> pageSize) throws Exception {
        return healthCheckHandler.getHealthChecksByGroup(groupName, pageIndex.or(1), pageSize.or(DEFAULT_SIZE));
    }

    @GET
    @Path("/healthchecks/{id: [a-zA-Z0-9\\-_]+}")
    public HealthCheckBean getHealthCheck(@Context SecurityContext sc, @PathParam("id") String id)
            throws Exception {
        return healthCheckHandler.getHealthCheckById(id);
    }

    @GET
    @Path("/healthchecks/errors/{id: [a-zA-Z0-9\\-_]+}")
    public HealthCheckErrorBean getHealthCheckError(@Context SecurityContext sc, @PathParam("id") String id)
            throws Exception {
        return healthCheckHandler.getHealthCheckErrorById(id);
    }

    @POST
    @Path("/{groupName: [a-zA-Z0-9\\-_]+}/healthcheck")
    public void createHealthCheck(@Context SecurityContext sc, @PathParam("groupName") String groupName,
            HealthCheckBean healthCheckBean) throws Exception {
        Utils.authorizeGroup(environDAO, groupName, sc, authorizer, Role.OPERATOR);
        String operator = sc.getUserPrincipal().getName();

        healthCheckBean.setGroup_name(groupName);
        List<String> ids = healthCheckHandler.createHealthCheck(healthCheckBean);
        String results = ids.toString();
        if (ids.isEmpty()) {
            results = "Health check isn't enabled";
        }
        configHistoryHandler.updateConfigHistory(groupName, Constants.TYPE_HELATHCHECK_MANAUALLY, results,
                operator);
        LOG.info("{} have added to group {} by {}", results, groupName, operator);
    }

    @POST
    @Path("/{groupName: [a-zA-Z0-9\\-_]+}/healthcheck/action")
    public void actionOnHealthCheckState(@Context SecurityContext sc, @PathParam("groupName") String groupName,
            @QueryParam("type") String type) throws Exception {
        Utils.authorizeGroup(environDAO, groupName, sc, authorizer, Role.OPERATOR);
        HealthCheckActionType actionType = HealthCheckActionType.valueOf(HealthCheckActionType.class,
                type.toUpperCase());
        if (actionType == HealthCheckActionType.ENABLE) {
            groupHandler.updateHealthCheckState(groupName, true);
            LOG.info(String.format("Enable health check for group %s", groupName));
            return;
        } else if (actionType == HealthCheckActionType.DISABLE) {
            groupHandler.updateHealthCheckState(groupName, false);
            LOG.info(String.format("Disable health check for group %s", groupName));
            return;
        }

        throw new TeletaanInternalException(Response.Status.BAD_REQUEST,
                String.format("Unkonw action type: %s", type));
    }
}