Implement extends

Signed-off-by: Aanand Prasad <aanand.prasad@gmail.com>
This commit is contained in:
Aanand Prasad 2015-03-18 13:51:27 -07:00
commit 4c582e4352
11 changed files with 421 additions and 28 deletions

12
tests/fixtures/extends/circle-1.yml vendored Normal file
View file

@ -0,0 +1,12 @@
foo:
image: busybox
bar:
image: busybox
web:
extends:
file: circle-2.yml
service: web
baz:
image: busybox
quux:
image: busybox

12
tests/fixtures/extends/circle-2.yml vendored Normal file
View file

@ -0,0 +1,12 @@
foo:
image: busybox
bar:
image: busybox
web:
extends:
file: circle-1.yml
service: web
baz:
image: busybox
quux:
image: busybox

6
tests/fixtures/extends/common.yml vendored Normal file
View file

@ -0,0 +1,6 @@
web:
image: busybox
command: /bin/true
environment:
- FOO=1
- BAR=1

View file

@ -0,0 +1,16 @@
myweb:
extends:
file: common.yml
service: web
command: sleep 300
links:
- "mydb:db"
environment:
# leave FOO alone
# override BAR
BAR: "2"
# add BAZ
BAZ: "2"
mydb:
image: busybox
command: sleep 300

View file

@ -0,0 +1,6 @@
webintermediate:
extends:
file: common.yml
service: web
environment:
- "FOO=2"

6
tests/fixtures/extends/nested.yml vendored Normal file
View file

@ -0,0 +1,6 @@
myweb:
extends:
file: nested-intermediate.yml
service: webintermediate
environment:
- "BAR=2"

View file

@ -427,3 +427,30 @@ class CLITestCase(DockerClientTestCase):
containers = self.project.containers(stopped=True)
self.assertEqual(len(containers), 1)
self.assertIn("FOO=1", containers[0].get('Config.Env'))
def test_up_with_extends(self):
self.command.base_dir = 'tests/fixtures/extends'
self.command.dispatch(['up', '-d'], None)
self.assertEqual(
set([s.name for s in self.project.services]),
set(['mydb', 'myweb']),
)
# Sort by name so we get [db, web]
containers = sorted(
self.project.containers(stopped=True),
key=lambda c: c.name,
)
self.assertEqual(len(containers), 2)
web = containers[1]
self.assertEqual(set(web.links()), set(['db', 'mydb_1', 'extends_mydb_1']))
expected_env = set([
"FOO=1",
"BAR=2",
"BAZ=2",
])
self.assertTrue(expected_env <= set(web.get('Config.Env')))

View file

@ -38,6 +38,8 @@ class ConfigTest(unittest.TestCase):
)
config.make_service_dict('foo', {'ports': ['8000']})
class EnvTest(unittest.TestCase):
def test_parse_environment_as_list(self):
environment =[
'NORMAL=F1',
@ -130,3 +132,112 @@ class ConfigTest(unittest.TestCase):
service_dict['environment'],
{'FILE_DEF': 'F1', 'FILE_DEF_EMPTY': '', 'ENV_DEF': 'E3', 'NO_DEF': ''},
)
class ExtendsTest(unittest.TestCase):
def test_extends(self):
service_dicts = config.load('tests/fixtures/extends/docker-compose.yml')
service_dicts = sorted(
service_dicts,
key=lambda sd: sd['name'],
)
self.assertEqual(service_dicts, [
{
'name': 'mydb',
'image': 'busybox',
'command': 'sleep 300',
},
{
'name': 'myweb',
'image': 'busybox',
'command': 'sleep 300',
'links': ['mydb:db'],
'environment': {
"FOO": "1",
"BAR": "2",
"BAZ": "2",
},
}
])
def test_nested(self):
service_dicts = config.load('tests/fixtures/extends/nested.yml')
self.assertEqual(service_dicts, [
{
'name': 'myweb',
'image': 'busybox',
'command': '/bin/true',
'environment': {
"FOO": "2",
"BAR": "2",
},
},
])
def test_circular(self):
try:
config.load('tests/fixtures/extends/circle-1.yml')
raise Exception("Expected config.CircularReference to be raised")
except config.CircularReference as e:
self.assertEqual(
[(os.path.basename(filename), service_name) for (filename, service_name) in e.trail],
[
('circle-1.yml', 'web'),
('circle-2.yml', 'web'),
('circle-1.yml', 'web'),
],
)
def test_extends_validation(self):
dictionary = {'extends': None}
load_config = lambda: config.make_service_dict('myweb', dictionary, working_dir='tests/fixtures/extends')
self.assertRaisesRegexp(config.ConfigurationError, 'dictionary', load_config)
dictionary['extends'] = {}
self.assertRaises(config.ConfigurationError, load_config)
dictionary['extends']['file'] = 'common.yml'
self.assertRaisesRegexp(config.ConfigurationError, 'service', load_config)
dictionary['extends']['service'] = 'web'
self.assertIsInstance(load_config(), dict)
dictionary['extends']['what'] = 'is this'
self.assertRaisesRegexp(config.ConfigurationError, 'what', load_config)
def test_blacklisted_options(self):
def load_config():
return config.make_service_dict('myweb', {
'extends': {
'file': 'whatever',
'service': 'web',
}
}, '.')
with self.assertRaisesRegexp(config.ConfigurationError, 'links'):
other_config = {'web': {'links': ['db']}}
with mock.patch.object(config, 'load_yaml', return_value=other_config):
print load_config()
with self.assertRaisesRegexp(config.ConfigurationError, 'volumes_from'):
other_config = {'web': {'volumes_from': ['db']}}
with mock.patch.object(config, 'load_yaml', return_value=other_config):
print load_config()
with self.assertRaisesRegexp(config.ConfigurationError, 'net'):
other_config = {'web': {'net': 'container:db'}}
with mock.patch.object(config, 'load_yaml', return_value=other_config):
print load_config()
other_config = {'web': {'net': 'host'}}
with mock.patch.object(config, 'load_yaml', return_value=other_config):
print load_config()