Use the API, Luke!

The thing about platforms is that everyone wants to use them in their own way. No matter how many features are built in, there will always be people who need something that isn't there or works differently from the defaults. This is why at resin.io we have an API which covers the device and application management tasks you would otherwise do in the resin.io dashboard, thus you can build the tools you need but don't yet exists.

To help you with adding that, our docs contain a detailed API reference, as well as references of the Node.js and Python SDKs. As examples, I'm highlighting two small projects that came out of questions in our chat: copying environment variables between applications, and a "staged deployment" implementation. These should give you some ideas how to get started on your own helper scripts using the API!

Copying Environment Variables Between Applications

Recently we've been asked whether there's an easy way to migrate environment variables between apps (e.g. when moving an app from one hardware architecture to another), without the time consuming manual copy-pasting. The original question mentioned having 68 environment variables, so automating was pretty important.

The API and SDK can easily work with environment variables, so I've created a helper script around the Python SDK to take an input app, an output app and copy the env vars from the first to the second. It can also delete environment variables from the output that weren't in the input originally.

The script is available on Github at resin-io-playground/resin-envmigrate. I'm using Click to create a command line interface, and here's the sample help output:

$./envmigrate.py --help
Usage: envmigrate.py [OPTIONS]

  Migrate environment variables from one resin.io app to another, optionally
  removing variables from the target that do not exist at the origin.

Options:  
  -f, --from INTEGER  ID of application to copy env vars from  [required]
  -t, --to INTEGER    ID of application to copy env vars to  [required]
  --token TEXT        Resin.io auth token, can specify it with the RESIN_TOKEN
                      env var as well  [required]
  --delete-extra      Toggles deleting extra environment variables in the
                      receiving app
  -q, --quiet         Toggles hiding process details
  --yes               Confirm the action without prompting.
  --help              Show this message and exit.

The script uses these SDK calls:

To run this you need Python 2.7. Install the requirements with pip from requirements.txt. Get you resin.io authentication token from the dashboard, and run the script, following the instructions. You can get the application ID from the dashboard (navigate to the application and get the ID value from the URL, such as https://dashboard.resin.io/apps/ID/devices)

One could also expand the script to copy environment variables between devices or other combination such as application-to-device or device-to-application, will probably add that in a future version.

Feedback on this scrip is appreciated on the forums!

Staged Deployment of a New Application Version

We've got a lot of questions about staged roll-out of new code, in which case only a part of the fleet is updated at any given time, while the rest is kept back till the update is considered correct. The effect of the changes is monitored, and when happy with the results, one can broaden 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. Now we can put our code where our mouth is, and show a proof-of-concept tool.

The source is available at resin-io-playground/resin-stageddeploy. The script takes an application ID, and either a number (how many devices to update) or a percentage (what fraction of the fleet to update). It then checks for eligible devices:

  • not updated yet
  • online
  • running an application
  • not provisioning

Finally, triggers an update (overrides the update lock) on a random subset of them up to the specified number or fraction if of devices. Here's the example output of one such deploy:

$./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 the fleet (-p) to trigger an update on. If no number added, then
  only the 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: StagedDemo / 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  

The script is using the following parts of the SDK:

Install the dependencies using pip from with requirements.txt in the source directory. In the application you deploy onto the resin.io devices you need to add a step of creating the update lockfile at /data/resin-updates.lock, for example adding touch /data/resin-updates.lock in your start script. After this updates will be downloaded but not applied until the lock is overridden either in the dashboard or through the API like this script does.

Of course, this is just one way of doing staged deploys, and the Python SDK can also be replaced by the Node.js SDK or even the Supervisor API, but that's the beauty of an API, enabling you to customize your toolkit.

If you try this out, would love to hear your feedback in the forums.



Luke's using the API to get some important things done

What kind of helper scripts you'd like to see? What have you built yourself? We'd love to discuss more about this in the Projects section of the forums!

resin_io