Skip to content

Commit cac3cb2

Browse files
authored
Scm build package (#4432)
1 parent 86472dd commit cac3cb2

File tree

8 files changed

+326
-75
lines changed

8 files changed

+326
-75
lines changed

src/WebJobs.Script.WebHost/Management/InstanceManager.cs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using Microsoft.Azure.WebJobs.Script.WebHost.Models;
1717
using Microsoft.Extensions.Logging;
1818
using Microsoft.Extensions.Options;
19+
using Microsoft.WindowsAzure.Storage.Blob;
1920
using Newtonsoft.Json;
2021

2122
namespace Microsoft.Azure.WebJobs.Script.WebHost.Management
@@ -130,7 +131,16 @@ public async Task<string> ValidateContext(HostAssignmentContext assignmentContex
130131
HttpResponseMessage response = null;
131132
try
132133
{
133-
var zipUrl = assignmentContext.ZipUrl;
134+
RunFromPackageContext pkgContext = assignmentContext.GetRunFromPkgContext();
135+
_logger.LogInformation($"Will be using {pkgContext.EnvironmentVariableName} app setting as zip url");
136+
137+
if (pkgContext.IsScmRunFromPackage())
138+
{
139+
// Not user assigned so limit validation
140+
return null;
141+
}
142+
143+
var zipUrl = pkgContext.Url;
134144
if (!string.IsNullOrEmpty(zipUrl))
135145
{
136146
// make sure the zip uri is valid and accessible
@@ -193,16 +203,35 @@ private async Task ApplyContext(HostAssignmentContext assignmentContext)
193203
_logger.LogInformation($"Applying {assignmentContext.Environment.Count} app setting(s)");
194204
assignmentContext.ApplyAppSettings(_environment);
195205

196-
// We need to get the non-PlaceholderMode script path so we can unzip to the correct location.
206+
// We need to get the non-PlaceholderMode script Path so we can unzip to the correct location.
197207
// This asks the factory to skip the PlaceholderMode check when configuring options.
198208
var options = _optionsFactory.Create(ScriptApplicationHostOptionsSetup.SkipPlaceholder);
209+
RunFromPackageContext pkgContext = assignmentContext.GetRunFromPkgContext();
199210

200-
var zipPath = assignmentContext.ZipUrl;
211+
var zipPath = pkgContext.Url;
201212
if (!string.IsNullOrEmpty(zipPath))
202213
{
203214
// download zip and extract
204215
var zipUri = new Uri(zipPath);
205-
var filePath = await DownloadAsync(zipUri);
216+
string filePath = null;
217+
218+
if (pkgContext.IsScmRunFromPackage())
219+
{
220+
bool blobExists = await pkgContext.BlobExistsAsync(_logger);
221+
if (blobExists)
222+
{
223+
filePath = await DownloadAsync(zipUri);
224+
}
225+
else
226+
{
227+
return;
228+
}
229+
}
230+
else
231+
{
232+
filePath = await DownloadAsync(zipUri);
233+
}
234+
206235
UnpackPackage(filePath, options.ScriptPath);
207236

208237
string bundlePath = Path.Combine(options.ScriptPath, "worker-bundle");

src/WebJobs.Script.WebHost/Models/HostAssignmentContext.cs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,31 @@ public class HostAssignmentContext
2424
[JsonProperty("MSISpecializationPayload")]
2525
public MSIContext MSIContext { get; set; }
2626

27-
public string ZipUrl
27+
public RunFromPackageContext GetRunFromPkgContext()
2828
{
29-
get
29+
if (Environment.ContainsKey(EnvironmentSettingNames.AzureWebsiteRunFromPackage))
3030
{
31-
if (Environment.ContainsKey(EnvironmentSettingNames.AzureWebsiteRunFromPackage))
32-
{
33-
return Environment[EnvironmentSettingNames.AzureWebsiteRunFromPackage];
34-
}
35-
else if (Environment.ContainsKey(EnvironmentSettingNames.AzureWebsiteAltZipDeployment))
36-
{
37-
return Environment[EnvironmentSettingNames.AzureWebsiteAltZipDeployment];
38-
}
39-
else if (Environment.ContainsKey(EnvironmentSettingNames.AzureWebsiteZipDeployment))
40-
{
41-
return Environment[EnvironmentSettingNames.AzureWebsiteZipDeployment];
42-
}
43-
else
44-
{
45-
return string.Empty;
46-
}
31+
return new RunFromPackageContext(EnvironmentSettingNames.AzureWebsiteRunFromPackage,
32+
Environment[EnvironmentSettingNames.AzureWebsiteRunFromPackage]);
33+
}
34+
else if (Environment.ContainsKey(EnvironmentSettingNames.AzureWebsiteAltZipDeployment))
35+
{
36+
return new RunFromPackageContext(EnvironmentSettingNames.AzureWebsiteAltZipDeployment,
37+
Environment[EnvironmentSettingNames.AzureWebsiteAltZipDeployment]);
38+
}
39+
else if (Environment.ContainsKey(EnvironmentSettingNames.AzureWebsiteZipDeployment))
40+
{
41+
return new RunFromPackageContext(EnvironmentSettingNames.AzureWebsiteZipDeployment,
42+
Environment[EnvironmentSettingNames.AzureWebsiteZipDeployment]);
43+
}
44+
else if (Environment.ContainsKey(EnvironmentSettingNames.ScmRunFromPackage))
45+
{
46+
return new RunFromPackageContext(EnvironmentSettingNames.ScmRunFromPackage,
47+
Environment[EnvironmentSettingNames.ScmRunFromPackage]);
48+
}
49+
else
50+
{
51+
return new RunFromPackageContext(string.Empty, string.Empty);
4752
}
4853
}
4954

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the MIT License. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Threading.Tasks;
6+
using Microsoft.Extensions.Logging;
7+
using Microsoft.WindowsAzure.Storage.Blob;
8+
9+
namespace Microsoft.Azure.WebJobs.Script.WebHost.Models
10+
{
11+
public class RunFromPackageContext
12+
{
13+
public RunFromPackageContext(string envVarName, string url)
14+
{
15+
EnvironmentVariableName = envVarName;
16+
Url = url;
17+
}
18+
19+
public string EnvironmentVariableName { get; set; }
20+
21+
public string Url { get; set; }
22+
23+
public bool IsScmRunFromPackage()
24+
{
25+
return string.Equals(EnvironmentVariableName, EnvironmentSettingNames.ScmRunFromPackage,
26+
StringComparison.OrdinalIgnoreCase);
27+
}
28+
29+
public async Task<bool> BlobExistsAsync(ILogger logger)
30+
{
31+
bool exists = false;
32+
await Utility.InvokeWithRetriesAsync(async () =>
33+
{
34+
try
35+
{
36+
CloudBlockBlob blob = new CloudBlockBlob(new Uri(Url));
37+
exists = await blob.ExistsAsync();
38+
}
39+
catch (Exception e)
40+
{
41+
logger.LogError(e, $"Failed to check if zip url blob exists");
42+
throw;
43+
}
44+
}, maxRetries: 2, retryInterval: TimeSpan.FromSeconds(0.3));
45+
46+
return exists;
47+
}
48+
}
49+
}

src/WebJobs.Script/Environment/EnvironmentExtensions.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,19 @@ public static bool IsZipDeployment(this IEnvironment environment)
7070
// Run From Package app setting exists
7171
return IsValidZipSetting(environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteZipDeployment)) ||
7272
IsValidZipSetting(environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteAltZipDeployment)) ||
73-
IsValidZipSetting(environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteRunFromPackage));
73+
IsValidZipSetting(environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteRunFromPackage)) ||
74+
IsValidZipUrl(environment.GetEnvironmentVariable(EnvironmentSettingNames.ScmRunFromPackage));
7475
}
7576

