Skip to content

bundle and handle Azure PowerShell #47

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Sep 12, 2018

Conversation

TylerLeonhardt
Copy link
Member

@TylerLeonhardt TylerLeonhardt commented Sep 11, 2018

This PR bundles modules into the src/Modules directory so that they can be distributed with the worker.

The modules are as followed:

  • AzureRm - to interact with Azure resources inside of an Azure Function
  • Microsoft.PowerShell.Archive - so that users can expand and archive zips
  • PowerShellGet - mainly for Publish-Module. User's will want to use AzF as a CICD pipeline for their modules

This psd1 also handles dev dependencies - so Pester has been moved to that.

Also, the format of the .psd1 is in the format that PSDepend uses. I wanted to leverage this package because it does exactly what we want but I was afraid that folks wouldn't like the extra dependency.

This also is an evaluation of the Module as a possible solution to specifying dependencies IN a user's function.

In addition to bundling, this PR includes changes to get Azure PowerShell working. Some work was needed to get Azure PowerShell to work at all (see #48)... but this PR includes lets you use it without needing to do any interactive work using Serivce Principals.

See this doc on how to set one up:
https://docs.microsoft.com/en-us/powershell/azure/create-azure-service-principal-azureps?view=azurermps-6.8.1

If the user specifies the environment variables:
ApplicationId, ApplicationSecret & TenantId

Then the PowerShell Worker will attempt to connect to Azure using that information without you needing to explicitly say Connect-AzureRmAccount. This is similar to what Azure Automation does today.

I've also included a working example of an HttpTrigger that can grab some VM's from Azure and send a response back.

Copy link
Contributor

@daxian-dbw daxian-dbw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left one comment

@@ -0,0 +1,21 @@
@{
# Packaged with the PowerShell Language Worker
'PowerShellGet' = @{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put this file in the tools folder? I guess we can call Invoke-PSDepend "$PSScriptRoot/tools/requirements.psd1

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We synced offline and think it should go in src

@TylerLeonhardt TylerLeonhardt changed the title Bundle all modules in build bundle and handle Azure PowerShell Sep 12, 2018
@TylerLeonhardt
Copy link
Member Author

@daxian-dbw I've addressed your comment. This PR was updated to fix Azure PowerShell being brought in and enables a step that will auto connect to Azure if the correct environment variables are present.

string.IsNullOrEmpty(applicationSecret) ||
string.IsNullOrEmpty(tenantId))
{
_logger.Log(LogLevel.Warning, "Required environment variables to authenticate to Azure were not present", isUserLog: true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We won't be able to see the log if it's user log, but I think this message should be visible to us too.

We probably shouldn't just return in this case, but should indicate a failure status so we can send a FunctionLoadResponse message with the status and the error message.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this actually should be a Warning because we shouldn't require connecting to Azure to run the function locally - especially if their function doesn't interact Azure at all.

Additionally, this shouldn't be a user log, it should be a system log because in the local scenario the user sees the system logs... so I'll make that change.

Copy link
Contributor

@daxian-dbw daxian-dbw Sep 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The local scenario makes sense. But I don't see the logging gets changed to the system log.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@@ -47,7 +47,7 @@ public async void Log(LogLevel logLevel, string message, Exception exception = n
RpcLog = new RpcLog()
{
Exception = exception?.ToRpcException(),
InvocationId = _invocationId,
InvocationId = _invocationId ?? _requestId,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to set the InvocationId? What will happen if leaving it null or empty string?

Copy link
Member Author

@TylerLeonhardt TylerLeonhardt Sep 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has to be set. I've tried setting it to empty string or null but it still fails by saying can't be null or empty.

Copy link
Contributor

@daxian-dbw daxian-dbw Sep 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand, we will hit this code only for user logging, which only happens when the function runs. _invocationId will not be null by that time. But when doing system logging, _invocationId could be null, so we should handle it there. And I think it should be _invocationId ?? "N/A".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

default:
throw new InvalidOperationException($"Not supportted message type: {request.ContentCase}");
}
await _msgStream.WriteAsync(response);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This async operation can be moved out of the using block.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@@ -103,6 +106,9 @@ internal void InitializeRunspace()
{
Dictionary<string, ParameterMetadata> parameterMetadata;

// We attempt to authenticate to Azure with every invocation
AuthenticateToAzure();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please explain why we are doing this for every function invocation? Are you expecting the environment variables may change for each function invocation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we talked offline. I will move it to WorkerInit for the demo but also opened #49 for understanding.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants