Why I Created an OpenFaaS template for COBOL
In early April a couple of articles were published stressing the need for COBOL programmers to once again come forward to use their skills to get us through a crisis of aging infrastructure. This wasn’t the first time their expertise was required. Even back in 1998, COBOL was described as
“… a computer language that runs many of the United States’ mainframe computers but is so old that relatively few American programmers know it.”
So why do these programs persist for decades? Why are new experts not hired to maintain this vast amount of COBOL code? The answer is clearly because the code works, and works well enough for modernization of the infrastructure to remain a low priority. Although the language gets a lot of blame, the truth is that much like maintenance of roads and bridges, maintenance of computational infrastructure has faltered, and nothing is better at showing the cracks in that infrastructure than a crisis.
Modern COBOL
It would be generous to call me a novice COBOL programmer. My interest in learning more about this “ancient” language was piqued by the recent articles. Is COBOL an unusable relic from the past? Can COBOL even be compiled on the modern PC with a modern operating system? The answers are a qualified no, and an unqualified yes. COBOL, like other languages, reflects computing at the time it was created. Languages do evolve along with the hardware they run on. Good examples are C and Fortran which have evolved with numerous revisions, but the paradigms of languages rarely shift. COBOL retains the trappings of its origins. Its punch-card origins is revealed in its line formatting (columns 1-6 for line numbers, column 7 to indicate a comment or continuation, 8-72 for statements, and columns 73-80 for marginalia, useful for card sequence numbering). The memory limits of the time are reflected in the flexibility of its variable definition blocks.
COBOL also reflects some interesting ideas. It is so verbose that it makes Java look rather terse, but this is done in the service of readability, which is also a goal of the Go language. Fundamentally, COBOL is an imperative language and as such, its basic structures and statements can be fairly easily decoded by most modern programmers. Although it may look somewhat archaic, and it may contain a lot of keywords, it is not outlandishly different from other modern programming languages. The COBOL compiler which runs under Linux called GnuCOBOL, and can be installed by the debian package manager on any debian-based distribution. Armed with a tiny bit of knowledge, I decided to merge the old with the new and write a serverless COBOL function.
Google Cloud Run
My first step in putting a serverless COBOL function online was to use Google
Cloud Run, a serverless offering from Google which will host any
containers listening for web requests on an open port defined by the PORT
environment variable (right now this is always port 8080). Cloud Run only
charges when there are active HTTP requests connected to the container, and
allows multiple simultaneous connections to the container. There are a number
of examples and tutorials available, and there is even a
sample of a Fortran function which is deployable to Cloud Run.
I do not know how to write a webserver in COBOL, so my COBOL
function includes an invocation server written in Go which in turn
runs the COBOL program and returns its output. You can try it out
here, or and put your name as the PATH
component to get a
personalized hello message. After announcing what I had done on twitter, I got
the intriguing tweet below, which started a journey into OpenFaas.
Rather than maintaining your own wrapper for that, you may find the OpenFaaS watchdog useful with cloudrun. https://t.co/GC1nEY74SZ
— Alex Ellis (@alexellisuk) April 7, 2020
OpenFaaS
I had heard of OpenFaaS before, but at the time I felt I was too busy to learn Kubernetes and OpenFaaS and abandoned it for later. When I got the tweet, I figured now was the time, so I dove into spending weekends learning Kubernetes and OpenFaaS. The fact that I had to stay home because of the pandemic may have also played a role.
The watchdog process itself doesn’t require any specific knowledge of either Kubernetes or OpenFaaS in order to understand. It serves the function of the invoker I previously wrote, but with more bells and whistles including health checks. Essentially the watchdog sends a request into a process’s standard input, and returns the standard output. It also provides several environment variables to describe the URL details and other HTTP headers. This should be familiar to anyone who has used CGI before.
I found that the Kubernetes landscape had changed and advanced significantly since my first attempts to use it. In particular Rancher’s k3s project is much easier to run on low-end equipment. The companion k3d project allows a developer to run k3s in a docker container, making setting up a development Kubernetes environment extremely easy. To begin working with clusters, Alex Ellis’s k3sup project can install k3s on any ssh accessible vm. I fired up k3d and worked through the Kubernetes Basics tutorial to become a little familiar with Kubernetes.
I then moved onto learning OpenFaaS using the OpenFaaS workshop. The workshop is an excellent introduction to OpenFaaS and presents an easy to follow set of labs to get a programmer quickly up to speed. I was impressed with the simplicity of OpenFaaS and the ability to do advanced things like asynchronous functions, auto-scaling, and secrets management. Plus it allows a user to avoid vendor lock-in. You can run your code in any cloud provider or on premises (premises, by the way, is the singular form of that word, premise is a proposition from which one draws a conclusion or forms an argument).
In order to create a COBOL function, I created a base COBOL container using debian-slim, and I created an OpenFaaS COBOL template which contains the information on how to put a COBOL function into an OpenFaaS container, as well as a sample COBOL function. I also submitted this template to the OpenFaaS store, so now a COBOL programmer can easily begin writing an OpenFaaS COBOL function using the commands below.
faas-cli template store pull cobol
followed by
faas-cli new --lang cobol cobolfunction
The standard practice for OpenFaaS is to send input data in the body of a POST
request which is then passed to the function via standard input, so I adjusted
the sample COBOL program accordingly. You can invoke the COBOL function
running on my Kubernetes cluster by issuing the following curl
command:
curl -d "CHRIS" -H "Content-Type: text/plain" https://tess.unnecessary.tech/
But Why?
Everything I have written so far explains what I did, but why did I do it? Initially I just wanted to learn a bit about COBOL and have some fun, after all serverless COBOL sounds a bit like an oxymoron. However, it became a tool for learning about OpenFaaS, and in the end my COBOL template shows that OpenFaaS is extremely flexible, and also very easy to use. Creating functions using your favorite language, or specialized environment is as easy as making an appropriate Docker container. Although it was not my initial goal, this project has highlighted the usefulness, maturity, and flexibility of the OpenFaaS project. I imagine I will be using OpenFaaS a lot moving forward, and I encourage others to learn more about it. I would also encourage others to try any of the other resources I mention above. For anyone who wants to learn more about COBOL, IBM has published their COBOL course for free on GitHub as part of the Open Mainframe project.