Skip to content

Commit b39e869

Browse files
author
Guilherme Ferreira
authored
Merge pull request #7 from OMNIALowCode/feature/apply-behaviours-to-api
Apply model from code
2 parents 5b7c3b8 + f85dfeb commit b39e869

61 files changed

Lines changed: 3414 additions & 352 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Omnia.CLI.sln

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 15
4-
VisualStudioVersion = 15.0.28307.572
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.30104.148
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Omnia.CLI", "src\Console\Omnia.CLI.csproj", "{9DC10F93-952F-463D-8782-1D851E1E13D0}"
77
EndProject
8+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{93B409F5-0379-4C91-89FE-77126C1E4BE0}"
9+
EndProject
10+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6FED1B5A-2FE5-4F39-BA53-C697412557D0}"
11+
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "test\UnitTests\UnitTests.csproj", "{D55481AB-D8EF-4FF9-841D-1481AB7719D3}"
13+
EndProject
814
Global
915
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1016
Debug|Any CPU = Debug|Any CPU
@@ -15,10 +21,18 @@ Global
1521
{9DC10F93-952F-463D-8782-1D851E1E13D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
1622
{9DC10F93-952F-463D-8782-1D851E1E13D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
1723
{9DC10F93-952F-463D-8782-1D851E1E13D0}.Release|Any CPU.Build.0 = Release|Any CPU
24+
{D55481AB-D8EF-4FF9-841D-1481AB7719D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25+
{D55481AB-D8EF-4FF9-841D-1481AB7719D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
26+
{D55481AB-D8EF-4FF9-841D-1481AB7719D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
27+
{D55481AB-D8EF-4FF9-841D-1481AB7719D3}.Release|Any CPU.Build.0 = Release|Any CPU
1828
EndGlobalSection
1929
GlobalSection(SolutionProperties) = preSolution
2030
HideSolutionNode = FALSE
2131
EndGlobalSection
32+
GlobalSection(NestedProjects) = preSolution
33+
{9DC10F93-952F-463D-8782-1D851E1E13D0} = {93B409F5-0379-4C91-89FE-77126C1E4BE0}
34+
{D55481AB-D8EF-4FF9-841D-1481AB7719D3} = {6FED1B5A-2FE5-4F39-BA53-C697412557D0}
35+
EndGlobalSection
2236
GlobalSection(ExtensibilityGlobals) = postSolution
2337
SolutionGuid = {E8E2E3C2-F2C1-4F8B-93BA-689C81E6487D}
2438
EndGlobalSection

build.cake

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,27 @@ Task("Build")
5656
});
5757
});
5858

59+
Task("Tests")
60+
.IsDependentOn("Build")
61+
.Does(() =>
62+
{
63+
var projectFiles = GetFiles("./test/**/*.csproj");
64+
var settings = new DotNetCoreTestSettings
65+
{
66+
Filter = "Category!=Ignore",
67+
Configuration = configuration,
68+
ArgumentCustomization = args=>args.Append($"--no-build")
69+
};
70+
71+
foreach(var file in projectFiles)
72+
{
73+
DotNetCoreTest(file.FullPath, settings);
74+
}
75+
});
76+
77+
5978
Task("Publish")
60-
.IsDependentOn("Build")
79+
.IsDependentOn("Tests")
6180
.Does(()=>
6281
{
6382
DotNetCorePack(solutionFile, new DotNetCorePackSettings()

src/Console/App.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ namespace Omnia.CLI
66
{
77
[Command(Name = "omnia-cli", Description = "OMNIA Platform CLI")]
88
[HelpOption("-h|--help")]
9-
[Subcommand(typeof(Omnia.CLI.Commands.Subscriptions.BaseCommand))]
10-
[Subcommand(typeof(Omnia.CLI.Commands.Model.BaseCommand))]
11-
[Subcommand(typeof(Omnia.CLI.Commands.Security.BaseCommand))]
12-
[Subcommand(typeof(Omnia.CLI.Commands.Management.BaseCommand))]
13-
[Subcommand(typeof(Omnia.CLI.Commands.Application.BaseCommand))]
9+
[Subcommand(typeof(Commands.Subscriptions.BaseCommand))]
10+
[Subcommand(typeof(Commands.Model.BaseCommand))]
11+
[Subcommand(typeof(Commands.Security.BaseCommand))]
12+
[Subcommand(typeof(Commands.Management.BaseCommand))]
13+
[Subcommand(typeof(Commands.Application.BaseCommand))]
1414
[VersionOptionFromMember(MemberName = nameof(GetVersion))]
1515

1616
public class App
@@ -23,6 +23,6 @@ public void OnExecute(CommandLineApplication app)
2323
private static string GetVersion() => typeof(Program)
2424
.Assembly
2525
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()
26-
.InformationalVersion;
26+
?.InformationalVersion ?? "0.0.0";
2727
}
2828
}

src/Console/AppSettings.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,22 @@ public class AppSettings
1010

1111
internal Subscription GetSubscription(string name)
1212
{
13-
var sourceSettings = Subscriptions.FirstOrDefault(s => s.Name.Equals(name));
13+
if (SubscriptionNotProvidedAndOnlyOneConfigured())
14+
return Subscriptions.Single();
15+
16+
if(!IsSubscriptionNameProvided())
17+
throw new InvalidOperationException("A registered subscription name must be provided.");
18+
19+
var sourceSettings = Subscriptions.SingleOrDefault(s => s.Name.Equals(name));
1420
if (sourceSettings == null)
1521
throw new InvalidOperationException($"Can't find subscription {name}");
1622
return sourceSettings;
23+
24+
bool SubscriptionNotProvidedAndOnlyOneConfigured()
25+
=> !IsSubscriptionNameProvided() && Subscriptions.Count == 1;
26+
27+
bool IsSubscriptionNameProvided()
28+
=> !string.IsNullOrEmpty(name);
1729
}
1830
internal bool Exists(string name)
1931
=> Subscriptions.Any(s => s.Name.Equals(name));

src/Console/Commands/Application/ImportCommand.cs

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
using McMaster.Extensions.CommandLineUtils;
22
using Microsoft.Extensions.Options;
3-
using Omnia.CLI.Extensions;
3+
using Omnia.CLI.Commands.Application.Infrastructure;
44
using Omnia.CLI.Infrastructure;
55
using ShellProgressBar;
66
using System;
77
using System.Collections.Generic;
88
using System.IO;
99
using System.Linq;
10-
using System.Net.Http;
1110
using System.Threading.Tasks;
12-
using Omnia.CLI.Commands.Application.Infrastructure;
11+
using Omnia.CLI.Extensions;
1312

1413
namespace Omnia.CLI.Commands.Application
1514
{
@@ -18,12 +17,12 @@ namespace Omnia.CLI.Commands.Application
1817
public class ImportCommand
1918
{
2019
private readonly AppSettings _settings;
21-
private readonly HttpClient _httpClient;
20+
private readonly IApiClient _apiClient;
2221

23-
public ImportCommand(IOptions<AppSettings> options, IHttpClientFactory httpClientFactory)
22+
public ImportCommand(IOptions<AppSettings> options, IApiClient apiClient)
2423
{
24+
_apiClient = apiClient;
2525
_settings = options.Value;
26-
_httpClient = httpClientFactory.CreateClient();
2726
}
2827

2928
[Option("--subscription", CommandOptionType.SingleValue, Description = "Name of the configured subscription.")]
@@ -54,7 +53,7 @@ public async Task<int> OnExecute(CommandLineApplication cmd)
5453

5554
var sourceSettings = _settings.GetSubscription(Subscription);
5655

57-
await _httpClient.WithSubscription(sourceSettings);
56+
await _apiClient.Authenticate(sourceSettings);
5857

5958
var reader = new ImportDataReader();
6059
try
@@ -90,7 +89,7 @@ private async Task<bool> ProcessDefinitions(ICollection<ImportData> data)
9089
foreach (var dataEntry in data)
9190
{
9291
var (success, messages) =
93-
await CreateEntities(progressBar, _httpClient, Tenant, Environment, dataEntry.Definition, dataEntry.DataSource, dataEntry.Data);
92+
await CreateEntities(progressBar, _apiClient, Tenant, Environment, dataEntry.Definition, dataEntry.DataSource, dataEntry.Data);
9493
progressBar.Tick();
9594

9695
if (success)
@@ -107,7 +106,8 @@ private async Task<bool> ProcessDefinitions(ICollection<ImportData> data)
107106
return !failed.Any();
108107
}
109108

110-
private static async Task<(bool Success, string[] Messages)> CreateEntities(ProgressBarBase progressBar, HttpClient httpClient,
109+
private static async Task<(bool Success, string[] Messages)> CreateEntities(ProgressBarBase progressBar,
110+
IApiClient apiClient,
111111
string tenantCode,
112112
string environmentCode,
113113
string definition,
@@ -120,14 +120,14 @@ private async Task<bool> ProcessDefinitions(ICollection<ImportData> data)
120120
{
121121
foreach (var (rowNumber, values) in data)
122122
{
123-
var (statusCode, errors) = await CreateEntity(httpClient, tenantCode, environmentCode, definition, dataSource, values);
123+
var (statusCode, errors) = await CreateEntity(apiClient, tenantCode, environmentCode, definition, dataSource, values);
124124

125125
child.Tick(statusCode == (int)StatusCodes.Success ? null : $"Error creating entity for {dataSource} {definition}");
126-
127-
if (statusCode == (int) StatusCodes.Success) continue;
128-
126+
127+
if (statusCode == (int)StatusCodes.Success) continue;
128+
129129
child.ForegroundColor = ConsoleColor.DarkRed;
130-
130+
131131
failedEntities.Add($"Error to import {dataSource}.{definition}: In row {rowNumber} with errors: {GetErrors(errors)}");
132132
}
133133
}
@@ -143,29 +143,16 @@ static string JoinErrors(ApiError errors)
143143
=> string.Join("", errors.Errors.Select(c => $"\n\r {c.Name} - {c.Message}"));
144144
}
145145

146-
private static async Task<(int statusCode, ApiError errors)> CreateEntity(HttpClient httpClient,
146+
private static async Task<(int statusCode, ApiError errors)> CreateEntity(IApiClient apiClient,
147147
string tenantCode,
148148
string environmentCode,
149149
string definition,
150150
string dataSource,
151151
IDictionary<string, object> data)
152152
{
153-
var response = await httpClient.PostAsJsonAsync($"/api/v1/{tenantCode}/{environmentCode}/application/{definition}/{dataSource}", data);
154-
if (response.IsSuccessStatusCode)
155-
{
156-
return ((int)StatusCodes.Success, null);
157-
}
158-
159-
var apiError = await GetErrorFromApiResponse(response) ?? new ApiError()
160-
{
161-
Code = ((int)response.StatusCode).ToString(),
162-
Message = (int)response.StatusCode != 403 ? response.StatusCode.ToString() : "Access denied!"
163-
};
164-
165-
return ((int)StatusCodes.InvalidOperation, apiError);
153+
var response = await apiClient.Post($"/api/v1/{tenantCode}/{environmentCode}/application/{definition}/{dataSource}", data.ToHttpStringContent());
154+
155+
return response.Success ? ((int)StatusCodes.Success, null) : ((int)StatusCodes.InvalidOperation, response.ErrorDetails);
166156
}
167-
168-
private static Task<ApiError> GetErrorFromApiResponse(HttpResponseMessage response)
169-
=> response.Content.ReadAsJsonAsync<ApiError>();
170157
}
171158
}

src/Console/Commands/Application/Infrastructure/ImportDataReader.cs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,10 @@ private void ScrollSheets(XSSFWorkbook workbook)
4343

4444
var activeWorksheet = workbook.GetSheetAt(workbook.GetSheetIndex(sheet.Sheet));
4545
var entityName = sheet.Entity;
46-
var dataSource = string.IsNullOrEmpty(sheet.DataSource) ? "Default" : sheet.DataSource; //GetDataSource(namingParts);
46+
var dataSource = string.IsNullOrEmpty(sheet.DataSource) ? "Default" : sheet.DataSource;
4747

48-
List<(int RowNum, IDictionary<string, object> Data)> lines;
49-
50-
if (_sheets.Any(s => s.Entity.StartsWith($"{entityName}.")))
51-
{
52-
lines = ProcessCollectionSheet(workbook, entityName);
53-
}
54-
else
55-
{
56-
lines = ProcessSimpleSheet(activeWorksheet);
57-
}
48+
var lines = _sheets.Any(s => s.Entity != null && s.Entity.StartsWith($"{entityName}.")) ?
49+
ProcessCollectionSheet(workbook, entityName) : ProcessSimpleSheet(activeWorksheet);
5850

5951
_data.Add(new ImportData(entityName, dataSource, lines));
6052

src/Console/Commands/Management/Tenants/AddCommand.cs

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,22 @@
22
using McMaster.Extensions.CommandLineUtils;
33
using Microsoft.Extensions.Options;
44
using Omnia.CLI.Extensions;
5-
using System.Net.Http;
65
using System.Threading.Tasks;
7-
using Newtonsoft.Json;
8-
using System.Text;
6+
using Omnia.CLI.Infrastructure;
97

108
namespace Omnia.CLI.Commands.Management.Tenants
119
{
1210
[Command(Name = "add", Description = "Create a new Tenant.")]
1311
[HelpOption("-h|--help")]
1412
public class AddCommand
1513
{
14+
private readonly IApiClient _apiClient;
1615
private readonly AppSettings _settings;
17-
private readonly HttpClient _httpClient;
18-
public AddCommand(IOptions<AppSettings> options, IHttpClientFactory httpClientFactory)
16+
17+
public AddCommand(IOptions<AppSettings> options, IApiClient apiClient)
1918
{
19+
_apiClient = apiClient;
2020
_settings = options.Value;
21-
_httpClient = httpClientFactory.CreateClient();
2221
}
2322

2423
[Option("--subscription", CommandOptionType.SingleValue, Description = "Name of the configured subscription.")]
@@ -54,34 +53,23 @@ public async Task<int> OnExecute(CommandLineApplication cmd)
5453

5554
var sourceSettings = _settings.GetSubscription(Subscription);
5655

57-
await _httpClient.WithSubscription(sourceSettings);
56+
await _apiClient.Authenticate(sourceSettings);
5857

59-
return await CreateTenant(_httpClient, Code, Name);
58+
return await CreateTenant(_apiClient, Code, Name);
6059
}
6160

62-
private static async Task<int> CreateTenant(HttpClient httpClient, string tenantCode, string tenantName)
61+
private static async Task<int> CreateTenant(IApiClient apiClient, string tenantCode, string tenantName)
6362
{
64-
var response = await httpClient.PostAsJsonAsync($"/api/v1/management/tenants", new { Code = tenantCode, Name = tenantName });
65-
if (response.IsSuccessStatusCode)
63+
var response = await apiClient.Post($"/api/v1/management/tenants", new { Code = tenantCode, Name = tenantName }.ToHttpStringContent());
64+
if (response.Success)
6665
{
6766
Console.WriteLine($"Tenant \"{tenantName}\" ({tenantCode}) created successfully.");
6867
return (int)StatusCodes.Success;
6968
}
7069

71-
var apiError = await GetErrorFromApiResponse(response);
72-
73-
Console.WriteLine($"{apiError.Code}: {apiError.Message}");
70+
Console.WriteLine($"{response.ErrorDetails.Code}: {response.ErrorDetails.Message}");
7471

7572
return (int)StatusCodes.InvalidOperation;
7673
}
77-
78-
private static async Task<ApiError> GetErrorFromApiResponse(HttpResponseMessage response)
79-
=> JsonConvert.DeserializeObject<ApiError>(await response.Content.ReadAsStringAsync());
80-
81-
private class ApiError
82-
{
83-
public string Code { get; set; }
84-
public string Message { get; set; }
85-
}
8674
}
8775
}

0 commit comments

Comments
 (0)