Compare commits

...

24 Commits
0.3.0 ... 0.3.2

Author SHA1 Message Date
Aanand Prasad
9164125177 Merge pull request #146 from orchardup/ship-0.3.2
Ship 0.3.2
2014-03-05 14:49:26 +00:00
Ben Firshman
2595f89519 Ship 0.3.2 2014-03-05 14:33:32 +00:00
Ben Firshman
a058c40dfb Merge pull request #143 from orchardup/expose-option
Support 'expose' config option, like docker's --expose
2014-03-05 14:30:17 +00:00
Ben Firshman
fc4b3d2771 Merge pull request #145 from marksteve/run-rm
Add option to remove container in `docker run` (Closes #137)
2014-03-05 11:58:44 +00:00
Mark Steve Samson
59cc9c9b68 Add option to remove container in docker run (Closes #137) 2014-03-05 09:03:06 +08:00
Aanand Prasad
d1a52d2b1a Remove unneeded 'ports' entries from WP and Django fig.ymls in docs 2014-03-04 21:54:10 +00:00
Aanand Prasad
5f5fbb3ea4 Display unpublished ports in 'fig ps' 2014-03-04 18:07:06 +00:00
Aanand Prasad
2d98071e55 Support 'expose' config option, like docker's --expose
Exposes ports to linked services without publishing them to the world.
2014-03-04 18:06:52 +00:00
Aanand Prasad
6a3d1d06b5 Check NetworkSettings.Ports instead of HostConfig.PortBindings in tests
The latter appears to be unreliable.
2014-03-04 17:58:42 +00:00
Ben Firshman
6813cb86a2 Update version in installation docs 2014-03-04 11:53:16 +00:00
Ben Firshman
f5cf9b60b2 Remove venv before building on OS X 2014-03-04 11:51:12 +00:00
Aanand Prasad
7cec029f03 Merge pull request #141 from orchardup/ship-0.3.1
Ship 0.3.1
2014-03-04 11:47:36 +00:00
Ben Firshman
4fbad941cb Ship 0.3.1 2014-03-04 11:40:39 +00:00
Aanand Prasad
d4bff56a61 Merge pull request #140 from orchardup/fix-ps-on-docker-0.8.1-with-no-command
Fix ps on Docker 0.8.1 when there is no command
2014-03-04 11:37:15 +00:00
Ben Firshman
f430b82b43 Fix ps on Docker 0.8.1 when there is no command
Fixes #138
2014-03-04 11:27:55 +00:00
Ben Firshman
71533791dd Merge pull request #139 from orchardup/fix-delete-volume
Fix delete volume
2014-03-04 11:19:35 +00:00
Ben Firshman
65f3411320 Merge pull request #133 from kvz/contributingdocs
Add a contributing page. Refs #123
2014-03-04 11:07:52 +00:00
Kevin van Zonneveld
b92651070f Add steps for contributing to README 2014-03-04 12:05:38 +01:00
Ben Firshman
5be8a37b7e Pass through standard remove_container options 2014-03-04 11:00:09 +00:00
Ben Firshman
044c348faf Add test for fig rm 2014-03-04 11:00:09 +00:00
Ben Firshman
465c7d569c Improve CLI test names 2014-03-04 11:00:09 +00:00
Ben Firshman
2ca0e7954a Add --force option to fig rm 2014-03-04 11:00:06 +00:00
Mark Steve Samson
96a92a73f1 Fix KeyError when -v is not specified in fig rm 2014-03-04 13:13:23 +08:00
Ben Firshman
48e7b4b0a6 Remove Python 3 from Travis
Let's not kid ourselves.
2014-03-03 19:21:27 +00:00
14 changed files with 83 additions and 30 deletions

View File

@@ -2,8 +2,6 @@ language: python
python:
- '2.6'
- '2.7'
- '3.2'
- '3.3'
env:
- DOCKER_VERSION=0.8.0
- DOCKER_VERSION=0.8.1

View File

@@ -1,6 +1,19 @@
Change log
==========
0.3.2 (2014-03-05)
------------------
- Added an `--rm` option to `fig run`. (Thanks @marksteve!)
- Added an `expose` option to `fig.yml`.
0.3.1 (2014-03-04)
------------------
- Added contribution instructions. (Thanks @kvz!)
- Fixed `fig rm` throwing an error.
- Fixed a bug in `fig ps` on Docker 0.8.1 when there is a container with no command.
0.3.0 (2014-03-03)
------------------

View File

@@ -60,3 +60,16 @@ Building OS X binaries
Note that this only works on Mountain Lion, not Mavericks, due to a [bug in PyInstaller](http://www.pyinstaller.org/ticket/807).
Contributing to Fig
-------------------
If you're looking contribute to [Fig](http://orchardup.github.io/fig/)
but you're new to the project or maybe even to Python, here are the steps
that should get you started.
1. Fork [https://github.com/orchardup/fig](https://github.com/orchardup/fig) to your username. kvz in this example.
1. Clone your forked repository locally `git clone git@github.com:kvz/fig.git`.
1. Enter the local directory `cd fig`.
1. Set up a development environment `python setup.py develop`. That will install the dependencies and set up a symlink from your `fig` executable to the checkout of the repo. So from any of your fig projects, `fig` now refers to your development project. Time to start hacking : )
1. Works for you? Run the test suite via `./scripts/test` to verify it won't break other usecases.
1. All good? Commit and push to GitHub, and submit a pull request.

View File

@@ -28,8 +28,6 @@ Simple enough. Finally, this is all tied together with a file called `fig.yml`.
db:
image: orchardup/postgresql
ports:
- "5432"
web:
build: .
command: python manage.py runserver 0.0.0.0:8000

View File

@@ -16,12 +16,12 @@ Docker has guides for [Ubuntu](http://docs.docker.io/en/latest/installation/ubun
Next, install Fig. On OS X:
$ curl -L https://github.com/orchardup/fig/releases/download/0.3.0/darwin > /usr/local/bin/fig
$ curl -L https://github.com/orchardup/fig/releases/download/0.3.1/darwin > /usr/local/bin/fig
$ chmod +x /usr/local/bin/fig
On 64-bit Linux:
$ curl -L https://github.com/orchardup/fig/releases/download/0.3.0/linux > /usr/local/bin/fig
$ curl -L https://github.com/orchardup/fig/releases/download/0.3.1/linux > /usr/local/bin/fig
$ chmod +x /usr/local/bin/fig
Fig is also available as a Python package if you're on another platform (or if you prefer that sort of thing):

View File

@@ -33,8 +33,6 @@ web:
- .:/code
db:
image: orchardup/mysql
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: wordpress
```

View File

@@ -44,6 +44,12 @@ ports:
- "8000:8000"
- "49100:22"
-- Expose ports without publishing them to the host machine - they'll only be
-- accessible to linked services. Only the internal port can be specified.
expose:
- "3000"
- "8000"
-- Map volumes from the host machine (HOST:CONTAINER).
volumes:
- cache/:/tmp/cache

View File

@@ -1,4 +1,4 @@
from __future__ import unicode_literals
from .service import Service
__version__ = '0.3.0'
__version__ = '0.3.2'

View File

@@ -170,19 +170,23 @@ class TopLevelCommand(Command):
"""
Remove stopped service containers.
Usage: rm [SERVICE...]
Usage: rm [options] [SERVICE...]
Options:
-v Remove volumes associated with containers
--force Don't ask to confirm removal
-v Remove volumes associated with containers
"""
all_containers = self.project.containers(service_names=options['SERVICE'], stopped=True)
stopped_containers = [c for c in all_containers if not c.is_running]
if len(stopped_containers) > 0:
print("Going to remove", list_containers(stopped_containers))
if yesno("Are you sure? [yN] ", default=False):
self.project.remove_stopped(service_names=options['SERVICE'],
remove_volumes=options['-v'])
if options.get('--force') \
or yesno("Are you sure? [yN] ", default=False):
self.project.remove_stopped(
service_names=options['SERVICE'],
v=options.get('-v', False)
)
else:
print("No stopped containers")
@@ -205,6 +209,7 @@ class TopLevelCommand(Command):
container name
-T Disable pseudo-tty allocation. By default `fig run`
allocates a TTY.
--rm Remove container after run. Ignored in detached mode.
"""
service = self.project.get_service(options['SERVICE'])
@@ -225,6 +230,10 @@ class TopLevelCommand(Command):
with self._attach_to_container(container.id, raw=tty) as c:
service.start_container(container, ports=None)
c.run()
if options['--rm']:
container.wait()
log.info("Removing %s..." % container.name)
self.client.remove_container(container.id)
def scale(self, options):
"""

View File

@@ -70,6 +70,8 @@ class Container(object):
for private, public in list(self.dictionary['NetworkSettings']['Ports'].items()):
if public:
ports.append('%s->%s' % (public[0]['HostPort'], private))
else:
ports.append(private)
return ', '.join(ports)
@property
@@ -86,7 +88,10 @@ class Container(object):
@property
def human_readable_command(self):
self.inspect_if_not_inspected()
return ' '.join(self.dictionary['Config']['Cmd'])
if self.dictionary['Config']['Cmd']:
return ' '.join(self.dictionary['Config']['Cmd'])
else:
return ''
@property
def environment(self):
@@ -112,8 +117,7 @@ class Container(object):
return self.client.kill(self.id)
def remove(self, **options):
v = options.get('remove_volumes', False)
return self.client.remove_container(self.id, v=v)
return self.client.remove_container(self.id, **options)
def inspect_if_not_inspected(self):
if not self.has_been_inspected:

View File

@@ -39,7 +39,7 @@ class Service(object):
if 'image' in options and 'build' in options:
raise ConfigError('Service %s has both an image and build path specified. A service can either be built to image or use an existing image, not both.' % name)
supported_options = DOCKER_CONFIG_KEYS + ['build']
supported_options = DOCKER_CONFIG_KEYS + ['build', 'expose']
for k in options:
if k not in supported_options:
@@ -246,9 +246,10 @@ class Service(object):
container_options['name'] = self.next_container_name(one_off)
if 'ports' in container_options:
if 'ports' in container_options or 'expose' in self.options:
ports = []
for port in container_options['ports']:
all_ports = container_options.get('ports', []) + self.options.get('expose', [])
for port in all_ports:
port = str(port)
if ':' in port:
port = port.split(':')[-1]

View File

@@ -1,5 +1,6 @@
#!/bin/bash
set -ex
rm -r venv
virtualenv venv
venv/bin/pip install pyinstaller==2.1
venv/bin/pip install .

View File

@@ -32,7 +32,7 @@ class CLITestCase(DockerClientTestCase):
self.assertIn('fig_simple_1', mock_stdout.getvalue())
@patch('sys.stdout', new_callable=StringIO)
def test_default_figfile(self, mock_stdout):
def test_ps_default_figfile(self, mock_stdout):
self.command.base_dir = 'tests/fixtures/multiple-figfiles'
self.command.dispatch(['up', '-d'], None)
self.command.dispatch(['ps'], None)
@@ -43,7 +43,7 @@ class CLITestCase(DockerClientTestCase):
self.assertNotIn('fig_yetanother_1', output)
@patch('sys.stdout', new_callable=StringIO)
def test_alternate_figfile(self, mock_stdout):
def test_ps_alternate_figfile(self, mock_stdout):
self.command.base_dir = 'tests/fixtures/multiple-figfiles'
self.command.dispatch(['-f', 'fig2.yml', 'up', '-d'], None)
self.command.dispatch(['-f', 'fig2.yml', 'ps'], None)
@@ -53,6 +53,14 @@ class CLITestCase(DockerClientTestCase):
self.assertNotIn('fig_another_1', output)
self.assertIn('fig_yetanother_1', output)
def test_rm(self):
service = self.command.project.get_service('simple')
service.create_container()
service.kill()
self.assertEqual(len(service.containers(stopped=True)), 1)
self.command.dispatch(['rm', '--force'], None)
self.assertEqual(len(service.containers(stopped=True)), 0)
def test_scale(self):
project = self.command.project
@@ -74,4 +82,3 @@ class CLITestCase(DockerClientTestCase):
self.command.scale({'SERVICE=NUM': ['simple=0', 'another=0']})
self.assertEqual(len(project.get_service('simple').containers()), 0)
self.assertEqual(len(project.get_service('another').containers()), 0)

View File

@@ -209,25 +209,30 @@ class ServiceTest(DockerClientTestCase):
def test_start_container_creates_ports(self):
service = self.create_service('web', ports=[8000])
container = service.start_container().inspect()
self.assertEqual(list(container['HostConfig']['PortBindings'].keys()), ['8000/tcp'])
self.assertNotEqual(container['HostConfig']['PortBindings']['8000/tcp'][0]['HostPort'], '8000')
self.assertEqual(list(container['NetworkSettings']['Ports'].keys()), ['8000/tcp'])
self.assertNotEqual(container['NetworkSettings']['Ports']['8000/tcp'][0]['HostPort'], '8000')
def test_expose_does_not_publish_ports(self):
service = self.create_service('web', expose=[8000])
container = service.start_container().inspect()
self.assertEqual(container['NetworkSettings']['Ports'], {'8000/tcp': None})
def test_start_container_creates_port_with_explicit_protocol(self):
service = self.create_service('web', ports=['8000/udp'])
container = service.start_container().inspect()
self.assertEqual(list(container['HostConfig']['PortBindings'].keys()), ['8000/udp'])
self.assertEqual(list(container['NetworkSettings']['Ports'].keys()), ['8000/udp'])
def test_start_container_creates_fixed_external_ports(self):
service = self.create_service('web', ports=['8000:8000'])
container = service.start_container().inspect()
self.assertIn('8000/tcp', container['HostConfig']['PortBindings'])
self.assertEqual(container['HostConfig']['PortBindings']['8000/tcp'][0]['HostPort'], '8000')
self.assertIn('8000/tcp', container['NetworkSettings']['Ports'])
self.assertEqual(container['NetworkSettings']['Ports']['8000/tcp'][0]['HostPort'], '8000')
def test_start_container_creates_fixed_external_ports_when_it_is_different_to_internal_port(self):
service = self.create_service('web', ports=['8001:8000'])
container = service.start_container().inspect()
self.assertIn('8000/tcp', container['HostConfig']['PortBindings'])
self.assertEqual(container['HostConfig']['PortBindings']['8000/tcp'][0]['HostPort'], '8001')
self.assertIn('8000/tcp', container['NetworkSettings']['Ports'])
self.assertEqual(container['NetworkSettings']['Ports']['8000/tcp'][0]['HostPort'], '8001')
def test_scale(self):
service = self.create_service('web')