forked from lobo/lambda-zig
implement package caching
This commit is contained in:
parent
8a70f19ae5
commit
12dd33db15
|
@ -102,12 +102,11 @@ pub fn configureBuild(b: *std.Build, exe: *std.Build.Step.Compile, function_name
|
||||||
// Deployment
|
// Deployment
|
||||||
const deploy = Deploy.create(b, .{
|
const deploy = Deploy.create(b, .{
|
||||||
.name = function_name,
|
.name = function_name,
|
||||||
.package = package_step.packagedFileLazyPath(),
|
|
||||||
.arch = exe.root_module.resolved_target.?.result.cpu.arch,
|
.arch = exe.root_module.resolved_target.?.result.cpu.arch,
|
||||||
.iam_step = iam,
|
.iam_step = iam,
|
||||||
|
.package_step = package_step,
|
||||||
.region = region,
|
.region = region,
|
||||||
});
|
});
|
||||||
deploy.step.dependOn(&package_step.step);
|
|
||||||
|
|
||||||
const deploy_step = b.step("awslambda_deploy", "Deploy the function");
|
const deploy_step = b.step("awslambda_deploy", "Deploy the function");
|
||||||
deploy_step.dependOn(&deploy.step);
|
deploy_step.dependOn(&deploy.step);
|
||||||
|
|
|
@ -13,15 +13,15 @@ pub const Options = struct {
|
||||||
/// Function name to be used for the function
|
/// Function name to be used for the function
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
|
|
||||||
/// LazyPath for the function package (zip file)
|
|
||||||
package: std.Build.LazyPath,
|
|
||||||
|
|
||||||
/// Architecture for Lambda function
|
/// Architecture for Lambda function
|
||||||
arch: std.Target.Cpu.Arch,
|
arch: std.Target.Cpu.Arch,
|
||||||
|
|
||||||
/// Iam step. This will be a dependency of the deployment
|
/// Iam step. This will be a dependency of the deployment
|
||||||
iam_step: *@import("Iam.zig"),
|
iam_step: *@import("Iam.zig"),
|
||||||
|
|
||||||
|
/// Packaging step. This will be a dependency of the deployment
|
||||||
|
package_step: *@import("Package.zig"),
|
||||||
|
|
||||||
/// Region for deployment
|
/// Region for deployment
|
||||||
region: *Region,
|
region: *Region,
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,7 @@ pub fn create(owner: *std.Build, options: Options) *Deploy {
|
||||||
const name = owner.dupe(options.name);
|
const name = owner.dupe(options.name);
|
||||||
const step_name = owner.fmt("{s} {s}{s}", .{
|
const step_name = owner.fmt("{s} {s}{s}", .{
|
||||||
"aws lambda",
|
"aws lambda",
|
||||||
"deploy",
|
"deploy ",
|
||||||
name,
|
name,
|
||||||
});
|
});
|
||||||
const self = owner.allocator.create(Deploy) catch @panic("OOM");
|
const self = owner.allocator.create(Deploy) catch @panic("OOM");
|
||||||
|
@ -45,6 +45,7 @@ pub fn create(owner: *std.Build, options: Options) *Deploy {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.step.dependOn(&options.iam_step.step);
|
self.step.dependOn(&options.iam_step.step);
|
||||||
|
self.step.dependOn(&options.package_step.step);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,13 +74,12 @@ fn make(step: *std.Build.Step, node: std.Progress.Node) anyerror!void {
|
||||||
if (self.options.arch != .aarch64 and self.options.arch != .x86_64)
|
if (self.options.arch != .aarch64 and self.options.arch != .x86_64)
|
||||||
return step.fail("AWS Lambda can only deploy aarch64 and x86_64 functions ({} not allowed)", .{self.options.arch});
|
return step.fail("AWS Lambda can only deploy aarch64 and x86_64 functions ({} not allowed)", .{self.options.arch});
|
||||||
|
|
||||||
// TODO: Work out cache. HOWEVER...this cannot be done until the caching
|
const last_packaged_sha256 = blk: {
|
||||||
// for the Deploy command works properly. Right now, it regenerates
|
// file should always be there, but we shouldn't break if the cache doesn't exist
|
||||||
// the zip file every time
|
const last_deployed_id_file = std.fs.openFileAbsolute(try self.options.package_step.shasumFilePath(), .{}) catch break :blk null;
|
||||||
// if (try getIamArnFromName(step, self.options.role_name)) |_| {
|
defer last_deployed_id_file.close();
|
||||||
// step.result_cached = true;
|
break :blk try last_deployed_id_file.readToEndAlloc(step.owner.allocator, 2048);
|
||||||
// return; // exists in cache - nothing to do
|
};
|
||||||
// }
|
|
||||||
|
|
||||||
var client = aws.Client.init(self.step.owner.allocator, .{});
|
var client = aws.Client.init(self.step.owner.allocator, .{});
|
||||||
defer client.deinit();
|
defer client.deinit();
|
||||||
|
@ -112,17 +112,22 @@ fn make(step: *std.Build.Step, node: std.Progress.Node) anyerror!void {
|
||||||
};
|
};
|
||||||
defer call.deinit();
|
defer call.deinit();
|
||||||
|
|
||||||
// TODO: Write call.response.configuration.last_modified to cache
|
|
||||||
|
|
||||||
// std.debug.print("Function found. Last modified: {s}, revision id: {s}\n", .{ call.response.configuration.?.last_modified.?, call.response.configuration.?.revision_id.? });
|
|
||||||
break :blk .{
|
break :blk .{
|
||||||
.last_modified = try step.owner.allocator.dupe(u8, call.response.configuration.?.last_modified.?),
|
.last_modified = try step.owner.allocator.dupe(u8, call.response.configuration.?.last_modified.?),
|
||||||
.revision_id = try step.owner.allocator.dupe(u8, call.response.configuration.?.revision_id.?),
|
.revision_id = try step.owner.allocator.dupe(u8, call.response.configuration.?.revision_id.?),
|
||||||
|
.sha256 = try step.owner.allocator.dupe(u8, call.response.configuration.?.code_sha256.?),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (last_packaged_sha256) |s|
|
||||||
|
if (function) |f|
|
||||||
|
if (std.mem.eql(u8, s, f.sha256)) {
|
||||||
|
step.result_cached = true;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
const encoder = std.base64.standard.Encoder;
|
const encoder = std.base64.standard.Encoder;
|
||||||
const file = try std.fs.openFileAbsolute(self.options.package.getPath2(step.owner, step), .{});
|
const file = try std.fs.openFileAbsolute(self.options.package_step.packagedFileLazyPath().getPath2(step.owner, step), .{});
|
||||||
defer file.close();
|
defer file.close();
|
||||||
const bytes = try file.readToEndAlloc(step.owner.allocator, 100 * 1024 * 1024);
|
const bytes = try file.readToEndAlloc(step.owner.allocator, 100 * 1024 * 1024);
|
||||||
const base64_buf = try step.owner.allocator.alloc(u8, encoder.calcSize(bytes.len));
|
const base64_buf = try step.owner.allocator.alloc(u8, encoder.calcSize(bytes.len));
|
||||||
|
@ -144,8 +149,6 @@ fn make(step: *std.Build.Step, node: std.Progress.Node) anyerror!void {
|
||||||
.zip_file = base64_bytes,
|
.zip_file = base64_bytes,
|
||||||
}, options);
|
}, options);
|
||||||
defer update_call.deinit();
|
defer update_call.deinit();
|
||||||
// TODO: Write call.response.last_modified to cache
|
|
||||||
// TODO: Write call.response.revision_id to cache?
|
|
||||||
} else {
|
} else {
|
||||||
// New function - we need to create from scratch
|
// New function - we need to create from scratch
|
||||||
const create_call = try aws.Request(services.lambda.create_function).call(.{
|
const create_call = try aws.Request(services.lambda.create_function).call(.{
|
||||||
|
|
|
@ -8,6 +8,8 @@ options: Options,
|
||||||
/// This is set as part of the make phase, and is the location in the cache
|
/// This is set as part of the make phase, and is the location in the cache
|
||||||
/// for the lambda package. The package will also be copied to the output
|
/// for the lambda package. The package will also be copied to the output
|
||||||
/// directory, but this location makes for a good cache key for deployments
|
/// directory, but this location makes for a good cache key for deployments
|
||||||
|
zipfile_cache_dest: ?[]const u8 = null,
|
||||||
|
|
||||||
zipfile_dest: ?[]const u8 = null,
|
zipfile_dest: ?[]const u8 = null,
|
||||||
|
|
||||||
const base_id: std.Build.Step.Id = .install_file;
|
const base_id: std.Build.Step.Id = .install_file;
|
||||||
|
@ -38,7 +40,13 @@ pub fn create(owner: *std.Build, options: Options) *Package {
|
||||||
|
|
||||||
return package;
|
return package;
|
||||||
}
|
}
|
||||||
|
pub fn shasumFilePath(self: Package) ![]const u8 {
|
||||||
|
return try std.fmt.allocPrint(
|
||||||
|
self.step.owner.allocator,
|
||||||
|
"{s}{s}{s}",
|
||||||
|
.{ std.fs.path.dirname(self.zipfile_cache_dest.?).?, std.fs.path.sep_str, "sha256sum.txt" },
|
||||||
|
);
|
||||||
|
}
|
||||||
pub fn packagedFilePath(self: Package) []const u8 {
|
pub fn packagedFilePath(self: Package) []const u8 {
|
||||||
return self.step.owner.getInstallPath(.prefix, self.options.zipfile_name);
|
return self.step.owner.getInstallPath(.prefix, self.options.zipfile_name);
|
||||||
}
|
}
|
||||||
|
@ -66,6 +74,7 @@ fn make(step: *std.Build.Step, node: std.Progress.Node) anyerror!void {
|
||||||
};
|
};
|
||||||
const bootstrap_dirname = std.fs.path.dirname(bootstrap).?;
|
const bootstrap_dirname = std.fs.path.dirname(bootstrap).?;
|
||||||
const zipfile_src = try std.fs.path.join(step.owner.allocator, &[_][]const u8{ bootstrap_dirname, self.options.zipfile_name });
|
const zipfile_src = try std.fs.path.join(step.owner.allocator, &[_][]const u8{ bootstrap_dirname, self.options.zipfile_name });
|
||||||
|
self.zipfile_cache_dest = zipfile_src;
|
||||||
self.zipfile_dest = self.step.owner.getInstallPath(.prefix, self.options.zipfile_name);
|
self.zipfile_dest = self.step.owner.getInstallPath(.prefix, self.options.zipfile_name);
|
||||||
if (std.fs.copyFileAbsolute(zipfile_src, self.zipfile_dest.?, .{})) |_| {
|
if (std.fs.copyFileAbsolute(zipfile_src, self.zipfile_dest.?, .{})) |_| {
|
||||||
// we're good here. The zip file exists in cache and has been copied
|
// we're good here. The zip file exists in cache and has been copied
|
||||||
|
@ -93,6 +102,21 @@ fn make(step: *std.Build.Step, node: std.Progress.Node) anyerror!void {
|
||||||
}
|
}
|
||||||
|
|
||||||
try std.fs.copyFileAbsolute(zipfile_src, self.zipfile_dest.?, .{}); // It better be there now
|
try std.fs.copyFileAbsolute(zipfile_src, self.zipfile_dest.?, .{}); // It better be there now
|
||||||
|
|
||||||
|
// One last thing. We want to get a Sha256 sum of the zip file, and
|
||||||
|
// store it in cache. This will help the deployment process compare
|
||||||
|
// to what's out in AWS, since revision id is apparently trash for these
|
||||||
|
// purposes
|
||||||
|
const zipfile = try std.fs.openFileAbsolute(zipfile_src, .{});
|
||||||
|
defer zipfile.close();
|
||||||
|
const zip_bytes = try zipfile.readToEndAlloc(step.owner.allocator, 100 * 1024 * 1024);
|
||||||
|
var hash: [std.crypto.hash.sha2.Sha256.digest_length]u8 = undefined;
|
||||||
|
std.crypto.hash.sha2.Sha256.hash(zip_bytes, &hash, .{});
|
||||||
|
const base64 = std.base64.standard.Encoder;
|
||||||
|
var encoded: [base64.calcSize(std.crypto.hash.sha2.Sha256.digest_length)]u8 = undefined;
|
||||||
|
const shaoutput = try std.fs.createFileAbsolute(try self.shasumFilePath(), .{});
|
||||||
|
defer shaoutput.close();
|
||||||
|
try shaoutput.writeAll(base64.encode(encoded[0..], hash[0..]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user