Technical Articles
Outgoing API calls from SAP Landscape Management (LaMa) with Automation Studio
Update Dec. 2022: SAP Landscape Management (LaMa) SP25 added REST API (outgoing) provider that can also be used for the examples covered below. Refer to this blog for details.
Introduction
In a previous blog, I covered the REST API interface of SAP Landscape Management (LaMa). This interface allows actions to be performed by LaMa with API calls coming in from other applications or your own scripts. Refer to Figure 1.
Figure 1: Incoming REST API Calls
In this blog I’m going to cover the reverse scenario where API or other execution calls are made from LaMa to external applications. Refer to Figure 2.
Making external calls from LaMa may be needed when creating a custom operation/process that requires triggering an action in an external application. Some examples could be kicking off a backup using a 3rd party tool, creating service requests in a ticketing system, triggering an event in an external system, launching external automation tools/scripts (e.g. ansible, chef) etc.
The supported provider implementation definitions in LaMa are (table updated to add provider type REST after the SP25 release):
Type | Description |
SAP host agent registered scripts | A script that is registered on and executed by SAP Host Agent. |
HTTP post service | A servlet or similar that is called directly by SAP Landscape Management. |
REST (as of SP25) | REST API calls made directly from SAP Landscape Management (LaMa) |
Web service | A web service (server-side) that implements the WSDL defined by SAP Landscape Management (LaMa). |
Remote function call | An ABAP function module that is called and executed by SAP Landscape Management. |
Confirmation action | A text that appears for user confirmation. |
Covering all the use cases mentioned above is not in scope of this blog, but I will give some basic examples to demonstrate the capability. I will use GitHub API in example 1 and Ansible in example 2.
We will use Automation Studio in SAP Landscape Management to get this done.
Since we need to make a REST API call, we are going to create a custom process that leverages “Script Registered with Host Agent” to make the necessary calls. It may be possible to use the HTTP post service but we will use the scripts approach in this blog.
In this case you have to decide which managed host you will use for such external calls. You would designate this server as a LaMa proxy or trusted host allowed to make such calls to external interfaces.
Figure 2: Outgoing calls
Disclaimer
This blog is published “AS IS”. Any software coding and/or code lines / strings (“Code”) included are only examples and are not intended to be used in any productive system environment. The Code is only intended to better explain and visualize the features of the SAP Landscape Management Automation Studio. No effort has been made to make the code production quality (e.g. security, error handling, robustness, etc). If you use any of the code shown, you are doing it at your own risk.
Information in this blog could include technical inaccuracies or typographical errors. Changes may be periodically made.
Assumptions
It is assumed that your environment is already setup correctly for creating custom processes in LaMa. This blog does not go over all the configuration steps. If this is your first time using LaMa Automation Studio then I recommend that you start with something simple. Please refer to this blog for other examples. All examples below use an environment with LaMa Enterprise Edition 3.0 SP13, SuSE Linux Enterprise 12 SP2 (all hosts).
Example 1: Outgoing API calls to GitHub
In this section we will create and update Gists on GitHub. A Gist is a mechanism to share snippets or excerpts of data with others. It can be a string of code, a script or some other small piece of data.
We will use access tokens as authentication mechanism. We will make the API calls from a script using the “curl” command. First we will test the commands individually and then put in a script to be called by LaMa.
Step 1 is to create the access token on GitHub. Creation of access tokens is via the web interface that GitHub offers. You access it by clicking the settings icon.
Give the token a meaningful name and define the scope. You can also revoke this token at a later time. After you generate the token, copy and paste it somewhere as this will be the only time you will see it.
Let’s now make sure the token works.
curl -u "<github_username>:<token>" https://api.github.com/user
You should get an output similar to this:
{
“login”: “xyz”,
“id”: 63888981,
“node_id”: “xyz”,
“avatar_url”: “https://avatars2.githubusercontent.com/u/63888981?v=4”,
“gravatar_id”: “”,
“url”: “https://api.github.com/users/xyz”,
“html_url”: “https://github.com/xyz”,
“followers_url”: “https://api.github.com/users/xyz/followers”,
“following_url”: “https://api.github.com/users/xyz/following{/other_user}”,
“gists_url”: “https://api.github.com/users/xyz/gists{/gist_id}”,
“starred_url”: “https://api.github.com/users/xyz/starred{/owner}{/repo}”,
“subscriptions_url”: “https://api.github.com/users/xyz/subscriptions”,
“organizations_url”: “https://api.github.com/users/xyz/orgs”,
“repos_url”: “https://api.github.com/users/xyz/repos”,
“events_url”: “https://api.github.com/users/xyz/events{/privacy}”,
“received_events_url”: “https://api.github.com/users/xyz/received_events”,
Now lets create a new Gist called “LaMa_gist_1.txt” which will have initial text of “LaMa Demo of Gist Create” and description of “Created via API”
curl -u "<username>:<token>" -X POST --data '{"description":"Created via API","public":"true","files":{"LaMa_gist_1.txt":{"content":"LaMa Demo of Gist Create"}}' https://api.github.com/gists
In the output you will get a lot of text and in the beginning is the full URL of the newly created Gist file as well as the ID. See bold text below from the sample output. Note this ID down as we will need it to perform an update.
“{
“url”: “https://api.github.com/gists/db02193dc5335f8fbb773210b260166e”,
“forks_url”: “https://api.github.com/gists/db02193dc5335f8fbb773210b260166e/forks”,
“commits_url”: “https://api.github.com/gists/db02193dc5335f8fbb773210b260166e/commits”,
“id”: “db02193dc5335f8fbb773210b260166e“,
“node_id”: “MDQ6R2lzdGRiMDIxOTNkYzUzMzVmOGZiYjc3MzIxMGIyNjAxNjZl”,
“git_pull_url”: “https://gist.github.com/db02193dc5335f8fbb773210b260166e.git”,
“git_push_url”: “https://gist.github.com/db02193dc5335f8fbb773210b260166e.git”,
“html_url”: “https://gist.github.com/db02193dc5335f8fbb773210b260166e”,
“files”: {
Now login to the web portal of GitHub and view your Gists. You should see this new Gist.
Now let’s update the above Gist with additional text “LaMa Demo Gist Updated via API”.
curl -u "<username>:<token>" -X PATCH --data '{"description":"Updated via API","public":"true","files":{"LaMa_gist_1.txt":{"content":"LaMa Demo Gist Updated via API"}}' https://api.github.com/gists/db02193dc5335f8fbb773210b260166e
On GitHub web you should see the update:
Now that we know the command line works, let’s create a custom operation that does a Gist create and an update.
Create the configuration files in directory /usr/sap/hostctrl/exe/operations.d on the managed host that is going to run the commands.
Create file gist_create.conf
Username: root
Name: gist_create
Description: Create gist on GitHub
Command: /usr/sap/scripts/gist_create.sh $[PARAM-GITUSER:#required] $[PARAM-TOKEN:#required] $[PARAM-FILENAME:#required] $[PARAM-TEXT:#required]
ResultConverter: flat
Platform: Unix
Set permissions:
chown root:root <.conf file>
chmod 755 <.conf file>
Create the bash script in a directory of your choice (in my case it was in /usr/sap/scripts):
Script name: “gist_create.sh”.
#!/bin/bash
GISTUSER=$1
TOKEN=$2
FILENAME=$3
TEXT=$4
COMMAND="curl -u \"$GISTUSER:$TOKEN\" -X POST --data '{\"description\":\"Created via API\",\"public\":\"true\",\"files\":{\"$FILENAME\":{\"content\":\"$TEXT\"}}' https://api.github.com/gists"
eval $COMMAND
Set permissions
chown root:root gist_create.sh
chmod 755 gist_create.sh
Create file gist_update.conf
Username: root
Name: gist_update
Description: Update gist on GitHub
Command: /usr/sap/scripts/gist_update.sh $[PARAM-GITUSER:#required] $[PARAM-TOKEN:#required] $[PARAM-FILENAME:#required] $[PARAM-TEXT:#required] $[PARAM-GISTID:#required]
ResultConverter: flat
Platform: Unix
Set permissions:
chown root:root <.conf file>
chmod 755 <.conf file>
Create the bash script in a directory of your choice (in my case it was in /usr/sap/scripts):
Script name: “gist_update.sh”
#!/bin/bash
GISTUSER=$1
TOKEN=$2
FILENAME=$3
TEXT=$4
GISTID=$5
COMMAND="curl -u \"$GISTUSER:$TOKEN\" -X POST --data '{\"description\":\"Updated
via API\",\"public\":\"true\",\"files\":{\"$FILENAME\":{\"content\":\"$TEXT\"}}
' https://api.github.com/gists/$GISTID"
eval $COMMAND
Set permissions
chown root:root gist_update.sh
chmod 755 gist_update.sh
Provider Definition for Gist Create
Login to LaMa and create a new provider definition as “Script Registered with Host Agent”
Add host (designated as your proxy) from the drop down and click “Retrieve Scripts”. The host agent fills the drop list.
Select the “Host Name” and click “Retrieve Scripts”. Choose the script (the configuration file) “gist_create” and give Name of “gist_create”. Check mark “Execute on Central Host Only” and fill in the trusted host information. Click on Create Provider.
Click on the newly created provider definition.
Go to Parameters tab and click on “Add Parameter”. Add the below 4 parameters of Type string and make Mandatory yes. Also mark the parameter TOKEN as secure.
Custom Operation for Gist Create
Go to Automation Studio -> Custom Operation -> Create
Now test the newly created custom operation. Go to Operations -> Hosts
Run the custom operation in the Operations Group API (against any host). Execution will only occur on the central host defined earlier when creating the provider definition.
Fill in the parameters
Click Execute
Verify that the gist was created on the GitHub web site.
If successful then get the ID of the gist from the LaMa Monitor. Go to Monitoring -> Activities and for the above operation look for the ID.
Note this down so we can do an update to this after creating the custom operation for an update.
Follow the same steps above to:
- Create the provider definition gist_update from the registered script gist_update (using gist_update.conf and gist_update.sh files)
- Create the new custom operation “API_GIST_UPDATE” from the new provider definition
- There is 1 extra parameter – GISTID (to provide the ID of the gist we are updating)
Now test the update.
After execution you should now see the Gist updated on the GitHub site with the new text.
Example 2: Outgoing calls to Ansible
In this example we assume that Ansible is already installed and configured on the trusted system and is able to perform automation tasks against other hosts. In my test the username “ansible” has been created on the trusted host as well as the hosts on which we want to perform automation tasks. Username “ansible” is able to ssh from trusted host to the other hosts without being prompted for password (i.e. using certificates).
Using Example 1 as a reference (which has a bit more detail), perform the following steps.
- Check your ansible inventory in /etc/ansible/hosts. The hosts listed here are the ones that will be updated by ansible with the ‘all’ option we are using in this test
- Create the file ansible_test.conf in /usr/sap/hostctrl/exe/operations.d
Name: ansible_test
Username: ansible
Description: Run ansible commands
Command: /usr/sap/scripts/ansible_test.sh
ResultConverter: flat
Platform: Unix
- Create the file /usr/sap/scripts/ansible_test.sh
#!/bin/sh
. /opt/ansible/ansible/hacking/env-setup -q
/opt/ansible/ansible/bin/ansible all -m command -a 'uname -r' -o
/opt/ansible/ansible/bin/ansible all -m copy -a 'content="Managed by Ansible\n" dest=/tmp/motd'
- Change permissions on both files
chown root:root <file>
chmod 755 <file>
- Create Provider Definition
- Create Custom Operation using above provider definition
- Perform the custom operation
- Monitor the progress in Monitoring -> Activities
- When successfully completed you should see that the file /tmp/motd has been updated on all the hosts that are setup for automation with ansible.
You have now learnt to make simple outgoing API calls as well as triggering Ansible from LaMa.
For more information on Automation Studio please refer to:
This is an interesting post. Can we not send the post message directly using the HTTP POST provider type?
You are right that LaMa also supports direct communications using HTTP POST provider type. The supported provider implementation definitions are:
Using SAP host agent registered scripts to make the API calls may give the user more flexibility in controlling the logic of the process. There are also authentication limitations when using http post service.