Skip to content

Commit

Permalink
- add S3 backups
Browse files Browse the repository at this point in the history
- add /health healthcheck endpoint
- use s6 to handle tasks interally in the container instead of scripts
- remove unnecessary docker-related files in /backend
- deprecate old startup scripts
  • Loading branch information
dreth committed Aug 12, 2024
1 parent 89a277d commit 958f96d
Show file tree
Hide file tree
Showing 21 changed files with 302 additions and 131 deletions.
32 changes: 0 additions & 32 deletions backend/Dockerfile

This file was deleted.

2 changes: 1 addition & 1 deletion backend/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ func Login(c *gin.Context) {
// @Failure 500 {object} structs.Error "Internal server error"
// @Security Bearer
// @Router /me [get]
// @Tags user
// @Tags auth
func Me(c *gin.Context) {
userData, err := GetUserData(c)
if helper.HE(c, err, http.StatusInternalServerError, "invalid email or password", true) {
Expand Down
109 changes: 109 additions & 0 deletions backend/backups/s3.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package backups

import (
"fmt"
"log"
"os"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
)

// S3EnvVarspresent checks if the required environment variables for S3 are set.
func S3EnvVarspresent() bool {
// Check if the required environment variables are set
if os.Getenv("HBD_BUCKET_NAME") == "" {
log.Println("HBD_BUCKET_NAME is not set")
return false
}

if os.Getenv("HBD_BUCKET_REGION") == "" {
log.Println("HBD_BUCKET_REGION is not set")
return false
}

if os.Getenv("HBD_USER_ACCESS_KEY_ID") == "" {
log.Println("HBD_USER_ACCESS_KEY_ID is not set")
return false
}

if os.Getenv("HBD_USER_SECRET_ACCESS_KEY") == "" {
log.Println("HBD_USER_SECRET_ACCESS_KEY is not set")
return false
}

return true
}

// BackupDBToS3 uploads the SQLite database to S3.
func BackupDBToS3() {
// Check if backups are enabled
if os.Getenv("ENABLE_BACKUP") != "true" {
return
}

if !S3EnvVarspresent() {
log.Println("S3 environment variables not set")
return
}

// Get the database URL from the environment
databaseURL := os.Getenv("DATABASE_URL")
bucketName := os.Getenv("HBD_BUCKET_NAME")
objectKey := databaseURL[strings.LastIndex(databaseURL, "/")+1:]

err := uploadDBToS3(databaseURL, bucketName, objectKey)
if err != nil {
log.Printf("Failed to upload database: %v", err)
}
}

// uploadDBToS3 uploads the database file to the specified S3 bucket and key.
func uploadDBToS3(dbPath, bucketName, objectKey string) error {
// Create a new S3 session
sess, err := session.NewSession(&aws.Config{
Region: aws.String(os.Getenv("HBD_BUCKET_REGION")),
Credentials: credentials.NewStaticCredentials(
os.Getenv("HBD_USER_ACCESS_KEY_ID"),
os.Getenv("HBD_USER_SECRET_ACCESS_KEY"),
"",
),
})
if err != nil {
log.Fatalf("Failed to create AWS session: %v", err)
}

// Create an S3 client
svc := s3.New(sess)

// Open the database file
file, err := os.Open(dbPath)
if err != nil {
return fmt.Errorf("failed to open database file: %w", err)
}
defer file.Close()

// Get the file size and content type (optional, could set a default)
fileInfo, err := file.Stat()
if err != nil {
return fmt.Errorf("failed to get file info: %w", err)
}
fileSize := fileInfo.Size()

// Upload the file to S3
_, err = svc.PutObject(&s3.PutObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
Body: file,
ContentLength: aws.Int64(fileSize),
ContentType: aws.String("application/x-sqlite3"),
})
if err != nil {
return fmt.Errorf("failed to upload file to S3: %w", err)
}

return nil
}
36 changes: 0 additions & 36 deletions backend/docker-compose.yml

This file was deleted.

30 changes: 29 additions & 1 deletion backend/docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,26 @@ const docTemplate = `{
"x-order": 1
}
},
"/health": {
"get": {
"description": "This endpoint checks the readiness of the service and returns a status.",
"produces": [
"application/json"
],
"tags": [
"health"
],
"summary": "Check service readiness",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/structs.Ready"
}
}
}
}
},
"/login": {
"post": {
"description": "This endpoint logs in a user by validating their email and password. Upon successful authentication, it generates a JWT token and returns the user's details along with the filtered list of birthdays.",
Expand Down Expand Up @@ -310,7 +330,7 @@ const docTemplate = `{
"application/json"
],
"tags": [
"user"
"auth"
],
"summary": "Get user data",
"responses": {
Expand Down Expand Up @@ -649,6 +669,14 @@ const docTemplate = `{
}
}
},
"structs.Ready": {
"type": "object",
"properties": {
"status": {
"type": "string"
}
}
},
"structs.RegisterRequest": {
"type": "object",
"required": [
Expand Down
30 changes: 29 additions & 1 deletion backend/docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,26 @@
"x-order": 1
}
},
"/health": {
"get": {
"description": "This endpoint checks the readiness of the service and returns a status.",
"produces": [
"application/json"
],
"tags": [
"health"
],
"summary": "Check service readiness",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/structs.Ready"
}
}
}
}
},
"/login": {
"post": {
"description": "This endpoint logs in a user by validating their email and password. Upon successful authentication, it generates a JWT token and returns the user's details along with the filtered list of birthdays.",
Expand Down Expand Up @@ -299,7 +319,7 @@
"application/json"
],
"tags": [
"user"
"auth"
],
"summary": "Get user data",
"responses": {
Expand Down Expand Up @@ -638,6 +658,14 @@
}
}
},
"structs.Ready": {
"type": "object",
"properties": {
"status": {
"type": "string"
}
}
},
"structs.RegisterRequest": {
"type": "object",
"required": [
Expand Down
21 changes: 20 additions & 1 deletion backend/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ definitions:
example: 9cc76406913372c2b3a3474e8ebb8dc917bdb9c4a7c5e98c639ed20f5bcf4da1
type: string
type: object
structs.Ready:
properties:
status:
type: string
type: object
structs.RegisterRequest:
properties:
email:
Expand Down Expand Up @@ -318,6 +323,20 @@ paths:
tags:
- auth
x-order: 1
/health:
get:
description: This endpoint checks the readiness of the service and returns a
status.
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/structs.Ready'
summary: Check service readiness
tags:
- health
/login:
post:
consumes:
Expand Down Expand Up @@ -375,7 +394,7 @@ paths:
- Bearer: []
summary: Get user data
tags:
- user
- auth
/modify-birthday:
put:
consumes:
Expand Down
6 changes: 5 additions & 1 deletion backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ require (
modernc.org/sqlite v1.30.2
)

require github.com/golang-jwt/jwt/v5 v5.2.1
require (
github.com/aws/aws-sdk-go v1.49.6
github.com/golang-jwt/jwt/v5 v5.2.1
)

require (
github.com/KyleBanks/depth v1.2.1 // indirect
Expand Down Expand Up @@ -55,6 +58,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
Expand Down
6 changes: 6 additions & 0 deletions backend/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go v1.49.6 h1:yNldzF5kzLBRvKlKz1S0bkvc2+04R1kt13KfBWQBfFA=
github.com/aws/aws-sdk-go v1.49.6/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
Expand Down Expand Up @@ -354,6 +356,10 @@ github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
Expand Down
18 changes: 18 additions & 0 deletions backend/helper/system.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package helper

import (
"hbd/structs"

"github.com/gin-gonic/gin"
)

// HealthCheck checks if the service is ready and returns a status response.
// @Summary Check service readiness
// @Description This endpoint checks the readiness of the service and returns a status.
// @Produce json
// @Success 200 {object} structs.Ready
// @Router /health [get]
// @Tags health
func HealthCheck(c *gin.Context) {
c.JSON(200, structs.Ready{Status: "ok"})
}
Loading

0 comments on commit 958f96d

Please sign in to comment.