forked from lobo/lambda-zig
tell sdk that the profile is a command line flag/change precedence
This commit is contained in:
parent
446b726cf9
commit
b3f5cb8203
5 changed files with 74 additions and 92 deletions
|
|
@ -4,8 +4,8 @@
|
||||||
.fingerprint = 0x6e61de08e7e51114,
|
.fingerprint = 0x6e61de08e7e51114,
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.aws = .{
|
.aws = .{
|
||||||
.url = "git+https://git.lerch.org/lobo/aws-sdk-for-zig#686b18d1f4329e80cf6d9b916eaa0c231333edb9",
|
.url = "git+https://git.lerch.org/lobo/aws-sdk-for-zig#4df27142d0efa560bd13f14cef8298ee9bceafc8",
|
||||||
.hash = "aws-0.0.1-SbsFcAc3CgCdWfayHWFazNfJBxkzLyU2wOJSj7h4W17-",
|
.hash = "aws-0.0.1-SbsFcP05CgDKqHcuxwvc-FZ5ITDVGqeGL9uUU7eE38nb",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
|
|
|
||||||
|
|
@ -231,19 +231,8 @@ fn deployFunction(deploy_opts: DeployOptions, options: RunOptions) !void {
|
||||||
const base64_data = try std.fmt.allocPrint(options.allocator, "{b64}", .{zip_data});
|
const base64_data = try std.fmt.allocPrint(options.allocator, "{b64}", .{zip_data});
|
||||||
defer options.allocator.free(base64_data);
|
defer options.allocator.free(base64_data);
|
||||||
|
|
||||||
var client = aws.Client.init(options.allocator, .{});
|
|
||||||
defer client.deinit();
|
|
||||||
|
|
||||||
const services = aws.Services(.{.lambda}){};
|
const services = aws.Services(.{.lambda}){};
|
||||||
|
|
||||||
const region = options.region orelse "us-east-1";
|
|
||||||
|
|
||||||
const aws_options = aws.Options{
|
|
||||||
.client = client,
|
|
||||||
.region = region,
|
|
||||||
.credential_options = .{ .profile = .{ .profile_name = options.profile } },
|
|
||||||
};
|
|
||||||
|
|
||||||
// Convert arch string to Lambda format
|
// Convert arch string to Lambda format
|
||||||
const lambda_arch: []const u8 = if (std.mem.eql(u8, arch_str, "aarch64") or std.mem.eql(u8, arch_str, "arm64"))
|
const lambda_arch: []const u8 = if (std.mem.eql(u8, arch_str, "aarch64") or std.mem.eql(u8, arch_str, "arm64"))
|
||||||
"arm64"
|
"arm64"
|
||||||
|
|
@ -273,12 +262,9 @@ fn deployFunction(deploy_opts: DeployOptions, options: RunOptions) !void {
|
||||||
.allocator = options.allocator,
|
.allocator = options.allocator,
|
||||||
};
|
};
|
||||||
|
|
||||||
const create_options = aws.Options{
|
// Use the shared aws_options but add diagnostics for create call
|
||||||
.client = client,
|
var create_options = options.aws_options;
|
||||||
.region = region,
|
create_options.diagnostics = &create_diagnostics;
|
||||||
.diagnostics = &create_diagnostics,
|
|
||||||
.credential_options = .{ .profile = .{ .profile_name = options.profile } },
|
|
||||||
};
|
|
||||||
|
|
||||||
const create_result = aws.Request(services.lambda.create_function).call(.{
|
const create_result = aws.Request(services.lambda.create_function).call(.{
|
||||||
.function_name = deploy_opts.function_name,
|
.function_name = deploy_opts.function_name,
|
||||||
|
|
@ -301,7 +287,7 @@ fn deployFunction(deploy_opts: DeployOptions, options: RunOptions) !void {
|
||||||
.function_name = deploy_opts.function_name,
|
.function_name = deploy_opts.function_name,
|
||||||
.architectures = architectures,
|
.architectures = architectures,
|
||||||
.zip_file = base64_data,
|
.zip_file = base64_data,
|
||||||
}, aws_options);
|
}, options.aws_options);
|
||||||
defer update_result.deinit();
|
defer update_result.deinit();
|
||||||
|
|
||||||
try options.stdout.print("Updated function: {s}\n", .{deploy_opts.function_name});
|
try options.stdout.print("Updated function: {s}\n", .{deploy_opts.function_name});
|
||||||
|
|
@ -311,11 +297,11 @@ fn deployFunction(deploy_opts: DeployOptions, options: RunOptions) !void {
|
||||||
try options.stdout.flush();
|
try options.stdout.flush();
|
||||||
|
|
||||||
// Wait for function to be ready before updating configuration
|
// Wait for function to be ready before updating configuration
|
||||||
try waitForFunctionReady(deploy_opts.function_name, aws_options);
|
try waitForFunctionReady(deploy_opts.function_name, options);
|
||||||
|
|
||||||
// Update environment variables if provided
|
// Update environment variables if provided
|
||||||
if (env_variables) |vars| {
|
if (env_variables) |vars| {
|
||||||
try updateFunctionConfiguration(deploy_opts.function_name, vars, aws_options, options);
|
try updateFunctionConfiguration(deploy_opts.function_name, vars, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
@ -333,7 +319,7 @@ fn deployFunction(deploy_opts: DeployOptions, options: RunOptions) !void {
|
||||||
try options.stdout.flush();
|
try options.stdout.flush();
|
||||||
|
|
||||||
// Wait for function to be ready before returning
|
// Wait for function to be ready before returning
|
||||||
try waitForFunctionReady(deploy_opts.function_name, aws_options);
|
try waitForFunctionReady(deploy_opts.function_name, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build environment variables in the format expected by AWS Lambda API
|
/// Build environment variables in the format expected by AWS Lambda API
|
||||||
|
|
@ -364,7 +350,6 @@ fn buildEnvVariables(
|
||||||
fn updateFunctionConfiguration(
|
fn updateFunctionConfiguration(
|
||||||
function_name: []const u8,
|
function_name: []const u8,
|
||||||
env_variables: []EnvVar,
|
env_variables: []EnvVar,
|
||||||
aws_options: aws.Options,
|
|
||||||
options: RunOptions,
|
options: RunOptions,
|
||||||
) !void {
|
) !void {
|
||||||
const services = aws.Services(.{.lambda}){};
|
const services = aws.Services(.{.lambda}){};
|
||||||
|
|
@ -374,24 +359,24 @@ fn updateFunctionConfiguration(
|
||||||
const update_config_result = try aws.Request(services.lambda.update_function_configuration).call(.{
|
const update_config_result = try aws.Request(services.lambda.update_function_configuration).call(.{
|
||||||
.function_name = function_name,
|
.function_name = function_name,
|
||||||
.environment = .{ .variables = env_variables },
|
.environment = .{ .variables = env_variables },
|
||||||
}, aws_options);
|
}, options.aws_options);
|
||||||
defer update_config_result.deinit();
|
defer update_config_result.deinit();
|
||||||
|
|
||||||
try options.stdout.print("Updated environment variables\n", .{});
|
try options.stdout.print("Updated environment variables\n", .{});
|
||||||
try options.stdout.flush();
|
try options.stdout.flush();
|
||||||
|
|
||||||
// Wait for configuration update to complete
|
// Wait for configuration update to complete
|
||||||
try waitForFunctionReady(function_name, aws_options);
|
try waitForFunctionReady(function_name, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn waitForFunctionReady(function_name: []const u8, aws_options: aws.Options) !void {
|
fn waitForFunctionReady(function_name: []const u8, options: RunOptions) !void {
|
||||||
const services = aws.Services(.{.lambda}){};
|
const services = aws.Services(.{.lambda}){};
|
||||||
|
|
||||||
var retries: usize = 30; // Up to ~6 seconds total
|
var retries: usize = 30; // Up to ~6 seconds total
|
||||||
while (retries > 0) : (retries -= 1) {
|
while (retries > 0) : (retries -= 1) {
|
||||||
const result = aws.Request(services.lambda.get_function).call(.{
|
const result = aws.Request(services.lambda.get_function).call(.{
|
||||||
.function_name = function_name,
|
.function_name = function_name,
|
||||||
}, aws_options) catch |err| {
|
}, options.aws_options) catch |err| {
|
||||||
// Function should exist at this point, but retry on transient errors
|
// Function should exist at this point, but retry on transient errors
|
||||||
std.log.warn("GetFunction failed during wait: {}", .{err});
|
std.log.warn("GetFunction failed during wait: {}", .{err});
|
||||||
std.Thread.sleep(200 * std.time.ns_per_ms);
|
std.Thread.sleep(200 * std.time.ns_per_ms);
|
||||||
|
|
|
||||||
|
|
@ -58,10 +58,6 @@ fn printHelp(writer: *std.Io.Writer) void {
|
||||||
/// Get or create an IAM role for Lambda execution
|
/// Get or create an IAM role for Lambda execution
|
||||||
/// Returns the role ARN
|
/// Returns the role ARN
|
||||||
pub fn getOrCreateRole(role_name: []const u8, options: RunOptions) ![]const u8 {
|
pub fn getOrCreateRole(role_name: []const u8, options: RunOptions) ![]const u8 {
|
||||||
var client = aws.Client.init(options.allocator, .{});
|
|
||||||
defer client.deinit();
|
|
||||||
|
|
||||||
// Try to get existing role
|
|
||||||
const services = aws.Services(.{.iam}){};
|
const services = aws.Services(.{.iam}){};
|
||||||
|
|
||||||
var diagnostics = aws.Diagnostics{
|
var diagnostics = aws.Diagnostics{
|
||||||
|
|
@ -70,11 +66,9 @@ pub fn getOrCreateRole(role_name: []const u8, options: RunOptions) ![]const u8 {
|
||||||
.allocator = options.allocator,
|
.allocator = options.allocator,
|
||||||
};
|
};
|
||||||
|
|
||||||
const aws_options = aws.Options{
|
// Use the shared aws_options but add diagnostics for this call
|
||||||
.client = client,
|
var aws_options = options.aws_options;
|
||||||
.diagnostics = &diagnostics,
|
aws_options.diagnostics = &diagnostics;
|
||||||
.credential_options = .{ .profile = .{ .profile_name = options.profile } },
|
|
||||||
};
|
|
||||||
|
|
||||||
const get_result = aws.Request(services.iam.get_role).call(.{
|
const get_result = aws.Request(services.iam.get_role).call(.{
|
||||||
.role_name = role_name,
|
.role_name = role_name,
|
||||||
|
|
@ -82,7 +76,7 @@ pub fn getOrCreateRole(role_name: []const u8, options: RunOptions) ![]const u8 {
|
||||||
defer diagnostics.deinit();
|
defer diagnostics.deinit();
|
||||||
if (diagnostics.http_code == 404) {
|
if (diagnostics.http_code == 404) {
|
||||||
// Role doesn't exist, create it
|
// Role doesn't exist, create it
|
||||||
return try createRole(options.allocator, role_name, client, options.profile);
|
return try createRole(role_name, options);
|
||||||
}
|
}
|
||||||
std.log.err("IAM GetRole failed: {} (HTTP {})", .{ err, diagnostics.http_code });
|
std.log.err("IAM GetRole failed: {} (HTTP {})", .{ err, diagnostics.http_code });
|
||||||
return error.IamGetRoleFailed;
|
return error.IamGetRoleFailed;
|
||||||
|
|
@ -93,14 +87,9 @@ pub fn getOrCreateRole(role_name: []const u8, options: RunOptions) ![]const u8 {
|
||||||
return try options.allocator.dupe(u8, get_result.response.role.arn);
|
return try options.allocator.dupe(u8, get_result.response.role.arn);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn createRole(allocator: std.mem.Allocator, role_name: []const u8, client: aws.Client, profile: ?[]const u8) ![]const u8 {
|
fn createRole(role_name: []const u8, options: RunOptions) ![]const u8 {
|
||||||
const services = aws.Services(.{.iam}){};
|
const services = aws.Services(.{.iam}){};
|
||||||
|
|
||||||
const aws_options = aws.Options{
|
|
||||||
.client = client,
|
|
||||||
.credential_options = .{ .profile = .{ .profile_name = profile } },
|
|
||||||
};
|
|
||||||
|
|
||||||
const assume_role_policy =
|
const assume_role_policy =
|
||||||
\\{
|
\\{
|
||||||
\\ "Version": "2012-10-17",
|
\\ "Version": "2012-10-17",
|
||||||
|
|
@ -122,10 +111,10 @@ fn createRole(allocator: std.mem.Allocator, role_name: []const u8, client: aws.C
|
||||||
const create_result = try aws.Request(services.iam.create_role).call(.{
|
const create_result = try aws.Request(services.iam.create_role).call(.{
|
||||||
.role_name = role_name,
|
.role_name = role_name,
|
||||||
.assume_role_policy_document = assume_role_policy,
|
.assume_role_policy_document = assume_role_policy,
|
||||||
}, aws_options);
|
}, options.aws_options);
|
||||||
defer create_result.deinit();
|
defer create_result.deinit();
|
||||||
|
|
||||||
const arn = try allocator.dupe(u8, create_result.response.role.arn);
|
const arn = try options.allocator.dupe(u8, create_result.response.role.arn);
|
||||||
|
|
||||||
// Attach the Lambda execution policy
|
// Attach the Lambda execution policy
|
||||||
std.log.info("Attaching AWSLambdaExecute policy", .{});
|
std.log.info("Attaching AWSLambdaExecute policy", .{});
|
||||||
|
|
@ -133,7 +122,7 @@ fn createRole(allocator: std.mem.Allocator, role_name: []const u8, client: aws.C
|
||||||
const attach_result = try aws.Request(services.iam.attach_role_policy).call(.{
|
const attach_result = try aws.Request(services.iam.attach_role_policy).call(.{
|
||||||
.policy_arn = "arn:aws:iam::aws:policy/AWSLambdaExecute",
|
.policy_arn = "arn:aws:iam::aws:policy/AWSLambdaExecute",
|
||||||
.role_name = role_name,
|
.role_name = role_name,
|
||||||
}, aws_options);
|
}, options.aws_options);
|
||||||
defer attach_result.deinit();
|
defer attach_result.deinit();
|
||||||
|
|
||||||
// IAM role creation can take a moment to propagate
|
// IAM role creation can take a moment to propagate
|
||||||
|
|
|
||||||
|
|
@ -57,19 +57,7 @@ fn printHelp(writer: *std.Io.Writer) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invokeFunction(function_name: []const u8, payload: []const u8, options: RunOptions) !void {
|
fn invokeFunction(function_name: []const u8, payload: []const u8, options: RunOptions) !void {
|
||||||
// Note: Profile is expected to be set via AWS_PROFILE env var before invoking this tool
|
|
||||||
// (e.g., via aws-vault exec)
|
|
||||||
|
|
||||||
var client = aws.Client.init(options.allocator, .{});
|
|
||||||
defer client.deinit();
|
|
||||||
|
|
||||||
const services = aws.Services(.{.lambda}){};
|
const services = aws.Services(.{.lambda}){};
|
||||||
const region = options.region orelse "us-east-1";
|
|
||||||
|
|
||||||
const aws_options = aws.Options{
|
|
||||||
.client = client,
|
|
||||||
.region = region,
|
|
||||||
};
|
|
||||||
|
|
||||||
std.log.info("Invoking function: {s}", .{function_name});
|
std.log.info("Invoking function: {s}", .{function_name});
|
||||||
|
|
||||||
|
|
@ -78,7 +66,7 @@ fn invokeFunction(function_name: []const u8, payload: []const u8, options: RunOp
|
||||||
.payload = payload,
|
.payload = payload,
|
||||||
.log_type = "Tail",
|
.log_type = "Tail",
|
||||||
.invocation_type = "RequestResponse",
|
.invocation_type = "RequestResponse",
|
||||||
}, aws_options);
|
}, options.aws_options);
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
|
|
||||||
// Print response payload
|
// Print response payload
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
//! invoke Invoke the deployed function
|
//! invoke Invoke the deployed function
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const aws = @import("aws");
|
||||||
const package = @import("package.zig");
|
const package = @import("package.zig");
|
||||||
const iam_cmd = @import("iam.zig");
|
const iam_cmd = @import("iam.zig");
|
||||||
const deploy_cmd = @import("deploy.zig");
|
const deploy_cmd = @import("deploy.zig");
|
||||||
|
|
@ -21,8 +22,8 @@ pub const RunOptions = struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
stdout: *std.Io.Writer,
|
stdout: *std.Io.Writer,
|
||||||
stderr: *std.Io.Writer,
|
stderr: *std.Io.Writer,
|
||||||
region: ?[]const u8 = null,
|
region: []const u8,
|
||||||
profile: ?[]const u8 = null,
|
aws_options: aws.Options,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() !u8 {
|
pub fn main() !u8 {
|
||||||
|
|
@ -35,46 +36,42 @@ pub fn main() !u8 {
|
||||||
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
|
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
|
||||||
var stderr_writer = std.fs.File.stderr().writer(&stderr_buffer);
|
var stderr_writer = std.fs.File.stderr().writer(&stderr_buffer);
|
||||||
|
|
||||||
var options = RunOptions{
|
run(allocator, &stdout_writer.interface, &stderr_writer.interface) catch |err| {
|
||||||
.allocator = allocator,
|
stderr_writer.interface.print("Error: {}\n", .{err}) catch {};
|
||||||
.stdout = &stdout_writer.interface,
|
stderr_writer.interface.flush() catch {};
|
||||||
.stderr = &stderr_writer.interface,
|
|
||||||
};
|
|
||||||
|
|
||||||
run(&options) catch |err| {
|
|
||||||
options.stderr.print("Error: {}\n", .{err}) catch {};
|
|
||||||
options.stderr.flush() catch {};
|
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
try options.stderr.flush();
|
try stderr_writer.interface.flush();
|
||||||
try options.stdout.flush();
|
try stdout_writer.interface.flush();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(options: *RunOptions) !void {
|
fn run(allocator: std.mem.Allocator, stdout: *std.Io.Writer, stderr: *std.Io.Writer) !void {
|
||||||
const args = try std.process.argsAlloc(options.allocator);
|
const args = try std.process.argsAlloc(allocator);
|
||||||
defer std.process.argsFree(options.allocator, args);
|
defer std.process.argsFree(allocator, args);
|
||||||
|
|
||||||
if (args.len < 2) {
|
if (args.len < 2) {
|
||||||
printUsage(options.stderr);
|
printUsage(stderr);
|
||||||
try options.stderr.flush();
|
try stderr.flush();
|
||||||
return error.MissingCommand;
|
return error.MissingCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse global options and find command
|
// Parse global options and find command
|
||||||
var cmd_start: usize = 1;
|
var cmd_start: usize = 1;
|
||||||
|
var region: []const u8 = "us-east-1";
|
||||||
|
var profile: ?[]const u8 = null;
|
||||||
|
|
||||||
while (cmd_start < args.len) {
|
while (cmd_start < args.len) {
|
||||||
const arg = args[cmd_start];
|
const arg = args[cmd_start];
|
||||||
if (std.mem.eql(u8, arg, "--region")) {
|
if (std.mem.eql(u8, arg, "--region")) {
|
||||||
cmd_start += 1;
|
cmd_start += 1;
|
||||||
if (cmd_start >= args.len) return error.MissingRegionValue;
|
if (cmd_start >= args.len) return error.MissingRegionValue;
|
||||||
options.region = args[cmd_start];
|
region = args[cmd_start];
|
||||||
cmd_start += 1;
|
cmd_start += 1;
|
||||||
} else if (std.mem.eql(u8, arg, "--profile")) {
|
} else if (std.mem.eql(u8, arg, "--profile")) {
|
||||||
cmd_start += 1;
|
cmd_start += 1;
|
||||||
if (cmd_start >= args.len) return error.MissingProfileValue;
|
if (cmd_start >= args.len) return error.MissingProfileValue;
|
||||||
options.profile = args[cmd_start];
|
profile = args[cmd_start];
|
||||||
cmd_start += 1;
|
cmd_start += 1;
|
||||||
} else if (std.mem.startsWith(u8, arg, "--")) {
|
} else if (std.mem.startsWith(u8, arg, "--")) {
|
||||||
// Unknown global option - might be command-specific, let command handle it
|
// Unknown global option - might be command-specific, let command handle it
|
||||||
|
|
@ -86,29 +83,52 @@ fn run(options: *RunOptions) !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd_start >= args.len) {
|
if (cmd_start >= args.len) {
|
||||||
printUsage(options.stderr);
|
printUsage(stderr);
|
||||||
try options.stderr.flush();
|
try stderr.flush();
|
||||||
return error.MissingCommand;
|
return error.MissingCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create AWS client and options once, used by all commands
|
||||||
|
var client = aws.Client.init(allocator, .{});
|
||||||
|
defer client.deinit();
|
||||||
|
|
||||||
|
const aws_options = aws.Options{
|
||||||
|
.client = client,
|
||||||
|
.region = region,
|
||||||
|
.credential_options = .{
|
||||||
|
.profile = .{
|
||||||
|
.profile_name = profile,
|
||||||
|
.prefer_profile_from_file = profile != null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = RunOptions{
|
||||||
|
.allocator = allocator,
|
||||||
|
.stdout = stdout,
|
||||||
|
.stderr = stderr,
|
||||||
|
.region = region,
|
||||||
|
.aws_options = aws_options,
|
||||||
|
};
|
||||||
|
|
||||||
const command = args[cmd_start];
|
const command = args[cmd_start];
|
||||||
const cmd_args = args[cmd_start + 1 ..];
|
const cmd_args = args[cmd_start + 1 ..];
|
||||||
|
|
||||||
if (std.mem.eql(u8, command, "package")) {
|
if (std.mem.eql(u8, command, "package")) {
|
||||||
try package.run(cmd_args, options.*);
|
try package.run(cmd_args, options);
|
||||||
} else if (std.mem.eql(u8, command, "iam")) {
|
} else if (std.mem.eql(u8, command, "iam")) {
|
||||||
try iam_cmd.run(cmd_args, options.*);
|
try iam_cmd.run(cmd_args, options);
|
||||||
} else if (std.mem.eql(u8, command, "deploy")) {
|
} else if (std.mem.eql(u8, command, "deploy")) {
|
||||||
try deploy_cmd.run(cmd_args, options.*);
|
try deploy_cmd.run(cmd_args, options);
|
||||||
} else if (std.mem.eql(u8, command, "invoke")) {
|
} else if (std.mem.eql(u8, command, "invoke")) {
|
||||||
try invoke_cmd.run(cmd_args, options.*);
|
try invoke_cmd.run(cmd_args, options);
|
||||||
} else if (std.mem.eql(u8, command, "--help") or std.mem.eql(u8, command, "-h")) {
|
} else if (std.mem.eql(u8, command, "--help") or std.mem.eql(u8, command, "-h")) {
|
||||||
printUsage(options.stdout);
|
printUsage(stdout);
|
||||||
try options.stdout.flush();
|
try stdout.flush();
|
||||||
} else {
|
} else {
|
||||||
options.stderr.print("Unknown command: {s}\n\n", .{command}) catch {};
|
stderr.print("Unknown command: {s}\n\n", .{command}) catch {};
|
||||||
printUsage(options.stderr);
|
printUsage(stderr);
|
||||||
try options.stderr.flush();
|
try stderr.flush();
|
||||||
return error.UnknownCommand;
|
return error.UnknownCommand;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +140,7 @@ fn printUsage(writer: *std.Io.Writer) void {
|
||||||
\\Lambda deployment CLI tool
|
\\Lambda deployment CLI tool
|
||||||
\\
|
\\
|
||||||
\\Global Options:
|
\\Global Options:
|
||||||
\\ --region <region> AWS region (default: from AWS config)
|
\\ --region <region> AWS region (default: us-east-1)
|
||||||
\\ --profile <profile> AWS profile to use
|
\\ --profile <profile> AWS profile to use
|
||||||
\\
|
\\
|
||||||
\\Commands:
|
\\Commands:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue