package ee.elinyo.teamcity.plugins.ansible.agent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import jetbrains.buildServer.agent.AgentLifeCycleAdapter;
import jetbrains.buildServer.agent.AgentLifeCycleListener;
import jetbrains.buildServer.agent.AgentRunningBuild;
import jetbrains.buildServer.agent.BuildFinishedStatus;
import jetbrains.buildServer.agent.artifacts.ArtifactsWatcher;
import jetbrains.buildServer.util.EventDispatcher;
import org.jetbrains.annotations.NotNull;
import com.intellij.openapi.diagnostic.Logger;
import ee.elinyo.teamcity.plugins.ansible.common.AnsibleRunnerConstants;
import ee.elinyo.teamcity.plugins.ansible.logparser.AnsibleOutputProcessor;
import ee.elinyo.teamcity.plugins.ansible.logparser.domain.Playbook;
public class AnsibleReportArtifatcsProvider extends AgentLifeCycleAdapter {
private static final Logger LOG = Logger.getInstance(AnsibleReportArtifatcsProvider.class.getName());
private static final String ACTIVITY_NAME = "Processing ansible output";
private static final String ACTIVITY_TYPE = "ansible_run_report";
private ArtifactsWatcher artifactsWatcher;
public AnsibleReportArtifatcsProvider(
@NotNull ArtifactsWatcher artifactsWatcher,
@NotNull EventDispatcher<AgentLifeCycleListener> agentDispatcher) {
agentDispatcher.addListener(this);
this.artifactsWatcher = artifactsWatcher;
}
public void beforeBuildFinish(@NotNull final AgentRunningBuild build, @NotNull final BuildFinishedStatus buildStatus) {
String tmpDirPath = build.getSharedConfigParameters().get(AnsibleRunnerConstants.ARTIFACTS_TMP_DIR_KEY);
if (tmpDirPath == null) {
return;
}
File tmpDir = new File(tmpDirPath);
if (tmpDir.exists() && tmpDir.isDirectory()) {
File[] rawFiles = tmpDir.listFiles();
if (rawFiles == null || rawFiles.length == 0) {
build.getBuildLogger().warning("Build defines ansible-run tmp directory but it doesn't contain any files");
} else {
generateReport(build, rawFiles);
}
} else {
build.getBuildLogger().warning("Build defines ansible-run tmp directory but it doesn't exist");
}
}
private void generateReport(AgentRunningBuild build, File[] rawFiles) {
build.getBuildLogger().activityStarted(ACTIVITY_NAME, ACTIVITY_TYPE);
try {
build.getBuildLogger().message("Generating ansible report artifacts...");
List<Playbook> playbooks = new ArrayList<Playbook>();
if (LOG.isDebugEnabled()) {
LOG.debug("Ansible reports will be generated for the following raw files: ");
for (File f : rawFiles) {
LOG.debug(f.getAbsolutePath());
}
}
Arrays.sort(rawFiles, new Comparator<File>() {
@Override
public int compare(File f1, File f2) {
return Long.valueOf(f1.lastModified() - f2.lastModified()).intValue();
}
});
for (File f: rawFiles) {
Playbook p = getPlaybook(f);
if (p == null) {
build.getBuildLogger().warning("Failed to generate report. Check agent logs for more details");
} else {
playbooks.add(p);
}
}
provideArtifacts(playbooks, build);
} finally {
build.getBuildLogger().activityFinished(ACTIVITY_NAME, ACTIVITY_TYPE);
}
}
private void provideArtifacts(List<Playbook> playbooks, AgentRunningBuild build) {
File tmpReport = new File(build.getBuildTempDirectory(), AnsibleRunnerConstants.ARTIFACTS_JSON_REPORT);
try {
tmpReport.createNewFile();
ReportBuilder.buildJsonReport(playbooks, tmpReport);
build.getBuildLogger().message("Uploading artifact...");
artifactsWatcher.addNewArtifactsPath(tmpReport.getAbsolutePath() + "=>" + AnsibleRunnerConstants.ARTIFACTS_BASE_DIR);
} catch (Exception e) {
LOG.error("Failed to create a file to write ansible run report", e);
build.getBuildLogger().warning("Failed to generate report. Check agent logs for more details");
}
}
private Playbook getPlaybook(File rawLog) {
AnsibleOutputProcessor logProcessor = new AnsibleOutputProcessor();
Playbook result = null;
try (BufferedReader br = new BufferedReader(new FileReader(rawLog))) {
String strLine = "";
while( (strLine = br.readLine()) != null){
logProcessor.onLine(strLine);
}
result = logProcessor.finish();
} catch (Exception e) {
LOG.error("Failed to generate ansible run report", e);
}
return result;
}
}