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.
$./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:
resin.auth.login_with_tokenauthenticates with the resin.io platform using a token, instead of username/password
resin.auth.who_am_ito query which user the token belongs to, just for debugging purposes
resin.models.environment_variables.application.get_allto query existing environment variables, both at the origin and the destination app
resin.models.environment_variables.application.createto create new environment variables
resin.models.environment_variables.application.updateto update values of existing variables
resin.models.environment_variables.application.removeto remove variables if needed
To run this you need Python 2.7. Install the requirements with
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
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
- 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:
resin.models.application.get_by_idto retreive info about an application by its ID
resin.models.device.get_all_by_applicationthe get the devices belonging to a given application
resin.models.supervisor.updateto override the update lock
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!