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