Environment Variables in Hybris local.properties - sap-commerce-cloud

I'm wondering if, in a Hybris properties file, there is a way to reference environment variables.
For example, in local.properties:
my.property = ${MY_ENVIRONMENT_VARIABLE}
My searching has concluded that this is possible in Spring, but doesn't appear to work in Hybris.
Any thoughts would be appreciated.

It's possible to access to environment variables within hybris. A partner of my company found out this deep down in hybris documentation:
Platform allows you to specify properties also as environment variables
# security: make the platform *abort startup* if no one overrides the settings below
db.url=<CHANGE_ME>
db.username=<CHANGE_ME>
db.password=<CHANGE_ME>
# security: end
The special property value has been introduced exactly for such use cases where administrators want to ensure that: a) files do not contain sensible settings, and b) the system doesn't start up if those settings haven't been overridden.
On the server, those settings are to be exposed as environment variables just before starting Platform:
foo$ export y_db_url=jdbc:mysql://my.secret-db-host.com/AlfavaMetraxis?useConfigs=maxPerformance&characterEncoding=utf8
foo$ export y_db_username=Amy
foo$ export y_db_password=Rory
foo$ ./hybrisserver.sh start
...
As you can see, settings need to be prefixed and escaped in order to work as environment variable.
https://help.sap.com/viewer/a74589c3a81a4a95bf51d87258c0ab15/1905/en-US/8b8e13c9866910149d40b151a9196543.html?q=CHANGE_ME
Hope this is useful for you.

I found this related to your question on Hybris Experts. Hope it helps.
It is not possible to access shell environment variables inside local.properties file. As a workaround you can do echo "my.property = $MY_ENVIRONMENT_VARIABLE" >> local.properties before starting platform.

No it's not possible.
Actually hybris use org.apache.commons.configuration package. In the documentation you'll find that it's possible to use environment variable.
user.file = ${sys:user.home}/settings.xml
action.key = ${const:java.awt.event.KeyEvent.VK_CANCEL}
java.home = ${env:JAVA_HOME}
Unfortunately hybris has done something I can't explain, they have overidded the default implementation and removed all interpolation features.
If we analyze the issue further, the configuration class used is called HybrisConfiguration. This class extends AbstractConfiguration from Apache Commons Configuration. The getProperty method use an other interface called ConfigIntf. The implementation is found in the class AbstractConfig. There every getString getInteger, etc... methods are overrided.
For example, for String, the method does not call the interpolate method but instead you'll find a really simple...
StringUtils.isEmpty(value) ? def : value;
So if you want to use all features of Apache API, then try to replace hybris implementation... However I think that it won't be so easy to do that without modifying the platform since I don't see any beans there that could be injected.

Related

Puppet 4: how to add calling class variables to scope of a defined type

In Puppet 3 and prior, templates in defines inherited scope from their calling class the same way native defined types do, so if I had a file resource with a template source created by a define, that template could make use of variables set in the calling class no matter which class called the define.
In Puppet 4 (also tested with Puppet 3.8 future parser), that appears to no longer be the case, and it is causing breakage that is hard to even measure in my environment, which has relied on this behavior for tens of thousands of lines of code. Is there any way at all to get this back? After looking into it, even converting the defines into native types doesn't solve the problem, as they rely on the ability to gather server-side information about what templates are available in different modules via custom functions, and everything in a native resource type appears to happen on the client.
Is this fixable, or do I attempt to wait for Puppet 5?
Edit: Don't get too caught up in the word 'scope' here -- I need any way to pass all class variables to a define and unpack them there so that they are available to templates, or a way to have a native type see what files are inside specified modules on the puppetmaster. I will accept any bizarre, obscure message passing option as long as it has this result, because the classes do not know where the templates are -- only the define does, because it's making use of the helper functions that scan the filesystem on the server.
Edit 2: To prove this works as expected in Puppet 3.8.5, use the following:
modules/so1/manifests/autotemplate.pp:
# Minimal define example for debugging
define so1::autotemplate (
$ensure = 'present',
$module = $caller_module_name,
) {
$realtemplate = "${module}${title}"
file { $title :
ensure => $ensure,
owner => 'root', group => 'root', mode => '0600',
content => template($realtemplate),
}
}
in modules/so2/manifests/example.pp:
# Example class calling so1::autotemplate
class so2::example (
$value = 'is the expected value'
) {
so1::autotemplate { '/tmp/qwerasdf': }
}
in modules/so2/templates/tmp/qwerasdf:
Expected value: <%= #value %>
In Puppet 3.8.5 with future parser off, this results in /tmp/qwerasdf being generated on the system with the contents:
Expected value: is the expected value
In Puppet 3.8.5. with parser = future in environment.conf (and also Puppet 4.x, though I tested for this example specifically on a 3.8.5 future parser environment), this results in the file being create with the contents:
Expected value:
Edit 3: two-word touch-up for precision
In Puppet 3 and prior, defines inherited scope from their calling class the same way native defined types do, so if I had a file resource with a template source created by a define, that template could make use of variables set in the calling class no matter which class called the define.
What you're describing is Puppet's old dynamic scoping. The change in scoping rules was one of the major changes in Puppet 3.0; it is not new in Puppet 4. There was, however, a bug in Puppet 3 that templates still used dynamic scope. That was fixed in Puppet 3.5, but only prospectively -- that is, when the future parser is enabled. Defined types themselves went through the scoping change in Puppet 3.0.0, along with everything else. The scope changes were a big deal (and Puppet devoted considerable effort to alerting users to them) when they first went into place, but nowadays there's no big deal here.
it is causing breakage that is hard to even measure in my environment, which has relied on this behavior for tens of thousands of lines of code.
I'm sorry you're having that experience.
Is there any way at all to get this back?
No. Puppet scoping rules do not work the way you want them to do. That they did work that way in templates (but not most other places) in Puppet 3 was and still is contrary to Puppet's documentation, and never intentional.
Is this fixable, or do I attempt to wait for Puppet 5?
There is no way to get dynamic variable scoping in templates or elsewhere in Puppet 4, and I have no reason to think that there will be one in Puppet 5.
If you need a template to expand host variables from the scope of a particular class, then you can get that by evaluating the template in the scope of that class. Alternatively, an ERB template can obtain variables from (specific) other scopes by means of the scope object. On the other hand, if you want to expand the template in the scope of a defined type, then you could consider passing the needed variables as parameters of that type.
There may be other ways to address your problem, but I'd need more details to make any other suggestions. (And that would constitute a separate question if you choose to ask it here on SO.)

