{"action":"created","comment":{"url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/comments/42503597","id":42503597,"diff_hunk":"@@ -0,0 +1,400 @@\n+---\n+layout: post\n+title: \"Life Without DevStack: Upstream Development With OSA\"\n+date: 2015-10-26 10:00\n+comments: true\n+author: Miguel Grinberg\n+published: true\n+categories:\n+    - openstack\n+    - osad\n+    - ansible\n+---\n+\n+If you are an OpenStack contributor, you likely rely on DevStack for most of\n+your work. DevStack is, and has been for a long time, the de-facto platform\n+that contributors use for development, testing and reviews. In this article I\n+want to introduce you to a project I'm a contributor of, called\n+[openstack-ansible](https://github.com/openstack/openstack-ansible). For the\n+last few months I have been using this project as an alternative to DevStack\n+for OpenStack upstream development, and the experience has been very positive.\n+\n+<!-- more -->\n+\n+What’s Wrong with DevStack?\n+---------------------------\n+\n+Before I delve into openstack-ansible, I want to briefly discuss the reasons\n+that motivated me to look for an alternative to DevStack. Overall, DevStack is\n+a well rounded project, but there are a couple of architectural decisions that\n+bother me.\n+\n+First of all, DevStack comes with a monolithic installer. To perform an\n+install, you run `stack.sh` and that installs all the modules you configured.\n+If you later want to add or remove modules, the only option is to run\n+`unstack.sh` to uninstall everything, and then re-run `stack.sh` with the\n+updated configuration. It happened to me a few times that when making source\n+code changes to a module I inadvertently caused the module to operate in an\n+erratic way. If I'm in that situation, the safest option is to reinstall it,\n+and the only way to do that with DevStack is to reinstall everything.\n+\n+An interesting characteristic of DevStack is that it performs a development\n+installation of all the modules, which creates an environment that is very\n+different from production deployments. In my opinion, a proper development\n+environment would have the module I'm working on installed for development,\n+while everything else installed for production. This is not possible to do with\n+DevStack.\n+\n+Another problem I used to have with DevStack is the constant fight to keep\n+dependencies in a consistent state. In DevStack, dependencies are shared among\n+all the modules, so a simple action of syncing the dependencies for one module\n+may cause a chain reaction that requires updating several other modules. To\n+some extent, this can be alleviated in recent DevStack releases with the use of\n+per-module virtual environments, but even with that, OS level packages remain\n+shared.\n+\n+What is openstack-ansible (OSA)?\n+--------------------------------\n+\n+The [openstack-ansible](https://github.com/openstack/openstack-ansible) project\n+is a Rackspace open source initiative that uses the power of\n+[Ansible](http://www.ansible.com/) to deploy OpenStack. Note that you may have\n+heard of this project with the name *os-ansible-deployment* on StackForge\n+before it moved to the OpenStack big tent.\n+\n+Like DevStack, openstack-ansible deploys all the OpenStack services directly\n+from their git repositories, without any vendor patches or add-ons. But the big\n+difference is that openstack-ansible deploys the OpenStack services in [LXC\n+containers](https://linuxcontainers.org/lxc/introduction/), so there is\n+complete OS level and Python package isolation between the services hosted on a\n+node.\n+\n+Another difference between DevStack and openstack-ansible is that the latter\n+is a production distribution. With it, you can deploy enterprise scale private\n+clouds that range from a handful nodes to large cluster with hundreds or even\n+thousands of nodes.\n+\n+The following diagram shows the structure of an openstack-ansible private\n+cloud:\n+\n+{% img center 2015-10-26-life-without-devstack-upstream-development-with-osa/osa-arch.jpg \"openstack-ansible architecture\" %}\n+\n+After looking at this you are probably scratching your head thinking how can\n+this project match the simplicity of DevStack for upstream development, given\n+that it is clearly oriented to multi-node private clouds. Do not despair, this\n+is the topic of the next section.\n+\n+OSA All-In-One\n+--------------\n+\n+The team that maintains the openstack-ansible project (of which I'm a part of),\n+uses a single-node deployment for day-to-day work and for gating, as that is\n+much more convenient and resource efficient. With this method of deployment it\n+is possible to stand up OSA on a cloud server or virtual machine, so taking\n+advantage of this feature makes this project comparable to DevStack.\n+\n+Unfortunately, the host requirements for a single-node deployment of OSA are\n+higher than DevStack, mainly due to the overhead introduced by the container\n+infrastructure. For a usable installation, the host must have 16GB of RAM and\n+80GB of disk space. At this time the only host OS that is supported is Ubuntu\n+14.04.\n+\n+One nice feature that OSA has against DevStack is that thanks to the\n+containerized architecture, it can deploy redundant services even on a\n+single-node install. On a default single-node deployment, galera, rabbitmq and\n+keystone are deployed with redundancy, and HAProxy is installed in the host to\n+do the load balancing.\n+\n+Are you ready to get your hands dirty? If you have access to a fresh Ubuntu\n+14.04 server that meets the specs mentioned above, you can clone the OSA\n+repository with the following commands:\n+\n+    # apt-get -y install git\n+    # git clone https://github.com/openstack/openstack-ansible /opt/openstack-ansible\n+\n+The directory in which the project is cloned does not need to be\n+*/opt/openstack-ansible*, you can really clone it anywhere you like.\n+\n+The next step is to generate a single-node configuration file. Luckily, the\n+project comes with a script that does that for you:\n+\n+    # cd /opt/openstack-ansible\n+    # scripts/bootstrap-aio.sh\n+\n+After the above command runs, the directory */etc/openstack_deploy* will be\n+populated with several configuration files in [YAML](http://yaml.org/) format.\n+Of particular interest is file *user_secrets.yml*, which contains all the\n+passwords that will be used in your installation. These passwords are randomly\n+generated, so they are hard to remember. I typically edit the admin password\n+since I will use it a lot. Basically I change this:\n+\n+    keystone_auth_admin_password: cY3QHwjMLRdSuZMlKI3OvujScCNeIMdH\n+\n+to this:\n+\n+    keystone_auth_admin_password: secrete\n+\n+The remaining passwords are not that useful in most cases, so I leave them\n+alone. But you can change any password you think you may need to use to\n+something that is easy to remember.\n+\n+The next step is to run another script that installs Ansible in the host, plus\n+a few Ansible extras and wrapper scripts that simplify its use:\n+\n+    # scripts/bootstrap-ansible.sh\n+\n+At this point the host is ready to receive the OSA install, so the final step\n+is to run the Ansible playbooks that carry on the installation:\n+\n+    # scripts/run-playbooks.sh\n+\n+On a Rackspace Public Cloud server, a full run through all the playbooks takes\n+about 45 minutes to complete. One nice aspect of working with Ansible is that\n+all the tasks are idempotent, meaning that the playbooks can be executed\n+multiple times without causing any problem. If a task has already been\n+performed, running it a second time does effectively nothing. This is actually\n+very useful, as it makes it possible to re-configure a live system simply by\n+changing the appropriate configuration files and re-running the playbooks,\n+without the need to tear everything down first.\n+\n+A Quick Tour of openstack-ansible\n+---------------------------------\n+\n+In this section I want to give you an overview of the OSA single-node\n+structure, at least so that those of you that were brave enough to stand one\n+up know where is everything.\n+\n+First of all, the Horizon dashboard is deployed and should be accessible on the\n+public IP address of the host. You can use the *admin* account, with the\n+password that you entered in the */etc/openstack_deploy/user_secrets.yml* file.\n+If you did not edit this file, you have to open this file and locate the\n+`keystone_auth_admin_password` setting to find out what password was used.\n+\n+As I mentioned above, the servers are all installed in LXC containers. The\n+following command shows you the list of containers:\n+\n+    root@miguel-lxc-server:~# lxc-ls -f\n+    NAME                                          STATE    IPV4                                        IPV6  AUTOSTART\n+    --------------------------------------------------------------------------------------------------------------------------------\n+    aio1_ceilometer_api_container-c8e825de        RUNNING  10.0.3.203, 172.29.237.195                  -     YES (onboot, openstack)\n+    aio1_ceilometer_collector_container-2da3371f  RUNNING  10.0.3.10, 172.29.238.178                   -     YES (onboot, openstack)\n+    aio1_cinder_api_container-88e59c04            RUNNING  10.0.3.125, 172.29.238.106, 172.29.247.183  -     YES (onboot, openstack)\n+    aio1_cinder_scheduler_container-69d2bec4      RUNNING  10.0.3.4, 172.29.239.79                     -     YES (onboot, openstack)\n+    aio1_galera_container-2f36d624                RUNNING  10.0.3.95, 172.29.237.18                    -     YES (onboot, openstack)\n+    aio1_galera_container-3b8e14d7                RUNNING  10.0.3.18, 172.29.237.166                   -     YES (onboot, openstack)\n+    aio1_galera_container-618973ae                RUNNING  10.0.3.82, 172.29.238.189                   -     YES (onboot, openstack)\n+    aio1_glance_container-4b41140f                RUNNING  10.0.3.21, 172.29.237.77, 172.29.246.233    -     YES (onboot, openstack)\n+    aio1_heat_apis_container-40ec9f3e             RUNNING  10.0.3.193, 172.29.239.6                    -     YES (onboot, openstack)\n+    aio1_heat_engine_container-36e270c9           RUNNING  10.0.3.171, 172.29.239.171                  -     YES (onboot, openstack)\n+    aio1_horizon_container-3497588e               RUNNING  10.0.3.33, 172.29.239.114                   -     YES (onboot, openstack)\n+    aio1_horizon_container-6cac5348               RUNNING  10.0.3.30, 172.29.238.168                   -     YES (onboot, openstack)\n+    aio1_keystone_container-821e7cf8              RUNNING  10.0.3.38, 172.29.238.105                   -     YES (onboot, openstack)\n+    aio1_keystone_container-d63c657e              RUNNING  10.0.3.69, 172.29.239.208                   -     YES (onboot, openstack)\n+    aio1_memcached_container-8baf34d5             RUNNING  10.0.3.158, 172.29.237.135                  -     YES (onboot, openstack)\n+    aio1_neutron_agents_container-21b819b7        RUNNING  10.0.3.233, 172.29.239.130, 172.29.240.182  -     YES (onboot, openstack)\n+    aio1_neutron_server_container-b4279bbe        RUNNING  10.0.3.52, 172.29.239.216                   -     YES (onboot, openstack)\n+    aio1_nova_api_metadata_container-79faf41a     RUNNING  10.0.3.60, 172.29.239.110                   -     YES (onboot, openstack)\n+    aio1_nova_api_os_compute_container-fed67563   RUNNING  10.0.3.231, 172.29.239.17                   -     YES (onboot, openstack)\n+    aio1_nova_cert_container-72f66c56             RUNNING  10.0.3.155, 172.29.237.152                  -     YES (onboot, openstack)\n+    aio1_nova_conductor_container-7d0f1b0f        RUNNING  10.0.3.164, 172.29.239.144                  -     YES (onboot, openstack)\n+    aio1_nova_console_container-62af2918          RUNNING  10.0.3.106, 172.29.238.236                  -     YES (onboot, openstack)\n+    aio1_nova_scheduler_container-e6b79b3b        RUNNING  10.0.3.250, 172.29.236.153                  -     YES (onboot, openstack)\n+    aio1_rabbit_mq_container-0e0fe308             RUNNING  10.0.3.86, 172.29.239.93                    -     YES (onboot, openstack)\n+    aio1_rabbit_mq_container-a4a04124             RUNNING  10.0.3.253, 172.29.237.188                  -     YES (onboot, openstack)\n+    aio1_rabbit_mq_container-b9c6dce6             RUNNING  10.0.3.22, 172.29.238.111                   -     YES (onboot, openstack)\n+    aio1_repo_container-6a8377fc                  RUNNING  10.0.3.102, 172.29.237.47                   -     YES (onboot, openstack)\n+    aio1_repo_container-b92c563a                  RUNNING  10.0.3.223, 172.29.239.251                  -     YES (onboot, openstack)\n+    aio1_rsyslog_container-a6e4f7d4               RUNNING  10.0.3.170, 172.29.237.249                  -     YES (onboot, openstack)\n+    aio1_swift_proxy_container-9f0130d3           RUNNING  10.0.3.20, 172.29.237.227, 172.29.247.52    -     YES (onboot, openstack)\n+    aio1_utility_container-d83fab91               RUNNING  10.0.3.39, 172.29.237.161                   -     YES (onboot, openstack)\n+\n+By going through this list you can see what services were deployed. You can\n+get inside a container using the `lxc-attach` command. A particularly\n+interesting container is the one with the *utility* name at the bottom of the\n+list. To enter this container this is the command that you should use:\n+\n+    # lxc-attach -n aio1_utility_container-d83fab91\n+\n+The utility container is useful because it has all the OpenStack command line\n+clients installed, plus a ready to go *openrc* file for the admin account.\n+Below you can see an example session in which I use the `openstack` utility to","path":"_posts/2015-10-26-life-without-devstack-upstream-development-with-osa.md","position":220,"original_position":220,"commit_id":"d81ed14b0aebed9778d84cb3f9857faba0c3eede","original_commit_id":"d81ed14b0aebed9778d84cb3f9857faba0c3eede","user":{"login":"catlook","id":5709104,"avatar_url":"https://avatars.githubusercontent.com/u/5709104?v=3","gravatar_id":"","url":"https://api.github.com/users/catlook","html_url":"https://github.com/catlook","followers_url":"https://api.github.com/users/catlook/followers","following_url":"https://api.github.com/users/catlook/following{/other_user}","gists_url":"https://api.github.com/users/catlook/gists{/gist_id}","starred_url":"https://api.github.com/users/catlook/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/catlook/subscriptions","organizations_url":"https://api.github.com/users/catlook/orgs","repos_url":"https://api.github.com/users/catlook/repos","events_url":"https://api.github.com/users/catlook/events{/privacy}","received_events_url":"https://api.github.com/users/catlook/received_events","type":"User","site_admin":false},"body":"In the following example session, I use the `openstack` utility to","created_at":"2015-10-20T14:37:34Z","updated_at":"2015-10-20T14:37:34Z","html_url":"https://github.com/rackerlabs/docs-developer-blog/pull/108#discussion_r42503597","pull_request_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/108","_links":{"self":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/comments/42503597"},"html":{"href":"https://github.com/rackerlabs/docs-developer-blog/pull/108#discussion_r42503597"},"pull_request":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/108"}}},"pull_request":{"url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/108","id":48151813,"html_url":"https://github.com/rackerlabs/docs-developer-blog/pull/108","diff_url":"https://github.com/rackerlabs/docs-developer-blog/pull/108.diff","patch_url":"https://github.com/rackerlabs/docs-developer-blog/pull/108.patch","issue_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/108","number":108,"state":"open","locked":false,"title":"Life Without DevStack","user":{"login":"miguelgrinberg","id":2715854,"avatar_url":"https://avatars.githubusercontent.com/u/2715854?v=3","gravatar_id":"","url":"https://api.github.com/users/miguelgrinberg","html_url":"https://github.com/miguelgrinberg","followers_url":"https://api.github.com/users/miguelgrinberg/followers","following_url":"https://api.github.com/users/miguelgrinberg/following{/other_user}","gists_url":"https://api.github.com/users/miguelgrinberg/gists{/gist_id}","starred_url":"https://api.github.com/users/miguelgrinberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/miguelgrinberg/subscriptions","organizations_url":"https://api.github.com/users/miguelgrinberg/orgs","repos_url":"https://api.github.com/users/miguelgrinberg/repos","events_url":"https://api.github.com/users/miguelgrinberg/events{/privacy}","received_events_url":"https://api.github.com/users/miguelgrinberg/received_events","type":"User","site_admin":false},"body":"This article is a companion to the talk I'm giving at the Openstack Summit in Tokyo on 2015/10/27. It would be good if it gets published on 10/26, which with the time difference will be more or less the time I give the talk over there.","created_at":"2015-10-20T03:02:48Z","updated_at":"2015-10-20T14:37:34Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cfb54bbbe0ecf767ff0bc51862715a1ecf5d724d","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/108/commits","review_comments_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/108/comments","review_comment_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/108/comments","statuses_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/statuses/d81ed14b0aebed9778d84cb3f9857faba0c3eede","head":{"label":"miguelgrinberg:life-without-devstack","ref":"life-without-devstack","sha":"d81ed14b0aebed9778d84cb3f9857faba0c3eede","user":{"login":"miguelgrinberg","id":2715854,"avatar_url":"https://avatars.githubusercontent.com/u/2715854?v=3","gravatar_id":"","url":"https://api.github.com/users/miguelgrinberg","html_url":"https://github.com/miguelgrinberg","followers_url":"https://api.github.com/users/miguelgrinberg/followers","following_url":"https://api.github.com/users/miguelgrinberg/following{/other_user}","gists_url":"https://api.github.com/users/miguelgrinberg/gists{/gist_id}","starred_url":"https://api.github.com/users/miguelgrinberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/miguelgrinberg/subscriptions","organizations_url":"https://api.github.com/users/miguelgrinberg/orgs","repos_url":"https://api.github.com/users/miguelgrinberg/repos","events_url":"https://api.github.com/users/miguelgrinberg/events{/privacy}","received_events_url":"https://api.github.com/users/miguelgrinberg/received_events","type":"User","site_admin":false},"repo":{"id":42468794,"name":"docs-developer-blog","full_name":"miguelgrinberg/docs-developer-blog","owner":{"login":"miguelgrinberg","id":2715854,"avatar_url":"https://avatars.githubusercontent.com/u/2715854?v=3","gravatar_id":"","url":"https://api.github.com/users/miguelgrinberg","html_url":"https://github.com/miguelgrinberg","followers_url":"https://api.github.com/users/miguelgrinberg/followers","following_url":"https://api.github.com/users/miguelgrinberg/following{/other_user}","gists_url":"https://api.github.com/users/miguelgrinberg/gists{/gist_id}","starred_url":"https://api.github.com/users/miguelgrinberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/miguelgrinberg/subscriptions","organizations_url":"https://api.github.com/users/miguelgrinberg/orgs","repos_url":"https://api.github.com/users/miguelgrinberg/repos","events_url":"https://api.github.com/users/miguelgrinberg/events{/privacy}","received_events_url":"https://api.github.com/users/miguelgrinberg/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/miguelgrinberg/docs-developer-blog","description":"The developer.rackspace.com blog.","fork":true,"url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog","forks_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/forks","keys_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/teams","hooks_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/hooks","issue_events_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/issues/events{/number}","events_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/events","assignees_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/assignees{/user}","branches_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/branches{/branch}","tags_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/tags","blobs_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/statuses/{sha}","languages_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/languages","stargazers_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/stargazers","contributors_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/contributors","subscribers_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/subscribers","subscription_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/subscription","commits_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/contents/{+path}","compare_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/merges","archive_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/downloads","issues_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/issues{/number}","pulls_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/pulls{/number}","milestones_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/milestones{/number}","notifications_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/labels{/name}","releases_url":"https://api.github.com/repos/miguelgrinberg/docs-developer-blog/releases{/id}","created_at":"2015-09-14T18:31:34Z","updated_at":"2015-09-14T18:31:36Z","pushed_at":"2015-10-20T03:09:16Z","git_url":"git://github.com/miguelgrinberg/docs-developer-blog.git","ssh_url":"git@github.com:miguelgrinberg/docs-developer-blog.git","clone_url":"https://github.com/miguelgrinberg/docs-developer-blog.git","svn_url":"https://github.com/miguelgrinberg/docs-developer-blog","homepage":null,"size":59950,"stargazers_count":0,"watchers_count":0,"language":"HTML","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":"rackerlabs:master","ref":"master","sha":"6fa92c818ecf943518f1d18798c55fcbad08f1cf","user":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":36315867,"name":"docs-developer-blog","full_name":"rackerlabs/docs-developer-blog","owner":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rackerlabs/docs-developer-blog","description":"The developer.rackspace.com blog.","fork":false,"url":"https://api.github.com/repos/rackerlabs/docs-developer-blog","forks_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/forks","keys_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/teams","hooks_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/hooks","issue_events_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/events{/number}","events_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/events","assignees_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/assignees{/user}","branches_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/branches{/branch}","tags_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/tags","blobs_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/statuses/{sha}","languages_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/languages","stargazers_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/stargazers","contributors_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/contributors","subscribers_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/subscribers","subscription_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/subscription","commits_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/contents/{+path}","compare_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/merges","archive_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/downloads","issues_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues{/number}","pulls_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls{/number}","milestones_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/milestones{/number}","notifications_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/labels{/name}","releases_url":"https://api.github.com/repos/rackerlabs/docs-developer-blog/releases{/id}","created_at":"2015-05-26T18:34:01Z","updated_at":"2015-07-14T20:57:56Z","pushed_at":"2015-10-20T03:09:16Z","git_url":"git://github.com/rackerlabs/docs-developer-blog.git","ssh_url":"git@github.com:rackerlabs/docs-developer-blog.git","clone_url":"https://github.com/rackerlabs/docs-developer-blog.git","svn_url":"https://github.com/rackerlabs/docs-developer-blog","homepage":null,"size":60734,"stargazers_count":6,"watchers_count":6,"language":"HTML","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":29,"mirror_url":null,"open_issues_count":10,"forks":29,"open_issues":10,"watchers":6,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/108"},"html":{"href":"https://github.com/rackerlabs/docs-developer-blog/pull/108"},"issue":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/108"},"comments":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/issues/108/comments"},"review_comments":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/108/comments"},"review_comment":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/pulls/108/commits"},"statuses":{"href":"https://api.github.com/repos/rackerlabs/docs-developer-blog/statuses/d81ed14b0aebed9778d84cb3f9857faba0c3eede"}}}}