How override grails configuration from command line - grails

I am trying to override dataSource.url value running grails from the command line, example
grails <set property> dbm-status
My first try was using -D command line parameter as
grails -DdataSource.url=jdbc:sqlserver://xx.xx.xx.xx;databaseName=db_name
I have tried to add an additional config file to grails.config.locations that get values from System.getProperty but does not seems to work.
Exist a built in way to override config values from the command line, otherwise how I can inject parameter from the command line to the grails configuration ?
EDIT: I don't want to use another environment/datasource to avoid datasource configuration duplication and the need to configure things for this new environment.

By including the following if in DataSource.groovy I'm able to override url,password and username property if url is provided. (Valid for Grails 2.x)
....
environments {
development {
dataSource {
url = "jdbc:postgresql://localhost/db"
username = "user"
password = "pass"
if (System.properties['dataSourceUrl']) {
println 'Taking dataSource url, password, username from command line overrides'
url = System.properties['dataSourceUrl']
password = System.properties['dataSourcePassword']
username = System.properties['dataSourceUsername']
}
}
}
...
Now when I run the command, the overrides get applied:
grails dev -DdataSourceUrl=newUrl -DdataSourcePassword=newPass -DdataSourceUsername=newUser run-app
Unfortunately if you want to be able to override on every environment you have to duplicate this code for every env block. If you pull it up to root it won't work since config merging kicks in and the last run will actually apply what's in the env {} block and not what's in the System properties.
Looking at it again something like that looks even better:
...
url = System.properties['dataSourceUrl'] ?: 'jdbc:postgresql://localhost/db'
//and for every property...
...

DATASOURCE_URL=jdbc:sqlserver://xx.xx.xx.xx;databaseName=db_name grials run-app
For any variable you want to set, you can set it in the environment. Change to upper case and replace dots with underscores. This is a feature of spring boot.

Related

Using Environment Variables to Configure a Sails.js app for CircleCI

I've accessed environmental varibales with node apps before with process.env.VARIABLE_NAME, but I was curious to try Sails' alternative solution. It seems like I should be able to put in a dummy value (or nothing) in the /config/foo.js file, then overwrite it with a carefully named environmental variable. I modeled my setup on this example.
Unfortunately, CircleCI seems to be ignoring the environmental variable and using the dummy value instead. Have I set something up incorrectly? FYI, I'm using /config/local.js (no environment variables) to overwrite the password on my local machine and everything works fine...
/config/datastores.js:
module.exports.datastores = {
postgresqlTestDb: {
adapter: 'sails-postgresql',
host: 'test-postgres.myhost.com',
user: 'postgres',
password: 'PASSWORD',
database: 'my-db',
},
};
Environment Variables in CircleCI:
sails_datastores__postgresqlTestDb__password = theRealPassword
Error in CircleCI:
1) "before all" hook:
Error: done() invoked with non-Error: {"error":{"name":"error","length":104,"severity":"FATAL","code":"28P01","file":"auth.c","line":"307","routine":"auth_failed"},"meta":{"adapter":"sails-postgresql","host":"test-postgres.myhost.com","user":"postgres","password":"PASSWORD","database":"","identity":"postgresqlTestDb","url":"postgres://postgres:PASSWORD#test-postgres.myhost.com:5432/my-db"}}
at sails.lift (test/lifecycle.test.js:46:23)
...
The Important part of the error:
"url":"postgres://postgres:PASSWORD#test-postgres.myhost.com:5432/my-db"
I want to connect to postgres://postgres:theRealPassword#test-postgres.myhost.com:5432/my-db instead...
I just set an ENV variable for the entire connection URL. looks something like this:
sails_datastores__default__url: postgresql://user:passwrod#host:port/databse
I think in your example you are missing the "default" part

“Inject environment variables” Jenkins 2.0

