CJ Eller

Classical Guitar by Training, Software by Accident

Just as I was learning about state in IaaC, I came across a video about how to add state to Super Mario Maker 2. State in this context means that a player can make “changes” in a level persist after losing a life. It'd be quixotic to explain how it works in game, so here's the video instead.

Incredible to see how state is achieved through hacking the game's fundamentals, stretching them as far as they can go. It's also interesting to think of state, or lack thereof, as something taken for granted in certain contexts. For a Super Mario Maker level, you play the level and that's it. State doesn't enter the picture except in the context of checkpoints. Everything in the level more or less stays the same. But once state enters the picture, what kind of levels could be created?

And what possibilities occur when you remove state from certain processes? I've been writing this blog through editing a single draft, not creating a new draft each time. A Lambda function just grabs the contents of the same draft at 5:00pm Monday through Friday and publishes it. It turns my editor into more of a palimpsest. That transformation helps me write more consistently here, which makes me feel better on the whole.

What else could be done with state?

I've been trying to learn more about AWS CloudFormation. One thing I've run into when diving in is having my expectations collide with similar tools I've used in the past. In this case it's the IaaC tool Terraform.

With Terraform, you can create a template and run terraform apply to create your cloud infrastructure. What if you want to make a change in that infrastructure? Just make your edits to the template, run terraform apply again, and you're off to the races. How does Terraform do this? State. Here's how the docs describe its purpose:

The primary purpose of Terraform state is to store bindings between objects in a remote system and resource instances declared in your configuration. When Terraform creates a remote object in response to a change of configuration, it will record the identity of that remote object against a particular resource instance, and then potentially update or delete that object in response to future configuration changes.

The beauty of Terraform is in how it handles state. I emphasize “handle” here, because a service like CloudFormation also handles state. It just does so in a different way. Coming from the world of Terraform, I thought it would be something akin to running the same command again. But CloudFormation requires a different approach. You need to declare the changes you are making in a separate API call. What's more, you can create change sets. Here's how AWS describes them:

When you need to update a stack, understanding how your changes will affect running resources before you implement them can help you update stacks with confidence. Change sets allow you to preview how proposed changes to a stack might impact your running resources, for example, whether your changes will delete or replace any critical resources, AWS CloudFormation makes the changes to your stack only when you decide to execute the change set, allowing you to decide whether to proceed with your proposed changes or explore other changes by creating another change set.

What's interesting here is that, again, we have a separation of duties in CloudFormation for something that Terraform tells you when you run the terraform apply command — it lets you know the resources you're going to change and asks if you're okay with those changes (of course you could run terraform plan to do this as a separated step but hey, living life on the edge).

At first I thought how CloudFormation handled state and updating stacks was a knock against it. But more and more I see it as a separate approach that has equal merit. Separating out the steps for updating cloud infrastructure is something I am not used to. Getting used to it can only help expand my experience.

Sometimes colliding with your expectations is a good thing.

I have just started George Dyson's most recent book, Analogia: The Emergence of Technology Beyond Programmable Control. His past works, like Turing's Cathedral and Darwin Among the Machines, were incredibly eye-opening for me. Criminally obscure figures like Nils Barricelli and Samuel Butler were brought to the forefront, people whose work both reflects and affects our digital present.

Here's a mind-blowing passage from the beginning of the book about how analog and digital computing relate to one another, especially from a biological perspective.

Nature uses digital coding, embodied in strings of DNA, for the storage, replication, modification, and error correction of instructions conveyed from one generation to the next, but relies on analog coding and analog computing, embodied in brains and nervous systems, for real-time intelligence and control. Coded sequences of nucleotides store the instructions to grow a brain, but the brain itself does not operate, like a digital computer, by storing and processing digital code.

[...]

