/*
* Copyright © 2014-2015 Cask Data, 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 co.cask.cdap.data2.datafabric.dataset.service.executor;
import co.cask.cdap.api.dataset.DatasetAdmin;
import co.cask.cdap.api.dataset.DatasetProperties;
import co.cask.cdap.api.dataset.DatasetSpecification;
import co.cask.cdap.common.BadRequestException;
import co.cask.cdap.common.NotFoundException;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.proto.DatasetTypeMeta;
import co.cask.cdap.proto.Id;
import co.cask.http.AbstractHttpHandler;
import co.cask.http.HttpResponder;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.gson.Gson;
import com.google.inject.Inject;
import org.apache.commons.lang.StringUtils;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
* Provides REST endpoints for {@link DatasetAdmin} operations.
*/
@Path(Constants.Gateway.API_VERSION_3 + "/namespaces/{namespace-id}")
public class DatasetAdminOpHTTPHandler extends AbstractHttpHandler {
private static final Logger LOG = LoggerFactory.getLogger(DatasetAdminOpHTTPHandler.class);
private static final Gson GSON = new Gson();
private final DatasetAdminService datasetAdminService;
@Inject
public DatasetAdminOpHTTPHandler(DatasetAdminService datasetAdminService) {
this.datasetAdminService = datasetAdminService;
}
@POST
@Path("/data/datasets/{name}/admin/exists")
public void exists(HttpRequest request, HttpResponder responder,
@PathParam("namespace-id") String namespaceId,
@PathParam("name") String instanceName) {
Id.Namespace namespace = Id.Namespace.from(namespaceId);
try {
Id.DatasetInstance instanceId = Id.DatasetInstance.from(namespace, instanceName);
responder.sendJson(HttpResponseStatus.OK,
new DatasetAdminOpResponse(datasetAdminService.exists(instanceId), null));
} catch (NotFoundException e) {
LOG.debug("Got handler exception", e);
responder.sendString(HttpResponseStatus.NOT_FOUND, StringUtils.defaultIfEmpty(e.getMessage(), ""));
} catch (Exception e) {
LOG.error(getAdminOpErrorMessage("exists", instanceName), e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, getAdminOpErrorMessage("exists", instanceName));
}
}
@POST
@Path("/data/datasets/{name}/admin/create")
public void create(HttpRequest request, HttpResponder responder,
@PathParam("namespace-id") String namespaceId,
@PathParam("name") String name) {
InternalDatasetCreationParams params = GSON.fromJson(request.getContent().toString(Charsets.UTF_8),
InternalDatasetCreationParams.class);
Preconditions.checkArgument(params.getProperties() != null, "Missing required 'instanceProps' parameter.");
Preconditions.checkArgument(params.getTypeMeta() != null, "Missing required 'typeMeta' parameter.");
Preconditions.checkArgument(params.isExisting() != null, "Missing required 'existing' parameter.");
DatasetProperties props = params.getProperties();
DatasetTypeMeta typeMeta = params.getTypeMeta();
try {
Id.DatasetInstance instanceId = Id.DatasetInstance.from(namespaceId, name);
DatasetSpecification spec = datasetAdminService.create(instanceId, typeMeta, props, params.isExisting());
responder.sendJson(HttpResponseStatus.OK, spec);
} catch (BadRequestException e) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
} catch (Exception e) {
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, e.getMessage());
}
}
@POST
@Path("/data/datasets/{name}/admin/drop")
public void drop(HttpRequest request, HttpResponder responder,
@PathParam("namespace-id") String namespaceId,
@PathParam("name") String instanceName) throws Exception {
InternalDatasetDropParams params = GSON.fromJson(request.getContent().toString(Charsets.UTF_8),
InternalDatasetDropParams.class);
Preconditions.checkArgument(params.getInstanceSpec() != null, "Missing required 'instanceSpec' parameter.");
Preconditions.checkArgument(params.getTypeMeta() != null, "Missing required 'typeMeta' parameter.");
DatasetSpecification spec = params.getInstanceSpec();
DatasetTypeMeta typeMeta = params.getTypeMeta();
try {
datasetAdminService.drop(Id.DatasetInstance.from(namespaceId, instanceName), typeMeta, spec);
responder.sendJson(HttpResponseStatus.OK, spec);
} catch (BadRequestException e) {
responder.sendString(HttpResponseStatus.BAD_REQUEST, e.getMessage());
}
}
@POST
@Path("/data/datasets/{name}/admin/truncate")
public void truncate(HttpRequest request, HttpResponder responder,
@PathParam("namespace-id") String namespaceId,
@PathParam("name") String instanceName) {
try {
Id.DatasetInstance instanceId = Id.DatasetInstance.from(namespaceId, instanceName);
datasetAdminService.truncate(instanceId);
responder.sendJson(HttpResponseStatus.OK, new DatasetAdminOpResponse(null, null));
} catch (NotFoundException e) {
LOG.debug("Got handler exception", e);
responder.sendString(HttpResponseStatus.NOT_FOUND, StringUtils.defaultIfEmpty(e.getMessage(), ""));
} catch (Exception e) {
LOG.error(getAdminOpErrorMessage("truncate", instanceName), e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, getAdminOpErrorMessage("truncate", instanceName));
}
}
@POST
@Path("/data/datasets/{name}/admin/upgrade")
public void upgrade(HttpRequest request, HttpResponder responder,
@PathParam("namespace-id") String namespaceId,
@PathParam("name") String instanceName) {
try {
Id.DatasetInstance instanceId = Id.DatasetInstance.from(namespaceId, instanceName);
datasetAdminService.upgrade(instanceId);
responder.sendJson(HttpResponseStatus.OK, new DatasetAdminOpResponse(null, null));
} catch (NotFoundException e) {
LOG.debug("Got handler exception", e);
responder.sendString(HttpResponseStatus.NOT_FOUND, StringUtils.defaultIfEmpty(e.getMessage(), ""));
} catch (Exception e) {
LOG.error(getAdminOpErrorMessage("upgrade", instanceName), e);
responder.sendString(HttpResponseStatus.INTERNAL_SERVER_ERROR, getAdminOpErrorMessage("upgrade", instanceName));
}
}
private String getAdminOpErrorMessage(String opName, String instanceName) {
return String.format("Error executing admin operation %s for dataset instance %s", opName, instanceName);
}
}