Skip to content
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

[K8SE] Add BetaMetadata options for 'feature/k8se' #136

Merged
merged 6 commits into from
Sep 30, 2020
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
19 changes: 19 additions & 0 deletions Kudu.Contracts/Deployment/BuildMetadata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;

namespace Kudu.Contracts.Deployment
{
public class BuildMetadata
{
[JsonProperty(PropertyName = "appName")]
public string AppName;

[JsonProperty(PropertyName = "buildVersion")]
public string BuildVersion;

[JsonProperty(PropertyName = "appSubPath")]
public string AppSubPath;
}
}
3 changes: 3 additions & 0 deletions Kudu.Contracts/Deployment/DeploymentInfoBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,8 @@ public bool IsValid()
// won't update until after a process restart. Therefore, we copy the needed
// files into a separate folders and run sync triggers from there.
public string SyncFunctionsTriggersPath { get; set; } = null;

// Used to set Publish Endpoint context
public bool ShouldBuildArtifact { get; set; }
}
}
5 changes: 2 additions & 3 deletions Kudu.Core/Deployment/DeploymentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using Kudu.Contracts.Infrastructure;
using Kudu.Contracts.Settings;
using Kudu.Contracts.Tracing;
using Kudu.Core.Functions;
using Kudu.Core.Helpers;
using Kudu.Core.Hooks;
using Kudu.Core.Infrastructure;
Expand Down Expand Up @@ -286,7 +285,7 @@ public async Task DeployAsync(
}

string appName = _environment.SiteRootPath.Replace("/home/apps/", "").Split("/")[0];
DockerContainerRestartTrigger.RequestContainerRestart(_environment, RestartTriggerReason, deploymentInfo.RepositoryUrl);
DockerContainerRestartTrigger.RequestContainerRestart(_environment, RestartTriggerReason, deploymentInfo.RepositoryUrl, deploymentInfo.TargetPath);
logger.Log($"Deployment Pod Rollout Started! Use kubectl watch deplotment {appName} to monitor the rollout status");
}
}
Expand Down Expand Up @@ -645,7 +644,7 @@ private async Task Build(
{
using (tracer.Step("Determining deployment builder"))
{
builder = _builderFactory.CreateBuilder(tracer, innerLogger, perDeploymentSettings, repository);
builder = _builderFactory.CreateBuilder(tracer, innerLogger, perDeploymentSettings, repository, deploymentInfo);
deploymentAnalytics.ProjectType = builder.ProjectType;
tracer.Trace("Builder is {0}", builder.GetType().Name);
}
Expand Down
8 changes: 8 additions & 0 deletions Kudu.Core/Deployment/Generator/OryxBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,15 @@ public override Task Build(DeploymentContext context)
{
PreOryxBuild(context);

args.Flags = BuildOptimizationsFlags.UseExpressBuild;

string buildCommand = args.GenerateOryxBuildCommand(context, environment);
RunCommand(context, buildCommand, false, "Running oryx build...");

//
// Run express build setups if needed
//

if (args.Flags == BuildOptimizationsFlags.UseExpressBuild)
{
if (FunctionAppHelper.LooksLikeFunctionApp())
Expand All @@ -73,6 +77,10 @@ public override Task Build(DeploymentContext context)
appServiceExpressBuilder.SetupExpressBuilderArtifacts(context.OutputPath, context, args);
}
}
else
{
Console.WriteLine("No Express :(");
}
}
return Task.CompletedTask;
}
Expand Down
11 changes: 8 additions & 3 deletions Kudu.Core/Deployment/Generator/SiteBuilderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,14 @@ private IEnvironment GetEnvironment(IHttpContextAccessor accessor, IEnvironment
return _environment;
}

