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

Add URL support in api/zipdeploy endpoint #35

Merged
merged 2 commits into from
May 21, 2019
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
3 changes: 3 additions & 0 deletions Kudu.Core/Deployment/ZipDeploymentInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,8 @@ public override IRepository GetRepository()

// This is used if the deployment is Run-From-Zip
public string ZipName { get; set; }

// This is used when getting the zipfile from the zipURL
public string ZipURL { get; set; }
}
}
3 changes: 3 additions & 0 deletions Kudu.Services.Web/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,9 @@ public void Configure(IApplicationBuilder app,
routes.MapRoute("zip-push-deploy", "api/zipdeploy",
new {controller = "PushDeployment", action = "ZipPushDeploy"},
new {verb = new HttpMethodRouteConstraint("POST")});
routes.MapRoute("zip-push-deploy-url", "api/zipdeploy",
new {controller = "PushDeployment", action = "ZipPushDeployViaUrl"},
new {verb = new HttpMethodRouteConstraint("PUT")});
routes.MapRoute("zip-war-deploy", "api/wardeploy",
new {controller = "PushDeployment", action = "WarPushDeploy"},
new {verb = new HttpMethodRouteConstraint("POST")});
Expand Down
98 changes: 95 additions & 3 deletions Kudu.Services/Deployment/PushDeploymentController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Newtonsoft.Json.Linq;
using System.Net.Http;

namespace Kudu.Services.Deployment
{
Expand Down Expand Up @@ -71,7 +73,8 @@ public async Task<IActionResult> ZipPushDeploy(
DoFullBuildByDefault = false,
Author = author,
AuthorEmail = authorEmail,
Message = message
Message = message,
ZipURL = null
};

if (_settings.RunFromLocalZip())
Expand All @@ -92,6 +95,41 @@ public async Task<IActionResult> ZipPushDeploy(
}
}

[HttpPut]
public async Task<IActionResult> ZipPushDeployViaUrl(
[FromBody] JObject requestJson,
[FromQuery] bool isAsync = false,
[FromQuery] string author = null,
[FromQuery] string authorEmail = null,
[FromQuery] string deployer = DefaultDeployer,
[FromQuery] string message = DefaultMessage)
{
using (_tracer.Step("ZipPushDeployViaUrl"))
{
string zipUrl = GetZipURLFromJSON(requestJson);

var deploymentInfo = new ZipDeploymentInfo(_environment, _traceFactory)
{
AllowDeploymentWhileScmDisabled = true,
Deployer = deployer,
IsContinuous = false,
AllowDeferredDeployment = false,
IsReusable = false,
TargetChangeset =
DeploymentManager.CreateTemporaryChangeSet(message: "Deploying from pushed zip file"),
CommitId = null,
RepositoryType = RepositoryType.None,
Fetch = LocalZipHandler,
DoFullBuildByDefault = false,
Author = author,
AuthorEmail = authorEmail,
Message = message,
ZipURL = zipUrl,
};
return await PushDeployAsync(deploymentInfo, isAsync, HttpContext);
}
}


[HttpPost]
[DisableRequestSizeLimit]
Expand Down Expand Up @@ -130,13 +168,39 @@ public async Task<IActionResult> WarPushDeploy(
DoFullBuildByDefault = false,
Author = author,
AuthorEmail = authorEmail,
Message = message
Message = message,
ZipURL = null
};

return await PushDeployAsync(deploymentInfo, isAsync, HttpContext);
}
}

private string GetZipURLFromJSON(JObject requestObject)
{
using (_tracer.Step("Reading the zip URL from the request JSON"))
{
try
{
string packageUri = requestObject.Value<string>("packageUri");
if (string.IsNullOrEmpty(packageUri))
{
throw new ArgumentException("Request body does not contain packageUri");
}

Uri zipUri = null;
if (!Uri.TryCreate(packageUri, UriKind.Absolute, out zipUri))
{
throw new ArgumentException("Malformed packageUri");
}
return packageUri;
}
catch (Exception ex)
{
_tracer.TraceError(ex, "Error reading the URL from the JSON {0}", requestObject.ToString());
throw;
}
}
}

private async Task<IActionResult> PushDeployAsync(ZipDeploymentInfo deploymentInfo, bool isAsync,
HttpContext context)
Expand All @@ -162,6 +226,34 @@ private async Task<IActionResult> PushDeployAsync(ZipDeploymentInfo deploymentIn
}
}
}
else if (deploymentInfo.ZipURL != null)
{
using (_tracer.Step("Writing zip file from packageUri to {0}", zipFilePath))
{
using (var httpClient = new HttpClient())
using (var fileStream = new FileStream(zipFilePath,
FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
{
var zipUrlRequest = new HttpRequestMessage(HttpMethod.Get, deploymentInfo.ZipURL);
var zipUrlResponse = await httpClient.SendAsync(zipUrlRequest);

try
{
zipUrlResponse.EnsureSuccessStatusCode();
}
catch (HttpRequestException hre)
{
_tracer.TraceError(hre, "Failed to get file from packageUri {0}", deploymentInfo.ZipURL);
throw;
}

using (var content = await zipUrlResponse.Content.ReadAsStreamAsync())
{
await content.CopyToAsync(fileStream);
}
}
}
}
else
{
using (var file = System.IO.File.Create(zipFilePath))
Expand Down