In this blog series we will develop a small web application that runs in the IBM Cloud. We will be using an old fashion way called rapid application development and an old framework called Plack, a Perl-based web service.

The purpose is twofold.  It demonstrates that traditional style environments can be used to build cloud applications and it also allows us to build a proof of concept in virtually no time.

Let’s get our hands dirty…

Hello world

So here is your basic application that does the usual.

#! /usr/bin/perl

use Plack::Builder;
use Plack::Response;
use strict;

sub main {
        my $env = shift;

        my $res = Plack::Response->new(200);
        $res->content_type("text/plain");
        $res->body("Hello World");

        return $res->finalize;
}

our $app = builder {
        mount "/" => \&main;
}

This small program sets up a default environment that handles incoming requests. If the incoming request starts with a forward, it redirects to a function called main. The main function creates a response of type 200, which is web equivalent to “OK, all is well”, content of type plain/text and the body of the page containing some text, in this case “Hello World”.

If you have set up your perl environment correctly, you can simply put this little program in a file called app.psgi and run ‘plackup’ from the command line. The program ‘plackup’ gets installed as a default runner when you install the Plack Perl library. As soon as you start the Plack framework it will tell you where the service is started.

$ plackup

HTTP::Server::PSGI: Accepting connections at http://0:5000/

Surfing to your local machine on http://localhost:5000/ should give you a “Hello World” page.

As much as this is not doing a lot of things, it will allow us to build up a Cloud Foundry application really quickly. So, let‘s move this application into the cloud.

Converting to a Cloud Foundry application

To convert the application, we will use one of the many small framework, a generic Buildpack for Cloud Foundry which is available on GitHub. To create a Cloud Foundry application with this build pack we will have to create 2 files named SourceyStart.sh and SourceyBuild.sh.

To move the application into the cloud, follow these steps:

1. Set up a basic Plack environment in the Cloud Foundry container.

To make your application work, tell your Cloud Foundry application builder how to create the correct Perl stack. This boils down to creating a SourceyBuild.sh file that contains a number of a “buildPerlModule” commands, per module you are using in your application that do not come with the standard Cloud Foundry environment.

For now, we will have to add the following:

buildPerlModule PSGI
buildPerlModule Plack
buildPerlModule Plack::Runner
buildPerlModule Plack::Request
buildPerlModule Plack::Response
buildPerlModule Plack::Builder

2. Create the startup script for your application.

The “SourceyStart.sh” script containing the startup code for your application.

Please note that the script will be passed the port number on which to accept web requests. In our case we decide to go for something really simple and handle the Plack setup in a little perl script:

#! /bin/sh
echo "starting plackup"
PERL5LIB="/home/vcap/app/sourcey/lib/perl:/home/vcap/app/sourcey/lib/perl5" ./app.pl --port $PORT

3. Create the Plack setup script and copy its content on your local machine.

Create the Plack setup script “app.pl” and with the PERL5LIB path set correctly this is no more difficult than just using making a copy of what is in the “plackup” script on your local machine.

#!/usr/bin/env perl
use strict;
use Plack::Runner;

my $runner = Plack::Runner->new;
$runner->parse_options(@ARGV);
$runner->run;

4. Set the app requirements.

The last thing to do is tell the Cloud Foundry environment what the application requires from a memory perspective and how many instances you would want to run. You can do so by creating a file named “manifest.yml” which is obviously in YML format:

applications:
- name: halloworld
  buildpacks:
  - https://github.com/oetiker/sourcey-buildpack
  disk_quota: 1G
  instances: 1
  memory: 32M
  stack: cflinuxfs3
  timeout: 60

In the example above, we run one instance of this app and give it a memory footprint of 32MB which should be fine for this small application.

You should now have 5 files in your application directory:

  1. app.psgi
  2. SourceyBuild.sh
  3. SourceyStart.sh
  4. app.pl
  5. manifest.yml

With these files you are ready to set up a Cloud Foundry application.

Running the app

In the previous sections we covered the necessary steps for building a simple “Hello World” and converting it into a Cloud Foundry application. Now we’ll show you how to push this app to a Cloud Foundry environment:

1. Set up a working Cloud Foundry environment.

In general terms that means you will have to install a piece of software that connects to an external environment.

In our particular case the Cloud Foundry environment comes integrated in the IBM Cloud environment. For more information, read Installing the stand-alone IBM Cloud CLI.

Once you are logged in into the environment you will be able to use “ibmcloud cf <command>” to run any Cloud Foundry command against the IBM Cloud environment.

In other circumstances you might have to set up your own Cloud Foundry environment which is most likely well documented.

2. Push the app to your Cloud Foundry environment

After you finish setting up your local Cloud Foundry environment, you can push your application by simply instructing the Cloud Foundry environment to use the manifest.yml and install the cloud application. To do so is as simple as “cf push” or in our case prepending “ibmcloud”.

As soon as you have done that you will see the lines of the application builder scroll by.

$ ibmcloud cf push
Invoking ‘cf push’...

Pushing from manifest to org Nexperteam / space digitalinvite as jan@nexperteam.be...
Using manifest file /home/jan/projects/blog/webapp/manifest.yml
Getting app info...
Creating app with these attributes...
+ name:                   halloworld
  path:                   /home/jan/projects/blog/webapp
  buildpacks:
+   https://github.com/oetiker/sourcey-buildpack
+ disk quota:             1G
+ health check timeout:   60
+ instances:              1
+ memory:                 64M
+ stack:                  cflinuxfs3
  routes:
