From 6fafa67d8afb4ae187a1c74fbf1b81f5eaace8e8 Mon Sep 17 00:00:00 2001 From: Konstantin Romanov Date: Sun, 3 Mar 2024 17:59:56 +0300 Subject: [PATCH] healthchecks --- .gitignore | 3 ++- Dockerfile | 5 ++++- api/moex.go | 3 ++- api/spbex.go | 3 ++- main.go => cmd/go-exchange-api/main.go | 0 cmd/healthcheck/main.go | 28 ++++++++++++++++++++++++++ constants/constants.go | 4 ++++ docker-compose.yml | 12 +++++++++++ errors/errors.go | 2 ++ utils/utils.go | 22 ++++++++++++++++++++ 10 files changed, 78 insertions(+), 4 deletions(-) rename main.go => cmd/go-exchange-api/main.go (100%) create mode 100644 cmd/healthcheck/main.go create mode 100644 constants/constants.go diff --git a/.gitignore b/.gitignore index 0259cbe..ca8c013 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ go-exchange-api -redis \ No newline at end of file +redis +!cmd/* \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index a09ef45..8977261 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,13 +3,16 @@ WORKDIR /src/app COPY go.mod go.sum ./ RUN go mod download COPY . ./ -RUN go build -ldflags "-s -w" -o go-exchange-api +RUN go build -ldflags "-s -w" -o go-exchange-api cmd/go-exchange-api/main.go +RUN go build -ldflags "-s -w" -o healthcheck cmd/healthcheck/main.go FROM alpine ENV GIN_MODE release WORKDIR /app COPY --from=builder /src/app/go-exchange-api ./go-exchange-api +COPY --from=builder /src/app/healthcheck ./healthcheck RUN addgroup -S appgroup && \ adduser -S appuser -G appgroup USER appuser +HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD ["./healthcheck"] ENTRYPOINT ["./go-exchange-api"] diff --git a/api/moex.go b/api/moex.go index 0298444..3ef5e70 100644 --- a/api/moex.go +++ b/api/moex.go @@ -6,6 +6,7 @@ import ( "log" "time" + "github.com/kiberdruzhinnik/go-exchange-api/constants" custom_errors "github.com/kiberdruzhinnik/go-exchange-api/errors" "github.com/kiberdruzhinnik/go-exchange-api/utils" ) @@ -50,7 +51,7 @@ type MoexPriceJSON struct { func NewMoexAPI(redis utils.RedisClient) MoexAPI { return MoexAPI{ - BaseURL: "https://iss.moex.com", + BaseURL: constants.MoexBaseApiURL, Redis: redis, } } diff --git a/api/spbex.go b/api/spbex.go index c91b7bd..8761733 100644 --- a/api/spbex.go +++ b/api/spbex.go @@ -6,6 +6,7 @@ import ( "log" "time" + "github.com/kiberdruzhinnik/go-exchange-api/constants" custom_errors "github.com/kiberdruzhinnik/go-exchange-api/errors" "github.com/kiberdruzhinnik/go-exchange-api/utils" ) @@ -30,7 +31,7 @@ type SpbexSecurityJSON struct { func NewSpbexAPI() SpbexAPI { return SpbexAPI{ - BaseURL: "https://investcab.ru/api", + BaseURL: constants.SpbexBaseApiURL, } } diff --git a/main.go b/cmd/go-exchange-api/main.go similarity index 100% rename from main.go rename to cmd/go-exchange-api/main.go diff --git a/cmd/healthcheck/main.go b/cmd/healthcheck/main.go new file mode 100644 index 0000000..bef7881 --- /dev/null +++ b/cmd/healthcheck/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "io" + "log" + "net/http" +) + +func main() { + resp, err := http.Get("http://127.0.0.1:8080/healthcheck") + + if err != nil { + log.Fatalln(err) + } + + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + + if err != nil { + log.Fatalln(err) + } + + status := string(body) + if status != "ok" { + log.Fatalln("status is not ok") + } +} diff --git a/constants/constants.go b/constants/constants.go new file mode 100644 index 0000000..6709762 --- /dev/null +++ b/constants/constants.go @@ -0,0 +1,4 @@ +package constants + +const MoexBaseApiURL = "https://iss.moex.com" +const SpbexBaseApiURL = "https://investcab.ru/api" diff --git a/docker-compose.yml b/docker-compose.yml index d26ebd1..14fc2a8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,6 +5,12 @@ services: image: redis:7-alpine volumes: - redis:/data + healthcheck: + test: [ "CMD-SHELL", "redis-cli ping | grep PONG" ] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s exchange-api: image: kotasha/go-exchange-api:latest @@ -14,6 +20,12 @@ services: - 8080:8080/tcp depends_on: - redis-cache + healthcheck: + test: [ "./healthcheck" ] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s volumes: redis: diff --git a/errors/errors.go b/errors/errors.go index a8b2828..bf91505 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -9,3 +9,5 @@ var ErrorNoData = errors.New("no data") var ErrorRedisNotConnected = errors.New("redis is not connected") var ErrorRedisNotFound = errors.New("not found in redis") + +var ErrorNotAllowed = errors.New("not allowed") diff --git a/utils/utils.go b/utils/utils.go index 134b5bf..42fb4ec 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -5,9 +5,31 @@ import ( "net/http" "strings" "unicode" + + "github.com/kiberdruzhinnik/go-exchange-api/constants" + "github.com/kiberdruzhinnik/go-exchange-api/errors" ) +var URLS_ALLOW_LIST []string = []string{ + constants.MoexBaseApiURL, + constants.SpbexBaseApiURL, +} + +func CheckSafeURL(url string) bool { + for _, u := range URLS_ALLOW_LIST { + if strings.HasPrefix(url, u) { + return true + } + } + return false +} + func HttpGet(url string) ([]byte, error) { + + if !CheckSafeURL(url) { + return nil, errors.ErrorNotAllowed + } + resp, err := http.Get(url) if err != nil {