Skip to content

Commit

Permalink
VCI-752: Virtocloud client (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
krankenbro authored Jan 9, 2024
1 parent 80f3246 commit ba3134f
Show file tree
Hide file tree
Showing 50 changed files with 15,167 additions and 8 deletions.
9 changes: 9 additions & 0 deletions VirtoCommerce.Build.sln
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 17.0.32112.339
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtoCommerce.Build", "src\VirtoCommerce.Build\VirtoCommerce.Build.csproj", "{826FB1DE-BF4F-4314-AA00-FC5BC7627D7F}"
ProjectSection(ProjectDependencies) = postProject
{46099661-167D-4212-AFBE-855179D6F67D} = {46099661-167D-4212-AFBE-855179D6F67D}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtoCommerce.Build.Tests", "src\VirtoCommerce.Build.Tests\VirtoCommerce.Build.Tests.csproj", "{9E6E4723-DBA4-4A4B-807D-F9184D792DCF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtoCloud.Client", "src\Virtocloud.Client\src\VirtoCloud.Client\VirtoCloud.Client.csproj", "{46099661-167D-4212-AFBE-855179D6F67D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -21,6 +26,10 @@ Global
{9E6E4723-DBA4-4A4B-807D-F9184D792DCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E6E4723-DBA4-4A4B-807D-F9184D792DCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E6E4723-DBA4-4A4B-807D-F9184D792DCF}.Release|Any CPU.Build.0 = Release|Any CPU
{46099661-167D-4212-AFBE-855179D6F67D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{46099661-167D-4212-AFBE-855179D6F67D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46099661-167D-4212-AFBE-855179D6F67D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46099661-167D-4212-AFBE-855179D6F67D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
147 changes: 139 additions & 8 deletions src/VirtoCommerce.Build/Cloud/Build.SaaS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,26 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Policy;
using System.Text.Json.Nodes;
using System.Text;
using System.Threading.Tasks;
using Cloud.Client;
using Cloud.Models;
using Microsoft.Build.Evaluation;
using Microsoft.TeamFoundation.Build.WebApi;
using Nuke.Common;
using Nuke.Common.IO;
using Nuke.Common.ProjectModel;
using Nuke.Common.Tooling;
using Nuke.Common.Tools.Docker;
using Nuke.Common.Tools.DotNet;
using Serilog;
using VirtoCommerce.Platform.Core.Common;
using Project = Nuke.Common.ProjectModel.Project;
using VirtoCloud.Client.Api;
using VirtoCloud.Client.Model;
using System.Net;
using System.Diagnostics;
using Microsoft.AspNetCore.Identity;

namespace VirtoCommerce.Build;

Expand Down Expand Up @@ -45,16 +52,23 @@ internal partial class Build

[Parameter("SaaS Portal")] public string CloudUrl { get; set; } = "https://portal.virtocommerce.cloud";
[Parameter("SaaS Token")] public string CloudToken { get; set; }
[Parameter("Path for the file with SaaS Token")] public string CloudTokenFile { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "vc-build", "cloud");
[Parameter("SaaS Auth Provider")] public string CloudAuthProvider { get; set; } = "GitHub";
[Parameter("App Project Name")] public string AppProject { get; set; }
[Parameter("Cloud Environment Name")] public string EnvironmentName { get; set; }
[Parameter("Cloud Environment Service Plan")] public string ServicePlan { get; set; }
[Parameter("Cloud Environment Cluster Name")] public string ClusterName { get; set; }
[Parameter("Cloud Environment Db Provider")] public string DbProvider { get; set; }
[Parameter("Cloud Environment Db Name")] public string DbName { get; set; }


[Parameter("Organization name", Name = "Organization")] public string SaaSOrganizationName { get; set; }

public Target WaitForStatus => _ => _
.Executes(async () =>
{
var isSuccess = false;
var cloudClient = new VirtoCloudClient(CloudUrl, CloudToken);
var cloudClient = new VirtoCloudClient(CloudUrl, await GetCloudTokenAsync());
for (var i = 0; i < AttemptsNumber; i++)
{
Log.Information($"Attempt #{i + 1}");
Expand All @@ -76,7 +90,7 @@ internal partial class Build
public Target SetEnvParameter => _ => _
.Executes(async () =>
{
var cloudClient = new VirtoCloudClient(CloudUrl, CloudToken);
var cloudClient = new VirtoCloudClient(CloudUrl, await GetCloudTokenAsync());
var env = await cloudClient.GetEnvironment(EnvironmentName, SaaSOrganizationName);

var envHelmParameters = env.Helm.Parameters;
Expand All @@ -91,7 +105,7 @@ internal partial class Build
public Target UpdateCloudEnvironment => _ => _
.Executes(async () =>
{
var cloudClient = new VirtoCloudClient(CloudUrl, CloudToken);
var cloudClient = new VirtoCloudClient(CloudUrl, await GetCloudTokenAsync());
var rawYaml = await File.ReadAllTextAsync(ArgoConfigFile);
await cloudClient.UpdateEnvironmentAsync(rawYaml, AppProject);
});
Expand Down Expand Up @@ -208,11 +222,11 @@ private static bool CheckAppServiceStatus(string expected, string actual)
AppsettingsPath = Path.Combine(platformDirectory, "appsettings.json");
});

public Target DeployImage => _ => _
public Target CloudDeploy => _ => _
.DependsOn(PrepareDockerContext, BuildAndPush)
.Executes(async () =>
{
var cloudClient = new VirtoCloudClient(CloudUrl, CloudToken);
var cloudClient = new VirtoCloudClient(CloudUrl, await GetCloudTokenAsync());
var env = await cloudClient.GetEnvironment(EnvironmentName, SaaSOrganizationName);

var envHelmParameters = env.Helm.Parameters;
Expand All @@ -222,4 +236,121 @@ private static bool CheckAppServiceStatus(string expected, string actual)

await cloudClient.UpdateEnvironmentAsync(env);
});

public Target CloudAuth => _ => _
.Executes(async () =>
{
var port = "60123";
var listenerPrefix = $"http://localhost:{port}/";

var listener = new HttpListener() {
Prefixes = { listenerPrefix }
};
Log.Information("Start listening to {0}", listenerPrefix);
listener.Start();


Log.Information("Openning browser window");
var authUrl = $"{CloudUrl}/externalsignin?authenticationType={CloudAuthProvider}&returnUrl=/api/saas/token/{port}";
Process.Start(new ProcessStartInfo(authUrl) { UseShellExecute = true });

var context = await listener.GetContextAsync();
context.Response.StatusCode = (int)HttpStatusCode.OK;
var apiKey = context.Request.QueryString["apiKey"];
context.Response.Close(Encoding.UTF8.GetBytes("You can close this browser tab now."), false);

SaveCloudToken(apiKey);
});

private async Task<string> GetCloudTokenAsync()
{
if (!string.IsNullOrEmpty(CloudToken))
{
return CloudToken;
}

if (File.Exists(CloudTokenFile))
{
return await File.ReadAllTextAsync(CloudTokenFile);
}

Assert.Fail("Parameter CloudToken is required.");
return string.Empty; // for sonar
}

private void SaveCloudToken(string token)
{
FileSystemTasks.EnsureExistingDirectory(Path.GetDirectoryName(CloudTokenFile));
File.WriteAllText(CloudTokenFile, token);
}

public Target CloudDown => _ => _
.Requires(() => EnvironmentName)
.Executes(async () =>
{
var cloudClient = CreateVirtocloudClient(CloudUrl, await GetCloudTokenAsync());
var envName = EnvironmentName;
if (!string.IsNullOrWhiteSpace(AppProject))
{
envName = $"{AppProject}-{EnvironmentName}";
}
await cloudClient.EnvironmentsDeleteAsync(new List<string> { envName });
});

public Target CloudEnvList => _ => _
.Executes(async () =>
{
var cloudClient = CreateVirtocloudClient(CloudUrl, await GetCloudTokenAsync());
var envList = await cloudClient.EnvironmentsListAsync();
Log.Information("There are {0} environments.", envList.Count);
foreach ( var env in envList)
{
Log.Information("{0} - {1}", env.MetadataName, env.Status);
}
});

public Target CloudEnvRestart => _ => _
.Requires(() => EnvironmentName)
.Executes(async () =>
{
var cloudClient = CreateVirtocloudClient(CloudUrl, await GetCloudTokenAsync());
var env = await cloudClient.EnvironmentsGetEnvironmentAsync(EnvironmentName);
Assert.NotNull(env, $"Environment {EnvironmentName} not found.");

var parameterName = "platform.system.reload";
env.Helm.Parameters[parameterName] = DateTime.Now.ToString();

await cloudClient.EnvironmentsUpdateAsync(env);
});

public Target CloudInit => _ => _
.Before(PrepareDockerContext, BuildAndPush, CloudDeploy)
.Requires(() => ServicePlan, () => EnvironmentName)
.Executes(async () =>
{
var model = new NewEnvironmentModel
{
Name = EnvironmentName,
AppProjectId = AppProject,
ServicePlan = ServicePlan,
Cluster = ClusterName,
DbProvider = DbProvider,
DbName = DbName
};

var cloudClient = CreateVirtocloudClient(CloudUrl, await GetCloudTokenAsync());
await cloudClient.EnvironmentsCreateAsync(model);
});

public Target CloudUp => _ => _
.DependsOn(CloudInit, CloudDeploy);

private static ISaaSDeploymentApi CreateVirtocloudClient(string url, string token)
{
var config = new VirtoCloud.Client.Client.Configuration();
config.BasePath = url;
config.AccessToken = token;
config.DefaultHeaders.Add("api_key", token);
return new SaaSDeploymentApi(config);
}
}
4 changes: 4 additions & 0 deletions src/VirtoCommerce.Build/VirtoCommerce.Build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,8 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Virtocloud.Client\src\VirtoCloud.Client\VirtoCloud.Client.csproj" />
</ItemGroup>
</Project>
Loading

0 comments on commit ba3134f

Please sign in to comment.