database & CD bucket

This commit is contained in:
2024-11-13 21:16:22 +01:00
parent f5013e5f9e
commit abd805b9cd
18 changed files with 530 additions and 34 deletions

42
config/env.go Normal file
View File

@ -0,0 +1,42 @@
package config
import (
"os"
"strconv"
"time"
)
func (c *Config) ReadEnv() (err error) {
// General Configuration
stringVar(&c.BaseUrl, "BASE_URL")
stringVar(&c.SavePath, "SAVE_PATH")
intVar(&c.Port, "PORT")
return
}
func stringVar(x *string, key string) {
if v := os.Getenv(key); v != "" {
*x = v
}
}
func float64Var(x *float64, key string) (err error) {
if v := os.Getenv(key); v != "" {
*x, err = strconv.ParseFloat(v, 64)
}
return
}
func intVar(x *int, key string) (err error) {
if v := os.Getenv(key); v != "" {
*x, err = strconv.Atoi(v)
}
return
}
func durationVar(x *time.Duration, key string) (err error) {
if v := os.Getenv(key); v != "" {
*x, err = time.ParseDuration(v)
}
return
}

134
config/env_test.go Normal file
View File

@ -0,0 +1,134 @@
package config
import (
"os"
"testing"
"time"
)
func TestReadEnv(t *testing.T) {
// Set up environment variables
os.Setenv("CONFIG_PATH", "/path/to/config")
os.Setenv("ENV", "dev")
os.Setenv("PORT", "80")
os.Setenv("BASE_URL", "https://example.com")
os.Setenv("ACCESS_ORIGIN", "lou-taylor.ch")
os.Setenv("DB_HOST", "localhost")
os.Setenv("DB_PORT", "5432")
os.Setenv("DB_USER", "testuser")
os.Setenv("DB_PASSWORD", "password")
os.Setenv("DB_NAME", "testdb")
os.Setenv("ADMIN_NAME", "admin")
os.Setenv("ADMIN_PASSWORD", "adminpass")
os.Setenv("JWT_SECRET", "supersecret")
os.Setenv("JWT_VALID_PERIOD", "24h")
os.Setenv("IMAGE_QUALITY", "85.5")
os.Setenv("IMAGE_MAX_WIDTH", "1920")
os.Setenv("IMAGE_SAVE_PATH", "/path/to/images")
// Initialize an empty Config struct
c := New()
// Call ReadEnv to populate the config from environment variables
err := c.ReadEnv()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if c.BaseUrl != "https://example.com" {
t.Errorf("expected BaseUrl to be 'https://example.com', got %v", c.BaseUrl)
}
if c.Port != 80 {
t.Errorf("expected Port to be 80, got %d", c.Port)
}
}
func TestHelperFunctions(t *testing.T) {
t.Run("stringVar", func(t *testing.T) {
// Set up environment variable
os.Setenv("TEST_STRING", "test_value")
var result string
stringVar(&result, "TEST_STRING")
if result != "test_value" {
t.Errorf("expected 'test_value', got '%v'", result)
}
// Test empty environment variable case
os.Setenv("TEST_STRING_EMPTY", "")
stringVar(&result, "TEST_STRING_EMPTY")
if result != "test_value" { // result shouldn't change
t.Errorf("expected 'test_value', got '%v'", result)
}
})
t.Run("float64Var", func(t *testing.T) {
// Set up valid float environment variable
os.Setenv("TEST_FLOAT", "42.42")
var result float64
err := float64Var(&result, "TEST_FLOAT")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result != 42.42 {
t.Errorf("expected 42.42, got '%v'", result)
}
// Test invalid float value
os.Setenv("TEST_FLOAT_INVALID", "invalid_float")
err = float64Var(&result, "TEST_FLOAT_INVALID")
if err == nil {
t.Errorf("expected error for invalid float, but got nil")
}
})
t.Run("intVar", func(t *testing.T) {
// Set up valid integer environment variable
os.Setenv("TEST_INT", "123")
var result int
err := intVar(&result, "TEST_INT")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result != 123 {
t.Errorf("expected 123, got '%v'", result)
}
// Test invalid int value
os.Setenv("TEST_INT_INVALID", "invalid_int")
err = intVar(&result, "TEST_INT_INVALID")
if err == nil {
t.Errorf("expected error for invalid int, but got nil")
}
})
t.Run("durationVar", func(t *testing.T) {
// Set up valid duration environment variable
os.Setenv("TEST_DURATION", "2h")
var result time.Duration
err := durationVar(&result, "TEST_DURATION")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expectedDuration := 2 * time.Hour
if result != expectedDuration {
t.Errorf("expected %v, got '%v'", expectedDuration, result)
}
// Test invalid duration value
os.Setenv("TEST_DURATION_INVALID", "invalid_duration")
err = durationVar(&result, "TEST_DURATION_INVALID")
if err == nil {
t.Errorf("expected error for invalid duration, but got nil")
}
})
}

13
config/flag.go Normal file
View File

@ -0,0 +1,13 @@
package config
import (
"flag"
)
func (c *Config) ReadFlags() {
flag.StringVar(&c.ConfigPath, "config", c.ConfigPath, "path of the toml configuration file")
flag.StringVar(&c.BaseUrl, "base-ulr", c.BaseUrl, "base url of the api")
flag.IntVar(&c.Port, "port", c.Port, "port of the api")
flag.Parse()
}

39
config/resource.go Normal file
View File

@ -0,0 +1,39 @@
package config
type Environment string
const (
Dev Environment = "dev"
Staging = "staging"
Production = "prod"
)
// Config holds all configuration values
type Config struct {
ConfigPath string `toml:"-"`
SavePath string `toml:"savePath"`
BaseUrl string `toml:"base_url"`
Port int `toml:"port"`
}
// New returns a pointer to a default configuration with all empty values
func New() *Config {
return &Config{
ConfigPath: "",
Port: 0,
SavePath: "",
BaseUrl: "",
}
}
// Default returns a pointer to a default configuration
func Default() *Config {
return &Config{
ConfigPath: "./config.toml",
BaseUrl: "http://localhost:8080",
Port: 8080,
SavePath: "./storage",
}
}

26
config/toml.go Normal file
View File

@ -0,0 +1,26 @@
package config
import (
"os"
"github.com/pelletier/go-toml/v2"
)
func (c *Config) ReadFile(name string) error {
file, err := os.Open(name)
if err != nil {
return err
}
err = toml.NewDecoder(file).Decode(c)
return err
}
func (c *Config) TOML() string {
b, err := toml.Marshal(c)
if err != nil {
panic(err)
}
return string(b)
}

22
config/toml_test.go Normal file
View File

@ -0,0 +1,22 @@
package config
import (
"testing"
)
func TestReadFile(t *testing.T) {
c := Default()
err := c.ReadFile("../config.example.toml")
if err != nil {
t.Fatalf("failed to read config file: %v", err)
}
// Validate the values are correctly set based on the TOML file
expectedBaseURL := "http://localhost:8080"
if c.BaseUrl != expectedBaseURL {
t.Errorf("expected BaseUrl to be '%v', got '%v'", expectedBaseURL, c.BaseUrl)
}
}