Staged roll-out helper script


#1

We’ve got a bunch of questions at resin about doing staged roll-out, when only a part of the fleet is updated, while the rest is kept back, and then increasing the deployment to the remaining devices in stages. There’s no official tool for that, but we were saying that it is entirely doable with update locking + API-triggered updates in a script. Took today’s Friday Hack time to actually write a proof of concept updater script for exactly this, so now we can put our code where our mouth is.

The source is available at resin-io-playground/resin-stageddeploy.

What it does is that it takes an APP_ID, and either a number (how many devices to update) or a percentage (what fraction of the fleet to update). Then it will check for eligible devices (ie. not updated yet, online, running an application, not provisioning), and triggers an update on a random subset of them up to the specified number of devices.

Install the dependencies for example by running pip install -r requirements.txt in the source directory.

$./stageddeploy.py --help
Usage: stageddeploy.py [OPTIONS] APP_ID

  Helper script for staged roll-out for application updates on resin.io

  Call it with a numerical APP_ID, and one of a number of devices (-n) or
  percentage of fleet (-p) to trigger update on. If no number added, then
  only query is run.

  Only triggers online, idle, not updated, not provisioning devices.

Options:
  -n, --number INTEGER   Number of devices to trigger the update on
  -p, --percent INTEGER  Percentage of fleet to trigger the update on
  -t, --token TEXT       Resin.io auth token, can specify it with the TOKEN
                         env var as well  [required]
  -q, --quiet            Toggles hiding process details
  --help                 Show this message and exit.

Running an update:

$ ./stageddeploy.py 126746 -n 2
Logged in user: imrehg
App: MakerFaireDemo / Commit: ec6568e7153d1059e351bfd90caa48c0b70acf00
=== Devices ===
Device: B3 5577326 / Commit: 449385a / Online: True / Status: Idle
Device: B2 859eb5a / Commit: 4e7dedb / Online: True / Status: Idle
Device: A2 c3bcb2d / Commit: 4e7dedb / Online: True / Status: Idle
Device: B1 531a886 / Commit: ec6568e / Online: True / Status: Idle
Device: A1 4da60b4 / Commit: 4e7dedb / Online: True / Status: Idle
Device: A3 33adbe1 / Commit: 4e7dedb / Online: True / Status: Idle
Number of eligible devices: 5
Devices to update         : 2
=== Updates ===
Updating: B2 859eb5a
Updating: A3 33adbe1

Of coures, it is just one way of doing it, and the Python SDK can also be replaced by the Node.js SDK, or even the Supervisor API, but at least there’s one version now that we can point to.

Let me know if you try it out, what do you think!


#2

We have something similar, but which updates the devices in an application one by one, prompting before updating to have more control.

Check it out here.


#3

Are the devices that get updated always random or is it possible to specify which devices get the update?


#4

@flavia that looks cool too, thanks for sharing :slight_smile: This is a proof-of-concept for me, the goal is to building things with the API. Everyone’s release method is different, and been asked a couple of times for “updating 10% of our devices” and similar questions, that’s why I made this format. The one-by-one confirmation is of course finer control.

@mccollam, at the moment it’s all random for simplicity and train of thought like that above.

But could image things like having a file, listing device UUIDs and the script would prioritize over that. E.g. have 100 devices, 10 on a list to update first, then can say “update 5%” -> take the first 5, “update 5%” again -> check the ones already updated, take the next 5, after which “update x%” would come from the remaining 90 devices at random, for example…


#5

Written up this script in a bit more detail, together with another one in the resin.io blog: Use the API, Luke