From f8aac8d4d77b597fbf07afdbf46d79306970908e Mon Sep 17 00:00:00 2001 From: Vikram Rangnekar Date: Mon, 28 Oct 2019 01:48:04 -0400 Subject: [PATCH] Allow config files to inherit from other config files --- config/prod.yml | 103 +++-------------------------------------------- docs/guide.md | 4 ++ serv/cmd.go | 16 +++++++- serv/cmd_conf.go | 9 ++--- serv/config.go | 6 ++- serv/serv.go | 10 ++++- tmpl/prod.yml | 101 +++------------------------------------------- 7 files changed, 46 insertions(+), 203 deletions(-) diff --git a/config/prod.yml b/config/prod.yml index 454092e..86b5563 100644 --- a/config/prod.yml +++ b/config/prod.yml @@ -1,3 +1,7 @@ +# Inherit config from this other config file +# so I only need to overwrite some values +inherit: dev + app_name: "Super Graph Production" host_port: 0.0.0.0:8080 web_ui: false @@ -76,104 +80,9 @@ database: type: postgres host: db port: 5432 - dbname: {{app_name_slug}}_development + dbname: app_production user: postgres password: '' #pool_size: 10 #max_retries: 0 - #log_level: "debug" - - # Define variables here that you want to use in filters - # sub-queries must be wrapped in () - variables: - account_id: "(select account_id from users where id = $user_id)" - - # Define defaults to for the field key and values below - defaults: - filters: ["{ user_id: { eq: $user_id } }"] - - # Field and table names that you wish to block - blocklist: - - ar_internal_metadata - - schema_migrations - - secret - - password - - encrypted - - token - -tables: - - name: customers - # remotes: - # - name: payments - # id: stripe_id - # url: http://rails_app:3000/stripe/$id - # path: data - # # pass_headers: - # # - cookie - # # - host - # set_headers: - # - name: Authorization - # value: Bearer - - - # You can create new fields that have a - # real db table backing them - name: me - table: users - -roles_query: "SELECT * FROM users as usr WHERE id = $user_id" - -roles: - - name: anon - tables: - - name: products - limit: 10 - - query: - columns: ["id", "name", "description" ] - aggregation: false - - insert: - block: false - - update: - block: false - - delete: - block: false - - - name: user - tables: - - name: users - query: - filters: ["{ id: { _eq: $user_id } }"] - - - name: products - query: - limit: 50 - filters: ["{ user_id: { eq: $user_id } }"] - columns: ["id", "name", "description" ] - disable_functions: false - - insert: - filters: ["{ user_id: { eq: $user_id } }"] - columns: ["id", "name", "description" ] - set: - - created_at: "now" - - update: - filters: ["{ user_id: { eq: $user_id } }"] - columns: - - id - - name - set: - - updated_at: "now" - - delete: - block: true - - - name: admin - match: id = 1 - tables: - - name: users - # query: - # filters: ["{ account_id: { _eq: $account_id } }"] + #log_level: "debug" \ No newline at end of file diff --git a/docs/guide.md b/docs/guide.md index f3f8f96..29b9b2f 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -1040,6 +1040,10 @@ Configuration files can either be in YAML or JSON their names are derived from t We're tried to ensure that the config file is self documenting and easy to work with. ```yaml +# Inherit config from this other config file +# so I only need to overwrite some values +inherit: base + app_name: "Super Graph Development" host_port: 0.0.0.0:8080 web_ui: true diff --git a/serv/cmd.go b/serv/cmd.go index 6fbc09f..c271280 100644 --- a/serv/cmd.go +++ b/serv/cmd.go @@ -150,13 +150,25 @@ func initLog() *zerolog.Logger { } func initConf() (*config, error) { - vi := newConfig() + vi := newConfig(getConfigName()) if err := vi.ReadInConfig(); err != nil { return nil, err } - c := &config{} + inherit := vi.GetString("inherit") + if len(inherit) != 0 { + vi = newConfig(inherit) + + if err := vi.ReadInConfig(); err != nil { + return nil, err + } + + vi.SetConfigName(getConfigName()) + vi.MergeInConfig() + } + + c := &config{Viper: vi} if err := vi.Unmarshal(c); err != nil { return nil, fmt.Errorf("unable to decode config, %v", err) diff --git a/serv/cmd_conf.go b/serv/cmd_conf.go index 6c182ac..13809e2 100644 --- a/serv/cmd_conf.go +++ b/serv/cmd_conf.go @@ -15,13 +15,12 @@ func cmdConfDump(cmd *cobra.Command, args []string) { fname := fmt.Sprintf("%s.%s", getConfigName(), args[0]) - vi := newConfig() - - if err := vi.ReadInConfig(); err != nil { - logger.Fatal().Err(err).Send() + conf, err := initConf() + if err != nil { + logger.Fatal().Err(err).Msg("failed to read config") } - if err := vi.WriteConfigAs(fname); err != nil { + if err := conf.Viper.WriteConfigAs(fname); err != nil { logger.Fatal().Err(err).Send() } diff --git a/serv/config.go b/serv/config.go index 635f536..d847304 100644 --- a/serv/config.go +++ b/serv/config.go @@ -9,6 +9,8 @@ import ( ) type config struct { + *viper.Viper + AppName string `mapstructure:"app_name"` Env string HostPort string `mapstructure:"host_port"` @@ -134,16 +136,16 @@ type configRole struct { } } -func newConfig() *viper.Viper { +func newConfig(name string) *viper.Viper { vi := viper.New() vi.SetEnvPrefix("SG") vi.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) vi.AutomaticEnv() + vi.SetConfigName(name) vi.AddConfigPath(confPath) vi.AddConfigPath("./config") - vi.SetConfigName(getConfigName()) vi.SetDefault("host_port", "0.0.0.0:8080") vi.SetDefault("web_ui", false) diff --git a/serv/serv.go b/serv/serv.go index c14bea6..e61795c 100644 --- a/serv/serv.go +++ b/serv/serv.go @@ -148,7 +148,15 @@ func startHTTP() { db.Close() }) - fmt.Printf("%s listening on %s (%s)\n", serverName, hostPort, conf.Env) + var ident string + + if len(conf.AppName) == 0 { + ident = conf.Env + } else { + ident = conf.AppName + } + + fmt.Printf("%s listening on %s (%s)\n", serverName, hostPort, ident) if err := srv.ListenAndServe(); err != http.ErrServerClosed { logger.Error().Err(err).Msg("server closed") diff --git a/tmpl/prod.yml b/tmpl/prod.yml index 068441b..8365fb6 100644 --- a/tmpl/prod.yml +++ b/tmpl/prod.yml @@ -1,3 +1,7 @@ +# Inherit config from this other config file +# so I only need to overwrite some values +inherit: dev + app_name: "Super Graph Production" host_port: 0.0.0.0:8080 web_ui: false @@ -81,99 +85,4 @@ database: password: '' #pool_size: 10 #max_retries: 0 - #log_level: "debug" - - # Define variables here that you want to use in filters - # sub-queries must be wrapped in () - variables: - account_id: "(select account_id from users where id = $user_id)" - - # Define defaults to for the field key and values below - defaults: - filters: ["{ user_id: { eq: $user_id } }"] - - # Field and table names that you wish to block - blocklist: - - ar_internal_metadata - - schema_migrations - - secret - - password - - encrypted - - token - -tables: - - name: customers - # remotes: - # - name: payments - # id: stripe_id - # url: http://rails_app:3000/stripe/$id - # path: data - # # pass_headers: - # # - cookie - # # - host - # set_headers: - # - name: Authorization - # value: Bearer - - - # You can create new fields that have a - # real db table backing them - name: me - table: users - -roles_query: "SELECT * FROM users as usr WHERE id = $user_id" - -roles: - - name: anon - tables: - - name: products - limit: 10 - - query: - columns: ["id", "name", "description" ] - aggregation: false - - insert: - block: false - - update: - block: false - - delete: - block: false - - - name: user - tables: - - name: users - query: - filters: ["{ id: { _eq: $user_id } }"] - - - name: products - query: - limit: 50 - filters: ["{ user_id: { eq: $user_id } }"] - columns: ["id", "name", "description" ] - disable_functions: false - - insert: - filters: ["{ user_id: { eq: $user_id } }"] - columns: ["id", "name", "description" ] - set: - - created_at: "now" - - update: - filters: ["{ user_id: { eq: $user_id } }"] - columns: - - id - - name - set: - - updated_at: "now" - - delete: - deny: true - - - name: admin - match: id = 1 - tables: - - name: users - # query: - # filters: ["{ account_id: { _eq: $account_id } }"] + #log_level: "debug" \ No newline at end of file