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

Merge branch 'projects-in-ldap' into 'master'

Projects in ldap

See merge request !23
parents ef98b1e3 96426274
Branches
No related tags found
No related merge requests found
......@@ -57,6 +57,7 @@ return array(
"project-action-overview",
"project-action-phase",
"project-action-setup",
"project-action-setup-edit-replacements",
),
// ----- wenn es mal eine feinere Granulierung braucht, muss man eine
......
......@@ -224,6 +224,7 @@
"defaultbranch": "[default: Master oder Trunk]",
"deploy": "Deploy",
"deploy-hint": "Deploy der Queue von Phase [%s]",
"deploy-settings": "Deployment - Einstellungen",
"deploytimes": "Deployment Zeitpunkte",
"deploytimes-immediately": "Ein Archiv in der Queue wird sofort ins Repo gestellt.",
"deploymethod": "Deployment-Methode",
......@@ -267,6 +268,10 @@
"projectname": "Projektname",
"projectmanager": "Projektleiter",
"queue": "Queue",
"replacement-fields": "erkannte Platzhalter:",
"replacement-targetfile": "Ziel-Datei",
"replacements": "Ersetzungen mit Template-Dateien",
"replacements-info": "Beim Build-Prozess gefundene Templates werden aufgelistet und darin erkannte Platzhalter erkannt. Die Felder sind ausschliesslich für die neue Infrastruktur relevant.",
"repositoryinfos": "Quell-Repository",
"repository-access-browser": "Browserzugriff auf das Repo",
"repository-auth": "Authentifizierung/ Dateiname zum SSH-Private-Key",
......
......@@ -226,6 +226,7 @@
"defaultbranch": "[default: master or trunk]",
"deploy": "Deploy",
"deploy-hint": "Deploy queue of phase [%s]",
"deploy-settings": "Deployment - settings",
"deploymethod": "Deployment method",
"deploymethod-none": "None. Do not trigger any action.",
"deploymethod-puppet": "Run Puppet on target host(s)",
......@@ -269,6 +270,10 @@
"projectname": "Project name",
"projectmanager": "Projekt manager",
"queue": "Queue",
"replacement-fields": "Detected placeholders:",
"replacement-targetfile": "Target file",
"replacements": "Replacements in template files",
"replacements-info": "List of detected templates with its placeholders.",
"repositoryinfos": "Sourcecode Repository",
"repository-access-browser": "Browser access to sources",
"repository-auth": "Authentication/ filename of ssh private key",
......
<?php
// namespace imldeployment;
require_once 'project.class.php';
/**
* config-replacement class
* reads templatefiles and scans its placeholders for replacements
*
* @author hahn
*/
class configreplacement {
/**
* project class
* @var type
*/
protected $_oProject = false;
/**
* init
* @param string $sProject optional: project id; you can use setProject() too
* @return boolean
*/
public function __construct($sProject = false) {
if ($sProject){
$this->setProject($sProject);
}
return true;
}
/**
* get an array with a flat list of all templatefiles of a build
* @param string $sPhase name of phase
* @return boolean|array
*/
public function getTemplatefiles($sPhase=false){
$aReturn = array();
if (!$sPhase){
$sPhase=$this->_oProject->getNextPhase(false);
}
$aBuildfiles=$this->_oProject->getBuildfilesByPlace($sPhase, 'onhold');
if (!$aBuildfiles){
$aBuildfiles=$this->_oProject->getBuildfilesByPlace($sPhase, 'ready2install');
}
if (!$aBuildfiles || !array_key_exists('types', $aBuildfiles) || !array_key_exists('templates', $aBuildfiles['types'])){
return false;
}
foreach ($aBuildfiles['types']['templates'] as $sFile){
$aReturn[]=$aBuildfiles['dir'].'/'.$sFile;
}
return $aReturn;
}
/**
* get an array with all template files (basename) and its replacement fields
* @param string $sPhase name of phase
* @return array
*/
public function getReplacements($sPhase=false){
$aFiles=$this->getTemplatefiles($sPhase);
if (!$aFiles){
return false;
}
$aReturn=array();
foreach ($aFiles as $sFile){
// $sFile always exists because it was read from filesystem
$sContent=file_get_contents($sFile);
preg_match_all('/\@replace\[[\'\"](.*)[\'\"]\]/U', $sContent, $aMatches);
$aReturn[$sFile]=$aMatches[1];
}
return $aReturn;
}
/**
* switch to a project
* @param type $sProject
*/
public function setProject($sProject){
$this->_oProject = new project($sProject);
}
}
......@@ -363,6 +363,84 @@ class project extends base {
return $sBase ? $sBase . '/' . $this->_aPrjConfig["fileprefix"] . '.tgz' : false;
}
/**
* list of files of a given phase and place
* @param string $sPhase one of preview|stage|live ...
* @param string $sPlace one of onhold|ready2install|deployed
* @return array
*/
public function _getBuildfilesByDir($sBase) {
$aReturn=array();
if(!$sBase || !is_dir($sBase)){
return false;
}
$iTotalSize=0;
$aReturn=array(
'dir'=>$sBase,
'filecount'=>false,
'totalsize'=>false,
'totalsize-hr'=>false,
);
foreach (glob($sBase . '/*') as $sFile){
$sFileBase=basename($sFile);
$sExt = pathinfo($sFile, PATHINFO_EXTENSION);
$aStat=stat($sFile);
switch($sExt){
case 'erb':
$sType='templates';
$sIcon='fa fa-file-code-o';
break;
case 'tgz':
$sType='package';
$sIcon='fa fa-file-archive-o';
break;
case 'json':
$sType='metadata';
$sIcon='fa fa-file-text-o';
break;
default:
$sType='any';
$sIcon='fa fa-file-o';
break;
}
$iTotalSize+=$aStat['size'];
$aReturn['files'][$sFileBase]=array(
'type'=>$sType,
'icon'=>$sIcon ? '<i class="'.$sIcon.'"></i> ' : '',
'extension'=>$sExt,
'size'=>$aStat['size'],
);
$aReturn['types'][$sType][]=$sFileBase;
}
$aReturn['totalsize']=$iTotalSize;
$aReturn['totalsize-hr']=(round($iTotalSize/1024/102.4)/10).' MB';
$aReturn['filecount']=count($aReturn['files']);
return $aReturn;
}
/**
* list of files of a given phase and place
* @param string $sPhase one of preview|stage|live ...
* @param string $sPlace one of onhold|ready2install|deployed
* @return array
*/
public function getBuildfilesByPlace($sPhase, $sPlace) {
$sBase = $this->_getFileBase($sPhase, $sPlace);
return $this->_getBuildfilesByDir($sBase);
}
/**
* list of files of a given version number
* @param string $sVersion name of version
* @return array
*/
public function getBuildfilesByVersion($sVersion) {
return $this->_getBuildfilesByDir($this->_getProjectArchiveDir().'/'.$sVersion);
}
/**
* get full path of a packed project archive
* @param string $sVersion version number of the build
......@@ -2270,6 +2348,28 @@ class project extends base {
}
return '';
}
/**
* get html code for list of files in a phase
* @param string $sPhase phase of a project
* @return string
*/
private function _renderFiles($sPhase){
$sReturn='';
$aFiles=$this->getBuildfilesByPlace($sPhase, 'ready2install');
if (!$aFiles || !$aFiles['filecount']){
return '';
}
$sReturn.='<strong>'.t("filelist").'</strong> ('.$aFiles['filecount'].'):<br>';
foreach($aFiles['files'] as $sFilename => $aData){
$sReturn.='<div class="file file-'.$aData['type'].' fileext-'.$aData['extension'].'" title="'.$sFilename.' ('.$aData['type'].')">'
. $aData['icon'] . $sFilename
// . ' ('.$aData['type'].')'
. '</div>'
;
}
$sReturn.='('.$aFiles['totalsize-hr'].')';
return $sReturn;
}
/**
* render html for a colored link to any project action
......@@ -2395,6 +2495,8 @@ class project extends base {
}
$sRow2.='<br>' . $this->renderLink("phase", $sPhase)
. $this->_renderHosts($sPhase)
.'<br>'
. $this->_renderFiles($sPhase)
. '</td>';
}
return '<table><thead><tr>' . $sRow1 . '</tr></thead><tbody><tr>' . $sRow2 . '</tr></tbody></table>';
......@@ -2699,8 +2801,6 @@ class project extends base {
$sRowHead2.='<td></td>' . $this->renderPlacesAsTd($sPhase);
}
// echo "<pre>" . print_r($aAllVersions, true) . "</pre>";
foreach ($aAllVersions as $sVersion => $aData) {
$sReturn.='<tr>';
......@@ -2850,6 +2950,11 @@ class project extends base {
$sMessages = '';
require_once ("formgen.class.php");
require_once("./classes/config-replacement.class.php");
$oConfig = new configreplacement();
$oConfig->setProject($this->_aConfig["id"]);
$i = 0;
$aPrefixItem = count($this->getVersions()) ?
......@@ -3034,13 +3139,16 @@ class project extends base {
'type' => 'markup',
'value' => ''
// .'<pre>'.print_r($this->_aPrjConfig["phases"][$sPhase], 1).'</pre>'
/*
. '<a class="'.$sPhase.'">'
. t("phase") . ' ' . $sPhase
. ($bActivePhase ? '' : ' (' . t("inactive") . ')')
. '</a>'
*/
. '<table class="table">'
. '<tbody>'
. '<tr><th class="' . $sPhase . '">'. t("phase") . ' ' . $sPhase.'</th></tr>'
. '<tr><td class="' . ($bActivePhase ? $sPhase : '') . '">'
. ''
);
$aForms["setup"]["form"]['input' . $i++] = array(
......@@ -3066,6 +3174,10 @@ class project extends base {
'value' => ''
.'<div id="'.$sDivId4PhaseSettings.'" '.($bActivePhase ? '' : ' style="display: none;"').'">'
);
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'markup',
'value' => '<div style="clear: both"></div><div class="form-group"><h3>'.t("deploy-settings").'</h3></div>'
);
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'text',
'name' => 'phases[' . $sPhase . '][url]',
......@@ -3096,11 +3208,14 @@ class project extends base {
'checked' => $sDeploymethod==="puppet",
'onclick' => '$(\'#'.$sDivId4TargetHosts.'\').css(\'display\', (this.checked ? \'block\' : \'none\') )',
),
/*
* see deploy method to handle an action
'sshproxy' => array(
'label' => t("deploymethod-sshproxy"),
'checked' => $sDeploymethod==="sshproxy",
'onclick' => '$(\'#'.$sDivId4TargetHosts.'\').css(\'display\', (this.checked ? \'block\' : \'none\') )',
),
*/
),
);
......@@ -3164,16 +3279,93 @@ class project extends base {
'size' => 100,
'placeholder' => implode(", ", $this->_aConfig["phases"][$sPhase]["deploytimes"]),
);
$aReplacements=$oConfig->getReplacements($sPhase);
$sDivIdReplacement='divreplacements-'.$sPhase;
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'markup',
'value' => ''
'value' => '<div style="clear: both; height: 2em;"></div>'
. '<div class="form-group">'
. ($aReplacements
? '<a class="expandable closed" href="#" onclick="$(\'#'.$sDivIdReplacement.'\').slideToggle(); $(this).toggleClass(\'closed\'); return false;">'
: ''
)
. '<h3>'.t("replacements").' ('.($aReplacements ? count($aReplacements):0).')</h3>'
. ($aReplacements ? '</a>' : '')
. t('replacements-info')
. '</div>'
);
if ($aReplacements){
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'markup',
'value' => '</td></tr></tbody></table>',
'value' => '<div id="'.$sDivIdReplacement.'" style="display: none;">'
);
foreach($aReplacements as $sFile=>$aFields){
$tTplFile=basename($sFile);
$aValues = (array_key_exists("replace", $this->_aPrjConfig["phases"][$sPhase])
&& array_key_exists($tTplFile, $this->_aPrjConfig["phases"][$sPhase]["replace"])
)
? $this->_aPrjConfig["phases"][$sPhase]["replace"][$tTplFile] : false;
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'markup',
'value' => '<div class="form-group"><br><h4><i class="fa fa-file-code-o"></i> '.$tTplFile.'</h4>'
// . '<textarea cols="100" rows="7" >'.file_get_contents($sFile).'</textarea>'
. '</div>'
);
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'text',
'name' => 'phases[' . $sPhase . '][replace]['.$tTplFile.'][targetfile]',
'label' => t("replacement-targetfile"),
'value' => $aValues && array_key_exists('targetfile', $aValues) ? $aValues['targetfile'] : '',
// 'required' => 'required',
'validate' => 'isastring',
'size' => 100,
'placeholder' => strip_tags(t("replacement-targetfile")),
);
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'markup',
'value' => '<br>'.t("replacement-fields")
// . '<pre>'.print_r($aValues, 1).'</pre>'
);
foreach ($aFields as $sField){
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'text',
'disabled' => $this->oUser->hasPermission("project-action-setup-edit-replacements") ? '' : 'disabled',
'name' => 'phases[' . $sPhase . '][replace]['.$tTplFile.']['.$sField.']',
'label' => $sField,
'value' => $aValues && array_key_exists($sField, $aValues) ? $aValues[$sField] : '',
// 'required' => 'required',
'validate' => 'isastring',
'size' => 100,
'placeholder' => $sField,
);
}
}
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'markup',
'value' => '</div>'
);
} else {
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'markup',
'value' => '<div class="form-group"><h4>'.t("none").'</h4></div>'
);
}
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'markup',
'value' => ''
.'</div>'
); // close div for active phase
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'markup',
'value' => '</td></tr></tbody></table>',
);
} // END: loop over phases
$aForms["setup"]["form"]['input' . $i++] = array(
'type' => 'markup',
'value' => '</div></div></div>'
......
......@@ -94,9 +94,9 @@ class vcs implements iVcs {
$this->_aCfg = $aRepoConfig;
// define temp dir
$this->_setTempdir();
$this->_sKeyfile = $this->_aCfg["dataDir"] . "/sshkeys/" . $this->_aCfg["auth"];
$this->_sWrapper = $this->_aCfg["appRootDir"] . "/shellscripts/gitsshwrapper.sh";
$this->_setTempdir();
return $this->_aCfg = $aRepoConfig;
}
......@@ -111,7 +111,7 @@ class vcs implements iVcs {
$sGitCmd = 'export GIT_SSH="' . $this->_sWrapper . '" ; export PKEY="' . $this->_sKeyfile . '" ; ';
$sGitCmd.='mkdir -p "' . $this->_sTempDir . '" && cd "' . $this->_sTempDir . '" && ';
$sGitCmd.='git init >/dev/null && ';
$sGitCmd.='git remote add origin "' . $this->getUrl() . '" 2>&1 && ';
$sGitCmd.='git remote add origin "' . $this->getUrl() . '" 2>&1 ';
// $sGitCmd='time ('.$sGitCmd.')';
exec($sGitCmd, $aOutput, $iRc);
}
......
body{padding-top: 0;}
#header,#footer{
background:#eee; background: linear-gradient(#fff,#eee);
......@@ -140,6 +139,27 @@ td.highlight{background:rgba(255,220,50,0.5) !important;}
.preview, .stage, .live{
}
a.expandable:before{
/*
border: 1px solid #aaa;
border-radius: 0.3em;
*/
color:#a00;
content: '+';
float: left;
font-size: 150%;
margin-right: 0em;
text-align: center;
transition: ease-in 0.3s;
transform: rotate(-45deg);
width: 1em;
}
a.closed:before{
color:#067;
content: '+';
transform: rotate(0deg);
}
a.info { border-bottom: 1px dotted; padding-bottom: 2px;}
a.info:hover { text-decoration: none; background: #fff;}
a.infoAsModal>span {display: none;}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment