Skip to content

Commit

Permalink
all working
Browse files Browse the repository at this point in the history
  • Loading branch information
MarioCarrion committed Jan 9, 2025
1 parent 78352b6 commit 9d841f9
Show file tree
Hide file tree
Showing 28 changed files with 628 additions and 271 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Docker
on: push
jobs:
build:
strategy:
matrix:
go-version: [1.22.x]
platform: [ubuntu-latest]
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
cache: true
cache-dependency-path: |
**/go.sum
internal/tool/go.sum
- name: Images
run: make docker
14 changes: 11 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# XXX: Adding "run.build-tags" was required before v1.60.x, leaving it here in the meantime
# Seems to be related to: https://github.com/golangci/golangci-lint/issues/4956
# run:
# build-tags:
# - redis
# - rabbitmq
# - kafka
linters:
enable-all: true
disable:
Expand Down Expand Up @@ -31,6 +38,8 @@ linters-settings:
- stdlib
#
- 'go.opentelemetry.io/otel/trace.Span'
- 'github.com/MarioCarrion/todo-api/internal/service.TaskMessageBrokerRepository'
- 'github.com/MarioCarrion/todo-api/cmd/rest-server.MessageBus'
varnamelen:
max-distance: 10
ignore-type-assert-ok: true
Expand All @@ -51,10 +60,9 @@ linters-settings:
- internal.WrapErrorf(
ignorePackageGlobs:
- github.com/MarioCarrion/todo-api/*
gosec:
excludes:
- G601 # "Implicit memory aliasing in for loop." Fixed in Go 1.22
issues:
exclude:
- "NewMessageHub redeclared in this block" # build tags: redis, rabbitmq or kafka
exclude-rules:
# All tests
- path: _test\.go
Expand Down
9 changes: 9 additions & 0 deletions .gonvim/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
return {
lsp_cfg = {
settings = {
gopls = {
buildFlags = {"-tags=redis,rabbitmq,kafka"}
}
}
}
}
18 changes: 10 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
GO_VERSION=1.22.0

.PHONY: all
all: lint test

Expand All @@ -8,6 +6,7 @@ tidy:
go mod tidy
go mod -C internal/tools tidy

.PHONY: tools
tools:
go install -C internal/tools \
github.com/fdaines/spm-go \
Expand All @@ -21,12 +20,6 @@ tools:
goa.design/model/cmd/stz \
golang.org/x/vuln/cmd/govulncheck

install:
go install golang.org/dl/go${GO_VERSION}@latest
go${GO_VERSION} download
mkdir -p bin
ln -sf `go env GOPATH`/bin/go${GO_VERSION} bin/go

# Formatting

.PHONY: fmt
Expand Down Expand Up @@ -68,3 +61,12 @@ security:
.PHONY: test
test:
go test -shuffle=on -race -coverprofile=coverage.txt -covermode=atomic $$(go list ./... | grep -v /cmd/)

# Build

.PHONY: docker
docker:
docker compose -f compose.yml -f compose.noop.yml build
docker compose -f compose.yml -f compose.redis.yml build
docker compose -f compose.yml -f compose.rabbitmq.yml build
docker compose -f compose.yml -f compose.kafka.yml build
49 changes: 34 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,26 +118,45 @@ In no particular order:
* [2017: Jaana Dogan's: Style guideline for Go packages](https://rakyll.org/style-packages/)
* [2018: Kat Zien - How Do You Structure Your Go Apps](https://www.youtube.com/watch?v=oL6JBUk6tj0)

## Docker Containers
## Running project locally using Docker Compose

Please notice in order to run this project locally you need to run a few programs in advance, if you use Docker please refer to the concrete instructions in [`docs/`](docs/) for more details.
Originally added as part of [Building Microservices In Go: Containerization with Docker](https://youtu.be/u_ayzie9pAQ), `docker compose` has evolved and with it the way to run everything locally. Make sure you are running a recent version of Docker Compose. The configuration in this repository and the instructions below are known to work:

There's also a [docker-compose.yml](docker-compose.yml), covered in [Building Microservices In Go: Containerization with Docker](https://youtu.be/u_ayzie9pAQ), however like I mentioned in the video you have to execute `docker-compose` in multiple steps.
* Engine: **27.0.3**
* Compose: **v2.28.1-desktop.1**

Notice that because of the way RabbitMQ and Kafka are being used they are sort of competing with each other, so at the moment we either have to enable Kafka and disable RabbitMQ or the other way around in both the code and the `docker-compose.yml` file, in either case there are Dockerfiles and services defined that cover building and running them.
This project takes advantage of [Go's build constrains](https://pkg.go.dev/go/build) and [Docker's arguments](https://docs.docker.com/reference/dockerfile/#arg) to build and run the [rest-server](cmd/rest-server) using any of the supported three message hubs:

The following instructions are confirmed to work with docker compose **v2.24.5-desktop.1**.
* Redis
* RabbitMQ
* Kafka

* Run `docker-compose up`, if you're using `rabbitmq` or `kafka` you may see the _rest-server_ and _elasticsearch-indexer_ services fail because those services take too long to start, in that case use any of the following instructions to manually start those services after the dependent server is ready:
* If you're planning to use RabbitMQ, run `docker-compose up rest-server elasticsearch-indexer-rabbitmq`.
* If you're planning to use Kafka, run `docker-compose up rest-server elasticsearch-indexer-kafka`.
* For building the service images you can use:
* `rest-server` image: `docker-compose build rest-server`.
* `elasticsearch-indexer-rabbitmq` image: `docker-compose build elasticsearch-indexer-rabbitmq`.
* `elasticsearch-indexer-kafka` image: `docker-compose build elasticsearch-indexer-kafka`.
* `elasticsearch-indexer-redis` image: `docker-compose build elasticsearch-indexer-redis`.
* Run `docker-compose run rest-server tern migrate --migrations "/api/migrations/" --conn-string "postgres://user:password@postgres:5432/dbname?sslmode=disable"` to have everything working correctly.
* Finally interact with the API using Swagger UI: http://127.0.0.1:9234/static/swagger-ui/
The `docker compose` instructions are executed in the form of:

```
docker compose -f compose.yml -f compose.<type>.yml <command>
```

Where:

* `<type>`: Indicates what message hub to use. There are three supported values: `redis`, `rabbitmq` and `kafka`; those effectively match the compose filename itself.
* `<command>`: Indicates the docker compose command to use.

For example to build images using Redis as the message hub you would do:

```
docker compose -f compose.yml -f compose.redis.yml build
```

Then to start the containers you would do:

```
docker compose -f compose.yml -f compose.redis.yml up
```

The Swagger UI should be accessible at http://127.0.0.1:9234/static/swagger-ui/ .

There's also a [`noop`](compose.noop.yml) version that does not have a message bus, and therefore there's no indexer so searching for Tasks is not possible.

## Diagrams

Expand Down
9 changes: 7 additions & 2 deletions build/elasticsearch-indexer-kafka/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ WORKDIR /build/

COPY . .

ENV CGO_ENABLED=1 \
GOOS=linux

RUN go mod download

RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -ldflags "-extldflags -static" \
RUN go build -a -installsuffix cgo -ldflags "-extldflags -static" \
-o elasticsearch-indexer github.com/MarioCarrion/todo-api/cmd/elasticsearch-indexer-kafka

#-

FROM debian:bookworm-20241223-slim

ENV DEBIAN_FRONTEND=noninteractive

RUN set -x && \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
apt-get install -y \
ca-certificates && \
rm -rf /var/lib/apt/lists/*

Expand Down
11 changes: 8 additions & 3 deletions build/elasticsearch-indexer-rabbitmq/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ WORKDIR /build/

COPY . .

ENV CGO_ENABLED=1 \
GOOS=linux

RUN go mod download

RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -ldflags "-extldflags -static" \
-o elasticsearch-indexer github.com/MarioCarrion/todo-api/cmd/elasticsearch-indexer-kafka
RUN go build -a -installsuffix cgo -ldflags "-extldflags -static" \
-o elasticsearch-indexer github.com/MarioCarrion/todo-api/cmd/elasticsearch-indexer-rabbitmq

#-

FROM debian:bookworm-20241223-slim

ENV DEBIAN_FRONTEND=noninteractive

RUN set -x && \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
apt-get install -y \
ca-certificates && \
rm -rf /var/lib/apt/lists/*

Expand Down
9 changes: 7 additions & 2 deletions build/elasticsearch-indexer-redis/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ WORKDIR /build/

COPY . .

ENV CGO_ENABLED=1 \
GOOS=linux

RUN go mod download

RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -ldflags "-extldflags -static" \
RUN go build -a -installsuffix cgo -ldflags "-extldflags -static" \
-o elasticsearch-indexer github.com/MarioCarrion/todo-api/cmd/elasticsearch-indexer-redis

#-

FROM debian:bookworm-20241223-slim

ENV DEBIAN_FRONTEND=noninteractive

RUN set -x && \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
apt-get install -y \
ca-certificates && \
rm -rf /var/lib/apt/lists/*

Expand Down
19 changes: 11 additions & 8 deletions build/rest-server/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
FROM golang:1.23.4-bookworm AS builder

# Explicitly NOT setting a default value
ARG TAG

WORKDIR /build/

COPY . .

RUN go mod download
ENV CGO_ENABLED=1 \
GOOS=linux

RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -ldflags "-extldflags -static" \
github.com/MarioCarrion/todo-api/cmd/rest-server
RUN go mod download

RUN CGO_ENABLED=1 GOOS=linux go install -a -installsuffix cgo -ldflags "-extldflags -static" \
github.com/jackc/tern/[email protected]
RUN go build -a -installsuffix cgo -ldflags "-extldflags -static" -tags=$TAG \
github.com/MarioCarrion/todo-api/cmd/rest-server

#-

FROM debian:bookworm-20241223-slim

ENV DEBIAN_FRONTEND=noninteractive

RUN set -x && \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y \
apt-get install -y \
ca-certificates && \
rm -rf /var/lib/apt/lists/*

WORKDIR /api/
ENV PATH=/api/bin/:$PATH

COPY --from=builder /build/rest-server ./bin/rest-server
COPY --from=builder /go/bin/tern ./bin/tern
COPY --from=builder /build/env.example .
COPY --from=builder /build/db/ .

EXPOSE 9234

Expand Down
35 changes: 35 additions & 0 deletions build/tern/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
FROM golang:1.23.0-bookworm AS builder

WORKDIR /build/

COPY db/ .

COPY internal/tools/ .

ENV CGO_ENABLED=1 \
GOOS=linux

RUN go mod download && go mod tidy

RUN go install -a -installsuffix cgo -ldflags "-extldflags -static" \
github.com/jackc/tern/v2

#-

FROM debian:bookworm-20240812-slim

ENV DEBIAN_FRONTEND=noninteractive

RUN set -x && \
apt-get update && \
apt-get install -y \
ca-certificates && \
rm -rf /var/lib/apt/lists/*

WORKDIR /db/
ENV PATH=/db/:$PATH

COPY --from=builder /go/bin/tern .
COPY --from=builder /build/migrations/ .

CMD ["tern"]
2 changes: 1 addition & 1 deletion cmd/elasticsearch-indexer-rabbitmq/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ func (s *Server) ListenAndServe() error {

go func() {
for msg := range msgs {
s.logger.Info("Received message: %s" + msg.RoutingKey)
s.logger.Info("Received message: " + msg.RoutingKey)

var nack bool

Expand Down
6 changes: 5 additions & 1 deletion cmd/elasticsearch-indexer-redis/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func (s *Server) ListenAndServe() error {

go func() {
for msg := range ch {
s.logger.Info("Received message: %s" + msg.Channel)
s.logger.Info("Received message: " + msg.Channel)

// XXX: Instrumentation to be added in a future episode

Expand All @@ -163,6 +163,8 @@ func (s *Server) ListenAndServe() error {
if err := s.task.Index(context.Background(), task); err != nil {
s.logger.Info("Couldn't index task", zap.Error(err))
}

s.logger.Info("Record saved")
case "tasks.event.deleted":
var id string

Expand All @@ -175,6 +177,8 @@ func (s *Server) ListenAndServe() error {
if err := s.task.Delete(context.Background(), id); err != nil {
s.logger.Info("Couldn't delete task", zap.Error(err))
}

s.logger.Info("Record deleted")
}
}

Expand Down
8 changes: 6 additions & 2 deletions cmd/internal/rabbitmq.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ func NewRabbitMQ(conf *envvar.Configuration) (*RabbitMQ, error) {
}

// Close ...
func (r *RabbitMQ) Close() {
r.Connection.Close()
func (r *RabbitMQ) Close() error {
if err := r.Connection.Close(); err != nil {
return internal.WrapErrorf(err, internal.ErrorCodeUnknown, "r.Connection.Close")
}

return nil
}
Loading

0 comments on commit 9d841f9

Please sign in to comment.