diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile index aab4164b7..4e089c9be 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Dockerfile @@ -24,6 +24,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs index 3f988395a..9c21c9fe0 100644 --- a/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs +++ b/src/ApiGateways/Mobile.Bff.Shopping/aggregator/Startup.cs @@ -15,6 +15,7 @@ public class Startup services.AddHealthChecks() .AddCheck("self", () => HealthCheckResult.Healthy()) .AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" }) + .AddUrlGroup(new Uri(Configuration["CouponUrlHC"]), name: "couponapi-check", tags: new string[] { "couponapi" }) .AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" }) .AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" }) .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }) diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile index 8761763a1..016443328 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Dockerfile @@ -24,6 +24,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs index 6e8e66931..68a6b0cac 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs @@ -15,6 +15,7 @@ public class Startup services.AddHealthChecks() .AddCheck("self", () => HealthCheckResult.Healthy()) .AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" }) + .AddUrlGroup(new Uri(Configuration["CouponUrlHC"]), name: "couponapi-check", tags: new string[] { "couponapi" }) .AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" }) .AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" }) .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }) diff --git a/src/Coupon.API/Controllers/WeatherForecastController.cs b/src/Coupon.API/Controllers/WeatherForecastController.cs deleted file mode 100644 index d17e15b7b..000000000 --- a/src/Coupon.API/Controllers/WeatherForecastController.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace Coupon.API.Controllers; - -[ApiController] -[Route("[controller]")] -public class WeatherForecastController : ControllerBase -{ - private static readonly string[] Summaries = new[] - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - }; - - private readonly ILogger _logger; - - public WeatherForecastController(ILogger logger) - { - _logger = logger; - } - - [HttpGet(Name = "GetWeatherForecast")] - public IEnumerable Get() - { - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateTime.Now.AddDays(index), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)] - }) - .ToArray(); - } -} \ No newline at end of file diff --git a/src/Coupon.API/Coupon.API.csproj b/src/Coupon.API/Coupon.API.csproj deleted file mode 100644 index 6108b7b28..000000000 --- a/src/Coupon.API/Coupon.API.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - net6.0 - enable - enable - - - - - - - diff --git a/src/Coupon.API/Program.cs b/src/Coupon.API/Program.cs deleted file mode 100644 index 8264bac54..000000000 --- a/src/Coupon.API/Program.cs +++ /dev/null @@ -1,25 +0,0 @@ -var builder = WebApplication.CreateBuilder(args); - -// Add services to the container. - -builder.Services.AddControllers(); -// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle -builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddSwaggerGen(); - -var app = builder.Build(); - -// Configure the HTTP request pipeline. -if (app.Environment.IsDevelopment()) -{ - app.UseSwagger(); - app.UseSwaggerUI(); -} - -app.UseHttpsRedirection(); - -app.UseAuthorization(); - -app.MapControllers(); - -app.Run(); \ No newline at end of file diff --git a/src/Coupon.API/WeatherForecast.cs b/src/Coupon.API/WeatherForecast.cs deleted file mode 100644 index ce301413f..000000000 --- a/src/Coupon.API/WeatherForecast.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Coupon.API; - -public class WeatherForecast -{ - public DateTime Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int) (TemperatureC / 0.5556); - - public string? Summary { get; set; } -} \ No newline at end of file diff --git a/src/Coupon.API/appsettings.Development.json b/src/Coupon.API/appsettings.Development.json deleted file mode 100644 index 0c208ae91..000000000 --- a/src/Coupon.API/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - } -} diff --git a/src/Coupon.API/appsettings.json b/src/Coupon.API/appsettings.json deleted file mode 100644 index 10f68b8c8..000000000 --- a/src/Coupon.API/appsettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*" -} diff --git a/src/Services/Basket/Basket.API/Dockerfile b/src/Services/Basket/Basket.API/Dockerfile index 9cd4abba8..d344e804a 100644 --- a/src/Services/Basket/Basket.API/Dockerfile +++ b/src/Services/Basket/Basket.API/Dockerfile @@ -24,6 +24,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/Services/Catalog/Catalog.API/Catalog.API.csproj b/src/Services/Catalog/Catalog.API/Catalog.API.csproj index b18df9bdb..c355efc59 100644 --- a/src/Services/Catalog/Catalog.API/Catalog.API.csproj +++ b/src/Services/Catalog/Catalog.API/Catalog.API.csproj @@ -68,10 +68,10 @@ - + - + diff --git a/src/Services/Catalog/Catalog.API/Dockerfile b/src/Services/Catalog/Catalog.API/Dockerfile index e491c2110..3c5c963cf 100644 --- a/src/Services/Catalog/Catalog.API/Dockerfile +++ b/src/Services/Catalog/Catalog.API/Dockerfile @@ -25,6 +25,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/Services/Coupon/Coupon.API/Controllers/CouponController.cs b/src/Services/Coupon/Coupon.API/Controllers/CouponController.cs new file mode 100644 index 000000000..10e6e094d --- /dev/null +++ b/src/Services/Coupon/Coupon.API/Controllers/CouponController.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Coupon.API.Controllers; + +[ApiController] +[ApiVersion("1.0")] +[Route("v{version:apiVersion}/[controller]")] +public class CouponController : ControllerBase +{ + [HttpGet("{code}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task GetCouponByCodeAsync(string code) + { + await Task.Delay(500); + + return Ok(code); + } +} \ No newline at end of file diff --git a/src/Services/Coupon/Coupon.API/Coupon.API.csproj b/src/Services/Coupon/Coupon.API/Coupon.API.csproj new file mode 100644 index 000000000..46d76a9c5 --- /dev/null +++ b/src/Services/Coupon/Coupon.API/Coupon.API.csproj @@ -0,0 +1,43 @@ + + + + net6.0 + enable + enable + portable + true + Coupon.API + Coupon.API + aspnet-Coupon.API-20161122013618 + ..\..\..\..\docker-compose.dcproj + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Services/Coupon/Coupon.API/CouponSettings.cs b/src/Services/Coupon/Coupon.API/CouponSettings.cs new file mode 100644 index 000000000..4093053d0 --- /dev/null +++ b/src/Services/Coupon/Coupon.API/CouponSettings.cs @@ -0,0 +1,14 @@ +namespace Coupon.API; + +public class CouponSettings +{ + public string ConnectionString { get; set; } + + public string CouponMongoDatabase { get; set; } + + public string EventBusConnection { get; set; } + + public bool UseCustomizationData { get; set; } + + public bool AzureStorageEnabled { get; set; } +} diff --git a/src/Services/Coupon/Coupon.API/Dockerfile b/src/Services/Coupon/Coupon.API/Dockerfile new file mode 100644 index 000000000..655c9eaba --- /dev/null +++ b/src/Services/Coupon/Coupon.API/Dockerfile @@ -0,0 +1,68 @@ +FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build +WORKDIR /src + +# It's important to keep lines from here down to "COPY . ." identical in all Dockerfiles +# to take advantage of Docker's build cache, to speed up local container builds +COPY "eShopOnContainers-ServicesAndWebApps.sln" "eShopOnContainers-ServicesAndWebApps.sln" + +COPY "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj" "ApiGateways/Mobile.Bff.Shopping/aggregator/Mobile.Shopping.HttpAggregator.csproj" +COPY "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" "ApiGateways/Web.Bff.Shopping/aggregator/Web.Shopping.HttpAggregator.csproj" +COPY "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" "BuildingBlocks/Devspaces.Support/Devspaces.Support.csproj" +COPY "BuildingBlocks/EventBus/EventBus/EventBus.csproj" "BuildingBlocks/EventBus/EventBus/EventBus.csproj" +COPY "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" "BuildingBlocks/EventBus/EventBus.Tests/EventBus.Tests.csproj" +COPY "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" "BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj" +COPY "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" "BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj" +COPY "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" "BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj" +COPY "BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj" "BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj" +COPY "Services/Basket/Basket.API/Basket.API.csproj" "Services/Basket/Basket.API/Basket.API.csproj" +COPY "Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj" "Services/Basket/Basket.FunctionalTests/Basket.FunctionalTests.csproj" +COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" +COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" +COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" +COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" +COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" +COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" +COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" +COPY "Services/Ordering/Ordering.Domain/Ordering.Domain.csproj" "Services/Ordering/Ordering.Domain/Ordering.Domain.csproj" +COPY "Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj" "Services/Ordering/Ordering.FunctionalTests/Ordering.FunctionalTests.csproj" +COPY "Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj" "Services/Ordering/Ordering.Infrastructure/Ordering.Infrastructure.csproj" +COPY "Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj" "Services/Ordering/Ordering.SignalrHub/Ordering.SignalrHub.csproj" +COPY "Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj" "Services/Ordering/Ordering.UnitTests/Ordering.UnitTests.csproj" +COPY "Services/Payment/Payment.API/Payment.API.csproj" "Services/Payment/Payment.API/Payment.API.csproj" +COPY "Services/Webhooks/Webhooks.API/Webhooks.API.csproj" "Services/Webhooks/Webhooks.API/Webhooks.API.csproj" +COPY "Tests/Services/Application.FunctionalTests/Application.FunctionalTests.csproj" "Tests/Services/Application.FunctionalTests/Application.FunctionalTests.csproj" +COPY "Web/WebhookClient/WebhookClient.csproj" "Web/WebhookClient/WebhookClient.csproj" +COPY "Web/WebMVC/WebMVC.csproj" "Web/WebMVC/WebMVC.csproj" +COPY "Web/WebSPA/WebSPA.csproj" "Web/WebSPA/WebSPA.csproj" +COPY "Web/WebStatus/WebStatus.csproj" "Web/WebStatus/WebStatus.csproj" + +COPY "docker-compose.dcproj" "docker-compose.dcproj" + +COPY "NuGet.config" "NuGet.config" + +RUN dotnet restore "eShopOnContainers-ServicesAndWebApps.sln" + +COPY . . +WORKDIR /src/Services/Coupon/Coupon.API +RUN dotnet publish --no-restore -c Release -o /app + +#FROM build as unittest +#WORKDIR /src/Services/Catalog/Catalog.UnitTests +# +#FROM build as functionaltest +#WORKDIR /src/Services/Catalog/Catalog.FunctionalTests + +FROM build AS publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app . +#COPY --from=build /src/Services/Catalog/Catalog.API/Proto /app/Proto +COPY --from=build /src/Services/Coupon/Coupon.API/eshop.pfx . +ENTRYPOINT ["dotnet", "Coupon.API.dll"] diff --git a/src/Services/Coupon/Coupon.API/Dockerfile.develop b/src/Services/Coupon/Coupon.API/Dockerfile.develop new file mode 100644 index 000000000..513396298 --- /dev/null +++ b/src/Services/Coupon/Coupon.API/Dockerfile.develop @@ -0,0 +1,22 @@ +FROM mcr.microsoft.com/dotnet/sdk:6.0 +ARG BUILD_CONFIGURATION=Debug +ENV ASPNETCORE_ENVIRONMENT=Development +ENV DOTNET_USE_POLLING_FILE_WATCHER=true +EXPOSE 80 + +WORKDIR /src + +COPY ["BuildingBlocks/EventBus/EventBus/EventBus.csproj", "BuildingBlocks/EventBus/EventBus/"] +COPY ["BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.csproj", "BuildingBlocks/EventBus/EventBusRabbitMQ/"] +COPY ["BuildingBlocks/EventBus/EventBusServiceBus/EventBusServiceBus.csproj", "BuildingBlocks/EventBus/EventBusServiceBus/"] +COPY ["BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEF.csproj", "BuildingBlocks/EventBus/IntegrationEventLogEF/"] +COPY ["BuildingBlocks/WebHostCustomization/WebHost.Customization/WebHost.Customization.csproj", "BuildingBlocks/WebHostCustomization/WebHost.Customization/"] +COPY ["Services/Catalog/Catalog.API/Catalog.API.csproj", "Services/Catalog/Catalog.API/"] +COPY ["NuGet.config", "NuGet.config"] + +RUN dotnet restore Services/Catalog/Catalog.API/Catalog.API.csproj -nowarn:msb3202,nu1503 +COPY . . +WORKDIR "/src/Services/Catalog/Catalog.API" +RUN dotnet build -c $BUILD_CONFIGURATION + +ENTRYPOINT ["dotnet", "run", "--no-build", "--no-launch-profile", "-c", "$BUILD_CONFIGURATION", "--"] \ No newline at end of file diff --git a/src/Services/Coupon/Coupon.API/Extensions/CustomExtensionMethods.cs b/src/Services/Coupon/Coupon.API/Extensions/CustomExtensionMethods.cs new file mode 100644 index 000000000..d63b84768 --- /dev/null +++ b/src/Services/Coupon/Coupon.API/Extensions/CustomExtensionMethods.cs @@ -0,0 +1,164 @@ +using System.Data.Common; +using System.Reflection; +using Autofac; +using Coupon.API.Infrastructure.Filters; +using Microsoft.AspNetCore.Mvc; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; +using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Options; +using Microsoft.OpenApi.Models; +using RabbitMQ.Client; + +namespace Coupon.API.Extensions; + +public static class CustomExtensionMethods +{ + public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) + { + services.AddApplicationInsightsTelemetry(configuration); + services.AddApplicationInsightsKubernetesEnricher(); + + return services; + } + + public static IServiceCollection AddCustomMVC(this IServiceCollection services) + { + services.AddControllers(options => + { + options.Filters.Add(typeof(HttpGlobalExceptionFilter)); + }) + .AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true); + + services.AddCors(options => + { + options.AddPolicy("CorsPolicy", + builder => builder + .SetIsOriginAllowed((host) => true) + .AllowAnyMethod() + .AllowAnyHeader() + .AllowCredentials()); + }); + + return services; + } + + public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) + { + var accountName = configuration.GetValue("AzureStorageAccountName"); + var accountKey = configuration.GetValue("AzureStorageAccountKey"); + + var hcBuilder = services.AddHealthChecks(); + + hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()) + .AddMongoDb( + configuration["ConnectionString"], + name: "CouponCollection-check", + tags: new string[] { "couponcollection" }); + + if (configuration.GetValue("AzureServiceBusEnabled")) + { + hcBuilder + .AddAzureServiceBusTopic( + configuration["EventBusConnection"], + topicName: "eshop_event_bus", + name: "coupon-servicebus-check", + tags: new string[] { "servicebus" }); + } + else + { + hcBuilder + .AddRabbitMQ( + $"amqp://{configuration["EventBusConnection"]}", + name: "coupon-rabbitmqbus-check", + tags: new string[] { "rabbitmqbus" }); + } + + return services; + } + + public static IServiceCollection AddCustomOptions(this IServiceCollection services, IConfiguration configuration) + { + services.Configure(configuration); + services.Configure(options => + { + options.InvalidModelStateResponseFactory = context => + { + var problemDetails = new ValidationProblemDetails(context.ModelState) + { + Instance = context.HttpContext.Request.Path, + Status = StatusCodes.Status400BadRequest, + Detail = "Please refer to the errors property for additional details." + }; + + return new BadRequestObjectResult(problemDetails) + { + ContentTypes = { "application/problem+json", "application/problem+xml" } + }; + }; + }); + + return services; + } + + public static IServiceCollection AddSwagger(this IServiceCollection services) + { + services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new OpenApiInfo + { + Title = "eShopOnContainers - Coupon HTTP API", + Version = "v1", + Description = "The Coupon Microservice HTTP API. This is a Data-Driven/CRUD microservice sample" + }); + }); + + return services; + + } + + public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) + { + if (configuration.GetValue("AzureServiceBusEnabled")) + { + services.AddSingleton(sp => + { + var serviceBusPersisterConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + string subscriptionName = configuration["SubscriptionClientName"]; + + return new EventBusServiceBus(serviceBusPersisterConnection, logger, + eventBusSubcriptionsManager, iLifetimeScope, subscriptionName); + }); + + } + else + { + services.AddSingleton(sp => + { + var subscriptionClientName = configuration["SubscriptionClientName"]; + var rabbitMQPersistentConnection = sp.GetRequiredService(); + var iLifetimeScope = sp.GetRequiredService(); + var logger = sp.GetRequiredService>(); + var eventBusSubcriptionsManager = sp.GetRequiredService(); + + var retryCount = 5; + if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) + { + retryCount = int.Parse(configuration["EventBusRetryCount"]); + } + + return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); + }); + } + + services.AddSingleton(); + + return services; + } +} \ No newline at end of file diff --git a/src/Services/Coupon/Coupon.API/Extensions/WebHostExtensions.cs b/src/Services/Coupon/Coupon.API/Extensions/WebHostExtensions.cs new file mode 100644 index 000000000..1faa2d6ed --- /dev/null +++ b/src/Services/Coupon/Coupon.API/Extensions/WebHostExtensions.cs @@ -0,0 +1,68 @@ +namespace Coupon.API.Extensions; + +public static class WebHostExtensions +{ + public static bool IsInKubernetes(this IWebHost host) + { + var cfg = host.Services.GetService(); + var orchestratorType = cfg.GetValue("OrchestratorType"); + return orchestratorType?.ToUpper() == "K8S"; + } + + // public static IWebHost MigrateDbContext(this IWebHost host, Action seeder) where TContext : DbContext + // { + // var underK8s = host.IsInKubernetes(); + // + // using var scope = host.Services.CreateScope(); + // var services = scope.ServiceProvider; + // + // var logger = services.GetRequiredService>(); + // + // var context = services.GetService(); + // + // try + // { + // logger.LogInformation("Migrating database associated with context {DbContextName}", typeof(TContext).Name); + // + // if (underK8s) + // { + // InvokeSeeder(seeder, context, services); + // } + // else + // { + // var retry = Policy.Handle() + // .WaitAndRetry(new TimeSpan[] + // { + // TimeSpan.FromSeconds(3), + // TimeSpan.FromSeconds(5), + // TimeSpan.FromSeconds(8), + // }); + // + // //if the sql server container is not created on run docker compose this + // //migration can't fail for network related exception. The retry options for DbContext only + // //apply to transient exceptions + // // Note that this is NOT applied when running some orchestrators (let the orchestrator to recreate the failing service) + // retry.Execute(() => InvokeSeeder(seeder, context, services)); + // } + // + // logger.LogInformation("Migrated database associated with context {DbContextName}", typeof(TContext).Name); + // } + // catch (Exception ex) + // { + // logger.LogError(ex, "An error occurred while migrating the database used on context {DbContextName}", typeof(TContext).Name); + // if (underK8s) + // { + // throw; // Rethrow under k8s because we rely on k8s to re-run the pod + // } + // } + // + // return host; + // } + // + // private static void InvokeSeeder(Action seeder, TContext context, IServiceProvider services) + // where TContext : DbContext + // { + // context.Database.Migrate(); + // seeder(context, services); + // } +} diff --git a/src/Services/Coupon/Coupon.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs b/src/Services/Coupon/Coupon.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs new file mode 100644 index 000000000..7c39ff7f3 --- /dev/null +++ b/src/Services/Coupon/Coupon.API/Infrastructure/ActionResults/InternalServerErrorObjectResult.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Coupon.API.Infrastructure.ActionResults; + +public class InternalServerErrorObjectResult : ObjectResult +{ + public InternalServerErrorObjectResult(object error) : base(error) + { + StatusCode = StatusCodes.Status500InternalServerError; + } +} diff --git a/src/Services/Coupon/Coupon.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs b/src/Services/Coupon/Coupon.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs new file mode 100644 index 000000000..054c31235 --- /dev/null +++ b/src/Services/Coupon/Coupon.API/Infrastructure/Filters/HttpGlobalExceptionFilter.cs @@ -0,0 +1,64 @@ +using System.Net; +using Coupon.API.Infrastructure.ActionResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace Coupon.API.Infrastructure.Filters; + +public class HttpGlobalExceptionFilter : IExceptionFilter +{ + private readonly IWebHostEnvironment env; + private readonly ILogger logger; + + public HttpGlobalExceptionFilter(IWebHostEnvironment env, ILogger logger) + { + this.env = env; + this.logger = logger; + } + + public void OnException(ExceptionContext context) + { + logger.LogError(new EventId(context.Exception.HResult), + context.Exception, + context.Exception.Message); + + // TODO: Create domain exception + if (context.Exception.GetType() == typeof(Exception)) + { + var problemDetails = new ValidationProblemDetails() + { + Instance = context.HttpContext.Request.Path, + Status = StatusCodes.Status400BadRequest, + Detail = "Please refer to the errors property for additional details." + }; + + problemDetails.Errors.Add("DomainValidations", new string[] { context.Exception.Message.ToString() }); + + context.Result = new BadRequestObjectResult(problemDetails); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; + } + else + { + var json = new JsonErrorResponse + { + Messages = new[] { "An error ocurred." } + }; + + if (env.IsDevelopment()) + { + json.DeveloperMessage = context.Exception; + } + + context.Result = new InternalServerErrorObjectResult(json); + context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError; + } + context.ExceptionHandled = true; + } + + private class JsonErrorResponse + { + public string[] Messages { get; set; } + + public object DeveloperMessage { get; set; } + } +} diff --git a/src/Services/Coupon/Coupon.API/Program.cs b/src/Services/Coupon/Coupon.API/Program.cs new file mode 100644 index 000000000..b2371a509 --- /dev/null +++ b/src/Services/Coupon/Coupon.API/Program.cs @@ -0,0 +1,53 @@ +using Coupon.API.Extensions; +using HealthChecks.UI.Client; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; + +var builder = WebApplication.CreateBuilder(args); +var configuration = builder.Configuration; + +builder.Services + .AddEndpointsApiExplorer() + .AddSwagger() + .AddApiVersioning() + .AddAppInsight(configuration) + .AddCustomMVC() + .AddCustomOptions(configuration) + .AddEventBus(configuration) + .AddCustomHealthCheck(configuration); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseRouting(); +app.UseAuthorization(); + +var pathBase = configuration["PATH_BASE"]; +if (!string.IsNullOrEmpty(pathBase)) +{ + app.UsePathBase(pathBase); +} + +app.UseEndpoints(endpoints => +{ + endpoints.MapControllers(); + + endpoints.MapHealthChecks("/hc", new HealthCheckOptions + { + Predicate = _ => true, + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + endpoints.MapHealthChecks("/liveness", new HealthCheckOptions + { + Predicate = r => r.Name.Contains("self") + }); +}); + +app.Run(); \ No newline at end of file diff --git a/src/Coupon.API/Properties/launchSettings.json b/src/Services/Coupon/Coupon.API/Properties/launchSettings.json similarity index 100% rename from src/Coupon.API/Properties/launchSettings.json rename to src/Services/Coupon/Coupon.API/Properties/launchSettings.json diff --git a/src/Services/Coupon/Coupon.API/appsettings.Development.json b/src/Services/Coupon/Coupon.API/appsettings.Development.json new file mode 100644 index 000000000..2bcb51617 --- /dev/null +++ b/src/Services/Coupon/Coupon.API/appsettings.Development.json @@ -0,0 +1,18 @@ +{ + "ConnectionString": "mongodb://localhost:27017", + "CouponMongoDatabase": "CouponDb", + "Serilog": { + "MinimumLevel": { + "Default": "Debug", + "Override": { + "Microsoft": "Warning", + "Microsoft.eShopOnContainers": "Debug", + "System": "Warning" + } + } + }, + "IdentityUrlExternal": "http://localhost:5105", + "IdentityUrl": "http://localhost:5105", + "AzureServiceBusEnabled": false, + "EventBusConnection": "localhost" +} \ No newline at end of file diff --git a/src/Services/Coupon/Coupon.API/appsettings.json b/src/Services/Coupon/Coupon.API/appsettings.json new file mode 100644 index 000000000..168a1daca --- /dev/null +++ b/src/Services/Coupon/Coupon.API/appsettings.json @@ -0,0 +1,28 @@ +{ + "ConnectionString": null, + "CouponMongoDatabase": "CouponDb", + "UseCustomizationData": false, + "Serilog": { + "SeqServerUrl": null, + "LogstashUrl": null, + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft": "Warning", + "Microsoft.eShopOnContainers": "Information", + "System": "Warning" + } + } + }, + "SubscriptionClientName": "Coupon", + "ApplicationInsights": { + "InstrumentationKey": "" + }, + "EventBusRetryCount": 5, + "UseVault": false, + "Vault": { + "Name": "eshop", + "ClientId": "your-client-id", + "ClientSecret": "your-client-secret" + } +} \ No newline at end of file diff --git a/src/Services/Coupon/Coupon.API/eshop.pfx b/src/Services/Coupon/Coupon.API/eshop.pfx new file mode 100644 index 000000000..8af82972f Binary files /dev/null and b/src/Services/Coupon/Coupon.API/eshop.pfx differ diff --git a/src/Services/Identity/Identity.API/Dockerfile b/src/Services/Identity/Identity.API/Dockerfile index 674cc4ec1..62c3bc028 100644 --- a/src/Services/Identity/Identity.API/Dockerfile +++ b/src/Services/Identity/Identity.API/Dockerfile @@ -24,6 +24,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/Services/Ordering/Ordering.API/Dockerfile b/src/Services/Ordering/Ordering.API/Dockerfile index 905d3bcd0..560a60c5c 100644 --- a/src/Services/Ordering/Ordering.API/Dockerfile +++ b/src/Services/Ordering/Ordering.API/Dockerfile @@ -24,6 +24,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile b/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile index 0a5ce8f0c..d2923dc37 100644 --- a/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile +++ b/src/Services/Ordering/Ordering.BackgroundTasks/Dockerfile @@ -24,6 +24,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/Services/Ordering/Ordering.SignalrHub/Dockerfile b/src/Services/Ordering/Ordering.SignalrHub/Dockerfile index 33771bf1f..f51b5d0cf 100644 --- a/src/Services/Ordering/Ordering.SignalrHub/Dockerfile +++ b/src/Services/Ordering/Ordering.SignalrHub/Dockerfile @@ -24,6 +24,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/Services/Payment/Payment.API/Dockerfile b/src/Services/Payment/Payment.API/Dockerfile index e91ed767b..caefc955e 100644 --- a/src/Services/Payment/Payment.API/Dockerfile +++ b/src/Services/Payment/Payment.API/Dockerfile @@ -24,6 +24,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/Services/Webhooks/Webhooks.API/Dockerfile b/src/Services/Webhooks/Webhooks.API/Dockerfile index b5fb88684..54186fd5f 100644 --- a/src/Services/Webhooks/Webhooks.API/Dockerfile +++ b/src/Services/Webhooks/Webhooks.API/Dockerfile @@ -24,6 +24,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/Web/WebMVC/Dockerfile b/src/Web/WebMVC/Dockerfile index 470de25d2..d70dfe1d0 100644 --- a/src/Web/WebMVC/Dockerfile +++ b/src/Web/WebMVC/Dockerfile @@ -24,6 +24,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/Web/WebSPA/Dockerfile b/src/Web/WebSPA/Dockerfile index 00ff8b3b5..ceca4c045 100644 --- a/src/Web/WebSPA/Dockerfile +++ b/src/Web/WebSPA/Dockerfile @@ -35,6 +35,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/Web/WebStatus/Dockerfile b/src/Web/WebStatus/Dockerfile index 47ecbd9e4..0f3ffe462 100644 --- a/src/Web/WebStatus/Dockerfile +++ b/src/Web/WebStatus/Dockerfile @@ -24,6 +24,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/Web/WebhookClient/Dockerfile b/src/Web/WebhookClient/Dockerfile index c25957029..14131701c 100644 --- a/src/Web/WebhookClient/Dockerfile +++ b/src/Web/WebhookClient/Dockerfile @@ -25,6 +25,7 @@ COPY "Services/Basket/Basket.UnitTests/Basket.UnitTests.csproj" "Services/Basket COPY "Services/Catalog/Catalog.API/Catalog.API.csproj" "Services/Catalog/Catalog.API/Catalog.API.csproj" COPY "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" "Services/Catalog/Catalog.FunctionalTests/Catalog.FunctionalTests.csproj" COPY "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" "Services/Catalog/Catalog.UnitTests/Catalog.UnitTests.csproj" +COPY "Services/Coupon/Coupon.API/Coupon.API.csproj" "Services/Coupon/Coupon.API/Coupon.API.csproj" COPY "Services/Identity/Identity.API/Identity.API.csproj" "Services/Identity/Identity.API/Identity.API.csproj" COPY "Services/Ordering/Ordering.API/Ordering.API.csproj" "Services/Ordering/Ordering.API/Ordering.API.csproj" COPY "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" "Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj" diff --git a/src/docker-compose.override.yml b/src/docker-compose.override.yml index 8251636e9..409014d38 100644 --- a/src/docker-compose.override.yml +++ b/src/docker-compose.override.yml @@ -100,7 +100,28 @@ services: ports: - "5101:80" - "9101:81" - + + coupon-api: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ConnectionString=mongodb://nosqldata + - CouponMongoDatabase=CouponDb + - EventBusConnection=${ESHOP_AZURE_SERVICE_BUS:-rabbitmq} + - EventBusUserName=${ESHOP_SERVICE_BUS_USERNAME} + - EventBusPassword=${ESHOP_SERVICE_BUS_PASSWORD} + - AzureStorageAccountName=${ESHOP_AZURE_STORAGE_CATALOG_NAME} + - AzureStorageAccountKey=${ESHOP_AZURE_STORAGE_CATALOG_KEY} + - UseCustomizationData=True + - AzureServiceBusEnabled=False + - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} + - OrchestratorType=${ORCHESTRATOR_TYPE} + - GRPC_PORT=81 + - PORT=80 + - PATH_BASE=/coupon-api + ports: + - "5110:80" + - "9110:81" + ordering-api: environment: - ASPNETCORE_ENVIRONMENT=Development @@ -177,27 +198,29 @@ services: volumes: - ./ApiGateways/Envoy/config/mobileshopping:/etc/envoy ports: - - "5200:80" - - "15200:8001" + - "5200:80" + - "15200:8001" webshoppingapigw: volumes: - ./ApiGateways/Envoy/config/webshopping:/etc/envoy ports: - - "5202:80" - - "15202:8001" + - "5202:80" + - "15202:8001" mobileshoppingagg: environment: - ASPNETCORE_ENVIRONMENT=Development - urls__basket=http://basket-api - urls__catalog=http://catalog-api + - urls__coupon=http://coupon-api - urls__orders=http://ordering-api - urls__identity=http://identity-api - urls__grpcBasket=http://basket-api:81 - urls__grpcCatalog=http://catalog-api:81 - urls__grpcOrdering=http://ordering-api:81 - CatalogUrlHC=http://catalog-api/hc + - CouponUrlHC=http://coupon-api/hc - OrderingUrlHC=http://ordering-api/hc - IdentityUrlHC=http://identity-api/hc - BasketUrlHC=http://basket-api/hc @@ -211,12 +234,14 @@ services: - ASPNETCORE_ENVIRONMENT=Development - urls__basket=http://basket-api - urls__catalog=http://catalog-api + - urls__coupon=http://coupon-api - urls__orders=http://ordering-api - urls__identity=http://identity-api - urls__grpcBasket=http://basket-api:81 - urls__grpcCatalog=http://catalog-api:81 - urls__grpcOrdering=http://ordering-api:81 - CatalogUrlHC=http://catalog-api/hc + - CouponUrlHC=http://coupon-api/hc - OrderingUrlHC=http://ordering-api/hc - IdentityUrlHC=http://identity-api/hc - BasketUrlHC=http://basket-api/hc @@ -257,14 +282,16 @@ services: - HealthChecksUI__HealthChecks__5__Uri=http://basket-api/hc - HealthChecksUI__HealthChecks__6__Name=Catalog HTTP Check - HealthChecksUI__HealthChecks__6__Uri=http://catalog-api/hc - - HealthChecksUI__HealthChecks__7__Name=Identity HTTP Check - - HealthChecksUI__HealthChecks__7__Uri=http://identity-api/hc - - HealthChecksUI__HealthChecks__8__Name=Payments HTTP Check - - HealthChecksUI__HealthChecks__8__Uri=http://payment-api/hc - - HealthChecksUI__HealthChecks__9__Name=Ordering SignalRHub HTTP Check - - HealthChecksUI__HealthChecks__9__Uri=http://ordering-signalrhub/hc - - HealthChecksUI__HealthChecks__10__Name=Ordering HTTP Background Check - - HealthChecksUI__HealthChecks__10__Uri=http://ordering-backgroundtasks/hc + - HealthChecksUI__HealthChecks__7__Name=Coupon HTTP Check + - HealthChecksUI__HealthChecks__7__Uri=http://coupon-api/hc + - HealthChecksUI__HealthChecks__8__Name=Identity HTTP Check + - HealthChecksUI__HealthChecks__8__Uri=http://identity-api/hc + - HealthChecksUI__HealthChecks__9__Name=Payments HTTP Check + - HealthChecksUI__HealthChecks__9__Uri=http://payment-api/hc + - HealthChecksUI__HealthChecks__10__Name=Ordering SignalRHub HTTP Check + - HealthChecksUI__HealthChecks__10__Uri=http://ordering-signalrhub/hc + - HealthChecksUI__HealthChecks__11__Name=Ordering HTTP Background Check + - HealthChecksUI__HealthChecks__11__Uri=http://ordering-backgroundtasks/hc - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - OrchestratorType=${ORCHESTRATOR_TYPE} ports: diff --git a/src/docker-compose.prod.yml b/src/docker-compose.prod.yml index 3ff3aa2f2..1ce2ec62a 100644 --- a/src/docker-compose.prod.yml +++ b/src/docker-compose.prod.yml @@ -114,6 +114,7 @@ services: - IdentityUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105. - PurchaseUrl=http://${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}:5202 - CatalogUrlHC=http://catalog-api/hc + - CouponUrlHC=http://coupon-api/hc - OrderingUrlHC=http://ordering-api/hc - IdentityUrlHC=http://identity-api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. - BasketUrlHC=http://basket-api/hc @@ -131,6 +132,7 @@ services: - PurchaseUrl=http://webshoppingapigw - IdentityUrl=http://10.0.75.1:5105 # Local Mac: Use http://docker.for.mac.localhost:5105 || Local Windows: Use 10.0.75.1 in a "Docker for Windows" environment, if using "localhost" from browser. || #Remote access: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP} if using external IP or DNS name from browser. - CatalogUrlHC=http://catalog-api/hc + - CouponUrlHC=http://coupon-api/hc - OrderingUrlHC=http://ordering-api/hc - IdentityUrlHC=http://identity-api/hc #Local: Use ${ESHOP_PROD_EXTERNAL_DNS_NAME_OR_IP}, if using external IP or DNS name from browser. - BasketUrlHC=http://basket-api/hc diff --git a/src/docker-compose.yml b/src/docker-compose.yml index e1e16a629..2da4e77dd 100644 --- a/src/docker-compose.yml +++ b/src/docker-compose.yml @@ -43,6 +43,16 @@ services: depends_on: - sqldata - rabbitmq + + coupon-api: + image: ${REGISTRY:-eshop}/coupon.api:${PLATFORM:-linux}-${TAG:-latest} + build: + context: . + dockerfile: Services/Coupon/Coupon.API/Dockerfile + depends_on: + - sqldata + - nosqldata + - rabbitmq ordering-api: image: ${REGISTRY:-eshop}/ordering.api:${PLATFORM:-linux}-${TAG:-latest} diff --git a/src/eShopOnContainers-ServicesAndWebApps.sln b/src/eShopOnContainers-ServicesAndWebApps.sln index 05021db2c..6bdce4959 100644 --- a/src/eShopOnContainers-ServicesAndWebApps.sln +++ b/src/eShopOnContainers-ServicesAndWebApps.sln @@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web Apps", "Web Apps", "{E2 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Catalog", "Catalog", "{326A7FB3-5295-468C-A4FE-67DCB823E1E5}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Coupon", "Coupon", "{112D21CD-E9A7-4815-81EF-ECB61E2D9CC2}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Basket", "Basket", "{BF3EF4F3-E4F5-41DA-9D2D-57223687D1A8}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ordering", "Ordering", "{0BD0DB92-2D98-44D9-9AC0-C59186D59B0B}" @@ -33,6 +35,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Basket.API", "Services\Bask EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Catalog.API", "Services\Catalog\Catalog.API\Catalog.API.csproj", "{42681D9D-750A-4DF7-BD9F-9292CFD5C253}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Coupon.API", "Services\Coupon\Coupon.API\Coupon.API.csproj", "{181F8727-ECA0-4D10-B6E5-E73593D35DA6}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.API", "Services\Ordering\Ordering.API\Ordering.API.csproj", "{231226CE-690B-4979-8870-9A79D80928E2}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ordering.Domain", "Services\Ordering\Ordering.Domain\Ordering.Domain.csproj", "{F5598DCB-6DDE-4661-AD9D-A55612DA7E76}" @@ -124,10 +128,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{373D8AA1 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventBus.Tests", "BuildingBlocks\EventBus\EventBus.Tests\EventBus.Tests.csproj", "{95D735BE-2899-4495-BE3F-2600E93B4E3C}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Coupon", "Coupon", "{EA8E5543-46DB-4646-B29B-847756FF0B37}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Coupon.API", "Coupon.API\Coupon.API.csproj", "{A50CFB1D-A31D-4399-9115-CF79A004E106}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -256,6 +256,32 @@ Global {42681D9D-750A-4DF7-BD9F-9292CFD5C253}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {42681D9D-750A-4DF7-BD9F-9292CFD5C253}.Release|x64.ActiveCfg = Release|Any CPU {42681D9D-750A-4DF7-BD9F-9292CFD5C253}.Release|x86.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.AppStore|ARM.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.AppStore|iPhone.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.AppStore|x64.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.AppStore|x86.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Debug|ARM.ActiveCfg = Debug|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Debug|x64.ActiveCfg = Debug|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Debug|x86.ActiveCfg = Debug|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Release|Any CPU.Build.0 = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Release|ARM.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Release|iPhone.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Release|x64.ActiveCfg = Release|Any CPU + {181F8727-ECA0-4D10-B6E5-E73593D35DA6}.Release|x86.ActiveCfg = Release|Any CPU {231226CE-690B-4979-8870-9A79D80928E2}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU {231226CE-690B-4979-8870-9A79D80928E2}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU {231226CE-690B-4979-8870-9A79D80928E2}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU @@ -1534,54 +1560,6 @@ Global {95D735BE-2899-4495-BE3F-2600E93B4E3C}.Release|x64.Build.0 = Release|Any CPU {95D735BE-2899-4495-BE3F-2600E93B4E3C}.Release|x86.ActiveCfg = Release|Any CPU {95D735BE-2899-4495-BE3F-2600E93B4E3C}.Release|x86.Build.0 = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|ARM.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|ARM.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|x64.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|x64.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Ad-Hoc|x86.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|ARM.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|ARM.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|iPhone.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|iPhone.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|x64.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|x64.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|x86.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.AppStore|x86.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|ARM.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|ARM.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|iPhone.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|x64.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|x64.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|x86.ActiveCfg = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Debug|x86.Build.0 = Debug|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|Any CPU.Build.0 = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|ARM.ActiveCfg = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|ARM.Build.0 = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|iPhone.ActiveCfg = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|iPhone.Build.0 = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|x64.ActiveCfg = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|x64.Build.0 = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|x86.ActiveCfg = Release|Any CPU - {A50CFB1D-A31D-4399-9115-CF79A004E106}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1590,12 +1568,14 @@ Global {91CF7717-08AB-4E65-B10E-0B426F01E2E8} = {932D8224-11F6-4D07-B109-DA28AD288A63} {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04} = {932D8224-11F6-4D07-B109-DA28AD288A63} {326A7FB3-5295-468C-A4FE-67DCB823E1E5} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} + {112D21CD-E9A7-4815-81EF-ECB61E2D9CC2} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {BF3EF4F3-E4F5-41DA-9D2D-57223687D1A8} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {EF0337F2-ED00-4643-89FD-EE10863F1870} = {A857AD10-40FF-4303-BEC2-FF1C58D5735E} {24CD3B53-141E-4A07-9B0D-796641E1CF78} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} {2110CBB0-3B38-4EE4-A743-DF6968D80D90} = {BF3EF4F3-E4F5-41DA-9D2D-57223687D1A8} {42681D9D-750A-4DF7-BD9F-9292CFD5C253} = {326A7FB3-5295-468C-A4FE-67DCB823E1E5} + {181F8727-ECA0-4D10-B6E5-E73593D35DA6} = {112D21CD-E9A7-4815-81EF-ECB61E2D9CC2} {231226CE-690B-4979-8870-9A79D80928E2} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} {F5598DCB-6DDE-4661-AD9D-A55612DA7E76} = {0BD0DB92-2D98-44D9-9AC0-C59186D59B0B} {F0333D8E-0B27-42B7-B2C6-78F3657624E2} = {E279BF0F-7F66-4F3A-A3AB-2CDA66C1CD04} @@ -1640,8 +1620,6 @@ Global {B62E859F-825E-4C8B-93EC-5966EACFD026} = {798BFC44-2CCD-45FA-B37A-5173B03C2B30} {373D8AA1-36BE-49EC-89F0-6CB736666285} = {807BB76E-B2BB-47A2-A57B-3D1B20FF5E7F} {95D735BE-2899-4495-BE3F-2600E93B4E3C} = {373D8AA1-36BE-49EC-89F0-6CB736666285} - {EA8E5543-46DB-4646-B29B-847756FF0B37} = {91CF7717-08AB-4E65-B10E-0B426F01E2E8} - {A50CFB1D-A31D-4399-9115-CF79A004E106} = {EA8E5543-46DB-4646-B29B-847756FF0B37} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {25728519-5F0F-4973-8A64-0A81EB4EA8D9}