Skip to content

Instantly share code, notes, and snippets.

@roderik
Created April 30, 2012 17:01
Show Gist options
  • Select an option

  • Save roderik/2560019 to your computer and use it in GitHub Desktop.

Select an option

Save roderik/2560019 to your computer and use it in GitHub Desktop.
BillSplitCommand v6
<?php
namespace Kunstmaan\Hosting\BillSplitBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use SimpleXMLElement;
use SplFileObject;
use SplFileInfo;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Yaml\Parser;
class BillSplitCommand extends ContainerAwareCommand
{
/**
* @var Parser $parser
*/
private $parser;
/**
* @var string $nagiosPath
*/
private $nagiosPath;
protected function configure()
{
$this
->setName('bill:split')
->setDescription('Split the bill')
->addArgument('billpath', InputArgument::REQUIRED, 'The path to the bill yml file')
->addArgument('nagiospath', InputArgument::REQUIRED, 'The path to the nagios.xml file');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->parser = new Parser();
$this->nagiosPath = $input->getArgument('nagiospath');
$bill = $this->parseBill($input->getArgument('billpath'), $output);
$ymlServers = $this->parseServers($output);
$ymlProjects = $this->parseProjects($output);
$globalCost = $this->calculateGlobalCosts($bill, $output);
$remoteServers = $this->createServerArray($bill, $ymlServers, $output);
$remoteProjects = $this->createProjectArray($remoteServers, $ymlProjects, $output);
$allProjects = $this->createCompleteProjectArray($ymlServers, $ymlProjects, $output);
$resultArray = array();
foreach ($ymlServers["servers"] as $hostname => $server) {
if ($server["type"] == 'dedicated') {
$resultArray[$hostname] = array(
"hostname" => $hostname,
"maconomy" => $server["maconomy"],
"cost" => 0.0
);
} else {
foreach ($allProjects[$hostname] as $name => $project) {
$resultArray[$name] = array(
"hostname" => $hostname,
"maconomy" => $project["maconomy"],
"cost" => 0.0
);
}
}
}
$globalCostPerItem = bcdiv($globalCost,count($resultArray),2);
array_walk($resultArray, function(&$item, $key) use ($globalCostPerItem)
{
$item["cost"] = bcadd($item["cost"],$globalCostPerItem,2);
});
foreach($remoteServers as $hostname => $server){
if($server["type"] == 'dedicated'){
$resultArray[$hostname]["cost"] = bcadd($resultArray[$hostname]["cost"] , $server["amount"],2);
} else {
$numberOfProjects = count($remoteProjects[$hostname]);
$costPerProject = bcdiv($server["amount"], $numberOfProjects,2);
foreach($remoteProjects[$hostname] as $name => $project){
$resultArray[$name]["cost"] = bcadd($resultArray[$name]["cost"] , $costPerProject,2);
}
}
}
$total = 0.0;
array_walk($resultArray, function(&$item, $key) use (&$total)
{
$total = bcadd($total , $item["cost"],2);
});
if ($total != $bill["bill"]["total"]){
$output->writeln("<error> !!! Bill total = " . $bill["bill"]["total"] . " and our total is " . $total . " !!!</error>");
}
}
/**
* Creates an array of all the projects it can find on the shared servers.
* @param array $ymlServers
* @param array $ymlProjects
* @param OutputInterface $output
* @return array an array of all the projects it can find on the shared servers.
*/
private function createCompleteProjectArray(array $ymlServers, array $ymlProjects, OutputInterface $output)
{
$projects = array();
foreach ($ymlServers["servers"] as $hostname => $server) {
if ($server["type"] == 'shared') {
$server["hostname"] = $hostname;
$projects = array_merge($projects, $this->getNagiosProjects($server, $ymlProjects, $output));
}
}
return $projects;
}
/**
* Prepares an array of all the projects in this bill with their billing ID's
*
* @param array $remoteServers
* @param array $ymlProjects
* @param OutputInterface $output
* @return array all the projects in this bill with their billing ID's
*/
private function createProjectArray(array $remoteServers, array $ymlProjects, OutputInterface $output)
{
$output->writeln(" - Preparing projects array");
$remoteProjects = array();
foreach ($remoteServers as $server) {
if ($server["type"] == 'shared') {
$remoteProjects = array_merge($remoteProjects, $this->getNagiosProjects($server, $ymlProjects, $output));
}
}
return $remoteProjects;
}
private function getNagiosProjects($server, $ymlProjects, $output)
{
$remoteProjects = array();
$nagios = $this->parseNagios("http://" . $server["hostname"] . $this->nagiosPath, $output);
foreach ($nagios as $project) {
$remoteProjects[$server["hostname"]][$project] = array(
"hostname" => $server["hostname"],
"name" => $project,
"maconomy" => (isset($ymlProjects["projects"][$project]) ? $ymlProjects["projects"][$project] : ""));
}
return $remoteProjects;
}
/**
* Calculates the sum of all the global costs
*
* @param array $bill
* @param OutputInterface $output
* @return float the sum of all the global costs
*/
private function calculateGlobalCosts(array $bill, OutputInterface $output)
{
$output->writeln(" - Calculation global costs");
$cost = 0.0;
foreach ($bill["bill"]["items"] as $item) {
if (isset($item["type"]) && $item["type"] == 'global') {
foreach ($item["amount"] as $amount) {
$cost = bcadd($cost,$amount,2);
}
}
}
return $cost;
}
/**
* Prepares an array of all the servers in this bill with amounts and billing ID's
*
* @param array $bill
* @param array $ymlServers
* @param OutputInterface $output
* @return array an array of all the servers in this bill with amounts and billing ID's
*/
private function createServerArray(array $bill, array $ymlServers, OutputInterface $output)
{
$output->writeln(" - Preparing servers array");
$remoteServers = array();
foreach ($bill["bill"]["items"] as $item) {
if (isset($item["server"])) {
$cost = 0.0;
foreach ($item["amount"] as $amount) {
$cost = bcadd($cost,$amount,2);
}
$remoteServers[$item["server"]] = array(
"hostname" => $item["server"],
"amount" => $cost,
"type" => $ymlServers["servers"][$item["server"]]["type"],
"maconomy" => (isset($ymlServers["servers"][$item["server"]]["maconomy"]) ? $ymlServers["servers"][$item["server"]]["maconomy"] : "")
);
}
}
return $remoteServers;
}
/**
* Parses the YAML file containing the bill content into an array.
*
* @param string $billpath
* @param OutputInterface $output
* @return array a multidimensional array with the bill.yml content
*/
private function parseBill($billpath, OutputInterface $output)
{
$output->writeln(" - Locating and parsing the bill input file: " . $billpath);
return $this->parseYML($billpath);
}
/**
* Parses the YAML file containing the servers into an array.
*
* @param OutputInterface $output
* @return array a multidimensional array with the servers.yml content
*/
private function parseServers(OutputInterface $output)
{
$output->writeln(" - Locating and parsing the servers input file: servers.yml");
return $this->parseYML("maconomy/servers.yml");
}
/**
* Parses the YAML file containing the projects into an array.
*
* @param OutputInterface $output
* @return array a multidimensional array with the projects.yml content
*/
private function parseProjects(OutputInterface $output)
{
$output->writeln(" - Locating and parsing the projects input file: projects.yml");
return $this->parseYML("maconomy/projects.yml");
}
/**
* Parses a YAML file to an array
*
* @param string $path
* @return array a multidimensional array with the yml content
*/
private function parseYML($path)
{
$content = file_get_contents($path);
return $this->parser->parse($content);
}
/**
* Parses the XML file containing the projects on a server into an array.
*
* @param string $nagiospath
* @param OutputInterface $output
* @return array a multidimensional array with the nagios.xml content
*/
private function parseNagios($nagiospath, OutputInterface $output)
{
$output->writeln(" - Locating and parsing the nagios input file: " . $nagiospath);
$content = file_get_contents($nagiospath);
$result = array();
$xml = new SimpleXMLElement($content);
foreach ($xml->children() as $project) {
if ($project->monitor != "false") {
$result[(string)$project->name] = (string)$project->name;
}
}
return $result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment