chore: initial commit

This commit is contained in:
2024-04-16 22:27:52 +01:00
commit 531b5dabe2
194 changed files with 27071 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/hexolan/stocklet/internal/pkg/config"
)
// Init Container Configuration
type InitConfig struct {
// Name of the service (e.g. 'auth' or 'order')
//
// Env Var: "INIT_SVC_NAME"
ServiceName string
// Env Var: "INIT_MIGRATIONS" (optional. accepts 'false')
// Defaults to true
ApplyMigrations bool
// 'ApplyDebezium' will default to false unless
// the debezium host is provided.
//
// Env Var: "INIT_DEBEZIUM_HOST" (optional)
// e.g. "http://debezium:8083"
ApplyDebezium bool
DebeziumHost string
}
func (opts *InitConfig) Load() error {
// ServiceName
opt, err := config.RequireFromEnv("INIT_SVC_NAME")
if err != nil {
return err
}
opts.ServiceName = opt
// ApplyMigrations
opts.ApplyMigrations = true
if opt, _ := config.RequireFromEnv("INIT_MIGRATIONS"); opt == "false" {
opts.ApplyMigrations = false
}
// ApplyDebezium and DebeziumHost
if opt, err := config.RequireFromEnv("INIT_DEBEZIUM_HOST"); err == nil {
opts.ApplyDebezium = true
opts.DebeziumHost = opt
}
return nil
}

View File

@@ -0,0 +1,67 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"bytes"
"encoding/json"
"net/http"
"github.com/rs/zerolog/log"
"github.com/hexolan/stocklet/internal/pkg/config"
)
func applyPostgresOutbox(cfg *InitConfig, conf *config.PostgresConfig) {
payloadB, err := json.Marshal(map[string]string{
"connector.class": "io.debezium.connector.postgresql.PostgresConnector",
"plugin.name": "pgoutput",
"tasks.max": "1",
"table.include.list": "public.event_outbox",
"transforms": "outbox",
"transforms.outbox.type": "io.debezium.transforms.outbox.EventRouter",
"transforms.outbox.route.topic.replacement": "${routedByValue}",
"value.converter": "io.debezium.converters.BinaryDataConverter",
"topic.prefix": cfg.ServiceName,
"database.hostname": conf.Host,
"database.port": conf.Port,
"database.user": conf.Username,
"database.password": conf.Password,
"database.dbname": conf.Database,
})
if err != nil {
log.Panic().Err(err).Msg("debezium connect: failed to marshal debezium cfg")
}
url := cfg.DebeziumHost + "/connectors/" + cfg.ServiceName + "-outbox/config"
log.Info().Str("url", url).Msg("debezium url")
req, err := http.NewRequest(
"PUT",
url,
bytes.NewReader(payloadB),
)
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
log.Panic().Err(err).Msg("debezium connect: failed to perform debezium request")
}
log.Info().Str("status", res.Status).Msg("debezium connect: applied outbox config")
}

52
cmd/service-init/main.go Normal file
View File

@@ -0,0 +1,52 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/rs/zerolog/log"
"github.com/hexolan/stocklet/internal/pkg/config"
)
func main() {
// Load the init container cfg options
cfg := InitConfig{}
if err := cfg.Load(); err != nil {
log.Panic().Err(err).Msg("missing required configuration")
}
// If migrations or debezium are enabled,
// then a database configuration will be required.
if cfg.ApplyMigrations || cfg.ApplyDebezium {
// Support for dynamic loading of configuration
// (e.g. mongo config instead of postgres config)
pgConf := config.PostgresConfig{}
if err := pgConf.Load(); err == nil {
// Using postgres as a database.
if cfg.ApplyMigrations {
applyPostgresMigrations(&pgConf)
}
if cfg.ApplyDebezium {
applyPostgresOutbox(&cfg, &pgConf)
}
} else {
log.Panic().Msg("unable to load any db configs (unable to perform migrations or apply connector cfgs)")
}
}
log.Info().Str("svc", cfg.ServiceName).Msg("completed init for service")
}

View File

@@ -0,0 +1,43 @@
// Copyright (C) 2024 Declan Teevan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"
"github.com/rs/zerolog/log"
"github.com/hexolan/stocklet/internal/pkg/config"
)
func applyPostgresMigrations(conf *config.PostgresConfig) {
m, err := migrate.New("file:///migrations", conf.GetDSN())
if err != nil {
log.Panic().Err(err).Msg("migrate: failed to open client")
}
err = m.Up()
if err != nil {
if err.Error() == "no change" {
log.Info().Err(err).Msg("migrate: migrations up to date")
} else {
log.Panic().Err(err).Msg("migrate: raised when performing db migration")
}
}
log.Info().Msg("migrate: succesfully performed postgres migrations")
}