David J Peacock - Code Blog     About     Archive     Feed

Spinning up a DigitalOcean Droplet with Ansible

Recently I faced the annoying task of switching VPS providers. I am of course a good little SysAdmin / DevOps engineer so of course I had a lot of things automated, but when it came to the actual task of spinning up a new virtual server, I found that over the years a few tweaks here and there had led me to a position in that I had manual work to do.

Unacceptable.

I decided to start working on completing my Ansible configuration management setup, which wasn’t actually a lot of work, but then I realized as I was perusing the Module Index that there is a DigitalOcean module baked into the core of Ansible! This moves me into fully automated territory including provisioning. I had to give it a shot.

Unfortunately due to some minor bugs with documentation, a missing Python module, a broken Python module, and a nuance of my Mac OS X environment, the examples listed wouldn’t work as presented. This blog post will serve as a reference to my future self as to how to get this working.

Pre-requisites:

  • Brew installed
  • Python installed via Brew
  • Ansible installed via Brew

Steps:

  • Install dopy 0.3.5. The latest version (0.3.7 at time of writing) is broken, so use 0.3.5 explicitly:

pip install -I dopy==0.3.5

  • Install six:

pip install six

  • Enter a localhost entry in your inventory file. This is used by Ansible which must talk over SSH as a method to get a Python interpreter:
[localhost]
localhost ansible_python_interpreter=/usr/local/bin/python
  • Enable SSH; you can either do this through the GUI or alternatively:

sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist

  • Don’t forget to add your SSH key’s public component to your authorized_keys:

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

With all of that duct tape out of the way, we’re onto the actual fun part. Add the following into droplet-playbook.yml

---
- hosts: localhost

  tasks:
  - name: deploy $5 droplet
    digital_ocean: >
        state=present
        command=droplet
        name=ubuntudroplet
        api_token=YOUR_API_TOKEN_HERE
        size_id=512mb
        region_id=tor1
        image_id=ubuntu-14-04-x64
        wait_timeout=500
    register: ubuntu_droplet
  - debug: msg="ID is {{ ubuntu_droplet.droplet.id }}"
  - debug: msg="IP is {{ ubuntu_droplet.droplet.ip_address }}"

With all of that in place, you can now provision a new droplet simply by:

ansible-playbook droplet-playbook.yml

If you found this post useful, and you’re thinking out about signing up for DigitalOcean, please consider doing so through my referral link; we’ll both get $ credits to our accounts.

DigitalOcean Referral Link

If you liked this post, you can share it with your followers or follow me on Twitter!

Cross-compiling Go Code

As I’ve set on a path to learn Golang, and decided to rewrite Icon Sizerator, one sticking point has been on my mind. It’s worth noting that my development system is OS X and that my production server is an Ubuntu Linux VPS. Since I installed Golang via Homebrew on my Mac, all I needed to do in order to gain the ability to cross-compile was:

brew reinstall go --cross-compile-common

This gave me ability to perform compilation for OS X, Linux, and Windows, all on various architectures.

[peacock@trashcan ~]$ brew reinstall go --cross-compile-common
==> Reinstalling go with --with-cc-common
Warning: go: --cross-compile-common was deprecated; using --with-cc-common instead!
==> Downloading https://storage.googleapis.com/golang/go1.4.2.src.tar.gz
######################################################################## 100.0%
==> Building go for 386-linux
==> ./make.bash --no-clean
==> Building go for amd64-linux
==> ./make.bash --no-clean
==> Building go for arm-linux
==> ./make.bash --no-clean
==> Building go for 386-windows
==> ./make.bash --no-clean
==> Building go for amd64-windows
==> ./make.bash --no-clean
==> Building go for 386-darwin
==> ./make.bash --no-clean
==> Building go for amd64-darwin
==> ./make.bash --no-clean
==> Cloning https://go.googlesource.com/tools.git
Cloning into '/Library/Caches/Homebrew/go--gotools--git'...
remote: Total 13157 (delta 9273), reused 13157 (delta 9273)
Receiving objects: 100% (13157/13157), 5.93 MiB | 2.78 MiB/s, done.
Resolving deltas: 100% (9273/9273), done.
Checking connectivity... done.
==> Checking out revision 69db398fe0e69396984e3967724820c1f631e971
==> go build
==> go build
==> Caveats
As of go 1.2, a valid GOPATH is required to use the `go get` command:
  https://golang.org/doc/code.html#GOPATH

You may wish to add the GOROOT-based install location to your PATH:
  export PATH=$PATH:/usr/local/opt/go/libexec/bin
==> Summary
🍺  /usr/local/Cellar/go/1.4.2: 5566 files, 609M, built in 3.4 minutes

Having been through this little process, it’s now possible for me to build on my Mac for my Ubuntu host, by running something like this:

GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o go-sizerator.linux go-sizerator.go

StackOverflow Source

