From b76cb2f80c4a701a3575aff4c1d8b4b07639907c Mon Sep 17 00:00:00 2001
From: "Hahn Axel (hahn)" <axel.hahn@iml.unibe.ch>
Date: Fri, 26 May 2017 11:31:09 +0200
Subject: [PATCH] task 1462 - add foreman integration: first commit of foreman
 API class - GET to hostgroups works

---
 .../classes/deploy-foreman.class.php          | 188 ++++++++++++++++++
 1 file changed, 188 insertions(+)
 create mode 100644 public_html/deployment/classes/deploy-foreman.class.php

diff --git a/public_html/deployment/classes/deploy-foreman.class.php b/public_html/deployment/classes/deploy-foreman.class.php
new file mode 100644
index 00000000..172d6eaa
--- /dev/null
+++ b/public_html/deployment/classes/deploy-foreman.class.php
@@ -0,0 +1,188 @@
+<?php
+
+/**
+ * deployForeman
+ * 
+ * foreman access to API
+ * 
+ *
+ * @author hahn
+ */
+class deployForeman {
+
+    protected $_aCfg=array();
+
+    protected $_sApi=false;
+    protected $_sApiUser=false;
+    protected $_sApiPassword=false;
+    
+    
+    public function __construct($aCfg) {
+        if(!is_array($aCfg) || !count($aCfg) || !array_key_exists('api', $aCfg)){
+            die("ERROR: class ".__CLASS__." must be initialized with an array containing api config for foreman.");
+            return false;
+        }
+        $this->_aCfg=$aCfg;
+        
+        $this->_sApi=$aCfg['api'];
+        $this->_sApiUser=array_key_exists('user', $aCfg) ? $aCfg['user'] : false;
+        $this->_sApiPassword=array_key_exists('password', $aCfg) ? $aCfg['password'] : false;
+        return true;
+    }
+    // ----------------------------------------------------------------------
+    // private functions
+    // ----------------------------------------------------------------------
+    /**
+     * add a log messsage
+     * @global object $oLog
+     * @param  string $sMessage  messeage text
+     * @param  string $sLevel    warnlevel of the given message
+     * @return bool
+     */
+    private function log($sMessage, $sLevel = "info") {
+        global $oCLog;
+        return $oCLog->add(basename(__FILE__) . " class " . __CLASS__ . " - " . $sMessage, $sLevel);
+    }
+    
+    /**
+     * make an http get request and return the response body
+     * 
+     * @param string  $url        url for Foreman API
+     * @param string  $method     method; one of GET|POST|PUT|DELETE
+     * @param array   $aPostData  Post data (arrray [key]=>[value]))
+     * @param integer $iTimeout
+     * @return string
+     */
+    
+    private function _httpCall($url, $method='GET', $aPostData = false, $iTimeout = 5) {
+        $this->log(__FUNCTION__ . " start");
+        if (!function_exists("curl_init")) {
+            die("ERROR: PHP CURL module is not installed.");
+        }
+        $sFullUrl=$this->_sApi.$url;
+        $this->log(__FUNCTION__ . " ".$method." $sFullUrl");
+        $ch = curl_init($sFullUrl);
+
+        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
+        if ($method==='POST'){
+            curl_setopt($ch, CURLOPT_POSTFIELDS, $aPostData);
+        }
+        curl_setopt($ch, CURLOPT_HEADER, 1);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
+        curl_setopt($ch, CURLOPT_TIMEOUT, $iTimeout);
+        curl_setopt($ch, CURLOPT_USERAGENT, 'IML Deployment GUI :: ' . __CLASS__);
+        if ($this->_sApiUser){
+            curl_setopt($ch, CURLOPT_USERPWD, $this->_sApiUser.":".$this->_sApiPassword);
+        }
+        $res = curl_exec($ch);
+        $aReturn=array('info'=>curl_getinfo($ch), 'error'=>curl_error($ch));
+        curl_close($ch);
+        $this->log(__FUNCTION__ . " done url: $url");
+
+        $sHeader=substr($res, 0, $aReturn['info']['header_size']);
+        $aReturn['header']=explode("\n", $sHeader);
+        $aReturn['body']=str_replace($sHeader, "", $res);
+                
+        return $aReturn;
+    }
+
+    // ----------------------------------------------------------------------
+    // public functions :: low level
+    // ----------------------------------------------------------------------
+    
+    /**
+     * make an http(s) request to foreman and scan result for http code and
+     * content in response json; method returns an array with subkeys
+     * - info: curl info array
+     * - error: curl error message
+     * - header: http response headers
+     * - body: http response body
+     * - _json: parsed json data from response body
+     * - _OK: flag if result is OK and complete
+     * - _status: info
+     * 
+     * @param string  $url        url for Foreman API
+     * @param string  $method     method; one of GET|POST|PUT|DELETE
+     * @param array   $aPostData  Post data (arrray [key]=>[value]))
+     * @return array
+     */
+    public function makeRequest($url, $method='GET', $aPostData = false) {
+        $sStatus='unknown';
+        $bOk=false;
+
+        // check name of method
+        if(array_search($method, array('GET', 'POST', 'PUT', 'DELETE'))===false){
+            die("ERROR in ".__CLASS__."::".__FUNCTION__.": method $method is invalid or not supported.");
+        }
+        
+        // prevent missing data because of paging
+        if ($method==='GET'){
+            $url.='?per_page=1000';
+        }
+        if ($method==='POST' && (!$aPostData || !count($aPostData))){
+            die("ERROR in ".__CLASS__."::".__FUNCTION__.": missing data to make a POST request");
+        }
+        
+        $aReturn=$this->_httpCall($url, $method);
+        
+        // --- check status
+        $iStatuscode=$aReturn['info']['http_code'];
+        if ($iStatuscode===0){
+            $sStatus='wrong host';
+        }
+        if ($iStatuscode>=200 && $iStatuscode<400){
+            $sStatus='OK';
+            $bOk=true;
+        }
+        if ($iStatuscode>=400 && $iStatuscode<500){
+            $sStatus='error';
+        }
+        if ($iStatuscode===404){
+            $sStatus='wrong url';
+        }
+        
+        // --- check result json
+        if($bOk){
+            $aJson=json_decode($aReturn['body'], 1);
+            if (is_array($aJson)){
+                if ($aJson['total'] > $aJson['per_page']){
+                    $bOk=false;
+                    $sStatus='Http OK, but incomplete results (paging)';
+                }
+                $aReturn['_json']=$aJson;
+            } else {
+                $bOk=false;
+                $sStatus='Http OK, but wrong response';
+            }
+        }
+        $aReturn['_OK']=$bOk;
+        $aReturn['_status']=$sStatus;
+
+        return $aReturn;
+    }
+
+    // ----------------------------------------------------------------------
+    // public functions
+    // ----------------------------------------------------------------------
+    
+    /**
+     * get list of host groups as an array with [id] => [name of title]
+     * @return boolean
+     */
+    public function getHostgroups() {
+        $aReturn=array();
+        $aData=$this->makeRequest('hostgroups/', 'GET');
+        
+        if (!$aData['_OK']){
+            return false;
+        }
+        if ($aData['_json']){
+            foreach ($aData['_json']['results'] as $aItem){
+                $aReturn[$aItem['id']]=$aItem['title'];
+            }
+        }
+        return $aReturn; 
+    }
+    
+}
-- 
GitLab