Stop installing CLI tools on your build server — CLI-as-a-Function with OpenFaaS

Continuous Integration and Delivery is a staple for modern software development and the build server is an integral part of that flow.

  • What happens when a CLI tool you have installed on you build server(s) needs updating?
  • Is there someone designated with the appropriate credentials to log in to all of them and run the update process?
  • What happens if they forget one?
What if you had one place to manage all the CLI tools on all your build servers? No matter how many, or where they were.

Enter serverless functions with OpenFaaS.

Serverless Functions Made Simple

OpenFaaS is a serverless framework built with native integrations with Docker Swarm and Kubernetes where the functions are nothing more than Docker containers. What that means is that (nearly) anything you can put into a Docker container can be a serverless function invoked over HTTP.

So, your build server needs to push an image to an AWS Elastic Container Registry? Don’t install the AWS CLI on your build server to get the log in! Call your OpenFaaS aws-cli function!

Need to deploy a container on Azure ACS after a successful build? No need to install the Azure CLI, just call your OpenFaaS azure-cli function!

By having your CLI tools as serverless functions, you no longer need extensive setup to get a new build server up and running. Plus, updating your CLI functions, means the CLI version is updated everywhere.

Let me show you some quick examples.

First, make sure you have OpenFaaS up and running somewhere that the build server will be able to access.

Having the OpenFaas CLI installed on you machine makes this process really easy! So, make sure that’s setup and ready to go.


Once OpenFaaS is up and runnning somewhere (locally, for these examples), and the OpenFaaS CLI is installed, let’s build out an AWS CLI function!

faas-cli new aws-cli --lang dockerfile

Now, go to the function’s folder that was created and open up the Dockerfile. We’ll need to tweak it just a little to install the tool we need. The Dockerfile should look like this when you’re done:

FROM python:2.7.14-alpine3.7
ADD /usr/bin
RUN chmod +x /usr/bin/fwatchdog
RUN pip install awscli --upgrade --user
RUN apk add --no-cache less groff
ENV PATH=$PATH:/root/.local/bin/
ENV fprocess="xargs aws"
HEALTHCHECK --interval=5s CMD [ -e /tmp/.lock ] || exit 1
CMD ["fwatchdog"]

You will also need to modify the aws-cli.yml file to add the environment variables that will hook up your aws account. The updated .yml file will look something like this:

name: faas
gateway: http://localhost:8080
lang: dockerfile
handler: ./aws-cli
image: aws-cli
AWS_ACCESS_KEY_ID: your-access-key
AWS_SECRET_ACCESS_KEY: your-secret-key

Of course, you will need to add your credentials, and adjust the gateway for where your OpenFaaS cluster is running.

Build and deploy your new CLI function

faas-cli build -f aws-cli.yml

faas-cli deploy -f aws-cli.yml

It is now possible to use basic HTTP calls to perform actions with aws!

curl -d "--version" http://localhost:8080/function/aws-cli

Look ma! Nothing installed locally!
Note: Because your credentials are included in the function, be sure OpenFaaS is running with some security in place. Some examples can be found here and here


We can do the same thing with Azure CLI!

Again, make sure OpenFaaS is up and running, and the OpenFaaS CLI is installed.

faas-cli new azurecli --lang dockerfile

Now, pop open the Dockerfile in the /azurecli directory and replace what’s there with this:

FROM azuresdk/azure-cli-python:latest
WORKDIR /root/.azure
ADD {path to .azure/accessTokens.json} ./
ADD {path to /az.json} ./
ADD {path to /az.sess} ./
ADD {path to /azureProfile.json} ./
ADD {path to /clouds.config} ./
ADD {path to /config} ./
ADD /usr/bin
RUN chmod +x /usr/bin/fwatchdog
ENV fprocess="xargs az"
HEALTHCHECK --interval=5s CMD [ -e /tmp/.lock ] || exit 1
CMD ["fwatchdog"]

You can see, we’re just building off of the azure-cli image that’s already provided. The block of ADD statements are locations that contain the files that are generated when you log in. This way, the function can have access to the resources on Azure. We’re just adding fwatchdog so we can call this through OpenFaaS. Easy!

Azure is a little more tricky than AWS in that you have to login through the CLI at least once since you cannot set the login credentials via environment variables.

What I’ve done here, is started the azure-cli container locally, and logged in via az login . Then, copied the generated files (in the /root/.azure directory) to the function directory (where the Dockerfile is). As long as the function runs at least once every 14 days, you’ll be good. The token expires after 14 days, but renews every time you use it

faas-cli build -f azurecli.yml

faas-cli deploy -f azurecli.yml

Now, let’s try an HTTP call to the Azure CLI

curl -d "aks -h" http://localhost:8080/function/azurecli

You should get back the resulting help documentation from your new Azure CLI function!

All of Azure CLI at the command of a simple HTTP call

Google Cloud-SDK

Finally, to round out the 3 major cloud providers, Google’s Cloud SDK.

Once more, ensure OpenFaaS is up and running and the OpenFaaS CLI is installed.

faas-cli new gcloud --lang dockerfile

Open up the generated Dockerfile in the gcloud/ directory and replace it with the below:

FROM google/cloud-sdk:latest
COPY ./gcloud/ /root/.config/gcloud/
ADD /usr/bin
RUN chmod +x /usr/bin/fwatchdog
ENV fprocess="xargs gcloud"
HEALTHCHECK --interval=5s CMD [ -e /tmp/.lock ] || exit 1
CMD ["fwatchdog"]

Similar to Azure, Google Cloud-SDK stores the credentials on the file system and does not provide an easy way to log in without manually entering everything. So, run the google/cloud-sdk locally, and go through the init steps first to generate your credentials.

docker run -it google/cloud-sdk:latest /bin/bash

gcloud init

Follow the steps in the terminal and once it’s complete, you can copy the credential files out to add them to your function.

docker cp gcloud:/root/.config/gcloud ./gcloud

Copy that directory to your gcloud function directory so that the build will add them to your function.

Let’s build and deploy our Google Cloud-SDK as a function!

faas-cli build -f gcloud.yml

faas-cli deploy -f gcloud.yml

Now, we’re ready to call our Google CLI via HTTP!

curl -d "version" http://localhost:8080/function/gcloud

Manage your GCP compute instances without any installation!

Now, your build server can be clean as a whistle without any extra tools installed! This means you can fire up a new server in no time and not need to worry about how many there are or where they are. You can also update the CLI tools by simply pushing a new version of your function!

For more CLI-as-a-Function, checkout Alex Ellis’ post: CLI Functions with OpenFaaS

The possibilities are endless with OpenFaaS. If you haven’t already, go checkout the Github repos and give it a star. Then, jump on the highly active Slack community by sending a quick introduction to to get an invite. There’s also a Patreon page for helping support this amazingly flexible solution