In a digital computer, one thing happens at a time. In an analog computer, everything happens at once. Brains process three-dimensional maps continuously, instead of processing one-dimensional algorithms step by step. Information is pulse-frequency coded, embodied in the topology of what connects where, not digitally coded by precise sequences of logical events. “The nervous system of even a very simple animal contains computing paradigms that are orders of magnitude more effective than those found in systems built by humans,” argued Carver Mead, a pioneer of the digital microprocessor, urging a reinvention of analog processing in 1989. Technology will follow nature's lead in the evolution of true artificial intelligence and control.

I find it interesting how the cadence of writing ebbs and flows. Topics abound at the start of the week only to taper off towards Friday. Then ideas slowly appear during the weekend, only to start the process over again for the next week.

Can't help but think of the seasonal nature of creativity.

I have been monitoring a crack in my classical guitar for sometime now. Humidity caused a split to form near the sound hole. The crack was too thin to fix at the time. A couple months later and the crack slivered its way to the bottom of the guitar. What to do?

I picked up some wood glue and a bar clamp, adding glue into the crack and gently clamping down on the guitar to help seal the crack. It did the trick. The glue left behind a burnt orange color down the crack, creating an eye-striking contrast to the warmth of the European spruce. I've become more and more bewitched by that color contrast.

This led me to add styling to my blog that reflects these colors — background as the color of my aged spruce guitar with links and

blockquotes

representing the sealed burnt orange crack.

It's been a shift from having styling on my blog that was more of, how should I put this, an aesthetic decision. If you asked me what past color choices on my blog meant to me, I couldn't tell you. They were removed from any personal experience. These colors? They feel like more of a representation of who I am. I can tell a story about these colors. They are a reflection of myself on the web.

And isn't that what we're all trying to get at in one form or another? How do we make CSS (and HTML and programming as a whole) more autobiographical?

I am currently learning a piece of music on guitar that starts in A minor and then, some measures later, shifts to A# minor. Such a chromatic move is curiously compelling. It's not traditional by any means. However, when taken into conte

For me, one of the more enjoyable parts about music theory is figuring out how composers connect disparate tonal regions together. And that's the joy about this piece I am learning in particular. The connective musical tissue between these two tonal centers is what makes the piece that much more fascinating.

This is how I feel when I program. Just recently I played around with Ansible and having it provision AWS resources that are created by using an AWS CloudFormation template. Ansible relies on an inventory file to know what resources it has access to when I run commands through Ansible. The catch is that, to cut costs, I delete the AWS resources after each session. With the IP addresses of the VM's always changing, Ansible cannot rely on a static inventory file.

Ansible and AWS CloudFormation were my tonal centers in this case. The goal was to connect them together so that, once I deploy the AWS resources, I create a new inventory file with the information from the AWS CloudFormation API. Here's the jacked up bash script (with a lot of help from jq):

#!/bin/bash

output=$(aws cloudformation describe-stacks --stack-name ansible | jq '.Stacks[0] .Outputs')

value="[webservers]
app1 ansible_host=$(echo $output | jq -r '.[0].OutputValue')
app2 ansible_host=$(echo $output | jq -r '.[1].OutputValue')

[loadbalancers]
lb1 ansible_host=$(echo $output | jq -r '.[2].OutputValue')

[local]
control ansible-connection=local
"
# So apparently if you put quotes around a var it will keep the og spacing
echo "$value" > hosts.ini

# Run the playbook
ansible-playbook playbooks/run-the-playbook.yml

With programming I find the joy in creating connective tissue — be it a kludged together application or a one-off script. That part of programming feels very much like music, whether that be classical music or free jazz.

There's this part from a recent episode of Screaming in the Cloud where guest Nora Jones (founder and CEO at Jeli) makes an Intriguing remark about software tools:

But I think the tools that work the best are the ones that you treat like a member of your team, almost.

It's not something that's doing something for you, it's something that you're working with to achieve the best outcome. And they're still putting something on the table.

