|
|
|
@ -5,7 +5,6 @@ var client: std.http.Client = .{ .allocator = allocator };
|
|
|
|
|
const Command = enum { list, logs, create, delete, start };
|
|
|
|
|
|
|
|
|
|
const ForwardedUser = "X-Forwarded-User";
|
|
|
|
|
|
|
|
|
|
const PluginError = error{ InvalidUser, InvalidCommand, NoContainerName, InvalidImage, Unprocessable };
|
|
|
|
|
|
|
|
|
|
const CodefirstAuth = struct {
|
|
|
|
@ -19,9 +18,12 @@ const CodefirstContainer = struct {
|
|
|
|
|
Image: []const u8,
|
|
|
|
|
Admins: []const u8,
|
|
|
|
|
Env: [][]const u8,
|
|
|
|
|
Private: bool,
|
|
|
|
|
Private: ?bool,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const jsonOptions = std.json.StringifyOptions{ .emit_null_optional_fields = false };
|
|
|
|
|
|
|
|
|
|
/// Sends a request to the CodeFirst proxy and print the response body.
|
|
|
|
|
fn sendRequest(method: std.http.Method, auth: CodefirstAuth, path: []const u8, body: []const u8) !std.http.Status {
|
|
|
|
|
const uri = std.Uri.parse(path) catch unreachable;
|
|
|
|
|
var headers = std.http.Headers{ .allocator = allocator };
|
|
|
|
@ -43,6 +45,7 @@ fn sendRequest(method: std.http.Method, auth: CodefirstAuth, path: []const u8, b
|
|
|
|
|
return req.response.status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Tests if a container with the given name exists.
|
|
|
|
|
fn exists(auth: CodefirstAuth, containerName: []const u8) !bool {
|
|
|
|
|
const path = try std.fmt.allocPrint(allocator, "{s}://{s}/containers/{s}/json", .{ auth.proxyScheme, auth.proxyHost, containerName });
|
|
|
|
|
defer allocator.free(path);
|
|
|
|
@ -50,39 +53,46 @@ fn exists(auth: CodefirstAuth, containerName: []const u8) !bool {
|
|
|
|
|
return status == .ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Pulls the given image.
|
|
|
|
|
fn createImage(auth: CodefirstAuth, imageName: []const u8) !void {
|
|
|
|
|
const path = try std.fmt.allocPrint(allocator, "{s}://{s}/images/create?fromImage={s}", .{ auth.proxyScheme, auth.proxyHost, imageName });
|
|
|
|
|
defer allocator.free(path);
|
|
|
|
|
_ = try sendRequest(.POST, auth, path, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates a container with the given name.
|
|
|
|
|
fn create(auth: CodefirstAuth, container: CodefirstContainer, containerName: []const u8) !void {
|
|
|
|
|
const path = try std.fmt.allocPrint(allocator, "{s}://{s}/containers/create/{s}", .{ auth.proxyScheme, auth.proxyHost, containerName });
|
|
|
|
|
defer allocator.free(path);
|
|
|
|
|
var json = std.ArrayList(u8).init(allocator);
|
|
|
|
|
defer json.deinit();
|
|
|
|
|
try std.json.stringify(container, .{}, json.writer());
|
|
|
|
|
try std.json.stringify(container, jsonOptions, json.writer());
|
|
|
|
|
_ = try sendRequest(.POST, auth, path, json.items);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Starts a container with the given options.
|
|
|
|
|
fn start(auth: CodefirstAuth, imageName: []const u8, containerName: []const u8, env: [][]const u8, private: bool) !void {
|
|
|
|
|
const ContainerStart = struct {
|
|
|
|
|
Id: []const u8,
|
|
|
|
|
Image: []const u8,
|
|
|
|
|
Env: [][]const u8,
|
|
|
|
|
Private: bool,
|
|
|
|
|
Private: ?bool,
|
|
|
|
|
};
|
|
|
|
|
const command = ContainerStart{
|
|
|
|
|
.Id = "",
|
|
|
|
|
.Image = imageName,
|
|
|
|
|
.Env = env,
|
|
|
|
|
.Private = private,
|
|
|
|
|
// Workaround for the proxy treating 'false' as a private container.
|
|
|
|
|
.Private = switch (private) {
|
|
|
|
|
true => true,
|
|
|
|
|
false => null,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
const path = try std.fmt.allocPrint(allocator, "{s}://{s}/containers/{s}/start", .{ auth.proxyScheme, auth.proxyHost, containerName });
|
|
|
|
|
defer allocator.free(path);
|
|
|
|
|
var json = std.ArrayList(u8).init(allocator);
|
|
|
|
|
defer json.deinit();
|
|
|
|
|
try std.json.stringify(command, .{}, json.writer());
|
|
|
|
|
try std.json.stringify(command, jsonOptions, json.writer());
|
|
|
|
|
_ = try sendRequest(.POST, auth, path, json.items);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -140,7 +150,11 @@ pub fn run() !void {
|
|
|
|
|
.Image = imageName,
|
|
|
|
|
.Admins = admins,
|
|
|
|
|
.Env = envs.items,
|
|
|
|
|
.Private = private,
|
|
|
|
|
// Workaround for the proxy treating 'false' as a private container.
|
|
|
|
|
.Private = switch (private) {
|
|
|
|
|
true => true,
|
|
|
|
|
false => null,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (overwrite) {
|
|
|
|
|