Uncle Deadly Image

Hi there. Welcome to blog.oddbit.com! I post articles here on a variety of technical topics. Mostly I’m posting for myself (writing things up helps me remember them in the future), but I always hope the content I put here is helpful to someone else. If you find something here useful and want to say thanks, feel free to buy me a coffee!

New comment system

As long as I’m switching site generators, it seems like a good idea to refresh the comment system as well. I’ve been using Disqus for a while, since when I started it was one of the only games in town. There are now alternatives of different sorts, and one in particular caught my eye: Utterances uses GitHub issues for storing comments, which seems like a fantastic idea.

That means that comments will finally be stored in the same place as the blog content, which I think is a happy state of affairs.

[read more]

Adding support for privilege escalation to Ansible’s docker connection driver

Update 2019-05-09 Pull request #55816 has merged, so you can now use sudo with the docker connection driver even when sudo is configured to require a password.


I often use Docker to test out Ansible playbooks. While normally that works great, I recently ran into an unexpected problem with privilege escalation. Given a simple playbook like this:

---
- hosts: all
  gather_facts: false
  become: true
  tasks:
    - ping:

And an inventory like this:

[read more]

Writing Ansible filter plugins

I often see questions from people who are attemping to perform complex text transformations in their Ansible playbooks. While I am a huge fan of Ansible, data transformation is not one of its strong points. For example, this past week someone asked a question on Stack Overflow in which they were attempting to convert the output of the keytool command into a list of dictionaries. The output of the keytool -list -v command looks something like this:

[read more]

Docker build learns about secrets and ssh agent forwarding

A common problem for folks working with Docker is accessing resources which require authentication during the image build step. A particularly common use case is getting access to private git repositories using ssh key-based authentication. Until recently there hasn’t been a great solution:

  • you can embed secrets in your image, but now you can’t share the image with anybody.
  • you can use build arguments, but this requires passing in an unenecrypted private key on the docker build command line, which is suboptimal for a number of reasons
  • you can perform all the steps requiring authentication at runtime, but this can needlessly complicate your container startup process.

With Docker 18.09, there are some experimental features available that makes this much easier. You can read the official announcement here, but I wanted to highlight the support for ssh agent forwarding and private keys.

[read more]

In which I PEBKAC so you don’t have to

Say you have a simple bit of code:

#include <avr/io.h>
#include <util/delay.h> 

#define LED_BUILTIN _BV(PORTB5)

int main(void) 
{
    DDRB |= LED_BUILTIN;

    while (1)
    {
        PORTB |= LED_BUILTIN;   // turn on led
        _delay_ms(1000);        // delay 1s

        PORTB &= ~LED_BUILTIN;  // turn off led
        _delay_ms(1000);        // delay 1s
    }                                                
}

You have a Makefile that compiles that into an object (.o) file like this:

avr-gcc -mmcu=atmega328p -DF_CPU=16000000 -Os -c blink.c

If you were to forget to set the device type when compiling your .c file into an object file (.o), you would get a warning:

[read more]

ATOMIC_BLOCK magic in avr-libc

The AVR C library, avr-libc, provide an ATOMIC_BLOCK macro that you can use to wrap critical sections of your code to ensure that interrupts are disabled while the code executes. At high level, the ATOMIC_BLOCK macro (when called using ATOMIC_FORCEON) does something like this:

cli();

...your code here...

seti();

But it’s more than that. If you read the documentation for the macro, it says:

Creates a block of code that is guaranteed to be executed atomically. Upon entering the block the Global Interrupt Status flag in SREG is disabled, and re-enabled upon exiting the block from any exit path.

[read more]

AVR micro-optimization: Avr-gcc and –short-enums

How big is an enum?

I noticed something odd while browsing through the assembly output of some AVR C code I wrote recently. In the code, I have the following expression:

int main() {
    setup();

    while (state != STATE_QUIT) {
        loop();
    }
}

Here, state is a variable of type enum STATE, which looks something like this (not exactly like this; there are actually 19 possible values but I didn’t want to clutter this post with unnecessary code listings):

[read more]

AVR micro-optimization: Losing malloc

Pssst! Hey…hey, buddy, wanna get an extra KB for cheap?

When I write OO-style code in C, I usually start with something like the following, in which I use malloc() to allocate memory for a variable of a particular type, perform some initialization actions, and then return it to the caller:

Button *button_new(uint8_t pin, uint8_t poll_freq) {
    Button *button = (Button *)malloc(sizeof(Button));
    // do some initialization stuff

    return button;
}

And when initially writing pipower, that’s exactly what I did. But while thinking about it after the fact, I realized the following:

[read more]