Skip to content
Open
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
6 changes: 3 additions & 3 deletions admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ import (
"os"
"time"

"github.com/webhookx-io/webhookx/config"
"github.com/webhookx-io/webhookx/config/modules"
"go.uber.org/zap"
)

// Admin is an HTTP Server
type Admin struct {
cfg *config.AdminConfig
cfg *modules.AdminConfig
s *http.Server
log *zap.SugaredLogger
}

func NewAdmin(cfg config.AdminConfig, handler http.Handler) *Admin {
func NewAdmin(cfg modules.AdminConfig, handler http.Handler) *Admin {
s := &http.Server{
Handler: handler,
Addr: cfg.Listen,
Expand Down
1 change: 0 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ func New(cfg *config.Config) (*Application, error) {

func (app *Application) initialize() error {
cfg := app.cfg
cfg.OverrideByRole(cfg.Role)

log, err := log.NewZapLogger(&cfg.Log)
if err != nil {
Expand Down
14 changes: 13 additions & 1 deletion cmd/db.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package cmd

import (
"context"
"errors"

"github.com/golang-migrate/migrate/v4"
"github.com/spf13/cobra"
"github.com/webhookx-io/webhookx/config"
"github.com/webhookx-io/webhookx/db"
"github.com/webhookx-io/webhookx/db/migrator"
)
Expand All @@ -25,6 +27,7 @@
return errors.New("canceled")
}
}
cfg := cmd.Context().Value("config").(*config.Config)
db, err := db.NewSqlDB(cfg.Database)
if err != nil {
return err
Expand All @@ -47,11 +50,18 @@
}

func newDatabaseCmd() *cobra.Command {

database := &cobra.Command{
Use: "db",
Short: "Database commands",
Long: ``,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
cfg, err := initConfig(configurationFile)
if err != nil {
return err
}
cmd.SetContext(context.WithValue(cmd.Context(), "config", cfg))

Check failure on line 62 in cmd/db.go

View workflow job for this annotation

GitHub Actions / lint

SA1029: should not use built-in type string as key for value; define your own type to avoid collisions (staticcheck)
return nil
},
}

database.PersistentFlags().StringVarP(&configurationFile, "config", "", "", "The configuration filename")
Expand All @@ -62,6 +72,7 @@
Short: "Print the migration status",
Long: ``,
RunE: func(cmd *cobra.Command, args []string) error {
cfg := cmd.Context().Value("config").(*config.Config)
db, err := db.NewSqlDB(cfg.Database)
if err != nil {
return err
Expand All @@ -81,6 +92,7 @@
Short: "Run any new migrations",
Long: ``,
RunE: func(cmd *cobra.Command, args []string) error {
cfg := cmd.Context().Value("config").(*config.Config)
db, err := db.NewSqlDB(cfg.Database)
if err != nil {
return err
Expand Down
24 changes: 10 additions & 14 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"os"

"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/webhookx-io/webhookx/config"
)
Expand All @@ -14,24 +15,20 @@ var (
var (
configurationFile string
verbose bool
cfg *config.Config
)

func initConfig() {
var err error

var options config.Options
if configurationFile != "" {
buf, err := os.ReadFile(configurationFile)
cobra.CheckErr(err)
options.YAML = buf
func initConfig(filename string) (*config.Config, error) {
cfg := config.New()
err := config.Load(filename, cfg)
if err != nil {
return nil, errors.Wrap(err, "could not load configuration")
}

cfg, err = config.New(&options)
cobra.CheckErr(err)

err = cfg.Validate()
cobra.CheckErr(err)
if err != nil {
return nil, errors.Wrap(err, "invalid configuration")
}
return cfg, nil
}

func NewRootCmd() *cobra.Command {
Expand All @@ -41,7 +38,6 @@ func NewRootCmd() *cobra.Command {
Long: ``,
SilenceUsage: true,
}
cobra.OnInitialize(initConfig)

cmd.SetOut(os.Stdout)
cmd.PersistentFlags().BoolVarP(&verbose, "verbose", "", false, "Verbose logging.")
Expand Down
5 changes: 5 additions & 0 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ func newStartCmd() *cobra.Command {
Short: "Start server",
Long: ``,
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := initConfig(configurationFile)
if err != nil {
return err
}

app, err := app.New(cfg)
if err != nil {
return err
Expand Down
48 changes: 48 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,51 @@ tracing:
# Example of grpc:
# protocol: grpc
# endpoint: localhost:4317


#------------------------------------------------------------------------------
# Secret Reference (External Secret Reference)
# Secret Reference allows fetching values from external secret providers.
#
# Syntax:
# {secret://<provider>/<name>[.<jsonpath>][?<parameters>]}
#
# Components:
# - <provider> The provider name (e.g.`aws`, `vault`).
# - <name> The secret name.
# - <jsonpath> A optional JSON Path to extract value from a JSON.
# JSON Path is a series of keys separated by a `.` character.
# Examples: `database.username`, `credentials.1.username`.
# - <parameters> The optional parameters.
#
# Examples:
# {secret://aws/path/to/mysecret}
# {secret://aws/path/to/mysecret.password}
#------------------------------------------------------------------------------
secret:
providers: # Specifies enabled providers.
- '@default' # Supported values:
# - `@default`: an alias of built-in providers.
# - `aws`
# - `vault`

aws: # AWS SecretsManager provider
region: # AWS region.
url: # Optional custom endpoint.
# If unset, uses AWS default endpoint resolution.

vault: # HashiCorp Vault provider (KV v2)
address: http://127.0.0.1:8200 # Vault server address.
mount_path: secret # The mount path for KV secrets engine.
namespace: # Vault namespace (for Vault Enterprise).
auth_method: token # Authentication method. Supported values: `token`, `approle`, `kubernetes`.
authn: # Authentication configuration.
token:
token: # The token used to making requests to Vault.
approle:
role_id: # RoleID used for login.
secret_id: # SecretID used for login.
response_wrapping: false # Whether to use response-wrapping. Defaults to false.
kubernetes:
role: # Vault role bound to the Kubernetes service account.
token_path: # Path to JWT token file.
114 changes: 56 additions & 58 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"slices"

"github.com/creasty/defaults"
"github.com/webhookx-io/webhookx/pkg/envconfig"
"gopkg.in/yaml.v3"
"github.com/webhookx-io/webhookx/config/core"
"github.com/webhookx-io/webhookx/config/modules"
)

var (
Expand All @@ -24,19 +24,54 @@ const (
RoleDPProxy Role = "dp_proxy"
)

var _ core.Config = &Config{}

type Config struct {
Log LogConfig `yaml:"log" json:"log" envconfig:"LOG"`
AccessLog AccessLogConfig `yaml:"access_log" json:"access_log" envconfig:"ACCESS_LOG"`
Database DatabaseConfig `yaml:"database" json:"database" envconfig:"DATABASE"`
Redis RedisConfig `yaml:"redis" json:"redis" envconfig:"REDIS"`
Admin AdminConfig `yaml:"admin" json:"admin" envconfig:"ADMIN"`
Status StatusConfig `yaml:"status" json:"status" envconfig:"STATUS"`
Proxy ProxyConfig `yaml:"proxy" json:"proxy" envconfig:"PROXY"`
Worker WorkerConfig `yaml:"worker" json:"worker" envconfig:"WORKER"`
Metrics MetricsConfig `yaml:"metrics" json:"metrics" envconfig:"METRICS"`
Tracing TracingConfig `yaml:"tracing" json:"tracing" envconfig:"TRACING"`
Role Role `yaml:"role" json:"role" envconfig:"ROLE" default:"standalone"`
AnonymousReports bool `yaml:"anonymous_reports" json:"anonymous_reports" envconfig:"ANONYMOUS_REPORTS" default:"true"`
core.BaseConfig
Log modules.LogConfig `yaml:"log" json:"log" envconfig:"LOG"`
AccessLog modules.AccessLogConfig `yaml:"access_log" json:"access_log" envconfig:"ACCESS_LOG"`
Database modules.DatabaseConfig `yaml:"database" json:"database" envconfig:"DATABASE"`
Redis modules.RedisConfig `yaml:"redis" json:"redis" envconfig:"REDIS"`
Admin modules.AdminConfig `yaml:"admin" json:"admin" envconfig:"ADMIN"`
Status modules.StatusConfig `yaml:"status" json:"status" envconfig:"STATUS"`
Proxy modules.ProxyConfig `yaml:"proxy" json:"proxy" envconfig:"PROXY"`
Worker modules.WorkerConfig `yaml:"worker" json:"worker" envconfig:"WORKER"`
Metrics modules.MetricsConfig `yaml:"metrics" json:"metrics" envconfig:"METRICS"`
Tracing modules.TracingConfig `yaml:"tracing" json:"tracing" envconfig:"TRACING"`
Role Role `yaml:"role" json:"role" envconfig:"ROLE" default:"standalone"`
AnonymousReports bool `yaml:"anonymous_reports" json:"anonymous_reports" envconfig:"ANONYMOUS_REPORTS" default:"true"`
Secret modules.SecretConfig `yaml:"secret" json:"secret" envconfig:"SECRET"`
}

func (c *Config) GetSecret() *modules.SecretConfig {
return &c.Secret
}

func (cfg *Config) Sanitize() {
//TODO implement me
panic("implement me")
}

func (cfg *Config) PostProcess() error {
switch cfg.Role {
case RoleCP:
if cfg.Admin.Listen == "" {
cfg.Admin.Listen = "127.0.0.1:9601"
}
cfg.Proxy.Listen = ""
cfg.Worker.Enabled = false
case RoleDPProxy:
if cfg.Proxy.Listen == "" {
cfg.Proxy.Listen = "0.0.0.0:9600"
}
cfg.Admin.Listen = ""
cfg.Worker.Enabled = false
case RoleDPWorker:
cfg.Admin.Listen = ""
cfg.Proxy.Listen = ""
cfg.Worker.Enabled = true
}
return nil
}

func (cfg Config) String() string {
Expand Down Expand Up @@ -81,54 +116,17 @@ func (cfg Config) Validate() error {
if !slices.Contains([]Role{RoleStandalone, RoleCP, RoleDPWorker, RoleDPProxy}, cfg.Role) {
return fmt.Errorf("invalid role: '%s'", cfg.Role)
}
if err := cfg.Secret.Validate(); err != nil {
return err
}

return nil
}

type Options struct {
YAML []byte
}

func New(opts *Options) (*Config, error) {
func New() *Config {
var cfg Config
err := defaults.Set(&cfg)
if err != nil {
return nil, err
}

if opts != nil {
if len(opts.YAML) > 0 {
if err := yaml.Unmarshal(opts.YAML, &cfg); err != nil {
return nil, err
}
}
}

err = envconfig.Process("WEBHOOKX", &cfg)
if err != nil {
return nil, err
}

return &cfg, nil
}

func (cfg *Config) OverrideByRole(role Role) {
switch role {
case RoleCP:
if cfg.Admin.Listen == "" {
cfg.Admin.Listen = "127.0.0.1:9601"
}
cfg.Proxy.Listen = ""
cfg.Worker.Enabled = false
case RoleDPProxy:
if cfg.Proxy.Listen == "" {
cfg.Proxy.Listen = "0.0.0.0:9600"
}
cfg.Admin.Listen = ""
cfg.Worker.Enabled = false
case RoleDPWorker:
cfg.Admin.Listen = ""
cfg.Proxy.Listen = ""
cfg.Worker.Enabled = true
if err := defaults.Set(&cfg); err != nil {
panic(err)
}
return &cfg
}
Loading
Loading