October 31, 2017

My First Blog Post Using Jekyll

  —A test post with Jekyll.

My first blog post hosted on GitHub.

Generated using Jekyll and using the Jekyll-Clean theme.

October 14, 2017

My First Blog Post Using Jekyll

  —A test post with Jekyll.

My first post on GitHub.

Blogger has served me well for a long time. I use a custom domain and Blogger doesn’t support HTTPS for those domains.

I wanted to consolidate my articles and notes into a Git repository. Doing so made the move to GitHub a no brainer. This change motivated me to move to Markdown so my note and articles all use the same markup language.

Jekyll has an impressive collection of tools to export blogs. I was able to export my blog from Blogger quickly and without trouble.

The initial revision of the site used the Jekyll-Clean theme. The Git repository is forked from Jekyll-Clean, but it’s been rewritten using Boostrap 3. The only improvement I made was to change the layout and include files and update the CSS.

October 8, 2017

Individuals and interactions over processes and tools

  —Working agreements improve outcomes.

Recently, I've had the opportunity to reflect on the value of individuals and interactions over processes and tools, part of the Agile Manifesto.

The team has created a working agreement for design reviews. This agreement requires the involvement of two people and the designer. The rationale for this approach is that it promotes better design and knowledge sharing amongst team members. Interactions are critical to good design because different perspectives can identify opportunities and alternative approaches.

The team struggled with design reviews. To their credit, we are almost at the point where design review is a regular practice. Unfortunately, a few developers have challenges adhering to the working agreement because they feel that it's an impediment for some activities.

In one example, a developer gave a student a design to implement and then went on vacation. Unfortunately, the implementation failed code review. When questions arose about the implementation the student was unable to explain the design rationale. In another example, a developer took liberties in an implementation that broke a best practice.

In the first case, the team was able to improve the resulting design significantly over what the original developer created. In the second case, the best practice got discussed and differences in approach got worked out.

In each example, the developers who avoided the working agreement introduced other challenges that they didn't anticipate. The redesign and implementation in the first example cost an additional week and introduced a delay equal to the vacation time. The second example created a knowledge void.

The rationale given by each developer that motivated these examples was that they knew what they were doing. In my opinion, they failed to recognized the benefit introduced through the intent of the working agreement: ensure the appropriate interactions occurred.

When the first example went through the sprint retrospective, we ended up with a simple result: require the interaction, use the stand up to create awareness of the design intent and invite participation.

September 15, 2017

Safer Packer Examples with SSH

  —How to avoid Vagrant's public SSH key pair.

It's a little unsettling to see Packer template files with a clear text password for the vagrant user and root embedded within. Some template authors tell you to delete the vagrant user account if the virtual machine is publicly accessible. Still it's cringe worthy.

In my experiments with Packer I decided to script away some of this cringe worthiness. I took the position that I can improve upon the situation if I
  1. generate my own SSH key pair,
  2. lockout the vagrant user account so that only SSH access is possible using my key, and
  3. encrypt the root password file in the kickstart and preseed files on CentOS, Debian and Fedora.
This isn't perfect but it mitigates the above points as follows:
  1. avoids the use of the vagrant insecure public key.
  2. avoids the use of common words and phrases in example passwords.
  3. limits root password exposure.
As an added benefit, any examples that accidentally make it into production are more secure because the passwords and SSH keys are generated when the Vagrant Boxes are built.

The basic strategy I used to achieve the above is embedded within makefile.credentials. Credentials are generated by default, but can easily be manually created. Credentials are used by the Packer Temple files and a script for generating a Preseed Configuration file.

These examples use Debian but there are Fedora and CentOS examples as well.

September 9, 2017

Subprocesses In Python

  —A look at layering subprocess calls in Python.

In A Poor Use of GitPython, I describe how my layering approach in a project using GitPython proved unsatisfactory. Unsatisfactory because I wasn't using GitPython to the full extent of its power. Unsatisfactory because I didn't want to spend time learning Git internals and how GitPython makes them available.

I revisited my approach without GitPython. In A Poor Use of GitPython, my approach resulted in the spread of Git command-line arguments to other functions and I'm looking for a nice abstraction that doesn't cause this problem.

Let's start with subprocess interaction:
1
2
3
4
5
def execute(command, *args):
""" Use a subprocess to execute a command. Supply the command with any arguments.
"""
assert 0 < len(command)
return subprocess.check_output([ command ] + list(args))

I want the output from the command and I want to know whenever I get a non-zero return code. It provides a nice test point for separating my application from the libraries it uses.

I call git using the following function.
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class GitException(Exception):
""" Throw an exception whenever an error occurs using GIT(1).
"""
def __init__(self, command, output, returncode):
assert 0 < len(command)
self._command = str(command)
assert 0 <= len(output)
self._output = str(output)
assert 0 < returncode
self._returncode = int(returncode)

@property
def command(self):
return self._command

@property
def output(self):
return self._output

@property
def returncode(self):
return self._returncode

def git(command, *args):
""" Execute GIT(1). Supply the git command and any arguments.
"""
assert 0 < len(command)
try:
execute("git", command, *args)
except subprocess.CalledProcessError as e:
raise GitException(e.cmd, e.output, e.returncode)

Too many layers? Perhaps. All I've achieved thus far is a couple of wrappers that provide strong guarantees on the length of the command. In some respects this is worse than the result I achieved in A Poor Use of GitPython.

The advantage lies in the recognition that some git commands (e.g., git-show-ref and git-ls-files.) return with error 1 under specific circumstances that I might want to handle in higher layers.