Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to mix configuration types #48

Closed
billelev opened this issue Aug 14, 2023 · 4 comments
Closed

Option to mix configuration types #48

billelev opened this issue Aug 14, 2023 · 4 comments
Labels
feature a feature request or enhancement

Comments

@billelev
Copy link

I have a configuration file for database connections, but for different DBs e.g. Postgres and Sqlite. I therefore need different fields.

When I run config::get the function appears to merge values from the configurations I am not asking for. Could functionality be added so that separate and unique configurations can be included in one file?

E.g. For the following configuration file, config::get(config = "sqlite_local") would return only type, path, not type, host, name, port, user, pass, path.

default:
  type: postgres
  host: xxx
  name: yyy
  port: 5432
  user: user1
  pass: pass1

postgres:
  type: postgres
  host: xxx
  name: yyy
  port: 5432
  user: user2
  pass: pass2

sqlite_local:
  type: sqlite
  path: "~/data/db/test.db"

Another style option would be to allow configuration types to nest under a particular config type.

e.g.

config::get(config = "postgres") would return type, host, name, port, user1, pass1
config::get(config = "postgres", key = "key1") would return type, host, name, port, user2, pass2
config::get(config = "sqlite_local") would return type, path

postgres:
  type: postgres
  host: xxx
  name: yyy
  port: 5432
  default:
    user: user1
    pass: pass1
  key1:
    user: user2
    pass: pass2

sqlite_local:
  type: sqlite
  path: "~/data/db/test.db"
@andrie
Copy link
Member

andrie commented Aug 14, 2023

The config::get() function does indeed inherit properties from the default configuration, as you observed, and as documented.

If you want different behaviour, I think you have broadly two options:

  • Design your configuration file structure in a different way, so that the default option really only contains the information you want for all child configurations
  • Create another configuration, where you set values you don't want to inherit to NULL.

Neither of these workarounds are probably going to be satisfactory, but this is what I mean for the second option:

default:
  type: postgres
  host: xxx
  name: yyy
  port: 5432
  user: user1
  pass: pass1


empty:
  type: null
  host: null
  name: null
  port: null
  user: null
  pass: null


postgres:
  type: postgres
  host: xxx
  name: yyy
  port: 5432
  user: user2
  pass: pass2

sqlite_local:
  inherits: empty
  type: sqlite
  path: "~/data/db/test.db"

If you can think of a way to get your desired behaviour that also satisfied backward compatibility, please let me know.

@andrie andrie added the feature a feature request or enhancement label Aug 14, 2023
@billelev
Copy link
Author

Thanks, Andrie. Below is a configuration that does a lot of what I am looking for. There is a minimal default definition, then multiple type_default definitions tied to child configurations.

default:
  type: ""

pg_default:
  type: postgres
  host: host_xxx
  name: name_xxx
  port: port_xxx
pg_ro:
  inherits: pg_default
  user: user_ro
  pass: pass_ro
pg_rw:
  inherits: pg_default
  user: user_rw
  pass: pass_rw

sql_default:
  type: sqlite
  path: path/to/file
sql_local:
  inherits: sql_default
  path: path/to/file2

slack_default:
  type: slack
  account: account_xxx
  emoji: emoji_xxx
slack_u1:
  inherits: slack_default
  user: user1
  pass: pass1
slack_u2:
  inherits: slack_default
  user: user2
  pass: pass2

@andrie
Copy link
Member

andrie commented Aug 15, 2023

That's sensible.

I have one suggestion, though, and that is to make use of environment variables to store your usernames and passwords.

Right now it seems you're trying to encode multiple usernames and passwords in a single plain text file.

A better pattern would be to use something like this:

pg_default:
  type: postgres
  host: host_xxx
  name: !expr Sys.getenv("postgres_user")
  port: !expr Sys.getenv("postgres_password")

See the vignette at https://rstudio.github.io/config/articles/inheritance.html#using-r-code-inside-the-yaml-file

@billelev
Copy link
Author

Yes, absolutely. Thanks for the suggestion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature a feature request or enhancement
Projects
None yet
Development

No branches or pull requests

2 participants