Skip to content
Snippets Groups Projects
Commit eff250b9 authored by Hahn Axel (hahn)'s avatar Hahn Axel (hahn)
Browse files

task 1462 - add foreman integration: first commit of foreman API class - GET to hostgroups works

parent b76cb2f8
No related branches found
No related tags found
No related merge requests found
<?php <?php
/** /**
* deployForeman * deployForeman
* *
* foreman access to API * foreman access to API
* *
* @example
* $oForeman=new deployForeman($this->_aConfig['foreman']);
* $aForemanHostgroups=$oForeman->getHostgroups();
* or
* $aForemanHostgroups=$oForeman->getHostgroups(array('id'=>11));
* *
* @author hahn * @author hahn
*/ */
...@@ -12,9 +16,27 @@ class deployForeman { ...@@ -12,9 +16,27 @@ class deployForeman {
protected $_aCfg=array(); protected $_aCfg=array();
protected $_sApi=false; /**
protected $_sApiUser=false; * alloews methods and prefixes for methods
protected $_sApiPassword=false; * @var array
*/
protected $_aAllowedMethods=array(
'GET'=>'get',
'POST'=>'create',
'PUT'=>'update',
'DELETE'=>'delete'
);
protected $_aApiUrls=array(
'hostgroups'=>'hostgroups/',
);
protected $_aRequest=array();
// ----------------------------------------------------------------------
// constructor
// ----------------------------------------------------------------------
public function __construct($aCfg) { public function __construct($aCfg) {
...@@ -24,9 +46,6 @@ class deployForeman { ...@@ -24,9 +46,6 @@ class deployForeman {
} }
$this->_aCfg=$aCfg; $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; return true;
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
...@@ -39,46 +58,127 @@ class deployForeman { ...@@ -39,46 +58,127 @@ class deployForeman {
* @param string $sLevel warnlevel of the given message * @param string $sLevel warnlevel of the given message
* @return bool * @return bool
*/ */
private function log($sMessage, $sLevel = "info") { protected function log($sMessage, $sLevel = "info") {
global $oCLog; global $oCLog;
return $oCLog->add(basename(__FILE__) . " class " . __CLASS__ . " - " . $sMessage, $sLevel); return $oCLog->add(basename(__FILE__) . " class " . __CLASS__ . " - " . $sMessage, $sLevel);
} }
/** /**
* make an http get request and return the response body * helper function ... get the METHOD by scanning function and search for
* it in _aAllowedMethods
* i.e. "getHostname" --> returns GET
*
* @return type
*/
protected function _getMethod(){
$sReturn='';
foreach ($this->_aAllowedMethods as $sMethod=>$sPrefix){
if (strpos($this->_aRequest['function'], $sPrefix)===0){
$sReturn=$sMethod;
continue;
}
}
if (!$sReturn){
die("ERROR in ".__CLASS__."::".__FUNCTION__.": function ".$this->_aRequest['function']." does not map to a valid method.");
}
return $sReturn;
}
/**
* generate an url for foreman API request based on option keys
* - function
* - id
* - more
*
* TODO: multiple items with ids
* POST /api/compute_profiles/:compute_profile_id/compute_resources/:compute_resource_id/compute_attributes
*
* @param type $aOptions
* @return string
*/
protected function _generateUrl(){
$sFunction=strtolower($this->_aRequest['function']);
foreach (array_values($this->_aAllowedMethods) as $sMethod){
$sFunction=preg_replace('/^'.$sMethod.'/i', '', $sFunction);
}
if (!array_key_exists($sFunction, $this->_aApiUrls)){
die("ERROR in ".__CLASS__."::".__FUNCTION__.": no API method found for function [".$aOptions['function']."].");
}
$sReturn=$this->_aApiUrls[$sFunction];
if (array_key_exists('id', $this->_aRequest)){
$sReturn.=(int)$aOptions['id'].'/';
}
if (array_key_exists('more', $this->_aRequest)){
$sReturn.=$aOptions['more'].'/';
}
return $sReturn;
}
/**
* add parameter for search and paging in an foreman API URL
* *
* @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 * @return string
*/ */
protected function _generateParams(){
$sUrl=$this->_aRequest['url'];
$sReturn=$sUrl.(strpos($sUrl, '?') ? '' : '?');
private function _httpCall($url, $method='GET', $aPostData = false, $iTimeout = 5) { // TODO: "sort by" and "sort order" ... need to be added here ... somehow
$this->log(__FUNCTION__ . " start"); foreach(array('page', 'per_page', 'search') as $sParam){
if (array_key_exists($sParam, $this->_aRequest)){
$sReturn.='&'.$sParam.'='.urlencode($this->_aRequest[$sParam]);
}
}
return $sReturn;
}
/**
* make an http get request and return the response body
* it is called by _makeRequest
* $aRequest contains subkeys
* - url
* - method; one of GET|POST|PUT|DELETE
* - postdata; for POST only
*
* @param array $aRequest arrayurl for Foreman API
* @return string
*/
protected function _httpCall($aRequest=false, $iTimeout = 5) {
if ($aRequest){
$this->_aRequest=$aRequest;
}
// $url, $method='GET', $aPostData = false, $iTimeout = 5
$this->log(__FUNCTION__ . " start <pre>".print_r($this->_aRequest,1)."</pre>");
if (!function_exists("curl_init")) { if (!function_exists("curl_init")) {
die("ERROR: PHP CURL module is not installed."); die("ERROR: PHP CURL module is not installed.");
} }
$sFullUrl=$this->_sApi.$url;
$this->log(__FUNCTION__ . " ".$method." $sFullUrl"); $sApiUrl=$this->_aCfg['api'];
$sApiUser=array_key_exists('user', $this->_aCfg) ? $this->_aCfg['user'] : false;
$sApiPassword=array_key_exists('password', $this->_aCfg) ? $this->_aCfg['password'] : false;
$sFullUrl=$sApiUrl.$this->_aRequest['url'];
$this->log(__FUNCTION__ . " ".$this->_aRequest['method']." $sFullUrl");
$ch = curl_init($sFullUrl); $ch = curl_init($sFullUrl);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->_aRequest['method']);
if ($method==='POST'){ if ($this->_aRequest['method']==='POST'){
curl_setopt($ch, CURLOPT_POSTFIELDS, $aPostData); curl_setopt($ch, CURLOPT_POSTFIELDS, $this->_aRequest['postdata']);
} }
curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, $iTimeout); curl_setopt($ch, CURLOPT_TIMEOUT, $iTimeout);
curl_setopt($ch, CURLOPT_USERAGENT, 'IML Deployment GUI :: ' . __CLASS__); curl_setopt($ch, CURLOPT_USERAGENT, 'IML Deployment GUI :: ' . __CLASS__);
if ($this->_sApiUser){ if ($sApiUser){
curl_setopt($ch, CURLOPT_USERPWD, $this->_sApiUser.":".$this->_sApiPassword); curl_setopt($ch, CURLOPT_USERPWD, $sApiUser.":".$sApiPassword);
} }
$res = curl_exec($ch); $res = curl_exec($ch);
$aReturn=array('info'=>curl_getinfo($ch), 'error'=>curl_error($ch)); $aReturn=array('info'=>curl_getinfo($ch), 'error'=>curl_error($ch));
curl_close($ch); curl_close($ch);
$this->log(__FUNCTION__ . " done url: $url"); $this->log(__FUNCTION__ . " status ".$aReturn['info']['http_code'].' '.$this->_aRequest['method']." $sFullUrl");
$sHeader=substr($res, 0, $aReturn['info']['header_size']); $sHeader=substr($res, 0, $aReturn['info']['header_size']);
$aReturn['header']=explode("\n", $sHeader); $aReturn['header']=explode("\n", $sHeader);
...@@ -102,31 +202,41 @@ class deployForeman { ...@@ -102,31 +202,41 @@ class deployForeman {
* - _OK: flag if result is OK and complete * - _OK: flag if result is OK and complete
* - _status: info * - _status: info
* *
* @param string $url url for Foreman API * * $aRequest contains subkeys
* @param string $method method; one of GET|POST|PUT|DELETE * - function --> to extract method and generate url
* @param array $aPostData Post data (arrray [key]=>[value])) * - method; one of GET|POST|PUT|DELETE
* - postdata; for POST only
* @param array $aRequest arrayurl for Foreman API
* @return array * @return array
*/ */
public function makeRequest($url, $method='GET', $aPostData = false) { public function makeRequest($aRequest=false) {
if ($aRequest){
$this->_aRequest=$aRequest;
}
$sStatus='unknown'; $sStatus='unknown';
$bOk=false; $bOk=false;
// check name of method $this->_aRequest['method']=$this->_getMethod();
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 // prevent missing data because of paging
if ($method==='GET'){ if ($this->_aRequest['method']==='GET' && !array_key_exists('per_page', $this->_aRequest)){
$url.='?per_page=1000'; $this->_aRequest['per_page']=1000;
} }
if ($method==='POST' && (!$aPostData || !count($aPostData))){ // check postdata
if ($this->_aRequest['method']==='POST' && (!array_key_exists('postdata',$this->_aRequest) || !count($this->_aRequest['postdata']))){
die("ERROR in ".__CLASS__."::".__FUNCTION__.": missing data to make a POST request"); die("ERROR in ".__CLASS__."::".__FUNCTION__.": missing data to make a POST request");
} }
$aReturn=$this->_httpCall($url, $method); // add url parameters (search, paging)
$this->_aRequest['url']=$this->_generateUrl();
$this->_aRequest['url']=$this->_generateParams();
// --- check status // ----- request
$aReturn=$this->_httpCall();
// ----- check result
// check status
$iStatuscode=$aReturn['info']['http_code']; $iStatuscode=$aReturn['info']['http_code'];
if ($iStatuscode===0){ if ($iStatuscode===0){
$sStatus='wrong host'; $sStatus='wrong host';
...@@ -142,11 +252,11 @@ class deployForeman { ...@@ -142,11 +252,11 @@ class deployForeman {
$sStatus='wrong url'; $sStatus='wrong url';
} }
// --- check result json // check result json
if($bOk){ if($bOk){
$aJson=json_decode($aReturn['body'], 1); $aJson=json_decode($aReturn['body'], 1);
if (is_array($aJson)){ if (is_array($aJson)){
if ($aJson['total'] > $aJson['per_page']){ if (array_key_exists('total', $aJson) && $aJson['total'] > $aJson['per_page']){
$bOk=false; $bOk=false;
$sStatus='Http OK, but incomplete results (paging)'; $sStatus='Http OK, but incomplete results (paging)';
} }
...@@ -162,22 +272,40 @@ class deployForeman { ...@@ -162,22 +272,40 @@ class deployForeman {
return $aReturn; return $aReturn;
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// public functions // public foreman functions
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** /**
* get list of host groups as an array with [id] => [name of title] * get list of host groups as an array with [id] => [name of title]
* $aOptions ... can contain optional subkeys
* - id - id of hostgroup
* - more - url behind "id"
* - search
* - page
* - per_page
*
* @param array $aOptions
* @return boolean * @return boolean
*/ */
public function getHostgroups() { public function getHostgroups($aOptions=array()) {
$aReturn=array(); $aReturn=array();
$aData=$this->makeRequest('hostgroups/', 'GET');
$this->_aRequest=$aOptions;
$this->_aRequest['function']=__FUNCTION__;
$aData=$this->makeRequest();
if (!$aData['_OK']){ if (!$aData['_OK']){
return false; return false;
} }
if ($aData['_json']){
// TODO: call a general method to create result array ... baased on
// $aOptions['result'] ...
if (array_key_exists('id', $aOptions)){
$aReturn[$aData['_json']['id']]=$aData['_json']['title'];
} else if (array_key_exists('_json', $aData) && count($aData['_json'])){
foreach ($aData['_json']['results'] as $aItem){ foreach ($aData['_json']['results'] as $aItem){
$aReturn[$aItem['id']]=$aItem['title']; $aReturn[$aItem['id']]=$aItem['title'];
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment