|
|
|
@ -24,32 +24,30 @@ const CodefirstContainer = struct {
|
|
|
|
|
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 };
|
|
|
|
|
defer headers.deinit();
|
|
|
|
|
try headers.append(ForwardedUser, auth.user);
|
|
|
|
|
if (body.len > 0) {
|
|
|
|
|
try headers.append("Content-Type", "application/json");
|
|
|
|
|
fn sendRequest(method: std.http.Method, auth: CodefirstAuth, path: []const u8, body: ?[]const u8) !std.http.Status {
|
|
|
|
|
var response_body = std.ArrayList(u8).init(allocator);
|
|
|
|
|
const headers = [_]std.http.Header{.{ .name = ForwardedUser, .value = auth.user }};
|
|
|
|
|
const res = try client.fetch(.{
|
|
|
|
|
.method = method,
|
|
|
|
|
.location = .{ .url = path },
|
|
|
|
|
.headers = .{ .content_type = if (body != null) .{ .override = "application/json" } else .default },
|
|
|
|
|
.extra_headers = &headers,
|
|
|
|
|
.payload = body,
|
|
|
|
|
.response_storage = .{ .dynamic = &response_body },
|
|
|
|
|
});
|
|
|
|
|
if (res.status.class() == .success) {
|
|
|
|
|
std.log.info("{s}", .{response_body.items});
|
|
|
|
|
} else {
|
|
|
|
|
std.log.err("[HTTP {d}] {s}", .{ res.status, response_body.items });
|
|
|
|
|
}
|
|
|
|
|
var req = try client.request(method, uri, headers, .{});
|
|
|
|
|
defer req.deinit();
|
|
|
|
|
req.transfer_encoding = std.http.Client.RequestTransfer{ .content_length = body.len };
|
|
|
|
|
try req.start();
|
|
|
|
|
try req.writeAll(body);
|
|
|
|
|
try req.finish();
|
|
|
|
|
try req.wait();
|
|
|
|
|
const responseBody = req.reader().readAllAlloc(allocator, 8192) catch unreachable;
|
|
|
|
|
defer allocator.free(responseBody);
|
|
|
|
|
std.log.info("{s}", .{responseBody});
|
|
|
|
|
return req.response.status;
|
|
|
|
|
return res.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);
|
|
|
|
|
var status = try sendRequest(.GET, auth, path, "");
|
|
|
|
|
const status = try sendRequest(.GET, auth, path, null);
|
|
|
|
|
return status == .ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -57,7 +55,7 @@ fn exists(auth: CodefirstAuth, containerName: []const u8) !bool {
|
|
|
|
|
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, "");
|
|
|
|
|
_ = try sendRequest(.POST, auth, path, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Creates a container with the given name.
|
|
|
|
@ -99,21 +97,22 @@ fn start(auth: CodefirstAuth, imageName: []const u8, containerName: []const u8,
|
|
|
|
|
fn delete(auth: CodefirstAuth, containerName: []const u8) !void {
|
|
|
|
|
const path = try std.fmt.allocPrint(allocator, "{s}://{s}/containers/{s}", .{ auth.proxyScheme, auth.proxyHost, containerName });
|
|
|
|
|
defer allocator.free(path);
|
|
|
|
|
_ = try sendRequest(.DELETE, auth, path, "");
|
|
|
|
|
_ = try sendRequest(.DELETE, auth, path, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn run() !void {
|
|
|
|
|
const command_name = std.os.getenv("PLUGIN_COMMAND") orelse return PluginError.InvalidCommand;
|
|
|
|
|
const env_map = std.process.getEnvMap(allocator) catch unreachable;
|
|
|
|
|
const command_name = env_map.get("PLUGIN_COMMAND") orelse return PluginError.InvalidCommand;
|
|
|
|
|
const command = std.meta.stringToEnum(Command, command_name) orelse return PluginError.InvalidCommand;
|
|
|
|
|
const auth = CodefirstAuth{
|
|
|
|
|
.proxyScheme = std.os.getenv("PROXYSCHEME") orelse "http",
|
|
|
|
|
.proxyHost = std.os.getenv("PROXYHOST") orelse "dockerproxy:8080",
|
|
|
|
|
.user = std.os.getenv("DRONE_REPO_OWNER") orelse return PluginError.InvalidUser,
|
|
|
|
|
.proxyScheme = env_map.get("PROXYSCHEME") orelse "http",
|
|
|
|
|
.proxyHost = env_map.get("PROXYHOST") orelse "dockerproxy:8080",
|
|
|
|
|
.user = env_map.get("DRONE_REPO_OWNER") orelse return PluginError.InvalidUser,
|
|
|
|
|
};
|
|
|
|
|
var containerNameEnv = std.os.getenv("PLUGIN_CONTAINER") orelse return PluginError.NoContainerName;
|
|
|
|
|
var shortUser = try std.mem.replaceOwned(u8, allocator, auth.user, ".", "");
|
|
|
|
|
const containerNameEnv = env_map.get("PLUGIN_CONTAINER") orelse return PluginError.NoContainerName;
|
|
|
|
|
const shortUser = try std.mem.replaceOwned(u8, allocator, auth.user, ".", "");
|
|
|
|
|
defer allocator.free(shortUser);
|
|
|
|
|
var containerName = try std.fmt.allocPrint(allocator, "{s}-{s}", .{ shortUser, containerNameEnv });
|
|
|
|
|
const containerName = try std.fmt.allocPrint(allocator, "{s}-{s}", .{ shortUser, containerNameEnv });
|
|
|
|
|
defer allocator.free(containerName);
|
|
|
|
|
|
|
|
|
|
var idx: usize = 0;
|
|
|
|
@ -140,10 +139,10 @@ pub fn run() !void {
|
|
|
|
|
|
|
|
|
|
switch (command) {
|
|
|
|
|
.create => {
|
|
|
|
|
const imageName = std.os.getenv("PLUGIN_IMAGE") orelse return PluginError.InvalidImage;
|
|
|
|
|
const private = std.mem.eql(u8, std.os.getenv("PLUGIN_PRIVATE") orelse "false", "true");
|
|
|
|
|
const overwrite = std.mem.eql(u8, std.os.getenv("PLUGIN_OVERWRITE") orelse "false", "true");
|
|
|
|
|
const admins = std.os.getenv("PLUGIN_ADMINS") orelse auth.user;
|
|
|
|
|
const imageName = env_map.get("PLUGIN_IMAGE") orelse return PluginError.InvalidImage;
|
|
|
|
|
const private = std.mem.eql(u8, env_map.get("PLUGIN_PRIVATE") orelse "false", "true");
|
|
|
|
|
const overwrite = std.mem.eql(u8, env_map.get("PLUGIN_OVERWRITE") orelse "false", "true");
|
|
|
|
|
const admins = env_map.get("PLUGIN_ADMINS") orelse auth.user;
|
|
|
|
|
|
|
|
|
|
const container = CodefirstContainer{
|
|
|
|
|
.Id = "",
|
|
|
|
@ -167,8 +166,8 @@ pub fn run() !void {
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
.start => {
|
|
|
|
|
const imageName = std.os.getenv("PLUGIN_IMAGE") orelse return PluginError.InvalidImage;
|
|
|
|
|
const private = std.mem.eql(u8, std.os.getenv("PLUGIN_PRIVATE") orelse "false", "true");
|
|
|
|
|
const imageName = env_map.get("PLUGIN_IMAGE") orelse return PluginError.InvalidImage;
|
|
|
|
|
const private = std.mem.eql(u8, env_map.get("PLUGIN_PRIVATE") orelse "false", "true");
|
|
|
|
|
try start(auth, imageName, containerName, envs.items, private);
|
|
|
|
|
},
|
|
|
|
|
.delete => {
|
|
|
|
@ -187,6 +186,6 @@ pub fn main() !void {
|
|
|
|
|
PluginError.InvalidImage => std.log.err("Invalid image", .{}),
|
|
|
|
|
else => std.log.err("{}", .{err}),
|
|
|
|
|
}
|
|
|
|
|
std.os.exit(1);
|
|
|
|
|
std.process.exit(1);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|