I recently upgraded to Jenkins 2.0.
I’m trying to add a build step to a jenkins job of "Inject environment variables" along the lines of this SO post, but it’s not showing up as an option.
Is this not feature in Jenkins 2.0 (or has it always been a separate plugin)? Do I have to install another plugin, such as Envinject?
If you are using Jenkins 2.0
you can load the property file (which consists of all required Environment variables along with their corresponding values) and read all the environment variables listed there automatically and inject it into the Jenkins provided env entity.
Here is a method which performs the above stated action.
def loadProperties(path) {
properties = new Properties()
File propertiesFile = new File(path)
properties.load(propertiesFile.newDataInputStream())
Set<Object> keys = properties.keySet();
for(Object k:keys){
String key = (String)k;
String value =(String) properties.getProperty(key)
env."${key}" = "${value}"
}
}
To call this method we need to pass the path of property file as a string variable
For example, in our Jenkins file using groovy script we can call like
path = "${workspace}/pic_env_vars.properties"
loadProperties(path)
Please ask me if you have any doubt

Why doesn't the default attribute for number fields work for Jenkins jelly configurations?

I'm working on a Jenkins plugin where we make a call out to a remote service using Spring's RestTemplate. To configure the timeout values, I'm setting up some fields in the global configuration using the global.jelly file for Jenkins plugins using a number field as shown here:
<f:entry title="Read Timeout" field="readTimeout" description="Read timeout in ms.">
<f:number default="3000"/>
</f:entry>
Now, this works to save the values and retrieve the values no problem, so it looks like everything is setup correctly for my BuildStepDescriptor. However, when I first install the update to a Jenkins instance, instead of getting 3000 in the field by default as I would expect, instead I am getting 0. This is the same for all the fields that I'm using.
Given that the Jelly tag reference library says this attribute should be the default value, why do I keep seeing 0 when I first install the plugin?
Is there some more Java code that needs to be added to my plugin to tie the default in Jelly back to the global configuration?
I would think that when Jenkins starts, it goes to get the plugin configuration XML and fails to find a value and sets it to a default of 0.
I have got round this in the past by setting a default in the descriptor (in groovy) then this value will be saved into the global config the first time in and also be available if the user never visits the config page.
#Extension
static class DescriptorImpl extends AxisDescriptor {
final String displayName = 'Selenium Capability Axis'
String server = 'http://localhost:4444'
Boolean sauceLabs = false
String sauceLabsName
Secret sauceLabsPwd
String sauceLabsAPIURL =
'http://saucelabs.com/rest/v1/info/platforms/webdriver'
String sauceLabsURL = 'http://ondemand.saucelabs.com:80'
from here

How to tell Grails application which environment it is in?

I would like to load Environment specific configurations in my grails application so that depending on which JVM the grails application is running on, I can point to that environment specific urls. In my case, I have 4 different environments to work with (instead of the default 3 that grails app assumes) when my app goes from dev to prod.
My JVMs all have a System property defined that, when I do "System.getProperty()", tell me which environment that application is running on.
My question is, what is the best place to check and load the environment-specific configurations during run-time? Inside BootStrap.groovy? I do not have the option to build my war file using command line or grails {env_name} war.
Thanks.
Set the variable grailsEnv as a environment Java variable for Tomcat below is an example:
set CATALINA_OPTS=%CATALINA_OPTS% -Xms256m -Xmx1024m -Dgrails.env=development
On a grails command line you add the environment variable:
grails run-app -Dgrails.env=stage
You can use check the environment variable like this:
if (grails.util.Environment.current.name == "development") {
UsageCodeDefinition ucd = new UsageCodeDefinition()
ucd.setDescription("UFARSFileUpload Upload Development")
ucd.setFiscalYear("12-13")
ucd.setInstructions("Welcome to UFARSFileUpload Development were Open")
ucd.save(failOnError: true)
}
You can use the Enumerated values instead of the name variable but if you use custom environmental values then they are mapped to the enumeration custom and using the name works to distinguish between the custom values.
if (grails.util.Environment.current == grails.util.Environment.DEVELOPMENT) {
Without setting the JVM startup parameter:
-Dgrails.env=whatever
Your grails app will use the value set in
<yourapp>/WEB-INF/classes/application.properties
There will be a value set like this:
grails.env=development
This default environment value is determined by what options are used when building the war. You can build the war with
-Dgrails.env=development war
Then the application.properties will have grails.env=development, if you leave that off, it defaults to grails.env=production
As far as your question, you are not specific about what is being configured to use "environment specific urls". And it is not clear how you are storing these environment specific urls. If, for example, the URL variable is a member variable of a Grails service and you are storing the environment specific URLs in the Config.groovy, then you could
import grails.util.Environment
...
//inject the GrailsApplication Configuration in Config.groovy
def grailsApplication
//Hold the URL value from Config.groovy
String environmentUrl
...
Environment current = Environment.getCurrent()
if(Environment.PRODUCTION == current) {
environmentUrl = grailsApplication.config.PRODUCTION_URL
} else {
environmentUrl = grailsApplication.config.DEVELOPMENT_URL
}
Where Config.groovy has
PRODUCTION_URL = "http://blah.com/blah/"
DEVELOPMENT_URL = "http://blah.dev/blah"
Hope that helps.
If you have a System property available that tells you what environment you're in you can simply add if statements or a switch statement in your Config.groovy file, like this:
if (System.getProperty("foo") == "myTestEnvironment") {
myConfigSetting = "test"
} else if (System.getProperty("foo") == "myProductionEnvironment") {
myConfigSetting = "production"
}
This solution also works in other config files under grails-app/conf
Grails config files are parsed using groovy ConfigSlurper so you can put executable code in there without a problem.
Sorry this is way late, but another way is to inject a configuration property in BootStrap.groovy.
For Example:
if (currentEnv == Environment.DEVELOPMENT) {
...
grailsApplication.config.some.property = DEVELOPMENT_ENVRIONMENT
...
}
else if (currentEnv == Environment.TEST) {
...
grailsApplication.config.some.property = TEST_ENVIRONMENT
...
}
I have used this recently and it works really well. We are using Grails 2.5.2
As an addendum to the other answers:
You can use Environment.isDevelopmentMode() or in a groovier way Environment.developmentMode to check if the environment is set to development. This is useful when you take the aproach of only modifying settings for development on your code where production settings are default.

Problems setting up Grails 2.3.5 App on Heroku with ClearDB

I am setting up a Grails 2.3.5 App on a Heroku Server and I keep getting the following error when tomcat starts up:
Caused by: java.sql.SQLException: Driver:com.mysql.jdbc.Driver#5a7359fe returned null for URL:jdbc:h2:mem:grailsDB;MVCC=TRUE;LOCK_TIMEOUT=10000
I am not using h2 as the Database. I would like to use ClearDB. My environment variables all look correct and everything looks correct in DataSource.groovy. I even setup the connection string to be hard coded to see if this would make a difference. Nada.
production {
datasource {
dbCreate = "create-drop"
url = "jdbc:mysql://us-cdbr-east-05.cleardb.net/heroku_5a952ab6aXXXXXXX?reconnect=true"
username = "XXXXX"
password = "xxxxx"
}
}
Obviously I'm missing something, but I cannot see what.
Where is the production setup getting the h2 connection string from?!
You don't show your full DataSource.groovy file, but it probably has the H2 driver in the top section (driverClassName = "org.h2.Driver"). The values there are the defaults, and the environment-specific blocks are merged into that to create the final settings. You can override that in the production block
production {
datasource {
dbCreate = "create-drop"
url = "jdbc:mysql://us-cdbr-east-05.cleardb.net/heroku_5a952ab6aXXXXXXX?reconnect=true"
username = "XXXXX"
password = "xxxxx"
driverClassName = 'com.mysql.jdbc.Driver'
dialect = org.hibernate.dialect.MySQL5InnoDBDialect
}
}
Additionally, you should always specify the dialect when using MySQL. Grails auto-detects the dialect well in most cases, but can't determine if you're using MyISAM or InnoDB, so it defaults to a dialect that uses the default engine type configured for the whole server. Newer versions of MySQL default to InnoDB and it's easy to change it in any version, but if you don't or it's an older version you'll end up with non-transactional MyISAM tables. Specifying the dialect ensures that your app uses the proper table type.
I found out the reason for my problems.
The code block for data source has a lower case "s" in source. It should have been dataSource, not datasource.
When this block is missing, it appears the default is a h2 database with the name "grailsDB". I could not find this documented anywhere, hence all my confusion.
Check your cases!!!!

Resources