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

What is the purpose of backticks as a (yml) config value? #7987

Closed
NightJar opened this issue Apr 5, 2018 · 8 comments
Closed

What is the purpose of backticks as a (yml) config value? #7987

NightJar opened this issue Apr 5, 2018 · 8 comments

Comments

@NightJar
Copy link
Contributor

NightJar commented Apr 5, 2018

Affected Version

silverstripe/framework 4.1.x-dev 99426cd

Description

I was under the impression that there is a specific syntax to parse environment variables into config values. e.g.

SomeVendor\SomeProject\SomeClass:
  some_setting: '`SOME_ENV_VAR`'

Where the environment variable value would then become the value of some_setting within that class's config context.

However in testing this recently I was alarmed to find that this string literal was instead being requested as a URI endpoint for an external service

keeping with the example above - var_dump($this->config()->some_setting);

string(14) "`SOME_ENV_VAR`"

Simply removing the config setting this value to the environment config resolved the issue (the code falls back from local (object instance) settings -> config settings -> environment setting).

I was then confused as to whether this functionality applied to environment settings, or to global constants. I added to mysite/_config.php a line define('SOME_ENV_VAR', 'thisisa.test');

This also failed. The resulting value attempted to be used by the code was the same as when testing with an environment variable.

Steps to Reproduce

In this particular case I am using an development environment with a .env file, however I hope that should be inconsequential.
I am using silverstripe/documentconverter@c990914
with cwp/cwp-core@a6aef24 providing the configuration.

@kinglozzer
Copy link
Member

AFAIK this is for constants, not env vars, but it does look like it might be broken in my testing too...

@kinglozzer
Copy link
Member

kinglozzer commented Apr 6, 2018

Oh, right - it only works for Injector definitions (and it does work for env vars):

// Evaluate constants surrounded by back ticks
if (preg_match('/^`(?<name>[^`]+)`$/', $value, $matches)) {
$envValue = Environment::getEnv($matches['name']);
if ($envValue !== false) {
$value = $envValue;
} elseif (defined($matches['name'])) {
$value = constant($matches['name']);
} else {
$value = null;
}
}

That’s a shame, it’d be nice to be able to use constants/env vars anywhere in config like this

@NightJar
Copy link
Contributor Author

NightJar commented Apr 8, 2018

Yeah, I spotted the test for Injector, but also thought it was more generic than that.
I guess in a perfect world we'd Injector all the things... so 🤷‍♂️

I'll leave it for the core team to make any further decisions as I have no opinion either way, but thanks for the clarification :)

@tractorcow
Copy link
Contributor

tractorcow commented Apr 9, 2018

It's kind of like another injector-shorthand for "some evaluated value".

Other examples:

  • "%$SomeService" means "inject the service with id 'SomeService'".
  • "`SOME_ENV`" means "inject value of this var from Environment::getEnv()"

@tractorcow
Copy link
Contributor

@NightJar you should use Injector::inst()->convertServiceProperty($alternate) if you want to evaluate these in your code.

@robbieaverill
Copy link
Contributor

For reference, I've logged an enhancement issue to add support for backticked env vars in all YAML config, rather than just in Injector definitions: silverstripe/silverstripe-config#37

@tractorcow
Copy link
Contributor

That would be cool, but careful since environment variables can change as a result of code execution, but config vars cannot (are cached at boot time).

@patricknelson
Copy link
Contributor

patricknelson commented Aug 31, 2021

FWIW, if you were determined to incorporate this yourself, you could probably still do it with some success, depending on your use case. I don't know of an easy way to allow you to decorate your YAMLs with environment variables anywhere you please, but if you're like me, you can probably settle for having them in just one or two places and then do the interpolation yourself and just update the config values in-situ using something like Class::config()->Variable = ... or Config::inst()->update('Class', 'Variable ', ...).

I realized that I needed this bad enough to justify the relatively simple implementation overhead (at least of defining these environment variables in just one place in my config). For anyone interested or googling and landing here, my implementation/hack is outlined at silverstripe/silverstripe-config#37 (comment). But, very basically:

---
Name: mysite-config-name
After:
  - 'framework/*'
  - 'cms/*'
---
Globals:
  # These values are accessible via Globals::config()->Values['NAME'] 
  Values:
    SomeValue: '`ENV_VAR1`'
    ComplexValue: 'The value `ENV_VAR2` can be interpolated mid-string as well.'

So you just write some code to iterate over those values and interpolate the backtick values from Environment::getEnv(). There's a lot more to this, especially in my case. What I needed was to dynamically define SS_* constants (as well as non-secret environment variables) to help me migrate away from SS v3. 😄

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

No branches or pull requests

5 participants