Skip to content

Commit 6c0c016

Browse files
address dongbo's feedback
1 parent e34c687 commit 6c0c016

File tree

4 files changed

+51
-60
lines changed

4 files changed

+51
-60
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ Prototype for Azure Functions PowerShell Language Worker
1111
```powershell
1212
# Windows if you installed the Azure Functions Core Tools via npm
1313
Remove-Item -Recurse -Force ~\AppData\Roaming\npm\node_modules\azure-functions-core-tools\bin\workers\powershell
14-
Copy-Item src\Azure.Functions.PowerShell.Worker\bin\Debug\netcoreapp2.1\publish ~\AppData\Roaming\npm\node_modules\azure-functions-core-tools\bin\workers\powershell -Recurse -Force
14+
Copy-Item src\bin\Debug\netcoreapp2.1\publish ~\AppData\Roaming\npm\node_modules\azure-functions-core-tools\bin\workers\powershell -Recurse -Force
1515
1616
# macOS if you installed the Azure Functions Core Tools via brew
1717
Remove-Item -Recurse -Force /usr/local/Cellar/azure-functions-core-tools/2.0.1-beta.33/workers/powershell
18-
Copy-Item src/Azure.Functions.PowerShell.Worker/bin/Debug/netcoreapp2.1/publish /usr/local/Cellar/azure-functions-core-tools/2.0.1-beta.33/workers/powershell -Recurse -Force
18+
Copy-Item src/bin/Debug/netcoreapp2.1/publish /usr/local/Cellar/azure-functions-core-tools/2.0.1-beta.33/workers/powershell -Recurse -Force
1919
```

src/Modules/Azure.Functions.PowerShell.Worker.Module/Azure.Functions.PowerShell.Worker.Module.psm1

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ function Get-OutputBinding {
3030
param(
3131
[Parameter(ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)]
3232
[string[]]
33-
$Name = '*'
33+
$Name = '*',
34+
35+
[switch]
36+
$Purge
3437
)
3538
begin {
3639
$bindings = @{}
@@ -39,6 +42,9 @@ function Get-OutputBinding {
3942
$script:_OutputBindings.GetEnumerator() | Where-Object Name -Like $Name | ForEach-Object { $null = $bindings.Add($_.Name, $_.Value) }
4043
}
4144
end {
45+
if($Purge.IsPresent) {
46+
$script:_OutputBindings.Clear()
47+
}
4248
return $bindings
4349
}
4450
}

src/PowerShell/PowerShellManager.cs

Lines changed: 24 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Collections;
88
using System.Collections.Generic;
99
using System.Collections.ObjectModel;
10+
using System.IO;
1011

1112
using Microsoft.Azure.Functions.PowerShellWorker.Utility;
1213
using Microsoft.Azure.WebJobs.Script.Grpc.Messages;
@@ -20,14 +21,15 @@ namespace Microsoft.Azure.Functions.PowerShellWorker.PowerShell
2021
internal class PowerShellManager
2122
{
2223
readonly static string s_TriggerMetadataParameterName = "TriggerMetadata";
23-
readonly static bool s_UseLocalScope = true;
2424

2525
RpcLogger _logger;
2626
PowerShell _pwsh;
2727

28-
PowerShellManager(PowerShell pwsh, RpcLogger logger)
28+
internal PowerShellManager(RpcLogger logger)
2929
{
30-
_pwsh = pwsh;
30+
var initialSessionState = InitialSessionState.CreateDefault();
31+
initialSessionState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;
32+
_pwsh = PowerShell.Create(initialSessionState);
3133
_logger = logger;
3234

3335
// Setup Stream event listeners
@@ -40,36 +42,19 @@ internal class PowerShellManager
4042
_pwsh.Streams.Warning.DataAdding += streamHandler.WarningDataAdding;
4143
}
4244

43-
public static PowerShellManager Create(RpcLogger logger)
45+
internal void InitializeRunspace()
4446
{
45-
// Set up initial session state
46-
var initialSessionState = InitialSessionState.CreateDefault();
47-
if(Platform.IsWindows)
48-
{
49-
initialSessionState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;
50-
}
51-
var pwsh = PowerShell.Create(initialSessionState);
52-
53-
// Build path to the Azure Functions binding helper module
54-
string modulePath = System.IO.Path.Join(
55-
AppDomain.CurrentDomain.BaseDirectory,
56-
"Azure.Functions.PowerShell.Worker.Module",
57-
"Azure.Functions.PowerShell.Worker.Module.psd1");
58-
5947
// Add HttpResponseContext namespace so users can reference
6048
// HttpResponseContext without needing to specify the full namespace
61-
pwsh.AddScript($"using namespace {typeof(HttpResponseContext).Namespace}")
62-
.AddStatement()
63-
// Import the Azure Functions binding helper module
64-
.AddCommand("Import-Module")
65-
.AddParameter("Name", modulePath)
66-
.AddParameter("Scope", "Global")
67-
.InvokeAndClearCommands();
68-
69-
return new PowerShellManager(pwsh, logger);
49+
_pwsh.AddScript($"using namespace {typeof(HttpResponseContext).Namespace}").InvokeAndClearCommands();
50+
51+
// Prepend the path to the internal Modules folder to the PSModulePath
52+
var modulePath = Environment.GetEnvironmentVariable("PSModulePath");
53+
var additionalPath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "Modules");
54+
Environment.SetEnvironmentVariable("PSModulePath", $"{additionalPath}{Path.PathSeparator}{modulePath}");
7055
}
7156

72-
public Hashtable InvokeFunction(
57+
internal Hashtable InvokeFunction(
7358
string scriptPath,
7459
string entryPoint,
7560
Hashtable triggerMetadata,
@@ -88,22 +73,19 @@ public Hashtable InvokeFunction(
8873
if (entryPoint != "")
8974
{
9075
parameterMetadata = _pwsh
91-
.AddScript($@". {scriptPath}", s_UseLocalScope)
76+
.AddScript($@". {scriptPath}")
9277
.AddStatement()
93-
.AddCommand("Get-Command", s_UseLocalScope).AddParameter("Name", entryPoint)
78+
.AddCommand("Get-Command", useLocalScope: true).AddParameter("Name", entryPoint)
9479
.InvokeAndClearCommands<FunctionInfo>()[0].Parameters;
9580

96-
_pwsh
97-
.AddScript($@". {scriptPath}", s_UseLocalScope)
98-
.AddStatement()
99-
.AddCommand(entryPoint, s_UseLocalScope);
81+
_pwsh.AddCommand(entryPoint, useLocalScope: true);
10082

10183
}
10284
else
10385
{
104-
parameterMetadata = _pwsh.AddCommand("Get-Command", s_UseLocalScope).AddParameter("Name", scriptPath)
86+
parameterMetadata = _pwsh.AddCommand("Get-Command", useLocalScope: true).AddParameter("Name", scriptPath)
10587
.InvokeAndClearCommands<ExternalScriptInfo>()[0].Parameters;
106-
_pwsh.AddCommand(scriptPath, s_UseLocalScope);
88+
_pwsh.AddCommand(scriptPath, useLocalScope: true);
10789
}
10890
}
10991

@@ -127,40 +109,32 @@ public Hashtable InvokeFunction(
127109
Collection<PSObject> pipelineItems = _pwsh.InvokeAndClearCommands<PSObject>();
128110
foreach (var psobject in pipelineItems)
129111
{
130-
_logger.LogInformation(psobject.ToString());
112+
_logger.LogInformation($"FROM FUNCTION: {psobject.ToString()}");
131113
}
132114

133115
returnObject = pipelineItems[pipelineItems.Count - 1];
134116
}
135117

136-
var result = _pwsh.AddCommand("Get-OutputBinding", s_UseLocalScope).InvokeAndClearCommands<Hashtable>()[0];
118+
var result = _pwsh.AddCommand("Azure.Functions.PowerShell.Worker.Module\\Get-OutputBinding", useLocalScope: true)
119+
.AddParameter("Purge")
120+
.InvokeAndClearCommands<Hashtable>()[0];
137121

138122
if(returnObject != null)
139123
{
140124
result.Add("$return", returnObject);
141125
}
142-
ResetRunspace();
143126
return result;
144127
}
145-
catch(Exception e)
128+
finally
146129
{
147130
ResetRunspace();
148-
throw;
149131
}
150132
}
151133

152-
void ResetRunspace()
134+
private void ResetRunspace()
153135
{
154136
// Reset the runspace to the Initial Session State
155137
_pwsh.Runspace.ResetRunspaceState();
156-
157-
// TODO: Change this to clearing the variable by running in the module
158-
string modulePath = System.IO.Path.Join(AppDomain.CurrentDomain.BaseDirectory, "Azure.Functions.PowerShell.Worker.Module", "Azure.Functions.PowerShell.Worker.Module.psd1");
159-
_pwsh.AddCommand("Import-Module")
160-
.AddParameter("Name", modulePath)
161-
.AddParameter("Scope", "Global")
162-
.AddParameter("Force")
163-
.InvokeAndClearCommands();
164138
}
165139
}
166140
}

