Skip navigation

Jive Developers

1 Post authored by: craig.reeves

Screen Shot 2014-07-22 at 09.51.20.png

I recently decided to try my hand at building a Jive App with some simple integration to one of our infrastructure provisioning tools called Foreman and I found that after following the Jive Developer training (which is an excellent way to get started, by the way) I still wasn't sure how to hook my app up to a third party API and use basic authentication.

 

Foreman itself is a fantastic open source tool which allows you to orchestrate the creation and configuration (via puppet or chef) of your VM's and physical infrastructure. In my organisation we use it to enable us to rapidly deploy development environments (host groups in foreman lingo, I use environments as a classification like production, pre-prod, dev etc).

 

The problem I am trying to solve, is to have a way for developers and managers to quickly see a list of environments that exist, the virtual machines which exist inside of those host groups and any IP addresses allocated to the server from within the Jive interface. I know that some of you might be uncomfortable with merging infrastructure tools with a social platform - but it's an experiment, it could work well or it could be awful - and there is only one way to find out!

 

Prerequisites

 

Before you begin this tutorial you will need to have the jive node sdk installed, have access to the jive developer sandbox or an on-prem development instance and have access to a foreman instance. My intention is that this could be used to access any tool with a REST API inside your organisation so feel free to swap and change as appropriate.

It would also help if you are familiar with deploying Jive Node SDK Add-ons - Getting Started > Deploying a Jive Node SDK Project as an Add-On

 

Where to begin?

 

Ok, so we know that our problem is to display a list of host groups and the hosts that they contain from within a Jive App so that our developers and managers can easily access the information from a unified interface that they are familiar with. Jive provides a great API in the form of the Jive Connects which we will leverage to send connections to the third party API.

 

The third party API I need to work with is documented here: The Foreman :: API and the main functions I am interested in using are:

  • /api/hostgroups - inside foreman all of my hosts belong to their own hostgroup, so a single Jive instance belongs to a hostgroup like jive-dev1, jive-dev2 etc
  • /api/hosts - gets a list of hosts, or an individual host if an ID is specified.

 

So lets get started.

 

First, we need to use the Jive SDK to deploy a skeleton app that we can use as the base for what we are trying to do.

mkdir TutorialApp
cd TutorialApp
jive-sdk create app --name="foremanapp"
npm update
nano jiveclientconfiguration.json # Edit this file to change from localhost to my node server IP
node app.js





 

Once you have done this, you will need to upload the extension.zip file to your server  have a basic app, configured and deployed. Make sure that you can see the App in your apps drop down menu to ensure it loaded correctly.

 

Now for the fun part. Lets modify our App to change the name and also to add support for the Jive Connects API. At this point I should tell you that there is already some great documentation for using Jive Connects with Authentication at Jive Apps Developer Community: Jive Connects API - Client Application Configuration and API Usage, but don't know if it was just a lack of coffee when I tried this but I struggled to find how to use basic auth in the documentation, hence this blog post.

 

The fun stuff....

 

Update app.xml

First, lets update apps/myforemanapp/public/app.xml and change some of the metadata and add support for the Jive Connects API. I have commented the bits I modified or added. I also removed anything that wasn't used in the file that comes out of the box.

<?xml version="1.0" encoding="UTF-8"?>
<Module specificationVersion="1">
 <!-- Updated with my details -->
  <ModulePrefs title="Foreman"
               description="Basic foreman integration"
               author="Craig Reeves"
               author_affiliation="Orange Business Services"
               author_email="craig.reeves@orange.com">


    <!-- Commonly used features -->
    <Require feature="dynamic-height" />
    <Require feature="jive-core-v2" />
    <Require feature="jquery-1.6" />
    <Require feature="osapi"/>
    <Require feature="settitle"/>
    <Require feature="views" />
    <Require feature="jive-core-v3" />
    <Require feature="embedded-experiences" />
  <Require feature="actions"> 
    <Param name="action-contributions"> 
      <![CDATA[
        <action id="com.jivesoftware.profile.rtc"
            path="jive/actions/profile"
            label="Example Profile Pop-Up"
            url="https://developer.jivesoftware.com" 
            icon="images/icon16.png"
            windowSpec="left=40,top=40,width=500,height=500,toolbar=1,resizable=0"/>
      ]]> 
    </Param> 
  </Require>


 <!-- Add support for the jive-connects API and specify a service tag to load. (Tag must exist in the admin console) -->
  <Require feature="jive-connects-v1">                
<Param name="alias:connector|title:connector">jive:service://foreman/api?version=2</Param>       
</Require>


    <!-- Icons: 3 sizes, 16x16, 48x48, 128x128 -->
    <Link rel="Icon"       href="images/icon16.png" />
    <Link rel="MediumIcon" href="images/icon48.png" />
    <Link rel="LargeIcon"  href="images/icon128.png" />


  </ModulePrefs>

 <!-- Removed the initial hello view and uncommented these views: -->
  <Content type="html" view="home" href="home.html" preferred_height="400" />
  <Content type="html" view="canvas" href="canvas.html" />


