using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Amazon.Common.DotNetCli.Tools; using Amazon.Common.DotNetCli.Tools.Options; using Amazon.Lambda.Model; using ThirdParty.Json.LitJson; namespace Amazon.Lambda.Tools.Commands { /// /// Invoke a function running in Lambda /// public class InvokeFunctionCommand : LambdaBaseCommand { public const string COMMAND_NAME = "invoke-function"; public const string COMMAND_DESCRIPTION = "Command to invoke a function in Lambda with an optional input"; public const string COMMAND_ARGUMENTS = " The name of the function to invoke"; public static readonly IList InvokeCommandOptions = BuildLineOptions(new List { LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_NAME, LambdaDefinedCommandOptions.ARGUMENT_PAYLOAD }); public string FunctionName { get; set; } /// /// If the value for Payload points to an existing file then the contents of the file is sent, otherwise /// the value of Payload is sent as the input to the function. /// public string Payload { get; set; } public InvokeFunctionCommand(IToolLogger logger, string workingDirectory, string[] args) : base(logger, workingDirectory, InvokeCommandOptions, args) { } /// /// Parse the CommandOptions into the Properties on the command. /// /// protected override void ParseCommandArguments(CommandOptions values) { base.ParseCommandArguments(values); if(values.Arguments.Count > 0) { this.FunctionName = values.Arguments[0]; } Tuple tuple; if ((tuple = values.FindCommandOption(LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_NAME.Switch)) != null) this.FunctionName = tuple.Item2.StringValue; if ((tuple = values.FindCommandOption(LambdaDefinedCommandOptions.ARGUMENT_PAYLOAD.Switch)) != null) this.Payload = tuple.Item2.StringValue; } protected override async Task PerformActionAsync() { var invokeRequest = new InvokeRequest { FunctionName = this.GetStringValueOrDefault(this.FunctionName, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_NAME, true), LogType = LogType.Tail }; if (!string.IsNullOrWhiteSpace(this.Payload)) { if (File.Exists(this.Payload)) { Logger.WriteLine($"Reading {Path.GetFullPath(this.Payload)} as input to Lambda function"); invokeRequest.Payload = File.ReadAllText(this.Payload); } else { invokeRequest.Payload = this.Payload.Trim(); } if(!invokeRequest.Payload.StartsWith("{")) { invokeRequest.Payload = "\"" + invokeRequest.Payload + "\""; } } InvokeResponse response; try { await LambdaUtilities.WaitTillFunctionAvailableAsync(this.Logger, this.LambdaClient, invokeRequest.FunctionName); response = await this.LambdaClient.InvokeAsync(invokeRequest); } catch(Exception e) { throw new LambdaToolsException("Error invoking Lambda function: " + e.Message, LambdaToolsException.LambdaErrorCode.LambdaInvokeFunction, e); } this.Logger.WriteLine("Payload:"); PrintPayload(response); this.Logger.WriteLine(""); this.Logger.WriteLine("Log Tail:"); var log = System.Text.UTF8Encoding.UTF8.GetString(Convert.FromBase64String(response.LogResult)); this.Logger.WriteLine(log); return true; } private void PrintPayload(InvokeResponse response) { try { var payload = new StreamReader(response.Payload).ReadToEnd(); this.Logger.WriteLine(payload); } catch (Exception) { this.Logger.WriteLine(""); } } protected override void SaveConfigFile(JsonData data) { data.SetIfNotNull(LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_NAME.ConfigFileKey, this.GetStringValueOrDefault(this.FunctionName, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_NAME, false)); data.SetIfNotNull(LambdaDefinedCommandOptions.ARGUMENT_PAYLOAD.ConfigFileKey, this.GetStringValueOrDefault(this.Payload, LambdaDefinedCommandOptions.ARGUMENT_PAYLOAD, false)); } } }