{"action":"created","comment":{"url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/comments/34749303","id":34749303,"diff_hunk":"@@ -0,0 +1,332 @@\n+import assert from 'assert';\n+import base from 'taskcluster-base';\n+import cmd from './helper/cmd';\n+import crypto from 'crypto';\n+import Debug from 'debug';\n+import {DockerExecClient} from 'docker-exec-websocket-server';\n+import DockerWorker from '../dockerworker';\n+import https from 'https';\n+import TestWorker from '../testworker';\n+import Promise from 'promise';\n+import * as settings from '../settings';\n+import slugid from 'slugid';\n+\n+suite('use docker exec websocket server', () => {\n+  let debug = Debug('docker-worker:test:interactive-test');\n+\n+  let worker;\n+  // If taskcluster/artifact upload is under high load, this number needs to be adjusted up.\n+  // It also causes the test to be slower by 2X that many seconds, so be careful with this.\n+  // TODO: add polling to tests so they don't rely as much on this type of timing\n+  let maxTime = 45; \n+  let expTime = 10;\n+  setup(async () => {\n+    settings.cleanup();\n+    settings.configure({\n+      interactive: {\n+        ssl: true,\n+        maxTime: maxTime,\n+        expirationAfterSession: expTime\n+      }\n+    });\n+    worker = new TestWorker(DockerWorker);\n+    await worker.launch();\n+  });\n+\n+  teardown(async () => {\n+    if (worker) {\n+      await worker.terminate();\n+      worker = null;\n+    }\n+    settings.cleanup();\n+  });\n+\n+  async function getWithoutRedirect (url) {\n+    let res = await new Promise((resolve, reject) => {\n+      https.request(url, (r) => {\n+        resolve(r);\n+      }).end();\n+    });\n+    return res.headers.location;\n+  };\n+\n+  test('expires', async () => {\n+    let taskId = slugid.v4();\n+    let task = {\n+      payload: {\n+        image: 'taskcluster/test-ubuntu',\n+        command: cmd('sleep 1'),\n+        maxRunTime: 4 * 60,\n+        features: {\n+          interactive: true\n+        }\n+      }\n+    };\n+    debug('posting to queue');\n+    worker.postToQueue(task, taskId);\n+\n+    let signedUrl = worker.queue.buildSignedUrl(\n+      worker.queue.getLatestArtifact,\n+      taskId,\n+      'private/mozilla/interactive.sock',\n+      {expiration: 60 * 5});\n+\n+    let url;\n+    await base.testing.poll(async () => {\n+      url = await getWithoutRedirect(signedUrl);\n+      assert(url, 'artifact not found');\n+    }, 20, 1000);\n+\n+    let client = new DockerExecClient({\n+      tty: false,\n+      command: ['pwd'],\n+      url: url,\n+      wsopts: {rejectUnauthorized: false}\n+    });\n+    let connected = false;\n+\n+    //check for proper connection\n+    //should still be alive here\n+    await client.execute();\n+    client.stdout.on('data', (message) => {\n+      assert(message[0] === 0x2f); // is a slash, as expected of pwd\n+      connected = true;\n+      client.close();\n+    });\n+\n+    await base.testing.sleep(maxTime * 1000 + 10000);\n+    //should be dead here\n+    let dead = true;\n+    let failClient = new DockerExecClient({\n+      tty: false,\n+      command: ['echo'],\n+      url: url,\n+      wsopts: {rejectUnauthorized: false}\n+    });\n+    failClient.on('resumed', () => {\n+      dead = false;\n+    });\n+    await failClient.execute();\n+    await base.testing.sleep(3000);\n+\n+    assert(dead, 'interactive session still available when it should have expired');\n+    assert(connected, 'interactive session failed to connect');\n+  });\n+\n+  test('stays alive', async () => {\n+    worker = new TestWorker(DockerWorker);\n+    await worker.launch();\n+\n+    let taskId = slugid.v4();\n+    let task = {\n+      payload: {\n+        image: 'taskcluster/test-ubuntu',\n+        command: cmd('echo hello'),\n+        maxRunTime: 4 * 60,\n+        features: {\n+          interactive: true\n+        }\n+      }\n+    };\n+    debug('posting to queue');\n+    worker.postToQueue(task, taskId);\n+\n+    let signedUrl = worker.queue.buildSignedUrl(\n+      worker.queue.getLatestArtifact,\n+      taskId,\n+      'private/mozilla/interactive.sock',\n+      {expiration: 60 * 5});\n+\n+    let url;\n+    await base.testing.poll(async () => {\n+      url = await getWithoutRedirect(signedUrl);\n+      assert(url, 'artifact not found');\n+    }, 20, 1000);\n+\n+    let client = new DockerExecClient({\n+      tty: false,\n+      command: ['cat'],\n+      url: url,\n+      wsopts: {rejectUnauthorized: false}\n+    });\n+    let connected = false;\n+\n+    //check for proper connection\n+    //should still be alive here\n+    await client.execute();\n+    client.stdin.write('a\\n');\n+    client.stdout.on('data', (message) => {\n+      assert(message[0] === 0x61);\n+      assert(message[1] === 0x0a);\n+      connected = true;\n+    });\n+\n+    await base.testing.sleep(maxTime * 1000 + 1000);\n+    //should still be alive here, even though it was dead here last time\n+    //This is because cat is still alive\n+    let status = await worker.queue.status(taskId);\n+    assert(status.status.state === 'running', 'stopped early!');\n+    \n+\n+    client.close();\n+    await base.testing.sleep(expTime * 1000 + 3000); ","path":"test/integration/interactive_test.js","position":172,"original_position":172,"commit_id":"b4ea3a5c14305ff3db495504ace1aba8f5cc8504","original_commit_id":"b4ea3a5c14305ff3db495504ace1aba8f5cc8504","user":{"login":"gregarndt","id":2592630,"avatar_url":"https://avatars.githubusercontent.com/u/2592630?v=3","gravatar_id":"","url":"https://api.github.com/users/gregarndt","html_url":"https://github.com/gregarndt","followers_url":"https://api.github.com/users/gregarndt/followers","following_url":"https://api.github.com/users/gregarndt/following{/other_user}","gists_url":"https://api.github.com/users/gregarndt/gists{/gist_id}","starred_url":"https://api.github.com/users/gregarndt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gregarndt/subscriptions","organizations_url":"https://api.github.com/users/gregarndt/orgs","repos_url":"https://api.github.com/users/gregarndt/repos","events_url":"https://api.github.com/users/gregarndt/events{/privacy}","received_events_url":"https://api.github.com/users/gregarndt/received_events","type":"User","site_admin":false},"body":"nit: trailing white space","created_at":"2015-07-16T01:45:37Z","updated_at":"2015-07-16T01:45:37Z","html_url":"https://github.com/taskcluster/docker-worker/pull/121#discussion_r34749303","pull_request_url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/121","_links":{"self":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/comments/34749303"},"html":{"href":"https://github.com/taskcluster/docker-worker/pull/121#discussion_r34749303"},"pull_request":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/121"}}},"pull_request":{"url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/121","id":39535895,"html_url":"https://github.com/taskcluster/docker-worker/pull/121","diff_url":"https://github.com/taskcluster/docker-worker/pull/121.diff","patch_url":"https://github.com/taskcluster/docker-worker/pull/121.patch","issue_url":"https://api.github.com/repos/taskcluster/docker-worker/issues/121","number":121,"state":"open","locked":false,"title":"Docker exec flock","user":{"login":"EggyLv999","id":2454672,"avatar_url":"https://avatars.githubusercontent.com/u/2454672?v=3","gravatar_id":"","url":"https://api.github.com/users/EggyLv999","html_url":"https://github.com/EggyLv999","followers_url":"https://api.github.com/users/EggyLv999/followers","following_url":"https://api.github.com/users/EggyLv999/following{/other_user}","gists_url":"https://api.github.com/users/EggyLv999/gists{/gist_id}","starred_url":"https://api.github.com/users/EggyLv999/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/EggyLv999/subscriptions","organizations_url":"https://api.github.com/users/EggyLv999/orgs","repos_url":"https://api.github.com/users/EggyLv999/repos","events_url":"https://api.github.com/users/EggyLv999/events{/privacy}","received_events_url":"https://api.github.com/users/EggyLv999/received_events","type":"User","site_admin":false},"body":"And here is the long-awaited PR for the interactive feature. I have no idea how a couple of random 1-line fixes are showing up here, but they are. ","created_at":"2015-07-08T23:52:29Z","updated_at":"2015-07-16T01:45:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"dbeec78cb6ee4d42db661f8bf7b2bc1cfb901df0","assignee":{"login":"jonasfj","id":149732,"avatar_url":"https://avatars.githubusercontent.com/u/149732?v=3","gravatar_id":"","url":"https://api.github.com/users/jonasfj","html_url":"https://github.com/jonasfj","followers_url":"https://api.github.com/users/jonasfj/followers","following_url":"https://api.github.com/users/jonasfj/following{/other_user}","gists_url":"https://api.github.com/users/jonasfj/gists{/gist_id}","starred_url":"https://api.github.com/users/jonasfj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonasfj/subscriptions","organizations_url":"https://api.github.com/users/jonasfj/orgs","repos_url":"https://api.github.com/users/jonasfj/repos","events_url":"https://api.github.com/users/jonasfj/events{/privacy}","received_events_url":"https://api.github.com/users/jonasfj/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/121/commits","review_comments_url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/121/comments","review_comment_url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/comments{/number}","comments_url":"https://api.github.com/repos/taskcluster/docker-worker/issues/121/comments","statuses_url":"https://api.github.com/repos/taskcluster/docker-worker/statuses/b4ea3a5c14305ff3db495504ace1aba8f5cc8504","head":{"label":"taskcluster:docker-exec-flock","ref":"docker-exec-flock","sha":"b4ea3a5c14305ff3db495504ace1aba8f5cc8504","user":{"login":"taskcluster","id":6257436,"avatar_url":"https://avatars.githubusercontent.com/u/6257436?v=3","gravatar_id":"","url":"https://api.github.com/users/taskcluster","html_url":"https://github.com/taskcluster","followers_url":"https://api.github.com/users/taskcluster/followers","following_url":"https://api.github.com/users/taskcluster/following{/other_user}","gists_url":"https://api.github.com/users/taskcluster/gists{/gist_id}","starred_url":"https://api.github.com/users/taskcluster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/taskcluster/subscriptions","organizations_url":"https://api.github.com/users/taskcluster/orgs","repos_url":"https://api.github.com/users/taskcluster/repos","events_url":"https://api.github.com/users/taskcluster/events{/privacy}","received_events_url":"https://api.github.com/users/taskcluster/received_events","type":"Organization","site_admin":false},"repo":{"id":15545665,"name":"docker-worker","full_name":"taskcluster/docker-worker","owner":{"login":"taskcluster","id":6257436,"avatar_url":"https://avatars.githubusercontent.com/u/6257436?v=3","gravatar_id":"","url":"https://api.github.com/users/taskcluster","html_url":"https://github.com/taskcluster","followers_url":"https://api.github.com/users/taskcluster/followers","following_url":"https://api.github.com/users/taskcluster/following{/other_user}","gists_url":"https://api.github.com/users/taskcluster/gists{/gist_id}","starred_url":"https://api.github.com/users/taskcluster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/taskcluster/subscriptions","organizations_url":"https://api.github.com/users/taskcluster/orgs","repos_url":"https://api.github.com/users/taskcluster/repos","events_url":"https://api.github.com/users/taskcluster/events{/privacy}","received_events_url":"https://api.github.com/users/taskcluster/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/taskcluster/docker-worker","description":"Docker worker for the cluster","fork":false,"url":"https://api.github.com/repos/taskcluster/docker-worker","forks_url":"https://api.github.com/repos/taskcluster/docker-worker/forks","keys_url":"https://api.github.com/repos/taskcluster/docker-worker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/taskcluster/docker-worker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/taskcluster/docker-worker/teams","hooks_url":"https://api.github.com/repos/taskcluster/docker-worker/hooks","issue_events_url":"https://api.github.com/repos/taskcluster/docker-worker/issues/events{/number}","events_url":"https://api.github.com/repos/taskcluster/docker-worker/events","assignees_url":"https://api.github.com/repos/taskcluster/docker-worker/assignees{/user}","branches_url":"https://api.github.com/repos/taskcluster/docker-worker/branches{/branch}","tags_url":"https://api.github.com/repos/taskcluster/docker-worker/tags","blobs_url":"https://api.github.com/repos/taskcluster/docker-worker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/taskcluster/docker-worker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/taskcluster/docker-worker/git/refs{/sha}","trees_url":"https://api.github.com/repos/taskcluster/docker-worker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/taskcluster/docker-worker/statuses/{sha}","languages_url":"https://api.github.com/repos/taskcluster/docker-worker/languages","stargazers_url":"https://api.github.com/repos/taskcluster/docker-worker/stargazers","contributors_url":"https://api.github.com/repos/taskcluster/docker-worker/contributors","subscribers_url":"https://api.github.com/repos/taskcluster/docker-worker/subscribers","subscription_url":"https://api.github.com/repos/taskcluster/docker-worker/subscription","commits_url":"https://api.github.com/repos/taskcluster/docker-worker/commits{/sha}","git_commits_url":"https://api.github.com/repos/taskcluster/docker-worker/git/commits{/sha}","comments_url":"https://api.github.com/repos/taskcluster/docker-worker/comments{/number}","issue_comment_url":"https://api.github.com/repos/taskcluster/docker-worker/issues/comments{/number}","contents_url":"https://api.github.com/repos/taskcluster/docker-worker/contents/{+path}","compare_url":"https://api.github.com/repos/taskcluster/docker-worker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/taskcluster/docker-worker/merges","archive_url":"https://api.github.com/repos/taskcluster/docker-worker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/taskcluster/docker-worker/downloads","issues_url":"https://api.github.com/repos/taskcluster/docker-worker/issues{/number}","pulls_url":"https://api.github.com/repos/taskcluster/docker-worker/pulls{/number}","milestones_url":"https://api.github.com/repos/taskcluster/docker-worker/milestones{/number}","notifications_url":"https://api.github.com/repos/taskcluster/docker-worker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/taskcluster/docker-worker/labels{/name}","releases_url":"https://api.github.com/repos/taskcluster/docker-worker/releases{/id}","created_at":"2013-12-31T07:38:22Z","updated_at":"2015-05-20T05:19:39Z","pushed_at":"2015-07-16T01:42:08Z","git_url":"git://github.com/taskcluster/docker-worker.git","ssh_url":"git@github.com:taskcluster/docker-worker.git","clone_url":"https://github.com/taskcluster/docker-worker.git","svn_url":"https://github.com/taskcluster/docker-worker","homepage":"","size":23359,"stargazers_count":12,"watchers_count":12,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":14,"mirror_url":null,"open_issues_count":6,"forks":14,"open_issues":6,"watchers":12,"default_branch":"master"}},"base":{"label":"taskcluster:master","ref":"master","sha":"b50eb9cd61beecfbd7e2e4f677f9b7f46193aaa7","user":{"login":"taskcluster","id":6257436,"avatar_url":"https://avatars.githubusercontent.com/u/6257436?v=3","gravatar_id":"","url":"https://api.github.com/users/taskcluster","html_url":"https://github.com/taskcluster","followers_url":"https://api.github.com/users/taskcluster/followers","following_url":"https://api.github.com/users/taskcluster/following{/other_user}","gists_url":"https://api.github.com/users/taskcluster/gists{/gist_id}","starred_url":"https://api.github.com/users/taskcluster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/taskcluster/subscriptions","organizations_url":"https://api.github.com/users/taskcluster/orgs","repos_url":"https://api.github.com/users/taskcluster/repos","events_url":"https://api.github.com/users/taskcluster/events{/privacy}","received_events_url":"https://api.github.com/users/taskcluster/received_events","type":"Organization","site_admin":false},"repo":{"id":15545665,"name":"docker-worker","full_name":"taskcluster/docker-worker","owner":{"login":"taskcluster","id":6257436,"avatar_url":"https://avatars.githubusercontent.com/u/6257436?v=3","gravatar_id":"","url":"https://api.github.com/users/taskcluster","html_url":"https://github.com/taskcluster","followers_url":"https://api.github.com/users/taskcluster/followers","following_url":"https://api.github.com/users/taskcluster/following{/other_user}","gists_url":"https://api.github.com/users/taskcluster/gists{/gist_id}","starred_url":"https://api.github.com/users/taskcluster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/taskcluster/subscriptions","organizations_url":"https://api.github.com/users/taskcluster/orgs","repos_url":"https://api.github.com/users/taskcluster/repos","events_url":"https://api.github.com/users/taskcluster/events{/privacy}","received_events_url":"https://api.github.com/users/taskcluster/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/taskcluster/docker-worker","description":"Docker worker for the cluster","fork":false,"url":"https://api.github.com/repos/taskcluster/docker-worker","forks_url":"https://api.github.com/repos/taskcluster/docker-worker/forks","keys_url":"https://api.github.com/repos/taskcluster/docker-worker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/taskcluster/docker-worker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/taskcluster/docker-worker/teams","hooks_url":"https://api.github.com/repos/taskcluster/docker-worker/hooks","issue_events_url":"https://api.github.com/repos/taskcluster/docker-worker/issues/events{/number}","events_url":"https://api.github.com/repos/taskcluster/docker-worker/events","assignees_url":"https://api.github.com/repos/taskcluster/docker-worker/assignees{/user}","branches_url":"https://api.github.com/repos/taskcluster/docker-worker/branches{/branch}","tags_url":"https://api.github.com/repos/taskcluster/docker-worker/tags","blobs_url":"https://api.github.com/repos/taskcluster/docker-worker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/taskcluster/docker-worker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/taskcluster/docker-worker/git/refs{/sha}","trees_url":"https://api.github.com/repos/taskcluster/docker-worker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/taskcluster/docker-worker/statuses/{sha}","languages_url":"https://api.github.com/repos/taskcluster/docker-worker/languages","stargazers_url":"https://api.github.com/repos/taskcluster/docker-worker/stargazers","contributors_url":"https://api.github.com/repos/taskcluster/docker-worker/contributors","subscribers_url":"https://api.github.com/repos/taskcluster/docker-worker/subscribers","subscription_url":"https://api.github.com/repos/taskcluster/docker-worker/subscription","commits_url":"https://api.github.com/repos/taskcluster/docker-worker/commits{/sha}","git_commits_url":"https://api.github.com/repos/taskcluster/docker-worker/git/commits{/sha}","comments_url":"https://api.github.com/repos/taskcluster/docker-worker/comments{/number}","issue_comment_url":"https://api.github.com/repos/taskcluster/docker-worker/issues/comments{/number}","contents_url":"https://api.github.com/repos/taskcluster/docker-worker/contents/{+path}","compare_url":"https://api.github.com/repos/taskcluster/docker-worker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/taskcluster/docker-worker/merges","archive_url":"https://api.github.com/repos/taskcluster/docker-worker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/taskcluster/docker-worker/downloads","issues_url":"https://api.github.com/repos/taskcluster/docker-worker/issues{/number}","pulls_url":"https://api.github.com/repos/taskcluster/docker-worker/pulls{/number}","milestones_url":"https://api.github.com/repos/taskcluster/docker-worker/milestones{/number}","notifications_url":"https://api.github.com/repos/taskcluster/docker-worker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/taskcluster/docker-worker/labels{/name}","releases_url":"https://api.github.com/repos/taskcluster/docker-worker/releases{/id}","created_at":"2013-12-31T07:38:22Z","updated_at":"2015-05-20T05:19:39Z","pushed_at":"2015-07-16T01:42:08Z","git_url":"git://github.com/taskcluster/docker-worker.git","ssh_url":"git@github.com:taskcluster/docker-worker.git","clone_url":"https://github.com/taskcluster/docker-worker.git","svn_url":"https://github.com/taskcluster/docker-worker","homepage":"","size":23359,"stargazers_count":12,"watchers_count":12,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":14,"mirror_url":null,"open_issues_count":6,"forks":14,"open_issues":6,"watchers":12,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/121"},"html":{"href":"https://github.com/taskcluster/docker-worker/pull/121"},"issue":{"href":"https://api.github.com/repos/taskcluster/docker-worker/issues/121"},"comments":{"href":"https://api.github.com/repos/taskcluster/docker-worker/issues/121/comments"},"review_comments":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/121/comments"},"review_comment":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/121/commits"},"statuses":{"href":"https://api.github.com/repos/taskcluster/docker-worker/statuses/b4ea3a5c14305ff3db495504ace1aba8f5cc8504"}}}}