</Module>





 

Update canvas.html

Next, open up apps/myforemanapp/public/canvas.html and change the content to this:

<link rel="stylesheet" href="stylesheets/main.css" type="text/css" media="screen" />
<script type="text/javascript" charset="utf-8" src="javascripts/main.js"></script>

<h2>Canvas View: Foreman</h2>

<script type="text/javascript" charset="utf-8">
loadHostGroups();
</script>
<div id="table-body"> </div>




 

The loadHostGroups() method will call the function we are about to put inside main.js to trigger the loading of the content from the remote API.

 

Update main.js

Now open up apps/myforemanapp/public/javascript/main.js and add the following code to the bottom. The code here was taken mostly from the Jive Connects API documentation:

function loadHostGroups() {
    var grouptarget = "";
    osapi.jive.connects.get({
        alias : 'connector', // This is the ALIAS for the service tag that we set up in the admin console
        headers : { 'Accept' : [ 'application/json' ] },
        href : '/hostgroups' // This is the url to the API method you want to call. We want a list of environments from /api/environments, so we use /environments here.
    }).execute(function(response) {
         if (response.error) {
// This part of the code detects if the API is restricted  and if it is, it will prompt the user to enter their credentials.
            if (response.error.code == 401) {
                // Request Jive to configure (or reconfigure) credentials for this connection
                osapi.jive.connects.reconfigure("connector", response, function(feedback) { // We need to make sure that the first parameter matches the alias value
                    loadHostGroups(); // Resubmit the failed request
            });
            }
            else {
                // Deal with an error scenario ...
            }
        }
        else {
            // response.content is an array of information for each hostgroup item
            var html = "";
            $.each(response.content.results, function(index, groupdata) {
                grouptarget = "hg_"+groupdata.id;
                html += "<h2>"+groupdata.name+"</h2>"; // Generate appropriate table row HTML for each host group
                html += "<div class=\""+grouptarget+"\"></div> ";
            
                loadHosts(groupdata.id,grouptarget);
            });
            $("#table-body").html(html);
            gadgets.window.adjustHeight();
        }
    })
}
function loadHosts(hostgroupid,grouptarget) {

    osapi.jive.connects.get({
        alias : 'connector',
        headers : { 'Accept' : [ 'application/json' ] },
        params : { 'search' : [ 'hostgroup_id='+hostgroupid ] },
        href : '/hosts'
    }).execute(function(response) {
         if (response.error) {
            if (response.error.code == 401) {
                // Request Jive to configure (or reconfigure) credentials for this connection
                osapi.jive.connects.reconfigure("connector", response, function(feedback) {
                    loadHosts(hostgroupid,groupclass); // Resubmit the failed request
                });
            }
            else {
                // Deal with an error scenario ...
            }
        }
        else {
            // response.content is an array of information for each quote
            var html = "";
            $.each(response.content.results, function(index, hostdata) {
                html += "<li>"+hostdata.name+" : "+hostdata.ip+"</li>" // Generate appropriate table row HTML for each host
            });
            $("."+grouptarget).html(html);
       
            gadgets.window.adjustHeight();
        }
    })
}




 

Setting up a service tag

The code we have created looks good, but even if you upload it, you still won't get any joy from it. Thats because we now need to create the service tag definition - which tells your jive instance exactly how it needs to connect to your third party API.

 

In your Jive Admin panel (/admin/apps-services.jspa) browse to the Add-On tab, then "App Services" from the menu on the left. Click 'Add Service' and then set up your service so that it matches my screenshots below, changing the service url to match the API you want to connect to. Note that the jive service tag field is the most important - this MUST be identical else your app won't work!

Screen Shot 2014-07-22 at 11.03.09.pngScreen Shot 2014-07-22 at 11.03.16.png

We are adding HTTP Header definitions version=2 because we need to tell Foreman that we want to use version2 of their API. After you have created your service tag you should be ready to go. Because we have modified the app.xml, I find it good practice to uninstall the app, re-run node app.js to generate a new extension.zip and then to redeploy the extension.zip file to your instance.

 

Once your app has been re-deployed visit your app, go ahead and launch it through the apps menu:

Screen Shot 2014-07-22 at 12.02.03.png

You should then see a screen asking for your Foreman credentials:

Screen Shot 2014-07-22 at 12.05.04.png

Enter your credentials provided by Foreman, and then click submit. This will be the last time that you are asked for your credentials unless you change the authentication type for the service tag, or your credentials change on the third party system. Once you have done that, you should see a screen like the (ugly) one below containing a list of your host groups, hosts and their IP addresses. With a bit of polish this will be ready for our users.

Screen Shot 2014-07-22 at 12.02.17.png

 

Thanks for reading. I hope this helps some novices like me to quickly put together a remote authenticated API call.

Filter Blog