{"action":"created","comment":{"url":"https://api.github.com/repos/ansible/ansible/pulls/comments/59222247","id":59222247,"diff_hunk":"@@ -0,0 +1,392 @@\n+.. _flow_modules:\n+\n+=======\n+Modules\n+=======\n+\n+This is an in-depth dive into understanding Ansible's program flow to execute\n+modules.  It will be of use to people working on the portions of the Core\n+Ansible Engine that execute a module, it may be of interest to people writing\n+Ansible Modules, and people simply wanting to use Ansible Modules will likely\n+not find anything helpful here.\n+\n+.. _flow_types_of_modules:\n+\n+Types of Modules\n+================\n+\n+Ansible supports several different types of modules in its code base.  Some of\n+these are for backwards compatibility and others to enable flexibility.\n+\n+.. _flow_action_plugins:\n+\n+Action Plugins\n+--------------\n+\n+Action Plugins look like modules to end users who are writing :term:`playbooks` but\n+they're distinct entities for the purposes of this paper.  Action Plugins\n+always execute on the controller. They sometimes are able to do all work there\n+(for instance, the debug Action Plugin which prints some text for the user to\n+see or the assert Action Plugin which can test whether several values in\n+a playbook satisfy certain criteria.)\n+\n+More often, Action Plugins set up some values and environment on the controller\n+and then invoke an actual module on the managed node that does something with\n+these values.  An easy to understand version of this is the\n+:ref:`template Action Plugin <template>`.  The\n+:ref:`template Action Plugin <template>` takes values from the user to\n+construct a file in a temporary location on the controller using variables\n+from the playbook environment.  It then transfers the temporary file to\n+a temporary file on the remote system.  After that, it invokes the\n+:ref:`copy module <copy>` which operates on the remote system to move the file\n+into its final location, set file permissions, and so on.\n+\n+.. _flow_new_style_modules:\n+\n+New-style Modules\n+-----------------\n+\n+All of the modules that ship with Ansible fall into this category.\n+\n+New-style modules have the arguments to the module embedded inside of them in\n+some manner.  Non-new-style modules have to copy a separate file over to the\n+managed node which is less efficient as it requires two over-the-wire\n+connections instead of only one.\n+\n+.. _flow_python_modules:\n+\n+Python\n+^^^^^^\n+\n+New-style python modules use the :ref:`ziploader` framework for constructing\n+modules.  All official modules (shipped with Ansible) use either this or the\n+:ref:`powershell module framework <flow_powershell_modules>`.\n+\n+These modules use imports from :code:`ansible.module_utils` in order to pull in\n+a lot of boilerplate module code such as argument parsing, formatting of return\n+values as :term:`JSON`, and various file operations.\n+\n+.. note:: In Ansible up to 2.0 the official python modules used the\n+    :ref:`module_replacer` framework.  For module authors, :ref:`ziploader` is\n+    largely a superset of :ref:`module_replacer` functionality so you usually\n+    do not need to know about one versus the other.\n+\n+.. _flow_powershell_modules:\n+\n+Powershell\n+^^^^^^^^^^\n+\n+New-style powershell modules use the :ref:`module_replacer` framework for\n+constructing modules.  These modules get a library of powershell code embedded\n+in them before being sent to the managed node.\n+\n+.. _flow_josnargs_modules:\n+\n+JSONARGS\n+^^^^^^^^\n+\n+Scripts can arrange for an argument string to be placed within them by placing\n+the string ``<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>`` somewhere inside of the\n+file.  The module will typically set a variable to that value like this::\n+\n+    json_arguments = \"\"\"<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>\"\"\"\n+\n+Which is expanded as::\n+\n+    json_arguments = \"\"\"{\"param1\": \"test's quotes\", \"param2\": \"\\\"To be or not to be\\\" - Hamlet\"}\"\"\"\n+\n+.. note:: Ansible outputs a :term:`JSON` string with bare quotes.  Double quotes are\n+       used to quote string values, double quotes inside of string values are\n+       backslash escaped, and single quotes may appear unescaped inside of\n+       a string value.  To use JSONARGS your scripting language must have a way\n+       to handle this type of string.  The example uses python's triple quoted\n+       strings to do this.  Other scripting languages may have a similar quote\n+       character that won't be confused by any quotes in the JSON or it may\n+       allow you to define your own start-of-quote and end-of-quote characters.\n+       If the language doesn't give you any of these then you'll need to write\n+       a :ref:`non-native JSON module <flow_want_json_modules>` or\n+       :ref:`Old-style module <flow_old_style_modules>` instead.\n+\n+The module will typically parse the contents of ``json_arguments`` using a json\n+library and then use them as native variables throughout the rest of its code.\n+\n+.. _flow_want_json_modules:\n+\n+Non-native want json modules\n+----------------------------\n+\n+If a module has the string ``WANT_JSON`` in it anywhere then Ansible will treat\n+it as a non-native module that accepts a filename as its only command line\n+parameter.  The filename is for a temporary file containing a :term:`JSON`\n+string containing th module's parameters.  The module needs to open the file,\n+read and parse the parameters, operate on the data, and print its return data\n+as a json encoded dictionary to stdout before exiting.\n+\n+These types of modules are self-contained entities.  As of Ansible 2.1, Ansible\n+only modifies them to change a shebang line if present.\n+\n+.. seealso:: Examples of Non-native modules written in ruby are in the `Ansible\n+    for Rubyists <https://github.com/ansible/ansible-for-rubyists>`_ repository.\n+\n+.. _flow_old_style_modules:\n+\n+Old-style Modules\n+-----------------\n+\n+Old-style modules are similar to :ref:`want JSON modules <flow_want_json_modules>` except that the\n+file that they take contains ``key=value`` pairs for their parameters instead of\n+:term:`JSON`.\n+\n+Ansible decides that a module is old style when it doesn't have any of the\n+markers that would show that it is one of the other types.\n+\n+.. _flow_how_modules_are_executed:\n+\n+How modules are executed\n+========================\n+\n+When a user uses :program:`ansible` or :program:`ansible-playbook`, they\n+specify a task to execute.  The task is usually the name of a module along\n+with several parameters to be passed to the module.  Ansible takes these\n+values and processes them in various ways before they are finally executed on\n+the remote machine.\n+\n+.. _flow_executor_task_executor:\n+\n+executor/task_executor\n+----------------------\n+\n+The TaskExecutor receives the module name and parameters that were parsed from\n+the :term:`playbook <playbooks>` (or command line in the case of\n+:command:`/usr/bin/ansible`).  It uses the name to decide whether it's looking\n+at a module or an :ref:`Action Plugin <flow_action_plugins>`.  If it's a module, it loads the\n+:ref:`Normal Action Plugin <flow_normal_action_plugin>` and passes the name,\n+variables, and other information about the task and play to that Action Plugin\n+for further processing.\n+\n+.. _flow_normal_action_plugin:\n+\n+Normal Action Plugin\n+--------------------\n+\n+The ``normal`` Action Plugin executes the module on the remote host.  It is\n+the primary coordinator of much of the work to actually execute the module on\n+the managed machine.\n+\n+* It takes care of creating a connection to the managed machine by\n+  instantiating a Connection class according to the inventory configuration for\n+  that host.\n+* It adds any internal ansible variables to the module's parameters (for\n+  instance, the ones that pass along ``no_log`` to the module).\n+* It takes care of creating any temporary files on the remote machine and\n+  cleans up afterwards.\n+* It does the actual work of pushing the module and module parameters to the\n+  remote host although the :ref:`module_common <flow_executor_module_common>`\n+  code described next does the work of deciding which format those will take.\n+* Handles any special cases regarding modules (for instance, various\n+  complications around Windows modules that need to have the same names as\n+  python modules so that internal calling of modules from other Action Plugins\n+  work.)\n+\n+Much of this functionality comes from the :code:`BaseAction`BaseAction class\n+which lives in :file:`plugins/action/__init__.py`.  It makes use of Connection\n+and Shell objects to do its work.\n+\n+.. _flow_executor_module_common:\n+\n+executor/module_common.py\n+-------------------------\n+\n+Code in :file:`executor/module_common.py` takes care of assembling the module\n+to be shipped to the managed node.  The module is first read in, then examined\n+to determine its type.  :ref:`PowerShell <flow_powershell_modules>` and\n+:ref:`JSON-args modules <flow_jsonargs_modules>` are passed through\n+:ref:`Module Replacer <module_replacer>`.  New-style\n+:ref:`python modules <flow_python_modules>` are are assembled by\n+:ref:`ziploader`.\n+:ref:`Non-native-want-json <flow_want_json_modules>` and\n+:ref:`Old-Style modules <flow_old_style_modules>` aren't touched by either of\n+these and pass through unchanged.  After the assembling step, one final\n+modification is made to all modules that have a shebang line.  We check\n+whether the interpreter in the shebang line has a specific path configured via\n+an ``ansible_$X_interpreter`` inventory variable.  If it does we substitute that\n+path for the interpreter path given in the module.  After this we return the\n+complete module data and the module type to the Normal Action which continues\n+execution of the module.\n+\n+Next we'll go into some details of the two assembler frameworks.\n+\n+.. _module_replacer:\n+\n+module replacer\n+^^^^^^^^^^^^^^^\n+\n+Module replacer is essentially a preprocessor (like the C Preprocessor for\n+those familiar with that language).  It does straight substitutions of specific\n+substring patterns in the module file.  There are two types of substitutions:\n+\n+* Replacements that only happen in the module file.  These are public\n+  replacement strings that modules can utilize to get helpful boilerplate or\n+  access to arguments.\n+\n+  - :code:`from ansible.module_utils.MOD_LIB_NAME import *` is replaced with the\n+    contents of the :file:`ansible/module_utils/MOD_LIB_NAME.py`  These should\n+    only be used with :ref:`new-style python modules <flow_python_modules>`.\n+  - :code:`#<<INCLUDE_ANSIBLE_MODULE_COMMON>>` is equivalent to\n+    :code:`from ansible.module_utils.basic import *` and should also only apply\n+    to new-style python modules.\n+  - :code:`# POWERSHELL_COMMON` substitutes the contents of\n+    :file:`ansible/module_utils/powershell.ps1`.  It should only be used with\n+    :ref:`new-style Powershell modules <flow_powershell_modules>`.\n+\n+* Replacements that are used by ansible ``module_utils`` code.  These are internal\n+  replacement patterns.  They may be used internally in the above public\n+  replacements but shouldn't be used directly by modules.\n+\n+  - :code:`\"<<ANSIBLE_VERSION>>\"` is substituted with the ansible version.  In\n+    a new-style python module, it's better to use ``from ansible import\n+    __version__`` and then use ``__version__`` instead.\n+  - :code:`\"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>\"` is substituted with\n+    a string which is the python ``repr`` of the :term:`JSON` encoded module\n+    parameters.  Using repr on the JSON string makes it safe to embed in\n+    a python file.  In :ref:`new-style python modules <flow_python_modules>`\n+    under :ref:`ziploader` this will be passed in via an environment variable\n+    instead.\n+  - :code:`<<SELINUX_SPECIAL_FILESYSTEMS>>` substitutes a string which is\n+    a comma separated list of filesystems which have a file system dependent\n+    security context in selinux.  In new-style python modules, this will be","path":"docsite/rst/developing_program_flow_modules.rst","position":257,"original_position":257,"commit_id":"d4faa430e98c2308e818a44d17ffad5ebc486619","original_commit_id":"d4faa430e98c2308e818a44d17ffad5ebc486619","user":{"login":"docschick","id":12143055,"avatar_url":"https://avatars.githubusercontent.com/u/12143055?v=3","gravatar_id":"","url":"https://api.github.com/users/docschick","html_url":"https://github.com/docschick","followers_url":"https://api.github.com/users/docschick/followers","following_url":"https://api.github.com/users/docschick/following{/other_user}","gists_url":"https://api.github.com/users/docschick/gists{/gist_id}","starred_url":"https://api.github.com/users/docschick/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/docschick/subscriptions","organizations_url":"https://api.github.com/users/docschick/orgs","repos_url":"https://api.github.com/users/docschick/repos","events_url":"https://api.github.com/users/docschick/events{/privacy}","received_events_url":"https://api.github.com/users/docschick/received_events","type":"User","site_admin":false},"body":"s/selinux/SELinux","created_at":"2016-04-11T15:13:54Z","updated_at":"2016-04-11T15:13:54Z","html_url":"https://github.com/ansible/ansible/pull/15355#discussion_r59222247","pull_request_url":"https://api.github.com/repos/ansible/ansible/pulls/15355","_links":{"self":{"href":"https://api.github.com/repos/ansible/ansible/pulls/comments/59222247"},"html":{"href":"https://github.com/ansible/ansible/pull/15355#discussion_r59222247"},"pull_request":{"href":"https://api.github.com/repos/ansible/ansible/pulls/15355"}}},"pull_request":{"url":"https://api.github.com/repos/ansible/ansible/pulls/15355","id":65891328,"html_url":"https://github.com/ansible/ansible/pull/15355","diff_url":"https://github.com/ansible/ansible/pull/15355.diff","patch_url":"https://github.com/ansible/ansible/pull/15355.patch","issue_url":"https://api.github.com/repos/ansible/ansible/issues/15355","number":15355,"state":"open","locked":false,"title":"Core module program flow and glossary","user":{"login":"abadger","id":209242,"avatar_url":"https://avatars.githubusercontent.com/u/209242?v=3","gravatar_id":"","url":"https://api.github.com/users/abadger","html_url":"https://github.com/abadger","followers_url":"https://api.github.com/users/abadger/followers","following_url":"https://api.github.com/users/abadger/following{/other_user}","gists_url":"https://api.github.com/users/abadger/gists{/gist_id}","starred_url":"https://api.github.com/users/abadger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abadger/subscriptions","organizations_url":"https://api.github.com/users/abadger/orgs","repos_url":"https://api.github.com/users/abadger/repos","events_url":"https://api.github.com/users/abadger/events{/privacy}","received_events_url":"https://api.github.com/users/abadger/received_events","type":"User","site_admin":false},"body":"##### ISSUE TYPE\r\n\r\n - Docs Pull Request\r\n\r\n##### SUMMARY\r\n\r\nI wrote up a document on how ansible invokes modules while I was working on ziploader.  Wanted to make sure that it didn't go to waste.  This PR creates a new area of the Developing Docs for Developing Ansible Core.  Presently the only document in that area is this document on the Program Flow when Ansible invokes a module but we could add others for Variable Manager, how Ansible invokese a Strategy, etc.\r\n\r\nWhile I was at it I noticed that ```:term:``` wasn't working.  When I looked into why that was i found that the glossary wasn't a real Sphinx glossary.  Switched that over and added some links between elements in the glossary.","created_at":"2016-04-09T20:17:15Z","updated_at":"2016-04-11T15:13:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"48fac4339cd44e521107b02dc506a814c420084b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ansible/ansible/pulls/15355/commits","review_comments_url":"https://api.github.com/repos/ansible/ansible/pulls/15355/comments","review_comment_url":"https://api.github.com/repos/ansible/ansible/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ansible/ansible/issues/15355/comments","statuses_url":"https://api.github.com/repos/ansible/ansible/statuses/d4faa430e98c2308e818a44d17ffad5ebc486619","head":{"label":"abadger:core-module-program-flow","ref":"core-module-program-flow","sha":"d4faa430e98c2308e818a44d17ffad5ebc486619","user":{"login":"abadger","id":209242,"avatar_url":"https://avatars.githubusercontent.com/u/209242?v=3","gravatar_id":"","url":"https://api.github.com/users/abadger","html_url":"https://github.com/abadger","followers_url":"https://api.github.com/users/abadger/followers","following_url":"https://api.github.com/users/abadger/following{/other_user}","gists_url":"https://api.github.com/users/abadger/gists{/gist_id}","starred_url":"https://api.github.com/users/abadger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abadger/subscriptions","organizations_url":"https://api.github.com/users/abadger/orgs","repos_url":"https://api.github.com/users/abadger/repos","events_url":"https://api.github.com/users/abadger/events{/privacy}","received_events_url":"https://api.github.com/users/abadger/received_events","type":"User","site_admin":false},"repo":{"id":17755774,"name":"ansible","full_name":"abadger/ansible","owner":{"login":"abadger","id":209242,"avatar_url":"https://avatars.githubusercontent.com/u/209242?v=3","gravatar_id":"","url":"https://api.github.com/users/abadger","html_url":"https://github.com/abadger","followers_url":"https://api.github.com/users/abadger/followers","following_url":"https://api.github.com/users/abadger/following{/other_user}","gists_url":"https://api.github.com/users/abadger/gists{/gist_id}","starred_url":"https://api.github.com/users/abadger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abadger/subscriptions","organizations_url":"https://api.github.com/users/abadger/orgs","repos_url":"https://api.github.com/users/abadger/repos","events_url":"https://api.github.com/users/abadger/events{/privacy}","received_events_url":"https://api.github.com/users/abadger/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/abadger/ansible","description":"Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications— automate in a language that approaches plain English, using SSH, with no agents to install on remote systems.","fork":true,"url":"https://api.github.com/repos/abadger/ansible","forks_url":"https://api.github.com/repos/abadger/ansible/forks","keys_url":"https://api.github.com/repos/abadger/ansible/keys{/key_id}","collaborators_url":"https://api.github.com/repos/abadger/ansible/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/abadger/ansible/teams","hooks_url":"https://api.github.com/repos/abadger/ansible/hooks","issue_events_url":"https://api.github.com/repos/abadger/ansible/issues/events{/number}","events_url":"https://api.github.com/repos/abadger/ansible/events","assignees_url":"https://api.github.com/repos/abadger/ansible/assignees{/user}","branches_url":"https://api.github.com/repos/abadger/ansible/branches{/branch}","tags_url":"https://api.github.com/repos/abadger/ansible/tags","blobs_url":"https://api.github.com/repos/abadger/ansible/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/abadger/ansible/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/abadger/ansible/git/refs{/sha}","trees_url":"https://api.github.com/repos/abadger/ansible/git/trees{/sha}","statuses_url":"https://api.github.com/repos/abadger/ansible/statuses/{sha}","languages_url":"https://api.github.com/repos/abadger/ansible/languages","stargazers_url":"https://api.github.com/repos/abadger/ansible/stargazers","contributors_url":"https://api.github.com/repos/abadger/ansible/contributors","subscribers_url":"https://api.github.com/repos/abadger/ansible/subscribers","subscription_url":"https://api.github.com/repos/abadger/ansible/subscription","commits_url":"https://api.github.com/repos/abadger/ansible/commits{/sha}","git_commits_url":"https://api.github.com/repos/abadger/ansible/git/commits{/sha}","comments_url":"https://api.github.com/repos/abadger/ansible/comments{/number}","issue_comment_url":"https://api.github.com/repos/abadger/ansible/issues/comments{/number}","contents_url":"https://api.github.com/repos/abadger/ansible/contents/{+path}","compare_url":"https://api.github.com/repos/abadger/ansible/compare/{base}...{head}","merges_url":"https://api.github.com/repos/abadger/ansible/merges","archive_url":"https://api.github.com/repos/abadger/ansible/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/abadger/ansible/downloads","issues_url":"https://api.github.com/repos/abadger/ansible/issues{/number}","pulls_url":"https://api.github.com/repos/abadger/ansible/pulls{/number}","milestones_url":"https://api.github.com/repos/abadger/ansible/milestones{/number}","notifications_url":"https://api.github.com/repos/abadger/ansible/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/abadger/ansible/labels{/name}","releases_url":"https://api.github.com/repos/abadger/ansible/releases{/id}","deployments_url":"https://api.github.com/repos/abadger/ansible/deployments","created_at":"2014-03-14T18:20:10Z","updated_at":"2016-03-10T15:07:40Z","pushed_at":"2016-04-11T14:14:40Z","git_url":"git://github.com/abadger/ansible.git","ssh_url":"git@github.com:abadger/ansible.git","clone_url":"https://github.com/abadger/ansible.git","svn_url":"https://github.com/abadger/ansible","homepage":"http://ansible.com/","size":40240,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":1,"default_branch":"devel"}},"base":{"label":"ansible:devel","ref":"devel","sha":"005dc84aa744c1cb71995d4f554fb946c19d1bc6","user":{"login":"ansible","id":1507452,"avatar_url":"https://avatars.githubusercontent.com/u/1507452?v=3","gravatar_id":"","url":"https://api.github.com/users/ansible","html_url":"https://github.com/ansible","followers_url":"https://api.github.com/users/ansible/followers","following_url":"https://api.github.com/users/ansible/following{/other_user}","gists_url":"https://api.github.com/users/ansible/gists{/gist_id}","starred_url":"https://api.github.com/users/ansible/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ansible/subscriptions","organizations_url":"https://api.github.com/users/ansible/orgs","repos_url":"https://api.github.com/users/ansible/repos","events_url":"https://api.github.com/users/ansible/events{/privacy}","received_events_url":"https://api.github.com/users/ansible/received_events","type":"Organization","site_admin":false},"repo":{"id":3638964,"name":"ansible","full_name":"ansible/ansible","owner":{"login":"ansible","id":1507452,"avatar_url":"https://avatars.githubusercontent.com/u/1507452?v=3","gravatar_id":"","url":"https://api.github.com/users/ansible","html_url":"https://github.com/ansible","followers_url":"https://api.github.com/users/ansible/followers","following_url":"https://api.github.com/users/ansible/following{/other_user}","gists_url":"https://api.github.com/users/ansible/gists{/gist_id}","starred_url":"https://api.github.com/users/ansible/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ansible/subscriptions","organizations_url":"https://api.github.com/users/ansible/orgs","repos_url":"https://api.github.com/users/ansible/repos","events_url":"https://api.github.com/users/ansible/events{/privacy}","received_events_url":"https://api.github.com/users/ansible/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ansible/ansible","description":"Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy. Avoid writing scripts or custom code to deploy and update your applications— automate in a language that approaches plain English, using SSH, with no agents to install on remote systems.","fork":false,"url":"https://api.github.com/repos/ansible/ansible","forks_url":"https://api.github.com/repos/ansible/ansible/forks","keys_url":"https://api.github.com/repos/ansible/ansible/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ansible/ansible/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ansible/ansible/teams","hooks_url":"https://api.github.com/repos/ansible/ansible/hooks","issue_events_url":"https://api.github.com/repos/ansible/ansible/issues/events{/number}","events_url":"https://api.github.com/repos/ansible/ansible/events","assignees_url":"https://api.github.com/repos/ansible/ansible/assignees{/user}","branches_url":"https://api.github.com/repos/ansible/ansible/branches{/branch}","tags_url":"https://api.github.com/repos/ansible/ansible/tags","blobs_url":"https://api.github.com/repos/ansible/ansible/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ansible/ansible/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ansible/ansible/git/refs{/sha}","trees_url":"https://api.github.com/repos/ansible/ansible/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ansible/ansible/statuses/{sha}","languages_url":"https://api.github.com/repos/ansible/ansible/languages","stargazers_url":"https://api.github.com/repos/ansible/ansible/stargazers","contributors_url":"https://api.github.com/repos/ansible/ansible/contributors","subscribers_url":"https://api.github.com/repos/ansible/ansible/subscribers","subscription_url":"https://api.github.com/repos/ansible/ansible/subscription","commits_url":"https://api.github.com/repos/ansible/ansible/commits{/sha}","git_commits_url":"https://api.github.com/repos/ansible/ansible/git/commits{/sha}","comments_url":"https://api.github.com/repos/ansible/ansible/comments{/number}","issue_comment_url":"https://api.github.com/repos/ansible/ansible/issues/comments{/number}","contents_url":"https://api.github.com/repos/ansible/ansible/contents/{+path}","compare_url":"https://api.github.com/repos/ansible/ansible/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ansible/ansible/merges","archive_url":"https://api.github.com/repos/ansible/ansible/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ansible/ansible/downloads","issues_url":"https://api.github.com/repos/ansible/ansible/issues{/number}","pulls_url":"https://api.github.com/repos/ansible/ansible/pulls{/number}","milestones_url":"https://api.github.com/repos/ansible/ansible/milestones{/number}","notifications_url":"https://api.github.com/repos/ansible/ansible/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ansible/ansible/labels{/name}","releases_url":"https://api.github.com/repos/ansible/ansible/releases{/id}","deployments_url":"https://api.github.com/repos/ansible/ansible/deployments","created_at":"2012-03-06T14:58:02Z","updated_at":"2016-04-11T14:40:16Z","pushed_at":"2016-04-11T14:22:20Z","git_url":"git://github.com/ansible/ansible.git","ssh_url":"git@github.com:ansible/ansible.git","clone_url":"https://github.com/ansible/ansible.git","svn_url":"https://github.com/ansible/ansible","homepage":"http://ansible.com/","size":55415,"stargazers_count":16229,"watchers_count":16229,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":4845,"mirror_url":null,"open_issues_count":1305,"forks":4845,"open_issues":1305,"watchers":16229,"default_branch":"devel"}},"_links":{"self":{"href":"https://api.github.com/repos/ansible/ansible/pulls/15355"},"html":{"href":"https://github.com/ansible/ansible/pull/15355"},"issue":{"href":"https://api.github.com/repos/ansible/ansible/issues/15355"},"comments":{"href":"https://api.github.com/repos/ansible/ansible/issues/15355/comments"},"review_comments":{"href":"https://api.github.com/repos/ansible/ansible/pulls/15355/comments"},"review_comment":{"href":"https://api.github.com/repos/ansible/ansible/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ansible/ansible/pulls/15355/commits"},"statuses":{"href":"https://api.github.com/repos/ansible/ansible/statuses/d4faa430e98c2308e818a44d17ffad5ebc486619"}}}}