Skip to content

Commit

Permalink
Add baseline code for other API endpoints
Browse files Browse the repository at this point in the history
- Add code for get ad update lambdas
- Add OpenAPI spec
- Build lambda containers in CI
- Deploy lambdas for each endpoint
- Update tests to

This includes adding `docs/schemas/lpa.json`, which can serve as a public JSON Schema definition _and_ get used in the OpenAPI doc.

For VEGA-2104 #minor
  • Loading branch information
gregtyler committed Oct 23, 2023
1 parent 90e5d8c commit b336ba7
Show file tree
Hide file tree
Showing 25 changed files with 450 additions and 21 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/build-push-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ jobs:
include:
- ecr_repository: lpa-store/lambda/api-create
dir: create
- ecr_repository: lpa-store/lambda/api-get
dir: get
- ecr_repository: lpa-store/lambda/api-update
dir: update
runs-on: ubuntu-latest
name: ${{ matrix.ecr_repository }}
steps:
Expand Down
8 changes: 5 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export AWS_ACCESS_KEY_ID ?= X
export AWS_SECRET_ACCESS_KEY ?= X

build:
docker compose build --parallel lambda-create apigw
docker compose build --parallel lambda-create lambda-update lambda-get apigw

up:
docker compose up -d apigw
Expand All @@ -16,7 +16,9 @@ test-api: URL ?= http://localhost:9000
test-api:
go build -o ./signer/test-api ./signer && \
chmod +x ./signer/test-api && \
./signer/test-api PUT $(URL)/lpas/M-AL9A-7EY3-075D '{"uid":"M-AL9A-7EY3-075D","version":"1"}'
./signer/test-api PUT $(URL)/lpas/M-AL9A-7EY3-075D '{"version":"1"}' && \
./signer/test-api POST $(URL)/lpas/M-AL9A-7EY3-075D/updates '{"type":"BUMP_VERSION","changes":[{"key":"/version","old":"1","new":"2"}]}' && \
./signer/test-api GET $(URL)/lpas/M-AL9A-7EY3-075D '' | grep '"version":"2"' \

create-tables:
docker compose run --rm aws dynamodb describe-table --table-name deeds || \
Expand All @@ -27,7 +29,7 @@ create-tables:
--billing-mode PAY_PER_REQUEST

docker compose run --rm aws dynamodb describe-table --table-name events || \
docker compose run --rm aws dynamodb create-table \
docker compose run --rm aws dynamodb create-ta~ble \
--table-name events \
--attribute-definitions AttributeName=uid,AttributeType=S AttributeName=created,AttributeType=S \
--key-schema AttributeName=uid,KeyType=HASH AttributeName=created,KeyType=RANGE \
Expand Down
36 changes: 35 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,42 @@ services:
- "./lambda/.aws-lambda-rie:/aws-lambda"
entrypoint: /aws-lambda/aws-lambda-rie /var/task/main

lambda-update:
depends_on: [ddb]
build:
context: .
dockerfile: ./lambda/Dockerfile
args:
- DIR=update
environment:
AWS_REGION: eu-west-1
AWS_DYNAMODB_ENDPOINT: http://ddb:8000
AWS_ACCESS_KEY_ID: X
AWS_SECRET_ACCESS_KEY: X
DDB_TABLE_NAME_DEEDS: deeds
volumes:
- "./lambda/.aws-lambda-rie:/aws-lambda"
entrypoint: /aws-lambda/aws-lambda-rie /var/task/main

lambda-get:
depends_on: [ddb]
build:
context: .
dockerfile: ./lambda/Dockerfile
args:
- DIR=get
environment:
AWS_REGION: eu-west-1
AWS_DYNAMODB_ENDPOINT: http://ddb:8000
AWS_ACCESS_KEY_ID: X
AWS_SECRET_ACCESS_KEY: X
DDB_TABLE_NAME_DEEDS: deeds
volumes:
- "./lambda/.aws-lambda-rie:/aws-lambda"
entrypoint: /aws-lambda/aws-lambda-rie /var/task/main

