Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/microsoft/TeamCloud
Browse files Browse the repository at this point in the history
  • Loading branch information
colbylwilliams committed Mar 30, 2020
2 parents a30f0e3 + 920f76c commit d5103de
Show file tree
Hide file tree
Showing 19 changed files with 167 additions and 23 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci_package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ jobs:
working-directory: ${{ env.SOURCE_DIRECTORY }}

- name: Publish NuGet Packages to MyGet
run: dotnet nuget push '*.nupkg' --api-key '${{ secrets.MYGET_DEV_TOKEN }}' --source 'https://www.myget.org/F/teamcloud-dev/api/v2/package' --symbol-api-key '${{ secrets.MYGET_DEV_TOKEN }}' --symbol-source 'https://www.myget.org/F/teamcloud-dev/symbols/api/v2/package' --skip-duplicate
run: dotnet nuget push '**/*.nupkg' --api-key '${{ secrets.MYGET_DEV_TOKEN }}' --source 'https://www.myget.org/F/teamcloud-dev/api/v2/package' --symbol-api-key '${{ secrets.MYGET_DEV_TOKEN }}' --symbol-source 'https://www.myget.org/F/teamcloud-dev/symbols/api/v2/package' --skip-duplicate
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ ASALocalRun/
local/
docs/local/
*.DS_Store
# src/TeamCloud.Orchestrator/local.settings.json
# appsettings.json
.vscode/TeamCloud.code-workspace

# Config files with default values
**/local.settings.json
**/appsettings.json

24 changes: 20 additions & 4 deletions src/TeamCloud.API/Services/Orchestrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,34 @@ private void SetResultLinks(ICommandResult commandResult, Guid? projectId)
{
commandResult.Links.Add("location", new Uri(baseUrl, "api/config").ToString());
}
else if (commandResult is ICommandResult<User> commandResultUserWithProject && projectId.HasValue)
else if (IsDeleteCommandResult(commandResult))
{
commandResult.Links.Add("location", new Uri(baseUrl, $"api/projects/{projectId}/users/{commandResultUserWithProject.Result?.Id}").ToString());
return;
}
else if (commandResult is ICommandResult<User> commandResultUserWithoutProject)
else if (commandResult is ICommandResult<User> userCommandResult)
{
commandResult.Links.Add("location", new Uri(baseUrl, $"api/users/{commandResultUserWithoutProject.Result?.Id}").ToString());
if (userCommandResult.Result is null)
return;

if (projectId.HasValue)
{
commandResult.Links.Add("location", new Uri(baseUrl, $"api/projects/{projectId}/users/{userCommandResult.Result.Id}").ToString());
}
else
{
commandResult.Links.Add("location", new Uri(baseUrl, $"api/users/{userCommandResult.Result.Id}").ToString());
}
}
else if (projectId.HasValue)
{
commandResult.Links.Add("location", new Uri(baseUrl, "api/projects/{projectId}").ToString());
}

static bool IsDeleteCommandResult(ICommandResult result)
=> result is OrchestratorProjectDeleteCommandResult
|| result is OrchestratorProjectUserDeleteCommandResult
|| result is OrchestratorProviderDeleteCommandResult
|| result is OrchestratorTeamCloudUserDeleteCommandResult;
}

public async Task<ICommandResult> QueryAsync(Guid commandId, Guid? projectId)
Expand Down
3 changes: 3 additions & 0 deletions src/TeamCloud.API/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ public void ConfigureServices(IServiceCollection services)
ConfigureAuthentication(services);
ConfigureAuthorization(services);

services
.AddApplicationInsightsTelemetry();

