GitHub PullRequestReviewCommentEvent at 2014-09-22 12:51:55
Repository: hanythingondemand
Actor: stdweird
Payload: {"action":"created","comment":{"url":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/comments/17846318","id":17846318,"diff_hunk":"@@ -0,0 +1,329 @@\n+# #\n+# Copyright 2009-2013 Ghent University\n+#\n+# This file is part of hanythingondemand\n+# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),\n+# with support of Ghent University (http://ugent.be/hpc),\n+# the Flemish Supercomputer Centre (VSC) (https://vscentrum.be/nl/en),\n+# the Hercules foundation (http://www.herculesstichting.be/in_English)\n+# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).\n+#\n+# http://github.com/hpcugent/hanythingondemand\n+#\n+# hanythingondemand is free software: you can redistribute it and/or modify\n+# it under the terms of the GNU General Public License as published by\n+# the Free Software Foundation v2.\n+#\n+# hanythingondemand is distributed in the hope that it will be useful,\n+# but WITHOUT ANY WARRANTY; without even the implied warranty of\n+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n+# GNU General Public License for more details.\n+#\n+# You should have received a copy of the GNU General Public License\n+# along with hanythingondemand. If not, see <http://www.gnu.org/licenses/>.\n+# #\n+\"\"\"\n+@author: Ewan Higgs (Ghent University)\n+\"\"\"\n+\n+from ConfigParser import SafeConfigParser, NoOptionError, NoSectionError\n+from collections import OrderedDict, Mapping\n+from importlib import import_module\n+from os.path import join as mkpath, realpath, dirname\n+from copy import deepcopy\n+\n+from hod.config.template import mklocalworkdir\n+\n+# hod manifest config sections\n+_META_SECTION = 'Meta'\n+_CONFIG_SECTION = 'Config'\n+\n+# serviceaconfig sections\n+_UNIT_SECTION = 'Unit'\n+_SERVICE_SECTION = 'Service'\n+_ENVIRONMENT_SECTION = 'Environment'\n+\n+RUNS_ON_MASTER = 0x1\n+RUNS_ON_SLAVE = 0x2\n+RUNS_ON_ALL = RUNS_ON_MASTER | RUNS_ON_SLAVE\n+\n+def load_service_config(fileobj):\n+    '''\n+    Load a .ini style config for a service.\n+    '''\n+    config = SafeConfigParser()\n+    # optionxform = Option Transform; using str stops making it lower case.\n+    config.optionxform = str\n+    config.readfp(fileobj)\n+    return config\n+\n+def _abspath(filepath, working_dir):\n+    '''\n+    Take a filepath and working_dir and return the absolute path for the\n+    filepath. If the filepath is already absolute then just return it.\n+    >>> _abspath('somedir/file', '/tmp')\n+    /tmp/somedir/file\n+    >>> _abspath('', '/tmp')\n+    /tmp\n+    >>> _abspath('/not-tmp/somedir/file', '/tmp')\n+    /not-tmp/somedir/file\n+    '''\n+    if not len(filepath):\n+        return realpath(working_dir)\n+    elif filepath[0] == '/': # filepath is already absolute\n+        return filepath\n+\n+    return realpath(mkpath(working_dir, filepath))\n+\n+def _fileobj_dir(fileobj):\n+    '''\n+    Return the directory of the fileobj if it exists. If it's a file-like\n+    object (e.g. StringIO) just return a blank string.\n+    '''\n+    if hasattr(fileobj, 'name'):\n+        return dirname(fileobj.name)\n+    return ''\n+\n+def _parse_runs_on(s):\n+    '''Returns the relevant constant depending on the string argument'''\n+\n+    if s.lower() == 'master':\n+        return RUNS_ON_MASTER\n+    elif s.lower() == 'slave':\n+        return RUNS_ON_SLAVE\n+    elif s.lower() == 'all':\n+        return RUNS_ON_ALL\n+    else:\n+        raise ValueError('runs-on field must be either \"master\", \"slave\", or \"all\".')\n+\n+def _cfgget(config, section, item, dflt=None):\n+    '''Get a value from a ConfigParser object or a default if it's not there.'''\n+    if dflt is None:\n+        return config.get(section, item)\n+    try:\n+        return config.get(section, item)\n+    except (NoSectionError, NoOptionError):\n+        return dflt\n+\n+def parse_comma_delim_list(s):\n+    '''\n+    Convert a string containing a comma delimited list into a list of strings\n+    with no spaces on the end or beginning.\n+    Blanks are also removed. e.g. 'a,,b' results in ['a', 'b']\n+    '''\n+    return [x.strip() for x in filter(lambda x: x, s.split(','))]\n+\n+class PreServiceConfigOpts(object):\n+    r\"\"\"\n+    Manifest file for the group of services responsible for defining service\n+    level configs which need to be run through the template before any services\n+    can begin.\n+    \"\"\"\n+    __slots__ = ['version', 'workdir', 'config_writer', 'directories',\n+            'modules', 'service_configs', 'service_files', 'master_env']\n+\n+    OptionalFields=['master_env', 'modules', 'service_configs', 'directories']\n+\n+    def __init__(self, fileobj):\n+        _config = load_service_config(fileobj)\n+        self.version = _cfgget(_config, _META_SECTION, 'version', '')\n+\n+        self.workdir = _cfgget(_config, _CONFIG_SECTION, 'workdir', '')\n+        fileobj_dir = _fileobj_dir(fileobj)\n+\n+        def _fixup_path(cfg):\n+            return _abspath(cfg, fileobj_dir)\n+\n+        def _get_list(name):\n+            return parse_comma_delim_list(_cfgget(_config, _CONFIG_SECTION, name, ''))\n+\n+        self.modules = _get_list('modules')\n+        self.master_env = _get_list('master_env')\n+        self.service_files = _get_list('services')\n+        self.service_files = [_fixup_path(cfg) for cfg in self.service_files]\n+        self.directories = _get_list('directories')\n+        self.config_writer = _cfgget(_config, _CONFIG_SECTION, 'config_writer', '')\n+\n+        self.service_configs = _collect_configs(_config)\n+\n+    @property\n+    def localworkdir(self):\n+        return mklocalworkdir(self.workdir)\n+\n+    @property\n+    def configdir(self):\n+        return mkpath(self.localworkdir, 'conf')\n+\n+def preserviceconfigopts_from_file_list(filenames):\n+    \"\"\"Create and merge PreServiceConfigOpts from a list of filenames.\"\"\"\n+    precfgs = [PreServiceConfigOpts(open(f, 'r')) for f in filenames]\n+    precfg = reduce(merge, precfgs)\n+    bad_fields = invalid_fields(precfg)\n+    if bad_fields:\n+        raise RuntimeError(\"A valid configuration could not be generated from the files: %s: missing fields: %s\" % (filenames, bad_fields))\n+    return precfg\n+\n+def merge(lhs, rhs):\n+    \"\"\"\n+    Merge two objects of the same type based on their __slot__ list. This\n+    returns a fresh object and the originals should not be replaced.\n+    Rules:\n+        List types are concatenated.\n+        Dict types are merged using a deep merge.\n+        String types are overwritten. These are\n+    \"\"\"\n+    if type(lhs) != type(rhs):\n+        raise RuntimeError('merge can only use two of the same type')\n+\n+    def _update(a, b):\n+        for k, v in b.iteritems():\n+            if isinstance(v, Mapping):\n+                c = _update(a.get(k, dict()), v)\n+                a[k] = c\n+            else:\n+                a[k] = b[k]\n+        return a\n+\n+    lhs = deepcopy(lhs)\n+    for attr in lhs.__slots__:\n+        _lhs = getattr(lhs, attr)\n+        _rhs = getattr(rhs, attr)\n+        # cat lists\n+        if isinstance(_lhs, list):\n+            setattr(lhs, attr, _lhs + _rhs)\n+        # update dicts\n+        elif isinstance(_lhs, Mapping):\n+            setattr(lhs, attr, _update(_lhs, _rhs))\n+        # replace strings\n+        elif isinstance(_lhs, basestring) and _rhs:\n+            setattr(lhs, attr, _rhs)\n+\n+    return lhs\n+\n+def invalid_fields(obj):\n+    \"\"\"Return list of fields which are empty.\"\"\"\n+    bad_fields = []\n+    for attr in obj.__slots__:\n+        print obj, attr, getattr(obj, attr)\n+        if attr not in obj.OptionalFields and len(getattr(obj, attr)) == 0:\n+            bad_fields.append(attr)\n+    return bad_fields\n+\n+def _collect_configs(config):\n+    \"\"\"Convert sections into dicts of options\"\"\"\n+    service_configs = dict()\n+    for section in [s for s in config.sections() if s not in [_META_SECTION, _CONFIG_SECTION]]:\n+        option_dict = dict()\n+        options = config.options(section)\n+        for option in options:\n+            option_dict[option] = config.get(section, option)\n+\n+        service_configs[section] = option_dict\n+\n+    return service_configs\n+\n+def env2str(env):\n+    '''\n+    Take a dict of environment variable names mapped to their values and\n+    convert it to a string that can be used to prepend a command.\n+    '''\n+    envstr = ''\n+    for k, v in env.items():\n+        envstr += '%s=%s ' % (k, v)\n+    return envstr\n+\n+\n+class ConfigOpts(object):\n+    r\"\"\"\n+    Wrapper for the service configuration.\n+    Each of the config values can have a $variable which will be replaces\n+    by the value in the template strings except 'name'. Name cannot be\n+    templated.\n+\n+    Some of the slots are computed on call so that they can run on the Slave\n+    nodes as opposed to the Master nodes.\n+    \"\"\"\n+    def __init__(self, fileobj, template_resolver):\n+        self._config = load_service_config(fileobj)\n+        self.name = _cfgget(self._config, _UNIT_SECTION, 'Name')\n+        self._runs_on = _parse_runs_on(_cfgget(self._config, _UNIT_SECTION, 'RunsOn'))\n+        self._tr = template_resolver\n+\n+    @property\n+    def pre_start_script(self):\n+        return self._tr(_cfgget(self._config, _SERVICE_SECTION, 'ExecStartPre', ''))\n+\n+    @property\n+    def start_script(self):\n+        return self._tr(_cfgget(self._config, _SERVICE_SECTION, 'ExecStart'))\n+\n+    @property\n+    def stop_script(self):\n+        return self._tr(_cfgget(self._config, _SERVICE_SECTION, 'ExecStop'))\n+\n+    @property\n+    def workdir(self):\n+        return self._tr.workdir\n+\n+    @property\n+    def localworkdir(self):\n+        return mklocalworkdir(self._tr.workdir)\n+\n+    @property\n+    def configdir(self):\n+        return mkpath(self.localworkdir, 'conf')\n+\n+    @property\n+    def env(self):\n+        return OrderedDict([(k, self._tr(v)) for k, v in self._config.items(_ENVIRONMENT_SECTION)])\n+\n+    def runs_on(self, masterrank, ranks):\n+        '''\n+        Given the master rank and all ranks, return a list of the ranks this\n+        service will run on.\n+        '''\n+        if self._runs_on == RUNS_ON_MASTER:\n+            return [masterrank]\n+        elif self._runs_on == RUNS_ON_SLAVE:\n+            return [x for x in ranks if x != masterrank]\n+        elif self._runs_on == RUNS_ON_ALL:\n+            return ranks\n+        else:\n+            raise ValueError('ConfigOpts.runs_on has invalid value: %s' %\n+                    self._runs_on)\n+\n+    def __str__(self):\n+        return 'ConfigOpts(name=%s, runs_on=%d, pre_start_script=%s, ' \\\n+                'start_script=%s, stop_script=%s, workdir=%s, localworkdir=%s)' %  (self.name,\n+                self._runs_on, self.pre_start_script, self.start_script,\n+                self.stop_script, self.workdir, self.localworkdir)\n+\n+    def __repr__(self):\n+        return 'ConfigOpts(name=%s, runs_on=%d)' % (self.name, self._runs_on)\n+\n+    def __getstate__(self): return self.__dict__","path":"hod/config/config.py","position":304,"original_position":304,"commit_id":"6d6e76ee3220440edf9f10ca49891d0737c32711","original_commit_id":"6d6e76ee3220440edf9f10ca49891d0737c32711","user":{"login":"stdweird","id":1517606,"avatar_url":"https://avatars.githubusercontent.com/u/1517606?v=2","gravatar_id":"ab38b1cdcb5cd98bce610ecbe480c0ba","url":"https://api.github.com/users/stdweird","html_url":"https://github.com/stdweird","followers_url":"https://api.github.com/users/stdweird/followers","following_url":"https://api.github.com/users/stdweird/following{/other_user}","gists_url":"https://api.github.com/users/stdweird/gists{/gist_id}","starred_url":"https://api.github.com/users/stdweird/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stdweird/subscriptions","organizations_url":"https://api.github.com/users/stdweird/orgs","repos_url":"https://api.github.com/users/stdweird/repos","events_url":"https://api.github.com/users/stdweird/events{/privacy}","received_events_url":"https://api.github.com/users/stdweird/received_events","type":"User","site_admin":false},"body":"no oneliners ","created_at":"2014-09-22T12:51:55Z","updated_at":"2014-09-22T12:51:55Z","html_url":"https://github.com/hpcugent/hanythingondemand/pull/12#discussion_r17846318","pull_request_url":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/12","_links":{"self":{"href":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/comments/17846318"},"html":{"href":"https://github.com/hpcugent/hanythingondemand/pull/12#discussion_r17846318"},"pull_request":{"href":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/12"}}},"pull_request":{"url":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/12","id":21503629,"html_url":"https://github.com/hpcugent/hanythingondemand/pull/12","diff_url":"https://github.com/hpcugent/hanythingondemand/pull/12.diff","patch_url":"https://github.com/hpcugent/hanythingondemand/pull/12.patch","issue_url":"https://api.github.com/repos/hpcugent/hanythingondemand/issues/12","number":12,"state":"open","locked":false,"title":"Support multiple configs and make template params self documenting.","user":{"login":"ehiggs","id":28823,"avatar_url":"https://avatars.githubusercontent.com/u/28823?v=2","gravatar_id":"3e2cc7b120705cf613cb794e126c96bd","url":"https://api.github.com/users/ehiggs","html_url":"https://github.com/ehiggs","followers_url":"https://api.github.com/users/ehiggs/followers","following_url":"https://api.github.com/users/ehiggs/following{/other_user}","gists_url":"https://api.github.com/users/ehiggs/gists{/gist_id}","starred_url":"https://api.github.com/users/ehiggs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ehiggs/subscriptions","organizations_url":"https://api.github.com/users/ehiggs/orgs","repos_url":"https://api.github.com/users/ehiggs/repos","events_url":"https://api.github.com/users/ehiggs/events{/privacy}","received_events_url":"https://api.github.com/users/ehiggs/received_events","type":"User","site_admin":false},"body":"Template configs are self documenting and can be seen with `hod_pbs.py --help-templates`\r\n\r\nUsers can also specify multiple configs. e.g. `hod_pbs.py --config dir1/hod.conf,dir2/hod.conf`. This will merge the configs with the following rules:\r\n\r\n1: Strings from the second config override the first one.\r\n\r\n2. Lists (e.g. `service=taskrunner.conf,resourcemanager.conf`) will get concatenated so users can specify extra services, modules, env vars and the like.\r\n\r\n3. Dicts are merged using a deep merging algorithm.","created_at":"2014-09-19T15:11:25Z","updated_at":"2014-09-22T12:51:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":null,"assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/12/commits","review_comments_url":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/12/comments","review_comment_url":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/comments/{number}","comments_url":"https://api.github.com/repos/hpcugent/hanythingondemand/issues/12/comments","statuses_url":"https://api.github.com/repos/hpcugent/hanythingondemand/statuses/6d6e76ee3220440edf9f10ca49891d0737c32711","head":{"label":"ehiggs:multiconfig","ref":"multiconfig","sha":"6d6e76ee3220440edf9f10ca49891d0737c32711","user":{"login":"ehiggs","id":28823,"avatar_url":"https://avatars.githubusercontent.com/u/28823?v=2","gravatar_id":"3e2cc7b120705cf613cb794e126c96bd","url":"https://api.github.com/users/ehiggs","html_url":"https://github.com/ehiggs","followers_url":"https://api.github.com/users/ehiggs/followers","following_url":"https://api.github.com/users/ehiggs/following{/other_user}","gists_url":"https://api.github.com/users/ehiggs/gists{/gist_id}","starred_url":"https://api.github.com/users/ehiggs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ehiggs/subscriptions","organizations_url":"https://api.github.com/users/ehiggs/orgs","repos_url":"https://api.github.com/users/ehiggs/repos","events_url":"https://api.github.com/users/ehiggs/events{/privacy}","received_events_url":"https://api.github.com/users/ehiggs/received_events","type":"User","site_admin":false},"repo":{"id":17957270,"name":"hanythingondemand","full_name":"ehiggs/hanythingondemand","owner":{"login":"ehiggs","id":28823,"avatar_url":"https://avatars.githubusercontent.com/u/28823?v=2","gravatar_id":"3e2cc7b120705cf613cb794e126c96bd","url":"https://api.github.com/users/ehiggs","html_url":"https://github.com/ehiggs","followers_url":"https://api.github.com/users/ehiggs/followers","following_url":"https://api.github.com/users/ehiggs/following{/other_user}","gists_url":"https://api.github.com/users/ehiggs/gists{/gist_id}","starred_url":"https://api.github.com/users/ehiggs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ehiggs/subscriptions","organizations_url":"https://api.github.com/users/ehiggs/orgs","repos_url":"https://api.github.com/users/ehiggs/repos","events_url":"https://api.github.com/users/ehiggs/events{/privacy}","received_events_url":"https://api.github.com/users/ehiggs/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ehiggs/hanythingondemand","description":"hanythingondemand provides a set of scripts to easily set up an ad-hoc Hadoop cluster through PBS jobs ","fork":true,"url":"https://api.github.com/repos/ehiggs/hanythingondemand","forks_url":"https://api.github.com/repos/ehiggs/hanythingondemand/forks","keys_url":"https://api.github.com/repos/ehiggs/hanythingondemand/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ehiggs/hanythingondemand/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ehiggs/hanythingondemand/teams","hooks_url":"https://api.github.com/repos/ehiggs/hanythingondemand/hooks","issue_events_url":"https://api.github.com/repos/ehiggs/hanythingondemand/issues/events{/number}","events_url":"https://api.github.com/repos/ehiggs/hanythingondemand/events","assignees_url":"https://api.github.com/repos/ehiggs/hanythingondemand/assignees{/user}","branches_url":"https://api.github.com/repos/ehiggs/hanythingondemand/branches{/branch}","tags_url":"https://api.github.com/repos/ehiggs/hanythingondemand/tags","blobs_url":"https://api.github.com/repos/ehiggs/hanythingondemand/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ehiggs/hanythingondemand/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ehiggs/hanythingondemand/git/refs{/sha}","trees_url":"https://api.github.com/repos/ehiggs/hanythingondemand/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ehiggs/hanythingondemand/statuses/{sha}","languages_url":"https://api.github.com/repos/ehiggs/hanythingondemand/languages","stargazers_url":"https://api.github.com/repos/ehiggs/hanythingondemand/stargazers","contributors_url":"https://api.github.com/repos/ehiggs/hanythingondemand/contributors","subscribers_url":"https://api.github.com/repos/ehiggs/hanythingondemand/subscribers","subscription_url":"https://api.github.com/repos/ehiggs/hanythingondemand/subscription","commits_url":"https://api.github.com/repos/ehiggs/hanythingondemand/commits{/sha}","git_commits_url":"https://api.github.com/repos/ehiggs/hanythingondemand/git/commits{/sha}","comments_url":"https://api.github.com/repos/ehiggs/hanythingondemand/comments{/number}","issue_comment_url":"https://api.github.com/repos/ehiggs/hanythingondemand/issues/comments/{number}","contents_url":"https://api.github.com/repos/ehiggs/hanythingondemand/contents/{+path}","compare_url":"https://api.github.com/repos/ehiggs/hanythingondemand/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ehiggs/hanythingondemand/merges","archive_url":"https://api.github.com/repos/ehiggs/hanythingondemand/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ehiggs/hanythingondemand/downloads","issues_url":"https://api.github.com/repos/ehiggs/hanythingondemand/issues{/number}","pulls_url":"https://api.github.com/repos/ehiggs/hanythingondemand/pulls{/number}","milestones_url":"https://api.github.com/repos/ehiggs/hanythingondemand/milestones{/number}","notifications_url":"https://api.github.com/repos/ehiggs/hanythingondemand/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ehiggs/hanythingondemand/labels{/name}","releases_url":"https://api.github.com/repos/ehiggs/hanythingondemand/releases{/id}","created_at":"2014-03-20T20:22:21Z","updated_at":"2014-06-23T22:30:54Z","pushed_at":"2014-09-19T15:07:53Z","git_url":"git://github.com/ehiggs/hanythingondemand.git","ssh_url":"git@github.com:ehiggs/hanythingondemand.git","clone_url":"https://github.com/ehiggs/hanythingondemand.git","svn_url":"https://github.com/ehiggs/hanythingondemand","homepage":null,"size":713,"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":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"hpcugent:master","ref":"master","sha":"641ab1946242109f6150bc220e0dae3bec6adbd5","user":{"login":"hpcugent","id":1515263,"avatar_url":"https://avatars.githubusercontent.com/u/1515263?v=2","gravatar_id":"b12f36a4d0f123b4b185272bf876c728","url":"https://api.github.com/users/hpcugent","html_url":"https://github.com/hpcugent","followers_url":"https://api.github.com/users/hpcugent/followers","following_url":"https://api.github.com/users/hpcugent/following{/other_user}","gists_url":"https://api.github.com/users/hpcugent/gists{/gist_id}","starred_url":"https://api.github.com/users/hpcugent/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hpcugent/subscriptions","organizations_url":"https://api.github.com/users/hpcugent/orgs","repos_url":"https://api.github.com/users/hpcugent/repos","events_url":"https://api.github.com/users/hpcugent/events{/privacy}","received_events_url":"https://api.github.com/users/hpcugent/received_events","type":"Organization","site_admin":false},"repo":{"id":17631938,"name":"hanythingondemand","full_name":"hpcugent/hanythingondemand","owner":{"login":"hpcugent","id":1515263,"avatar_url":"https://avatars.githubusercontent.com/u/1515263?v=2","gravatar_id":"b12f36a4d0f123b4b185272bf876c728","url":"https://api.github.com/users/hpcugent","html_url":"https://github.com/hpcugent","followers_url":"https://api.github.com/users/hpcugent/followers","following_url":"https://api.github.com/users/hpcugent/following{/other_user}","gists_url":"https://api.github.com/users/hpcugent/gists{/gist_id}","starred_url":"https://api.github.com/users/hpcugent/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hpcugent/subscriptions","organizations_url":"https://api.github.com/users/hpcugent/orgs","repos_url":"https://api.github.com/users/hpcugent/repos","events_url":"https://api.github.com/users/hpcugent/events{/privacy}","received_events_url":"https://api.github.com/users/hpcugent/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hpcugent/hanythingondemand","description":"hanythingondemand provides a set of scripts to easily set up an ad-hoc Hadoop cluster through PBS jobs ","fork":false,"url":"https://api.github.com/repos/hpcugent/hanythingondemand","forks_url":"https://api.github.com/repos/hpcugent/hanythingondemand/forks","keys_url":"https://api.github.com/repos/hpcugent/hanythingondemand/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hpcugent/hanythingondemand/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hpcugent/hanythingondemand/teams","hooks_url":"https://api.github.com/repos/hpcugent/hanythingondemand/hooks","issue_events_url":"https://api.github.com/repos/hpcugent/hanythingondemand/issues/events{/number}","events_url":"https://api.github.com/repos/hpcugent/hanythingondemand/events","assignees_url":"https://api.github.com/repos/hpcugent/hanythingondemand/assignees{/user}","branches_url":"https://api.github.com/repos/hpcugent/hanythingondemand/branches{/branch}","tags_url":"https://api.github.com/repos/hpcugent/hanythingondemand/tags","blobs_url":"https://api.github.com/repos/hpcugent/hanythingondemand/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hpcugent/hanythingondemand/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hpcugent/hanythingondemand/git/refs{/sha}","trees_url":"https://api.github.com/repos/hpcugent/hanythingondemand/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hpcugent/hanythingondemand/statuses/{sha}","languages_url":"https://api.github.com/repos/hpcugent/hanythingondemand/languages","stargazers_url":"https://api.github.com/repos/hpcugent/hanythingondemand/stargazers","contributors_url":"https://api.github.com/repos/hpcugent/hanythingondemand/contributors","subscribers_url":"https://api.github.com/repos/hpcugent/hanythingondemand/subscribers","subscription_url":"https://api.github.com/repos/hpcugent/hanythingondemand/subscription","commits_url":"https://api.github.com/repos/hpcugent/hanythingondemand/commits{/sha}","git_commits_url":"https://api.github.com/repos/hpcugent/hanythingondemand/git/commits{/sha}","comments_url":"https://api.github.com/repos/hpcugent/hanythingondemand/comments{/number}","issue_comment_url":"https://api.github.com/repos/hpcugent/hanythingondemand/issues/comments/{number}","contents_url":"https://api.github.com/repos/hpcugent/hanythingondemand/contents/{+path}","compare_url":"https://api.github.com/repos/hpcugent/hanythingondemand/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hpcugent/hanythingondemand/merges","archive_url":"https://api.github.com/repos/hpcugent/hanythingondemand/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hpcugent/hanythingondemand/downloads","issues_url":"https://api.github.com/repos/hpcugent/hanythingondemand/issues{/number}","pulls_url":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls{/number}","milestones_url":"https://api.github.com/repos/hpcugent/hanythingondemand/milestones{/number}","notifications_url":"https://api.github.com/repos/hpcugent/hanythingondemand/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hpcugent/hanythingondemand/labels{/name}","releases_url":"https://api.github.com/repos/hpcugent/hanythingondemand/releases{/id}","created_at":"2014-03-11T13:48:31Z","updated_at":"2014-04-03T12:27:38Z","pushed_at":"2014-04-03T12:27:36Z","git_url":"git://github.com/hpcugent/hanythingondemand.git","ssh_url":"git@github.com:hpcugent/hanythingondemand.git","clone_url":"https://github.com/hpcugent/hanythingondemand.git","svn_url":"https://github.com/hpcugent/hanythingondemand","homepage":null,"size":676,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":11,"forks":2,"open_issues":11,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/12"},"html":{"href":"https://github.com/hpcugent/hanythingondemand/pull/12"},"issue":{"href":"https://api.github.com/repos/hpcugent/hanythingondemand/issues/12"},"comments":{"href":"https://api.github.com/repos/hpcugent/hanythingondemand/issues/12/comments"},"review_comments":{"href":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/12/comments"},"review_comment":{"href":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/hpcugent/hanythingondemand/pulls/12/commits"},"statuses":{"href":"https://api.github.com/repos/hpcugent/hanythingondemand/statuses/6d6e76ee3220440edf9f10ca49891d0737c32711"}}}}