docs: def _do_setup_step(self, play):
          ''' get facts from the remote system '''
  
          host_list = self._list_available_hosts(play.hosts)
  
          if play.gather_facts is False:
              return {}
          elif play.gather_facts is None:
              host_list = [h for h in host_list if h not in self.SETUP_CACHE or 'module_setup' not in self.SETUP_CACHE[h]]
              if len(host_list) == 0:
                  return {}
  
          self.callbacks.on_setup()
          self.inventory.restrict_to(host_list)
  
          # push any variables down to the system
          setup_results = cirruscluster.ext.ansible.runner.Runner(
              pattern=play.hosts, module_name='setup', module_args={}, inventory=self.inventory,
              forks=self.forks, module_path=self.module_path, timeout=self.timeout, remote_user=play.remote_user,
              remote_pass=self.remote_pass, remote_port=play.remote_port, private_key_file=self.private_key_file,
              private_key=self.private_key,
              setup_cache=self.SETUP_CACHE, callbacks=self.runner_callbacks, sudo=play.sudo, sudo_user=play.sudo_user,
              transport=play.transport, sudo_pass=self.sudo_pass, is_playbook=True, module_vars=play.vars,
          ).run()
          self.stats.compute(setup_results, setup=True)
  
          self.inventory.lift_restriction()
  
          # now for each result, load into the setup cache so we can
          # let runner template out future commands
          setup_ok = setup_results.get('contacted', {})
          for (host, result) in setup_ok.iteritems():
              self.SETUP_CACHE[host].update({'module_setup': True})
              self.SETUP_CACHE[host].update(result.get('ansible_facts', {}))
          return setup_results