Skip to content

Commit

Permalink
Adding default settings to support SDK container builds (#2671)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattchenderson authored and fabiocav committed Oct 11, 2024
1 parent 0f5cfef commit ff6e067
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 0 deletions.
4 changes: 4 additions & 0 deletions release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@
### Microsoft.Azure.Functions.Worker.Grpc <version>

- Removed fallback command line argument reading code for grpc worker startup options. (#1908)

### Microsoft.Azure.Functions.Worker.Sdk 2.0.0-preview2

- Adding support for SDK container builds with Functions base images
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,30 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and
<Import Project="$(MSBuildThisFileDirectory)Microsoft.Azure.Functions.Worker.Sdk.Publish.$(PublishProtocol).targets"
Condition="Exists('$(MSBuildThisFileDirectory)Microsoft.Azure.Functions.Worker.Sdk.Publish.$(PublishProtocol).targets')" />

<Target
Name="AssignFunctionsBaseImage"
BeforeTargets="ComputeContainerBaseImage"
DependsOnTargets="_FunctionsPreBuild" >
<PropertyGroup>
<_FunctionsRuntimeMajorVersion>$(_AzureFunctionsVersionStandardized.TrimStart('vV'))</_FunctionsRuntimeMajorVersion>
<ContainerBaseImage Condition="'$(ContainerBaseImage)' == ''">mcr.microsoft.com/azure-functions/dotnet-isolated:$(_FunctionsRuntimeMajorVersion)-dotnet-isolated$(TargetFrameworkVersion.TrimStart('vV'))</ContainerBaseImage>
<ContainerWorkingDirectory Condition="'$(ContainerWorkingDirectory)' == ''">/home/site/wwwroot</ContainerWorkingDirectory>
<!-- Functions base images only support amd64 runtimes -->
<ContainerRuntimeIdentifier Condition="'$(ContainerRuntimeIdentifier)' == ''">linux-x64</ContainerRuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<ContainerEnvironmentVariable
Condition="@(ContainerEnvironmentVariable->AnyHaveMetadataValue('Identity', 'AzureWebJobsScriptRoot')) == false"
Include="AzureWebJobsScriptRoot"
Value="$(ContainerWorkingDirectory)" />
<ContainerEnvironmentVariable
Condition="@(ContainerEnvironmentVariable->AnyHaveMetadataValue('Identity', 'AzureFunctionsJobHost__Logging__Console__IsEnabled')) == false"
Include="AzureFunctionsJobHost__Logging__Console__IsEnabled"
Value="true" />
</ItemGroup>
<ItemGroup>
<ContainerAppCommand Include="/opt/startup/start_nonappservice.sh" />
</ItemGroup>
</Target>

</Project>
24 changes: 24 additions & 0 deletions test/SdkE2ETests/ProcessWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit.Abstractions;
Expand All @@ -11,8 +12,22 @@ namespace Microsoft.Azure.Functions.SdkE2ETests
{
public class ProcessWrapper
{

public async Task<int?> RunProcess(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null)
{
return await RunProcessInternal(fileName, arguments, workingDirectory, testOutputHelper);
}

public async Task<Tuple<int?, string>> RunProcessForOutput(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null)
{
StringBuilder processOutputStringBuilder = new StringBuilder();
var exitCode = await RunProcessInternal(fileName, arguments, workingDirectory, testOutputHelper, processOutputStringBuilder);
return new Tuple<int?,string>(exitCode, processOutputStringBuilder.ToString());
}

private async Task<int?> RunProcessInternal(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null, StringBuilder processOutputBuilder = null)
{

SemaphoreSlim processExitSemaphore = new SemaphoreSlim(0, 1);

ProcessStartInfo startInfo = new ProcessStartInfo
Expand All @@ -39,6 +54,10 @@ public class ProcessWrapper
if (o.Data != null)
{
testOutputHelper.WriteLine($"[{DateTime.UtcNow:O}] Error: {o.Data}");
if (processOutputBuilder != null)
{
processOutputBuilder.AppendLine(o.Data);
}
}
};

Expand All @@ -47,6 +66,10 @@ public class ProcessWrapper
if (o.Data != null)
{
testOutputHelper.WriteLine($"[{DateTime.UtcNow:O}] {o.Data}");
if (processOutputBuilder != null)
{
processOutputBuilder.AppendLine(o.Data);
}
}
};

Expand All @@ -65,4 +88,5 @@ public class ProcessWrapper
return testProcess?.ExitCode;
}
}

}
28 changes: 28 additions & 0 deletions test/SdkE2ETests/PublishTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,34 @@ public async Task Publish_Rid()
await RunPublishTest(outputDir, "-r win-x86");
}

