Why GitHub is Essential for Network Automation
With the move toward network automation comes an increase in demand for IT professionals who work with code, which means working with source code control systems like GitHub.
Often enough new tools and skill sets appear in the professional community long before they make their way to a certification exam. So, anyone who has been automating networks for a while won't be surprised to see GitHub in the Cisco 300-435 exam, Automating and Programming Cisco Enterprise Solutions.
Git is a source code control software and works closely with a website called GitHub. Specifically, the 300-435 exam requires you to understand seven concepts used by git:
Pushing and pulling
Checking for differences
What is Git and Why Does it Matter?
The fundamental idea behind most source code control systems is to allow you, the coder or programmer, to work on changes and fixes to the code in an isolated situation. There, you have your own copy of the code and then when you're ready, add your changes into the main set of code. Each copy of the code — the original and the one you're working on — is known as a branch of the code. The process of combining your changes back into the original code is called merging.
Most of them require a central place from where the team members get their copies of code (a process called checking out). Git, however, takes a slightly different approach. You still get your code from a central location of sorts, but that central location (called a repository or repo for short) lives right on your own computer. If you have other team members working on the same code, they too get an entire repository of the code.
Here's how git works. Each branch gets a name, and the main code is usually called master. You and your teammates might all have a copy of the master branch. When you're ready to make some changes to the code, you'll create a new branch, which is an exact copy of master. You'll give that branch a name of your choosing, usually one related to the fix or feature you're working on, for example ConnectFeature (such as a feature that adds new network connectivity to the code). You'll make your changes using this ConnectFeature branch, then when you're finished and have fully tested the new features, you'll merge them back into your own master.
At this point your master is no longer the same as the master on your teammates' computers. You'll then send your copy of master to your teammates, and they'll treat the master they're receiving as a separate branch and merge it into their own copies of master. Now everybody has the same master.
The process of sending the branch to the teammates is a little tricky, so typically teams will create a repository on a server they can all access, and changes will merge into that server's repository. In a sense, they will treat that as a central repository like other version control packages use, even though it's technically just another copy of the repository. Then when you make a change, you'll copy the changes up to that server, a process known as "pushing". Your team members will then pull the changes down to their own repositories and merge the changes into their own branches.
Although you can set up your own server and install git on it for your team to treat like a central repository, most teams skip that part and go with a server already set up with git. One example is the site GitHub.com. You can create an account for your team and create a repository inside your team's account. You then create accounts for each team member, and do all your pushes and pulls to and from the team's repository on GitHub.
Now let's explore the nitty gritty of all these steps.
The process of creating a repository on GitHub is straightforward. You simply provide a name and answer some basic questions, such as whether you want a default README file and a default license file. After the repository is created, however, the very first time you copy the repo down to your own computer, you don't use a pull. Instead, you have to start with what's called a clone. This is a one-time step that initializes the directories or folders on your computer with information about the repo, and then pulls down copies of any branches that exist in the repo.
In order to clone a repo from GitHub, you first have to set up an SSH key linked to your GitHub account. This process isn't difficult but has several steps, too many to describe here. Instead, take a look at the official documentation.
Once your SSH key is in place and you've added it to your ssh-agent (as described in the aforementioned documentation), you can clone the repo. From within your bash shell, make sure you're in a parent directory that you want to contain a new directory holding the source. This new directory will get created for you and will have the same name as the repo. Then go to the repo's page on GitHub, click the green "Clone or download" button, and make sure the dropdown box says "Clone with SSH." (If it says "Clone with HTTPS," click the link that says "Use SSH". Otherwise this next step won't work.) Copy the URL you see in the dropdown box. Then in your bash shell, type:
1 git clone repo–url
You'll be replacing "repo-url" with the full URL you copied. This will create a directory and initialize it with the repo. If you want to practice on an existing repo, Google github practice repository. Here's one that you might try.
Next, you need to understand how to perform branching. Each branch that you create needs to start as a copy of an existing branch. Usually you'll start with the master branch. So after you've cloned the repo, you can create a branch like so:
1 git checkout –b newfeature
This is where you'll replace the word "newfeature" with whatever you want to call the branch. Memorize this. The process of creating a branch uses a git command called "checkout" followed by a -b option. (The -b refers to "branch".)
Now you have a new branch that is thus far an exact duplicate of the master branch, and you're using the new branch that you created. Want to bounce back and forth between the two branches? You can go back to master by checking it out without the -b option, like so:
1 git checkout master
Then when you're ready to return to the branch you're working on, type:
1 git checkout newfeature
Again, you are replacing newfeature with whatever you called the branch.
Adding and Committing Files
Make sure you're inside your new feature branch and then create a new file. Ensure the file is inside the directory containing the repository, or inside a subdirectory beneath it. For example, use your favorite editor to create a new python file called tests.py and put some python code in it, such as this:
1 print('Hello') 2 print('World')
Just because the tests.py file lives inside the directory containing your repository doesn't mean it will automatically be a part of the repository. You have to manually add it using git's add command. Make sure you're in the directory containing tests.py and type:
1 git add tests.py
The next step is a little strange at first, but you'll become comfortable with it over time. Git keeps track of your changes such as adding a new file using the git add command, but it still doesn't automatically save the changes to your branch. Instead, it calls the list of changes the "staging area." So, the next step is to go ahead and finally add the change, in this case the creation of a new file, into the branch. This requires a process called committing your changes. To do so, type:
1 git commit –a –m 'Some description'
This is where you'll replace Some description with a brief description of the work you did, such as "Created a test python file." Make sure you surround the description with single quotes.
After you've committed your changes into your new branch, you're ready to merge that branch into the master branch. When you merge, you have to be in the branch receiving the changes. That means in this case you'll want to be in the master branch. Switch to that branch by typing:
1 git checkout master
And then you can merge the newfeature branch into master by typing:
1 git merge newfeature
Now your changes are merged into master.
Often this merging process goes smoothly. However, imagine a situation where you were working on your own branch, and then separately you pulled down the latest changes to the master branch. Unfortunately, one of your team members made a change in the master branch to the same file you're presently modifying in your own branch, and this happened after the last time you pulled down master.
Now when you try to merge your changes, git will see that the file changed in both branches and won't allow the merge to happen because it considers the situation a "conflict." It will halt the merge as a way to guard against overwriting the changes your teammates made. Here's a message you'll see when you try to merge:
1 CONFLICT (content): Merge conflict in tests.py 2 Automatic merge failed; fix conflicts and then commit the result.
Instead, you have to do what's called a manual merge. You have to decide which changes you want to work into the master branch; you can keep the changes you made, or you can keep the changes your teammates made. Or you can do something different altogether. Either way, you have to open up the file tests.py (or whatever file caused the conflict) and modify it so it matches how you want it to look in the master branch.
Git will actually fill in the file with both sets of changes, and surround them with greater-than and less-than symbols so you can quickly find the problems. For example, if the newfeature branch had this code in tests.py:
1 print('Hello') 2 print('World')
And master had this code in tests.py:
1 print('Hello') 2 print('Everyone')
Then tests.py in master will now look like this:
1 print ('Hello') 2 <<<<<<< HEAD 3 print ('Everyone') 4 ======= 5 print ('World') 6 >>>>>>> newfeature
This is not valid python code and you won't want to leave it like this. You'll probably want to change it to look like either version before you tried to merge. Make the changes, and then save it. Now you need to do another commit:
1 git commit –a –m 'Merge fix'
Because git knew you were in the middle of a merge, that's all you need to do; the merge is now complete.
Pushing and Pulling
Next you're ready to push your changes up to your GitHub repository. Make sure you're in the branch you want to push up to GitHub, such as new feature, by checking it out if necessary:
1 git checkout newfeature
Type the following to push the branch to GitHub:
1 git push origin newfeature
The word "origin" refers to the remote repository, in this case the one on GitHub.
Typically when using GitHub, you won't do your merges locally as described in the previous section. Instead you'll do them from within GitHub in the browser. The name of this merge process is a bit of a misnomer; you create what's called a "pull request" or "PR" for short. You can learn about them here.
After you or your team has merged the changes in GitHub, you'll want to pull down the branch the changes were merged into, such as master, so that your copy of master has the latest changes. You can do so by first switching to the branch you're going to pull down:
1 git checkout master
And then typing:
1 git pull
This will pull down the current code in master and merge it into your own copy of master. Note that this is a true merge, and if you made changes to master that aren't present in the master on GitHub, you'll get a conflict and have to do a manual merge just like we looked at earlier.
Checking for differences
If you're working on a file, and you want to see what changes you've made to a file before committing it, there's a simple git command for that. Just type:
1 git diff tests.py
Replacing tests.py with the name of the file you're interested in reviewing. This will compare the change against what's currently been committed into the current branch. Or you can see all the changes that you've made but haven't yet committed by leaving off a filename:
1 git diff
The diff command is quite powerful. You can compare code between branches, or even have diff open up a GUI tool of your choice that's built for showing differences, such as meld.
So how does all this fit in with automation? There are plenty of ways you can automate with git. For example, you might have a cron script that automatically pulls changes down from GitHub and pushes them onto a network device. This is easier than it sounds, as all the script needs is an account with GitHub, and a call to git pull. Then the script would copy the new files it pulls down onto the device.
Or, you can access git right from within all the usual automation tools such as Puppet, Chef, and Ansible; all of these tools understand and support git. Think of the possibilities! Your team could push changes to GitHub, merge them into master, and every night a chef recipe pulls down the latest master and pushes it to the devices, all without any human intervention.
Git and GitHub are powerful tools that will be important on your resume. We've only scratched the surface here.