If you liked this post, you can share it with your followers or follow me on Twitter!

Canadian Cheese Directory to JSON

Publishing data in CSV format is highly efficient for transmission but that is where the story ends for most other use cases. The Canada Open Data Portal has a great many datasets available for analysis, and one such dataset is the Canadian Cheese Directory. This lists 1,400+ cheeses made in Canada, with details such as where they are made, how sharp they are, how long their ripening process is, and other such facts.

This data is in a very easy to download yet difficult to consume CSV format, so I took the opportunity to make my April app a parser which pulls this data directly, and then converts it to the more useful and human readable JSON format.

In the native CSV format, the data looks like this:

730,Eweda (Best Baa Dairy),,Ewenity Dairy Co-operative,,ON,Artisan,Artisanale,http://www.ewenity.com,,32.00,47.00,made with gouda recipe but with a very different taste,Recette du gouda mais avec un gout different,,,,,1 Month,1 mois,0,Semi-soft Cheese,Pâte demi-ferme,Ewe,Brebis,Pasteurized,Pasteurisé,,,2015-02-06

And this is how the data looks in JSON:

    {
        "CheeseId": "730",
        "CheeseNameEn": "Eweda (Best Baa Dairy)",
        "CheeseNameFr": "",
        "ManufacturerNameEn": "Ewenity Dairy Co-operative",
        "ManufacturerNameFr": "",
        "ManufacturerProvCode": "ON",
        "ManufacturingTypeEn": "Artisan",
        "ManufacturingTypeFr": "Artisanale",
        "WebSiteEn": "http://www.ewenity.com",
        "WebSiteFr": "",
        "FatContentPercent": "32.00",
        "MoisturePercent": "47.00",
        "ParticularitiesEn": "made with gouda recipe but with a very different taste",
        "ParticularitiesFr": "Recette du gouda mais avec un gout different",
        "FlavourEn": "",
        "FlavourFr": "",
        "CharacteristicsEn": "",
        "CharacteristicsFr": "",
        "RipeningEn": "1 Month",
        "RipeningFr": "1 mois",
        "Organic": "0",
        "CategoryTypeEn": "Semi-soft Cheese",
        "CategoryTypeFr": "Pâte demi-ferme",
        "MilkTypeEn": "Ewe",
        "MilkTypeFr": "Brebis",
        "MilkTreatmentTypeEn": "Pasteurized",
        "MilkTreatmentTypeFr": "Pasteurisé",
        "RindTypeEn": "",
        "RindTypeFr": "",
        "LastUpdateDate": "2015-02-06"
    }

For this month I decided to get started learning Golang, the virtues of which have been sung to me from several sources. Golang is very pleasant to use, and whilst I have yet to get into its primary specialties of goroutines (threads), channels (concurrency) and interfaces (alternative to OO), it has been easy to pickup, and quite rational. I enjoy it, a lot. Maybe this will be the language of choice for App #5.

Without further ado, you can find my Canadian Cheese Directory to JSON tool on my GitHub. You will need to install Go first, if you have not done so already. Please follow links below.

Source Code at GitHub

Go Lang

If you liked this post, you can share it with your followers or follow me on Twitter!

Brightside

Announcing App #3 of 12, Brightside is a standalone service built on Meteor, which helps you look forward to events and count down the time until you get to them!

Ok so confession time. My month totally derailed. I had a few unexpected projects fall in my lap and a bunch of other things in my personal life that basically bumped my 12 Apps in 12 Months challenge. This month was supposed to be my first attempt at a Unity game, but it got pushed back and pushed back until I was down to this last weekend of March. And then that was stolen from me too. Last night, in a panic and with determination to not drop the ball on my challenge, I sat down with the TV on in the background, Hacker News in my browser as inspiration, and a lovely Muskoka Brewery Mad Tom IPA by my side. I had a quick think, then start to finish hacked this together in two hours. I apologize about the colour scheme. What can I say, I like orange.

This will hopefully be my last CRUD app for a while. Back to your regularly scheduled 12 Apps in 12 Months for April; I hope. :-)

Brightside

Brightside is designed to operate either SaaS or standalone if you wish to clone the project and run locally. The backend is made up of Meteor, Node.js, JavaScript, and MongoDB.

Use the service: Brightside

Improve the service: Sourcecode at GitHub

Please do reach out with any comments or suggestions.

If you liked this post, you can share it with your followers or follow me on Twitter!

HomeSure

Announcing App #2 of 12, HomeSure is a standalone service built on Meteor, which serves to assist home buyers in visualizing their purchasing decision.

HomeSure

HomeSure is designed to operate either SaaS or standalone if you wish to clone the project and run locally. The backend is made up of Meteor, Node.js, JavaScript, and MongoDB.

Use the service: HomeSure

Improve the service: Sourcecode at GitHub

Please do reach out with any comments or suggestions.

If you liked this post, you can share it with your followers or follow me on Twitter!