76-
private static bool IsValidZipSetting(string appSetting)
77+
public static bool IsValidZipSetting(string appSetting)
7778
{
7879
// valid values are 1 or an absolute URI
79-
return string.Equals(appSetting, "1") || Uri.TryCreate(appSetting, UriKind.Absolute, out Uri result);
80+
return string.Equals(appSetting, "1") || IsValidZipUrl(appSetting);
81+
}
82+
83+
public static bool IsValidZipUrl(string appSetting)
84+
{
85+
return Uri.TryCreate(appSetting, UriKind.Absolute, out Uri result);
8086
}
8187

8288
public static bool IsAppServiceWindowsEnvironment(this IEnvironment environment)

src/WebJobs.Script/Environment/EnvironmentSettingNames.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ public static class EnvironmentSettingNames
5656
public const string AzureWebsiteRunFromPackage = "WEBSITE_RUN_FROM_PACKAGE";
5757
public const string RegionName = "REGION_NAME";
5858

59+
// handling server side builds
60+
public const string ScmRunFromPackage = "SCM_RUN_FROM_PACKAGE";
61+
5962
public const string LinuxAzureAppServiceStorage = "WEBSITES_ENABLE_APP_SERVICE_STORAGE";
6063
public const string CoreToolsEnvironment = "FUNCTIONS_CORETOOLS_ENVIRONMENT";
6164
public const string RunningInContainer = "DOTNET_RUNNING_IN_CONTAINER";

