Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
mariusobert
Developer Advocate
Developer Advocate
In this third post in my CloudFoundryFun series, I will explain the concepts of Cloud Foundry apps, services, and service bindings. To illustrate this in a fun way, we will deploy our own personal Wordpress instance and extend it with Microsoft Azure Cloud Services.

Create a Blog on SAP Cloud Platform


Cloud Foundry Apps vs. Services


But before we start with the fun part, we need to learn some Cloud Foundry concepts. You might have heard that Cloud Foundry applications consist of two types of components: apps and services.

An app is basically the written code when it has been deployed and runs. An app must not have any hard-coded dependencies to another app or to services such as a database. Those dependencies need to be modeled as a (backing) service.

A backing service, on the other hand, provides consumable functionality to apps. Those services have their own lifecycle and are loosely coupled to the apps. This allows you to scale your apps rapidly when needed. So aspects such as logging, messaging or persistency are backing services by definition.

One of the many advantages that come with this architecture, is that you can simply "plug" services into your application when need. Cloud Foundry will then inject the required credentials of the backing service in your app at runtime.

In some situations like debugging, you might want to bind a local app to the backing services. This can be achieved with service keys. Service keys are copies of the credentials that will be injected into your app at runtime.

Let's see this in action when we build our own blog on SAP Cloud Platform!

Deploy your own Wordpress Blog


For demonstration purposes, I want to show how to modify a well-known standard application like WordPress to run on Cloud Foundry. I recently found a post by Daniel Mikusa in which he explains how to deploy Wordpress to a Cloud Foundry environment. He says that the Wordpress application requires two types of storage for:

Structured Data

This type of storage is needed for structured data as users, posts, comments, and metadata. A relational database is well suited for this kind of data.


Unstructured Data

This type, on the other hand, is needed for media files. Content creators want to enrich their posts with images, files and possibly also videos. It wouldn't make sense to store these kinds of data in a traditional database. This is why WordPress stores them by default on the file system.


 

At first, I thought: Great, writing this blog post will be child's play to me since the instructions are already out there. Then I realized that Wordpress requires a MySQL database (Postgres won't work) and a network file system (NFS) volume service. Unfortunately, neither one of those services is being offered in the default SAP Cloud Foundry marketplace.

But thanks to the Open Service Broker API (OSBAPI) that's not an issue at all! This spinoff of the Cloud Foundry project allows you to connect backing services from various vendors and sources to your app running in SAP Cloud Platform.

Most hyperscalers offer a service broker (implementing the OSBAPI) to provision, connect and deprovision managed services. In other words, we can create required persistency services in other datacenters, create access keys and inject those keys in our WordPress application. All those things can be done with the exact same flow as if you were creating native services from the SAP Cloud Platform

In this post, I want to leverage Microsoft's service broker to create the needed services. You can find instructions on how to create a service broker in the SAP Help Portal. We will use an Azure Database for MySQL for the structured data and a Blob Storage service to persist unstructured data. Once the services are created, we need to make the standard WordPress application aware of them.

Disclaimer: I never administered a Wordpress blog and my PHP skills are... let's say limited. So the WordPress configuration might not follow best-practices.


Me when I'm trying to do PHP



Prerequisites



Deploy Wordpress to SAP Cloud Platform


Download the WordPress project


Download the latest version of WordPress on your local machine and unpack it in the current directory:
curl https://wordpress.org/latest.tar.gz | tar xvz

Create a MySQL database in Azure


Please make sure to install the Microsoft Azure service broker before you continue.

This command will create a new Cloud Foundry service named AzureMySqlDB. In the background, the creation of a MySQL database (service name: azure-mysql-5-7, plan: basic) will be triggered in an Azure datacenter in North Europe. This database will be assigned to my existing resource group "IObertRG". Resource groups are logical units that bundle different resources in Azure.

It's important to configure the firewall to allow traffic from the Internet. In productive scenarios, you might want to choose another configuration.
cf create-service azure-mysql-5-7  basic AzureMySqlDB -c '{
"location": "northeurope",
"resourceGroup": "IObertRG",
"firewallRules" : [{
"name": "AllowAll",
"startIPAddress": "0.0.0.0",
"endIPAddress" : "255.255.255.255"
}]
}'

By default the database only accepts incoming HTTPS traffic, we'll need to make sure we use HTTPS in WordPress later.

Create a Blob Store in Azure


A blob storage account can be created in the same way. We simply chose a different service and specify the corresponding plan. The name of the CF service is AzureBlobStore.
cf create-service azure-storage-blob-storage-account-and-container \
all-in-one AzureBlobStore -c '{
"location": "northeurope",
"resourceGroup": "IObertRG"
}'

Make sure both services have been created successfully before you continue. You can check the current state with:
cf services

Create the manifest of the application


Create a new file named manifest.yaml in the WordPress root folder. This file contains information about the runtime environment and the bound services. Make sure the file looks as follows
applications:
- name: wordpress
memory: 128M
random-route: true
path: .
buildpack: php_buildpack
services:
- AzureMySqlDB
- AzureBlobStore

Define the PHP runtime


We also need to define the PHP version and extensions we want to use.

Create a new folder called .bp-config in the project root which stores the buildpack configuration. Define the following configuration in the options.json file within the created folder:
{
"WEBDIR": "wordpress",
"PHP_VERSION": "{PHP_73_LATEST}"
}

Specify the following PHP extensions in a new file .bp-config/php/php.ini.d/wp-extensions.ini
extension=mbstring.so
extension=mysqli.so
extension=gd.so
extension=zip.so
extension=openssl.so
extension=sockets.so

Rename the sample configuration file to wp-config.php
mv wp-config-sample.php wp-config.php

Configure the connection to the MySQL Database


