Skip to content
This repository has been archived by the owner on Jun 22, 2018. It is now read-only.

Commit

Permalink
Merge pull request #544 from riccardomc/cli/minimesos-logs
Browse files Browse the repository at this point in the history
Add "minimesos logs" command
  • Loading branch information
frankscholten authored Sep 28, 2017
2 parents 4299c82 + 637e970 commit c087cb3
Show file tree
Hide file tree
Showing 11 changed files with 494 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
package com.containersol.minimesos.main;

import com.containersol.minimesos.cluster.ClusterRepository;
import com.containersol.minimesos.cluster.MesosCluster;
import com.containersol.minimesos.cluster.MesosClusterFactory;
import com.containersol.minimesos.mesos.MesosAgentContainer;
import com.containersol.minimesos.mesos.MesosMasterContainer;
import com.containersol.minimesos.state.*;
import com.containersol.minimesos.util.Downloader;
import org.junit.Before;
import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

import static java.util.Collections.singletonList;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class CommandLogsTest {

private final String slaveId = "de09c926-7be6-47c6-ab9a-6d1a2b32b642-S0";
private final String taskId = "http-ports-static-assigned-to-31002.0f732069-a1f2-11e7-97e0-0242ac110006";
private final String workDir = "/var/lib/mesos/agent-3039938407";
private final String frameworkId = "de09c926-7be6-47c6-ab9a-6d1a2b32b642-0000";
private final String runId = "fd7f7182-5ee8-47fc-a1c4-6928aeb1f769";
private final String agentServiceURL = "http://172.17.0.7:5051";

private final String PATH_FORMAT = "%s/slaves/%s/frameworks/%s/executors/%s/runs/%s";
private final String executorDirectory = String.format(PATH_FORMAT, workDir, slaveId, frameworkId, taskId, runId);

private final String STDOUT_URL = "http://172.17.0.7:5051" +
"/files/download?path=" +
"%2Fvar%2Flib%2Fmesos" +
"%2Fagent-3039938407" +
"%2Fslaves%2Fde09c926-7be6-47c6-ab9a-6d1a2b32b642-S0" +
"%2Fframeworks%2Fde09c926-7be6-47c6-ab9a-6d1a2b32b642-0000" +
"%2Fexecutors%2Fhttp-ports-static-assigned-to-31002.0f732069-a1f2-11e7-97e0-0242ac110006" +
"%2Fruns%2Ffd7f7182-5ee8-47fc-a1c4-6928aeb1f769" +
"%2Fstdout";

private final String STDERR_URL = "http://172.17.0.7:5051" +
"/files/download?path=" +
"%2Fvar%2Flib%2Fmesos" +
"%2Fagent-3039938407" +
"%2Fslaves%2Fde09c926-7be6-47c6-ab9a-6d1a2b32b642-S0" +
"%2Fframeworks%2Fde09c926-7be6-47c6-ab9a-6d1a2b32b642-0000" +
"%2Fexecutors%2Fhttp-ports-static-assigned-to-31002.0f732069-a1f2-11e7-97e0-0242ac110006" +
"%2Fruns%2Ffd7f7182-5ee8-47fc-a1c4-6928aeb1f769" +
"%2Fstderr";

private ByteArrayOutputStream outputStream;

private PrintStream ps;

private ClusterRepository repository;

private Downloader downloader;

private State masterState;

private State agentState;

@Before
public void initTest() throws URISyntaxException {
outputStream = new ByteArrayOutputStream();
ps = new PrintStream(outputStream, true);

masterState = generateMasterState();
agentState = generateAgentState();

MesosMasterContainer master = mock(MesosMasterContainer.class);
when(master.getState()).thenReturn(masterState);

MesosAgentContainer agent = mock(MesosAgentContainer.class);
when(agent.getState()).thenReturn(agentState);
when(agent.getServiceUrl()).thenReturn(new URI(agentServiceURL));

MesosCluster mesosCluster = mock(MesosCluster.class);
when(mesosCluster.getMaster()).thenReturn(master);
when(mesosCluster.getAgents()).thenReturn(Collections.singletonList(agent));

repository = mock(ClusterRepository.class);
when(repository.loadCluster(any(MesosClusterFactory.class))).thenReturn(mesosCluster);

downloader = mock(Downloader.class);
when(downloader.getFileContentAsString(STDOUT_URL)).thenReturn("stdout file content");
when(downloader.getFileContentAsString(STDERR_URL)).thenReturn("stderr file content");
}

@Test
public void TestStdout() throws UnsupportedEncodingException, URISyntaxException {
// Given
CommandLogs commandLogs = new CommandLogs(ps);
commandLogs.setRepository(repository);
commandLogs.setDownloader(downloader);
commandLogs.taskId = taskId;

// When
commandLogs.execute();

// Then
String result = outputStream.toString("UTF-8");
assertEquals(
"[minimesos] Fetching 'stdout' of task 'http-ports-static-assigned-to-31002.0f732069-a1f2-11e7-97e0-0242ac110006'\n\n" +
"stdout file content\n",
result);

}

@Test
public void TestUnexistingTask() throws UnsupportedEncodingException, URISyntaxException {
// Given
CommandLogs commandLogs = new CommandLogs(ps);
commandLogs.setRepository(repository);
commandLogs.setDownloader(downloader);
commandLogs.taskId = "doesn't exist";

// When
commandLogs.execute();

// Then
String result = outputStream.toString("UTF-8");
assertEquals("Cannot find task: 'doesn't exist'\n", result);

}

@Test
public void TestStderr() throws UnsupportedEncodingException, URISyntaxException {
// Given
CommandLogs commandLogs = new CommandLogs(ps);
commandLogs.setRepository(repository);
commandLogs.setDownloader(downloader);
commandLogs.taskId = taskId;
commandLogs.stderr = true;

// When
commandLogs.execute();

// Then
String result = outputStream.toString("UTF-8");
assertEquals(
"[minimesos] Fetching 'stderr' of task 'http-ports-static-assigned-to-31002.0f732069-a1f2-11e7-97e0-0242ac110006'\n\n" +
"stderr file content\n",
result);
}

private State generateAgentState() {
State state = new State();
state.setId(slaveId);

Framework marathon = new Framework();
marathon.setName("marathon");
marathon.setId(frameworkId);

Executor executor = new Executor();
executor.setDirectory(executorDirectory);
executor.setId(taskId);
ArrayList<Executor> executors = new ArrayList<>();
executors.add(executor);
marathon.setExecutors(executors);

ArrayList<Framework> frameworks = new ArrayList<>();
frameworks.add(marathon);
state.setFrameworks(frameworks);

return state;
}

private State generateMasterState() {
State state = new State();
Framework marathon = new Framework();
marathon.setName("marathon");

Task task = new Task();
task.setName("weave-scope");
task.setState("TASK_RUNNING");
task.setId(taskId);
task.setSlaveId(slaveId);
task.setFrameworkId(frameworkId);
task.setExecutorId("");

Port port = new Port();
port.setNumber(4040);

Ports ports = new Ports();
ports.setPorts(singletonList(port));

Discovery discovery = new Discovery();
discovery.setPorts(ports);

task.setDiscovery(discovery);

ArrayList<Task> tasks = new ArrayList<>();
tasks.add(task);

marathon.setTasks(tasks);

ArrayList<Framework> frameworks = new ArrayList<>();
frameworks.add(marathon);
state.setFrameworks(frameworks);

return state;
}
}
150 changes: 150 additions & 0 deletions cli/src/main/java/com/containersol/minimesos/main/CommandLogs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package com.containersol.minimesos.main;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.containersol.minimesos.MinimesosException;
import com.containersol.minimesos.cluster.ClusterRepository;
import com.containersol.minimesos.cluster.MesosAgent;
import com.containersol.minimesos.cluster.MesosCluster;
import com.containersol.minimesos.mesos.MesosClusterContainersFactory;
import com.containersol.minimesos.state.Executor;
import com.containersol.minimesos.state.Framework;
import com.containersol.minimesos.state.State;
import com.containersol.minimesos.state.Task;
import com.containersol.minimesos.util.Downloader;
import org.apache.http.client.utils.URIBuilder;

