Rust + Gtk = Wow

As I’ve been experimenting with writing Rust apps, I attempted to create a small little GUI application. At first I attempted to setup everything with Qt, but C++/Qt interoperability with Rust is painful. Very, very painful. I experimented with some more radical UI frameworks such as Azul and Conrad. These have a lot of promise going forward. However for the here and now, I recommend looking at gtk-rs, Rust binding for Gtk.

With a bit of experimentation, looking through gtk-rs examples, some other projects using gtk-rs, and lots and lots of searching, I was able to create this:

This is a code viewer that lets you open Rust code, and view it. Yes, you are looking at a portion of the code that runs that code viewer. Getting the GtkSourceView working took some coaxing. Also I had to learn how to use the Glade UI editor for Gtk. Overall it took me about 2 to 3 hours to pull this off. I am very impressed with the results, and it opens up new possibilities for me.

Packaging up a Rust Binary for Linux

Prologue

I should of written an update for quite some time. While I’ve been experimenting with marketing analytics, learning about data science, business development, doing DevOps with GitLab CI and various other things, I wanted to write up my learning when I had a chance to internalize everything. However what made me decide to write an update is this tweet from Chris Krycho. Chris runs the amazing New Rustacean podcast, which is a must listen for anyone interested in learning about programming in Rust.

How does one package a Rust app?

Chris asked about finding a good way to distribute Rust binaries across Linux distros:

Interestingly enough, I recently figured out how to package a small Rust CLI utility that I’m working on. My response was:

This post elaborates on what I meant with my reply.

Building snap packages using snapcraft

The fine folks at Canonical (the makers of Ubuntu Linux), have created something called snap packages. These packages and associated package manager help developers distribute applications (desktop, cloud, etc.) in a safe, isolated manner. I currently have slack installed this way. snaps isolate apps by having the package maintainer declare the capabilities an app requires (network access, access to system files, the GPU, home directory, etc.), and then ensuring the apps can not escape this sandbox.

Basic Setup

Getting setup with packaging a Rust crate was not too hard:

  1. Install snapcraft: sudo snap install snapcraft --classic
  2. Create a snap template inside your crate project: snap init
  3. Edit the generated snap/snapcraft.yml as per the documentation.
  4. Build the snap using snapcraft.
  5. Install the resulting snap with sudo snap install my-cool-rust-bin_x.y.z.snap --devmode --dangerous (this assuming you are experimenting with building a snap)
  6. Add you should be able to distribute your app as a snap now. (See the caveats below.)

Caveats working with snaps

Now there a bunch of caveats when working with snaps. And for my own Rust utility, I found these too taxing and I decided to go with creating a standard Debian package instead. However if I wanted to target multiple distributions and my app didn’t have a very unorthodox setup (my app relies on using the Chrome WebDriver to control a networked device managed by dd-wrt), I would probably have gone with a snap instead:

  • You need to know what capabilities your app needs: file access, network, etc. and you need to declare the appropriate interfaces in your snapcraft.yml
  • Using something other than my local system (be it a Docker based build or using a different base like base18), failed terribly at least for Rust.
  • Whether or not I’d have more success if my base system was the recommended Ubuntu 16.04 and not 18.04 is an outstanding mystery.
  • The snap confinement, even on the much more liberal devmode, works very well. No amount of coaxing on my part, let me use system paths when trying to spawn a process. This could just be me though, as not declaring network access did not block my app.
  • The docs could of been clearer about what was the latest recommended approach. (Still way clearer than the documentation for creating a DEB or RPM from scratch.)
  • Knowing which libraries (for the type of base system) your app needs takes a bit of experimentation. (e.g. I needed libssl1.0 for some builds and libssl1.1)
  • I have no idea how the classical confinement should work, and it is not recommended either way.

The end result for me was a working snap package, but an app that would not work when called from an installed snap. However I think snap packages are probably the way to go moving forward (or a similar format like flatpak). Since I only plan on targeting local Ubuntu 18.04 installs, I ended up creating a Debian package instead.

Building a Debian package with Cargo

I found a nice utility for creating a deb out of a Rust crate, called cargo-deb. After installing the crate with cargo: cargo install cargo-deb, I simply ran cargo deb and I was done. cargo-deb looked into my Cargo.toml for the metadata, ran a build and a few moments later I was the proud owner of a Debian package. Since my app relies on the chromium-browser and chromium-chromedriver packages, I added a small section in my Cargo.toml as so:

[package.metadata.deb]
depends = "$auto, chromium-browser, chromium-chromedriver"

The $auto is something that the Debian packaging mechanism needs, and that is the comma separated format that DEBs use.

Building a RPM from a DEB package

Now this the part that I didn’t do this time around. However I figured out how to create RPM packages from DEB packages a few months ago. The trick is to use the alien utility to create a RPM out of a DEB:

sudo alien --to-rpm --scripts --verbose my-cool-rust-bin.deb

For the record, I did not try to improve or debug the resulting RPM. (This entire effort was for a product that failed to launch.) However as part of my tests I was able install it and run it from on CentOS VM.

Epilogue

