Adding to the Boot Sequence

In this tutorial, we'll build a mission control service that relies on an ansible service to communicate with rovers on mars (yes, we're Sci-Fi nerds here at Cosaic). We'll help you with the Finsemble boot sequence - the ansible and Mars rovers are up to you!

To motivate our example, suppose your organization has two teams: a particle physics team responsible for the ansible service, and a space-comms team responsible for the mission control service. While developed and deployed independently, these services depend on each other for their function: namely, the mission control services makes use of the ansible service's exposed API's. By default, custom services launch in the preuser stage - by this stage, the core services (the router, storage, etc.) are online, but apps launched by the workspace are not. Normally, specifying the boot stage is enough; however, since both services will be starting in the same stage, we'll have to rely on explicit boot dependencies to ensure the mission control service is only launched after the ansible service is initialized.

Mars awaits your command, so let's get started!

Creating the Ansible Service

As usual, we'll rely on the Finsemble CLI to do most of the heavy lifting for us. On a command line, in the root of your SmartDesktop directory, run the following:

finsemble-cli add service ansible

This will create our new service, adding it to the SmartDesktop's config.

For edification's sake, let's look at the output. For the purposes of the boot sequence, we can just focus on the added bootParams properties:

{
    // ...
	"ansibleService": {
		"bootParams": {
            "stage": "preuser",
            "dependencies": []
        }
    // ...
    }
    // ...
}

Let's consider each bootParams property in its turn:

  • stage: This controls at which stage the service is launched. Refer back to the boot sequence guide for a list of the different stages.
  • dependencies: This is where you you can specify which other modules your new module depends on.

These defaults look good for our ansible service. Keep in mind that there are several other bootParams you can configure - see the Configuration Reference.

For proof of life (in our service, not on Mars), let's inspect our new service while it's running. Go ahead and start the SmartDesktop:

npm start

Once it comes online, open the System Log from the Finsemble menu and confirm the ansible service was started in the preuser stage (look for the text starting service: ansibleService).

As an additional check, let's open the Central Logger by pressing Ctrl + Shift + L. In "Filters" section, type "ansible service" to find a few logs related to our nascent service.

Searching for Signs of Life

Looks good! With the ansible in place, we can now add our mission control service, which will make calls via the new ansible client.

Creating the Mission Control Service

Shut down Finsemble and add the mission control service with the same Finsemble CLI command as before:

finsemble-cli add service missionControl

Let's add some code to have mission control call the ansible on initialization. Modify the readyHandler function inside missionControlService.js so that it reads like so:

// ...
readyHandler(callback) {
	this.createRouterEndpoints();
	Finsemble.Clients.RouterClient.query("ansible.myFunction", { hello: "world" }, (err, response) => {
		if (err) {
			Finsemble.Clients.Logger.error(err);
		} else {
			Finsemble.Clients.Logger.log("Mission Control made contact with Ansible!", response.data);
		}
	});
	callback();
}
// ...

If we stopped here and tried to start the SmartDesktop, the mission control service might call the ansible successfully, or it might not - since the services are started in parallel during the preuser stage, there's an element of non-determinism at play (and that's no good in space business!).

Let's fix this issue by making the ansible service an explicit dependency of the mission control service. Open up ./configs/application/services.json and make the following edit:

"missionControlService": {
  "bootParams": {
    "stage": "preuser",
    "dependencies": ["ansibleService"]
  },
  "name": "missionControlService",
  "html": "$applicationRoot/services/missionControl/missionControl.html"
}

Start Finsemble, and when it comes online, open the Central Logger again (Ctrl + Shift + L), and enter "mission control" in the "Filters" section. You should see the text, Mission Control made contact with Ansible!, along with a JSON response from the ansible service.

Going Further

This tutorial covered the most basic use case for boot sequence dependencies: a single service depending on a single other service. However, the boot sequence supports more complex scenarios (in fact, the whole SmartDesktop is bootstrapped by the boot sequence); to learn more, check out the guide on the Boot Sequence.

🚀 Give our greeting to Mars!