Skip to content

Commit

Permalink
Merge pull request #239 from microsoft/dev
Browse files Browse the repository at this point in the history
integrate minor changes +resetdemo
  • Loading branch information
markusheiliger authored Mar 15, 2021
2 parents 9239373 + e22cbd0 commit 5176c19
Show file tree
Hide file tree
Showing 14 changed files with 409 additions and 176 deletions.
8 changes: 5 additions & 3 deletions src/TeamCloud.API/Controllers/ProjectController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,7 @@ public Task<IActionResult> Post([FromBody] ProjectDefinition projectDefinition)
Id = projectId,
Organization = organization.Id,
Users = users,
DisplayName = projectDefinition.DisplayName,
// Tags = projectDefinition.Tags,
// Properties = projectDefinition.Properties
DisplayName = projectDefinition.DisplayName
};

ProjectTemplate template = null;
Expand Down Expand Up @@ -191,6 +189,10 @@ public Task<IActionResult> Post([FromBody] ProjectDefinition projectDefinition)
project.Template = template.Id;
project.TemplateInput = projectDefinition.TemplateInput;

project.Tags = input
.ToObject<Dictionary<string, object>>()
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToString());

var currentUser = users.FirstOrDefault(u => u.Id == UserService.CurrentUserId);

var command = new ProjectCreateCommand(currentUser, project);
Expand Down
1 change: 0 additions & 1 deletion src/TeamCloud.Git/Data/ComponentPermissionYaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* Licensed under the MIT License.
*/


