Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions protobuf/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Azure Functions Languge Worker Protobuf
# Azure Functions Language Worker Protobuf

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.

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

1. Draft a release in the GitHub UI
- Be sure to inculde details of the release
- Be sure to include details of the release
2. Create a release version, following semantic versioning guidelines ([semver.org](https://semver.org/))
3. Tag the version with the pattern: `v<M>.<m>.<p>-protofile` (example: `v1.1.0-protofile`)
3. Merge `dev` to `master`
Expand Down
8 changes: 7 additions & 1 deletion protobuf/src/proto/FunctionRpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ message WorkerInitRequest {
// inform worker of supported categories and their levels
// i.e. Worker = Verbose, Function.MyFunc = None
map<string, RpcLog.Level> log_categories = 3;

// Full path of worker.config.json location
string worker_directory = 4;
}

// Worker responds with the result of initializing itself
Expand Down Expand Up @@ -189,6 +192,8 @@ message WorkerStatusResponse {
message FunctionEnvironmentReloadRequest {
// Environment variables from the current process
map<string, string> environment_variables = 1;
// Current directory of function app
string function_app_directory = 2;
}

message FunctionEnvironmentReloadResponse {
Expand Down Expand Up @@ -429,11 +434,12 @@ message RpcException {

// Http cookie type. Note that only name and value are used for Http requests
message RpcHttpCookie {
// Enum that lets servers require that a cookie shouoldn't be sent with cross-site requests
// Enum that lets servers require that a cookie shouldn't be sent with cross-site requests
enum SameSite {
None = 0;
Lax = 1;
Strict = 2;
ExplicitNone = 3;
}

// Cookie name
Expand Down
52 changes: 52 additions & 0 deletions src/FunctionsEnvironmentReloader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Azure.Functions.PowerShellWorker.Utility;
using LogLevel = Microsoft.Azure.WebJobs.Script.Grpc.Messages.RpcLog.Types.Level;

namespace Microsoft.Azure.Functions.PowerShellWorker
{
internal class FunctionsEnvironmentReloader
{
private readonly ILogger _logger;
private readonly Action<string, string> _setEnvironmentVariable;
private readonly Action<string> _setCurrentDirectory;

public FunctionsEnvironmentReloader(ILogger logger)
: this(logger, Environment.SetEnvironmentVariable, Directory.SetCurrentDirectory)
{
}

internal FunctionsEnvironmentReloader(
ILogger logger,
Action<string, string> setEnvironmentVariable,
Action<string> setCurrentDirectory)
{
this._logger = logger ?? throw new ArgumentNullException(nameof(logger));
this._setEnvironmentVariable = setEnvironmentVariable;
this._setCurrentDirectory = setCurrentDirectory;
}

public void ReloadEnvironment(
IEnumerable<KeyValuePair<string, string>> environmentVariables,
string functionAppDirectory)
{
foreach (var (name, value) in environmentVariables)
{
this._setEnvironmentVariable(name, value);
}

if (functionAppDirectory != null)
{
var setCurrentDirMessage = string.Format(PowerShellWorkerStrings.SettingCurrentDirectory, functionAppDirectory);
_logger.Log(isUserOnlyLog: false, LogLevel.Trace, setCurrentDirMessage);
_setCurrentDirectory(functionAppDirectory);
}
}
}
}
11 changes: 7 additions & 4 deletions src/RequestProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
namespace Microsoft.Azure.Functions.PowerShellWorker
{
using System.Diagnostics;
using System.IO;
using LogLevel = Microsoft.Azure.WebJobs.Script.Grpc.Messages.RpcLog.Types.Level;

internal class RequestProcessor
Expand Down Expand Up @@ -338,13 +339,15 @@ internal StreamingMessage ProcessFunctionEnvironmentReloadRequest(StreamingMessa
stopwatch.Start();

var environmentReloadRequest = request.FunctionEnvironmentReloadRequest;
foreach (var (name, value) in environmentReloadRequest.EnvironmentVariables)
{
Environment.SetEnvironmentVariable(name, value);
}

var rpcLogger = new RpcLogger(_msgStream);
rpcLogger.SetContext(request.RequestId, null);

var functionsEnvironmentReloader = new FunctionsEnvironmentReloader(rpcLogger);
functionsEnvironmentReloader.ReloadEnvironment(
environmentReloadRequest.EnvironmentVariables,
environmentReloadRequest.FunctionAppDirectory);

rpcLogger.Log(isUserOnlyLog: false, LogLevel.Trace, string.Format(PowerShellWorkerStrings.EnvironmentReloadCompleted, stopwatch.ElapsedMilliseconds));

StreamingMessage response = NewStreamingMessageTemplate(
Expand Down
3 changes: 3 additions & 0 deletions src/resources/PowerShellWorkerStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -316,4 +316,7 @@
<data name="EnvironmentReloadCompleted" xml:space="preserve">
<value>Environment reload completed in {0} ms.</value>
</data>
<data name="SettingCurrentDirectory" xml:space="preserve">
<value>Setting current directory to '{0}'.</value>
</data>
</root>
65 changes: 65 additions & 0 deletions test/Unit/Function/FunctionsEnvironmentReloaderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using Moq;
using Xunit;
using Microsoft.Azure.Functions.PowerShellWorker.Utility;
using System.Collections.Generic;

namespace Microsoft.Azure.Functions.PowerShellWorker.Test
{
public class FunctionsEnvironmentReloaderTests
{
private readonly Mock<ILogger> _mockLogger = new Mock<ILogger>();

[Fact]
public void SetsEnvironmentVariables()
{
var actualEnvironmentVariables = new List<KeyValuePair<string, string>>();

var reloader = new FunctionsEnvironmentReloader(
logger: _mockLogger.Object,
setEnvironmentVariable: (name, value) => { actualEnvironmentVariables.Add(new KeyValuePair<string, string>(name, value)); },
setCurrentDirectory: directory => { });

var requestedEnvironmentVariables = new[] {
new KeyValuePair<string, string>( "name1", "valueA" ),
new KeyValuePair<string, string>( "name2", "valueB" ),
new KeyValuePair<string, string>( "name3", "valueC" ),
};

reloader.ReloadEnvironment(requestedEnvironmentVariables, functionAppDirectory: null);

Assert.Equal(requestedEnvironmentVariables, actualEnvironmentVariables);
}

[Fact]
public void SetsFunctionAppDirectoryIfRequested()
{
const string RequestedNewDirectory = "new app directory";
string actualNewDirectory = null;

var reloader = new FunctionsEnvironmentReloader(
logger: _mockLogger.Object,
setEnvironmentVariable: (name, value) => { },
setCurrentDirectory: directory => { actualNewDirectory = directory; });

reloader.ReloadEnvironment(new List<KeyValuePair<string, string>>(), RequestedNewDirectory);

Assert.Equal(RequestedNewDirectory, actualNewDirectory);
}

[Fact]
public void DoesNotSetFunctionAppDirectoryIfNotRequested()
{
var reloader = new FunctionsEnvironmentReloader(
logger: _mockLogger.Object,
setEnvironmentVariable: (name, value) => { },
setCurrentDirectory: directory => { Assert.True(false, "Unexpected invocation"); });

reloader.ReloadEnvironment(new List<KeyValuePair<string, string>>(), functionAppDirectory: null);
}
}
}