Intriguing for me because I am playing around with such a tool when it comes to my publishing workflow. The AWS Lambda function I've set up publishes my most recent draft on a regular weekly cadence.

This might not sound like much, but it requires a lot of give & take on my part to schedule writing to hit that mark. The function acts like an overbearing editor on a news team who is always pushes their writers to make the deadline.

And that's where it feels like I am working with the function rather than it just mindlessly doing something for me. There's this give and take which Nora Jones mentions that I can relate to. I wonder if there's more I can do to make the function more of a member on my team.

It's a tiny miracle when you find someone who has solved the same problem you're currently having. What's more is when the same person generously puts that knowledge out there for anyone to access at any time.

I had difficulties adding multiple ingress rules to a security group within an AWS CloudFormation template. Each attempt would trip an error. A rather esoteric question I thought. Within my first search I came across Leah Erb's blog post outlining the same problem I was running into. Further, Leah even shows how she thought multiple ingress rules work, bearing an uncanny resemblance to my own attempts.

Not only did I leave with a solution, but with a rekindled sense of optimism. Someone decided to share their own solution to a problem. There's a chance that Leah might not have shared it, but she decided to hit publish anyway. I am better because of that generosity and the generosity of many others who decide to contribute. Many tiny miracles that, intertwined, make up the web.

The conclusion from a recent Jon Udell blog post says it all:

Yes, there’s a dark side to our connected world, darker than I was once willing to imagine. But there is also so much light. It’s always helpful to consider deep geological time. [ ... ] We’ve only been connected like this for 25 years. Maybe we’ll figure it out. For today, at least, I choose to believe that we will.

If you make it, the code will run. Even if it's close to the weekend. Even if you're tired. Even if you don't want to write. The code won't listen to your excuses. The code will run.

So here I am writing this little post after forgetting that I set my AWS Lambda function to publish my blog at 5pm.

Again, back to the programmatic accountability I set up in the first place. This is what I wanted — a system that would help me push past my writer's block and publish regardless.

Funny how something as simple as a cron job in the cloud can surprise you.

A while back in conservatory, I had to learn a piece of music on guitar called “El Polifemo de Oro” by Reginald Smith Brindle (here's a beastly recording of Julian Bream playing it).

What made the piece so maddeningly difficult to learn is that it eschews chords & patterns that you're used to playing. You want to play one way but the sheet music says otherwise. You feel like you're exploring another world, dealing with another world on its own terms and not yours.

I am reminded of this feeling when trying to figure out a recent pull request for WriteFreely the other day. It's solution required me to deal with the underlying web template system.

I come from the world of Python, so specifically the land of Jinja as far as web templating goes. When adding an if/or conditional statement to a template, I add something like this:

{% if this or that  %}

So when approached with Golang's templating language, I saw a nail that I thought my usual hammer could work with.

{{ if this or that }}

But that didn't work at all. Error after error popped up, I couldn't figure it out for the life of me. Then I ended up at the documentation (where I should've started in the first place) and saw that Golang implemented conditionals in a unique way. Below is how the above statement would look like with Golangs web templating:

{{ if or this that }}

From what I could understand, “or” is treated as a function with the two values being compared acting as arguments to that function. I hadn't seen anything like it before. Like with “El Polifemo de Oro”, I had to deal with Golang on its own terms, not my own Pythonic terms.

What started as frustration gave way to wonder. One reason I love playing classical guitar is the breadth of music to play — so many different genres and styles and eras and periods. One day you can play a piece from a guitarist of Chopin's time and the next you're wrestling with a thorny mess like “El Polifemo de Oro.” Each piece builds upon your current skillset but also asks of new things from you.

I feel the same with programming, especially when learning different languages and frameworks and tools. Each new thing builds upon your current skillset but also asks new things of you, new ways to approach similar problems or new problems entirely.

It's that feeling of exploring another world, dealing with another world on its own terms and not yours. That's the feeling I pursue.