alles en scheiss

This commit is contained in:
adlerhurst
2025-03-07 07:26:32 +01:00
parent 67b22ef9c4
commit 9bc75d43d9
5 changed files with 173 additions and 7 deletions

View File

@@ -0,0 +1,70 @@
package bla4
import (
"fmt"
"log/slog"
"reflect"
"github.com/manifoldco/promptui"
)
type Iterator interface {
// NextField returns the name of the next field to configure.
// If it returns an empty string, the configuration is complete.
NextField() string
// FinishAllowed returns true if the configuration is complete and the user can skip the remaining fields.
FinishAllowed() bool
}
func fieldFunctionByIterator(l *slog.Logger, f *field) Configure {
if !f.value.Type().Implements(reflect.TypeFor[Iterator]()) {
return nil
}
return func() (value any, err error) {
iter := f.value.Interface().(Iterator)
sub := f.sub()
for {
fieldName := iter.NextField()
if fieldName == "" {
break
}
if iter.FinishAllowed() {
prompt := promptui.Prompt{
Label: fmt.Sprintf("Finish configuration of %s", f.info.Name),
IsConfirm: true,
}
_, err := prompt.Run()
if err == nil {
break
}
}
info, ok := f.value.Type().FieldByName(fieldName)
if !ok {
return nil, fmt.Errorf("field %s not found", fieldName)
}
tag, err := newTag(info, f.value.FieldByName(fieldName))
if err != nil {
return nil, err
}
if tag.skip {
continue
}
res, err := fieldFunction(
l.With(slog.String("field", fieldName)),
&field{
info: info,
viper: sub, //TODO: sub of sub
tag: tag,
},
)()
if err != nil {
return nil, err
}
reflect.Indirect(f.value).FieldByName(fieldName).Set(reflect.ValueOf(res))
}
f.viper.Set(f.tag.fieldName, sub.AllSettings())
return value, err
}
}

View File

@@ -88,7 +88,8 @@ func structToConfigureMap(l *slog.Logger, v *viper.Viper, object reflect.Value)
func fieldFunction(l *slog.Logger, f *field) (configure Configure) {
for _, mapper := range []func(*slog.Logger, *field) Configure{
fieldFunctionByImplementation,
fieldFunctionByConfigurer,
fieldFunctionByIterator,
fieldFunctionByReflection,
} {
if configure = mapper(l, f); configure != nil {
@@ -98,9 +99,8 @@ func fieldFunction(l *slog.Logger, f *field) (configure Configure) {
panic(fmt.Sprintf("unsupported field type: %s", f.info.Type.String()))
}
func fieldFunctionByImplementation(l *slog.Logger, f *field) Configure {
func fieldFunctionByConfigurer(l *slog.Logger, f *field) Configure {
if f.value.Type().Implements(reflect.TypeFor[Configurer]()) {
l.Debug("field is a custom implementation")
return func() (value any, err error) {
f.printStructInfo()
res, err := f.value.Interface().(Configurer).Configure()

View File

@@ -0,0 +1,74 @@
package bla5
import (
"log/slog"
"os"
"reflect"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var Logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
AddSource: true,
Level: slog.LevelDebug,
}))
type Configure func() (value any, err error)
type Configurer interface {
// Configure is called to configure the value.
// It must return the same type as itself. Otherwise [Update] will panic because it is not able to set the value.
Configure() (value any, err error)
}
func Update(v *viper.Viper, config any) func(cmd *cobra.Command, args []string) {
return func(cmd *cobra.Command, args []string) {
value := reflect.ValueOf(config)
structConfigures := structToConfigureMap(Logger, v, value)
for key, configure := range structConfigures {
result, err := configure()
if err != nil {
Logger.Error("error configuring field", slog.String("field", key), slog.Any("cause", err))
return
}
value.Elem().FieldByName(key).Set(reflect.ValueOf(result))
}
err := v.WriteConfig()
if err != nil {
Logger.Error("error writing config", slog.Any("cause", err))
os.Exit(1)
}
}
}
func objectToFlow(l *slog.Logger, value reflect.Value) {
if value.Kind() == reflect.Pointer {
if value.IsNil() {
value = reflect.New(value.Type().Elem())
}
value = value.Elem()
}
typeOfValue := value.Type()
for i := 0; i < value.NumField(); i++ {
fieldValue := value.Field(i)
fieldType := typeOfValue.Field(i)
l.Info("Processing field", slog.String("field", fieldType.Name))
}
}
type field struct {
set func(value reflect.Value) error
}
type structField struct {
name string
fields []field
}
type primitiveField struct {
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/manifoldco/promptui"
"github.com/mitchellh/mapstructure"
"github.com/zitadel/zitadel/backend/cmd/configure/bla4"
"github.com/zitadel/zitadel/backend/storage/database"
)
@@ -24,19 +25,38 @@ type Config struct {
// Host string
// Port int32
// Database string
// EventPushConnRatio float64
// MaxOpenConns uint32
// MaxIdleConns uint32
// MaxConnLifetime time.Duration
// MaxConnIdleTime time.Duration
// User User
// Admin AdminUser
// // Additional options to be appended as options=<Options>
// // The value will be taken as is. Multiple options are space separated.
// Options string
configuredFields []string
}
// Configure implements bla3.Custom.
// FinishAllowed implements [bla4.Iterator].
func (c *Config) FinishAllowed() bool {
// Option can be skipped
return len(c.configuredFields) < 2
}
// NextField implements [bla4.Iterator].
func (c *Config) NextField() string {
if c.configuredFields == nil {
c.configuredFields = []string{"Host", "Port", "Database", "MaxOpenConns", "MaxIdleConns", "MaxConnLifetime", "MaxConnIdleTime", "User", "Options"}
}
if len(c.configuredFields) == 0 {
return ""
}
field := c.configuredFields[0]
c.configuredFields = c.configuredFields[1:]
return field
}
// Configure implements [bla4.Configurer].
func (c *Config) Configure() (value any, err error) {
typeSelect := promptui.Select{
Label: "Configure the database connection",
@@ -67,6 +87,8 @@ func (c *Config) Configure() (value any, err error) {
return prompt.Run()
}
var _ bla4.Iterator = (*Config)(nil)
// Connect implements [database.Connector].
func (c *Config) Connect(ctx context.Context) (database.Pool, error) {
pool, err := pgxpool.NewWithConfig(ctx, c.config)