Anyways, I would recommend the cargo-deb and alien approach, if you are not planning to distribute a Rust app across a multitude of Linux distros. I would recommend dipping into snap if you plan on distributing something more commercial and wide-spread like a slack or kubectl. And I hope that helps you on your Rust app packaging for Linux journey!

Embedded Rust Library Experiment for Python and Web Assembly

With my ever growing list of things that I need to catch up (like wiring my home network and managing Rookeries), I needed a small fun project that I can work on. Ever since I learned enough Rust to be able to convert Rookeries, I wanted to play around with being able to speed up my code with a Rust library. I am especially interested in figuring how to call Rust code from Python or from JS with Web Assembly.

As a test bed (and a reason) for me to learn this, I created a small little library for getting the uptime of a local server (Linux only): embedded-uptime converting between different measurement units like Celsius and Fahrenheit: embedded-unit-converter. If you’d like to follow along, feel free to check it out. I will be posting updates on the blog, and on the Rookeries mailing list.

Updated on 2019 February 4: When I setup the project, I forgot that server uptimes that rely on accessing a server’s /proc/uptime can not possibly work in Web Assembly in browser environment. After some consideration I decided to go with something simple that accessible from any platform, namely conversion between different units of measure.

Fixing Docker on Linode (Linux v4.18.16)

This week as I had some downtime after PyCon Canada, I started working on resolving all the issues that I postponed. One of these issues involved applying security updates to my Linode server and rebooting the server. However when I did so… I noticed that the Rookeries site went down. When I logged into the server, I quickly found the problem: Docker refused to start after the kernel updates.

As this bug report on Docker for Linux says, there is an issue with the latest Linode kernel when it comes to OverlayFS.

This causes the containerdservice that docker-ce is dependent on to not start. When looking at the logs (using sudo journalctl -xe), you’ll see an error along the lines of:

modprobe: ERROR: ../libkmod/libkmod.c:514 lookup_builtin_file() could not open builtin file '/lib/modules/4.18.16-x86_64-linode118/modules.builtin.bin'
modprobe: FATAL: Module overlay not found in directory /lib/modules/4.18.16-x86_64-linode118)

Thankfully there is a workaround to resolve this problem. From the instructions you need to an override configuration for the containerd service:

$ mkdir -p /etc/systemd/system/containerd.service.d/
$ cat << EOF > /etc/systemd/system/containerd.service.d/override.conf [Service]
ExecStartPre=
EOF
$ systemctl reload
$ systemctl restart docker

Anyways, I hope this helps if you run into the same situation.

Juggling JSON with jq is Out Today

Apologies for the late post but it has been a busy day. As of today you can buy the early edition of Juggling JSON with jq on Gumroad. I am very excited since this is my first attempt at self publishing a book. Naturally the journey is still continuing as I work towards the final release of the book. All buyers of the book will get updates including the final version when it comes out.

I plan sending out an update on the book and the companion site/API that I am working on.

Getting Started with Writing a Technical ebook

The early release of my ebook Juggling JSON with jq comes out tomorrow! However this post is more about the process of writing the book itself.

Getting started on an technical ebook, (such as Juggling JSON with jq), requires a bit of upfront setup. On the ebook side, I decided to go the route of writing the book in Markdown, and generating the various formats using Sphinx. While I feel most comfortable using Markdown, and yet Sphinx uses reStructedText by default. So I had to coax Sphinx to accept Markdown by using a project called m2r. Generating the PDF version of the ebook took a bit to get working. Sphinx uses LaTeX to generate PDFs, and LaTeX while powerful can be clunky to work with. I wrapped everything up with an invoke script, and now I can quickly generating new versions of ebook in the various formats I want to support.

Something unique to writing technical books, is the need to have actual working examples. You can learn by reading, but working through exercises and examples re-enforces that learning. In the case of Unjumbling JSON with jq, I needed an example REST API that readers play with. I searched for some nice open APIs, but nothing seemed very compelling. Many of the open APIs require some form of user registration and non-trivial authentication method that would complicate the examples in the book. So I setup a simple demo API for the book. Thankfully with Docker and Flask, that isn’t a particularly daunting task. (Dockerizing most of my webapps definitely made my live easier overall.)

Finally using Gumroad made marketing and selling the book a lot more approachable. Getting everything setup for e-commerce is a daunting job, if you plan on doing it yourself. Thankfully for ebooks, and similar digital products, Gumroad solves most of the problems one can encounter. I definitely recommend using them if you are planning to do something similar.

Book Announcement: Unjumbling JSON with jq

jq is an amazing tool for querying and manipulating JSON in command-line, that I learned about from one of my good colleagues, Eric Olsen. And I feel that jq deserves a good book describing how to use this tool. Hence I am writing a book called Unjumbling JSON with jq on the topic.

As mentioned in a previous post, I originally planned on writing a single book on both jq and httpie. I divided the original book in two, because there is only a small overlap between the two. I wanted to show examples of grabbing a REST API response via httpie, and parsing the JSON output with jq. However basic querying a REST API is something that could be covered in a short section. By writing the books separately, I will be able to release them faster, and the books will be much more focused.