import java.io.PrintStream;
import java.net.URI;
import java.net.URISyntaxException;

import static org.apache.commons.lang.StringUtils.isNotBlank;
import static org.apache.commons.lang.StringUtils.isBlank;

@Parameters(separators = "=", commandDescription = "Fetches the stdout logs of the specified task")
public class CommandLogs implements Command {

private PrintStream output = System.out; // NOSONAR

private ClusterRepository repository = new ClusterRepository();

private Downloader downloader = new Downloader();

@Parameter(names = "--task", description = "Substring of a task ID", required = true)
String taskId = null;

@Parameter(names = "--stderr", description = "Fetch the stderr logs instead of stdout")
Boolean stderr = false;

public CommandLogs(PrintStream output) {
this.output = output;
}

public CommandLogs() {
//NOSONAR
}

@Override
public boolean validateParameters() {
return isNotBlank(taskId);
}

@Override
public String getName() {
return "logs";
}

@Override
public void execute() {
MesosCluster cluster = repository.loadCluster(new MesosClusterContainersFactory());
if (cluster == null) {
output.println("Minimesos cluster is not running");
return;
}

State masterState = cluster.getMaster().getState();
Task task = findTask(masterState, taskId);
if (task == null) {
output.println(String.format("Cannot find task: '%s'", taskId));
return;
}

MesosAgent agent = findAgent(cluster, task.getSlaveId());
if (agent == null) {
output.println(String.format("Cannot find agent: '%s'", task.getSlaveId()));
return;
}


String filename = stderr ? "stderr" : "stdout";
output.println(String.format("[minimesos] Fetching '%s' of task '%s'\n", filename, task.getId()));
URI fileUrl = getFileUrl(agent, task, filename);
String content = downloader.getFileContentAsString(fileUrl.toString());
output.println(content);
}

public void setRepository(ClusterRepository repository) {
this.repository = repository;
}

void setDownloader(Downloader downloader) {
this.downloader = downloader;
}

private Task findTask(State state, String taskId) {
for (Framework framework : state.getFrameworks()) {
for (Task task: framework.getTasks()) {
if (task.getId().contains(taskId)) {
return task;
}
}
}
return null;
}

private MesosAgent findAgent(MesosCluster cluster, String slaveId) {
for (MesosAgent agent : cluster.getAgents()) {
State agentState = agent.getState();
if (agentState.getId().equals(slaveId)) {
return agent;
}
}
return null;
}

private URI getFileUrl(MesosAgent agent, Task task, String filename) throws MinimesosException {
Executor executor = findExecutor(agent, task);
if (executor == null) {
throw new MinimesosException(String.format("Cannot find executor: '%s'", taskId));
}
String path = executor.getDirectory();
URIBuilder uriBuilder = new URIBuilder(agent.getServiceUrl())
.setPath("/files/download")
.addParameter("path", path + "/" + filename);
URI sandboxUrl = null;
try {
sandboxUrl = uriBuilder.build();
} catch (URISyntaxException e) {
throw new MinimesosException(e.getMessage());
}
return sandboxUrl;
}

private Executor findExecutor(MesosAgent agent, Task task) {
String executorId = task.getExecutorId();
if (isBlank(executorId)) { // if executorId is empty, try with the taskId
executorId = task.getId();
}
for (Framework framework : agent.getState().getFrameworks()) {
if (framework.getId().equals(task.getFrameworkId())) {
for (Executor executor : framework.getExecutors()) {
if (executor.getId().equals(executorId)) {
return executor;
}
}
}
}
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public static void main(String[] args) {
main.addCommand(new CommandInit());
main.addCommand(new CommandPs());
main.addCommand(new CommandVersion());
main.addCommand(new CommandLogs());
try {
int rc = main.run(args);
if (EXIT_CODE_OK != rc) {
Expand Down
Loading

0 comments on commit c087cb3

Please sign in to comment.