Repository: deis/deis

Issue:
deis apps:run can't handle unicode output?
I'm using a pretty basic command, that was working under deis 1.0.2, but now with 1.1.1:

``` shell
$ deis run -- "CSV_IMPORT_ID=17994 rake tracking:groupon"
Running `CSV_IMPORT_ID=17994 rake tracking:groupon`...
Traceback (most recent call last):
  File "<string>", line 2096, in <module>
  File "<string>", line 2092, in main
  File "<string>", line 2035, in _dispatch_cmd
  File "<string>", line 672, in apps_run
UnicodeEncodeError: 'ascii' codec can't encode characters in position 4098-4101: ordinal not in range(128)
```

~~It appears to not like the underscores I'm using.~~



Discussion:
Ah, it's not the input - it's the output that's causing the issue.
It's unicode. I'll find some way to pull the example returned data and update

Looks like https://github.com/deis/deis/blob/b3fbc166befc68d4282b5f600b02582ba676fe98/client/deis.py#L672 doesn't accept unicode as input?

I've got the string `EsmÃƒÂ©` in my response which throws the error.
If this unicode isn't present the response is as expected.

So the fix is pretty simple (we already have an [`encode`](https://github.com/deis/deis/blob/b3fbc166befc68d4282b5f600b02582ba676fe98/client/deis.py#L296-L301) function to wrap the response format in), but we need to go through the client code and identify any places where we could get a UTF-8 response.


Resolving patch:
diff --git a/client/deis.py b/client/deis.py
--- a/client/deis.py
+++ b/client/deis.py
@@ -680,7 +680,7 @@ def apps_run(self, args):
                                   json.dumps(body))
         if response.status_code == requests.codes.ok:
             rc, output = json.loads(response.content)
-            sys.stdout.write(output)
+            sys.stdout.write(encode(output))
             sys.stdout.flush()
             sys.exit(rc)
         else:
diff --git a/controller/scheduler/fleet.py b/controller/scheduler/fleet.py
--- a/controller/scheduler/fleet.py
+++ b/controller/scheduler/fleet.py
@@ -116,6 +116,9 @@ def _create_container(self, name, image, command, unit, **kwargs):
         entrypoint = kwargs.get('entrypoint')
         if entrypoint:
             l.update({'entrypoint': '{}'.format(entrypoint)})
+        # encode command as utf-8
+        if isinstance(l.get('command'), basestring):
+            l['command'] = l['command'].encode('utf-8')
         # construct unit from template
         for f in unit:
             f['value'] = f['value'].format(**l)


Test patch:
diff --git a/tests/apps_test.go b/tests/apps_test.go
--- a/tests/apps_test.go
+++ b/tests/apps_test.go
@@ -15,7 +15,7 @@ var (
 	appsCreateCmdNoRemote  = "apps:create {{.AppName}} --no-remote"
 	appsCreateCmdBuildpack = "apps:create {{.AppName}} --buildpack https://example.com"
 	appsListCmd            = "apps:list"
-	appsRunCmd             = "apps:run echo hello"
+	appsRunCmd             = "apps:run echo Hello, 世界"
 	appsOpenCmd            = "apps:open --app={{.AppName}}"
 	appsLogsCmd            = "apps:logs --app={{.AppName}}"
 	appsInfoCmd            = "apps:info --app={{.AppName}}"
@@ -111,7 +111,7 @@ func appsRunTest(t *testing.T, params *utils.DeisTestConfig) {
 	if err := utils.Chdir(params.ExampleApp); err != nil {
 		t.Fatal(err)
 	}
-	utils.Execute(t, cmd, params, false, "hello")
+	utils.CheckList(t, cmd, params, "Hello, 世界", false)
 	utils.Execute(t, "apps:run env", params, true, "GIT_SHA")
 	// run a REALLY large command to test https://github.com/deis/deis/issues/2046
 	largeString := randomString(1024)