Author: Stuart Herbert (stuart.herbert@datasift.com)
 /**
  * @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);
 }
Exemple #2
0
 /**
  * @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__);
 }
Exemple #3
0
 /**
  *
  * @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();
 }