apigw:
depends_on: [lambda-create]
depends_on: [lambda-create, lambda-update, lambda-get]
build: ./mock-apigw
ports:
- 9000:8080
Expand Down
99 changes: 97 additions & 2 deletions docs/openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ paths:
content:
application/json:
schema:
type: object
additionalProperties: false
$ref: "#/components/schemas/Lpa"
responses:
"201":
description: Case created
Expand All @@ -50,6 +49,74 @@ paths:
httpMethod: "POST"
type: "aws_proxy"
contentHandling: "CONVERT_TO_TEXT"
get:
operationId: getLpa
summary: Retrieve an LPA
requestBody:
content:
application/json:
schema:
type: object
additionalProperties: false
responses:
"200":
description: Case found
content:
application/json:
schema:
$ref: "#/components/schemas/Lpa"
"400":
description: Invalid request
content:
application/json:
schema:
$ref: "#/components/schemas/BadRequestError"
x-amazon-apigateway-auth:
type: "AWS_IAM"
x-amazon-apigateway-integration:
uri: ${lambda_get_invoke_arn}
httpMethod: "POST"
type: "aws_proxy"
contentHandling: "CONVERT_TO_TEXT"
/lpas/{uid}/updates:
parameters:
- name: uid
in: path
required: true
description: The UID of the complaint
schema:
type: string
pattern: "M-([A-Z0-9]{4})-([A-Z0-9]{4})-([A-Z0-9]{4})"
example: M-789Q-P4DF-4UX3
post:
operationId: createUpdate
summary: Update an LPA
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/Update"
responses:
"201":
description: Update created
content:
application/json:
schema:
type: object
"400":
description: Invalid request
content:
application/json:
schema:
$ref: "#/components/schemas/BadRequestError"
x-amazon-apigateway-auth:
type: "AWS_IAM"
x-amazon-apigateway-integration:
uri: ${lambda_update_invoke_arn}
httpMethod: "POST"
type: "aws_proxy"
contentHandling: "CONVERT_TO_TEXT"

/health:
get:
operationId: healthCheck
Expand Down Expand Up @@ -125,3 +192,31 @@ components:
example:
- source: "/uid"
detail: "invalid uid format"
Lpa:
$ref: "../schemas/lpa.json"
Update:
type: object
required:
- type
- changes
properties:
type:
enum:
- DONOR_ADDRESS_UPDATE
- ATTORNEY_ADDRESS_UPDATE
- SCANNING_CORRECTION
changes:
type: array
items:
type: object
required:
- key
- old
- new
properties:
key:
type: string
old:
nullable: true
new:
nullable: true
14 changes: 14 additions & 0 deletions docs/schemas/lpa.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$id": "https://opg.service.justice.gov.uk/schema/lpa/2023-10",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "LPA",
"description": "Digital representation of a Lasting Power of Attorney",
"type": "object",
"properties": {
"uid": {
"type": "string",
"pattern": "M-([A-Z0-9]{4})-([A-Z0-9]{4})-([A-Z0-9]{4})",
"example": "M-789Q-P4DF-4UX3"
}
}
}
2 changes: 2 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ go 1.21.0

use (
./lambda/create
./lambda/get
./lambda/shared
./lambda/update
./mock-apigw
./signer
)
5 changes: 4 additions & 1 deletion go.work.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
github.com/aws/aws-sdk-go-v2 v1.6.0/go.mod h1:tI4KhsR5VkzlUa2DZAdwx7wCAYGwkZZ1H31PYrBFx1w=
github.com/aws/aws-sdk-go-v2/service/route53 v1.6.2/go.mod h1:ZnAMilx42P7DgIrdjlWCkNIGSBLzeyk6T31uB8oGTwY=
github.com/aws/smithy-go v1.4.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
Expand All @@ -15,3 +17,4 @@ golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
2 changes: 1 addition & 1 deletion lambda/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
FROM golang:1.21.0 AS build-env

ARG DIR
WORKDIR /app

COPY go.work .
COPY go.work.sum .

COPY . .

ARG DIR
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -o /go/bin/main ./lambda/$DIR

FROM alpine:3
Expand Down
4 changes: 3 additions & 1 deletion lambda/create/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Lambda struct {
}

