Skip to content

Commit

Permalink
Merge pull request #17 from criteo-forks/configure-env
Browse files Browse the repository at this point in the history
Add support for custom environment in Mesos term
  • Loading branch information
clems4ever authored Mar 8, 2019
2 parents cbb58e2 + c1a7c10 commit a9333e8
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ Here are the details of available options.
| Parameter | Description |
|-----------------------------------------|------------------------------------------------------------------------------------------|
| MESOS\_TERM\_COMMAND | The command to be run in the container when a user logs in. (Default: /bin/sh) |
| MESOS\_TERM\_ENVIRONMENT | List of environment variable to enrich the shell with (NAME=value, colon separated) |
| MESOS\_TERM\_ENABLE\_PER\_APP\_ADMINS | If 'true', application administrators can be declared with the Mesos label MESOS\_TERM\_DEBUG\_GRANTED\_TO label. It means those users can log into the application containers. An example is provided below. (Default: false) |
| MESOS\_TERM\_ALLOWED\_TASK\_ADMINS | White list of application administrators (users or groups) allowed to override application configuration through Mesos label |
| MESOS\_TERM\_ENABLE\_RIGHTS\_DELEGATION | If 'true', super administrators can delegate rights to log into one specific container to one person for a certain amount of time. (Default: false) |
Expand Down
1 change: 1 addition & 0 deletions scripts/tests/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ services:
- MESOS_TERM_MESOS_STATE_CACHE_TIME=60
- MESOS_TERM_SESSION_SECRET=abcd
- MESOS_TERM_SUPER_ADMINS=admins
- 'MESOS_TERM_ENVIRONMENT=TOTO=tata:Bad=var'

mesos-term-no-auth:
build:
Expand Down
5 changes: 5 additions & 0 deletions src/controllers/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ function spawnTerminal(
params.push(task.user);
}

if (env.EXTRA_ENV) {
params.push('--env');
params.push(env.EXTRA_ENV);
}

const options: NodePty.IPtyForkOptions = {
name: 'bash'
};
Expand Down
2 changes: 2 additions & 0 deletions src/env_vars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface EnvVars {
ALLOWED_TASK_ADMINS: string[];
ENABLE_PER_APP_ADMINS?: boolean;
ENABLE_RIGHTS_DELEGATION?: boolean;
EXTRA_ENV: string;
COMMAND: string;
}

Expand Down Expand Up @@ -58,6 +59,7 @@ export const env: EnvVars = {
MESOS_MASTER_URL: getOrExit('MESOS_TERM_MESOS_MASTER_URL'),
AUTHORIZATIONS_ENABLED: authorizations_enabled,
MESOS_STATE_CACHE_TIME: parseFloat(getOrExit('MESOS_TERM_MESOS_STATE_CACHE_TIME')),
EXTRA_ENV: getOrElse('MESOS_TERM_ENVIRONMENT', ''),
COMMAND: getOrElse('MESOS_TERM_COMMAND', '/bin/sh')
};

Expand Down
22 changes: 22 additions & 0 deletions src/python/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import time
import uuid
import urllib.parse
import re

from functools import partial
from queue import Queue
Expand All @@ -31,6 +32,8 @@ class TaskIO(object):
:type cmd: str
:param args: Additional arguments for the command
:type args: str
:param env: List of environment variable to enrich the shell with (NAME=value, colon separated)
:type env: str
:param interactive: whether to attach STDIN of the current
terminal to the new command being launched
:type interactive: bool
Expand All @@ -45,9 +48,11 @@ class TaskIO(object):
HEARTBEAT_INTERVAL_NANOSECONDS = HEARTBEAT_INTERVAL * 1000000000

