Variable interpolation inside Map directive - nginx

I am trying to map a variable inside the http directive in Nginx.
When left alone, the variable alone gets expanded, if I add anything else to the string the expansion stops working.
http {
map $host $foo {
#default "$host"; # - this works fine and returns 'localhost'
default "This is my host: $host"; # - THIS DOESN'T WORK
}
server {
location / {
echo $foo;
}
}
}
Do you have any suggestions to make the expansion work inside the map?

As stated in the map directive documentation :
The resulting value can be a string or another variable (0.9.0).
Update: This functionality has been added to version 1.11.2 of NGinx, as per Comment #7 here: https://trac.nginx.org/nginx/ticket/663#comment:7

Related

Initialising a driver instance with callSingle does not work for automated UI tests [duplicate]

I was trying to find a way to launch all features in Karate testing through maven using an external variable to set up the browser (with a local webdriver or using a Selenium grid).
So something like:
mvn test -Dbrowser=chrome (or firefox, safari, etc)
or using a Selenium grid:
mvn test -Dbrowser=chrome (or firefox, safari, etc) -Dgrid="grid url"
With Cucumber and Java this was quite simple using a singleton for setting up a global webdriver that was then used in all tests. In this way I could run the tests with different local or remote webdrivers.
In Karate I tried different solution, the last was to:
define the Karate config file a variable "browser"
use the variable "browser" in a single feature "X" in which I set up only the Karate driver
from all the other features with callonce to re-call the feature "X" for using that driver
but it didn't work and to be honest it doesn't seem to me to be the right approach.
Probably being able to set the Karate driver from a Javascript function inside the features is the right way but I was not able to find a solution of that.
Another problem I found with karate is differentiating the behavior using a local or a remote webdriver as in the features files they're set in different ways.
So does anyone had my same needs and how can I solve it?
With the suggestions of Peter Thomas I used this karate-config.js
function fn() {
// browser settings, if not set it takes chrome
var browser = karate.properties['browser'] || 'chrome';
karate.log('the browser set is: ' + browser + ', default: "chrome"');
// grid flag, if not set it takes false. The grid url is in this format http://localhost:4444/wd/hub
var grid_url = karate.properties['grid_url'] || false;
karate.log('the grid url set is: ' + grid_url + ', default: false');
// configurations.
var config = {
host: 'http://httpstat.us/'
};
if (browser == 'chrome') {
if (!grid_url) {
karate.configure('driver', { type: 'chromedriver', executable: 'chromedriver' });
karate.log("Selected Chrome");
} else {
karate.configure('driver', { type: 'chromedriver', start: false, webDriverUrl: grid_url });
karate.log("Selected Chrome in grid");
}
} else if (browser == 'firefox') {
if (!grid_url) {
karate.configure('driver', { type: 'geckodriver', executable: 'geckodriver' });
karate.log("Selected Firefox");
} else {
karate.configure('driver', { type: 'geckodriver', start: false, webDriverUrl: grid_url });
karate.log("Selected Firefox in grid");
}
}
return config;
}
In this way I was able to call the the test suite specifying the browser to use directly from the command line (to be used in a Jenkins pipeline):
mvn clean test -Dbrowser=firefox -Dgrid_url=http://localhost:4444/wd/hub
Here are a couple of principles. Karate is responsible for starting the driver (the equivalent of the Selenium WebDriver). All you need to do is set up the configure driver as described here: https://github.com/intuit/karate/tree/master/karate-core#configure-driver
Finally, depending on your environment, just switch the driver config. This can easily be done in karate-config.js actually (globally) instead of in each feature file:
function fn() {
var config = {
baseUrl: 'https://qa.mycompany.com'
};
if (karate.env == 'chrome') {
karate.configure('driver', { type: 'chromedriver', start: false, webDriverUrl: 'http://somehost:9515/wd/hub' });
}
return config;
}
And on the command-line:
mvn test -Dkarate.env=chrome
I suggest you get familiar with Karate's configuration: https://github.com/intuit/karate#configuration - it actually ends up being simpler than typical Java / Maven projects.
Another way is to set variables in the karate-config.js and then use them in feature files.
* configure driver = { type: '#(myVariableFromConfig)' }
Keep these principles in mind:
Any driver instances created by a "top level" feature will be available to "called" features
You can even call a "common" feature, create the driver there, and it will be set in the "calling" feature
Any driver created will be closed when the "top level" feature ends
You don't need any other patterns.
EDIT: there's some more details in the documentation: https://github.com/intuit/karate/tree/develop/karate-core#code-reuse
And for parallel execution or trying to re-use a single browser for all tests, refer: https://stackoverflow.com/a/60387907/143475

PHP Deployer: How to get user name from host setup

