Skip to content

Commit

Permalink
Update language worker to support parsing command-line arguments pref…
Browse files Browse the repository at this point in the history
…ix with functions-<argumentname> (#993) (#996)

* Add support to parsing command-line arguments prefix with functions-<argumentname>

* Configure parser to ignore unknown arguments

* Remove deprecated option grpcMaxMessageLength
  • Loading branch information
Francisco-Gamino authored Sep 11, 2023
1 parent 5657019 commit fdc5360
Showing 1 changed file with 81 additions and 13 deletions.
94 changes: 81 additions & 13 deletions src/Worker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,53 @@ public async static Task Main(string[] args)
LogLevel.Information,
string.Format(PowerShellWorkerStrings.PowerShellWorkerVersion, typeof(Worker).Assembly.GetName().Version));

WorkerArguments arguments = null;
Parser.Default.ParseArguments<WorkerArguments>(args)
.WithParsed(ops => arguments = ops)
.WithNotParsed(err => Environment.Exit(1));
var workerOptions = new WorkerOptions();

var parser = new Parser(settings =>
{
settings.EnableDashDash = true;
settings.IgnoreUnknownArguments = true;
});
parser.ParseArguments<WorkerArguments>(args)
.WithParsed(workerArgs =>
{
// TODO: Remove parsing old command-line arguments that are not prefixed with functions-<argumentname>
// for more information, see https://github.com/Azure/azure-functions-powershell-worker/issues/995
workerOptions.WorkerId = workerArgs.FunctionsWorkerId ?? workerArgs.WorkerId;
workerOptions.RequestId = workerArgs.FunctionsRequestId ?? workerArgs.RequestId;

if (!string.IsNullOrWhiteSpace(workerArgs.FunctionsUri))
{
try
{
// TODO: Update WorkerOptions to have a URI property instead of host name and port number
// for more information, see https://github.com/Azure/azure-functions-powershell-worker/issues/994
var uri = new Uri(workerArgs.FunctionsUri);
workerOptions.Host = uri.Host;
workerOptions.Port = uri.Port;
}
catch (UriFormatException formatEx)
{
var message = $"Invalid URI format: {workerArgs.FunctionsUri}. Error message: {formatEx.Message}";
throw new ArgumentException(message, nameof(workerArgs.FunctionsUri));
}
}
else
{
workerOptions.Host = workerArgs.Host;
workerOptions.Port = workerArgs.Port;
}

// Validate workerOptions
ValidateProperty("WorkerId", workerOptions.WorkerId);
ValidateProperty("RequestId", workerOptions.RequestId);
ValidateProperty("Host", workerOptions.Host);

if (workerOptions.Port <= 0)
{
throw new ArgumentException("Port number has not been initialized", nameof(workerOptions.Port));
}
});

// Create the very first Runspace so the debugger has the target to attach to.
// This PowerShell instance is shared by the first PowerShellManager instance created in the pool,
Expand All @@ -44,14 +87,14 @@ public async static Task Main(string[] args)
LogPowerShellVersion(pwshVersion);
WarmUpPowerShell(firstPowerShellInstance);

var msgStream = new MessagingStream(arguments.Host, arguments.Port);
var msgStream = new MessagingStream(workerOptions.Host, workerOptions.Port);
var requestProcessor = new RequestProcessor(msgStream, firstPowerShellInstance, pwshVersion);

// Send StartStream message
var startedMessage = new StreamingMessage()
{
RequestId = arguments.RequestId,
StartStream = new StartStream() { WorkerId = arguments.WorkerId }
RequestId = workerOptions.RequestId,
StartStream = new StartStream() { WorkerId = workerOptions.WorkerId }
};

msgStream.Write(startedMessage);
Expand Down Expand Up @@ -81,23 +124,48 @@ private static void LogPowerShellVersion(string pwshVersion)
var message = string.Format(PowerShellWorkerStrings.PowerShellVersion, pwshVersion);
RpcLogger.WriteSystemLog(LogLevel.Information, message);
}

private static void ValidateProperty(string name, string value)
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException($"{name} is null or empty", name);
}
}
}

internal class WorkerArguments
{
[Option("host", Required = true, HelpText = "IP Address used to connect to the Host via gRPC.")]
[Option("host", Required = false, HelpText = "IP Address used to connect to the Host via gRPC.")]
public string Host { get; set; }

[Option("port", Required = true, HelpText = "Port used to connect to the Host via gRPC.")]
[Option("port", Required = false, HelpText = "Port used to connect to the Host via gRPC.")]
public int Port { get; set; }

[Option("workerId", Required = true, HelpText = "Worker ID assigned to this language worker.")]
[Option("workerId", Required = false, HelpText = "Worker ID assigned to this language worker.")]
public string WorkerId { get; set; }

[Option("requestId", Required = true, HelpText = "Request ID used for gRPC communication with the Host.")]
[Option("requestId", Required = false, HelpText = "Request ID used for gRPC communication with the Host.")]
public string RequestId { get; set; }

[Option("grpcMaxMessageLength", Required = false, HelpText = "[Deprecated and ignored] gRPC Maximum message size.")]
public int MaxMessageLength { get; set; }
[Option("functions-uri", Required = false, HelpText = "URI with IP Address and Port used to connect to the Host via gRPC.")]
public string FunctionsUri { get; set; }

[Option("functions-workerid", Required = false, HelpText = "Worker ID assigned to this language worker.")]
public string FunctionsWorkerId { get; set; }

[Option("functions-requestid", Required = false, HelpText = "Request ID used for gRPC communication with the Host.")]
public string FunctionsRequestId { get; set; }
}

internal class WorkerOptions
{
public string Host { get; set; }

public int Port { get; set; }

public string WorkerId { get; set; }

public string RequestId { get; set; }
}
}

0 comments on commit fdc5360

Please sign in to comment.