Externalizing Run configurations for Grails app - java

Is there a way to externalize the run config for per environment configurations with Grails 3 applications?
I am aware that there are run config arguments that allow one to run their application under a dev, prod, test, etc environment, but I was wondering if there is a variable, for example "grails.env" that I can change in a properties, YAML, config, or other file that can be read at run time that will do this for me.
This is just to avoid confusion between the application being tested and run in one setting/environment(physical environment like my local machine), then being given to another individual or team to run elsewhere.
The goal is to configure or set this variable so the run team/individual wont need to know or change the run commands.
Im aware of how to configure the environment with the command line, and within intelliJ and Eclipse. I'm wondering if there is a way to default this in perhaps a file that is read instead.
Thanks

I'm not to sure what is confusing you here but let me try and see if I can point you in the right direction
From the documentation here: http://docs.grails.org/latest/guide/conf.html#environments your application can be delivered as a package war file to the target user to have tested, and the war file can be created with any of of the environment configurations
grails test war
Since the command is can be run in the console, you could run with system properties like this:
grails $ENVIRONMENT war
Hope this helps
Update 2
By default the grails run-app runs with the dev environment, but you can force an environment by doing
grails $env run-app
If you want some default configurations to be run when you use the run-app command, then you should make sure that configuration is not in the environment block in either application.yml or application.groovy
Example of configuration in the environment block:
-----------------------------------------------------
environment{
development{
appConfig{
ishybrid = true
}
}
}
Example of configuration not in any environment block:
-------------------------------------------------------
appConfig{
ishybrid = true
}
environment{
development{
//other configs
}
}
So basically depending on what you exclude from the environment block configuration is what will be configured as the default configuration for your application to run.
Hope this helps better?

Related

Can I change a database depending on the branch I am on (specified in Dockerfile)?

I would like to have my:
spring.datasource.url = jdbc:mysql://666.666.666.666/prod_very_wow
Change into:
spring.datasource.url = jdbc:mysql://666.666.666.666/dev_very_wow
According to the branch I am currently on. I think I should also have it specified within the Dockerfile - I should have a property added next to docker's RUN which should determine which data source ought to be activated.
Namely, I would like my app to be connected to prod_very_wow when I am on master branch and dev_very_wow everytime I am checking out to dev or creating a new feature branch and have it all determined by a property added to RUN mvn package within the Dockerfile.
I apologise if the question makes no sense, but, frankly - I am a little bit clueless how to ask this question and so I have troubles googling for answers.
I just found a couple of leads about "environmental variables", but I can't find any connection between the datasource connected to and the branch I am currently on.
The best way to handle different configuration based on environment is to have decoupled your code from your configuration that is one of the twelve-factor apps principles. In this case you should have an external config server, like spring cloud config server, that will host the configurations files for the different environments and the application will ask this config server for the proper config file depending on the environment where it is deployed.
However, if you don't want to follow this approach you can create the different configuration files in the application and use an environment variable that tells spring which file to use. For example, in your case you can have an application-local.yaml and application-prod.yaml, and then if you want to specify it in the dockerfile in the mvn package command, you can use:
RUN mvn -Dspring.profiles.activ=local package
RUN mvn -Dspring.profiles.activ=prod package

How to edit app.properties file with build parameter in Jenkins

I have a selenium script which I want to run from Jenkins. I have a properties file called app.properties. This file consists properties such as:
browser=chrome
I configured my project as parameterized so when I run my build, it asks for browser parameter. I want to select this parameter(for example firefox), so that it will change browser property in app.properties and will run the automation in Firefox.
Normally, when I change the browser property in app.properties in Intellij, my program runs with that browser. So there is nothing wrong with my program in that sense.
Is there a way to change app.properties with respect to my Jenkins build parameter and run the program with that configuration?
EDIT: I found the following solution:
Install surefire plugin.
Add a browser parameter.
In your property managing class, take browser parameter as
System.getProperty("browser");
From jenkins, configure a browser parameter
Invoke maven command: mvn test "-Dbrowser=${BROWSER}"
You can pass system properties to change configuration.
First you should configure your project to read both system properties and configuration file, where system properties will have higher priority. I'd recommend Apache Commons Composite Configuration. It can look like this:
CompositeConfiguration configuration = new CompositeConfiguration();
try {
configuration.addConfiguration(new SystemConfiguration());
configuration.addConfiguration(new PropertiesConfiguration("app.properties"));
} catch (ConfigurationException e) {
e.printStackTrace();
}
//Read your configuration values here
This way when you provide system property -Dbrowser=chrome it will override value from configuration file.
Secondly, you'll need to configure Jenkins job. Since you're passing a parameter you can use it in your build step definition:
mvn clean test -Dbroswer=${browser-param}
“The way parameters take effect is also different depending on the parameter type you choose ... String parameters are exposed as environment variables of the same name.”
https://wiki.jenkins.io/plugins/servlet/mobile?contentId=34930782#content/view/34930782