+   halloworld.eu-de.mybluemix.net

Creating app halloworld...
Mapping routes...
Comparing local files to remote cache...
Packaging files to upload...
Uploading files...
 130.33 KiB / 130.33 KiB [==========================================================] 100.00% 1s

Waiting for API to complete processing files...

Staging app and tracing logs...
   Cell e18fb5f1-d6fb-4e1d-b9f8-fcd13fa4b4df creating container for instance 0cb5c538-83bc-4808-ad10-e5974a3a4eb5
   Cell e18fb5f1-d6fb-4e1d-b9f8-fcd13fa4b4df successfully created container for instance 0cb5c538-83bc-4808-ad10-e5974a3a4eb5
   Downloading app package...
   Downloaded app package (130.3K)
          Environment
          -  WORK_DIR=/home/vcap/tmp/sourcey.53
          -  BUILD_DIR=/tmp/app
          -  APP_DIR=app
          -  PREFIX=/home/vcap/app/sourcey
          -  CACHE_DIR=/tmp/cache/final
          Downloading cpanminus
   --2020-09-18 11:25:01--  http://cpanmin.us/
   Resolving cpanmin.us (cpanmin.us)... 151.101.66.217, 151.101.194.217, 151.101.2.217, ...
   Connecting to cpanmin.us (cpanmin.us)|151.101.66.217|:80... connected.
   HTTP request sent, awaiting response... 200 OK
   Length: 302780 (296K) [text/plain]
   Saving to: ‘cpanm’
      250K .......... .......... .......... .......... .....     100% 13.3M=0.01s
   2020-09-18 11:25:01 (21.4 MB/s) - ‘cpanm’ saved [302780/302780]
          Successfully installed PSGI-1.102
          1 distribution installed
          Successfully installed File-ShareDir-Install-0.13
          Successfully installed Stream-Buffered-0.03
          Successfully installed Devel-StackTrace-2.04
          Successfully installed ExtUtils-Config-0.008
          Successfully installed ExtUtils-InstallPaths-0.012
          Successfully installed ExtUtils-Helpers-0.026
          Successfully installed Module-Build-Tiny-0.039
          Successfully installed TimeDate-2.33
          Successfully installed Time-Local-1.30 (upgraded from 1.25)
          Successfully installed HTTP-Date-6.05
          Successfully installed HTTP-Headers-Fast-0.22
          Successfully installed Try-Tiny-0.30
          Successfully installed Module-Build-0.4231
          Successfully installed WWW-Form-UrlEncoded-0.26
          Successfully installed Test-SharedFork-0.35
          Successfully installed Test-TCP-2.22
          Successfully installed URI-1.76
          Successfully installed Cookie-Baker-0.11
          Successfully installed Devel-StackTrace-AsHTML-0.15
          Successfully installed IO-HTML-1.001
          Successfully installed LWP-MediaTypes-6.04
          Successfully installed Encode-3.07 (upgraded from 2.88)
          Successfully installed Encode-Locale-1.05
          Successfully installed HTTP-Message-6.26
          Successfully installed POSIX-strftime-Compiler-0.44
          Successfully installed Apache-LogFormat-Compiler-0.36
          Successfully installed Class-Inspector-1.36
          Successfully installed File-ShareDir-1.116
          Successfully installed Test-Deep-1.130
          Successfully installed HTTP-MultiPartParser-0.02
          Successfully installed Cpanel-JSON-XS-4.23
          Successfully installed JSON-MaybeXS-1.004002
          Successfully installed Hash-MultiValue-0.16
          Successfully installed HTTP-Entity-Parser-0.24
          Successfully installed Filesys-Notify-Simple-0.14
          Successfully installed Plack-1.0047
          36 distributions installed
          Plack::Runner is up to date. (undef)
          Plack::Request is up to date. (1.0047)
          Plack::Response is up to date. (1.0047)
          Plack::Builder is up to date. (undef)
…
   Exit status 0
   Uploading droplet, build artifacts cache...
   Uploading droplet...
   Uploading build artifacts cache...
   Uploaded build artifacts cache (9.8M)
   Uploaded droplet (10M)
   Uploading complete
   Cell e18fb5f1-d6fb-4e1d-b9f8-fcd13fa4b4df stopping instance 0cb5c538-83bc-4808-ad10-e5974a3a4eb5
   Cell e18fb5f1-d6fb-4e1d-b9f8-fcd13fa4b4df destroying container for instance 0cb5c538-83bc-4808-ad10-e5974a3a4eb5

Waiting for app to start...

name:              halloworld
requested state:   started
routes:            halloworld.eu-de.mybluemix.net
last uploaded:     Fri 18 Sep 13:30:43 CEST 2020
stack:             cflinuxfs3
buildpacks:        https://github.com/oetiker/sourcey-buildpack

type:            web
instances:       1/1
memory usage:    64M
start command:   PATH=$HOME/sourcey/bin:$PATH PERL5LIB='/home/vcap/sourcey/lib/perl5' ./SourceyStart.sh
     state     since                  cpu    memory     disk      details
#0   running   2020-09-18T11:30:54Z   0.0%   0 of 64M   0 of 1G

Right at the top of the application builder lines you find the URL that runs your web application. In our case it is https://halloworld.eu-de.mybluemix.net and visiting the location will give you a warm welcome.

In the next post we will extend this application to do something more practical.

Drop me a note below with your thoughts and questions about building cloud applications and I’ll do my best to answer them in future posts.