some ideas

This commit is contained in:
adlerhurst
2025-03-04 20:00:09 +01:00
parent 8f0ca7b2cd
commit b093112063
10 changed files with 165 additions and 122 deletions

View File

@@ -114,6 +114,10 @@ func handleField(v *viper.Viper, field reflect.StructField, value reflect.Value)
value = reflect.Indirect(value)
if value.IsZero() {
value = reflect.New(value.Type()).Elem()
}
// Check if potential non pointer value implements [OneOfField]
if value.Type().Implements(reflect.TypeFor[OneOfField]()) {
return handleOneOf(v, field, value, fieldConfig)

View File

@@ -0,0 +1,70 @@
package bla2
import (
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
type TestConfig struct {
API APIConfig `configure:""`
Database DatabaseOneOf `configure:"type=oneof"`
}
type APIConfig struct {
Host string `configure:""`
Port uint16 `configure:""`
}
type DatabaseOneOf struct {
ConnectionString *string `configure:""`
Config *DatabaseConfig `configure:""`
}
type DatabaseConfig struct {
Host string `configure:""`
Port uint16 `configure:""`
SSLMode string `configure:""`
}
type Config interface {
Hooks() []viper.DecoderConfigOption
}
func Update(v *viper.Viper, config any) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
// promptui.Select
// err := handleStruct(v, reflect.ValueOf(config), configuration{})
// if err != nil {
// fmt.Println(err)
// os.Exit(1)
// }
// err = v.WriteConfig()
// if err != nil {
// fmt.Println(err)
// os.Exit(1)
// }
}
}
const (
tagName = "configure"
defaultKey = "default"
oneOfKey = "oneof"
)
type Field struct {
Name string
DefaultValue any
Prompt prompt
}
type prompt interface {
Run()
}
var (
_ prompt = (*promptui.Select)(nil)
_ prompt = (*promptui.SelectWithAdd)(nil)
_ prompt = (*promptui.Prompt)(nil)
)

View File