Maven run configuration doesn't pick up active profile while Spring run configuration does

My Spring run configuration is just the default with the following the VM options:
-Dspring.profiles.active=local
My Maven run configuration is the defaults with the following in the command line:
spring-boot:run
and the following in VM options:
-Dspring.profiles.active=local
When I run the maven one it doesn't pick up on a profile and instead uses default:
No active profile set, falling back to default profiles: default
With the Spring configuration I have no issues, the problem is with how I need to deploy it, it uses a maven command, so I can't have this failing and I don't really understand why it's happening. There really isn't anything fancy is this projects. It's your basic micro service.
Just in case it's needed. The root 'Application' file only has the following:
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Link to the Maven run config. It is all defaults outside of what is pictured. https://imgur.com/a/GGiwimQ
Adding the following to the command line arguments seemed to fix it:
-Drun.jvmArguments=-Dspring.profiles.active=local
Although I understand why it worked it doesn't explain why this happened in the first place. I will update this answer if I ever find out the true reason.
create
application.properties
file in src/main/resources if it doesnt exist and add
spring.profiles.active=local

Set Spring Boot application.properties based on Environment Variable

I have a Spring Boot application that will run in various environments, and based on the environment it runs in, it will connect to a different database. I have a few application.properties files, one for each environment which look like such:
application-local.properties:
spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://localhost:5432/mydb
spring.datasource.username=dbuser
spring.datasource.password=123456789
application-someserver.properties:
spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://someserver:5432/myproddb
spring.datasource.username=produser
spring.datasource.password=productionpass
etc. etc.
On each of my environments, I have a environment variable called MYENV which is set to the type of environment it is, for example local or someserver (the name of the application-{env}.properties files perfectly matches the environment name).
How can I get spring boot to read this environment variable and automatically choose the correct .properties file? I don't want to have to do the whole -Dspring.profiles.active=someserver because of the way this package is deployed (it will not be running as a jar).
How can I get spring boot to read this environment variable and
automatically choose the correct .properties file?
Tell Spring Boot to select the Active Profile from the MYENV property or environment variable. One way of doing this is to add the following into your application.properties:
spring.profiles.active=${MYENV}
This way Spring Boot will set spring.profiles.active to the value of MYENV environment variable.
I don't to have to do the whole -Dspring.profiles.active=someserver
because of the way this package is deployed (it will not be running as
a jar)
You can use the corresponding environment variable to that spring.profiles.active, if you don't like to pass a system property through -D arguments. That corresponding environment variable is SPRING_PROFILES_ACTIVE. For example if you set the SPRING_PROFILES_ACTIVE to local, the local profile will be activated. If you're insisting to use MYENV environment variable, the first solution is the way to go.
If you are deploying that application to some container (tomcat, weblogic, ...) you can specify environment variable. For example lets specify environment variable application1.spring.profiles.active=someserver and then in your application.properties set property spring.profiles.active=${application1.spring.profiles.active}
Using Spring context 5.0 I have successfully achieved loading correct property file based on system environment via the following annotation
#PropertySources({
#PropertySource("classpath:application.properties"),
#PropertySource("classpath:application-${MYENV:test}.properties")})
Here MYENV value is read from system environment and if system environment is not present then default test environment property file will be loaded, if I give a wrong MYENV value - it will fail to start the application.
Note: for each profile, you want to maintain you need to make an application-[profile].property file and although I used Spring context 5.0 & not Spring boot - I believe this will also work on Spring 4.1
This is the best solution I believe for my AWS Lambda - with minimal dependencies

Setting system property get agent in teamcity maven build

I am trying to create plugin, which deploys my application in pre-integration-phase and runs the test against it. Now my application requires some property called LOOKUPLOCATOR which should be unique per envrionment. Now i have multiple agents configured in teamcity and many builds can run in parallel and if all the builds will have same property they will interfere with each other and test results will be unexpected.
Is there a way so that when my build run and in my java code if somehow get to know the agent name, and i will maintain a hardcoded value for LOOKUPLOCATOR for each agent, we can set that value. So my property will be per agent
Teamcity has some pre-defined variables which are available while a build is running. Agent name can be found in %teamcity.agent.name%.
Here is how to set agent-specific parameters
If additional applications/libraries are available in the environment, the administrator can manually define the property in the /conf/buildAgent.properties file. These properties can be used for setting various build configuration options, for defining build configuration requirements (for example, existence or absence of some property) and inside build scripts.

Categories