def __init__(self, agent_url, parent_container_id, user=None, cmd=None,
env=None,
args=None, interactive=False, tty=False):
# Store relevant parameters of the call for later.
self.cmd = cmd
self.env = env
self.interactive = interactive
self.tty = tty
self.args = args
Expand Down Expand Up @@ -228,6 +233,21 @@ def _launch_nested_container_session(self):
'value': self.cmd,
'arguments': [self.cmd] + self.args,
'shell': False}}}
if self.env is not None:
env_vars = []
env_var_regex = re.compile('^([A-Z_][A-Z0-9_]*)=(.*)$')
for env_var in self.env.split(':'):
matches = env_var_regex.match(env_var)
if matches and len(matches.groups()) == 2:
env_vars.append({
'name': matches.group(1),
'type': 'VALUE',
'value': matches.group(2)
})
message['launch_nested_container_session']['command']['environment'] = {
'variables': env_vars
}

if not self.user is None:
message['launch_nested_container_session']['command']['user'] =\
self.user
Expand Down Expand Up @@ -489,10 +509,12 @@ def _window_resize(self, signum, frame):
parser.add_argument('container_id', type=str, help='The container id to connect to.')
parser.add_argument('--user', type=str, help='The user to run the command as.')
parser.add_argument('--cmd', type=str, default="/bin/sh", help='The command to run in the container.')
parser.add_argument('--env', type=str, help='List of environment variable to enrich the shell with (NAME=value, colon separated).')
args = parser.parse_args()

t = TaskIO(agent_url=args.agent_url, parent_container_id=args.container_id,
tty=True, user=args.user, interactive=True, cmd=args.cmd,
env=args.env,
args=[])
t.run()

21 changes: 21 additions & 0 deletions tests/apps_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,27 @@ export function interactWithTerminal(driver: any) {
});
}

export function testAnswerToCommand(driver: any, command: string, expected: string) {
return driver.wait(webdriver.until.elementLocated(webdriver.By.css('.xterm-rows>div')), TIMEOUT)
.then(function(el: webdriver.WebElement) {
return Bluebird.resolve(driver.wait(webdriver.until.elementTextContains(el, 'runs'), TIMEOUT));
})
.then(function() {
return Bluebird.resolve(
driver.wait(webdriver.until.elementLocated(webdriver.By.css('.terminal')), TIMEOUT));
})
.then(function(el: webdriver.WebElement) {
return Bluebird.resolve(el.sendKeys(command + '\n'));
})
.then(function() {
return Bluebird.resolve(
driver.wait(webdriver.until.elementLocated(webdriver.By.css('.xterm-rows')), TIMEOUT));
})
.then(function(el: webdriver.WebElement) {
return Bluebird.resolve(driver.wait(webdriver.until.elementTextContains(el, expected), TIMEOUT));
});
}

export function checkInteractionsWithTerminal(
port: number,
user: string,
Expand Down
37 changes: 37 additions & 0 deletions tests/term_env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Bluebird = require('bluebird');
import AppsHelpers = require('./apps_helpers');
import helpers = require('./helpers');
import webdriver = require('selenium-webdriver');


describe('custom environment variables', function() {
const user = 'john';
const port = 3000;
const appName = 'app1';

describe('environment variable TOTO=tata is configured', function() {
it('environment variable is set', function() {
this.timeout(5000);
const instanceId = this.mesosTaskIds[appName];
return helpers.withChrome(function(driver) {
return Bluebird.resolve(driver.get(`http://${user}:password@localhost:${port}/login/${instanceId}`))
.then(function() {
return AppsHelpers.testAnswerToCommand(driver, 'echo $TOTO', 'tata');
});
});
});
});

describe('environment variable Bad=var is configured', function() {
it('environment variable is not set', function() {
this.timeout(5000);
const instanceId = this.mesosTaskIds[appName];
return helpers.withChrome(function(driver) {
return Bluebird.resolve(driver.get(`http://${user}:password@localhost:${port}/login/${instanceId}`))
.then(function() {
return AppsHelpers.testAnswerToCommand(driver, 'echo ${Bad-not set}', 'not set');
});
});
});
});
});

0 comments on commit a9333e8

Please sign in to comment.