Repository: deis/deis

Issue:
Docker image pull hangs if latest tag does not exist
Steps to reproduce:
- deis create foo
- deis pull giorgos/masterfirefoxos

waits forever while it should return saying that no 'latest' tag exists and that user should define a tag to pull.



Discussion:
nice catch. this is odd behaviour because it'll still pull the image and think everything is all fine and dandy until it's actually deployed. There are two ways we could fix this:
1. discover that the image does not have a 'latest' tag after pulling it down and error out before the request goes to the scheduler
2. force `deis pull` to be explicit about tag `latest`

The former seems like the better solution here, IMO.

I like the second solution as well. If user does not define a tag to pull `deis pull` defaults to `latest`. 

I want to try to fix this if you think it's a good candidate for contributors. Is this part of the django controller? Any pointers / tips?

Inside the controller is a registry module for communicating with a registry. controller/registry is the path, I believe. The pull logic is somewhere in controller/api/models.py

After talking internally, we want to tackle this by being explicit about the tag in the client, which means that we'd drop support for an implied tag. In other words:

```
GOOD deis pull foo:latest
GOOD deis pull foo:someothertag
BAD deis pull foo
```

If you want to take a look into implementing this, that would be greatly appreciated!

Cool. I'll try to tackle this on Friday.

Obviously I didn't tackle this "on Friday". I don't have time to work on this atm so if anyone else is interested before I find time, feel free to take it :) 


Resolving patch:
diff --git a/client/deis.py b/client/deis.py
--- a/client/deis.py
+++ b/client/deis.py
@@ -296,6 +296,22 @@ def encode(obj):
         return obj
 
 
+def parse_repository_tag(repo):
+    """Parses a given docker image and splits the tag from the repository.
+
+    See github.com/docker/docker-py#be73aaf, lines 188-197
+    """
+    column_index = repo.rfind(':')
+    if column_index < 0:
+        return repo, None
+    tag = repo[column_index + 1:]
+    slash_index = tag.find('/')
+    if slash_index < 0:
+        return repo[:column_index], tag
+
+    return repo, None
+
+
 def readable_datetime(datetime_str):
     """
     Return a human-readable datetime string from an ECMA-262 (JavaScript)
@@ -958,8 +974,9 @@ def builds_create(self, args):
 
         Arguments:
           <image>
-            A fully-qualified docker image, either from Docker Hub (e.g. deis/example-go)
-            or from an in-house registry (e.g. myregistry.example.com:5000/example-go).
+            A fully-qualified docker image, either from Docker Hub (e.g. deis/example-go:latest)
+            or from an in-house registry (e.g. myregistry.example.com:5000/example-go:latest).
+            This image must include the tag.
 
         Options:
           -a --app=<app>
@@ -967,6 +984,10 @@ def builds_create(self, args):
           -p --procfile=<procfile>
             A YAML string used to supply a Procfile to the application.
         """
+        _, tag = parse_repository_tag(args['<image>'])
+        if tag is None:
+            self._logger.error('<image> must contain a tag')
+            sys.exit(1)
         app = args.get('--app')
         if not app:
             app = self._session.app


Test patch: