Skip to content

Commit 13e92f7

Browse files
authored
Change current directory on environment reload request (Azure#522) (Azure#524)
* Updated subtree from https://github.com/azure/azure-functions-language-worker-protobuf. Tag: v1.3.8-protofile. Commit: 8db40c8 * Set current directory on environment reload request
1 parent 124ec35 commit 13e92f7

File tree

6 files changed

+136
-7
lines changed

6 files changed

+136
-7
lines changed

protobuf/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Azure Functions Languge Worker Protobuf
1+
# Azure Functions Language Worker Protobuf
22

33
This repository contains the protobuf definition file which defines the gRPC service which is used between the [Azure Functions Host](https://github.com/Azure/azure-functions-host) and the Azure Functions language workers. This repo is shared across many repos in many languages (for each worker) by using git commands.
44

@@ -39,7 +39,7 @@ From within the Azure Functions language worker repo:
3939
## Releasing a Language Worker Protobuf version
4040

4141
1. Draft a release in the GitHub UI
42-
- Be sure to inculde details of the release
42+
- Be sure to include details of the release
4343
2. Create a release version, following semantic versioning guidelines ([semver.org](https://semver.org/))
4444
3. Tag the version with the pattern: `v<M>.<m>.<p>-protofile` (example: `v1.1.0-protofile`)
4545
3. Merge `dev` to `master`

protobuf/src/proto/FunctionRpc.proto

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ message WorkerInitRequest {
9696
// inform worker of supported categories and their levels
9797
// i.e. Worker = Verbose, Function.MyFunc = None
9898
map<string, RpcLog.Level> log_categories = 3;
99+
100+
// Full path of worker.config.json location
101+
string worker_directory = 4;
99102
}
100103

101104
// Worker responds with the result of initializing itself
@@ -189,6 +192,8 @@ message WorkerStatusResponse {
189192
message FunctionEnvironmentReloadRequest {
190193
// Environment variables from the current process
191194
map<string, string> environment_variables = 1;
195+
// Current directory of function app
196+
string function_app_directory = 2;
192197
}
193198

194199
message FunctionEnvironmentReloadResponse {
@@ -429,11 +434,12 @@ message RpcException {
429434

430435
// Http cookie type. Note that only name and value are used for Http requests
431436
message RpcHttpCookie {
432-
// Enum that lets servers require that a cookie shouoldn't be sent with cross-site requests
437+
// Enum that lets servers require that a cookie shouldn't be sent with cross-site requests
433438
enum SameSite {
434439
None = 0;
435440
Lax = 1;
436441
Strict = 2;
442+
ExplicitNone = 3;
437443
}
438444

439445
// Cookie name
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
using System;
7+
using System.Collections.Generic;
8+
using System.IO;
9+
using Microsoft.Azure.Functions.PowerShellWorker.Utility;
10+
using LogLevel = Microsoft.Azure.WebJobs.Script.Grpc.Messages.RpcLog.Types.Level;
11+
12+
namespace Microsoft.Azure.Functions.PowerShellWorker
13+
{
14+
internal class FunctionsEnvironmentReloader
15+
{
16+
private readonly ILogger _logger;
17+
private readonly Action<string, string> _setEnvironmentVariable;
18+
private readonly Action<string> _setCurrentDirectory;
19+
20+
public FunctionsEnvironmentReloader(ILogger logger)
21+
: this(logger, Environment.SetEnvironmentVariable, Directory.SetCurrentDirectory)
22+
{
23+
}
24+
25+
internal FunctionsEnvironmentReloader(
26+
ILogger logger,
27+
Action<string, string> setEnvironmentVariable,
28+
Action<string> setCurrentDirectory)
29+
{
30+
this._logger = logger ?? throw new ArgumentNullException(nameof(logger));
31+
this._setEnvironmentVariable = setEnvironmentVariable;
32+
this._setCurrentDirectory = setCurrentDirectory;
33+
}
34+
35+
public void ReloadEnvironment(
36+
IEnumerable<KeyValuePair<string, string>> environmentVariables,
37+
string functionAppDirectory)
38+
{
39+
foreach (var (name, value) in environmentVariables)
40+
{
41+
this._setEnvironmentVariable(name, value);
42+
}
43+
44+
if (functionAppDirectory != null)
45+
{
46+
var setCurrentDirMessage = string.Format(PowerShellWorkerStrings.SettingCurrentDirectory, functionAppDirectory);
47+
_logger.Log(isUserOnlyLog: false, LogLevel.Trace, setCurrentDirMessage);
48+
_setCurrentDirectory(functionAppDirectory);
49+
}
50+
}
51+
}
52+
}

src/RequestProcessor.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
namespace Microsoft.Azure.Functions.PowerShellWorker
2121
{
2222
using System.Diagnostics;
23+
using System.IO;
2324
using LogLevel = Microsoft.Azure.WebJobs.Script.Grpc.Messages.RpcLog.Types.Level;
2425

2526
internal class RequestProcessor
@@ -338,13 +339,15 @@ internal StreamingMessage ProcessFunctionEnvironmentReloadRequest(StreamingMessa
338339
stopwatch.Start();
339340

340341
var environmentReloadRequest = request.FunctionEnvironmentReloadRequest;
341-
foreach (var (name, value) in environmentReloadRequest.EnvironmentVariables)
342-
{
343-
Environment.SetEnvironmentVariable(name, value);
344-
}
345342

346343
var rpcLogger = new RpcLogger(_msgStream);
347344
rpcLogger.SetContext(request.RequestId, null);
345+
346+
var functionsEnvironmentReloader = new FunctionsEnvironmentReloader(rpcLogger);
347+
functionsEnvironmentReloader.ReloadEnvironment(
348+
environmentReloadRequest.EnvironmentVariables,
349+
environmentReloadRequest.FunctionAppDirectory);
350+
348351
rpcLogger.Log(isUserOnlyLog: false, LogLevel.Trace, string.Format(PowerShellWorkerStrings.EnvironmentReloadCompleted, stopwatch.ElapsedMilliseconds));
349352

350353
StreamingMessage response = NewStreamingMessageTemplate(

src/resources/PowerShellWorkerStrings.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,4 +316,7 @@
316316
<data name="EnvironmentReloadCompleted" xml:space="preserve">
317317
<value>Environment reload completed in {0} ms.</value>
318318
</data>
319+
<data name="SettingCurrentDirectory" xml:space="preserve">
320+
<value>Setting current directory to '{0}'.</value>
321+
</data>
319322
</root>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
using Moq;
7+
using Xunit;
8+
using Microsoft.Azure.Functions.PowerShellWorker.Utility;
9+
using System.Collections.Generic;
10+
11+
namespace Microsoft.Azure.Functions.PowerShellWorker.Test
12+
{
13+
public class FunctionsEnvironmentReloaderTests
14+
{
15+
private readonly Mock<ILogger> _mockLogger = new Mock<ILogger>();
16+
17+
[Fact]
18+
public void SetsEnvironmentVariables()
19+
{
20+
var actualEnvironmentVariables = new List<KeyValuePair<string, string>>();
21+
22+
var reloader = new FunctionsEnvironmentReloader(
23+
logger: _mockLogger.Object,
24+
setEnvironmentVariable: (name, value) => { actualEnvironmentVariables.Add(new KeyValuePair<string, string>(name, value)); },
25+
setCurrentDirectory: directory => { });
26+
27+
var requestedEnvironmentVariables = new[] {
28+
new KeyValuePair<string, string>( "name1", "valueA" ),
29+
new KeyValuePair<string, string>( "name2", "valueB" ),
30+
new KeyValuePair<string, string>( "name3", "valueC" ),
31+
};
32+
33+
reloader.ReloadEnvironment(requestedEnvironmentVariables, functionAppDirectory: null);
34+
35+
Assert.Equal(requestedEnvironmentVariables, actualEnvironmentVariables);
36+
}
37+
38+
[Fact]
39+
public void SetsFunctionAppDirectoryIfRequested()
40+
{
41+
const string RequestedNewDirectory = "new app directory";
42+
string actualNewDirectory = null;
43+
44+
var reloader = new FunctionsEnvironmentReloader(
45+
logger: _mockLogger.Object,
46+
setEnvironmentVariable: (name, value) => { },
47+
setCurrentDirectory: directory => { actualNewDirectory = directory; });
48+
49+
reloader.ReloadEnvironment(new List<KeyValuePair<string, string>>(), RequestedNewDirectory);
50+
51+
Assert.Equal(RequestedNewDirectory, actualNewDirectory);
52+
}
53+
54+
[Fact]
55+
public void DoesNotSetFunctionAppDirectoryIfNotRequested()
56+
{
57+
var reloader = new FunctionsEnvironmentReloader(
58+
logger: _mockLogger.Object,
59+
setEnvironmentVariable: (name, value) => { },
60+
setCurrentDirectory: directory => { Assert.True(false, "Unexpected invocation"); });
61+
62+
reloader.ReloadEnvironment(new List<KeyValuePair<string, string>>(), functionAppDirectory: null);
63+
}
64+
}
65+
}

0 commit comments

Comments
 (0)