I’ve been working on an open-source project for managing the Kong API Gateway, both as an SDK and as a CLI tool using a straightforward, YAML-based templated configuration. The project is called Skull Island and is available on RubyGems via skull_island, on DockerHub via jgnagy/skull_island, and of course on GitHub as jgnagy/skull_island.
I bought a new (arguably better) domain for my blog now! If you’re reading this, you’ve probably noticed, but it is therubyist.org, because I’m a fan of Ruby. The old name won’t be going anywhere, at least for the time being. Given the purchase of this new domain, I have several domains I need to maintain. Since I run this blog (and a few other services) from my home server which has a dynamic IP, setting up the domain apex (i.e., “naked domain”) is tricky. I’ve been using a dynamic DNS service called duckdns.org which gets the job done for subdomains since I can just CNAME to my personal DuckDNS subdomain, but it doesn’t solve this apex problem.
I decided that I was tired of doing this manually and that I would try to write a script. It would be appropriate, given my blog’s new domain name, to write it in Ruby. I did a quick DuckDuckGo search and noticed that someone wrote a GoDaddy SDK for Ruby. Yes, I use GoDaddy for my DNS… not necessarily endorsing them, but they seem to work well for my needs, especially now that I’ve discovered that they offer RESTful APIs.
There are lots of good reasons for and articles recommending running Docker containers read-only, but what I have a difficult time finding are descriptions of how to do this for many popular images. Some software needs to write to a few important and predictable locations. It surprises me how often image providers neglect to offer instructions or details required to run their image this way.
Even setting aside read-only containers, counting on writing to the writable layer just feels wrong. Per the documentation, for the writable layer, both read and write speeds are lower because of the copy-on-write/overlay process through the storage driver. In my experience,
docker diff output means I haven’t taken the time to configure my volume declarations, either through tmpfs mounts, volumes, or bind mounts.
Throughout my career, I’ve seen a couple recurring patterns related to the tools I write: I write a lot of small CLI tools and I like to share them with my coworkers (and whenever possible, the rest of the world).
This has led to several iterations of solving the problem How do I make this tool easy to run? since I don’t want to burden people with understanding the intricacies of all my tools’ dependencies. These tend to be Ruby, some number of gems, and possibly some other common unix utilities. The solutions I’ve come up with have included a lengthy README with detailed instructions, Bundler with Rake tasks to do all the heavy lifting for non-Ruby things, fpm, and even “curl bash piping” (yes, I’m horrible).
Recently I decided to use Docker to solve this problem, since I’m using it so much anyway. Using Docker has some huge benefits for sharing applications of all types: the dependencies list gets whittled down to just Docker, things work on more platforms, testing gets simpler, and it is the new hotness which makes people say “whoa” and that’s fun. That said, the downsides can be frustrating: working with files on your machine gets messy, more typing with the extra Docker-related preamble, things are less straightforward and clear, simple mistakes can lead to lots of images and containers to clean up, and the executable gets significantly larger (since the Docker image is a whole, albeit lightweight, OS userland to run the app). After weighing these pros and cons, I’ve found that telling a coworker to
docker pull registry.url/my/app and run it with
--help is so much more convenient than the alternatives.
At work, I’ve been working on a lot of automation lately and I ran into a seemingly simple problem that ended up being a bit more complicated than I had first imagined. I have been collaborating on a project that we’re using for auditing Active Directory users and groups and tracking changes to those groups via some simple automation. While that project is interesting in its own right, my boss and I agreed that tackling another helpful automation problem would help our entire IT team: determining if user accounts are locked. I’ve been pushing #ChatOps hard at work through Lita, so adding a plugin for our bot to work with Active Directory seemed only logical.
Context out of the way, making Ruby work with LDAP is a solved problem, many times over. Thankfully, Active Directory exposes most everything you’d want via LDAP, so with a few helper methods, building a few objects tailored to this task was easy work. We quickly discovered that each Active Directory user has a handy attribute called
lockoutTime, and even some helpful hints via the interwebs that we just need to check if that value is
0 (meaning the user isn’t locked out) or any other value (indicating, naturally, that they are locked out). Well, this would be a pretty crappy blog post if that was the end, but it wasn’t.
Continue reading Check for locked out Active Directory user via Ruby
Amazon’s CloudFormation is a wonderful and flexible tool for provisioning and managing resources in an EC2 VPC. It really takes the concept of infrastructure-as-code and helps make it a reality. For all its flexibility though, it sacrifices intuitiveness and ease. It is also limited by the rigidity of JSON, which isn’t a full-fledged language so it doesn’t support variables (although Parameters, Mappings, and References to them are a long-winded and difficult to parse approach that comes close) or easily referencing reusable external libraries. It also isn’t possible to define arbitrary functions, iterate over lists, or define anything but the most rudimentary conditional sections. This is by no means a criticism of CloudFormation, as it has certainly done a lot to turn a serialization format into a pseudo scripting language, but these are my observations that might frustrate other people when using it.
That’s where ERB comes in. As a big advocate of Ruby, whenever I think of templating the first thing that comes to mind is ERB. A while back, I put together a super simple script that generates templates from JSON “layouts” and “snippets” (think views and partials from Rails), both of which fully support ERB and all of its Ruby goodness.
Continue reading Reusable CloudFormation Snippets with ERB