test/WebJobs.Script.Tests.Integration/Host/StandbyManager/StandbyManagerE2ETests_Linux.cs

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,12 @@ private async Task Assign(string encryptionKey)
139139
var contentRoot = Path.Combine(Path.GetTempPath(), @"FunctionsTest");
140140
var sourcePath = Path.Combine(Directory.GetCurrentDirectory(), @"TestScripts\Node\HttpTrigger");
141141
var zipFilePath = Path.Combine(contentRoot, "content.zip");
142-
await CreateContentZip(contentRoot, zipFilePath, @"TestScripts\Node\HttpTrigger");
142+
await TestHelpers.CreateContentZip(contentRoot, zipFilePath, @"TestScripts\Node\HttpTrigger");
143143

144144
// upload the blob and get a SAS uri
145-
var sasUri = await CreateBlobSas(zipFilePath, "azure-functions-test", "appcontents.zip");
145+
var configuration = _httpServer.Host.Services.GetService<IConfiguration>();
146+
string connectionString = configuration.GetWebJobsConnectionString(ConnectionStringNames.Storage);
147+
var sasUri = await TestHelpers.CreateBlobSas(connectionString, zipFilePath, "azure-functions-test", "appcontents.zip");
146148

147149
// Now specialize the host by invoking assign
148150
var secretManager = _httpServer.Host.Services.GetService<ISecretManagerProvider>().Current;
@@ -166,45 +168,5 @@ private async Task Assign(string encryptionKey)
166168
var response = await _httpClient.SendAsync(request);
167169
Assert.Equal(HttpStatusCode.Accepted, response.StatusCode);
168170
}
169-
170-
private static async Task CreateContentZip(string contentRoot, string zipPath, params string[] copyDirs)
171-
{
172-
var contentTemp = Path.Combine(contentRoot, @"ZipContent");
173-
await FileUtility.DeleteDirectoryAsync(contentTemp, true);
174-
175-
foreach (var sourceDir in copyDirs)
176-
{
177-
var directoryName = Path.GetFileName(sourceDir);
178-
var targetPath = Path.Combine(contentTemp, directoryName);
179-
FileUtility.EnsureDirectoryExists(targetPath);
180-
var sourcePath = Path.Combine(Directory.GetCurrentDirectory(), sourceDir);
181-
FileUtility.CopyDirectory(sourcePath, targetPath);
182-
}
183-
184-
FileUtility.DeleteFileSafe(zipPath);
185-
ZipFile.CreateFromDirectory(contentTemp, zipPath);
186-
}
187-
188-
private async Task<Uri> CreateBlobSas(string filePath, string blobContainer, string blobName)
189-
{
190-
var configuration = _httpServer.Host.Services.GetService<IConfiguration>();
191-
string connectionString = configuration.GetWebJobsConnectionString(ConnectionStringNames.Storage);
192-
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
193-
var blobClient = storageAccount.CreateCloudBlobClient();
194-
var container = blobClient.GetContainerReference(blobContainer);
195-
await container.CreateIfNotExistsAsync();
196-
var blob = container.GetBlockBlobReference(blobName);
197-
await blob.UploadFromFileAsync(filePath);
198-
var policy = new SharedAccessBlobPolicy
199-
{
200-
SharedAccessStartTime = DateTime.UtcNow,
201-
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1),
202-
Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.List
203-
};
204-
var sas = blob.GetSharedAccessSignature(policy);
205-
var sasUri = new Uri(blob.Uri, sas);
206-
207-
return sasUri;
208-
}
209171
}
210172
}

0 commit comments

Comments
 (0)