/** * @covers DataSift\Storyplayer\CommandLib\CommandRunner::runSilently */ public function testReturns127IfTheCommandDoesNotExist() { // ---------------------------------------------------------------- // setup your test // our test subject $obj = new CommandRunner(); // a fake logging object $log = Mockery::mock("DataSift\\Storyplayer\\PlayerLib\\Action_LogItem"); $log->shouldReceive('endAction')->once(); $log->shouldReceive('captureOutput')->once(); // our mocked $st $st = Mockery::mock("DataSift\\Storyplayer\\PlayerLib\\StoryTeller"); $st->shouldReceive('startAction')->andReturn($log); // our example command $helperCmd = "/fred/alice/this_command_does_not_exist"; // ---------------------------------------------------------------- // perform the change $result = $obj->runSilently($st, $helperCmd); // ---------------------------------------------------------------- // test the results $this->assertTrue($result instanceof CommandResult); $this->assertEquals(127, $result->returnCode); }
/** * @return string */ public function determineBridgedInterface() { // what are we doing? $log = usingLog()->startAction("determine bridged network interface for Vagrant VM"); try { // 1. try to load Vagrant settings from storyplayer.json // e.g.: "moduleSettings":{"vagrant":{"bridgedIface":"eth0"}} $vagrantSettings = fromStoryplayer()->getModuleSetting('vagrant'); if (!empty($vagrantSettings->bridgedIface)) { $log->endAction('Returning configured ' . $vagrantSettings->bridgedIface . ' interface'); return $vagrantSettings->bridgedIface; } } catch (E5xx_ActionFailed $e) { // ignore errors as this setting may not exist } // 2. check if VirtualBox (VBoxManage) is installed $command = 'which VBoxManage'; $commandRunner = new CommandRunner(); $result = $commandRunner->runSilently($command); if ($result->returnCode !== 0) { // VBoxManage is not installed, we are probably using another provider // like OpenStack that do not require this setting $log->endAction('VBoxManage is not installed: returning default eth0 interface'); return 'eth0'; } // 3. VBoxManage can actually tell us what we need to know $command = 'VBoxManage list bridgedifs'; $commandRunner = new CommandRunner(); $result = $commandRunner->runSilently($command); if ($result->returnCode != 0) { $log->endAction('unable to get list of bridgable network interfaces from VBoxManage :('); throw new E5xx_ActionFailed(__METHOD__); } // now we just need to make sense of it all $lines = explode("\n", $result->output); $iface = null; foreach ($lines as $line) { $matches = []; if (preg_match("|Name:[\\s]+(.*)|", $line, $matches)) { $iface = $matches[1]; } else { if ($iface !== null && preg_match("|IPAddress:[\\s]+(.*)|", $line, $matches)) { // our network interface contains an IPAddress - it is likely // to be one that works if ($matches[1] != '0.0.0.0') { $log->endAction($iface); return $iface; } } } } // if we get here, then we haven't found a network interface to use $log->endAction("no bridgeable network interface found :("); throw new E5xx_ActionFailed(__METHOD__); }
/** * * @param VagrantVmDetails $vmDetails * @param string $command * @return CommandResult */ public function runCommandViaHostManager($vmDetails, $command) { // what are we doing? $log = usingLog()->startAction("run vagrant command '{$command}'"); // build the command $fullCommand = "cd '{$vmDetails->dir}' && vagrant ssh -c \"{$command}\""; // run the command $commandRunner = new CommandRunner(); $result = $commandRunner->runSilently($fullCommand); // all done $log->endAction("return code was '{$result->returnCode}'"); return $result; }
public function provisionHosts(ProvisioningDefinition $hosts, $provConf) { // what are we doing? $log = usingLog()->startAction("use Ansible to provision host(s)"); // get our ansible configuration $ansibleSettings = fromConfig()->getModuleSetting('ansible'); // our reverse list of roles => hosts $rolesToHosts = array(); // build up the list of roles foreach ($hosts as $hostId => $hostProps) { // what is the host's IP address? $ipAddress = fromHost($hostId)->getIpAddress(); // add the host to the required roles if (isset($hostProps->roles)) { foreach ($hostProps->roles as $role) { if (!isset($rolesToHosts[$role])) { $rolesToHosts[$role] = array(); } $rolesToHosts[$role][] = $ipAddress; } } } // at this point, we know which roles need applying to which hosts // // build up the inventory file $inventory = ""; foreach ($rolesToHosts as $role => $hostsForRole) { // add the role marker $inventory .= "[{$role}]" . PHP_EOL; // add the list of hosts foreach ($hostsForRole as $host) { $inventory .= $host . PHP_EOL; } // add an extra blank line for readability $inventory .= PHP_EOL; } // write out the inventory $inventoryFile = $this->writeInventoryFile($inventory); // where should we create the host_vars? $inventoryFolder = dirname($inventoryFile); // we set these in the foreach() loop $sshUsername = null; $sshKeyFile = null; // now we need to write out the host files foreach ($hosts as $hostId => $hostProps) { // what is the host's IP address? $ipAddress = fromHost($hostId)->getIpAddress(); $sshUsername = fromHost($hostId)->getSshUsername(); $sshKeyFile = fromHost($hostId)->getSshKeyFile(); // do we have any vars to write? if (!isset($hostProps->params) || $hostProps->params === null || is_array($hostProps) && count($hostProps) == 0) { // we'd better remove any host_vars file that exists, // in case what's there (if anything) is left over from // a different test run $this->removeHostVarsFile($inventoryFolder, $ipAddress); } else { // write the host vars file $this->writeHostVarsFile($inventoryFolder, $ipAddress, $hostProps->params); } } // build the command for Ansible $command = 'ansible-playbook -i "' . $inventoryFile . '"' . ' "--private-key=' . $sshKeyFile . '"' . ' "--user='******'"'; $command .= ' "' . $ansibleSettings->dir . DIRECTORY_SEPARATOR . $ansibleSettings->playbook . '"'; // let's run the command // // this looks like a hack, but it is the only way to work with Ansible // if there's an ansible.cfg in the root of the playbook :( $cwd = getcwd(); chdir($ansibleSettings->dir); $commandRunner = new CommandRunner(); $result = $commandRunner->runSilently($command); chdir($cwd); // what happened? if (!$result->didCommandSucceed()) { throw new E5xx_ActionFailed(__METHOD__, "provisioning failed"); } // all done $log->endAction(); }
public function provisionHosts(ProvisioningDefinition $hosts, $provConfig) { // what are we doing? $log = usingLog()->startAction("use dsbuild to provision host(s)"); // the params file that we are going to output $dsbuildParams = new BaseObject(); // build up the list of settings to write out foreach ($hosts as $hostId => $hostProps) { // what is the host's IP address? $ipAddress = fromHost($hostId)->getIpAddress(); $propName = $hostId . '_ipv4Address'; $dsbuildParams->{$propName} = $ipAddress; if (isset($hostProps->params)) { $dsbuildParams->mergeFrom($hostProps->params); } } // add in all the config settings that we know about $dsbuildParams->storyplayer_ipv4Address = fromConfig()->get('storyplayer.ipAddress'); $dsbuildParams->mergeFrom($this->flattenData($this->st->getActiveConfig()->getData(''))); // write them out $this->writeDsbuildParamsShellFile((array) $dsbuildParams); $this->writeDsbuildParamsYamlFile((array) $dsbuildParams); // at this point, we are ready to attempt provisioning // // provision each host in the order that they're listed foreach ($hosts as $hostId => $hostProps) { // which dsbuildfile are we going to run? $hostDir = fromHost($hostId)->getLocalFolder(); $dsbuildFilename = $this->getDsbuildFilename($hostDir, $provConfig, $hostId); if ($dsbuildFilename === null) { // there is no dsbuildfile at all to run $log->endAction("cannot find dsbuildfile to run :("); throw new E5xx_ActionFailed(__METHOD__, "no dsbuildfile to run"); } // at this point, we are ready to provision $commandRunner = new CommandRunner(); // copy the dsbuildparams files to the target machine using scp // NOTE: the "vagrant rsync" command seems not working with some Vagrant provisioners (e.g. OpenStack) $command = 'scp' . ' ' . $dsbuildParams->{'hosts_' . $hostId . '_scpOptions_0'} . ' ' . $dsbuildParams->{'hosts_' . $hostId . '_scpOptions_1'} . ' dsbuildparams.*' . ' ' . $dsbuildParams->{'hosts_' . $hostId . '_sshUsername'} . '@' . $dsbuildParams->{'hosts_' . $hostId . '_ipAddress'} . ':/vagrant/'; $result = $commandRunner->runSilently($command); if (!$result->didCommandSucceed()) { // try to rsync folders in case of scp fail $command = 'vagrant rsync ' . $hostId; $commandRunner->runSilently($command); } // provision $command = 'sudo bash /vagrant/' . $dsbuildFilename; $result = usingHost($hostId)->runCommand($command); // what happened? if (!$result->didCommandSucceed()) { throw new E5xx_ActionFailed(__METHOD__, "provisioning failed"); } } // all done $log->endAction(); }