{"action":"created","comment":{"url":"https://api.github.com/repos/RackHD/RackHD/pulls/comments/74550475","id":74550475,"diff_hunk":"@@ -0,0 +1,528 @@\n+'''\n+Copyright 2016, EMC, Inc.\n+\n+Author(s):\n+George Paulos\n+\n+OnRack/RackHD Functional Integration Test (FIT) library\n+This is the main common function library for OnRack/RackHD FIT tests.\n+'''\n+\n+# Standard imports\n+import os\n+import sys\n+import json\n+import subprocess\n+import time, datetime\n+import unittest\n+import signal\n+import re\n+import requests\n+import pexpect\n+import shutil\n+\n+# Globals\n+\n+# Pull arguments from environment into ARGS_LIST\n+ARGS_LIST = \\\n+    {\n+    \"v\": os.getenv(\"VERBOSITY\", \"0\"),\n+    \"config\":  os.getenv(\"CONFIG\", \"config\"),\n+    \"stack\": os.getenv(\"STACK\", \"None\"), # Stack label\n+    \"ora\": os.getenv(\"ORA\", \"localhost\"), # Appliance IP or hostname\n+    \"bmc\": \"None\", # BMC IP or hostname\n+    \"sku\": os.getenv(\"SKU\", \"all\"), # node SKU name\n+    \"obmmac\": os.getenv(\"OBMMAC\", \"all\"), # node OBM MAC address\n+    \"nodeid\": os.getenv(\"NODEID\", \"None\"), # node ID\n+    \"hyper\": \"None\", # hypervisor address\n+    \"version\": os.getenv(\"VERSION\", \"onrack-devel\"), # code version\n+    \"xunit\": os.getenv(\"XUNIT\", False), # XUNIT output\n+    \"list\": os.getenv(\"LIST\", False), # list tests\n+    \"group\": os.getenv(\"GROUP\", \"all\"), # test group\n+    \"http\": os.getenv(\"HTTP\", \"False\"), # force http api protocol\n+    \"https\": os.getenv(\"HTTPS\", \"False\"), # force https api protocol\n+}\n+\n+# Get top level path via git\n+TEST_PATH = subprocess.check_output(\"git rev-parse --show-toplevel\", shell=True).rstrip(\"\\n\") + \"/test/fit_tests/\"\n+CONFIG_PATH = TEST_PATH + ARGS_LIST[\"config\"] + \"/\"\n+if ARGS_LIST[\"config\"] != 'config':\n+    print \"**** Using config file path:\", ARGS_LIST[\"config\"]\n+VERBOSITY = int(os.getenv(\"VERBOSITY\", \"1\"))\n+GLOBAL_CONFIG = []\n+STACK_CONFIG = []\n+API_PORT=None\n+API_PROTOCOL=None\n+\n+# List of BMC IP addresses\n+BMC_LIST = []\n+\n+\n+# Global Config files\n+try:\n+    GLOBAL_CONFIG = json.loads(open(CONFIG_PATH + \"global_config.json\").read())\n+except:\n+    print \"**** Global Config file: \" + CONFIG_PATH + \"global_config.json\" + \" missing or corrupted! Exiting....\"\n+    sys.exit(255)\n+try:\n+    STACK_CONFIG = json.loads(open(CONFIG_PATH + \"stack_config.json\").read())\n+except:\n+    print \"**** Stack Config file:\" + CONFIG_PATH + \"stack_config.json\" + \" missing or corrupted! Creating empty stack file....\"\n+    STACK_CONFIG = []\n+\n+# apply stack detail files from config dir to STACK_CONFIG dict\n+for entry in os.listdir(CONFIG_PATH):\n+    if entry != \"global_config.json\" and entry != \"stack_config.json\" and \".json\" in entry:\n+        try:\n+            detailfile = json.loads(open(CONFIG_PATH + entry).read())\n+        except:\n+            print \"**** Invalid JSON file:\", CONFIG_PATH + entry\n+        else:\n+            STACK_CONFIG.update(detailfile)\n+\n+\n+# This section derives default stack configuration data from STACK-CONFIG, use environment to override\n+ARGS_LIST.update(\n+    {\n+        \"usr\": GLOBAL_CONFIG['credentials']['ora'][0]['username'],\n+        \"pwd\": GLOBAL_CONFIG['credentials']['ora'][0]['password']\n+    }\n+)\n+\n+if ARGS_LIST[\"stack\"] != \"None\":\n+    if \"ora\" in STACK_CONFIG[ARGS_LIST[\"stack\"]]:\n+        ARGS_LIST[\"ora\"] = STACK_CONFIG[ARGS_LIST[\"stack\"]]['ora']\n+    else:\n+        ARGS_LIST[\"ora\"] = \"localhost\"\n+    if \"bmc\" in STACK_CONFIG[ARGS_LIST[\"stack\"]]:\n+        ARGS_LIST[\"bmc\"] = STACK_CONFIG[ARGS_LIST[\"stack\"]]['bmc']\n+    if \"hyper\" in STACK_CONFIG[ARGS_LIST[\"stack\"]]:\n+        ARGS_LIST[\"hyper\"] = STACK_CONFIG[ARGS_LIST[\"stack\"]]['hyper']\n+\n+# set api port and protocol\n+if ARGS_LIST['http'] == \"True\":\n+    API_PROTOCOL = 'http'\n+    API_PORT = GLOBAL_CONFIG['ports']['http']\n+if ARGS_LIST['https'] == \"True\":\n+    API_PROTOCOL = 'https'\n+    API_PORT = GLOBAL_CONFIG['ports']['http']\n+if ARGS_LIST[\"ora\"] == \"localhost\":\n+    API_PROTOCOL = 'http'\n+    API_PORT = '8080'\n+\n+def timestamp(): # return formatted current timestamp\n+    return time.strftime(\"%Y-%m-%dT%H:%M:%S\", time.gmtime())\n+\n+# This routine executes a sleep with countdown\n+def countdown(sleep_time, sleep_interval=1):\n+    sys.stdout.write(\"Sleeping for \" + str(sleep_time * sleep_interval)\n+                     + \" seconds.\")\n+    sys.stdout.flush()\n+    for _ in range(0, sleep_time):\n+        time.sleep(sleep_interval)\n+        sys.stdout.write(\".\")\n+        sys.stdout.flush()\n+    print \"Waking!\"\n+    return\n+\n+def remote_shell(shell_cmd, expect_receive=\"\", expect_send=\"\", timeout=300, address=ARGS_LIST['ora'], user=ARGS_LIST['usr'], password=ARGS_LIST['pwd']):\n+    '''\n+    Run ssh based shell command on a remote machine at ARGS_LIST[\"ora\"]\n+\n+    :param shell_cmd: string based command\n+    :param expect_receive:\n+    :param expect_send:\n+    :param timeout: in seconds\n+    :param address: IP or hostname of remote host\n+    :param user: username of remote host\n+    :param password: password of remote host\n+    :return: dict = {'stdout': str:ouput, 'exitcode': return code}\n+    '''\n+\n+    # if localhost just run the command local\n+    if ARGS_LIST['ora'] == 'localhost':\n+        (command_output, exitstatus) = \\\n+            pexpect.run(\"sudo bash -c \\\\\\\"\" + shell_cmd + \"\\\\\\\"\",\n+                        withexitstatus=1,\n+                        events={\"assword\": password + \"\\n\"},\n+                        timeout=timeout, logfile=logfile_redirect)\n+        return {'stdout':command_output, 'exitcode':exitstatus}\n+\n+    # this clears the ssh key from ~/.ssh/known_hosts\n+    subprocess.call([\"touch ~/.ssh/known_hosts;ssh-keygen -R \"\n+                     + address  + \" -f ~/.ssh/known_hosts >/dev/null 2>&1\"], shell=True)\n+\n+    logfile_redirect = None\n+    shell_cmd.replace(\"'\", \"\\\\\\'\")\n+    if VERBOSITY >= 4:\n+        print \"remote_shell: Host =\", address\n+        print \"remote_shell: Command =\", shell_cmd\n+\n+    if VERBOSITY >= 9:\n+        print \"remote_shell: STDOUT =\\n\"\n+        logfile_redirect = sys.stdout\n+\n+    if expect_receive == \"\" or expect_send == \"\":\n+        (command_output, exitstatus) = \\\n+            pexpect.run(\"ssh -q -o StrictHostKeyChecking=no -t \" + user + \"@\"\n+                        + address + \" sudo bash -c \\\\\\\"\" + shell_cmd + \"\\\\\\\"\",","path":"test/fit_tests/common/fit_common.py","position":168,"original_position":168,"commit_id":"bd48bae9e7df33db10d6564f76a02a5900e0b0aa","original_commit_id":"bd48bae9e7df33db10d6564f76a02a5900e0b0aa","user":{"login":"yyscamper","id":511378,"avatar_url":"https://avatars.githubusercontent.com/u/511378?v=3","gravatar_id":"","url":"https://api.github.com/users/yyscamper","html_url":"https://github.com/yyscamper","followers_url":"https://api.github.com/users/yyscamper/followers","following_url":"https://api.github.com/users/yyscamper/following{/other_user}","gists_url":"https://api.github.com/users/yyscamper/gists{/gist_id}","starred_url":"https://api.github.com/users/yyscamper/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yyscamper/subscriptions","organizations_url":"https://api.github.com/users/yyscamper/orgs","repos_url":"https://api.github.com/users/yyscamper/repos","events_url":"https://api.github.com/users/yyscamper/events{/privacy}","received_events_url":"https://api.github.com/users/yyscamper/received_events","type":"User","site_admin":false},"body":"A little suggestion, use `format` will be more clear:\r\n```python\r\n\"ssh -q -o StrictHostKeyChecking=no -t {0}@{1} sudo bash -c \\\\\\\"{2}\\\\\\\"\".format(user, address, shell_cmd)\r\n```","created_at":"2016-08-12T07:22:45Z","updated_at":"2016-08-12T07:22:45Z","html_url":"https://github.com/RackHD/RackHD/pull/370#discussion_r74550475","pull_request_url":"https://api.github.com/repos/RackHD/RackHD/pulls/370","_links":{"self":{"href":"https://api.github.com/repos/RackHD/RackHD/pulls/comments/74550475"},"html":{"href":"https://github.com/RackHD/RackHD/pull/370#discussion_r74550475"},"pull_request":{"href":"https://api.github.com/repos/RackHD/RackHD/pulls/370"}}},"pull_request":{"url":"https://api.github.com/repos/RackHD/RackHD/pulls/370","id":80489630,"html_url":"https://github.com/RackHD/RackHD/pull/370","diff_url":"https://github.com/RackHD/RackHD/pull/370.diff","patch_url":"https://github.com/RackHD/RackHD/pull/370.patch","issue_url":"https://api.github.com/repos/RackHD/RackHD/issues/370","number":370,"state":"open","locked":false,"title":"Add FIT tests to rackhd test","user":{"login":"gpaulos","id":10143363,"avatar_url":"https://avatars.githubusercontent.com/u/10143363?v=3","gravatar_id":"","url":"https://api.github.com/users/gpaulos","html_url":"https://github.com/gpaulos","followers_url":"https://api.github.com/users/gpaulos/followers","following_url":"https://api.github.com/users/gpaulos/following{/other_user}","gists_url":"https://api.github.com/users/gpaulos/gists{/gist_id}","starred_url":"https://api.github.com/users/gpaulos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gpaulos/subscriptions","organizations_url":"https://api.github.com/users/gpaulos/orgs","repos_url":"https://api.github.com/users/gpaulos/repos","events_url":"https://api.github.com/users/gpaulos/events{/privacy}","received_events_url":"https://api.github.com/users/gpaulos/received_events","type":"User","site_admin":false},"body":"This PR is the FIT (Functional Integration Test) test suite that is used by OnRack (Corsair) to test RackHD/OnRack via Jenkins.\r\n\r\nFIT tests are located in the RackHD/test/fit_tests directory. They will not interfere with existing test jobs running from RackHD/test directory.\r\n\r\nThe goal is to integrate all RackHD/OnRack testing under a single universal and unified framework. This is the first step towards achieveing that goal.\r\n\r\nCurrently FIT contains 185 tests total, of which 164 are 'smoke' tests.\r\n\r\nThe framework has been tested and operated under both real hardware stacks and Vagrant simulated stacks. It is adaptable to many diverse environments via configuration files in RackHD/test/fit_tests/config/.  Refer to README files for operation and configuration.\r\n\r\nResult from a Jenkins FIT test run is available here (EMC internal):\r\nhttps://roebling.hwimo.lab.emc.com/jenkins/job/Running-Tests/job/RackHD-FIT-Smoke-Test/65/\r\n\r\nThe test failures are related to the following bugs:\r\nODR-801 - SKU pack failures\r\nODR-803 - management server fails on redfish\r\nODR-812 - api/2.0/skus fail post/put\r\nODR-796 - chassis/enclosure issues\r\nODR-795 - chassis/enclosure issues\r\nODR-793 - chassis/enclosure issues\r\n\r\nShort-term goal is to get a clean run of FIT smoke test by fixing product bugs and any other test bugs that may crop up.\r\n\r\nMedium-term goal is to run FIT along with legacy test suite as the release test gate.\r\n\r\nLong-term goal is to unify all testing under a single suite.\r\n\r\n- George Paulos","created_at":"2016-08-08T17:27:35Z","updated_at":"2016-08-12T07:22:45Z","closed_at":null,"merged_at":null,"merge_commit_sha":"575aabdc1282bb6cbc67070db9083d63f1d83b49","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/RackHD/RackHD/pulls/370/commits","review_comments_url":"https://api.github.com/repos/RackHD/RackHD/pulls/370/comments","review_comment_url":"https://api.github.com/repos/RackHD/RackHD/pulls/comments{/number}","comments_url":"https://api.github.com/repos/RackHD/RackHD/issues/370/comments","statuses_url":"https://api.github.com/repos/RackHD/RackHD/statuses/bd48bae9e7df33db10d6564f76a02a5900e0b0aa","head":{"label":"gpaulos:add-fit_tests-to-rackhd-test","ref":"add-fit_tests-to-rackhd-test","sha":"bd48bae9e7df33db10d6564f76a02a5900e0b0aa","user":{"login":"gpaulos","id":10143363,"avatar_url":"https://avatars.githubusercontent.com/u/10143363?v=3","gravatar_id":"","url":"https://api.github.com/users/gpaulos","html_url":"https://github.com/gpaulos","followers_url":"https://api.github.com/users/gpaulos/followers","following_url":"https://api.github.com/users/gpaulos/following{/other_user}","gists_url":"https://api.github.com/users/gpaulos/gists{/gist_id}","starred_url":"https://api.github.com/users/gpaulos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gpaulos/subscriptions","organizations_url":"https://api.github.com/users/gpaulos/orgs","repos_url":"https://api.github.com/users/gpaulos/repos","events_url":"https://api.github.com/users/gpaulos/events{/privacy}","received_events_url":"https://api.github.com/users/gpaulos/received_events","type":"User","site_admin":false},"repo":{"id":65032256,"name":"RackHD","full_name":"gpaulos/RackHD","owner":{"login":"gpaulos","id":10143363,"avatar_url":"https://avatars.githubusercontent.com/u/10143363?v=3","gravatar_id":"","url":"https://api.github.com/users/gpaulos","html_url":"https://github.com/gpaulos","followers_url":"https://api.github.com/users/gpaulos/followers","following_url":"https://api.github.com/users/gpaulos/following{/other_user}","gists_url":"https://api.github.com/users/gpaulos/gists{/gist_id}","starred_url":"https://api.github.com/users/gpaulos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gpaulos/subscriptions","organizations_url":"https://api.github.com/users/gpaulos/orgs","repos_url":"https://api.github.com/users/gpaulos/repos","events_url":"https://api.github.com/users/gpaulos/events{/privacy}","received_events_url":"https://api.github.com/users/gpaulos/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/gpaulos/RackHD","description":"RackHD™ provides hardware management and orchestration services","fork":true,"url":"https://api.github.com/repos/gpaulos/RackHD","forks_url":"https://api.github.com/repos/gpaulos/RackHD/forks","keys_url":"https://api.github.com/repos/gpaulos/RackHD/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gpaulos/RackHD/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gpaulos/RackHD/teams","hooks_url":"https://api.github.com/repos/gpaulos/RackHD/hooks","issue_events_url":"https://api.github.com/repos/gpaulos/RackHD/issues/events{/number}","events_url":"https://api.github.com/repos/gpaulos/RackHD/events","assignees_url":"https://api.github.com/repos/gpaulos/RackHD/assignees{/user}","branches_url":"https://api.github.com/repos/gpaulos/RackHD/branches{/branch}","tags_url":"https://api.github.com/repos/gpaulos/RackHD/tags","blobs_url":"https://api.github.com/repos/gpaulos/RackHD/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gpaulos/RackHD/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gpaulos/RackHD/git/refs{/sha}","trees_url":"https://api.github.com/repos/gpaulos/RackHD/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gpaulos/RackHD/statuses/{sha}","languages_url":"https://api.github.com/repos/gpaulos/RackHD/languages","stargazers_url":"https://api.github.com/repos/gpaulos/RackHD/stargazers","contributors_url":"https://api.github.com/repos/gpaulos/RackHD/contributors","subscribers_url":"https://api.github.com/repos/gpaulos/RackHD/subscribers","subscription_url":"https://api.github.com/repos/gpaulos/RackHD/subscription","commits_url":"https://api.github.com/repos/gpaulos/RackHD/commits{/sha}","git_commits_url":"https://api.github.com/repos/gpaulos/RackHD/git/commits{/sha}","comments_url":"https://api.github.com/repos/gpaulos/RackHD/comments{/number}","issue_comment_url":"https://api.github.com/repos/gpaulos/RackHD/issues/comments{/number}","contents_url":"https://api.github.com/repos/gpaulos/RackHD/contents/{+path}","compare_url":"https://api.github.com/repos/gpaulos/RackHD/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gpaulos/RackHD/merges","archive_url":"https://api.github.com/repos/gpaulos/RackHD/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gpaulos/RackHD/downloads","issues_url":"https://api.github.com/repos/gpaulos/RackHD/issues{/number}","pulls_url":"https://api.github.com/repos/gpaulos/RackHD/pulls{/number}","milestones_url":"https://api.github.com/repos/gpaulos/RackHD/milestones{/number}","notifications_url":"https://api.github.com/repos/gpaulos/RackHD/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gpaulos/RackHD/labels{/name}","releases_url":"https://api.github.com/repos/gpaulos/RackHD/releases{/id}","deployments_url":"https://api.github.com/repos/gpaulos/RackHD/deployments","created_at":"2016-08-05T16:13:01Z","updated_at":"2016-08-05T16:13:02Z","pushed_at":"2016-08-11T18:57:18Z","git_url":"git://github.com/gpaulos/RackHD.git","ssh_url":"git@github.com:gpaulos/RackHD.git","clone_url":"https://github.com/gpaulos/RackHD.git","svn_url":"https://github.com/gpaulos/RackHD","homepage":" http://rackhd.readthedocs.io","size":2433,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"RackHD:master","ref":"master","sha":"cdadd5830cf5e82525fedd19b08c986fa3ca7c2c","user":{"login":"RackHD","id":13982662,"avatar_url":"https://avatars.githubusercontent.com/u/13982662?v=3","gravatar_id":"","url":"https://api.github.com/users/RackHD","html_url":"https://github.com/RackHD","followers_url":"https://api.github.com/users/RackHD/followers","following_url":"https://api.github.com/users/RackHD/following{/other_user}","gists_url":"https://api.github.com/users/RackHD/gists{/gist_id}","starred_url":"https://api.github.com/users/RackHD/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RackHD/subscriptions","organizations_url":"https://api.github.com/users/RackHD/orgs","repos_url":"https://api.github.com/users/RackHD/repos","events_url":"https://api.github.com/users/RackHD/events{/privacy}","received_events_url":"https://api.github.com/users/RackHD/received_events","type":"Organization","site_admin":false},"repo":{"id":45687347,"name":"RackHD","full_name":"RackHD/RackHD","owner":{"login":"RackHD","id":13982662,"avatar_url":"https://avatars.githubusercontent.com/u/13982662?v=3","gravatar_id":"","url":"https://api.github.com/users/RackHD","html_url":"https://github.com/RackHD","followers_url":"https://api.github.com/users/RackHD/followers","following_url":"https://api.github.com/users/RackHD/following{/other_user}","gists_url":"https://api.github.com/users/RackHD/gists{/gist_id}","starred_url":"https://api.github.com/users/RackHD/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RackHD/subscriptions","organizations_url":"https://api.github.com/users/RackHD/orgs","repos_url":"https://api.github.com/users/RackHD/repos","events_url":"https://api.github.com/users/RackHD/events{/privacy}","received_events_url":"https://api.github.com/users/RackHD/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/RackHD/RackHD","description":"RackHD™ provides hardware management and orchestration services","fork":false,"url":"https://api.github.com/repos/RackHD/RackHD","forks_url":"https://api.github.com/repos/RackHD/RackHD/forks","keys_url":"https://api.github.com/repos/RackHD/RackHD/keys{/key_id}","collaborators_url":"https://api.github.com/repos/RackHD/RackHD/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/RackHD/RackHD/teams","hooks_url":"https://api.github.com/repos/RackHD/RackHD/hooks","issue_events_url":"https://api.github.com/repos/RackHD/RackHD/issues/events{/number}","events_url":"https://api.github.com/repos/RackHD/RackHD/events","assignees_url":"https://api.github.com/repos/RackHD/RackHD/assignees{/user}","branches_url":"https://api.github.com/repos/RackHD/RackHD/branches{/branch}","tags_url":"https://api.github.com/repos/RackHD/RackHD/tags","blobs_url":"https://api.github.com/repos/RackHD/RackHD/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/RackHD/RackHD/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/RackHD/RackHD/git/refs{/sha}","trees_url":"https://api.github.com/repos/RackHD/RackHD/git/trees{/sha}","statuses_url":"https://api.github.com/repos/RackHD/RackHD/statuses/{sha}","languages_url":"https://api.github.com/repos/RackHD/RackHD/languages","stargazers_url":"https://api.github.com/repos/RackHD/RackHD/stargazers","contributors_url":"https://api.github.com/repos/RackHD/RackHD/contributors","subscribers_url":"https://api.github.com/repos/RackHD/RackHD/subscribers","subscription_url":"https://api.github.com/repos/RackHD/RackHD/subscription","commits_url":"https://api.github.com/repos/RackHD/RackHD/commits{/sha}","git_commits_url":"https://api.github.com/repos/RackHD/RackHD/git/commits{/sha}","comments_url":"https://api.github.com/repos/RackHD/RackHD/comments{/number}","issue_comment_url":"https://api.github.com/repos/RackHD/RackHD/issues/comments{/number}","contents_url":"https://api.github.com/repos/RackHD/RackHD/contents/{+path}","compare_url":"https://api.github.com/repos/RackHD/RackHD/compare/{base}...{head}","merges_url":"https://api.github.com/repos/RackHD/RackHD/merges","archive_url":"https://api.github.com/repos/RackHD/RackHD/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/RackHD/RackHD/downloads","issues_url":"https://api.github.com/repos/RackHD/RackHD/issues{/number}","pulls_url":"https://api.github.com/repos/RackHD/RackHD/pulls{/number}","milestones_url":"https://api.github.com/repos/RackHD/RackHD/milestones{/number}","notifications_url":"https://api.github.com/repos/RackHD/RackHD/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/RackHD/RackHD/labels{/name}","releases_url":"https://api.github.com/repos/RackHD/RackHD/releases{/id}","deployments_url":"https://api.github.com/repos/RackHD/RackHD/deployments","created_at":"2015-11-06T14:42:16Z","updated_at":"2016-08-05T10:12:17Z","pushed_at":"2016-08-11T18:57:19Z","git_url":"git://github.com/RackHD/RackHD.git","ssh_url":"git@github.com:RackHD/RackHD.git","clone_url":"https://github.com/RackHD/RackHD.git","svn_url":"https://github.com/RackHD/RackHD","homepage":" http://rackhd.readthedocs.io","size":2888,"stargazers_count":153,"watchers_count":153,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":73,"mirror_url":null,"open_issues_count":68,"forks":73,"open_issues":68,"watchers":153,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/RackHD/RackHD/pulls/370"},"html":{"href":"https://github.com/RackHD/RackHD/pull/370"},"issue":{"href":"https://api.github.com/repos/RackHD/RackHD/issues/370"},"comments":{"href":"https://api.github.com/repos/RackHD/RackHD/issues/370/comments"},"review_comments":{"href":"https://api.github.com/repos/RackHD/RackHD/pulls/370/comments"},"review_comment":{"href":"https://api.github.com/repos/RackHD/RackHD/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/RackHD/RackHD/pulls/370/commits"},"statuses":{"href":"https://api.github.com/repos/RackHD/RackHD/statuses/bd48bae9e7df33db10d6564f76a02a5900e0b0aa"}}}}
{"actor":{"display_login":"yyscamper"}}