Open Source: My First Contribution

Published on:
Aug. 23, 2017

I’ve been studying Django development for a few months now. A good friend of mine (let’s call him Jimothy) just happens to be a full-time maintainer of Pulp, an open-source Django project. Pulp is preparing their next major release right now, and I was asked to be a guinnea pig to see if their on-boarding documentation for community developers was beginner friendly. This led to my first pull request on an open-source project.

What’s Pulp?


Pulp is a repository management system. It can be used to sync multiple machines to a remote repository automatically. Here’s the real world example Jimothy used to exxplain it:

Let’s say I’m [large business] (they are a real customer).
omg heartbleed!
I have 100,000 machines, and I need to update them all. until I do, they are vulnerable. Every hacker in the world knows how to attack. Do I run ssh into each machine and run yum update? Thats what a lot of sysadmins actually do.
 
[The] solution is to run pulp.
...
You sync your pulp (which pulls down the fix) and then if you’ve got a [lot] of machines, you sync other pulps from your first pulp and they all can sync locally. With heartbleed, [different large company] used our [software] to update everything in like 2 hours

That sounded pretty cool to me. I wanted to help.

New Developer Guide


Part of my friend’s job is guiding new professional and community developers. He wrote the new developer quickstart guide for setting up a local development environment. This guide introduced me to Ansible and Vagrant, neither of which I’d used before. The new developer guide boiled down to configuring a Vagrantfile to run several Ansible roles to install a bunch of tools and dependencies into a Virtual Machine. Once completed, this VM would be set up to match those of every other member of the team.

Getting new developers into an environment that matches their teamates’ is especially important for a project like Pulp. Because so many of their developers work remotely, and they regularly receive contributions from people all over the world, experienced developers need to be able to provide guidance without being in the same room. Having matching VMs is a quick and easy way to make sure everyone has the same tools at their disposal.

First Hiccup


I ran into my first problem before the VM was up and running. Vagrant was running into a problem with an Ansible role and giving me an error message I had no idea what to do with:

fatal: [dev]: FAILED! => 
    {"changed": false, 
     "failed": true, 
     "msg": "Destination /etc/sudoers.d/vagrant-nopasswd does not exist !", 
     "rc": 257}

I immediately asked Jimothy for help.Thankfully his first reaction wasn’t to solve the issue, but to point me in the direction of a solution I could find myself.

Diagnosis


The first step I took to find the problem was to check Vagrant’s documentation to see if I could understand what was supposed to be happening. In typical Jay Welborn fashion, I did a depth-first search into the technologies involved. To get a better idea of what Vagrant was doing, I followed the Vagrant Getting Started guide. After working through setting up a vagrant VM from scratch I recognized that the probem wasn’t with Vagrant itself. The error was occuring while Vagrant was running tasks based on an Ansible playbook.

In continuing the depth-first-search, I read the Ansible Getting Started Guide. After doing all of this, I re-read the error message and recognized that it was pointing me directly to the problem file the whole time. Ansible’s error message clearly stated writing to /etc/sudoers.d/vagrant-nopasswd was failing because the line it was looking for wasn’t in the file. Thinking myself brilliant, I told Jimothy about my discovery.

Solution


Jimothy, probably having realized what was wrong immediately, pointed me to Ansible’s lineinefile documentation . Here I found out that simply adding create: yes to the script would tell Ansible to write the line it was looking for if it didn’t already exist. This is what the script looked like before and after my addition.

Before:

- name: Grant vagrant all sudo rights
  lineinfile:
      dest: /etc/sudoers.d/vagrant-nopasswd
      regexp: '^vagrant'
      line: 'vagrant ALL=(ALL) NOPASSWD: ALL'
      validate: 'visudo -cf %s'
      mode: 0440

After:

- name: Grant vagrant all sudo rights
  lineinfile:
      create: yes
      dest: /etc/sudoers.d/vagrant-nopasswd
      regexp: '^vagrant'
      line: 'vagrant ALL=(ALL) NOPASSWD: ALL'
      validate: 'visudo -cf %s'
      mode: 0440

One pull request later, I had my first accepted contribution to an open-source project! Even though it was a pretty simple fix, contributing something to a real-world codebase was quite a rush. I’m looking forward to making many more contributions in the future.

In retrospect, maybe I spent too much time researching and not enough time reading error messages critically, but I have the feeling I’ll be using Vagrant and Ansible enough that it was time well spent.