@@ -17,7 +17,7 @@ var (
)
type Step001 struct {
Database database.Pool `mapstructure:"-"`
Database database.Pool `mapstructure:"-" configure:"-"`
DatabaseName string `configure:"default=zitadel"`
Username string `configure:"default=zitadel"`

View File

@@ -1,12 +1,12 @@
package prepare
import (
"github.com/Masterminds/semver/v3"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/zitadel/zitadel/backend/cmd/config"
"github.com/zitadel/zitadel/backend/cmd/configure"
"github.com/zitadel/zitadel/backend/cmd/configure/bla"
step001 "github.com/zitadel/zitadel/backend/cmd/prepare/001"
"github.com/zitadel/zitadel/backend/storage/database"
"github.com/zitadel/zitadel/backend/storage/database/dialect"
@@ -36,62 +36,24 @@ var (
// panic(err)
// }
// },
Run: configure.Update(
"prepare",
"Writes the configuration for the prepare command",
configuration.Fields(),
),
// Run: configure.Update(
// "prepare",
// "Writes the configuration for the prepare command",
// configuration.Fields(),
// ),
Run: bla.Update(viper.GetViper(), &configuration),
PreRun: configure.ReadConfigPreRun(viper.GetViper(), &configuration),
}
)
type Config struct {
config.Config `mapstructure:",squash"`
config.Config `mapstructure:",squash" configure:"-"`
Database dialect.Config
Database dialect.Config // `configure:"-"`
Step001 step001.Step001
// runtime config
Client database.Pool `mapstructure:"-"`
}
// Describe implements configure.StructUpdater.
func (c *Config) Describe() string {
return "Configuration for the prepare command"
}
// Name implements configure.StructUpdater.
func (c *Config) Name() string {
return "prepare"
}
// ShouldUpdate implements configure.StructUpdater.
func (c *Config) ShouldUpdate(version *semver.Version) bool {
if version == nil {
return true
}
for _, field := range c.Fields() {
if field.ShouldUpdate(version) {
return true
}
}
return false
}
// Fields implements configure.UpdateConfig.
func (c Config) Fields() []configure.Updater {
return []configure.Updater{
&configure.Struct{
FieldName: "step001",
Description: "The configuration for the first step of the prepare command",
SubFields: c.Step001.Fields(),
},
&configure.Struct{
FieldName: "database",
Description: "The configuration for the database connection",
SubFields: c.Database.Fields(),
},
}
Client database.Pool `mapstructure:"-" configure:"-"`
}
func (c *Config) Hooks() (decoders []viper.DecoderConfigOption) {

View File

@@ -18,11 +18,11 @@ var (
// This application is a tool to generate the needed files
// to quickly create a Cobra application.`,
Run: func(cmd *cobra.Command, args []string) {
var err error
configuration.Client, err = configuration.Database.Connect(cmd.Context())
if err != nil {
panic(err)
}
// var err error
// configuration.Client, err = configuration.Database.Connect(cmd.Context())
// if err != nil {
// panic(err)
// }
defer configuration.Client.Close(cmd.Context())
if err := (&step001.Step001{Database: configuration.Client}).Migrate(cmd.Context()); err != nil {
panic(err)

View File

@@ -2,5 +2,5 @@ configuredversion: 2025.2.23
database:
postgres: host=local
step001:
databasename: zita
username: adel
databasename: asdf
username: asdf

View File

@@ -3,7 +3,6 @@ package dialect
import (
"context"
"errors"
"fmt"
"reflect"
"github.com/mitchellh/mapstructure"
@@ -11,70 +10,43 @@ import (
"github.com/zitadel/zitadel/backend/cmd/config"
"github.com/zitadel/zitadel/backend/cmd/configure"
"github.com/zitadel/zitadel/backend/cmd/configure/bla"
"github.com/zitadel/zitadel/backend/storage/database"
"github.com/zitadel/zitadel/backend/storage/database/dialect/gosql"
"github.com/zitadel/zitadel/backend/storage/database/dialect/postgres"
)
type Hook struct {
Match func(string) bool
Decode func(name string, config any) (database.Connector, error)
Name string
Field configure.Updater
Match func(string) bool
Decode func(name string, config any) (database.Connector, error)
Name string
Field configure.Updater
Constructor func() any
}
var hooks = make([]Hook, 0)
func init() {
hooks = append(hooks,
Hook{
Match: postgres.NameMatcher,
Decode: postgres.DecodeConfig,
Name: postgres.Name,
Field: postgres.Field,
},
Hook{
Match: gosql.NameMatcher,
Decode: gosql.DecodeConfig,
Name: gosql.Name,
Field: gosql.Field,
},
)
var hooks = []Hook{
{
Match: postgres.NameMatcher,
Decode: postgres.DecodeConfig,
Name: postgres.Name,
Field: postgres.Field,
Constructor: func() any { return new(postgres.Config) },
},
{
Match: gosql.NameMatcher,
Decode: gosql.DecodeConfig,
Name: gosql.Name,
Field: gosql.Field,
Constructor: func() any { return new(gosql.Config) },
},
}
type Config struct {
Dialects map[string]any `mapstructure:",remain"`
Dialects dialects `mapstructure:",remain"`
connector database.Connector
}
// Fields implements [configure.StructUpdater].
func (c *Config) Fields() []configure.Updater {
dialects := configure.OneOf{
Description: "The database dialect Zitadel connects to",
SubFields: []configure.Updater{},
}
for _, hook := range hooks {
if hook.Field == nil {
panic("hook must configure its config fields")
}
dialects.SubFields = append(dialects.SubFields, &configure.Struct{
FieldName: hook.Name,
Description: fmt.Sprintf("Configuration for %s", hook.Name),
SubFields: []configure.Updater{hook.Field},
})
}
return []configure.Updater{
dialects,
}
}
// Name implements [configure.StructUpdater].
func (c *Config) Name() string {
return "database"
}
func (c Config) Connect(ctx context.Context) (database.Pool, error) {
if len(c.Dialects) != 1 {
return nil, errors.New("Exactly one dialect must be configured")
@@ -131,3 +103,21 @@ func decodeHook(from, to reflect.Value) (_ interface{}, err error) {
return config, nil
}
type dialects map[string]any
// ConfigForIndex implements [bla.OneOfField].
func (d dialects) ConfigForIndex(i int) any {
return hooks[i].Constructor()
}
// Possibilities implements [bla.OneOfField].
func (d dialects) Possibilities() []string {
possibilities := make([]string, len(hooks))
for i, hook := range hooks {
possibilities[i] = hook.Name
}
return possibilities
}
var _ bla.OneOfField = (dialects)(nil)

View File

@@ -10,6 +10,7 @@ import (
"github.com/jackc/pgx/v5/pgxpool"
"github.com/zitadel/zitadel/backend/cmd/configure"
"github.com/zitadel/zitadel/backend/cmd/configure/bla"
"github.com/zitadel/zitadel/backend/storage/database"
)
@@ -93,11 +94,29 @@ var (
}
)
type Config struct{ *pgxpool.Config }
type Config struct{ pgxpool.Config }
// ConfigForIndex implements bla.OneOfField.
func (c Config) ConfigForIndex(i int) any {
switch i {
case 0:
return new(string)
case 1:
return &c.Config
}
return nil
}
// Possibilities implements bla.OneOfField.
func (c Config) Possibilities() []string {
return []string{"connection string", "fields"}
}
var _ bla.OneOfField = (*Config)(nil)
// Connect implements [database.Connector].
func (c *Config) Connect(ctx context.Context) (database.Pool, error) {
pool, err := pgxpool.NewWithConfig(ctx, c.Config)
pool, err := pgxpool.NewWithConfig(ctx, &c.Config)
if err != nil {
return nil, err
}
@@ -118,10 +137,10 @@ func DecodeConfig(_ string, config any) (database.Connector, error) {
if err != nil {
return nil, err
}
return &Config{config}, nil
return &Config{Config: *config}, nil
case map[string]any:
return &Config{
Config: &pgxpool.Config{},
Config: pgxpool.Config{},
}, nil
}
return nil, errors.New("invalid configuration")

9
go.mod
View File

@@ -8,6 +8,7 @@ require (
github.com/BurntSushi/toml v1.4.0
github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace v1.24.0
github.com/Masterminds/semver/v3 v3.3.1
github.com/Masterminds/squirrel v1.5.4
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b
github.com/alecthomas/participle/v2 v2.1.1
@@ -47,6 +48,7 @@ require (
github.com/jinzhu/gorm v1.9.16
github.com/k3a/html2text v1.2.1
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/manifoldco/promptui v0.9.0
github.com/minio/minio-go/v7 v7.0.73
github.com/mitchellh/mapstructure v1.5.0
github.com/muesli/gamut v0.3.1
@@ -57,6 +59,8 @@ require (
github.com/pquerna/otp v1.4.0
github.com/rakyll/statik v0.1.7
github.com/redis/go-redis/v9 v9.7.0
github.com/riverqueue/river v0.16.0
github.com/riverqueue/river/riverdriver v0.16.0
github.com/rs/cors v1.11.1
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/sony/gobreaker/v2 v2.0.0
@@ -100,7 +104,6 @@ require (
cloud.google.com/go/auth v0.6.1 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.0 // indirect
github.com/Masterminds/semver/v3 v3.3.1 // indirect
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect
github.com/chzyer/readline v1.5.1 // indirect
@@ -120,15 +123,12 @@ require (
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/riverqueue/river v0.16.0 // indirect
github.com/riverqueue/river/riverdriver v0.16.0 // indirect
github.com/riverqueue/river/rivershared v0.16.0 // indirect
github.com/riverqueue/river/rivertype v0.16.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
@@ -140,7 +140,6 @@ require (
github.com/tidwall/sjson v1.2.5 // indirect
github.com/yuin/gopher-lua v1.1.1 // indirect
github.com/zenazn/goji v1.0.1 // indirect
go.uber.org/goleak v1.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d // indirect

13
go.sum
View File

@@ -113,11 +113,13 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -425,16 +427,14 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa h1:s+4MhCQ6YrzisK6hFJUX53drDT4UsSW3DEhKn0ifuHw=
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.0 h1:FG6VLIdzvAPhnYqP14sQ2xhFLkiUQHCs6ySqO91kF4g=
github.com/jackc/pgx/v5 v5.7.0/go.mod h1:awP1KNnjylvpxHuHP63gzjhnGkI1iw+PMoIwvoleN/8=
github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI=
github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jarcoal/jpath v0.0.0-20140328210829-f76b8b2dbf52 h1:jny9eqYPwkG8IVy7foUoRjQmFLcArCSz+uPsL6KS0HQ=
@@ -659,6 +659,8 @@ github.com/riverqueue/river v0.16.0 h1:YyQrs0kGgjuABwgat02DPUYS0TMyG2ZFlzvf6+fSF
github.com/riverqueue/river v0.16.0/go.mod h1:pEZ8Gc15XyFjVY89nJeL256ub5z18XF7ukYn8ktqQrs=
github.com/riverqueue/river/riverdriver v0.16.0 h1:y4Df4e1Xk3Id0nnu1VxHJn9118OzmRHcmvOxM/i1Q30=
github.com/riverqueue/river/riverdriver v0.16.0/go.mod h1:7Kdf5HQDrLyLUUqPqXobaK+7zbcMctWeAl7yhg4nHes=
github.com/riverqueue/river/riverdriver/riverdatabasesql v0.16.0 h1:T/DcMmZXiJAyLN3CSyAoNcf3U4oAD9Ht/8Vd5SXv5YU=
github.com/riverqueue/river/riverdriver/riverdatabasesql v0.16.0/go.mod h1:a9EUhD2yGsAeM9eWo+QrGGbL8LVWoGj2m8KEzm0xUxE=
github.com/riverqueue/river/riverdriver/riverpgxv5 v0.16.0 h1:6HP296OPN+3ORL9qG1f561pldB5eovkLzfkNIQmaTXI=
github.com/riverqueue/river/riverdriver/riverpgxv5 v0.16.0/go.mod h1:MAeBNoTQ+CD3nRvV9mF6iCBfsGJTxYHZeZSP4MYoeUE=
github.com/riverqueue/river/rivershared v0.16.0 h1:L1lQ3gMwdIsxA6yF0/PwAdsFP0T82yBD1V03q2GuJDU=
@@ -738,7 +740,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
@@ -935,8 +936,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=