src/RequestProcessor.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ internal RequestProcessor(MessagingStream msgStream)
2626
{
2727
_msgStream = msgStream;
2828
_logger = new RpcLogger(msgStream);
29-
_powerShellManager = PowerShellManager.Create(_logger);
29+
_powerShellManager = new PowerShellManager(_logger);
3030
_functionLoader = new FunctionLoader();
3131
}
3232

@@ -63,15 +63,27 @@ internal async Task ProcessRequestLoop()
6363

6464
internal StreamingMessage ProcessWorkerInitRequest(StreamingMessage request)
6565
{
66+
StatusResult status = new StatusResult()
67+
{
68+
Status = StatusResult.Types.Status.Success
69+
};
70+
71+
try
72+
{
73+
_powerShellManager.InitializeRunspace();
74+
}
75+
catch (Exception e)
76+
{
77+
status.Status = StatusResult.Types.Status.Failure;
78+
status.Exception = e.ToRpcException();
79+
}
80+
6681
return new StreamingMessage()
6782
{
6883
RequestId = request.RequestId,
6984
WorkerInitResponse = new WorkerInitResponse()
7085
{
71-
Result = new StatusResult()
72-
{
73-
Status = StatusResult.Types.Status.Success
74-
}
86+
Result = status
7587
}
7688
};
7789
}
@@ -143,8 +155,7 @@ internal StreamingMessage ProcessInvocationRequest(StreamingMessage request)
143155
try
144156
{
145157
result = _powerShellManager
146-
.InvokeFunctionAndSetGlobalReturn(scriptPath, entryPoint, triggerMetadata, invocationRequest.InputData)
147-
.ReturnBindingHashtable(functionInfo.OutputBindings);
158+
.InvokeFunction(scriptPath, entryPoint, triggerMetadata, invocationRequest.InputData);
148159
}
149160
catch (Exception e)
150161
{

0 commit comments

Comments
 (0)