Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ go.work.sum
# Misc
.vscode/launch.json
.vscode/settings.json
.secrets
.backups
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# gopen-api

This is just a - better - port of my nodejs api (dotpen-api), using it as a scratchpad for my golang skills and docker/k8s skills

yes i know thats not the "right way" to do migrations but i honestly dont care about it rn

yes i know a password is in compose.yaml and migrations, obviously that's a test password i'd only use it for testing (that's why it has "test" in it)
6 changes: 5 additions & 1 deletion api/bruno/character.bru
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ params:query {
}

params:path {
id: d0a1f17505c56abf439835dd
id: eZHsSMoEGHV3JTfuyst7Tb
}

body:json {
Expand All @@ -25,3 +25,7 @@ body:json {
"skip": 0
}
}

vars:pre-request {
id: d0a1f17505c56abf439835
}
15 changes: 15 additions & 0 deletions api/bruno/health.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
meta {
name: health
type: http
seq: 7
}

get {
url: {{BASE_URL}}/health
body: none
auth: inherit
}

settings {
encodeUrl: true
}
2 changes: 2 additions & 0 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/UltimateForm/gopen-api/cmd/api/charactersapi"
"github.com/UltimateForm/gopen-api/cmd/api/loginapi"
"github.com/UltimateForm/gopen-api/cmd/api/meta"
"github.com/UltimateForm/gopen-api/internal/core"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
Expand All @@ -24,6 +25,7 @@ func Start() http.Handler {
r.Put("/{id}", charactersapi.HandleUpdateCharacter)
r.Delete("/{id}", charactersapi.HandleDeleteCharacter)
})
router.Get("/health", meta.HandleGetHealth)
log.Println("ROUTER CREATED")
return router
}
11 changes: 11 additions & 0 deletions cmd/api/meta/health.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package meta

import (
"net/http"

"github.com/UltimateForm/gopen-api/internal/core"
)

func HandleGetHealth(res http.ResponseWriter, req *http.Request) {
core.RespondOk(res, map[string]string{"status": "healthy"})
}
60 changes: 60 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: gopen
services:
api:
build:
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
NEO4J_URI: bolt://db:7687
NEO4J_USERNAME: neo4j
NEO4J_PASSWORD: testpassword
depends_on:
db:
condition: service_healthy
secrets:
- jwt_sign

db:
image: neo4j:community-trixie
ports:
- "7687:7687"
healthcheck:
test: ["CMD-SHELL", "cypher-shell -u neo4j -p testpassword --access-mode=read \"RETURN 0\""]
interval: 5s
timeout: 1m
retries: 5
start_period: 15s
environment:
NEO4J_AUTH: neo4j/testpassword
volumes:
- db-data:/data

db-fill:
image: neo4j:community-trixie
volumes:
- ./migrations:/migrations
command: cypher-shell -a bolt://db:7687 -u neo4j -p testpassword -f /migrations/test_docs.cypher
depends_on:
db:
condition: service_healthy
profiles:
- tools

db-setup:
image: neo4j:community-trixie
volumes:
- ./migrations:/migrations
command: cypher-shell -a bolt://db:7687 -u neo4j -p testpassword -f /migrations/setup.cypher
depends_on:
db:
condition: service_healthy
profiles:
- tools

secrets:
jwt_sign:
file: .secrets/jwt_sign

volumes:
db-data:
15 changes: 10 additions & 5 deletions internal/config/main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package config

import (
"errors"
"log"
"os"

Expand All @@ -21,9 +20,15 @@ func LoadDbConfig() DbConfig {
}

func LoadAuthConfig() AuthConfig {
jwtSign := os.Getenv("JWT_SIGN")
if jwtSign == "" {
panic(errors.New("JWT_SIGN not in environment variables"))
jwtSign, err := os.ReadFile("/run/secrets/jwt_sign")
if err != nil {
if os.IsNotExist(err) {
// TODO: remove this fallback secret management is set
// will need to change tests too
jwtSign = []byte(os.Getenv("JWT_SIGN"))
} else {
panic(err)
}
}
return AuthConfig{JwtSign: jwtSign}
return AuthConfig{JwtSign: string(jwtSign)}
}
20 changes: 20 additions & 0 deletions kube/api.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: v1
kind: Pod
metadata:
name: api
spec:
containers:
- image: gopen-api:latest
imagePullPolicy: IfNotPresent
name: api
livenessProbe:
httpGet:
path: health
port: 3000
initialDelaySeconds: 2
failureThreshold: 1
successThreshold: 1
ports:
- containerPort: 8080
name: http
protocol: TCP
7 changes: 7 additions & 0 deletions migrations/setup.cypher
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE CONSTRAINT user_email_is_unique
FOR (u:User)
REQUIRE u.email IS UNIQUE;

CREATE CONSTRAINT character_name_is_unique
FOR (c:Character)
REQUIRE c.name IS UNIQUE;
Loading