Replace the database configuration in wp-config.php with the following content.
 // ** Read MySQL service properties from _ENV['VCAP_SERVICES']
$services = json_decode($_ENV['VCAP_SERVICES'], true);
$service = $services['azure-mysql-5-7'][0]; // pick the first MySQL service


// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', $service['credentials']['database']);

/** MySQL database username */
define('DB_USER', $service['credentials']['username']);

/** MySQL database password */
define('DB_PASSWORD', $service['credentials']['password']);

/** MySQL hostname */
define('DB_HOST', $service['credentials']['host'].':'.$service['credentials']['port']);

/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );

/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );

define('DB_SSL', true);
define('FS_METHOD', 'direct');

Cloud Foundry will inject the credentials of the MySQL DB into the environment variable VCAP_SERVICES for us. So we only need to read them here. If you, later on, decide to switch the underlying DB, you can simply change the service binding and restart your application. 

This is how loose coupling should look!

As mentioned earlier, Azure DBs only accept HTTPS traffic by default. So we need to define the public certificate for the SSL connection. Only add the first line above the existing if statement in wp-includes/wp-db.php:
// Just add this line
mysqli_ssl_set($this->dbh, NULL, NULL, ABSPATH . 'BaltimoreCyberTrustRoot.crt.pem', NULL, NULL);

if ( WP_DEBUG ) {
mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
} else {
@mysqli_real_connect( $this->dbh, $host, $this->dbuser, $this->dbpassword, null, $port, $socket, $client_flags );
}

Download the public certification and place it in the root of your project:
curl https://www.digicert.com/CACerts/BaltimoreCyberTrustRoot.crt.pem  > BaltimoreCyberTrustRoot.crt.pem

Install the Blob Storage Plugin


By default, WordPress wants to saved unstructured data to its local file system or to a remote NFS. Luckily, there's a plugin that can handle Azure's Blob Storage as well.

Download the Azure Blob Storage plugin and unzip its content to wp-content/plugins/.

Set the default values for the Blob Storage


Replace the content of the following function in the plugin file wp-content/plugins/windows-azure-storage/windows-azure-storage-settings.php.
function windows_azure_storage_plugin_settings_section() {
?>
<p><?php echo __( 'If you do not have Microsoft Azure Storage Account, please <a href="http://go.microsoft.com/fwlink/?LinkID=129453">register </a>for Microsoft Azure Services.', 'windows-azure-storage' ); ?></p>
<?php
// ** Read MySQL service properties from _ENV['VCAP_SERVICES']
$services = json_decode($_ENV['VCAP_SERVICES'], true);
$service = $services['azure-storage-blob-storage-account-and-container'][0];

update_option( 'azure_storage_account_name', $service['credentials']['storageAccountName']);
update_option( 'azure_storage_account_primary_access_key', $service['credentials']['accessKey']);
}

This will read the credentials of the blob storage service and set them as default values in the plugin settings. This way you won't need to access them manually. In a production scenario, you want to hide those credentials from end users.

Deploy Wordpress


Deploying Cloud Foundry apps is as easy as:
cf push

Activate and configure the plugin


Once your application has been deployed, go to https://wordpress-<unique-route>-cfapps.eu10.hana.ondemand.com/wp-admin/install.php and enter your preferred language and choose the admin credentials.



In case you see a Timeout Error, just refresh the page to continue.

In the admin view, click on plugins in the left sidebar and activate the Azure plugin.

After the successful activation, you should find a settings page for the plugin. Navigate there to note that there are default values now.



Create a new Container to store the uploaded data. Next, select the Use for default upload checkbox and click save changes.

Write a sample blog


Write your first blog post about a topic of your choice by click on the +New in the upper toolbar. Make sure to add a media file which we can inspect later. Click Publish... to release the post.



Have you ever had a Bavarian Breakfast? If no, please stop reading this post and find out where you can buy Weißwurst near you.

Inspect the Persisted Data


Let's see if the data has actually been persisted in our Azure services!

As mentioned before, we can create service keys locally. These keys contain the same kind of information that will be injected into your running apps. It's important to note, that it won't be the same credentials! You can revoke the keys of one app without disrupting other apps using the same service.

Create and view service keys for the MySQL database with the following commands. The second command should print your credentials to the console.
cf create-service-key AzureMySqlDB sqlkey
cf service-key AzureMySqlDB sqlkey

Use the MySQL client of your choice (e.g. Sequel Pro) to connect to the database. Don't forget that Azure blocks insecure HTTP traffic. Therefore you need to specify the public certificate again.

Now you have access to the database and you can inspect what WordPress saved when you created the blog post. Awesome!



Lastly, we want to inspect the data saved in the blob store. Same as before, we want to create and view a service key for this service.
cf create-service-key AzureBlobStore blobkey
cf service-key AzureBlobStore blobkey

Navigate to the container you just created and follow the folder hierarchy to find the media files you uploaded. Can you find all your files in there?

You might notice that WordPress created three copies of your image (in various resolutions).

Summary


In this edition you have learned:

  • What apps, services, and service keys are

  • How to use a new service broker

  • How to provision backing services from Azure

  • How to deploy stateless applications with backing services to Cloud Foundry

  • How to modify Wordpress to consume the bound services

  • How to create service keys

  • How to use service keys in a local setup


Service brokers of the hyperscalers:

 

About this series










This was the third blog post of my monthly new series #CloudFoundryFun. The name already says all there is to it, this series won’t be about building enterprise apps on Cloud Foundry. I think there are already plenty of great posts about those aspects out there. This series rather thinks outside the box and demonstrates unconventional Cloud Foundry use-cases. And sometimes it might be pure entertainment.?.


CloudFoundryFun #4 – Fetch (football) scores periodically