Build a Server-Less Cloud OS
Server-less compute environments provide the missing compute functionality, i.e., CPU, in building a server-less cloud operating system; coupled with communications, storage, authentication/authorization, and input / output you have you need.
In this article, I will illustrate what I mean by a server-less cloud operating system through an example; building a system that allows a visitor to touch various fruits, real fruits, and see a summary of that fruit on a screen. They can then request to receive an email for more details on that fruit.
While the Internet is the clearly the conduit for anything cloud, websockets, specifically, are the key to the real-time communications for this system.
While socket.io has been my websocket go-to solution for some time, it requires a server. At the same time, I had been using Google Firebase as my server-less websocket solution (among other things) for prototyping.
note: The recent introduction of Google Cloud Functions (more on that later) has changed my calculus and I am seriously considering using Google Firebase for production solutions.
Google Firebase’s database feature, uses websockets under the hood, allows various components of the system to communicate by sharing, real-time, a common state tree (tree of key-value pairs).
The initial setup is as simple as creating a new Google Firebase project; I named it fruit-kiosk.
In the context of this system, storage consists of persisting two types of information: static and dynamic. Each type, in turn, consists of two sub-types: key/value pairs and files.
Both the static and dynamic persistent key/value pairs will be stored along-side of the transient information (used for component communication) in the Google Firebase’s (fruit-kiosk) database feature.
- Static — Key/Value Pairs: The list of touchable fruits.
- Dynamic — Key/Value Pairs: The touched fruit and the list of visitors that signed up.
The static — files will be stored in the Google Firebase’s (fruit-kiosk) hosting feature.
note: If dynamic — files were needed, I would be using the Google Firebase’s (fruit-kiosk) storage feature.
In the fruit-kiosk project, I followed the instructions (involves creating a local development repository) for the hosting feature to upload three images: apple.jpg, banana.jpg, and orange.jpg into a fruits folder. These became publicly available as:
Using the database GUI editor, I created following structure:
+ detail: "The apple tree (Malus pumila, commonly and erroneously called Malus domestica) is a deciduous tree in the rose family best known for its sweet, pomaceous fruit, the apple."
+ image: "https://fruit-kiosk.firebaseapp.com/fruits/apple.jpg"
+ order: 0
+ summary: "red crunchy goodness"
+ detail: "The banana is an edible fruit – botanically a berry – produced by several kinds of large herbaceous flowering plants in the genus Musa."
+ image: "https://fruit-kiosk.firebaseapp.com/fruits/banana.jpg"
+ order: 1
+ summary: "yellow creamy"
+ detail: "The orange is the fruit of the citrus species Citrus × sinensis in the family Rutaceae."
+ image: "https://fruit-kiosk.firebaseapp.com/fruits/orange.jpg"
+ order: 2
+ summary: "sweet and juicy"
Because the system communicates over the open Internet, I first needed a way to authenticate and authorize components:
- The touch component: Raspberry Pi application that detects the touches on the fruit.
- The display component: Front-end application that displays the image and summary of a touched fruit. User can request to be sent an email with details.
- The administrative component: Administration front-end application displays the list of those who signed up for an email.
I used the Google Firebase (fruit-kiosk) authentication feature and created three users (using email/password feature): firstname.lastname@example.org, email@example.com, and firstname.lastname@example.org.
Out-of-the-box, the database is configured to gives the read/write authorization for the entire state tree to any authenticated user; in this simple example I will not lock down the database further.
Input / Output — Display Component
I next built the front-end application (to be run on a browser on a computer connected to a TV) that displays the touched fruit (image and summary) and a email form for details; source code.
- Error conditions were not considered; just made it work.
Input / Output — Admin Component
I next built the front-end application (to be run on a browser on an administrator’s computer) that displays the list of those who requested an email; source code.
- Like the display component, it is bare-bones without consideration for error conditions.
- The admin username/password is hard-coded into the application; under normal circumstances one would have a login form.
Input / Output — Touch Component
I used a Raspberry Pi and a Adafruit Capacitive Touch HAT for Raspberry Pi — Mini Kit — MPR121 as the hardware for the touch component.
Because there is only a Python library for the MPR121, I had to write a small Python application (source code) to detect the touches. Because, I wanted to minimize my use of Python, I used a socket.io client to send messages to a second application running on the Raspberry Pi.
The initial motivation for this article was to illustrate using the new (it is still in beta) Google Cloud Functions. Much like Amazon Web Services’ Lamdas, Google Cloud Functions provide a server-less compute environment.
In this system, I used a Google Cloud Function, source code, to send an email using the Mailgun email service every time a new entry is added to the database emails branch (when a user requests an email of details).
Using Google Firebase’s server-less features, I have demonstrated building a system consisting of multiple components (running on different computers) with communication, storage, authentication/authorization, input/output, and compute; aka a server-less cloud operating system.