namespace TeamCloud.Git.Data
{
public class ComponentPermissionYaml
Expand Down
16 changes: 16 additions & 0 deletions src/TeamCloud.Model/Commands/ComponentUpdateCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*/

using TeamCloud.Model.Commands.Core;
using TeamCloud.Model.Data;

namespace TeamCloud.Model.Commands
{
public sealed class ComponentUpdateCommand : UpdateCommand<Component, ComponentUpdateCommandResult>
{
public ComponentUpdateCommand(User user, Component payload) : base(user, payload)
=> ProjectId = payload?.ProjectId ?? throw new System.ArgumentNullException(nameof(payload));
}
}
12 changes: 12 additions & 0 deletions src/TeamCloud.Model/Commands/ComponentUpdateCommandResult.cs
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.Model.Commands.Core;
using TeamCloud.Model.Data;

namespace TeamCloud.Model.Commands
{
public sealed class ComponentUpdateCommandResult : CommandResult<Component> { }
}
36 changes: 33 additions & 3 deletions src/TeamCloud.Orchestrator/Handlers/ProjectUserCommandHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
* Licensed under the MIT License.
*/

using System;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using System;
using System.Threading.Tasks;
using TeamCloud.Data;
using TeamCloud.Model.Commands;
using TeamCloud.Model.Commands.Core;
using TeamCloud.Model.Data;

namespace TeamCloud.Orchestrator.Handlers
{
Expand All @@ -19,10 +20,12 @@ public sealed class ProjectUserCommandHandler
ICommandHandler<ProjectUserDeleteCommand>
{
private readonly IUserRepository userRepository;
private readonly IComponentRepository componentRepository;

public ProjectUserCommandHandler(IUserRepository userRepository)
public ProjectUserCommandHandler(IUserRepository userRepository, IComponentRepository componentRepository)
{
this.userRepository = userRepository ?? throw new ArgumentNullException(nameof(userRepository));
this.componentRepository = componentRepository ?? throw new ArgumentNullException(nameof(componentRepository));
}

public async Task<ICommandResult> HandleAsync(ProjectUserCreateCommand command, IAsyncCollector<ICommand> commandQueue, IDurableClient durableClient = null)
Expand All @@ -47,6 +50,11 @@ public async Task<ICommandResult> HandleAsync(ProjectUserCreateCommand command,
{
commandResult.Errors.Add(exc);
}
finally
{
await UpdateComponentsAsync(command.User, command.ProjectId, commandQueue)
.ConfigureAwait(false);
}

return commandResult;
}
Expand All @@ -73,6 +81,11 @@ public async Task<ICommandResult> HandleAsync(ProjectUserUpdateCommand command,
{
commandResult.Errors.Add(exc);
}
finally
{
await UpdateComponentsAsync(command.User, command.ProjectId, commandQueue)
.ConfigureAwait(false);
}

return commandResult;
}
Expand All @@ -99,8 +112,25 @@ public async Task<ICommandResult> HandleAsync(ProjectUserDeleteCommand command,
{
commandResult.Errors.Add(exc);
}
finally
{
await UpdateComponentsAsync(command.User, command.ProjectId, commandQueue)
.ConfigureAwait(false);
}

return commandResult;
}

private async Task UpdateComponentsAsync(User user, string projectId, IAsyncCollector<ICommand> commandQueue)
{
await foreach (var component in componentRepository.ListAsync(projectId))
{
var command = new ComponentUpdateCommand(user, component);

await commandQueue
.AddAsync(command)
.ConfigureAwait(false);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,30 @@ public static async Task<ICommandResult> RunActivity(
if (durableClient is null)
throw new ArgumentNullException(nameof(durableClient));

ICommandResult commandResult;

try
{
commandResult = context.GetInput<ICommandResult>();
}
catch (Exception exc)
{
log?.LogError(exc, $"Failed deserialize command result from json: {exc.Message}");

throw exc.AsSerializable();
}
var input = context.GetInput<Input>();

try
{
var commandStatus = await durableClient
.GetStatusAsync(commandResult.CommandId.ToString())
.GetStatusAsync(input.CommandResult.CommandId.ToString())
.ConfigureAwait(false);

if (commandStatus != null)
commandResult.ApplyStatus(commandStatus);
input.CommandResult.ApplyStatus(commandStatus);

return input.CommandResult;
}
catch (Exception exc)
{
log?.LogWarning(exc, $"Failed to augment command result with orchestration status {commandResult.CommandId}: {exc.Message}");
log?.LogWarning(exc, $"Failed to augment command result with orchestration status: {exc.Message}");

throw exc.AsSerializable();
}
}

return commandResult;
internal struct Input
{
public ICommandResult CommandResult { get; set; }
}
}
}

This file was deleted.

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

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Threading.Tasks;
using TeamCloud.Azure.Resources;
using TeamCloud.Data;
using TeamCloud.Model.Data;
using TeamCloud.Orchestration;
using TeamCloud.Serialization;

namespace TeamCloud.Orchestrator.Operations.Activities
{
public sealed class ComponentEnsureTaggingActivity
{
private readonly IOrganizationRepository organizationRepository;
private readonly IProjectRepository projectRepository;
private readonly IAzureResourceService azureResourceService;

public ComponentEnsureTaggingActivity(IOrganizationRepository organizationRepository, IProjectRepository projectRepository, IAzureResourceService azureResourceService)
{
this.organizationRepository = organizationRepository ?? throw new ArgumentNullException(nameof(organizationRepository));
this.projectRepository = projectRepository ?? throw new ArgumentNullException(nameof(projectRepository));
this.azureResourceService = azureResourceService ?? throw new ArgumentNullException(nameof(azureResourceService));
}

[FunctionName(nameof(ComponentEnsureTaggingActivity))]
[RetryOptions(3)]
public async Task<Component> Run(
[ActivityTrigger] IDurableActivityContext context,
ILogger log)
{
if (context is null)
throw new ArgumentNullException(nameof(context));

if (log is null)
throw new ArgumentNullException(nameof(log));

var component = context.GetInput<Input>().Component;

try
{
if (AzureResourceIdentifier.TryParse(component.ResourceId, out var azureResourceIdentifier))
{
var tenantId = (await azureResourceService.AzureSessionService.GetIdentityAsync().ConfigureAwait(false)).TenantId;

var organization = await organizationRepository
.GetAsync(tenantId.ToString(), component.Organization, true)
.ConfigureAwait(false);

var project = await projectRepository
.GetAsync(component.Organization, component.ProjectId, true)
.ConfigureAwait(false);

var tags = organization.Tags
.Union(project.Tags)
.GroupBy(kvp => kvp.Key)
.ToDictionary(g => g.Key, g => g.First().Value);

if (string.IsNullOrEmpty(azureResourceIdentifier.ResourceGroup))
{
var subscription = await azureResourceService
.GetSubscriptionAsync(azureResourceIdentifier.SubscriptionId)
.ConfigureAwait(false);

if (subscription != null)
await subscription.SetTagsAsync(tags, true).ConfigureAwait(false);
}
else
{
var resourceGroup = await azureResourceService
.GetResourceGroupAsync(azureResourceIdentifier.SubscriptionId, azureResourceIdentifier.ResourceGroup)
.ConfigureAwait(false);

if (resourceGroup != null)
await resourceGroup.SetTagsAsync(tags, true).ConfigureAwait(false);
}
}
}
catch (Exception exc)
{
throw exc.AsSerializable();
}

return component;
}

internal struct Input
{
public Component Component { get; set; }
}
}
}
Loading

0 comments on commit 5176c19

Please sign in to comment.