Skip to content
Snippets Groups Projects
Commit 13356a34 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 eff250b9
No related branches found
No related tags found
No related merge requests found
......@@ -15,21 +15,72 @@
class deployForeman {
protected $_aCfg=array();
/**
* alloews methods and prefixes for methods
* @var array
*/
protected $_aAllowedMethods=array(
'GET'=>'get',
'POST'=>'create',
'PUT'=>'update',
'DELETE'=>'delete'
protected $_bDebug = false;
protected $_aAllowedUrls=array(
'api/'=>array(
''=>array(),
'architectures'=>array(),
'audits'=>array('methods'=>array('GET')),
'auth_source_ldaps'=>array(),
'bookmarks'=>array(),
'common_parameters'=>array(),
'compliance'=>array(),
'compute_attributes'=>array(),
'compute_profiles'=>array(),
'compute_resources'=>array(),
'config_groups'=>array(),
'config_reports'=>array(),
'config_templates'=>array(),
'dashboard'=>array('methods'=>array('GET')),
'domains'=>array(),
'environments'=>array(),
'fact_values'=>array(),
'filters'=>array(),
'hosts'=>array(),
'hostgroups'=>array(),
'job_invocations'=>array(),
'job_templates'=>array(),
'locations'=>array(),
'mail_notifications'=>array(),
'media'=>array(),
'models'=>array(),
'operatingsystems'=>array('methods'=>array('GET')),
'orchestration'=>array(),
'organizations'=>array(),
'permissions'=>array(),
'plugins'=>array(),
'provisioning_templates'=>array(),
'ptables'=>array(),
'puppetclasses'=>array(),
'realms'=>array(),
'remote_execution_features'=>array(),
'reports'=>array(),
'roles'=>array(),
'settings'=>array(),
'smart_class_parameters'=>array(),
'smart_proxies'=>array(),
'smart_variables'=>array(),
'statistics'=>array('methods'=>array('GET')),
'status'=>array('methods'=>array('GET')),
'subnets'=>array(),
'template_combinations'=>array(),
'template_kinds'=>array('methods'=>array('GET')),
'templates'=>array(),
'usergroups'=>array(),
'users'=>array(),
// ...
),
'api/v2/'=>array(
'discovered_hosts'=>array(),
'discovery_rules'=>array(),
),
'foreman_tasks/api/'=>array(
'recurring_logics'=>array(),
'tasks'=>array(),
),
);
protected $_aApiUrls=array(
'hostgroups'=>'hostgroups/',
);
protected $_aRequest=array();
......@@ -64,54 +115,47 @@ class deployForeman {
}
/**
* helper function ... get the METHOD by scanning function and search for
* it in _aAllowedMethods
* i.e. "getHostname" --> returns GET
*
* search url prefix in $this->_aAllowedUrls by given key
* @param type $sFunction
* @return type
*/
protected function _getMethod(){
protected function _guessPrefixUrl($sFunction=false){
$sReturn='';
foreach ($this->_aAllowedMethods as $sMethod=>$sPrefix){
if (strpos($this->_aRequest['function'], $sPrefix)===0){
$sReturn=$sMethod;
continue;
if (!$sFunction){
$sFunction=$this->_aRequest['request'][0][0];
}
foreach($this->_aAllowedUrls as $sPrefix=>$aUrls){
foreach(array_keys($aUrls) as $sKeyword){
if ($sFunction==$sKeyword){
$sReturn=$sPrefix;
break;
}
}
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']."].");
if(!array_key_exists('request', $this->_aRequest)){
die('ERROR: missing key [request]');
}
$sReturn=$this->_aApiUrls[$sFunction];
$sReturn=$this->_aCfg['api'];
$sPrefix=$this->_guessPrefixUrl();
$sReturn.=$sPrefix;
if (array_key_exists('id', $this->_aRequest)){
$sReturn.=(int)$aOptions['id'].'/';
foreach($this->_aRequest['request'] as $aReqItem){
if (!array_key_exists($aReqItem[0], $this->_aAllowedUrls[$sPrefix])){
echo 'WARNING: wrong item: [' . $aReqItem[0]."]<br>\n";
}
$sReturn.=$aReqItem[0] ? $aReqItem[0].'/' : '';
if(count($aReqItem)>1){
$sReturn.=(int)$aReqItem[1].'/';
}
if (array_key_exists('more', $this->_aRequest)){
$sReturn.=$aOptions['more'].'/';
}
return $sReturn;
}
......@@ -122,13 +166,15 @@ class deployForeman {
* @return string
*/
protected function _generateParams(){
$sUrl=$this->_aRequest['url'];
$sReturn=$sUrl.(strpos($sUrl, '?') ? '' : '?');
if (!array_key_exists('filter', $this->_aRequest)){
return '';
}
$sReturn='?';
// TODO: "sort by" and "sort order" ... need to be added here ... somehow
foreach(array('page', 'per_page', 'search') as $sParam){
if (array_key_exists($sParam, $this->_aRequest)){
$sReturn.='&'.$sParam.'='.urlencode($this->_aRequest[$sParam]);
if (array_key_exists($sParam, $this->_aRequest['filter'])){
$sReturn.='&'.$sParam.'='.urlencode($this->_aRequest['filter'][$sParam]);
}
}
return $sReturn;
......@@ -148,19 +194,17 @@ class deployForeman {
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")) {
die("ERROR: PHP CURL module is not installed.");
}
$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);
$this->log(__FUNCTION__ . " ".$this->_aRequest['method']." " . $this->_aRequest['url']);
$ch = curl_init($this->_aRequest['url']);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->_aRequest['method']);
if ($this->_aRequest['method']==='POST'){
......@@ -187,6 +231,18 @@ class deployForeman {
return $aReturn;
}
/**
* write debug infos if enabled
* @param string $sMessage
* @return boolean
*/
protected function _writeDebug($sMessage){
if ($this->_bDebug){
echo "$sMessage<br>\n";
}
return true;
}
// ----------------------------------------------------------------------
// public functions :: low level
// ----------------------------------------------------------------------
......@@ -217,22 +273,20 @@ class deployForeman {
$sStatus='unknown';
$bOk=false;
$this->_aRequest['method']=$this->_getMethod();
// prevent missing data because of paging
if ($this->_aRequest['method']==='GET' && !array_key_exists('per_page', $this->_aRequest)){
$this->_aRequest['per_page']=1000;
if ($this->_aRequest['method']==='GET' && !array_key_exists('per_page', $this->_aRequest['filter'])){
$this->_aRequest['filter']['per_page']=1000;
}
// check postdata
// TODO 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");
}
// add url parameters (search, paging)
$this->_aRequest['url']=$this->_generateUrl();
$this->_aRequest['url']=$this->_generateParams();
$this->_aRequest['url']=$this->_generateUrl().$this->_generateParams();
// ----- request
$this->_writeDebug(__FUNCTION__ . ' start request <pre>'.print_r($this->_aRequest,1).'</pre>');
$aReturn=$this->_httpCall();
// ----- check result
......@@ -268,49 +322,137 @@ class deployForeman {
}
$aReturn['_OK']=$bOk;
$aReturn['_status']=$sStatus;
$this->_writeDebug(__FUNCTION__ . ' result of request <pre>'.print_r($aReturn,1).'</pre>');
return $aReturn;
}
/**
* filter output for the response based on values $this->_aRequest['response']
* @param array $aData response of $this->makeRequest();
* @return array
*/
protected function _filterOutput($aData){
if(!array_key_exists('response', $this->_aRequest)){
return $aData;
}
$aTmp=array_key_exists('results', $aData['_json']) ? $aData['_json']['results'] : array($aData['_json']);
if(!count($aTmp)){
return array();
}
$aReturn=array();
foreach($aTmp as $aItem){
$aReturn[] = array_filter($aItem, function($key) {
return array_search($key, $this->_aRequest['response']) !==false;
}, ARRAY_FILTER_USE_KEY
);
}
return $aReturn;
}
// ----------------------------------------------------------------------
// public foreman functions
// ----------------------------------------------------------------------
/**
* get list of host groups as an array with [id] => [name of title]
* enable/ disable debugging
* @param boolean $bNewDebugFlag new value; true|false
* @return boolean
*/
public function setDebug($bNewDebugFlag){
return $this->_bDebug=$bNewDebugFlag;
}
/**
* check for missing config entries
* @return type
*/
public function selfcheck() {
$sOut='';
$sWarning='';
$sOut.="<h1>selfcheck</h1>";
$aApi=$this->read(array('request'=>array(array(''))));
if($aApi['_OK']){
foreach($aApi['_json']['links'] as $sKey=>$aCalls){
$sOut.="<h2>$sKey</h2><ul>";
foreach ($aCalls as $sLabel=>$sUrl){
$sOut.="<li>$sLabel .. $sUrl ";
$aTmp=preg_split('#\/#', $sUrl);
$sDir2=count($aTmp)>2 ? $aTmp[2] : '??';
$sDir3=count($aTmp)>3 ? $aTmp[3] : '??';
$sOut.="..... "
. ($this->_guessPrefixUrl($sDir2).$this->_guessPrefixUrl($sDir3)
?'<span style="background:#cfc">OK</span>'
:'<span style="background:#fcc">miss</span>'
) . ' ' . $sDir2.', '.$sDir3 . "</li>\n";
if (!($this->_guessPrefixUrl($sDir2).$this->_guessPrefixUrl($sDir3))){
$sWarning.="<li>$sKey - $sLabel - $sUrl</li>";
}
}
$sOut.="</ul>";
}
} else {
$sOut.='ERROR: connect to foreman failed.<br>';
}
if ($sWarning){
echo 'WARNINGS:<ol>'.$sWarning.'</ol>';
}
echo $sOut;
echo 'API: <pre>'.print_r($aApi,1).'</pre>';
return true;
}
// ----------------------------------------------------------------------
// public foreman API functions
// ----------------------------------------------------------------------
/**
* TODO: create
* @param array $aOptions
*/
public function create($aOptions){
}
/**
* GETTER
* $aOptions ... can contain optional subkeys
* - id - id of hostgroup
* - more - url behind "id"
* - search
* - page
* - per_page
* - request
* [] list of array(keyword [,id])
* - filter (array)
* - search (string)
* - page (string)
* - per_page (string)
* - response (array)
* - list of keys, i.e. array('id', 'title')
*
* @param array $aOptions
* @return boolean
* @return array
*/
public function getHostgroups($aOptions=array()) {
$aReturn=array();
public function read($aOptions){
$this->_aRequest=$aOptions;
$this->_aRequest['function']=__FUNCTION__;
$this->_aRequest['method']='GET';
$aData=$this->makeRequest();
if (!$aData['_OK']){
return false;
}
return $this->_filterOutput($aData);
}
// TODO: call a general method to create result array ... baased on
// $aOptions['result'] ...
/**
* TODO
* @param type $aOptions
*/
public function update($aOptions){
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){
$aReturn[$aItem['id']]=$aItem['title'];
}
}
return $aReturn;
/**
* TODO
* @param type $aOptions
*/
public function delete($aOptions){
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment