Un-set a property by overriding it - spring

I have a logistical Problem with spring property files. Im doing a refactor of our profiles with the following goal:
I want to have two configurations in which I want to start the application. One for local development and one for the production environment. I know the property values for both configurations. The aim is to have the default profile act as the local configuration and have just one profile 'production' which will overwrite values for the production scenario.
The problem is now that the local configuration sets some properties which the production config does not set. So in any case where the production config is an extension of the local (i.e. default) config, there will be some properties which are set to some value which should actually be undefined.
Is there some way by which I can "un-set" these properties in the production profile?
Example of how I would like it to work:
# application.properties
# this is the local configuration
app.config.name = "FOO"
services.search.url = localhost:8081
app.mock.provider = localhost:8082
.
# application-production.properties
# activating this should yield the production configuration
services.search.url = production-search-url.com # Overriding works of course
app.mock.provider = PLEASE_MAKE_THIS_PROP_UNDEFINED_AGAIN # I suppose this doesn't work
spring.sentry.dns = nw9x74b3kqllanx6rh3
# app.config.name = "FOO" should be and is still set

Related

Serverless stage environment variables using dotenv (.env)

I'm new to serverless,
So far I was be able to deploy and use .env for the app.
then, under provider in stage property in serverless.yml file, I change it to different stage. I also made new.env.{stage}.
after re-deploy using sls deploy, It still reads the default .env file.
the documentation states:
The framework looks for .env and .env.{stage} files in service directory and then tries to load them using dotenv. If .env.{stage} is found, .env will not be loaded. If stage is not explicitly defined, it defaults to dev.
So, I still don't understand "If stage is not explicitly defined, it defaults to dev". How to explicitly define it?
The dotenv File is choosen based on your stage property configuration. You need to explicitly define the stage property in your serverless.yaml or set it within your deployment command.
This will use the .env.dev file
useDotenv: true
provider:
name: aws
stage: dev # dev [default], stage, prod
memorySize: 3008
timeout: 30
Or you set the stage property via deploy command.
This will use the .env.prod file
sls deploy --stage prod
In your serverless.yml you need to define the stage property inside the provider object.
Example:
provider:
name: aws
[...]
stage: prod
As Feb 2023 I'm going to attempt to give my solution. I'm using the Nx tootling for monorepo (this shouldn't matter but just in case) and I'm using the serverless.ts instead.
I see the purpose of this to be to enhance the developer experience in the sense that it is nice to just nx run users:serve --stage=test (in my case using Nx) or sls offline --stage=test and serverless to be able to load the appropriate variables for that specific environment.
Some people went the route of using several .env.<stage> per environment. I tried to go this route but because I'm not that good of a developer I couldn't make it work. The approach that worked for the was to concatenate variable names inside the serverless.ts. Let me explain...
I'm using just one .env file instead but changing variable names based on the --stage. The magic is happening in the serverless.ts
// .env
STAGE_development=test
DB_NAME_development=mycraftypal
DB_USER_development=postgres
DB_PASSWORD_development=abcde1234
DB_PORT_development=5432
READER_development=localhost // this could be aws rds uri per db instances
WRITER_development=localhost // this could be aws rds uri per db instances
# TEST
STAGE_test=test
DB_NAME_test=mycraftypal
DB_USER_test=postgres
DB_PASSWORD_test=abcde1234
DB_PORT_test=5433
READER_test=localhost // this could be aws rds uri per db instances
WRITER_test=localhost // this could be aws rds uri per db instances
// serverless.base.ts or serverless.ts based on your configuration
...
useDotenv: true, // this property is at the root level
...
provider: {
...
stage: '${opt:stage, "development"}', // get the --stage flag value or default to development
...,
environment: {
STAGE: '${env:STAGE_${self:provider.stage}}}',
DB_NAME: '${env:DB_NAME_${self:provider.stage}}',
DB_USER: '${env:DB_USER_${self:provider.stage}}',
DB_PASSWORD: '${env:DB_PASSWORD_${self:provider.stage}}',
READER: '${env:READER_${self:provider.stage}}',
WRITER: '${env:WRITER_${self:provider.stage}}',
DB_PORT: '${env:DB_PORT_${self:provider.stage}}',
AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1',
}
...
}
When one is utilizing the useDotenv: true, serverless loads your variables from the .env and puts them in the env variable so you can access them env:STAGE.
Now I can access the variable with dynamic stage like so ${env:DB_PORT_${self:provider.stage}}. If you look at the .env file each variable has the ..._<stage> at the end. In this way I can retrieve dynamically each value.
I'm still figuring it out since I don't want to have the word production in my url but still get the values dynamically and since I'm concatenating this value ${env:DB_PORT_${self:provider.stage}}... then the actual variable becomes DB_PORT_ instead of DB_PORT.

Environment issue in Laravel

$env = $app->detectEnvironment(array(
'local' => array('*localhost*'),
'test' => array('chan.app'),
));
This is how I set in boostrap/start.php, and I set ip in hosts file
127.0.0.1 localhost
127.0.0.1 chan.app
No matter I type http://localhost/ or http://chan.app, App::environment() always reveal production, therefore I can't change database config for it.
Open your CMD (Mac, Linux, and Windows) and type the command:
hostname
this will return the name of your computer. Then use that name:
$env = $app->detectEnvironment(array(
'local' => array('ComputerName'),
));
Because of security issues, the use of url domains in environment is forbidden. Laravel says to use hostnames instead.
This is why I doubt, that Laravel would recognise (detect) your configuration correctly, as both are on the same machine.
From the 4.2 Upgrade Guide:
Environment Detection Updates
For security reasons, URL domains may no longer be used to detect your
application environment. These values are easily spoofable and allow
attackers to modify the environment for a request. You should convert
your environment detection to use machine host names (hostname command
on Mac, Linux, and Windows).
EDIT
Let's say, you want a local and a live environment.
1. Create folders for each configuration:
Create a folder local & live inside /app/config/
Inside each of those folders you create the config file(s) you wish to override from /app/config/,
For example, in your live (production) environment, you don't want to have the debug option activated.
Create a file app.php in the /app/config/live folder.
Inside, you'll just return the desired options to override, as defined in the original /app/config/app.php.
return array('debug' => false);
In the local environment, 'debug' would be set to true, for development.
2. Add the environment to the framework:
In your /bootstrap/start.php file:
$env = $app->detectEnvironment(array(
'local' => array('local-machine-name'),
'live' => array('yourdoamin.com')
));
That's the important part:
- Development (local): --> machine name
- Production: --> root-url (yourdomain.com) which represents the "machine" name
See the docs about environment config for further information.

Set application name on stage files on capistrano

I'm trying to deploy my application with the multistage/ext estensions. It works fine when each stage is in different servers. But for one particular proyect I want to deploy two stages to the same server.
For that I need to set a different application name on each server. And that is what isn't working.
I moved the application variable to the stage file and define the deploy_to variable with lazy loading.
config/deploy.rb
set :stages, %w(production beta)
set :default_stage, "beta"
require 'capistrano/ext/multistage'
#set :application, "myapp-beta"
set :user, "deploy"
set (:deploy_to) { "/home/#{user}/applications/#{application}" }
config/deploy/beta.rb
server "my.server.com", :web, :app, :db, primary: true
set :application, "myapp-beta"
set :domains, "beta.myapp.com"
set :branch, "beta"
I get Please specify the name of your application, set :application, 'foo' error
Maybe I should be thinking about deploying to a different server, but now I really want to understand why this isn't working.
thanks
There is nothing functionally wrong with your code. As Lavixu mentioned, as long as you specify the stage name when deploying (i.e. cap beta deploy:setup, cap beta deploy) then the application variable will be recognised.
set (:deploy_to) { "/home/#{user}/applications/#{application}" }
Should be
set :deploy_to, -> { "/home/#{user}/applications/#{application}" }
I had to use fetch to reference other capistrano variables. ie:
set :deploy_to, -> { "/var/deploy/#{fetch(:application)}" }
Trying to access application directly raised a undefined local variable or method 'application' for main:Object error.

How to export Plone session configuration?

I'd like to export my Plone session configuration to my portal product.
The session configuration is set via the ZMI -> acl-users -> session -> properties
I have tried creating a snapshot of the site but can't locate the session configuration within the snapshot xml...
Indeed, there is no GenericSetup configuration support included in plone.session; there is currently nothing that'll export it for you, nor anything to then import the settings.
You'd have to write a setup step for it instead, and configure the session plugin manually through that.
Add an import step to your configure.zcml configuration file:
<?xml version="1.0"?>
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
<genericsetup:importStep
name="yourpackage.a_unique_id_for_your_step"
title="Configures the plone.session plugin"
description="Perhaps an optional description"
handler="your.package.setuphandlers.setupPloneSession"
/>
</configure>
and add an empty 'sentinel' text file to the same profile directory named youpackage.setup-plonesession.txt
then add a setuphandlers.py module to your package (what handler points to in the above example):
def setupPloneSession(context):
if context.readDataFile('youpackage.setup-plonesession.txt') is None:
return
portal = context.getSite()
plugin = portal.acl_users.session
# Configure the plugin manually
plugin.path = '/'
plugin.cookie_name = '__ac'
plugin.cookie_domain = ''
# Set up a shared auth_tkt secret
plugin._shared_secret = 'YourSharedSecretKey'
plugin.mod_auth_tkt = True
Note that we first test if the sentinel file is present; if you reuse your package setup elsewhere the setup step could be run multiple times if you don't do this.
You'll need to refer to the plugin source to get an idea of what you can configure, I'm afraid.

Capistrano: How to Include common settings in multiple project deploy.rb files

this is probably a newbie ruby question. I have several libraries and apps that I need to deploy to several different hosts. All of the apps and libs will share some common settings for those hosts-- e.g. host name, database server/user/pass, etc.
My goal is to do something like:
cap host1 stage deploy
cap host2 stage deploy
cap host1 prod deploy
# ...
My question is how do you include these common settings in all of your deploy.rb files? More specifically, I want to create a an rb file that I can include that has some common settings and several host specific task definitions:
set :use_sudo, false
# set some other options
task :host1 do
role :app, "host1.example.com"
role :web, "host1.example.com"
role :db, "host1.example.com", :primary => true
set :rodb_host, "dbhost"
set :rodb_user, "user"
set :rodb_pass, "pass"
set :rodb_name, "db"
end
task :host2 do
#...
end
deploy.task :carsala do
transaction do
setup
update_code
symlink
end
end
And then "include" this file in all of my deploy.rb files where I define stage, prod, etc and overwrite any "common" configuration parameters as necessary. Any suggestions would be appreciated. I've tried a few different things, but I get errors from cap for all of them.
Edit: I've tried
require 'my_module'
But I get errors complaining about an undefined task object.
I just experimented with it a little more and what I discovered is that you have to:
load 'config/my_module'
I can put all of my common definitions here and just load it into my deploy.rb.
It appears from the docs that load loads and executes the file. Alternatively, require attempts to load the library specified. I'm not totally sure about real difference, but it appears that there is some separation between the current app symbol space and the library require'd (hence the errors about the undefined task object) that isn't a problem when you do a load.
require 'my_extension'
Save your extensions in my_extension.rb
Jon has it right, that's the simplest way to go, just save it in a separate file and use require 'filename'. You could also use something fancy like Webistrano for deployment which also supports this in the form of Capistrano 'Recipes'. I've been using it for a while on a few projects and have come to love it.
I'm not sure how complex your needs are, but this works well for me for deployment:
set :application, "app"
set :scm, :subversion
# ... set all your common variables
task :staging do
set :repository, "http://app/repository/trunk/"
# ... set other uncommon variables in task
end
task :production do
set :repository, "http://app/repository/production/"
# ...
end
Deployment is just
cap staging deploy
or
cap production deploy

Resources