Skip to content

Commit 69e6083

Browse files
author
Matthew Fisher
committed
Merge pull request #2605 from bacongobbler/fix-get-command
feat(controller): send procfile entries to scheduler
2 parents a428f13 + 93495aa commit 69e6083

14 files changed

Lines changed: 173 additions & 27 deletions

File tree

client/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
build: setup-venv
3-
venv/bin/pip install docopt==0.6.2 python-dateutil==2.2 requests==2.4.3 pyinstaller==2.1 termcolor==1.1.0
3+
venv/bin/pip install docopt==0.6.2 python-dateutil==2.2 PyYAML==3.11 requests==2.4.3 pyinstaller==2.1 termcolor==1.1.0
44
venv/bin/pyinstaller deis.spec
55
chmod +x dist/deis
66

client/README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ you used to provision the server. You can make a symlink or shell alias for
7575

7676
.. code-block:: console
7777
78-
$ pip install docopt==0.6.2 python-dateutil==2.2 requests==2.4.3 termcolor==1.1.0
78+
$ pip install docopt==0.6.2 python-dateutil==2.2 PyYAML==3.11 requests==2.4.3 termcolor==1.1.0
7979
$ sudo ln -fs $(pwd)/client/deis.py /usr/local/bin/deis
8080
$ deis
8181
Usage: deis <command> [<args>...]

client/deis.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import time
6060
import urlparse
6161
import webbrowser
62+
import yaml
6263

6364
from dateutil import parser
6465
from dateutil import relativedelta
@@ -878,7 +879,8 @@ def builds(self, args):
878879
def builds_create(self, args):
879880
"""
880881
Creates a new build of an application. Imports an <image> and deploys it to Deis
881-
as a new release.
882+
as a new release. If a Procfile is present in the current directory, it will be used
883+
as the default process types for this application.
882884
883885
Usage: deis builds:create <image> [options]
884886
@@ -890,11 +892,28 @@ def builds_create(self, args):
890892
Options:
891893
-a --app=<app>
892894
The uniquely identifiable name for the application.
895+
-p --procfile=<procfile>
896+
A YAML string used to supply a Procfile to the application.
893897
"""
894898
app = args.get('--app')
895899
if not app:
896900
app = self._session.app
897901
body = {'image': args['<image>']}
902+
procfile = args.get('--procfile')
903+
if procfile:
904+
try:
905+
body['procfile'] = yaml.load(procfile)
906+
except yaml.YAMLError:
907+
self._logger.error('could not parse --procfile')
908+
sys.exit(1)
909+
else:
910+
# read in Procfile for default process types
911+
if os.path.exists('Procfile'):
912+
try:
913+
body['procfile'] = yaml.load(open('Procfile'))
914+
except yaml.YAMLError:
915+
self._logger.error('could not parse Procfile')
916+
sys.exit(1)
898917
sys.stdout.write('Creating build... ')
899918
sys.stdout.flush()
900919
try:

client/setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@
5757
],
5858
long_description=LONG_DESCRIPTION,
5959
install_requires=[
60-
'docopt==0.6.2', 'python-dateutil==2.2', 'requests==2.4.3', 'termcolor==1.1.0'
60+
'docopt==0.6.2', 'python-dateutil==2.2',
61+
'PyYAML==3.11', 'requests==2.4.3',
62+
'termcolor==1.1.0'
6163
],
6264
zip_safe=True,
6365
**KWARGS)

controller/api/models.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,11 @@ def _get_command(self):
404404
# handle special case for Dockerfile deployments
405405
if self.type == 'cmd':
406406
return ''
407-
else:
407+
try:
408+
# ensure they cannot break out and run commands on the host
409+
return "bash -c '{}'".format(self.release.build.procfile[self.type])
410+
# if the key is not present or if a parent attribute is None
411+
except (KeyError, TypeError):
408412
return 'start {}'.format(self.type)
409413

410414
_command = property(_get_command)

controller/api/tests/test_container.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,3 +435,36 @@ def test_scale_without_build_should_error(self):
435435
HTTP_AUTHORIZATION='token {}'.format(self.token))
436436
self.assertEqual(response.status_code, 400)
437437
self.assertEqual(response.data, "No build associated with this release")
438+
439+
def test_command_good(self):
440+
"""Test the default command for each container workflow"""
441+
url = '/v1/apps'
442+
response = self.client.post(url, HTTP_AUTHORIZATION='token {}'.format(self.token))
443+
self.assertEqual(response.status_code, 201)
444+
app_id = response.data['id']
445+
app = App.objects.get(id=app_id)
446+
user = User.objects.get(username='autotest')
447+
build = Build.objects.create(owner=user,
448+
app=app,
449+
image="qwerty",
450+
procfile={'web': 'node server.js',
451+
'worker': 'node worker.js'})
452+
# create an initial release
453+
release = Release.objects.create(version=2,
454+
owner=user,
455+
app=app,
456+
config=app.config_set.latest(),
457+
build=build)
458+
# create a container
459+
c = Container.objects.create(owner=user,
460+
app=app,
461+
release=release,
462+
type='web',
463+
num=1)
464+
self.assertEqual(c._command, "bash -c 'node server.js'")
465+
c.type = 'worker'
466+
self.assertEqual(c._command, "bash -c 'node worker.js'")
467+
c.release.build.procfile = None
468+
self.assertEqual(c._command, 'start worker')
469+
c.type = 'cmd'
470+
self.assertEqual(c._command, '')

