Introduction
A recurrent question I get is how the hell can we easily run a microservice locally.
Regardless of the technology, one needs to provide the following environment variables to the microservice (given it is multitenant):
- C8Y_BASEURL
- C8Y_BOOTSTRAP_USER
- C8Y_BOOTSTRAP_PASSWORD
- C8Y_BOOTSTRAP_TENANT
- C8Y_MICROSERVICE_ISOLATION=MULTI_TENANT
- APPLICATION_NAME
- APPLICATION_KEY
C8Y_URL is rather straightforward: this is your tenant URL.
C8Y_BOOTSTRAP_TENANT is also rather straightforward as getting one’s tenant Id is easy.
Now the tricky part is getting the other parameters. If you create an application or a microservice in Cumulocity UI, you will immediately see the application name and the application key.
But how the hell do you get the bootstrap user and the bootstrap password? Let’s dig into that.
Creating your application
The first thing to do is to create the application.
Basically, you will need to do that through the API… Or using go-c8y-cli!
If you’re not familiar with this wonderful tool, I urge you to get a look at its website: Cumulocity IoT CLI | Cumulocity IoT CLI (goc8ycli.netlify.app)
Now, let’s first detail the steps to create an application:
- First, you need to create the application object itself in Cumulocity
- While creating this application object you need to indicate this is a microservice
- Last but not least, you need to give at least the required roles of your microservice, otherwise, your nice little microservice won’t be able to do a thing in Cumulocity
The go-c8y-cli command to create such an app with the minimum required stuff looks like this:
c8y applications create --name my-new-ms --type MICROSERVICE --key my-new-ms-key --data 'requiredRoles=[
"ROLE_INVENTORY_READ",
"ROLE_INVENTORY_ADMIN",
"ROLE_INVENTORY_CREATE",
"ROLE_EVENT_READ",
"ROLE_EVENT_ADMIN",
"ROLE_ALARM_READ",
"ROLE_ALARM_ADMIN",
"ROLE_IDENTITY_READ",
"ROLE_IDENTITY_ADMIN",
"ROLE_DEVICE_CONTROL_READ",
"ROLE_DEVICE_CONTROL_ADMIN",
"ROLE_MEASUREMENT_READ",
"ROLE_MEASUREMENT_ADMIN"
]'
This will create a new empty microservice called my-new-ms
Enable your microservice
Next, since this is a multi-tenant microservice, you’ll need to ensure that your tenant subscribes to this microservice.
With go-c8y-cli this can be done with a simple command:
c8y microservices enable --id my-new-ms
Getting your microservice bootstrap user
Again, with go-c8y-cli this is insanely simple:
c8y microservices getBootstrapUser --id my-new-ms
Now you’ve got all you need to run any microservice locally.
But let’s focus on Java.
Running your Java microservice with one line
I will assume that you are using the Microservice SDK which is based on Spring Boot.
There are plenty of environment variables that are supported by Spring Boot, but only one that is of special interest to us here: SPRING_APPLICATION_JSON
This variable allows you to pass the whole application configuration as a JSON string to Spring Boot.
Why do we need that? Because go-c8y-cli outputs are in JSON
With that we can start our microservice with just one line:
SPRING_APPLICATION_JSON=$(c8y microservices get --id my-new-ms | c8y microservices getBootstrapUser --outputTemplate="{application:{name:'my-new-ms'}, C8Y:{baseUrl:'$C8Y_HOST', bootstrap:{tenant:output.tenant, user:output.name, password:output.password}, microservice: {isolation: 'MULTI_TENANT'}}}") java -jar my-new-ms/target/my-new-ms-1.0-SNAPSHOT.jar
That’s it!
If you’re wondering, the C8Y_HOST env variable is set for you by go-c8y-cli when you set a session.
Putting everything together
Finally here is a script (for Debian/Ubuntu) that takes your application name as a parameter and will do everything for you:
- Installs go-c8y-cli if it’s not there
- Creates a session if none exists
- Sets a session
- Creates and enables the application
- Starts the microservice
#!/usr/bin/bash
echo "Checking that go-c8y-cli is installed"
if ! c8y version 2> /dev/null ; then
echo "go-c8y-cli will be installed"
sudo apt-get install -y curl gnupg2 apt-transport-https
curl https://reubenmiller.github.io/go-c8y-cli-repo/debian/PUBLIC.KEY | gpg --dearmor | sudo tee /usr/share/keyrings/go-c8y-cli-archive-keyring.gpg >/dev/null
sudo sh -c "echo 'deb [signed-by=/usr/share/keyrings/go-c8y-cli-archive-keyring.gpg] http://reubenmiller.github.io/go-c8y-cli-repo/debian stable main' >> /etc/apt/sources.list"
sudo apt-get update
sudo apt-get install go-c8y-cli
fi
echo "Checking that at least a Cumulocity session exists"
if ! c8y sessions list 2> /dev/null ; then
echo "A Cumulocity session needs to be created"
c8y sessions create
fi
c8y sessions set
if c8y microservices get --id $1 2> /dev/null ; then
echo "Microservice $1 exists"
else
echo "Microservice $1 does not exist and will be created"
c8y applications create --name $1 --type MICROSERVICE --key $1-key --data 'requiredRoles=[
"ROLE_INVENTORY_READ",
"ROLE_INVENTORY_ADMIN",
"ROLE_INVENTORY_CREATE",
"ROLE_EVENT_READ",
"ROLE_EVENT_ADMIN",
"ROLE_ALARM_READ",
"ROLE_ALARM_ADMIN",
"ROLE_IDENTITY_READ",
"ROLE_IDENTITY_ADMIN",
"ROLE_DEVICE_CONTROL_READ",
"ROLE_DEVICE_CONTROL_ADMIN",
"ROLE_MEASUREMENT_READ",
"ROLE_MEASUREMENT_ADMIN"
]'
c8y microservices enable --id $1
fi
SPRING_APPLICATION_JSON=$(c8y microservices get --id $1 | c8y microservices getBootstrapUser --outputTemplate="{application:{name:'$1'}, C8Y:{baseUrl:'$C8Y_HOST', bootstrap:{tenant:output.tenant, user:output.name, password:output.password}, microservice: {isolation: 'MULTI_TENANT'}}}") java -jar $1/target/$1-1.0-SNAPSHOT.jar