From 736f9745dddf4b3252ff0b7835f60fd24ffcdfcf Mon Sep 17 00:00:00 2001 From: UltimateForm Date: Sun, 8 Feb 2026 02:14:31 +0000 Subject: [PATCH 1/7] feat: Add health check endpoint and Kubernetes configuration for gopen-api --- api/bruno/health.bru | 15 +++++++++++++++ cmd/api/main.go | 2 ++ cmd/api/meta/health.go | 11 +++++++++++ compose.yaml | 8 ++++++++ kube/api.yaml | 20 ++++++++++++++++++++ 5 files changed, 56 insertions(+) create mode 100644 api/bruno/health.bru create mode 100644 cmd/api/meta/health.go create mode 100644 compose.yaml create mode 100644 kube/api.yaml diff --git a/api/bruno/health.bru b/api/bruno/health.bru new file mode 100644 index 0000000..0509eea --- /dev/null +++ b/api/bruno/health.bru @@ -0,0 +1,15 @@ +meta { + name: health + type: http + seq: 7 +} + +get { + url: {{BASE_URL}}/health + body: none + auth: inherit +} + +settings { + encodeUrl: true +} diff --git a/cmd/api/main.go b/cmd/api/main.go index 124bccd..c9b7bde 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -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" @@ -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 } diff --git a/cmd/api/meta/health.go b/cmd/api/meta/health.go new file mode 100644 index 0000000..fbc9b42 --- /dev/null +++ b/cmd/api/meta/health.go @@ -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"}) +} diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..01b1b7e --- /dev/null +++ b/compose.yaml @@ -0,0 +1,8 @@ + +name: gopen +services: + api: + build: + dockerfile: Dockerfile + ports: + - "3000:3000" \ No newline at end of file diff --git a/kube/api.yaml b/kube/api.yaml new file mode 100644 index 0000000..f6122c2 --- /dev/null +++ b/kube/api.yaml @@ -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 \ No newline at end of file From 47a85a1ffe692bfd400dc73b9275d420972123fe Mon Sep 17 00:00:00 2001 From: UltimateForm Date: Sun, 8 Feb 2026 17:55:51 +0000 Subject: [PATCH 2/7] feat: more kube stuff --- compose.yaml | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/compose.yaml b/compose.yaml index 01b1b7e..34a573a 100644 --- a/compose.yaml +++ b/compose.yaml @@ -5,4 +5,27 @@ services: build: dockerfile: Dockerfile ports: - - "3000:3000" \ No newline at end of file + - "3000:3000" + environment: + NEO4J_URI: localhost:7474 + NEO4J_USERNAME: neo4j + NEO4J_PASSWORD: testpassword + # secrets: + # - jwt_sign + # - neo4j_password + + db: + image: neo4j:2026.01.3-trixie + ports: + - "7474:7474" + environment: + NEO4J_AUTH: neo4j/testpassword + + + +# secrets: +# jwt_sign: +# environment: JWT_SIGN +# neo4j_password: +# environment: NEO4J_PASSWORD + \ No newline at end of file From 128227a0b398b31d2549f989a9f7f106aa2a3f15 Mon Sep 17 00:00:00 2001 From: UltimateForm Date: Sun, 8 Feb 2026 22:11:19 +0000 Subject: [PATCH 3/7] feat: Introduce Neo4j database setup with migrations and secure JWT signing via Docker secrets. --- .gitignore | 2 + README.md | 7 + api/bruno/character.bru | 6 +- compose.yaml | 57 ++- internal/config/main.go | 9 +- migrations/setup.cypher | 7 + migrations/test_docs.cypher | 745 ++++++++++++++++++++++++++++++++++++ 7 files changed, 813 insertions(+), 20 deletions(-) create mode 100644 README.md create mode 100644 migrations/setup.cypher create mode 100644 migrations/test_docs.cypher diff --git a/.gitignore b/.gitignore index fcee21c..a82079d 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ go.work.sum # Misc .vscode/launch.json .vscode/settings.json +.secrets +.backups \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..2220cba --- /dev/null +++ b/README.md @@ -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) \ No newline at end of file diff --git a/api/bruno/character.bru b/api/bruno/character.bru index 897b4f3..4eb381d 100644 --- a/api/bruno/character.bru +++ b/api/bruno/character.bru @@ -16,7 +16,7 @@ params:query { } params:path { - id: d0a1f17505c56abf439835dd + id: eZHsSMoEGHV3JTfuyst7Tb } body:json { @@ -25,3 +25,7 @@ body:json { "skip": 0 } } + +vars:pre-request { + id: d0a1f17505c56abf439835 +} diff --git a/compose.yaml b/compose.yaml index 34a573a..79b8258 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,4 +1,3 @@ - name: gopen services: api: @@ -7,25 +6,55 @@ services: ports: - "3000:3000" environment: - NEO4J_URI: localhost:7474 + NEO4J_URI: bolt://db:7687 NEO4J_USERNAME: neo4j NEO4J_PASSWORD: testpassword - # secrets: - # - jwt_sign - # - neo4j_password + depends_on: + db: + condition: service_healthy + secrets: + - jwt_sign db: - image: neo4j:2026.01.3-trixie + image: neo4j:community-trixie ports: - - "7474:7474" + - "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 -# secrets: -# jwt_sign: -# environment: JWT_SIGN -# neo4j_password: -# environment: NEO4J_PASSWORD - \ No newline at end of file +volumes: + db-data: diff --git a/internal/config/main.go b/internal/config/main.go index 6ead26d..1187695 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -1,7 +1,6 @@ package config import ( - "errors" "log" "os" @@ -21,9 +20,9 @@ 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 { + panic(err) } - return AuthConfig{JwtSign: jwtSign} + return AuthConfig{JwtSign: string(jwtSign)} } diff --git a/migrations/setup.cypher b/migrations/setup.cypher new file mode 100644 index 0000000..300ca5a --- /dev/null +++ b/migrations/setup.cypher @@ -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; \ No newline at end of file diff --git a/migrations/test_docs.cypher b/migrations/test_docs.cypher new file mode 100644 index 0000000..e4df2f7 --- /dev/null +++ b/migrations/test_docs.cypher @@ -0,0 +1,745 @@ +:begin +UNWIND [{name:"Michael Miller", properties:{debut:92.0, description:"Represent half plan film mouth former. She them education analysis cause.", id:"qxeiGXUx1GtnDfvhTD3oB7"}}, {name:"Jesse Davis", properties:{debut:51.0, description:"One relationship it difficult benefit four avoid. Operation strategy best character whole.", id:"crK6qMRExdGLrrMED97pjh"}}, {name:"Ruth Jackson", properties:{debut:9.0, description:"Car season compare whom. Skin half value high play main theory. Economy human never customer.", id:"jwzP1S4rDfEpJ2BJD4488L"}}, {name:"Deborah Cooper", properties:{debut:72.0, description:"Answer respond foot Democrat. Natural go carry not.", id:"vySzKVL9Pj2LpfvjZF36M8"}}, {name:"Brittany Preston", properties:{debut:77.0, description:"Hard whether whom audience wonder. Important billion never chance push.", id:"4QzWFid9HvaYTAwJWKgT1p"}}, {name:"Rhonda Bullock MD", properties:{debut:99.0, description:"Market able set be point deal water.", id:"rDbhox2b1yau1jx9mRzAEM"}}, {name:"Thomas Brown", properties:{debut:43.0, description:"Edge yeah land future kitchen response. Read day run office in song. Per plant travel by Mrs.", id:"c3xUXUUpibWar1emhd2oUK"}}, {name:"Randy Sullivan", properties:{debut:86.0, description:"Though serve picture. Store color back. Treat election easy knowledge sport.", id:"2qf3tqYdVyvgXs37EV26hL"}}, {name:"David Wong", properties:{debut:26.0, description:"Perform value recently war south until. Start finally send side. Born center recent structure.", id:"ojbrd5KUAsi9nAApFmXXZa"}}, {name:"Heather Ruiz", properties:{debut:99.0, description:"Single show add foot sign. Share soldier result computer number point.", id:"6BmSS5RbyYhNvucDEFZXin"}}, {name:"Cynthia Mendez", properties:{debut:79.0, description:"Window attorney nation him. Bit well assume she. Dog attorney area thousand they.", id:"fheRBjpmwp27iJSN2XXxQ9"}}, {name:"Christopher Bell", properties:{debut:53.0, description:"Community voice expert current east. Score conference it participant.", id:"jCNVTHDB88HwnTccmFAWhg"}}, {name:"Phillip Cook", properties:{debut:46.0, description:"Local result candidate much fine ground place. Bar could have maintain season memory.", id:"4zhvbmEWX5gKYq9cqwXh8D"}}, {name:"Tyler Li", properties:{debut:95.0, description:"Power performance event. Play poor pick standard soldier across quality.", id:"fYHcCFx9k7JkqQmpph4ibb"}}, {name:"Mason Martin", properties:{debut:48.0, description:"Tough employee special. So interesting rather big order threat.", id:"7a2FSFAqumC2aiqbS64YB2"}}, {name:"Kelly Green", properties:{debut:22.0, description:"Read somebody success far. Explain bill east manager decision movement once.", id:"iiV4gTSWY2X7A53A8eSeQn"}}, {name:"Jeremiah Brewer", properties:{debut:78.0, description:"Hit hit about impact political notice. If budget property stand.", id:"qxtgnL3QAZiaMTeyS1aCWz"}}, {name:"Ashley Hill", properties:{debut:7.0, description:"Performance participant any think bring discover final. Agreement activity fast order.", id:"s7gKNW9n6VaQ5fJNs4CueT"}}, {name:"Jonathan Khan", properties:{debut:25.0, description:"Here both away summer. Language national writer building physical.", id:"dWdTDRLRG4zXWkAmSgHkba"}}, {name:"Lisa Reed", properties:{debut:66.0, description:"Data example rate. Practice best me hotel.", id:"8DKbZ45ysNVwbakru1bPV1"}}] AS row +CREATE (n:Character{name: row.name}) SET n += row.properties; +UNWIND [ + { + name: "Janice Dominguez", + properties: { + debut: 79.0, + description: + "Foreign third strategy lead listen carry plan. Down weight leader name mother rock.", + id: "opG3HmnFgFmGZXSJDNcbFL" + } + }, + { + name: "Thomas Alvarez", + properties: { + debut: 3.0, + description: "Country style common. Both respond rise.", + id: "cgi2TEUhoHANfNNkVB75Sv" + } + }, + { + name: "Anita Lopez", + properties: { + debut: 22.0, + description: + "Court sometimes someone every. Term ask natural. Several language friend arm.", + id: "obyEu7VTjFhDQ1iKCEViMk" + } + }, + { + name: "Jason Brown", + properties: { + debut: 84.0, + description: + "Ten their particular boy Congress form. Attack form appear popular.", + id: "2RU9mqXbyLsgi3KkpdRHJB" + } + }, + { + name: "Brandon Blair", + properties: { + debut: 71.0, + description: "Foreign almost miss weight.", + id: "mxcrfkjwSUR3CcAKxgrdxr" + } + }, + { + name: "Theodore Anderson", + properties: { + debut: 49.0, + description: + "Game still beautiful many move. Expect yard something live.", + id: "ffnsJeLaJoe2gybZS398km" + } + }, + { + name: "Mario Foley", + properties: { + debut: 84.0, + description: + "Mrs concern power industry action concern fire. Group your whom ground out clear pattern civil.", + id: "sV3cZbw7ugudkcV1Pi88wR" + } + }, + { + name: "Jennifer Hill", + properties: { + debut: 70.0, + description: + "They technology decide after. Treatment anything finish card media seem week.", + id: "xn5mkpdvC6zrffbEhgsoGG" + } + }, + { + name: "Abigail Burns", + properties: { + debut: 36.0, + description: + "Level kind parent door police road visit. Again off guy list. Little ever mean true player.", + id: "vprNviSx5rt39X8RdkwBuE" + } + }, + { + name: "Andrea Goodwin", + properties: { + debut: 96.0, + description: "Bill compare best throughout fill community.", + id: "uSxFPknefsVjJ6thpVJFZ7" + } + }, + { + name: "Shawn Wu", + properties: { + debut: 72.0, + description: + "Break lay front arrive. Scene serious both strong already want. Rise million choice red include.", + id: "11Ev9S4a7ESsMnQxHsFp2M" + } + }, + { + name: "Mark Hammond", + properties: { + debut: 67.0, + description: "Drive produce role current tell. Must consumer mind.", + id: "wrDetKRTVRNUTNmT5Wnz3d" + } + }, + { + name: "Timothy Harris", + properties: { + debut: 28.0, + description: + "Half involve language government environmental doctor camera responsibility.", + id: "6KwQKXHcg8JiZGEMLidL7M" + } + }, + { + name: "Sean Davis", + properties: { + debut: 71.0, + description: "Trial quickly least subject.", + id: "gc37nw1ig5C6EY6XTqRV7V" + } + }, + { + name: "Christopher Dorsey", + properties: { + debut: 70.0, + description: + "Force share both protect general. Exactly development bank charge.", + id: "gtn12jYoU8R2dKq3yaT6Tk" + } + }, + { + name: "Alyssa Ross", + properties: { + debut: 41.0, + description: + "Score campaign wish pull cell meet majority. Order past window husband entire science stay.", + id: "e3oHaoBtC6MP6LYVUc3ysp" + } + }, + { + name: "Angela Spencer", + properties: { + debut: 25.0, + description: + "Smile campaign shoulder relate. Onto prevent rise itself. Beat tonight window light.", + id: "28vmPUEWBGzgC6tF4KLQLd" + } + }, + { + name: "Justin Tran", + properties: { + debut: 65.0, + description: + "Accept alone beat. Local he feel they according. Yeah environment finish hair ball task.", + id: "2JbCBhMtd71woPt3yPaP1E" + } + }, + { + name: "James Garcia", + properties: { + debut: 28.0, + description: "Recently country family off world rise.", + id: "heGX5T5L6ymLsVkTYzcQhM" + } + }, + { + name: "Troy Warner", + properties: { + debut: 42.0, + description: + "Six vote crime guess. Action center nearly occur strategy relationship through.", + id: "1gm5yCRFCursR8jv2LmpC8" + } + } +] AS row +CREATE (n:Character {name: row.name}) +SET n += row.properties; +UNWIND [ + { + name: "Lonnie Holt", + properties: { + debut: 53.0, + description: "Help prevent range put.", + id: "76LXxJgDdHqezdVELYkxfw" + } + }, + { + name: "Nicholas Delgado", + properties: { + debut: 60.0, + description: "Take design budget agree the front. Short lot hair fire.", + id: "aBZFPLpjK3BPTg5WVwdhZR" + } + }, + { + name: "Michael Whitaker", + properties: { + debut: 48.0, + description: + "Dark various already boy carry. Standard candidate interesting believe.", + id: "tnfd9pWDvxdduT3mZUqjtB" + } + }, + { + name: "Mary Russell", + properties: { + debut: 88.0, + description: + "Between thank fine down avoid option. Go into car mean available between. Fight rest fly everybody.", + id: "shTi9VNP8sQdH49B2DLBB3" + } + }, + { + name: "Leon Petersen", + properties: { + debut: 85.0, + description: "On see contain fill doctor attorney.", + id: "vZHvTkhTidfiutPExBB7Kf" + } + }, + { + name: "Hannah Dorsey", + properties: { + debut: 67.0, + description: + "Test history forward enough miss machine reveal. Management realize course thousand yet while.", + id: "fA1eMWG4geff97TR2ucJcc" + } + }, + { + name: "Laura Ward", + properties: { + debut: 12.0, + description: "Tv view where perhaps half you. Ready bad maintain remain.", + id: "eZHsSMoEGHV3JTfuyst7Tb" + } + }, + { + name: "Emily Stanley", + properties: { + debut: 63.0, + description: + "Base guess issue like. Score rate bill huge ago away politics.", + id: "fFtqaQYkZJGHNTtEDfSvrR" + } + }, + { + name: "Erika Vaughn", + properties: { + debut: 23.0, + description: + "Look number measure add my if expert because. Also deal avoid young. Media me realize five.", + id: "rj4EvFTaEvba1E3BJdAF5A" + } + }, + { + name: "Cristoph Rot", + properties: {debut: 1, description: "edited", id: "d0a1f17505c56abf439835"} + } +] AS row +CREATE (n:Character {name: row.name}) +SET n += row.properties; +UNWIND [{email: "helio@mail.com", properties: {password: "q1234"}}] AS row +CREATE (n:User {email: row.email}) +SET n += row.properties;:commit +:begin +UNWIND [{start: {name:"Michael Miller"}, end: {name:"Cynthia Mendez"}, properties:{level:2, spark:"Two part edge."}}, {start: {name:"Jesse Davis"}, end: {name:"Thomas Brown"}, properties:{level:2, spark:"Sure us hear."}}, {start: {name:"Jesse Davis"}, end: {name:"Brandon Blair"}, properties:{level:3, spark:"Pass success man."}}, {start: {name:"Ruth Jackson"}, end: {name:"Jeremiah Brewer"}, properties:{level:-1, spark:"Head impact follow."}}, {start: {name:"Rhonda Bullock MD"}, end: {name:"Mario Foley"}, properties:{level:2, spark:"Teach development."}}, {start: {name:"Tyler Li"}, end: {name:"Lonnie Holt"}, properties:{level:1, spark:"Leg draw Congress."}}, {start: {name:"Theodore Anderson"}, end: {name:"Andrea Goodwin"}, properties:{level:1, spark:"Assume tell too."}}, {start: {name:"Angela Spencer"}, end: {name:"James Garcia"}, properties:{level:0, spark:"Opportunity."}}, {start: {name:"Justin Tran"}, end: {name:"Mario Foley"}, properties:{level:2, spark:"Lot hand someone."}}, {start: {name:"James Garcia"}, end: {name:"Brittany Preston"}, properties:{level:1, spark:"Car pressure."}}, {start: {name:"James Garcia"}, end: {name:"Janice Dominguez"}, properties:{level:3, spark:"Beyond usually."}}, {start: {name:"Hannah Dorsey"}, end: {name:"Angela Spencer"}, properties:{level:1, spark:"Soldier strategy."}}] AS row +MATCH (start:Character{name: row.start.name}) +MATCH (end:Character{name: row.end.name}) +CREATE (start)-[r:FRIENDSHIP]->(end) SET r += row.properties; +UNWIND [ + { + start: {name: "Randy Sullivan"}, + end: {name: "Andrea Goodwin"}, + properties: {level: -1, spark: "Live travel recent."} + }, + { + start: {name: "David Wong"}, + end: {name: "Theodore Anderson"}, + properties: {level: -1, spark: "Rather me high."} + }, + { + start: {name: "Heather Ruiz"}, + end: {name: "Christopher Dorsey"}, + properties: {level: 3, spark: "Sister become nor."} + }, + { + start: {name: "Mason Martin"}, + end: {name: "Theodore Anderson"}, + properties: {level: 2, spark: "Five size week view."} + }, + { + start: {name: "Kelly Green"}, + end: {name: "Mary Russell"}, + properties: {level: 2, spark: "Factor training."} + }, + { + start: {name: "Ashley Hill"}, + end: {name: "Brandon Blair"}, + properties: {level: -1, spark: "Outside action view."} + }, + { + start: {name: "Jonathan Khan"}, + end: {name: "David Wong"}, + properties: {level: -1, spark: "Remain whole effort."} + }, + { + start: {name: "Thomas Alvarez"}, + end: {name: "Hannah Dorsey"}, + properties: {level: -1, spark: "Opportunity quality."} + }, + { + start: {name: "Brandon Blair"}, + end: {name: "Jonathan Khan"}, + properties: {level: -1, spark: "System magazine."} + }, + { + start: {name: "Brandon Blair"}, + end: {name: "Jennifer Hill"}, + properties: {level: 3, spark: "Time throughout."} + }, + { + start: {name: "Brandon Blair"}, + end: {name: "Troy Warner"}, + properties: {level: 1, spark: "Country go our left."} + }, + { + start: {name: "Theodore Anderson"}, + end: {name: "Cynthia Mendez"}, + properties: {level: 0, spark: "Article spend child."} + }, + { + start: {name: "Theodore Anderson"}, + end: {name: "Jeremiah Brewer"}, + properties: {level: 3, spark: "He about series."} + }, + { + start: {name: "Justin Tran"}, + end: {name: "Thomas Brown"}, + properties: {level: -1, spark: "Rock realize man."} + }, + { + start: {name: "James Garcia"}, + end: {name: "David Wong"}, + properties: {level: -1, spark: "Manage camera seat."} + }, + { + start: {name: "Nicholas Delgado"}, + end: {name: "David Wong"}, + properties: {level: 0, spark: "Last east choose be."} + }, + { + start: {name: "Leon Petersen"}, + end: {name: "Theodore Anderson"}, + properties: {level: 3, spark: "Fine education."} + } +] AS row +MATCH (start:Character {name: row.start.name}) +MATCH (end:Character {name: row.end.name}) +CREATE (start)-[r:WORSHIP]->(end) +SET r += row.properties; +UNWIND [ + { + start: {name: "Jesse Davis"}, + end: {name: "Janice Dominguez"}, + properties: {level: 0, spark: "Crime available."} + }, + { + start: {name: "Heather Ruiz"}, + end: {name: "Hannah Dorsey"}, + properties: {level: 1, spark: "Individual cover."} + }, + { + start: {name: "Christopher Bell"}, + end: {name: "David Wong"}, + properties: {level: -1, spark: "Woman nice."} + }, + { + start: {name: "Christopher Bell"}, + end: {name: "Mason Martin"}, + properties: {level: 0, spark: "Region part wear."} + }, + { + start: {name: "Lisa Reed"}, + end: {name: "Lonnie Holt"}, + properties: {level: 1, spark: "Large watch federal."} + }, + { + start: {name: "Janice Dominguez"}, + end: {name: "Sean Davis"}, + properties: {level: 0, spark: "Move work record."} + }, + { + start: {name: "Theodore Anderson"}, + end: {name: "Heather Ruiz"}, + properties: {level: 0, spark: "Wide subject risk."} + }, + { + start: {name: "Abigail Burns"}, + end: {name: "Mario Foley"}, + properties: {level: 3, spark: "Consumer student."} + }, + { + start: {name: "Christopher Dorsey"}, + end: {name: "Rhonda Bullock MD"}, + properties: {level: 2, spark: "Hot cut write."} + }, + { + start: {name: "Christopher Dorsey"}, + end: {name: "Randy Sullivan"}, + properties: {level: 1, spark: "Deep buy exist."} + }, + { + start: {name: "James Garcia"}, + end: {name: "Mario Foley"}, + properties: {level: 3, spark: "Entire good."} + }, + { + start: {name: "Nicholas Delgado"}, + end: {name: "Shawn Wu"}, + properties: {level: 3, spark: "Power away how fine."} + }, + { + start: {name: "Mary Russell"}, + end: {name: "Brandon Blair"}, + properties: {level: 0, spark: "Up management."} + }, + { + start: {name: "Hannah Dorsey"}, + end: {name: "Brandon Blair"}, + properties: {level: 3, spark: "Community."} + } +] AS row +MATCH (start:Character {name: row.start.name}) +MATCH (end:Character {name: row.end.name}) +CREATE (start)-[r:KILLED]->(end) +SET r += row.properties; +UNWIND [ + { + start: {name: "Michael Miller"}, + end: {name: "Mario Foley"}, + properties: {level: 2, spark: "Although figure."} + }, + { + start: {name: "Jesse Davis"}, + end: {name: "Mark Hammond"}, + properties: {level: -1, spark: "Hair go several."} + }, + { + start: {name: "Tyler Li"}, + end: {name: "Emily Stanley"}, + properties: {level: 1, spark: "Resource eye."} + }, + { + start: {name: "Kelly Green"}, + end: {name: "Erika Vaughn"}, + properties: {level: -1, spark: "Executive simple."} + }, + { + start: {name: "Ashley Hill"}, + end: {name: "Timothy Harris"}, + properties: {level: 1, spark: "Stay down street."} + }, + { + start: {name: "Janice Dominguez"}, + end: {name: "Heather Ruiz"}, + properties: {level: 1, spark: "Contain attorney."} + }, + { + start: {name: "Thomas Alvarez"}, + end: {name: "Shawn Wu"}, + properties: {level: 3, spark: "Black morning."} + }, + { + start: {name: "Jason Brown"}, + end: {name: "Hannah Dorsey"}, + properties: {level: 1, spark: "Professor forget."} + }, + { + start: {name: "Mark Hammond"}, + end: {name: "Michael Miller"}, + properties: {level: -1, spark: "Step area low."} + }, + { + start: {name: "Nicholas Delgado"}, + end: {name: "Ruth Jackson"}, + properties: {level: 3, spark: "Sister fish soon."} + }, + { + start: {name: "Nicholas Delgado"}, + end: {name: "Jason Brown"}, + properties: {level: 1, spark: "Seem same family."} + }, + { + start: {name: "Michael Whitaker"}, + end: {name: "Angela Spencer"}, + properties: {level: 0, spark: "Party quickly song."} + }, + { + start: {name: "Mary Russell"}, + end: {name: "Jesse Davis"}, + properties: {level: 2, spark: "Miss seek."} + }, + { + start: {name: "Mary Russell"}, + end: {name: "Angela Spencer"}, + properties: {level: 0, spark: "Break move on cut."} + } +] AS row +MATCH (start:Character {name: row.start.name}) +MATCH (end:Character {name: row.end.name}) +CREATE (start)-[r:KINSHIP]->(end) +SET r += row.properties; +UNWIND [ + { + start: {name: "Randy Sullivan"}, + end: {name: "Jason Brown"}, + properties: {level: 3, spark: "Life allow some."} + }, + { + start: {name: "David Wong"}, + end: {name: "Andrea Goodwin"}, + properties: {level: 3, spark: "Certainly himself."} + }, + { + start: {name: "Phillip Cook"}, + end: {name: "Emily Stanley"}, + properties: {level: 0, spark: "Name world score."} + }, + { + start: {name: "Jeremiah Brewer"}, + end: {name: "Michael Whitaker"}, + properties: {level: 3, spark: "Fly camera eat."} + }, + { + start: {name: "Ashley Hill"}, + end: {name: "Justin Tran"}, + properties: {level: 0, spark: "Have my staff."} + }, + { + start: {name: "Jonathan Khan"}, + end: {name: "Heather Ruiz"}, + properties: {level: -1, spark: "Whatever manager."} + }, + { + start: {name: "Janice Dominguez"}, + end: {name: "Ruth Jackson"}, + properties: {level: 1, spark: "Sing business."} + }, + { + start: {name: "Mark Hammond"}, + end: {name: "Troy Warner"}, + properties: {level: 0, spark: "Focus compare this."} + }, + { + start: {name: "Mark Hammond"}, + end: {name: "Mary Russell"}, + properties: {level: 3, spark: "Coach study really."} + }, + { + start: {name: "Mark Hammond"}, + end: {name: "Laura Ward"}, + properties: {level: 2, spark: "Himself from."} + }, + { + start: {name: "Alyssa Ross"}, + end: {name: "Ashley Hill"}, + properties: {level: 1, spark: "Practice off me."} + }, + { + start: {name: "James Garcia"}, + end: {name: "Deborah Cooper"}, + properties: {level: 3, spark: "Star maintain least."} + }, + { + start: {name: "Troy Warner"}, + end: {name: "Randy Sullivan"}, + properties: {level: 3, spark: "Stop yeah even."} + }, + { + start: {name: "Lonnie Holt"}, + end: {name: "Laura Ward"}, + properties: {level: 0, spark: "Stop matter product."} + }, + { + start: {name: "Nicholas Delgado"}, + end: {name: "Deborah Cooper"}, + properties: {level: 0, spark: "Value check."} + }, + { + start: {name: "Nicholas Delgado"}, + end: {name: "Anita Lopez"}, + properties: {level: 1, spark: "And site officer."} + }, + { + start: {name: "Mary Russell"}, + end: {name: "Lisa Reed"}, + properties: {level: 0, spark: "Six vote cost."} + }, + { + start: {name: "Mary Russell"}, + end: {name: "Jennifer Hill"}, + properties: {level: 3, spark: "Cover mouth share."} + }, + { + start: {name: "Leon Petersen"}, + end: {name: "Michael Whitaker"}, + properties: {level: -1, spark: "They west build."} + } +] AS row +MATCH (start:Character {name: row.start.name}) +MATCH (end:Character {name: row.end.name}) +CREATE (start)-[r:VASSALAGE]->(end) +SET r += row.properties; +UNWIND [ + { + start: {name: "Ruth Jackson"}, + end: {name: "Jennifer Hill"}, + properties: {level: 3, spark: "Develop hand future."} + }, + { + start: {name: "Deborah Cooper"}, + end: {name: "Michael Miller"}, + properties: {level: 3, spark: "Truth response."} + }, + { + start: {name: "Randy Sullivan"}, + end: {name: "Ashley Hill"}, + properties: {level: 0, spark: "Cut really issue."} + }, + { + start: {name: "Christopher Bell"}, + end: {name: "Mary Russell"}, + properties: {level: 0, spark: "Argue he source."} + }, + { + start: {name: "Phillip Cook"}, + end: {name: "Justin Tran"}, + properties: {level: 2, spark: "Can cut worker line."} + }, + { + start: {name: "Tyler Li"}, + end: {name: "Andrea Goodwin"}, + properties: {level: 3, spark: "Memory approach."} + }, + { + start: {name: "Ashley Hill"}, + end: {name: "Jesse Davis"}, + properties: {level: 0, spark: "Mission fish type."} + }, + { + start: {name: "Lisa Reed"}, + end: {name: "Andrea Goodwin"}, + properties: {level: 0, spark: "Blood pass away one."} + }, + { + start: {name: "Shawn Wu"}, + end: {name: "Anita Lopez"}, + properties: {level: 2, spark: "Parent according."} + }, + { + start: {name: "Alyssa Ross"}, + end: {name: "Jesse Davis"}, + properties: {level: 1, spark: "Cultural list."} + }, + { + start: {name: "James Garcia"}, + end: {name: "Mary Russell"}, + properties: {level: -1, spark: "Economy herself."} + }, + { + start: {name: "Michael Whitaker"}, + end: {name: "Jeremiah Brewer"}, + properties: {level: 2, spark: "Order after parent."} + }, + { + start: {name: "Michael Whitaker"}, + end: {name: "Thomas Alvarez"}, + properties: {level: -1, spark: "Century without."} + }, + { + start: {name: "Erika Vaughn"}, + end: {name: "Troy Warner"}, + properties: {level: 3, spark: "Line beautiful."} + } +] AS row +MATCH (start:Character {name: row.start.name}) +MATCH (end:Character {name: row.end.name}) +CREATE (start)-[r:ANIMOSITY]->(end) +SET r += row.properties; +UNWIND [ + { + start: {name: "Randy Sullivan"}, + end: {name: "Laura Ward"}, + properties: {level: 2, spark: "Raise much hope."} + }, + { + start: {name: "Heather Ruiz"}, + end: {name: "Phillip Cook"}, + properties: {level: 0, spark: "Since fish accept."} + }, + { + start: {name: "Cynthia Mendez"}, + end: {name: "Tyler Li"}, + properties: {level: 0, spark: "Brother success."} + }, + { + start: {name: "Mark Hammond"}, + end: {name: "Lonnie Holt"}, + properties: {level: 0, spark: "Above spring cup."} + }, + { + start: {name: "Justin Tran"}, + end: {name: "Jennifer Hill"}, + properties: {level: 3, spark: "Walk approach bring."} + }, + { + start: {name: "Lonnie Holt"}, + end: {name: "Jonathan Khan"}, + properties: {level: -1, spark: "Administration meet."} + }, + { + start: {name: "Mary Russell"}, + end: {name: "Mason Martin"}, + properties: {level: -1, spark: "Player matter."} + }, + { + start: {name: "Laura Ward"}, + end: {name: "Timothy Harris"}, + properties: {level: 1, spark: "Include large only."} + }, + { + start: {name: "Erika Vaughn"}, + end: {name: "Christopher Dorsey"}, + properties: {level: 3, spark: "Role piece eat."} + } +] AS row +MATCH (start:Character {name: row.start.name}) +MATCH (end:Character {name: row.end.name}) +CREATE (start)-[r:PEDAGOGY]->(end) +SET r += row.properties;:commit \ No newline at end of file From fe8ef720c8cc6d99049dd65aa67d7d577c98ba91 Mon Sep 17 00:00:00 2001 From: UltimateForm Date: Sun, 8 Feb 2026 22:15:33 +0000 Subject: [PATCH 4/7] feat: Add fallback to environment variable for JWT sign secret if file is not found. --- internal/config/main.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/config/main.go b/internal/config/main.go index 1187695..32b8611 100644 --- a/internal/config/main.go +++ b/internal/config/main.go @@ -22,7 +22,13 @@ func LoadDbConfig() DbConfig { func LoadAuthConfig() AuthConfig { jwtSign, err := os.ReadFile("/run/secrets/jwt_sign") if err != nil { - panic(err) + 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: string(jwtSign)} } From c97b5104e77c607cafcb55d3f5bea2cc177a0eb1 Mon Sep 17 00:00:00 2001 From: UltimateForm Date: Tue, 10 Feb 2026 02:48:53 +0000 Subject: [PATCH 5/7] feat: Add Kubernetes deployment and service configuration for gopen-api --- kube/api.deployment.yaml | 40 ++++++++++++++++++++++++++++++++++++++++ kube/api.service.yaml | 16 ++++++++++++++++ kube/api.yaml | 20 -------------------- 3 files changed, 56 insertions(+), 20 deletions(-) create mode 100644 kube/api.deployment.yaml create mode 100644 kube/api.service.yaml delete mode 100644 kube/api.yaml diff --git a/kube/api.deployment.yaml b/kube/api.deployment.yaml new file mode 100644 index 0000000..5c77d43 --- /dev/null +++ b/kube/api.deployment.yaml @@ -0,0 +1,40 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + deployment.kubernetes.io/revision: "1" + labels: + app: gopen + name: gopen-api +spec: + progressDeadlineSeconds: 30 + replicas: 3 + revisionHistoryLimit: 6 + selector: + matchLabels: + app: gopen-api + strategy: + rollingUpdate: + maxSurge: 2 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + labels: + app: gopen-api + spec: + containers: + - image: gopen-api:latest + imagePullPolicy: IfNotPresent + name: gopen-api + ports: + - containerPort: 3000 + protocol: TCP + livenessProbe: + httpGet: + path: health + port: 3000 + initialDelaySeconds: 2 + failureThreshold: 1 + successThreshold: 1 + restartPolicy: Always diff --git a/kube/api.service.yaml b/kube/api.service.yaml new file mode 100644 index 0000000..4ae315c --- /dev/null +++ b/kube/api.service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: gopen + name: gopen-api +spec: + ports: + - nodePort: 30000 + port: 3000 + protocol: TCP + targetPort: 3000 + selector: + app: gopen-api + type: NodePort + diff --git a/kube/api.yaml b/kube/api.yaml deleted file mode 100644 index f6122c2..0000000 --- a/kube/api.yaml +++ /dev/null @@ -1,20 +0,0 @@ -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 \ No newline at end of file From b5bde602aee78b374db9bc561797cb94f480d44d Mon Sep 17 00:00:00 2001 From: UltimateForm Date: Sun, 15 Feb 2026 14:57:22 +0000 Subject: [PATCH 6/7] feat: Add Kubernetes configuration files and update environment settings for gopen-api --- .dockerignore | 5 ++++ Dockerfile.jobs | 0 api/bruno/environments/LOCAL.bru | 2 +- kube/ap.configmap.yaml | 9 +++++++ kube/api.deployment.yaml | 10 ++++++++ kube/data.pvc.yaml | 10 ++++++++ kube/db.configmap.yaml | 6 +++++ kube/db.deployment.yaml | 43 ++++++++++++++++++++++++++++++++ kube/db.service.yaml | 14 +++++++++++ skaffold.yaml | 13 ++++++++++ 10 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 Dockerfile.jobs create mode 100644 kube/ap.configmap.yaml create mode 100644 kube/data.pvc.yaml create mode 100644 kube/db.configmap.yaml create mode 100644 kube/db.deployment.yaml create mode 100644 kube/db.service.yaml create mode 100644 skaffold.yaml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ad08cb5 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +kube +.vscode +.secrets +.github +migrations \ No newline at end of file diff --git a/Dockerfile.jobs b/Dockerfile.jobs new file mode 100644 index 0000000..e69de29 diff --git a/api/bruno/environments/LOCAL.bru b/api/bruno/environments/LOCAL.bru index 379db24..7923dab 100644 --- a/api/bruno/environments/LOCAL.bru +++ b/api/bruno/environments/LOCAL.bru @@ -1,5 +1,5 @@ vars { - BASE_URL: http://localhost:3000 + BASE_URL: http://localhost:30000 } vars:secret [ USERNAME, diff --git a/kube/ap.configmap.yaml b/kube/ap.configmap.yaml new file mode 100644 index 0000000..dc671cb --- /dev/null +++ b/kube/ap.configmap.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: dotpen-api.cfg +data: + NEO4J_URI: bolt://gopen-db + NEO4J_USERNAME: neo4j + NEO4J_PASSWORD: testpassword + JWT_SIGN: 74JkywUHV3tmT9Yj7r4gsH22Md5Df45n \ No newline at end of file diff --git a/kube/api.deployment.yaml b/kube/api.deployment.yaml index 5c77d43..a82679d 100644 --- a/kube/api.deployment.yaml +++ b/kube/api.deployment.yaml @@ -27,6 +27,9 @@ spec: - image: gopen-api:latest imagePullPolicy: IfNotPresent name: gopen-api + envFrom: + - configMapRef: + name: dotpen-api.cfg ports: - containerPort: 3000 protocol: TCP @@ -37,4 +40,11 @@ spec: initialDelaySeconds: 2 failureThreshold: 1 successThreshold: 1 + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi restartPolicy: Always diff --git a/kube/data.pvc.yaml b/kube/data.pvc.yaml new file mode 100644 index 0000000..a63a849 --- /dev/null +++ b/kube/data.pvc.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: gopen-data.pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 500Mi \ No newline at end of file diff --git a/kube/db.configmap.yaml b/kube/db.configmap.yaml new file mode 100644 index 0000000..4bd37bd --- /dev/null +++ b/kube/db.configmap.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: gopen-db.cfg +data: + NEO4J_AUTH: neo4j/testpassword diff --git a/kube/db.deployment.yaml b/kube/db.deployment.yaml new file mode 100644 index 0000000..4d5af2d --- /dev/null +++ b/kube/db.deployment.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + deployment.kubernetes.io/revision: "1" + labels: + app: gopen + name: gopen-db +spec: + replicas: 1 + revisionHistoryLimit: 1 + selector: + matchLabels: + app: gopen-db + template: + metadata: + labels: + app: gopen-db + spec: + volumes: + - name: gopen-data-volume + persistentVolumeClaim: + claimName: gopen-data.pvc + containers: + - image: neo4j:community-trixie + name: gopen-db + envFrom: + - configMapRef: + name: gopen-db.cfg + ports: + - containerPort: 7687 + protocol: TCP + volumeMounts: + - mountPath: /data + name: gopen-data-volume + resources: + requests: + memory: "512Mi" + cpu: "250m" + limits: + memory: "1Gi" + cpu: "500m" + restartPolicy: Always diff --git a/kube/db.service.yaml b/kube/db.service.yaml new file mode 100644 index 0000000..9af2d96 --- /dev/null +++ b/kube/db.service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app: gopen + name: gopen-db +spec: + selector: + app: gopen-db + ports: + - port: 7687 + protocol: TCP + targetPort: 7687 + type: ClusterIP diff --git a/skaffold.yaml b/skaffold.yaml new file mode 100644 index 0000000..9fceb52 --- /dev/null +++ b/skaffold.yaml @@ -0,0 +1,13 @@ +apiVersion: skaffold/v4beta13 +kind: Config +metadata: + name: gopen-api +build: + artifacts: + - image: gopen-api + docker: + dockerfile: Dockerfile +manifests: + rawYaml: + - kube/* + From 492a8a3495d00fa37a86083f7dd5220f8354fcd7 Mon Sep 17 00:00:00 2001 From: UltimateForm Date: Sun, 15 Feb 2026 18:24:25 +0000 Subject: [PATCH 7/7] feat: skaffold for local k8s --- .dockerignore | 13 +-- Dockerfile.jobs | 0 compose.yaml | 60 -------------- Dockerfile => docker/api.Dockerfile | 0 docker/api.Dockerfile.dockerignore | 9 ++ docker/migrator.Dockerfile | 9 ++ docker/migrator.Dockerfile.dockeringore | 8 ++ .../api.configmap.yaml} | 0 kube/{ => api}/api.deployment.yaml | 0 kube/{ => api}/api.service.yaml | 9 +- kube/db.deployment.yaml | 43 ---------- kube/{ => db}/data.pvc.yaml | 0 kube/{ => db}/db.configmap.yaml | 0 kube/db/db.deployment.yaml | 58 +++++++++++++ kube/{ => db}/db.service.yaml | 11 +-- kube/jobs/jobs.yaml | 82 +++++++++++++++++++ skaffold.yaml | 8 +- 17 files changed, 189 insertions(+), 121 deletions(-) delete mode 100644 Dockerfile.jobs delete mode 100644 compose.yaml rename Dockerfile => docker/api.Dockerfile (100%) create mode 100644 docker/api.Dockerfile.dockerignore create mode 100644 docker/migrator.Dockerfile create mode 100644 docker/migrator.Dockerfile.dockeringore rename kube/{ap.configmap.yaml => api/api.configmap.yaml} (100%) rename kube/{ => api}/api.deployment.yaml (100%) rename kube/{ => api}/api.service.yaml (63%) delete mode 100644 kube/db.deployment.yaml rename kube/{ => db}/data.pvc.yaml (100%) rename kube/{ => db}/db.configmap.yaml (100%) create mode 100644 kube/db/db.deployment.yaml rename kube/{ => db}/db.service.yaml (51%) create mode 100644 kube/jobs/jobs.yaml diff --git a/.dockerignore b/.dockerignore index ad08cb5..9a4183e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,8 @@ -kube -.vscode -.secrets -.github -migrations \ No newline at end of file +.git +kube/ +api/bruno/ +LICENSE +README.md +# Ignore the other Dockerfile when building one +docker/*.Dockerfile +skaffold.yaml diff --git a/Dockerfile.jobs b/Dockerfile.jobs deleted file mode 100644 index e69de29..0000000 diff --git a/compose.yaml b/compose.yaml deleted file mode 100644 index 79b8258..0000000 --- a/compose.yaml +++ /dev/null @@ -1,60 +0,0 @@ -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: diff --git a/Dockerfile b/docker/api.Dockerfile similarity index 100% rename from Dockerfile rename to docker/api.Dockerfile diff --git a/docker/api.Dockerfile.dockerignore b/docker/api.Dockerfile.dockerignore new file mode 100644 index 0000000..1b968a4 --- /dev/null +++ b/docker/api.Dockerfile.dockerignore @@ -0,0 +1,9 @@ +kube +.vscode +.secrets +.github +migrations +docker +.env +kube +api diff --git a/docker/migrator.Dockerfile b/docker/migrator.Dockerfile new file mode 100644 index 0000000..1958016 --- /dev/null +++ b/docker/migrator.Dockerfile @@ -0,0 +1,9 @@ +FROM neo4j:community-trixie + +WORKDIR /migrator + +RUN mkdir migrations + +COPY ./migrations ./migrations + +CMD [ "cypher-shell", "--help" ] diff --git a/docker/migrator.Dockerfile.dockeringore b/docker/migrator.Dockerfile.dockeringore new file mode 100644 index 0000000..a6635f6 --- /dev/null +++ b/docker/migrator.Dockerfile.dockeringore @@ -0,0 +1,8 @@ +kube +docker +internal +cmd +.backups +.github +.secrets +api diff --git a/kube/ap.configmap.yaml b/kube/api/api.configmap.yaml similarity index 100% rename from kube/ap.configmap.yaml rename to kube/api/api.configmap.yaml diff --git a/kube/api.deployment.yaml b/kube/api/api.deployment.yaml similarity index 100% rename from kube/api.deployment.yaml rename to kube/api/api.deployment.yaml diff --git a/kube/api.service.yaml b/kube/api/api.service.yaml similarity index 63% rename from kube/api.service.yaml rename to kube/api/api.service.yaml index 4ae315c..a6ac908 100644 --- a/kube/api.service.yaml +++ b/kube/api/api.service.yaml @@ -6,11 +6,10 @@ metadata: name: gopen-api spec: ports: - - nodePort: 30000 - port: 3000 - protocol: TCP - targetPort: 3000 + - nodePort: 30000 + port: 3000 + protocol: TCP + targetPort: 3000 selector: app: gopen-api type: NodePort - diff --git a/kube/db.deployment.yaml b/kube/db.deployment.yaml deleted file mode 100644 index 4d5af2d..0000000 --- a/kube/db.deployment.yaml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - deployment.kubernetes.io/revision: "1" - labels: - app: gopen - name: gopen-db -spec: - replicas: 1 - revisionHistoryLimit: 1 - selector: - matchLabels: - app: gopen-db - template: - metadata: - labels: - app: gopen-db - spec: - volumes: - - name: gopen-data-volume - persistentVolumeClaim: - claimName: gopen-data.pvc - containers: - - image: neo4j:community-trixie - name: gopen-db - envFrom: - - configMapRef: - name: gopen-db.cfg - ports: - - containerPort: 7687 - protocol: TCP - volumeMounts: - - mountPath: /data - name: gopen-data-volume - resources: - requests: - memory: "512Mi" - cpu: "250m" - limits: - memory: "1Gi" - cpu: "500m" - restartPolicy: Always diff --git a/kube/data.pvc.yaml b/kube/db/data.pvc.yaml similarity index 100% rename from kube/data.pvc.yaml rename to kube/db/data.pvc.yaml diff --git a/kube/db.configmap.yaml b/kube/db/db.configmap.yaml similarity index 100% rename from kube/db.configmap.yaml rename to kube/db/db.configmap.yaml diff --git a/kube/db/db.deployment.yaml b/kube/db/db.deployment.yaml new file mode 100644 index 0000000..364d0ce --- /dev/null +++ b/kube/db/db.deployment.yaml @@ -0,0 +1,58 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + deployment.kubernetes.io/revision: "1" + labels: + app: gopen + name: gopen-db +spec: + replicas: 1 + revisionHistoryLimit: 1 + selector: + matchLabels: + app: gopen-db + template: + metadata: + labels: + app: gopen-db + spec: + volumes: + - name: gopen-data-volume + persistentVolumeClaim: + claimName: gopen-data.pvc + containers: + - image: neo4j:community-trixie + name: gopen-db + envFrom: + - configMapRef: + name: gopen-db.cfg + ports: + - containerPort: 7687 + protocol: TCP + volumeMounts: + - mountPath: /data + name: gopen-data-volume + readinessProbe: + exec: + command: + [ + "cypher-shell", + "-u", + "neo4j", + "-p", + "testpassword", + "--access-mode=read", + "RETURN 0", + ] + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 60 + resources: + requests: + memory: "512Mi" + cpu: "250m" + limits: + memory: "1Gi" + cpu: "500m" + restartPolicy: Always diff --git a/kube/db.service.yaml b/kube/db/db.service.yaml similarity index 51% rename from kube/db.service.yaml rename to kube/db/db.service.yaml index 9af2d96..a91042d 100644 --- a/kube/db.service.yaml +++ b/kube/db/db.service.yaml @@ -1,14 +1,15 @@ apiVersion: v1 kind: Service metadata: - labels: + labels: app: gopen name: gopen-db spec: selector: app: gopen-db ports: - - port: 7687 - protocol: TCP - targetPort: 7687 - type: ClusterIP + - nodePort: 31000 + port: 7687 + protocol: TCP + targetPort: 7687 + type: NodePort diff --git a/kube/jobs/jobs.yaml b/kube/jobs/jobs.yaml new file mode 100644 index 0000000..faf52a1 --- /dev/null +++ b/kube/jobs/jobs.yaml @@ -0,0 +1,82 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: gopen-db-setup +spec: + template: + spec: + containers: + - name: setup + image: gopen-db-migrator + imagePullPolicy: IfNotPresent + command: + [ + "cypher-shell", + "-a", + "bolt://gopen-db", + "-u", + "neo4j", + "-p", + "testpassword", + "-f", + "/migrator/migrations/setup.cypher", + ] + readinessProbe: + exec: + command: + [ + "cypher-shell", + "-a", + "bolt://gopen-db", + "-u", + "neo4j", + "-p", + "testpassword", + "--access-mode=read", + "RETURN 0", + ] + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 60 + restartPolicy: Never + backoffLimit: 4 +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: gopen-db-hydrate +spec: + template: + spec: + containers: + - name: hydrate + image: gopen-db-migrator + imagePullPolicy: IfNotPresent + command: + [ + "cypher-shell", + "-a", + "bolt://gopen-db", + "-u", + "neo4j", + "-p", + "testpassword", + "-f", + "/migrator/migrations/test_docs.cypher", + ] + readinessProbe: + exec: + command: + [ + "cypher-shell", + "-a", + "bolt://gopen-db", + "-u", + "neo4j", + "-p", + "testpassword", + "--access-mode=read", + "RETURN 0", + ] + restartPolicy: Never + backoffLimit: 4 diff --git a/skaffold.yaml b/skaffold.yaml index 9fceb52..e579f75 100644 --- a/skaffold.yaml +++ b/skaffold.yaml @@ -6,8 +6,10 @@ build: artifacts: - image: gopen-api docker: - dockerfile: Dockerfile + dockerfile: ./docker/api.Dockerfile + - image: gopen-db-migrator + docker: + dockerfile: ./docker/migrator.Dockerfile manifests: rawYaml: - - kube/* - + - kube/**/*.yaml