I plan on selling early drafts of the ebook on August 10th. Buyers of the ebook will get regular versions of the evolving drafts of the ebook, and a free upgrade to the final version of the book. I want to release the early drafts to get early reader feedback. In addition readers of the book will have access to the REST API that accompanies the book.

You can order the early version of Unjumbling JSON with jq from here].

WordPress Password Resets via MySQL

I have not completed the switch away from WordPress completely, (as this site and the justCheckers site show). I might switch to using something like Django CMS or Wagtail. Unfortunately I have not had as much time as I’d like to, to work on Rookeries, my own Flask based CMS

Still in the meantime, I managed to accidentally lock myself out of my own WordPress sites. Thankfully there are a few ways to reset passwords in WordPress. The most surefire way I found was to reset the password using MySQL. (Using the wp-cli tools looks interesting, but I didn’t feel like setting up get another PHP tool.) Most of the time you don’t need to do this. However if you’ve managed to forget your only admin password… well this will get you out of that problem. So what does resetting a WordPress password via MySQL, you ask?

  1. Log into your server via SSH (or to MySQL via a SSH tunnel if you have that enabled)
  2. Login into MySQL: mysql -u $MY_DB_USER -p
  3. Get the username if you have not already. You can look those up in the ${MY_WP_SUFFIX}_wp_users table.
  4. Finally reset the password, using the MD5() function and an update SQL statement: UPDATE "wp_users" SET "user_pass" = MD5('new_password') WHERE "wp_users"."user_login"= "username";
  5. Log in with the user using the regular WordPress login (e.g. https://my-wordpress.example.com/wp-login.php). Remember to change the password, as that will use a stronger hash than MD5 internally and is more secure.

And there you go!

Notify Me when Done “X” in KDE

One of the few Java webapps I work on at work, has a very long startup time. Unfortunately since the server startup code is proprietary and owned by the vendor, there is not much I can do about that. However it is easy to forget to check if the server has started up, I decided to that I needed a way for my computer to notify me that the webapp was up. Here is how I came up with a simple and quick way to do just that in KDE.

So my webapp has an health endpoint that can be easily queried via HTTP. With httpie the HTTP query was very easy, however to script httpie to keep querying until the result came back, meaning the server was up. At first I tried do a while with negation of the return code, and then I found on StackOverflow that the bash until command will do just that. (Without needing to figure out the appropriate negation).

The second part was figuring how to create notifications in KDE via the console. Turns out that kdialog will create both notifications and general popup alerts.

Putting the two together I came up:

until http :8080/my_health_endpoint; do echo 'Waiting...'; sleep 10; done; kdialog --passivepopup "Ready to go!" 10`

I added a sleep in there, to throttle the number of times that httpie would run. The second parameter on the kdialog dictates how long the notification popup will be around. Alternatively I could of used --msgbox if I wanted a dialog that I had to press ‘OK’ on.

Resources

Approaching Inbox Zero in Gmail

Earlier this year (yes I meant to send this out much earlier) I went to a meetup hosted by my local PyLadies group. There Tracy Osborn of Wedding Lovely and Hello Web App fame gave an amazing talk about marketing for developers. I was truly inspired by the talk, and I feel it was very relevant for me, especially as I try to launch my first product and startup Amber Penguin Software. I could write a series of blog posts just on the content from this one meetup alone, and I probably will over time. But today I’ll focus on one thing in particular that I’ve learned from Tracy.

Getting to Inbox Zero

Nowadays I try to not organize my day to day tasks, by either my inbox or even one of my many, many Trello boards. Rather I try to bite off a few urgent and important tasks each day. Still I end up spending time on tasks initiated from emails in my email inbox. Unfortunately my inboxes seems to fill up faster than I can manage them at times. I would love to have a clean inbox as in Inbox Zero technique but more importantly I want to be much more responsive to the emails I get. Also opening up my email can be overwhelming when I see the number of emails in my inbox.

Using Multiple Inboxes in Gmail

One of the things I learned after the meetup, while browsing Tracy’s site was a technique to get my inbox under control at least in Gmail. In essence, you need to enable the “Multiple Inboxes” lab experiment in the Gmail Labs settings. Then you need to write a few filters such as is:drafts || label:follow-up (which happens to be my filter for follow-up emails) for each particular inbox. Et voilà! You have a much more manageable inbox that is subdivided into categories, and the actions you need to take.

Where it works and where it doesn’t work

Unfortunate this technique only works in Gmail at the moment. Some other webmail providers maybe have a similar multiple inbox solution, but unfortunately ProtonMail does not but it is a suggested feature. So my ProtonMail will probably lag behind in terms of how quickly I respond, unless I or someone else implements the multiple inbox feature in ProtonMail.

However where I can use multiple inboxes like in my Amber Penguin Software email (managed by Gmail) it has drastically improved my email experience and my own responsiveness. My Gmail still needs some love to get everything under control, but once I do I will be much better at replying to emails. Ultimately this technique helps you become more confident in categorizing your email, and then acting up on it when the time comes.