Repository: deis/deis

Issue:
Units have the registry ip hardcoded
Today all unit files have the registry ip hardcoded. Example:

```
$ fleetctl cat example_v3.web.2.service

[Unit]
Description=example_v3.web.2

[Service]
ExecStartPre=/usr/bin/docker pull 10.237.160.37:5000/example:v3
ExecStartPre=/bin/sh -c "docker inspect example_v3.web.2 >/dev/null 2>&1 && docker rm -f example_v3.web.2 || true"
ExecStart=/bin/sh -c "port=$(docker inspect -f '{{range $k, $v := .config.ExposedPorts }}{{$k}}{{end}}' 10.237.160.37:5000/example:v3 | cut -d/ -f1) ; /usr/bin/docker run --name example_v3.web.2 -P -e PORT=$port 10.237.160.37:5000/example:v3 start web"
ExecStartPost=/bin/sh -c "until docker inspect example_v3.web.2 >/dev/null 2>&1; do sleep 1; done";     /bin/sh -c "arping -Idocker0 -c1 `docker inspect -f '{{ .NetworkSettings.IPAddress }}' example_v3.web.2`"
ExecStop=/usr/bin/docker rm -f example_v3.web.2
TimeoutStartSec=20m
```

This would make all units fail to deploy when the registry is moving hosts. Maybe fetch the registry ip on scheduling from etcd like the custom images https://github.com/deis/deis/pull/1123?



Discussion:
Yep, this is definitely an issue. We'll have to patch this separately.

Sounds good, I just referenced the issue as the same technique could be used to fix this one.

@carmstrong could we use something similar to the functions that you defined for https://github.com/deis/deis/pull/1123? Either that or we could call etcdctl directly from the unit file to retrieve the registry host/port. This change will affect how the controller stores the app image in the database, because `app.release.image` is what's templated out to the scheduler (see https://github.com/deis/deis/blob/master/controller/api/models.py#L447 and https://github.com/deis/deis/blob/master/controller/api/models.py#L312).

@bacongobbler I think we could probably just call etcd in the unitfile, unless it starts to look clunky. 

using an external registry can solve it for the time being maybe?


Resolving patch:
diff --git a/controller/api/models.py b/controller/api/models.py
--- a/controller/api/models.py
+++ b/controller/api/models.py
@@ -469,8 +469,7 @@ def new(self, user, config=None, build=None, summary=None, source_version='lates
         new_version = self.version + 1
         tag = 'v{}'.format(new_version)
         release_image = '{}:{}'.format(self.app.id, tag)
-        target_image = '{}:{}/{}'.format(
-            settings.REGISTRY_HOST, settings.REGISTRY_PORT, self.app.id)
+        target_image = '{}'.format(self.app.id)
         # create new release and auto-increment version
         release = Release.objects.create(
             owner=user, app=self.app, config=config,
diff --git a/controller/scheduler/coreos.py b/controller/scheduler/coreos.py
--- a/controller/scheduler/coreos.py
+++ b/controller/scheduler/coreos.py
@@ -222,9 +222,9 @@ def attach(self, name):
 Description={name}
 
 [Service]
-ExecStartPre=/usr/bin/docker pull {image}
+ExecStartPre=/bin/sh -c "IMAGE=`/run/deis/bin/determine_registry {image}`; docker pull $IMAGE"
 ExecStartPre=/bin/sh -c "docker inspect {name} >/dev/null 2>&1 && docker rm -f {name} || true"
-ExecStart=/bin/sh -c "port=$(docker inspect -f '{{{{range $k, $v := .ContainerConfig.ExposedPorts }}}}{{{{$k}}}}{{{{end}}}}' {image} | cut -d/ -f1) ; docker run --name {name} -P -e PORT=$port {image} {command}"
+ExecStart=/bin/sh -c "IMAGE=`/run/deis/bin/determine_registry {image}`; port=$(docker inspect -f '{{{{range $k, $v := .ContainerConfig.ExposedPorts }}}}{{{{$k}}}}{{{{end}}}}' $IMAGE | cut -d/ -f1) ; docker run --name {name} -P -e PORT=$port $IMAGE {command}"
 ExecStop=/usr/bin/docker rm -f {name}
 TimeoutStartSec=20m
 """


Test patch:
diff --git a/controller/api/tests/test_hooks.py b/controller/api/tests/test_hooks.py
--- a/controller/api/tests/test_hooks.py
+++ b/controller/api/tests/test_hooks.py
@@ -116,7 +116,7 @@ def test_build_hook(self):
         url = '/api/hooks/builds'.format(**locals())
         body = {'receive_user': 'autotest',
                 'receive_repo': app_id,
-                'image': 'registry.local:5000/{app_id}:v2'.format(**locals())}
+                'image': '{app_id}:v2'.format(**locals())}
         # post the build without a session
         self.assertIsNone(self.client.logout())
         response = self.client.post(url, json.dumps(body), content_type='application/json')
@@ -142,7 +142,7 @@ def test_build_hook_procfile(self):
         SHA = 'ecdff91c57a0b9ab82e89634df87e293d259a3aa'
         body = {'receive_user': 'autotest',
                 'receive_repo': app_id,
-                'image': 'registry.local:5000/{app_id}:v2'.format(**locals()),
+                'image': '{app_id}:v2'.format(**locals()),
                 'sha': SHA,
                 'procfile': PROCFILE}
         # post the build without a session
@@ -191,7 +191,7 @@ def test_build_hook_dockerfile(self):
         """
         body = {'receive_user': 'autotest',
                 'receive_repo': app_id,
-                'image': 'registry.local:5000/{app_id}:v2'.format(**locals()),
+                'image': '{app_id}:v2'.format(**locals()),
                 'sha': SHA,
                 'dockerfile': DOCKERFILE}
         # post the build without a session