Skip to content

Commit

Permalink
add items api to code config
Browse files Browse the repository at this point in the history
  • Loading branch information
cecilphillip committed Sep 20, 2020
1 parent baa5af4 commit aad905a
Show file tree
Hide file tree
Showing 13 changed files with 400 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/CodeConfigSample/ItemsApi/Controllers/ItemsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace ItemsApi.Controllers
{
[Route("/api/items")]
[ApiController]
public class ItemsController : ControllerBase
{
[HttpGet]
public async Task<ActionResult<IEnumerable<Item>>> GetItems()
{
var result= await DataService.GetItems();
if (result == null || !result.Any()) return NotFound();
return Ok(result);
}

[HttpGet("{id}")]
public async Task<ActionResult<Item>> GetItemByID(int id)
{
var item = await DataService.GetItemByID(id);
if (item == null) return NotFound();
return item;
}
}
}
34 changes: 34 additions & 0 deletions src/CodeConfigSample/ItemsApi/DataService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bogus;

namespace ItemsApi
{
public static class DataService
{
private static List<Item> Items { get; set; }

static DataService()
{
Items = new Faker<Item>()
.RuleFor(i => i.ID, f => f.IndexVariable++)
.RuleFor(i => i.Name, f => f.Commerce.ProductName())
.RuleFor(i => i.Category, f => f.PickRandom(f.Commerce.Categories(5)))
.RuleFor(i => i.Origin, f => f.Address.Country())
.RuleFor(i => i.Quantity, f => f.Random.Number(10, 100))
.Generate(50);
}

public static ValueTask<IEnumerable<Item>> GetItems()
{
return new ValueTask<IEnumerable<Item>>(Items);
}

public static ValueTask<Item> GetItemByID(int id)
{
var item = Items.SingleOrDefault(i => i.ID == id);
return item != null ? new ValueTask<Item>(item) : new ValueTask<Item>();
}
}
}
20 changes: 20 additions & 0 deletions src/CodeConfigSample/ItemsApi/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["ItemsApi.csproj", "./"]
RUN dotnet restore "ItemsApi.csproj"
COPY . .
WORKDIR "/src"
RUN dotnet build "ItemsApi.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "ItemsApi.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ItemsApi.dll"]
11 changes: 11 additions & 0 deletions src/CodeConfigSample/ItemsApi/Item.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace ItemsApi
{
public class Item
{
public int ID { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public string Origin { get; set; }
public int Quantity { get; set; }
}
}
16 changes: 16 additions & 0 deletions src/CodeConfigSample/ItemsApi/ItemsApi.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Bogus" Version="31.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.1" />
<PackageReference Include="Consul" Version="1.6.1.1" />
</ItemGroup>

<ItemGroup>
<Folder Include="Workers\" />
</ItemGroup>
</Project>
22 changes: 22 additions & 0 deletions src/CodeConfigSample/ItemsApi/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace ItemsApi
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

}
}

16 changes: 16 additions & 0 deletions src/CodeConfigSample/ItemsApi/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"ItemsApi": {
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://0.0.0.0:5010",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_URLS" : "http://0.0.0.0:5010"
}
}
}
}
48 changes: 48 additions & 0 deletions src/CodeConfigSample/ItemsApi/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Linq;
using System.Net;
using Consul;
using ItemsApi.Workers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace ItemsApi
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddConsulClient(this IServiceCollection services)
{
return services.AddConsulClient(options => { });
}

public static IServiceCollection AddConsulClient(
this IServiceCollection services,
Action<ConsulClientConfiguration> options)
{
/*
* CONSUL_HTTP_ADDR
* CONSUL_HTTP_SSL
* CONSUL_HTTP_SSL_VERIFY
* CONSUL_HTTP_AUTH
* CONSUL_HTTP_TOKEN
*/
services.TryAddSingleton<IConsulClient>(sp => new ConsulClient(options));

return services;
}

public static IServiceCollection AddConsulServiceRegistration(this IServiceCollection services,
Action<AgentServiceRegistration> options)
{
return services
.AddSingleton(provider =>
{
var registration = new AgentServiceRegistration();
options.Invoke(registration);

return registration;
})
.AddHostedService<ConsulRegistrationService>();
}
}
}
91 changes: 91 additions & 0 deletions src/CodeConfigSample/ItemsApi/Startup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.Net;
using System.Text.Json;
using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;

namespace ItemsApi
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddJsonOptions(option =>
{
option.JsonSerializerOptions.IgnoreNullValues = true;
option.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});

services.AddHealthChecks();
services.AddConsulClient(opts =>
{
var consulClientConfig = Configuration.GetSection("consul:client");
var port = consulClientConfig.GetValue<int>("port");
var host = consulClientConfig.GetValue<string>("host");
var scheme = consulClientConfig.GetValue<string>("scheme");
var dc = consulClientConfig.GetValue<string>("datacenter");

var address = $"{scheme}://{host}:{port}";
opts.Address = new Uri(address);
opts.Datacenter = dc;
});

services.AddConsulServiceRegistration(reg =>
{
Configuration.Bind("consul:registration", reg);

if (string.IsNullOrEmpty(reg.ID))
{
var rand = new Random();
var instanceId = rand.Next().ToString();
reg.ID = $"{reg.Name}-{instanceId}";
}

if (string.IsNullOrEmpty(reg.Address))
{
var dnsHostName = Dns.GetHostName();
var hostname = Dns.GetHostEntry(dnsHostName);
reg.Address = $"http://{hostname.HostName}";
}

reg.Check = new AgentServiceCheck
{
DeregisterCriticalServiceAfter = TimeSpan.FromMinutes(2.5),
Interval = TimeSpan.FromSeconds(30),
Timeout = TimeSpan.FromMinutes(1),
HTTP = $"{reg.Address}:{reg.Port}/health"
};
});

services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo {Title = "ItemsApi", Version = "v1"}); });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "ItemsApi v1"));


app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
endpoints.MapControllers();
});
}
}
}
44 changes: 44 additions & 0 deletions src/CodeConfigSample/ItemsApi/Workers/ConsulRegistrationService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Consul;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace ItemsApi.Workers
{
public class ConsulRegistrationService: BackgroundService
{
private readonly IConsulClient _consulClient;
private readonly AgentServiceRegistration _serviceRegistration;
private readonly ILogger<ConsulRegistrationService> _logger;

public ConsulRegistrationService(IConsulClient consulClient,
AgentServiceRegistration serviceRegistration, ILogger<ConsulRegistrationService> logger)
{
_consulClient = consulClient;
_serviceRegistration = serviceRegistration;
_logger = logger;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
var result = await _consulClient.Agent.ServiceRegister(_serviceRegistration, stoppingToken);
_logger.LogInformation(result.StatusCode.ToString());

}
catch (Exception ex)
{

}
}

public override async Task StopAsync(CancellationToken cancellationToken)
{
await _consulClient.Agent.ServiceDeregister(_serviceRegistration.ID, cancellationToken);
await base.StopAsync(cancellationToken);
}
}
}
27 changes: 27 additions & 0 deletions src/CodeConfigSample/ItemsApi/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"consul": {
"client": {
"host": "localhost",
"port": 8500,
"scheme": "http",
"datacenter" : "yarp_dc"
},
"registration": {
"name": "itemsapi",
"tags": [ "webapi", "items", "webapi", "dotnet", "yarp" ],
"meta" : {
"yarp" : "on",
"yarp_hosts" : "items",
"yarp_path" : "/api/items/{**catchall}"
},
"port": 5010
}
}
}
Loading

0 comments on commit aad905a

Please sign in to comment.