Why I Created an OpenFaaS template for COBOL
Christopher De Vries
April 27, 2020
In early April a [couple][article1] [of][article2] [articles][article3] 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][y2k] 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."
>
> — [Feder & Pollack, "Computers and Year 2000: A Race for Security
> (and Against Time)", New York Times, 1998][y2k]
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][compiler], 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][cloudrun], 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][awesomecloudrun] available, and there is even a
sample of a [Fortran function][fortran] which is deployable to Cloud Run.
I do not know how to write a webserver in COBOL, so [my COBOL
function][cobolrun] includes an invocation server written in Go which in turn
runs the COBOL program and returns its output. You can [try it out
here][runexample], 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][openfaas].
{{< x user="alexellisuk" id="1247431951956480001" >}}
OpenFaaS
I had heard of [OpenFaaS][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][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][Kubernetesbasics] tutorial to become a little familiar with
Kubernetes.
I then moved onto learning [OpenFaaS][openfaas] using the [OpenFaaS
workshop][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][cobolcontainer], and I created an [OpenFaaS COBOL
template][cobolfaas] 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.
followed by
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:
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][ibmcourse] for
free on GitHub as part of the [Open Mainframe][openmainframe] project.
[article1]: https://www.cnn.com/2020/04/08/business/coronavirus-cobol-programmers-new-jersey-trnd/index.html
[article2]: https://www.npr.org/2020/04/22/841682627/cobol-cowboys-aim-to-rescue-sluggish-state-unemployment-systems
[article3]: https://arstechnica.com/tech-policy/2020/04/ibm-scrambles-to-find-or-train-more-cobol-programmers-to-help-states/
[y2k]: https://archive.nytimes.com/www.nytimes.com/library/tech/98/12/biztech/articles/27millennium.html?RefId=PjxYEutt2uFFwKZO
[compiler]: https://sourceforge.net/projects/open-cobol/
[cloudrun]: https://cloud.google.com/run/
[awesomecloudrun]: https://github.com/steren/awesome-cloudrun
[fortran]: https://github.com/zachmccormick/fortran-cloudrun
[cobolrun]: https://github.com/devries/cloud-run-cobol
[openfaas]: https://www.openfaas.com/
[k3s]: https://k3s.io/
[k3d]: https://github.com/rancher/k3d
[k3sup]: https://github.com/alexellis/k3sup
[watchdog]: https://docs.openfaas.com/architecture/watchdog/
[cobolcontainer]: https://github.com/devries/docker-cobol
[cobolfaas]: https://github.com/devries/openfaas-cobol-template
[runexample]: https://cloud-run-cobol-j6z4gxi7tq-uc.a.run.app/CHRIS
[workshop]: https://github.com/openfaas/workshop
[kubernetesbasics]: https://kubernetes.io/docs/tutorials/kubernetes-basics/
[ibmcourse]: https://github.com/openmainframeproject/cobol-programming-course
[openmainframe]: https://www.openmainframeproject.org/
Discussion in the ATmosphere