mirror of
https://github.com/ohwgiles/laminar.git
synced 2024-10-27 20:34:20 +00:00
implement display and serving of archived artifacts
This commit is contained in:
parent
dbc75000a5
commit
a729a6782e
10
laminar.conf
10
laminar.conf
@ -15,3 +15,13 @@
|
|||||||
### will not be deleted after the run has completed
|
### will not be deleted after the run has completed
|
||||||
###
|
###
|
||||||
#LAMINAR_KEEP_WORKDIR=1
|
#LAMINAR_KEEP_WORKDIR=1
|
||||||
|
|
||||||
|
###
|
||||||
|
### LAMINAR_ARCHIVE_URL
|
||||||
|
###
|
||||||
|
### Base url used to request artifacts. Laminar can serve build
|
||||||
|
### artifacts (and it will if you leave this unset), but it
|
||||||
|
### uses a very naive and inefficient method. Best to let a real
|
||||||
|
### webserver handle serving those requests.
|
||||||
|
###
|
||||||
|
#LAMINAR_ARCHIVE_URL=http://backbone.example.com/ci/archive
|
||||||
|
@ -107,6 +107,11 @@ struct LaminarInterface {
|
|||||||
// arbitrary parameters on a run (usually itself) to be available in
|
// arbitrary parameters on a run (usually itself) to be available in
|
||||||
// the environment of subsequent scripts.
|
// the environment of subsequent scripts.
|
||||||
virtual bool setParam(std::string job, int buildNum, std::string param, std::string value) = 0;
|
virtual bool setParam(std::string job, int buildNum, std::string param, std::string value) = 0;
|
||||||
|
|
||||||
|
// Fetches the content of an artifact given its filename relative to
|
||||||
|
// $LAMINAR_HOME/archive. This shouldn't be used, because the sysadmin
|
||||||
|
// should have configured a real webserver to serve these things.
|
||||||
|
virtual bool getArtefact(std::string path, std::string& result) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INTERFACE_H
|
#endif // INTERFACE_H
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <fstream>
|
||||||
#include <kj/debug.h>
|
#include <kj/debug.h>
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
@ -56,12 +57,15 @@ namespace {
|
|||||||
// Default values when none were supplied in $LAMINAR_CONF_FILE (/etc/laminar.conf)
|
// Default values when none were supplied in $LAMINAR_CONF_FILE (/etc/laminar.conf)
|
||||||
constexpr const char* INTADDR_RPC_DEFAULT = "unix:\0laminar";
|
constexpr const char* INTADDR_RPC_DEFAULT = "unix:\0laminar";
|
||||||
constexpr const char* INTADDR_HTTP_DEFAULT = "*:8080";
|
constexpr const char* INTADDR_HTTP_DEFAULT = "*:8080";
|
||||||
constexpr const char* BASE_CFG_DIR = "/home/og/dev/laminar/cfg";
|
constexpr const char* ARCHIVE_URL_DEFAULT = "/archive";
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::string str;
|
typedef std::string str;
|
||||||
|
|
||||||
Laminar::Laminar() {
|
Laminar::Laminar() {
|
||||||
|
archiveUrl = ARCHIVE_URL_DEFAULT;
|
||||||
|
if(char* envArchive = getenv("LAMINAR_ARCHIVE_URL"))
|
||||||
|
archiveUrl = envArchive;
|
||||||
eraseWorkdir = true;
|
eraseWorkdir = true;
|
||||||
homeDir = getenv("LAMINAR_HOME") ?: "/var/lib/laminar";
|
homeDir = getenv("LAMINAR_HOME") ?: "/var/lib/laminar";
|
||||||
|
|
||||||
@ -125,6 +129,20 @@ void Laminar::sendStatus(LaminarClient* client) {
|
|||||||
j.set("result", to_string(RunState(result)));
|
j.set("result", to_string(RunState(result)));
|
||||||
j.set("reason", reason);
|
j.set("reason", reason);
|
||||||
});
|
});
|
||||||
|
j.startArray("artifacts");
|
||||||
|
fs::path dir(fs::path(homeDir)/"archive"/client->scope.job/std::to_string(client->scope.num));
|
||||||
|
fs::recursive_directory_iterator rdt(dir);
|
||||||
|
int prefixLen = (fs::path(homeDir)/"archive").string().length();
|
||||||
|
int scopeLen = dir.string().length();
|
||||||
|
for(fs::directory_entry e : rdt) {
|
||||||
|
if(!fs::is_regular_file(e))
|
||||||
|
continue;
|
||||||
|
j.StartObject();
|
||||||
|
j.set("url", archiveUrl + e.path().string().substr(prefixLen));
|
||||||
|
j.set("filename", e.path().string().substr(scopeLen+1));
|
||||||
|
j.EndObject();
|
||||||
|
}
|
||||||
|
j.EndArray();
|
||||||
j.EndObject();
|
j.EndObject();
|
||||||
client->sendMessage(j.str());
|
client->sendMessage(j.str());
|
||||||
} else if(client->scope.type == MonitorScope::JOB) {
|
} else if(client->scope.type == MonitorScope::JOB) {
|
||||||
@ -556,3 +574,26 @@ void Laminar::runFinished(const Run * r) {
|
|||||||
// will delete the job
|
// will delete the job
|
||||||
activeJobs.get<2>().erase(r);
|
activeJobs.get<2>().erase(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Laminar::getArtefact(std::string path, std::string& result) {
|
||||||
|
if(archiveUrl != ARCHIVE_URL_DEFAULT) {
|
||||||
|
// we shouldn't have got here. Probably an invalid link.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Reads in the whole file into the given string reference.
|
||||||
|
// This is a terrible way to serve files (especially large ones).
|
||||||
|
fs::path file(fs::path(homeDir)/"archive"/path);
|
||||||
|
// no support for browsing archived directories
|
||||||
|
if(fs::is_directory(file))
|
||||||
|
return false;
|
||||||
|
std::ifstream fstr(file.string());
|
||||||
|
fstr.seekg(0, std::ios::end);
|
||||||
|
size_t sz = fstr.tellg();
|
||||||
|
if(fstr.rdstate() == 0) {
|
||||||
|
result.resize(sz);
|
||||||
|
fstr.seekg(0);
|
||||||
|
fstr.read(&result[0], sz);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -53,6 +53,7 @@ public:
|
|||||||
void deregisterClient(LaminarClient* client) override;
|
void deregisterClient(LaminarClient* client) override;
|
||||||
void sendStatus(LaminarClient* client) override;
|
void sendStatus(LaminarClient* client) override;
|
||||||
bool setParam(std::string job, int buildNum, std::string param, std::string value) override;
|
bool setParam(std::string job, int buildNum, std::string param, std::string value) override;
|
||||||
|
bool getArtefact(std::string path, std::string& result) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool loadConfiguration();
|
bool loadConfiguration();
|
||||||
@ -85,6 +86,7 @@ private:
|
|||||||
std::string homeDir;
|
std::string homeDir;
|
||||||
std::set<LaminarClient*> clients;
|
std::set<LaminarClient*> clients;
|
||||||
bool eraseWorkdir;
|
bool eraseWorkdir;
|
||||||
|
std::string archiveUrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _LAMINAR_LAMINAR_H_
|
#endif // _LAMINAR_LAMINAR_H_
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
<dt></dt><dd> </dd>
|
<dt></dt><dd> </dd>
|
||||||
<dt>Reason</dt><dd>{{job.reason}}</dd>
|
<dt>Reason</dt><dd>{{job.reason}}</dd>
|
||||||
<dt>Started</dt><dd>{{job.when}}</dd>
|
<dt>Started</dt><dd>{{job.when}}</dd>
|
||||||
|
<dt>Artifacts</dt><dd><ul><li ng-repeat="art in job.artifacts"><a href="{{art.url}}" target="_self">{{art.filename}}</a></li></ul></dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -168,7 +168,17 @@ public:
|
|||||||
wss.set_http_handler([this](websocketpp::connection_hdl hdl){
|
wss.set_http_handler([this](websocketpp::connection_hdl hdl){
|
||||||
websocket::connection_ptr c = wss.get_con_from_hdl(hdl);
|
websocket::connection_ptr c = wss.get_con_from_hdl(hdl);
|
||||||
const char* start, *end;
|
const char* start, *end;
|
||||||
if(resources.handleRequest(c->get_resource(), &start, &end)) {
|
std::string resource = c->get_resource();
|
||||||
|
if(resource.compare(0, strlen("/archive/"), "/archive/") == 0) {
|
||||||
|
std::string file(resource.substr(strlen("/archive/")));
|
||||||
|
std::string content;
|
||||||
|
if(laminar.getArtefact(file, content)) {
|
||||||
|
c->set_status(websocketpp::http::status_code::ok);
|
||||||
|
c->set_body(content);
|
||||||
|
} else {
|
||||||
|
c->set_status(websocketpp::http::status_code::not_found);
|
||||||
|
}
|
||||||
|
} else if(resources.handleRequest(resource, &start, &end)) {
|
||||||
c->set_status(websocketpp::http::status_code::ok);
|
c->set_status(websocketpp::http::status_code::ok);
|
||||||
c->append_header("Content-Encoding", "gzip");
|
c->append_header("Content-Encoding", "gzip");
|
||||||
c->set_body(std::string(start, end));
|
c->set_body(std::string(start, end));
|
||||||
|
Loading…
Reference in New Issue
Block a user