func (l *Lambda) HandleEvent(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
var data shared.Case
var data shared.Lpa
response := events.APIGatewayProxyResponse{
StatusCode: 500,
Body: "{\"code\":\"INTERNAL_SERVER_ERROR\",\"detail\":\"Internal server error\"}",
Expand All @@ -37,6 +37,8 @@ func (l *Lambda) HandleEvent(ctx context.Context, event events.APIGatewayProxyRe
return shared.ProblemInternalServerError.Respond()
}

data.Uid = event.PathParameters["uid"]

if data.Version == "" {
problem := shared.ProblemInvalidRequest
problem.Errors = []shared.FieldError{
Expand Down
11 changes: 11 additions & 0 deletions lambda/get/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module github.com/ministryofjustice/opg-data-lpa-deed/lambda/get

go 1.21.0

toolchain go1.21.3

require (
github.com/aws/aws-lambda-go v1.41.0
github.com/ministryofjustice/opg-data-lpa-deed/lambda/shared v0.0.0-20231012101804-da267f23d7db
github.com/ministryofjustice/opg-go-common v0.0.0-20220816144329-763497f29f90
)
14 changes: 14 additions & 0 deletions lambda/get/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
github.com/aws/aws-lambda-go v1.41.0 h1:l/5fyVb6Ud9uYd411xdHZzSf2n86TakxzpvIoz7l+3Y=
github.com/aws/aws-lambda-go v1.41.0/go.mod h1:jwFe2KmMsHmffA1X2R09hH6lFzJQxzI8qK17ewzbQMM=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ministryofjustice/opg-data-lpa-deed/lambda/shared v0.0.0-20231012101804-da267f23d7db h1:HcdoeSkWe5Bkokl3SvmaOlPNsCk+T78oQqVDrFNgsD8=
github.com/ministryofjustice/opg-data-lpa-deed/lambda/shared v0.0.0-20231012101804-da267f23d7db/go.mod h1:uarvaw7JMaubij8CuiO2bNcJBp8zWEdiU+AVqe78Ggc=
github.com/ministryofjustice/opg-go-common v0.0.0-20220816144329-763497f29f90 h1:mxTHIeCYV7LDZPN7C44wwLlBTUsgQ0G8FQprsrsKXaA=
github.com/ministryofjustice/opg-go-common v0.0.0-20220816144329-763497f29f90/go.mod h1:1RmCNi6dkAv8umAgNHp8RkuBoSKLlxp1UtfsGYH7ufc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
56 changes: 56 additions & 0 deletions lambda/get/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package main

import (
"context"
"encoding/json"
"os"

"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/ministryofjustice/opg-data-lpa-deed/lambda/shared"
"github.com/ministryofjustice/opg-go-common/logging"
)

type Logger interface {
Print(...interface{})
}

type Lambda struct {
store shared.Client
logger Logger
}

func (l *Lambda) HandleEvent(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
response := events.APIGatewayProxyResponse{
StatusCode: 500,
Body: "{\"code\":\"INTERNAL_SERVER_ERROR\",\"detail\":\"Internal server error\"}",
}

lpa, err := l.store.Get(ctx, event.PathParameters["uid"])

if err != nil {
l.logger.Print(err)
return shared.ProblemInternalServerError.Respond()
}

body, err := json.Marshal(lpa)

if err != nil {
l.logger.Print(err)
return shared.ProblemInternalServerError.Respond()
}

response.StatusCode = 200
response.Body = string(body)

return response, nil
}

func main() {
l := &Lambda{
store: shared.NewDynamoDB(os.Getenv("DDB_TABLE_NAME_DEEDS")),
logger: logging.New(os.Stdout, "opg-data-lpa-deed"),
}

lambda.Start(l.HandleEvent)
}
5 changes: 2 additions & 3 deletions lambda/shared/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
)

type Client interface {
Put(ctx context.Context, data Case) error
// Get(ctx context.Context, id string) (Case, error)
// Patch(ctx context.Context, id string, data Update) (Case, error)
Put(ctx context.Context, data Lpa) error
Get(ctx context.Context, uid string) (Lpa, error)
}
Loading

0 comments on commit b336ba7

Please sign in to comment.