docs/docs_requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ gunicorn==19.1.1
1919
paramiko==1.14.1
2020
psycopg2==2.5.4
2121
python-etcd==0.3.2
22+
PyYAML==3.11
2223
South==1.0.1
2324

2425
# Deis client requirements

docs/using_deis/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Using Deis
1515
install-client
1616
register-user
1717
deploy-application
18+
process-types
1819
using-buildpacks
1920
using-dockerfiles
2021
using-docker-images

docs/using_deis/process-types.rst

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
:title: Process Types and the Procfile
2+
:description: First steps for using the 12 factor process model with Deis.
3+
4+
.. _process-types:
5+
6+
Process Types and the Procfile
7+
==============================
8+
9+
A Procfile is a mechanism for declaring what commands are run by your application’s containers on
10+
the Deis platform. It follows the `process model`_. You can use a Procfile to declare various
11+
process types, such as multiple types of workers, a singleton process like a clock, or a consumer
12+
of the Twitter streaming API.
13+
14+
Process Types as Templates
15+
--------------------------
16+
17+
A Procfile is a text file named ``Procfile`` placed in the root of your application that lists the
18+
process types in an application. Each process type is a declaration of a command that is executed
19+
when a container of that process type is started.
20+
21+
All the language and frameworks using :ref:`Heroku's Buildpacks <using-buildpacks>` declare a
22+
``web`` process type, which starts the application server. Rails 3 has the following process type:
23+
24+
.. code-block:: console
25+
26+
web: bundle exec rails server -p $PORT
27+
28+
All applications using :ref:`Dockerfile deployments <using-dockerfiles>` have an implied ``cmd``
29+
process type, which spawns the default process of a Docker image:
30+
31+
.. code-block:: console
32+
33+
$ cat Dockerfile
34+
FROM centos:latest
35+
COPY . /app
36+
WORKDIR /app
37+
CMD python -m SimpleHTTPServer 5000
38+
EXPOSE 5000
39+
40+
For applications using :ref:`Docker image deployments <using-docker-images>`, a ``cmd`` process
41+
type is also implied and spawns the default process of the image.
42+
43+
Declaring Process Types
44+
-----------------------
45+
46+
Process types are declared via a file named ``Procfile``, placed in the root of your app. Its
47+
format is one process type per line, with each line containing:
48+
49+
.. code-block:: console
50+
51+
<process type>: <command>
52+
53+
The syntax is defined as:
54+
55+
``<process type>`` – an alphanumeric string, is a name for your command, such as web, worker, urgentworker, clock, etc.
56+
57+
``<command>`` – a command line to launch the process, such as ``rake jobs:work``.
58+
59+
.. note::
60+
61+
The web and cmd process types are special as they’re the only process types that will receive
62+
HTTP traffic from Deis’s routers. Other process types can be named arbitrarily.
63+
64+
Deploying to Deis
65+
-----------------
66+
67+
A ``Procfile`` is not necessary to deploy most languages supported by Deis. The platform
68+
automatically detects the language and supplies a default ``web`` process type to boot the server.
69+
70+
Creating an explicit Procfile is recommended for greater control and flexibility over your app.
71+
72+
For Deis to use your Procfile, add the Procfile to the root of your application, then push to Deis:
73+
74+
.. code-block:: console
75+
76+
$ git add .
77+
$ git commit -m "Procfile"
78+
$ git push deis master
79+
...
80+
-----> Procfile declares process types: web, worker
81+
Compiled slug size is 10.4MB
82+
83+
Launching... done, v2
84+
85+
-----> unisex-huntress deployed to Deis
86+
http://unisex-huntress.example.com
87+
88+
For Docker image deployments, a Procfile in the current directory or specified by
89+
``deis push --procfile`` will define the default process types for the application.
90+
91+
.. _`process model`: https://devcenter.heroku.com/articles/process-model

docs/using_deis/using-docker-images.rst

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,6 @@ Because you are deploying a Docker image, the ``cmd`` process type is automatica
7272

7373
Support for Docker registry authentication is coming soon
7474

75-
Define Process Types
76-
--------------------
77-
Docker containers have a default command usually specified by a `CMD instruction`_.
78-
Deis uses the ``cmd`` process type to refer to this default command.
79-
80-
Process types other than ``cmd`` are not supported when using Docker images.
81-
8275

8376
.. _`Docker Image`: https://docs.docker.com/introduction/understanding-docker/
8477
.. _`DockerHub`: https://registry.hub.docker.com/

0 commit comments

Comments
 (0)