public ISiteBuilder CreateBuilder(ITracer tracer, ILogger logger, IDeploymentSettingsManager settings, IRepository repository)
public ISiteBuilder CreateBuilder(ITracer tracer, ILogger logger, IDeploymentSettingsManager settings, IRepository repository, DeploymentInfoBase deploymentInfo)
{

string repositoryRoot = _environment.RepositoryPath;
if (!string.IsNullOrEmpty(repository.RepositoryPath))
{
repositoryRoot = repository.RepositoryPath;
}

// Use the cached vs projects file finder for: a. better performance, b. ignoring solutions/projects under node_modules
var fileFinder = new CachedVsProjectsFileFinder(repository);
Expand Down Expand Up @@ -75,14 +80,14 @@ public ISiteBuilder CreateBuilder(ITracer tracer, ILogger logger, IDeploymentSet
return new RunFromZipSiteBuilder();
}

if (!settings.DoBuildDuringDeployment() && repository.RepositoryType != RepositoryType.Git)
if (!deploymentInfo.ShouldBuildArtifact && !settings.DoBuildDuringDeployment() && repository.RepositoryType != RepositoryType.Git)
{
var projectPath = !String.IsNullOrEmpty(targetProjectPath) ? targetProjectPath : repositoryRoot;
return new BasicBuilder(_environment, settings, _propertyProvider, repositoryRoot, projectPath);
}

string enableOryxBuild = System.Environment.GetEnvironmentVariable("ENABLE_ORYX_BUILD");
if (!string.IsNullOrEmpty(enableOryxBuild))
if (!string.IsNullOrEmpty(enableOryxBuild) && (deploymentInfo.ShouldBuildArtifact || settings.DoBuildDuringDeployment()))
{
if (StringUtils.IsTrueLike(enableOryxBuild))
{
Expand Down
2 changes: 1 addition & 1 deletion Kudu.Core/Deployment/ISiteBuilderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ namespace Kudu.Core.Deployment
{
public interface ISiteBuilderFactory
{
ISiteBuilder CreateBuilder(ITracer tracer, ILogger logger, IDeploymentSettingsManager settings, IRepository fileFinder);
ISiteBuilder CreateBuilder(ITracer tracer, ILogger logger, IDeploymentSettingsManager settings, IRepository fileFinder, DeploymentInfoBase deploymentInfo);
}
}
4 changes: 2 additions & 2 deletions Kudu.Core/Deployment/Oryx/AppServiceOryxArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ public AppServiceOryxArguments(IEnvironment environment)

if (K8SEDeploymentHelper.IsK8SEEnvironment())
{
Console.WriteLine("Oryx App Name : " + environment.K8SEAppName);
this.AppName = environment.K8SEAppName;

// K8SE TODO: Inject Environment
Expand Down Expand Up @@ -184,12 +183,13 @@ public string GenerateOryxBuildCommand(DeploymentContext context, IEnvironment e
{
// 10-LTS, 12-LTS should use versions 10, 12 etc
// Oryx Builder uses lts for major versions
Version = Version.Replace("LTS", "").Replace("-", "");
Version = Version.Replace("LTS", "").Replace("lts", "").Replace("-", "");
if (string.IsNullOrEmpty(Version))
{
// Current LTS
Version = "10";
}
OryxArgumentsHelper.AddLanguageVersion(args, Version);
}
break;
case Framework.Python:
Expand Down
14 changes: 11 additions & 3 deletions Kudu.Core/Infrastructure/DockerContainerRestartTrigger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
using System.Globalization;
using System.IO;
using System.Linq;
using Kudu.Contracts.Deployment;
using Kudu.Core.Functions;
using Kudu.Core.Helpers;
using Kudu.Core.K8SE;
using Newtonsoft.Json;

namespace Kudu.Core.Infrastructure
{
Expand All @@ -25,22 +27,28 @@ public static class DockerContainerRestartTrigger
"The last modification Kudu made to this file was at {0}, for the following reason: {1}.",
System.Environment.NewLine);

public static void RequestContainerRestart(IEnvironment environment, string reason, string repositoryUrl = null)
public static void RequestContainerRestart(IEnvironment environment, string reason, string repositoryUrl = null, string appSubPath = "")
{
if (K8SEDeploymentHelper.IsK8SEEnvironment())
{
string appName = environment.SiteRootPath.Replace("/home/apps/", "").Split("/")[0];
string buildNumber = environment.CurrId;
var functionTriggers = FunctionTriggerProvider.GetFunctionTriggers<IEnumerable<ScaleTrigger>>("keda", repositoryUrl);
var buildMetadata = new BuildMetadata()
{
AppName = appName,
BuildVersion = buildNumber,
AppSubPath = appSubPath
};

//Only for function apps functionTriggers will be non-null/non-empty
if (functionTriggers?.Any() == true)
{
K8SEDeploymentHelper.UpdateFunctionAppTriggers(appName, functionTriggers, $"{buildNumber}|{appName}");
K8SEDeploymentHelper.UpdateFunctionAppTriggers(appName, functionTriggers, buildMetadata);
}
else
{
K8SEDeploymentHelper.UpdateBuildNumber(appName, buildNumber);
K8SEDeploymentHelper.UpdateBuildNumber(appName, buildMetadata);
}

return;
Expand Down
47 changes: 36 additions & 11 deletions Kudu.Core/K8SE/K8SEDeploymentHelper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Kudu.Contracts.Tracing;
using Kudu.Contracts.Deployment;
using Kudu.Contracts.Tracing;
using Kudu.Core.Deployment;
using Kudu.Core.Functions;
using Microsoft.AspNetCore.Http;
Expand All @@ -8,6 +9,7 @@
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Web;

namespace Kudu.Core.K8SE
{
Expand Down Expand Up @@ -44,25 +46,43 @@ public static string GetLinuxFxVersion(string appName)
/// </summary>
/// <param name="appName"></param>
/// <returns></returns>
public static void UpdateBuildNumber(string appName, string buildNumber)
public static void UpdateBuildNumber(string appName, BuildMetadata buildMetadata)
{
var buildPatchJson = $"\"{HttpUtility.JavaScriptStringEncode(JsonConvert.SerializeObject(buildMetadata)).Replace("\\","\\\\")}\"";

var cmd = new StringBuilder();
BuildCtlArgumentsHelper.AddBuildCtlCommand(cmd, "update");
BuildCtlArgumentsHelper.AddAppNameArgument(cmd, appName);
BuildCtlArgumentsHelper.AddAppPropertyArgument(cmd, "buildVersion");
BuildCtlArgumentsHelper.AddAppPropertyValueArgument(cmd, buildNumber);
BuildCtlArgumentsHelper.AddAppPropertyArgument(cmd, "buildMetadata");
BuildCtlArgumentsHelper.AddAppPropertyValueArgument(cmd, buildPatchJson);
RunBuildCtlCommand(cmd.ToString(), "Updating build version...");
}

/// <summary>
/// Updates the Image Tag of the K8SE custom container app
/// </summary>
/// <param name="appName"></param>
/// <param name="imageTag">container image tag of the format registry/<image>:<tag></param>
/// <returns></returns>
public static void UpdateImageTag(string appName, string imageTag)
{
var cmd = new StringBuilder();
BuildCtlArgumentsHelper.AddBuildCtlCommand(cmd, "update");
BuildCtlArgumentsHelper.AddAppNameArgument(cmd, appName);
BuildCtlArgumentsHelper.AddAppPropertyArgument(cmd, "appImage");
BuildCtlArgumentsHelper.AddAppPropertyValueArgument(cmd, imageTag);
RunBuildCtlCommand(cmd.ToString(), "Updating image tag...");
}

/// <summary>
/// Updates the triggers for the function apps
/// </summary>
/// <param name="appName">The app name to update</param>
/// <param name="functionTriggers">The IEnumerable<ScaleTrigger></param>
/// <param name="buildNumber">Build number to update</param>
public static void UpdateFunctionAppTriggers(string appName, IEnumerable<ScaleTrigger> functionTriggers, string buildNumber)
public static void UpdateFunctionAppTriggers(string appName, IEnumerable<ScaleTrigger> functionTriggers, BuildMetadata buildMetadata)
{
var functionAppPatchJson = GetFunctionAppPatchJson(functionTriggers, buildNumber);
var functionAppPatchJson = GetFunctionAppPatchJson(functionTriggers, buildMetadata);
if (string.IsNullOrEmpty(functionAppPatchJson))
{
return;
Expand Down Expand Up @@ -118,19 +138,24 @@ public static string GetAppName(HttpContext context)
// K8SE TODO: move this to resource map
throw new InvalidOperationException("Couldn't recognize AppName");
}

Console.WriteLine("AppName :::::::: " + appName);

return appName;
}

private static string GetFunctionAppPatchJson(IEnumerable<ScaleTrigger> functionTriggers, string buildNumber)
private static string GetFunctionAppPatchJson(IEnumerable<ScaleTrigger> functionTriggers, BuildMetadata buildMetadata)
{
if (functionTriggers == null || !functionTriggers.Any())
{
return null;
}

if (buildMetadata == null )
{
return null;
}

var buildPatchJson = JsonConvert.SerializeObject(buildMetadata);
var buildmetaJsonString = JsonConvert.ToString(buildPatchJson);

var patchAppJson = new PatchAppJson
{
PatchSpec = new PatchSpec
Expand All @@ -143,7 +168,7 @@ private static string GetFunctionAppPatchJson(IEnumerable<ScaleTrigger> function
{
PackageRef = new PackageReference
{
BuildVersion = buildNumber
BuildVersion = buildmetaJsonString
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions Kudu.Services.Web/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ public void ConfigureServices(IServiceCollection services)
services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit = 52428800;
options.ValueCountLimit = 500000;
options.KeyLengthLimit = 500000;
options.ValueCountLimit = 1000000;
options.KeyLengthLimit = 1000000;
});

services.AddRouteAnalyzer();
Expand Down Expand Up @@ -518,6 +518,8 @@ public void Configure(IApplicationBuilder app,
new {controller = "Deployment", action = "GetLogEntry"});
routes.MapHttpRouteDual("one-deployment-log-details", "deployments/{id}/log/{logId}",
new {controller = "Deployment", action = "GetLogEntryDetails"});
routes.MapHttpRouteDual("update-container-tag", "app/update",
new { controller = "Deployment", action = "UpdateContainerTag" });

// Deployment script
routes.MapRoute("get-deployment-script", "api/deploymentscript",
Expand Down
Loading