services
.AddMvc(options =>
{
Expand Down
1 change: 1 addition & 0 deletions src/TeamCloud.API/TeamCloud.API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<PackageReference Include="FluentValidation" Version="8.6.2" />
<PackageReference Include="FluentValidation.AspNetCore" Version="8.6.2" />
<PackageReference Include="Flurl.Http" Version="2.4.2" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.12.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="3.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.2" />
<PackageReference Include="Microsoft.Azure.AppConfiguration.AspNetCore" Version="3.0.0" />
Expand Down
3 changes: 3 additions & 0 deletions src/TeamCloud.API/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"ApplicationInsights": {
"InstrumentationKey": "00000000-0000-0000-0000-000000000000"
},
"ConnectionStrings": {
"ConfigurationService": "file:///C:/Users/%USERNAME%/Desktop/ConfigurationService.json"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ public interface IAzureDeploymentArtifactsProvider

Task<string> DownloadArtifactAsync(Guid deploymentId, string artifactName);
}

public abstract class AzureDeploymentArtifactsProvider : IAzureDeploymentArtifactsProvider
{
public abstract Task<string> DownloadArtifactAsync(Guid deploymentId, string artifactName);

public abstract Task<IAzureDeploymentArtifactsContainer> UploadArtifactsAsync(Guid deploymentId, AzureDeploymentTemplate azureDeploymentTemplate);
}
}
2 changes: 0 additions & 2 deletions src/TeamCloud.Azure.Deployment/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
* Licensed under the MIT License.
*/



// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

namespace TeamCloud.Azure.Deployment.Providers
{
public class AzureStorageArtifactsProvider : IAzureDeploymentArtifactsProvider
public class AzureStorageArtifactsProvider : AzureDeploymentArtifactsProvider
{
private const string DEPLOYMENT_CONTAINER_NAME = "deployments";

Expand All @@ -32,7 +32,7 @@ public AzureStorageArtifactsProvider(IAzureStorageArtifactsOptions azureStorageA
.CreateCloudBlobClient().GetContainerReference(DEPLOYMENT_CONTAINER_NAME));
}

public async Task<IAzureDeploymentArtifactsContainer> UploadArtifactsAsync(Guid deploymentId, AzureDeploymentTemplate azureDeploymentTemplate)
public override async Task<IAzureDeploymentArtifactsContainer> UploadArtifactsAsync(Guid deploymentId, AzureDeploymentTemplate azureDeploymentTemplate)
{
if (azureDeploymentTemplate is null)
throw new ArgumentNullException(nameof(azureDeploymentTemplate));
Expand Down Expand Up @@ -101,7 +101,7 @@ private async Task<string> CreateSasTokenAsync()
return deploymentContainer.Value.GetSharedAccessSignature(adHocPolicy, null);
}

public async Task<string> DownloadArtifactAsync(Guid deploymentId, string artifactName)
public override async Task<string> DownloadArtifactAsync(Guid deploymentId, string artifactName)
{
if (!deploymentContainer.IsValueCreated)
await deploymentContainer.Value.CreateIfNotExistsAsync().ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/

using System;
using System.Linq;
using System.Threading.Tasks;

namespace TeamCloud.Azure.Deployment.Providers
{
public sealed class NullStorageArtifactsProvider : AzureDeploymentArtifactsProvider
{
public static readonly IAzureDeploymentArtifactsProvider Instance = new NullStorageArtifactsProvider();

public override Task<string> DownloadArtifactAsync(Guid deploymentId, string artifactName)
=> Task.FromResult(default(string));

public override Task<IAzureDeploymentArtifactsContainer> UploadArtifactsAsync(Guid deploymentId, AzureDeploymentTemplate azureDeploymentTemplate)
=> (azureDeploymentTemplate?.LinkedTemplates.Any() ?? false)
? Task.FromException<IAzureDeploymentArtifactsContainer>(new NotSupportedException($"{nameof(NullStorageArtifactsProvider)} doesn't support linked templates or artifacts"))
: Task.FromResult<IAzureDeploymentArtifactsContainer>(Container.Instance);

internal sealed class Container : IAzureDeploymentArtifactsContainer
{
public static readonly IAzureDeploymentArtifactsContainer Instance = new Container();

public string Location => default(string);

public string Token => default(string);
}
}
}
21 changes: 20 additions & 1 deletion src/TeamCloud.Azure.Resources/AzureResourceGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TeamCloud.Azure.Deployment;
using TeamCloud.Azure.Deployment.Providers;
using TeamCloud.Azure.Resources.Templates;

namespace TeamCloud.Azure.Resources
{
Expand Down Expand Up @@ -34,13 +37,29 @@ public override Task<bool> ExistsAsync()

public override async Task DeleteAsync(bool deleteLocks = false)
{
var cleanupTask = CleanupAsync();

if (deleteLocks)
{
await DeleteLocksAsync(true)
.ConfigureAwait(false);
}

await base.DeleteAsync(false)
await cleanupTask
.ContinueWith(task => base.DeleteAsync(false), TaskScheduler.Current)
.ConfigureAwait(false);
}

private async Task CleanupAsync()
{
var azureDeploymentService = new AzureDeploymentService(null, AzureResourceService.AzureSessionService, NullStorageArtifactsProvider.Instance);

var azureDeployment = await azureDeploymentService
.DeployResourceGroupTemplateAsync(new AzureResourceGroupCleanupTemplate(), ResourceId.SubscriptionId, ResourceId.ResourceGroup, true)
.ConfigureAwait(false);

await azureDeployment
.WaitAsync()
.ConfigureAwait(false);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@
<FileVersion>0.0.0.0</FileVersion>
</PropertyGroup>

<ItemGroup>
<None Remove="Templates\AzureResourceGroupCleanupTemplate.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Templates\AzureResourceGroupCleanupTemplate.json" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\LICENSE">
<Pack>True</Pack>
Expand All @@ -32,6 +40,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\TeamCloud.Azure.Deployment\TeamCloud.Azure.Deployment.csproj" />
<ProjectReference Include="..\TeamCloud.Azure\TeamCloud.Azure.csproj" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/

using TeamCloud.Azure.Deployment.Templates;

namespace TeamCloud.Azure.Resources.Templates
{
public sealed class AzureResourceGroupCleanupTemplate : EmbeddedDeploymentTemplate
{ }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": { },
"variables": { },
"resources": [ ],
"outputs": { }
}
4 changes: 4 additions & 0 deletions src/TeamCloud.Http/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -21,6 +22,7 @@
using Microsoft.Extensions.DependencyInjection.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TeamCloud.Http.Telemetry;

namespace TeamCloud.Http
{
Expand All @@ -29,6 +31,8 @@ public static class Extensions
{
public static IServiceCollection AddTeamCloudHttp(this IServiceCollection services, Action<GlobalFlurlHttpSettings> configure = null)
{
services.AddSingleton<ITelemetryInitializer>(new TeamCloudTelemetryInitializer(Assembly.GetCallingAssembly()));

if (services.Any(sd => sd.ServiceType == typeof(IHttpClientFactory) && sd.ImplementationType == typeof(DefaultHttpClientFactory)))
{
services.Replace(new ServiceDescriptor(typeof(IHttpClientFactory), HttpClientFactoryInitializer, ServiceLifetime.Singleton));
Expand Down
1 change: 1 addition & 0 deletions src/TeamCloud.Http/TeamCloud.Http.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<ItemGroup>
<PackageReference Include="Flurl.Http" Version="2.4.2" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.12.0" />
<PackageReference Include="Microsoft.ApplicationInsights.PerfCounterCollector" Version="2.12.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.2" />
Expand Down
25 changes: 25 additions & 0 deletions src/TeamCloud.Http/Telemetry/TeamCloudTelemetryInitializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Reflection;
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;

namespace TeamCloud.Http.Telemetry
{
public sealed class TeamCloudTelemetryInitializer : ITelemetryInitializer
{
private readonly Assembly assembly;

internal TeamCloudTelemetryInitializer(Assembly assembly)
{
this.assembly = assembly ?? throw new System.ArgumentNullException(nameof(assembly));
}

public void Initialize(ITelemetry telemetry)
{
if (telemetry is null)
throw new System.ArgumentNullException(nameof(telemetry));

if (string.IsNullOrEmpty(telemetry.Context.Cloud.RoleName))
telemetry.Context.Cloud.RoleName = assembly.GetName().Name;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,36 +39,36 @@ public Task RunActivity(

var tasks = new Task[]
{
DeleteKeyVaultAsync(project),
DeleteResourceGroupAsync(project)
DeleteInternalResourceGroupAsync(project),
DeleteProjectResourceGroupAsync(project)
};

return Task.WhenAll(tasks);
}

private async Task DeleteResourceGroupAsync(Project project)
private async Task DeleteProjectResourceGroupAsync(Project project)
{
if (string.IsNullOrEmpty(project?.ResourceGroup?.ResourceGroupId))
return;

var resourceGroup = await azureResourceService
.GetResourceGroupAsync(project.ResourceGroup.SubscriptionId, project.ResourceGroup.ResourceGroupId)
.GetResourceGroupAsync(project.ResourceGroup.SubscriptionId, project.ResourceGroup.ResourceGroupName)
.ConfigureAwait(false);

await (resourceGroup?.DeleteAsync(true) ?? Task.CompletedTask)
.ConfigureAwait(false);
}

private async Task DeleteKeyVaultAsync(Project project)
private async Task DeleteInternalResourceGroupAsync(Project project)
{
if (string.IsNullOrEmpty(project?.KeyVault?.VaultId))
if (string.IsNullOrEmpty(project?.ResourceGroup?.ResourceGroupId))
return;

var resource = await azureResourceService
.GetResourceAsync(project.KeyVault.VaultId)
var resourceGroup = await azureResourceService
.GetResourceGroupAsync(project.ResourceGroup.SubscriptionId, $"{project.ResourceGroup.ResourceGroupName}_Internal")
.ConfigureAwait(false);

await (resource?.DeleteAsync(true) ?? Task.CompletedTask)
await (resourceGroup?.DeleteAsync(true) ?? Task.CompletedTask)
.ConfigureAwait(false);
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/TeamCloud.Orchestrator/local.settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"DurableFunctionsHubStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"AzureWebJobsSecretStorageType": "files"
"AzureWebJobsSecretStorageType": "files",
"APPINSIGHTS_INSTRUMENTATIONKEY": "00000000-0000-0000-0000-000000000000"

},
"ConnectionStrings": {
"ConfigurationService": "file:///C:/Users/%USERNAME%/Desktop/ConfigurationService.json"
Expand Down

0 comments on commit d5103de

Please sign in to comment.