Including user home dir in Jrebel.xml

Using Jrebel with NetBeans 8.0.2, projects shared by multiple users. The root of the projects is variable "dev.env.home" defined as an ant variable in Netbeans settings. Is it possible to pass this variable to rebel.xml file? I have tried this:
<dir name="${dev.env.home}\java\projects\Generator\target\classes"/>
But it does not seem to work
try providing the value for that placeholder as JVM parameter.
-Ddev.env.home=C:\myhomedir
That should work.

groovy typesafe configurations with ConfigObject and ConfigSlurper

I am using a groovy configuration file and parse it with ConfigSlurper resulting in a ConfigObject that I use for accessing my configuration. The disadvantage is that I have no help from eclipse regarding if properties exist - every configuration property is underlined as groovy/eclipse do not know which properties the (dynamic) ConfigObject has. Refactoring is also not possible - for example if I rename a property in the config, groovy/eclipse does not recognise its usages in the sourcecode and does not rename it there.
Are there ways to fix or workaround these two issues?
Groovy-eclipse DSL Descriptors come to mind:
Also, #TypeChecked extensions may be used if you want type safety in your DSL.

How can I append to a construction variable in a Program() call?

I have a custom environment set up for my tests:
test_env = env.Clone()
test_env.Append(LIBS=['boost_unit_test_framework'])
But for one of my tests, I want to link against an additional library:
test_env.Program('foo_tests',
source='foo/tests.cpp',
LIBS=['extralib'],
LIBPATH=['.'])
Sadly this overrides the LIBS from the environment, when I'd like it to just add to it. Is there a better (i.e. more canonical) way to do this than LIBS=test_env['LIBS'] + ['extralib']?
Specifying a new value for an environment variable in a Builder call (like Program) is always interpreted as an "override". So there is no way around compiling the full replacement value, as you did in your example above.
The other option would be to Clone the environment "test_env" again, and then use Append to add the "extralib" to LIBS...
It's possible to do it like this:
test_env.Program('foo_tests',
source='foo/tests.cpp',
LIBS=['$LIBS', 'extralib'],
LIBPATH=['$LIBPATH', '.'])
SCons is clever enough to properly expand the variable into a list there.

How to write a path that include environment variables?

I'm writing a Qt app that runs in Linux. I need to write a file to:
"$XDG_CONFIG_DIRS/whatever"/ "$HOME/whatever"
How do I resolve the environment variables ## Heading ##in my code?
Using nothing but plain library functions, you use getenv() to look up the value of environment variables:
const char *dirs = getenv("XDK_CONFIG_DIRS");
This will return NULL if the variable was not set in the environment, so make sure your code handles this case.
You'll have to do the "interpolation" of the variable values into the rest of the text yourself, in that case.
Not sure if Qt provides a wrapper or something more high-level that can do the interpolation for you, I haven't worked with Qt.
getenv, as already mentioned, if you really only target Linux. If you want it portable to Non-Unix platforms, you should use qgetenv() or QProcessEnvironment::systemEnvironment().value(QLatin1String("XDG_CONFIG_DIRS")). In general, it's good practice to use the portable Qt way.

Resources