[Fact]
// This test requires the Docker daemon to be installed and running
// It is excluded through the SdkE2ETests_default.runsettings file from normal tests
// To run the test, use `dotnet test -s SdkE2ETests_dockertests.runsettings`
[Trait("Requirement", "Docker")]
public async Task Publish_Container()
{
string outputDir = await TestUtility.InitializeTestAsync(_testOutputHelper, nameof(Publish_Container));
var repository = nameof(SdkE2ETests).ToLower();
var imageTag = nameof(Publish_Container);

// setup test environment state in case there is leftover data from previous runs
await TestUtility.RemoveDockerTestImage(repository, imageTag, _testOutputHelper);

// perform the publish
await RunPublishTest(outputDir, $"--no-restore /t:PublishContainer --property:ContainerRepository={repository} --property:ContainerImageTag={imageTag}");

// validate the image base
Tuple<int?,string> inspectResults = await new ProcessWrapper().RunProcessForOutput("docker", $"inspect {repository}:{imageTag} --format \"{{{{ index .Config.Labels \\\"org.opencontainers.image.base.name\\\"}}}}\"", outputDir, _testOutputHelper);
var inspectExitCode = inspectResults.Item1;
var inspectOutput = inspectResults.Item2;
Assert.True(inspectExitCode.HasValue && inspectExitCode.Value == 0);
Assert.Matches("mcr\\.microsoft\\.com/azure-functions/dotnet-isolated:(\\d)+-dotnet-isolated(\\d+\\.\\d+)", inspectOutput);

// clean up
await TestUtility.RemoveDockerTestImage(repository, imageTag, _testOutputHelper);
}

private async Task RunPublishTest(string outputDir, string additionalParams = null)
{
// Name of the csproj
Expand Down
4 changes: 4 additions & 0 deletions test/SdkE2ETests/SdkE2ETests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
<AssemblyOriginatorKeyFile>..\..\key.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>

<PropertyGroup>
<RunSettingsFilePath>$(MSBuildProjectDirectory)\SdkE2ETests_default.runsettings</RunSettingsFilePath>
</PropertyGroup>

<ItemGroup>
<None Remove="Contents\functions.metadata" />
</ItemGroup>
Expand Down
6 changes: 6 additions & 0 deletions test/SdkE2ETests/SdkE2ETests_default.runsettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<TestCaseFilter>(Requirement != Docker)</TestCaseFilter>
</RunConfiguration>
</RunSettings>
6 changes: 6 additions & 0 deletions test/SdkE2ETests/SdkE2ETests_dockertests.runsettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<TestCaseFilter>(Requirement = Docker)</TestCaseFilter>
</RunConfiguration>
</RunSettings>
7 changes: 7 additions & 0 deletions test/SdkE2ETests/TestUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,12 @@ private static string InitializeOutputDir(string testName)

return outputDir;
}

public static async Task RemoveDockerTestImage(string repository, string imageTag, ITestOutputHelper outputHelper)
{
outputHelper.WriteLine($"Removing image {repository}:{imageTag} from local registry");
int? rmiExitCode = await new ProcessWrapper().RunProcess("docker", $"rmi -f {repository}:{imageTag}", TestOutputDir, outputHelper);
Assert.True(rmiExitCode.HasValue && rmiExitCode.Value == 0); // daemon may still error if the image doesn't exist, but it will still return 0
}
}
}

0 comments on commit ff6e067

Please sign in to comment.