I am trying to deploy my code via php deployer, but I am facing a syntax issue, which is how can I re-use the host user on task?
For instance, I would like to replace USERNAME with barfoo in dynamic way. Not hard code.
Can anyone give me a suggestion? Much appropriate.
host('17.99.88.225')
->user('barfoo') // This is the server user name
->stage('production')
->set('deploy_path', '/SERVER_PATH/{{application}}')
->set('branch', 'develop');
...
task('upload:env', function () {
runLocally('scp .env USERNAME#{{hostname}}:{{release_path}}/.env');
})->desc('Environment setup');
I just figure it out myself. I would like to share here:
All I need to do is set a new variable and use it on my script. LOL
set('username', 'nanomed1'); // set my own variable
...
task('upload:env', function () {
$username = get( 'username'); // use the variable I created on the top
runLocally('scp .env '.$username.'#{{hostname}}:{{release_path}}/.env');
})->desc('Environment setup');
That's it!

How to pass a parameter from the Jupyter backend to a frontend extension

I currently have a value that is stored as an environment variable the environment where a jupyter server is running. I would like to somehow pass that value to a frontend extension. It does not have to read the environment variable in real time, I am fine with just using the value of the variable at startup. Is there a canonical way to pass parameters a frontend extension on startup? Would appreciate an examples of both setting the parameter from the backend and accessing it from the frontend.
[update]
I have posted a solution that works for nbextentions, but I can't seem to find the equivalent pattern for labextensions (typescript), any help there would be much appreciated.
I was able to do this by adding the following code to my jupter_notebook_config.py
from notebook.services.config import ConfigManager
cm = ConfigManager()
cm.update('notebook', {'variable_being_set': value})
Then I had the parameters defined in my extension in my main.js
// define default values for config parameters
var params = {
variable_being_set : 'default'
};
// to be called once config is loaded, this updates default config vals
// with the ones specified by the server's config file
var update_params = function() {
var config = Jupyter.notebook.config;
for (var key in params) {
if (config.data.hasOwnProperty(key) ){
params[key] = config.data[key];
}
}
};
I also have the parameters declared in my main.yaml
Parameters:
- name: variable_being_set
description: ...
input_type: text
default: `default_value`
This took some trial and error to find out because there is very little documentation on the ConfigManager class and none of it has an end-to-end example.

Nginx rewrite by map with parameters

I would like to rewrite with map as
/oldpage?f=regist -> /signup
/oldpage?f=regist&a=1 -> /signup?a=1
/oldpage?f=confirm -> /signup?t=confirm
/oldpage?f=confirm&a=1 -> /signup?t=confirm&a=1
but my redirect result in nginx (v1.12.2) is
/oldpage?f=regist -> /signup?f=regist
/oldpage?f=regist&a=1 -> Not Found
/oldpage?f=confirm -> /signup?t=confirm?f=confirm
/oldpage?f=confirm&a=1 -> Not Found
I set nginx.conf as,
map $request_uri $rewrite_uri {
include conf.d/redirect.map;
}
server {
...
if ($rewrite_uri) {
rewrite ^ $rewrite_uri redirect;
}
}
and redirect.map is
/oldpage?f=regist /signup;
/oldpage?f=confirm /signup?t=confirm;
It would be really appreciated if you could give me some advices.
If the a=1 parameter represents any other parameters, and you do not wish to add those combinations to the map file, you should change the syntax of your map file to use regular expressions.
The regular expressions in the map block can create named captures which can be used later in the configuration. In the example below, the $prefix and $suffix variables are named captures from the map block.
The example below has some caveats - because the $prefix and $suffix values may be empty, the generated URIs may contain a trailing ? or & - which should not affect the overall semantics.
All of the regular expressions and the mapped values have a common pattern to capture optional parameters and append them to the resulting value.
map $request_uri $new {
default 0;
~*^/oldpage\?(?<prefix>.*&)?f=regist(&(?<suffix>.*))?$ /signup?;
~*^/oldpage\?(?<prefix>.*&)?f=confirm(&(?<suffix>.*))?$ /signup?t=confirm&;
}
server {
...
if ($new) {
return 301 $new$prefix$suffix;
}
See this document for more.

Non-scalar ENVs for use as Symfony Parameter

I'm trying to use ENVs to set my parameters in Symfony2. The scalar values are easy enough, but I have parameters that are arrays that I need to set somehow with ENVs.
The parameter in question:
parameters:
redis.servers:
- { host: 127.0.0.1, port: 6379 }
- { host: other, port: 6379 }
# and so on
The kicker here is that the array of servers can change dynamically, so I can't just assume there's 2.
What I hoped to do (but this just gives me a string of json):
SYMFONY__REDIS__SERVERS=[{"host":"127.0.0.1","port":"6379"}]
Is this possible? Any work-arounds that are feasible? There are multiple bundles we're using that accept array/object parameters, so I can't do an update there to process the param. It would have to be app level, if anything.
Thanks.
I was able to solve this by updating the AppKernel to override the getEnvParameters() method of the parent Kernel. This method only runs on parameters that the Kernel already found in the ENV (technically from $_SERVER). I like it because it won't run on the entire parameter stack, nor the entire $_SERVER array.
protected function getEnvParameters()
{
$parameters = parent::getEnvParameters();
foreach ($parameters as &$parameter) {
if (is_string($parameter)) {
$decoded = json_decode($parameter, true);
// we only care about arrays (or objects that get turned into arrays)
if (!json_last_error() && is_array($decoded)) {
$parameter = $decoded;
}
}
}
return $parameters;
}

Resources