Skip to content

Commit

Permalink
Add Swagger docs. Add validation for a maximum name length of 50.
Browse files Browse the repository at this point in the history
Remove unused PostGres environment variable. Update Readme.
  • Loading branch information
connorads committed Nov 14, 2018
1 parent ea5edfd commit 615839c
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 23 deletions.
34 changes: 19 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,29 @@ Get a personalised birthday countdown and happy birthday message 🎂
* When Connor's Birthday is today:
* `{ "message" : "Hello, Connor! Happy Birthday!" }`

![Swagger UI](https://i.postimg.cc/CLRY9mD4/happy-birthday-world.gif)

## Environments

Running on my Google Cloud Platform, please don't hammer it 😅
Happy Birthday World is deployed on Google Cloud Platform*
It's got the Swagger UI running so you can test it quite easily 👍
Probably best to avoid the Staging environment for now 😬

Environment | Repo | Storage Status
----------- | -------------- | --------------
Local | ¯\\\_(ツ)\_/¯ | Works with PostgreSQL and in-memory mode
[Staging](http://happy-birthday-world.jx-staging.35.234.144.66.nip.io/) | [razorbow-staging](https://github.com/connorads/environment-razorbow-staging) |Not working, needs Cloud SQL proxy sidecar
[Production](http://happy-birthday-world.jx-production.35.234.144.66.nip.io/) | [razorbow-production](https://github.com/connorads/environment-razorbow-production) |Works but in-memory (ephemeral)
Local | ¯\\\_(ツ)\_/¯ | PostgreSQL or in-memory mode
[Staging](http://happy-birthday-world.jx-staging.35.234.144.66.nip.io/) | [razorbow-staging](https://github.com/connorads/environment-razorbow-staging) |Connected to Staging Cloud SQL instance
[Production](http://happy-birthday-world.jx-production.35.234.144.66.nip.io/) | [razorbow-production](https://github.com/connorads/environment-razorbow-production) |Using in-memory mode (ephemeral)

_* for as long as my credits last ... please don't hammer it 😅_


## Technologies

A non-exhaustive list of technologies used.

* ASP.NET Core 2.1
* Swagger / Swashbuckle.AspNetCore
* xUnit
* PostgreSQL / Google Cloud SQL
* Kubernetes / GKE
* NGINX
Expand All @@ -39,7 +45,6 @@ A non-exhaustive list of technologies used.
* Nexus
* Fabric8


### Jenkins-X

[Jenkins X](https://jenkins-x.io/) is a CI/CD solution for modern cloud applications on Kubernetes.
Expand All @@ -53,23 +58,22 @@ If you want to promote a version of your app to production:
![GKE Services](http://i68.tinypic.com/29xgfms.png)
![Cloud SQL](http://i64.tinypic.com/2rm39lf.png)


## Assumptions

Here are some assumptions that need to be validated by the "Product Owner" 👀

* Leap-year babies are born on February 29th. We currently assume a birthday of February 28th on non-leap years for leap-year babies. But some "leapers" celebrate on March 1st [*[Wikipedia]*](https://bit.ly/2ENDhFe)
* Dates of Birth in the future are invalid. We perform validation to ensure that the Date of Births entered on the API are not in the future because otherwise it's difficult to define the expected behaviour.
* Name can be a maximum of [50 characters](https://stackoverflow.com/a/15474655/4319653).

## Todo

* Update this README!
* Deploy Cloud SQL proxy sidecar in Staging
* Tidy up secrets: got a mix/repeat of DB secrets with env and volumes
* Setup database in Production environment
* ~~Deploy Cloud SQL proxy sidecar in Staging~~
* ~~Tidy up secrets: got a mix/repeat of DB secrets with env and volumes~~
* ~~Upgrade Swagger page to show example date format using C# XML comments~~
* Connect Cloud SQL in "Production" (perhaps use [PodPreset](https://kubernetes.io/docs/concepts/workloads/pods/podpreset/) to [define Cloud SQL Instances](https://cloud.google.com/sql/docs/mysql/sql-proxy#instances-options) in [deployment yaml command argument](https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/))
* Automatically run tests as part of the build ([*dotnet docker best practices*](https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/dotnet-docker-unit-testing.md))
* Add Database Health check
* Upgrade Swagger page to show example date format using C# XML comments
* Return validation error message for when a DOB that is in the future is submitted
* JX Pull request preview environment deployment doesn't work 😥
* Automatically run tests as part of the build [*(dotnet docker best practices)*](https://github.com/dotnet/dotnet-docker/blob/master/samples/dotnetapp/dotnet-docker-unit-testing.md)
* Return validation error message for when a DOB that is in the future is submitted (it already returns a bad request but without a reason)
* Fix JX Pull request preview environment deployments
* Many more ...
3 changes: 0 additions & 3 deletions charts/happy-birthday-world/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ spec:
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.internalPort }}
env:
- name: POSTGRES_DB_HOST
value: 127.0.0.1:5432
resources:
{{ toYaml .Values.resources | indent 12 }}
volumeMounts:
Expand Down
23 changes: 20 additions & 3 deletions src/Controllers/HelloController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace HappyBirthdayWorld.Api.Controllers
[Route("/hello")]
public class HelloController : Controller
{
private const int MaxNameLength = 50;
private readonly IBirthdayRepository birthdayRepository;
private readonly IBirthdayCalculator birthdayCalculator;

Expand All @@ -22,10 +23,18 @@ public HelloController(
this.birthdayCalculator = birthdayCalculator;
}

/// <summary>
/// Return birthday related message
/// </summary>
/// <param name="name">e.g. "Connor" (Must be 50 characters or less)</param>
[ProducesResponseType(200)]
[ProducesResponseType(400)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
[HttpGet("{name}")]
public ActionResult<string> Get(string name)
public ActionResult<string> Get([MaxLength(MaxNameLength)] string name)
{
if (name == null) return BadRequest();
if (!ModelState.IsValid || name == null) return BadRequest(ModelState);

name = name.Trim();
var foundDob = birthdayRepository.TryGetDateOfBirth(name, out var dateOfBirth);
Expand All @@ -42,9 +51,17 @@ public ActionResult<string> Get(string name)

}

/// <summary>
/// Save/update name and date of birth
/// </summary>
/// <param name="name">e.g. "Connor" (Must be 50 characters or less)</param>
/// <param name="dateOfBirth">e.g. "1997-08-04" (YYYY-MM-DD)</param>
[ProducesResponseType(204)]
[ProducesResponseType(400)]
[ProducesResponseType(500)]
[HttpPut("{name}")]
public ActionResult Put(
[FromRoute, Required] string name,
[FromRoute, Required, MaxLength(MaxNameLength)] string name,
[FromBody, Required] DateOfBirth dateOfBirth)
{
if (!ModelState.IsValid || name == null || DobIsInFuture(dateOfBirth)) return BadRequest(ModelState);
Expand Down
2 changes: 2 additions & 0 deletions src/HappyBirthdayWorld.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

<ItemGroup>
Expand Down
9 changes: 8 additions & 1 deletion src/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using HappyBirthdayWorld.Api.Domain;
using System;
using System.IO;
using System.Reflection;
using HappyBirthdayWorld.Api.Domain;
using HappyBirthdayWorld.Api.Repositories;
using HappyBirthdayWorld.Api.Services;
using Microsoft.AspNetCore.Builder;
Expand Down Expand Up @@ -48,6 +51,10 @@ public void ConfigureServices(IServiceCollection services)
Description = "Get a personalised birthday countdown and happy birthday message.",
Contact = new Contact { Name = "@connorads", Url = "http://connoradams.co.uk" }
});

var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
}

Expand Down
2 changes: 1 addition & 1 deletion test/HelloControllerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public void NullStringGetReturnsBadRequest()

var getResult = helloController.Get(null).Result;

Assert.IsType<BadRequestResult>(getResult);
Assert.IsType<BadRequestObjectResult>(getResult);
}
}
}

0 comments on commit 615839c

Please sign in to comment.