package com.thinkbiganalytics.metadata.rest.api; /*- * #%L * thinkbig-metadata-rest-controller * %% * Copyright (C) 2017 ThinkBig Analytics * %% * 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. * #L% */ import com.thinkbiganalytics.metadata.api.MetadataAccess; import com.thinkbiganalytics.metadata.api.event.MetadataEventService; import com.thinkbiganalytics.metadata.api.event.feed.FeedOperationStatusEvent; import com.thinkbiganalytics.metadata.api.event.feed.OperationStatus; import com.thinkbiganalytics.metadata.api.op.FeedOperation; import com.thinkbiganalytics.metadata.api.security.MetadataAccessControl; import com.thinkbiganalytics.metadata.api.sla.FeedExecutedSinceFeed; import com.thinkbiganalytics.metadata.api.sla.FeedExecutedSinceSchedule; import com.thinkbiganalytics.metadata.api.sla.WithinSchedule; import com.thinkbiganalytics.metadata.modeshape.JcrMetadataAccess; import com.thinkbiganalytics.metadata.modeshape.support.JcrTool; import com.thinkbiganalytics.metadata.rest.model.data.Datasource; import com.thinkbiganalytics.metadata.rest.model.data.HiveTableDatasource; import com.thinkbiganalytics.metadata.rest.model.feed.FeedPrecondition; import com.thinkbiganalytics.metadata.sla.api.Metric; import com.thinkbiganalytics.security.AccessController; import org.modeshape.jcr.api.JcrTools; import org.springframework.stereotype.Component; import java.io.PrintWriter; import java.io.StringWriter; import java.text.ParseException; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import javax.jcr.Node; import javax.jcr.Session; import javax.ws.rs.DELETE; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriInfo; import io.swagger.annotations.Api; import io.swagger.annotations.SwaggerDefinition; import io.swagger.annotations.Tag; /** * A controller to use when debugging issues with the UI */ @Api(tags = "Internal", produces = "application/json") @Component @Path("/v1/metadata/debug") @SwaggerDefinition(tags = @Tag(name = "Internal", description = "debugging tools")) public class DebugController { @Context private UriInfo uriInfo; @Inject private MetadataAccess metadata; @Inject private MetadataEventService eventService; @Inject private AccessController accessController; /** * Allows the caller to update status events for the feed * * @param feedName the name of the feed * @param opIdStr the operation for the feed * @param stateStr the new state to persist * @param status the status of the operation * @return the feed operation status event */ @POST @Path("feedop/event") public String postFeedOperationStatusEvent(@QueryParam("feed") String feedName, @QueryParam("op") String opIdStr, @QueryParam("state") String stateStr, @QueryParam("status") @DefaultValue("") String status) { // TODO: Is this a feed ops permission? this.accessController.checkPermission(AccessController.SERVICES, MetadataAccessControl.ADMIN_METADATA); FeedOperation.ID opId = null; FeedOperation.State state = FeedOperation.State.valueOf(stateStr.toUpperCase()); OperationStatus opStatus = new OperationStatus(feedName, opId, state, status); FeedOperationStatusEvent event = new FeedOperationStatusEvent(opStatus); this.eventService.notify(event); return event.toString(); } /** * creates a hive table model object for debugging * * @return the hive table data source model */ @GET @Path("datasource/hivetable") @Produces(MediaType.APPLICATION_JSON) public Datasource exampleHiveTable() { return new HiveTableDatasource("table1", "database1", "table1"); } /** * returns a list of metrics for debugging * * @return a list of metrics */ @GET @Path("metrics") @Produces(MediaType.APPLICATION_JSON) public List<Metric> exampleMetrics() { List<Metric> metrics = new ArrayList<>(); FeedExecutedSinceSchedule feedExecutedSinceSchedule = null; try { feedExecutedSinceSchedule = new FeedExecutedSinceSchedule("category", "Feed", "* * * * * ? *"); metrics.add(feedExecutedSinceSchedule); WithinSchedule withinSchedule = new com.thinkbiganalytics.metadata.api.sla.WithinSchedule("* * * * * ? *", "4 hours"); metrics.add(withinSchedule); } catch (ParseException e) { throw new RuntimeException(e); } return metrics; } /** * returns a new feed precondition model for debugging * * @return the precondition model */ @GET @Path("precondition") @Produces(MediaType.APPLICATION_JSON) public FeedPrecondition examplePrecondition() { FeedPrecondition procond = new FeedPrecondition("DependingPrecondition"); procond.addMetrics("Feed dependson on execution of another feed", new FeedExecutedSinceFeed("DependentCategory", "DependentFeed", "ExecutedSinceCategory", "ExecutedSinceFeed")); return procond; } /** * Delete the JCR tree specified by the absolute path following ".../jcr/". * * @param abspath the path with JCR to delete * @return a confirmation message that the path was deleted */ @DELETE @Path("jcr/{abspath: .*}") @Produces(MediaType.TEXT_PLAIN) public String deleteJcrTree(@PathParam("abspath") final String abspath) { this.accessController.checkPermission(AccessController.SERVICES, MetadataAccessControl.ADMIN_METADATA); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); try { metadata.commit(() -> { Session session = JcrMetadataAccess.getActiveSession(); session.removeItem("/" + abspath); pw.print("DELETED " + abspath); }); } catch (Exception e) { e.printStackTrace(pw); throw new RuntimeException(e); } pw.flush(); return sw.toString(); } /** * Prints the nodes of the JCR path given, for debugging. * * @param abspath the path in JCR * @return a printout of the JCR tree */ @GET @Path("jcr/{abspath: .*}") @Produces({ MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON }) public String printJcrTree(@PathParam("abspath") final String abspath) { this.accessController.checkPermission(AccessController.SERVICES, MetadataAccessControl.ACCESS_METADATA); return metadata.read(() -> { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); try { Session session = JcrMetadataAccess.getActiveSession(); Node node = session.getRootNode().getNode(abspath); JcrTools tools = new JcrTool(true, pw); tools.printSubgraph(node); } catch (Exception e) { throw new RuntimeException(e); } pw.flush(); return sw.toString(); }); } /** * Prints the subgraph of the node in JCR with the specified ID. * * @param jcrId the id of the node in JCR * @return the subgraph print out */ @GET @Path("jcr") @Produces({ MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON }) public String printJcrId(@QueryParam("id") final String jcrId) { this.accessController.checkPermission(AccessController.SERVICES, MetadataAccessControl.ACCESS_METADATA); return metadata.read(() -> { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); try { Session session = JcrMetadataAccess.getActiveSession(); Node node = session.getNodeByIdentifier(jcrId); pw.print("Path: "); pw.println(node.getPath()); JcrTools tools = new JcrTool(true, pw); tools.printSubgraph(node); } catch (Exception e) { throw new RuntimeException(e); } pw.flush(); return sw.toString(); }); } }