Ejemplo n.º 1
0
    def delete_org(self):
        """ Uses sfdx force:org:delete to create the org """
        if not self.created:
            self.logger.info(
                'Skipping org deletion: the scratch org has not been created')
            return

        command = 'sfdx force:org:delete -p -u {}'.format(self.username)
        self.logger.info(
            'Deleting scratch org with command {}'.format(command))
        p = sarge.Command(command, stdout=sarge.Capture(buffer_size=-1))
        p.run()

        org_info = None
        stdout = []
        for line in p.stdout:
            stdout.append(line)
            if line.startswith('An error occurred deleting this org'):
                self.logger.error(line)
            else:
                self.logger.info(line)

        if p.returncode:
            message = 'Failed to delete scratch org: \n{}'.format(
                ''.join(stdout))
            raise ScratchOrgException(message)

        # Flag that this org has been created
        self.config['created'] = False
        self.config['username'] = None
Ejemplo n.º 2
0
    def delete_org(self):
        """ Uses sfdx force:org:delete to delete the org """
        if not self.created:
            self.logger.info(
                "Skipping org deletion: the scratch org has not been created")
            return

        command = sarge.shell_format("sfdx force:org:delete -p -u {0}",
                                     self.username)
        self.logger.info(
            "Deleting scratch org with command {}".format(command))
        p = sarge.Command(command,
                          stdout=sarge.Capture(buffer_size=-1),
                          shell=True)
        p.run()

        stdout = []
        for line in io.TextIOWrapper(p.stdout):
            stdout.append(line)
            if line.startswith("An error occurred deleting this org"):
                self.logger.error(line)
            else:
                self.logger.info(line)

        if p.returncode:
            message = "Failed to delete scratch org: \n{}".format(
                "".join(stdout))
            raise ScratchOrgException(message)

        # Flag that this org has been deleted
        self.config["created"] = False
        self.config["username"] = None
        self.config["date_created"] = None
Ejemplo n.º 3
0
    def delete_org(self):
        """ Uses sfdx force:org:delete to delete the org """
        if not self.created:
            self.logger.info(
                "Skipping org deletion: the scratch org has not been created"
            )
            return

        p = sfdx("force:org:delete -p", self.username, "Deleting scratch org")

        stdout = []
        for line in p.stdout_text:
            stdout.append(line)
            if line.startswith("An error occurred deleting this org"):
                self.logger.error(line)
            else:
                self.logger.info(line)

        if p.returncode:
            message = "Failed to delete scratch org: \n{}".format("".join(stdout))
            raise ScratchOrgException(message)

        # Flag that this org has been deleted
        self.config["created"] = False
        self.config["username"] = None
        self.config["date_created"] = None
Ejemplo n.º 4
0
    def create_org(self):
        """ Uses sfdx force:org:create to create the org """
        if not self.config_file:
            # FIXME: raise exception
            return
        if not self.scratch_org_type:
            self.config["scratch_org_type"] = "workspace"

        options = {
            "config_file":
            self.config_file,
            "devhub":
            " --targetdevhubusername {}".format(self.devhub)
            if self.devhub else "",
            "namespaced":
            " -n" if not self.namespaced else "",
            "days":
            " --durationdays {}".format(self.days) if self.days else "",
            "alias":
            sarge.shell_format(' -a "{0!s}"', self.sfdx_alias)
            if self.sfdx_alias else "",
            "extraargs":
            os.environ.get("SFDX_ORG_CREATE_ARGS", ""),
        }

        # This feels a little dirty, but the use cases for extra args would mostly
        # work best with env vars
        command = "sfdx force:org:create -f {config_file}{devhub}{namespaced}{days}{alias} {extraargs}".format(
            **options)
        self.logger.info(
            "Creating scratch org with command {}".format(command))
        p = sarge.Command(command,
                          stdout=sarge.Capture(buffer_size=-1),
                          shell=True)
        p.run()

        re_obj = re.compile(
            "Successfully created scratch org: (.+), username: (.+)")
        stdout = []
        for line in p.stdout:
            match = re_obj.search(line)
            if match:
                self.config["org_id"] = match.group(1)
                self.config["username"] = match.group(2)
            stdout.append(line)
            self.logger.info(line)

        self.config["date_created"] = datetime.datetime.now()

        if p.returncode:
            message = "{}: \n{}".format(FAILED_TO_CREATE_SCRATCH_ORG,
                                        "".join(stdout))
            raise ScratchOrgException(message)

        if self.config.get("set_password"):
            self.generate_password()

        # Flag that this org has been created
        self.config["created"] = True
Ejemplo n.º 5
0
    def create_org(self):
        """ Uses sfdx force:org:create to create the org """
        if not self.config_file:
            # FIXME: raise exception
            return
        if not self.scratch_org_type:
            self.config['scratch_org_type'] = 'workspace'

        options = {
            'config_file':
            self.config_file,
            'devhub':
            ' --targetdevhubusername {}'.format(self.devhub)
            if self.devhub else '',
            'namespaced':
            ' -n' if not self.namespaced else '',
            'days':
            ' --durationdays {}'.format(self.days) if self.days else '',
            'alias':
            ' -a "{}"'.format(self.sfdx_alias) if self.sfdx_alias else '',
            'extraargs':
            os.environ.get('SFDX_ORG_CREATE_ARGS', ''),
        }

        # This feels a little dirty, but the use cases for extra args would mostly
        # work best with env vars
        command = 'sfdx force:org:create -f {config_file}{devhub}{namespaced}{days}{alias} {extraargs}'.format(
            **options)
        self.logger.info(
            'Creating scratch org with command {}'.format(command))
        p = sarge.Command(command, stdout=sarge.Capture(buffer_size=-1))
        p.run()

        org_info = None
        re_obj = re.compile(
            'Successfully created scratch org: (.+), username: (.+)')
        stdout = []
        for line in p.stdout:
            match = re_obj.search(line)
            if match:
                self.config['org_id'] = match.group(1)
                self.config['username'] = match.group(2)
            stdout.append(line)
            self.logger.info(line)

        self.config['date_created'] = datetime.datetime.now()

        if p.returncode:
            message = '{}: \n{}'.format(
                FAILED_TO_CREATE_SCRATCH_ORG,
                ''.join(stdout),
            )
            raise ScratchOrgException(message)

        if self.config.get('set_password'):
            self.generate_password()

        # Flag that this org has been created
        self.config['created'] = True
    def force_refresh_oauth_token(self):
        # Call force:org:display and parse output to get instance_url and
        # access_token
        p = sfdx("force:org:open -r", self.username, log_note="Refreshing OAuth token")

        stdout_list = [line.strip() for line in p.stdout_text]

        if p.returncode:
            self.logger.error(f"Return code: {p.returncode}")
            for line in stdout_list:
                self.logger.error(line)
            message = f"Message: {nl.join(stdout_list)}"
            raise ScratchOrgException(message)
Ejemplo n.º 7
0
    def force_refresh_oauth_token(self):
        # Call force:org:display and parse output to get instance_url and
        # access_token
        p = sfdx("force:org:open -r",
                 self.username,
                 log_note="Refreshing OAuth token")

        stdout_list = [line.strip() for line in io.TextIOWrapper(p.stdout)]

        if p.returncode:
            self.logger.error("Return code: {}".format(p.returncode))
            for line in stdout_list:
                self.logger.error(line)
            message = "Message: {}".format("\n".join(stdout_list))
            raise ScratchOrgException(message)
Ejemplo n.º 8
0
    def force_refresh_oauth_token(self):
        # Call force:org:display and parse output to get instance_url and access_token
        command = 'sfdx force:org:open -r -u {}'.format(self.username)
        self.logger.info('Refreshing OAuth token with command: {}'.format(command))
        p = sarge.Command(command, stdout=sarge.Capture(buffer_size=-1))
        p.run()

        stdout_list = []
        for line in p.stdout:
            stdout_list.append(line.strip())

        if p.returncode:
            self.logger.error('Return code: {}'.format(p.returncode))
            for line in stdout_list:
                self.logger.error(line)
            message = 'Message: {}'.format('\n'.join(stdout_list))
            raise ScratchOrgException(message)
Ejemplo n.º 9
0
    def create_org(self):
        """ Uses sfdx force:org:create to create the org """
        if not self.config_file:
            # FIXME: raise exception
            return
        if not self.scratch_org_type:
            self.config['scratch_org_type'] = 'workspace'

        devhub = ''
        if self.devhub:
            devhub = ' --targetdevhubusername {}'.format(self.devhub)

        # This feels a little dirty, but the use cases for extra args would mostly
        # work best with env vars
        extraargs = os.environ.get('SFDX_ORG_CREATE_ARGS', '')
        command = 'sfdx force:org:create -f {}{} {}'.format(
            self.config_file, devhub, extraargs)
        self.logger.info(
            'Creating scratch org with command {}'.format(command))
        p = sarge.Command(command, stdout=sarge.Capture(buffer_size=-1))
        p.run()

        org_info = None
        re_obj = re.compile(
            'Successfully created scratch org: (.+), username: (.+)')
        stdout = []
        for line in p.stdout:
            match = re_obj.search(line)
            if match:
                self.config['org_id'] = match.group(1)
                self.config['username'] = match.group(2)
            stdout.append(line)
            self.logger.info(line)

        if p.returncode:
            message = 'Failed to create scratch org: \n{}'.format(
                ''.join(stdout))
            raise ScratchOrgException(message)

        self.generate_password()

        # Flag that this org has been created
        self.config['created'] = True
Ejemplo n.º 10
0
    def force_refresh_oauth_token(self):
        # Call force:org:display and parse output to get instance_url and
        # access_token
        command = sarge.shell_format("sfdx force:org:open -r -u {0}",
                                     self.username)
        self.logger.info(
            "Refreshing OAuth token with command: {}".format(command))
        p = sarge.Command(command,
                          stdout=sarge.Capture(buffer_size=-1),
                          shell=True)
        p.run()

        stdout_list = [line.strip() for line in io.TextIOWrapper(p.stdout)]

        if p.returncode:
            self.logger.error("Return code: {}".format(p.returncode))
            for line in stdout_list:
                self.logger.error(line)
            message = "Message: {}".format("\n".join(stdout_list))
            raise ScratchOrgException(message)
Ejemplo n.º 11
0
    def test_flow_run_expected_failure(self):
        org_config = mock.Mock(config={})
        config = CliRuntime(
            config={
                "flows": {
                    "test": {
                        "steps": {
                            1: {
                                "task": "test_task"
                            }
                        }
                    }
                },
                "tasks": {
                    "test_task": {
                        "class_path": "cumulusci.cli.tests.test_cci.DummyTask",
                        "description": "Test Task",
                    }
                },
            },
            load_keychain=False,
        )
        config.get_org = mock.Mock(return_value=("test", org_config))
        DummyTask._run_task = mock.Mock(side_effect=ScratchOrgException("msg"))

        with self.assertRaises(click.ClickException) as e:
            run_click_command(
                cci.flow_run,
                config=config,
                flow_name="test",
                org="test",
                delete_org=False,
                debug=False,
                o=None,
                skip=(),
                no_prompt=True,
            )
            assert "msg" in str(e)
Ejemplo n.º 12
0
    def scratch_info(self):
        if hasattr(self, "_scratch_info"):
            return self._scratch_info

        # Create the org if it hasn't already been created
        if not self.created:
            self.create_org()

        self.logger.info("Getting scratch org info from Salesforce DX")

        username = self.config.get("username")
        if not username:
            raise ScratchOrgException(
                "SFDX claimed to be successful but there was no username "
                "in the output...maybe there was a gack?")

        # Call force:org:display and parse output to get instance_url and
        # access_token
        p = sfdx("force:org:display --json", self.username)

        org_info = None
        stderr_list = [line.strip() for line in p.stderr_text]
        stdout_list = [line.strip() for line in p.stdout_text]

        if p.returncode:
            self.logger.error("Return code: {}".format(p.returncode))
            for line in stderr_list:
                self.logger.error(line)
            for line in stdout_list:
                self.logger.error(line)
            message = "\nstderr:\n{}".format("\n".join(stderr_list))
            message += "\nstdout:\n{}".format("\n".join(stdout_list))
            raise ScratchOrgException(message)

        else:
            try:
                org_info = json.loads("".join(stdout_list))
            except Exception as e:
                raise ScratchOrgException(
                    "Failed to parse json from output. This can happen if "
                    "your scratch org gets deleted.\n  "
                    "Exception: {}\n  Output: {}".format(
                        e.__class__.__name__, "".join(stdout_list)))
            org_id = org_info["result"]["accessToken"].split("!")[0]

        if "password" in org_info["result"] and org_info["result"]["password"]:
            password = org_info["result"]["password"]
        else:
            password = self.config.get("password")

        self._scratch_info = {
            "instance_url": org_info["result"]["instanceUrl"],
            "access_token": org_info["result"]["accessToken"],
            "org_id": org_id,
            "username": org_info["result"]["username"],
            "password": password,
        }

        self.config.update(self._scratch_info)

        self._scratch_info_date = datetime.datetime.utcnow()

        return self._scratch_info
Ejemplo n.º 13
0
    def create_org(self):
        """ Uses sfdx force:org:create to create the org """
        if not self.config_file:
            # FIXME: raise exception
            return
        if not self.scratch_org_type:
            self.config["scratch_org_type"] = "workspace"

        # If the scratch org definition itself contains an `adminEmail` entry,
        # we don't want to override it from our own configuration, which may
        # simply come from the user's Git config.

        with open(self.config_file, "r") as org_def:
            org_def_data = json.load(org_def)
            org_def_has_email = "adminEmail" in org_def_data

        options = {
            "config_file":
            self.config_file,
            "devhub":
            " --targetdevhubusername {}".format(self.devhub)
            if self.devhub else "",
            "namespaced":
            " -n" if not self.namespaced else "",
            "days":
            " --durationdays {}".format(self.days) if self.days else "",
            "alias":
            sarge.shell_format(' -a "{0!s}"', self.sfdx_alias)
            if self.sfdx_alias else "",
            "email":
            sarge.shell_format('adminEmail="{0!s}"', self.email_address)
            if self.email_address and not org_def_has_email else "",
            "default":
            " -s" if self.default else "",
            "extraargs":
            os.environ.get("SFDX_ORG_CREATE_ARGS", ""),
        }

        # This feels a little dirty, but the use cases for extra args would mostly
        # work best with env vars
        command = "force:org:create -f {config_file}{devhub}{namespaced}{days}{alias}{default} {email} {extraargs}".format(
            **options)
        p = sfdx(command, username=None, log_note="Creating scratch org")

        stderr = [line.strip() for line in p.stderr_text]
        stdout = [line.strip() for line in p.stdout_text]

        if p.returncode:
            message = "{}: \n{}\n{}".format(FAILED_TO_CREATE_SCRATCH_ORG,
                                            "\n".join(stdout),
                                            "\n".join(stderr))
            raise ScratchOrgException(message)

        re_obj = re.compile(
            "Successfully created scratch org: (.+), username: (.+)")
        for line in stdout:
            match = re_obj.search(line)
            if match:
                self.config["org_id"] = match.group(1)
                self.config["username"] = match.group(2)
            self.logger.info(line)
        for line in stderr:
            self.logger.error(line)

        self.config["date_created"] = datetime.datetime.now()

        if self.config.get("set_password"):
            self.generate_password()

        # Flag that this org has been created
        self.config["created"] = True
Ejemplo n.º 14
0
    def scratch_info(self):
        if hasattr(self, "_scratch_info"):
            return self._scratch_info

        # Create the org if it hasn't already been created
        if not self.created:
            self.create_org()

        self.logger.info("Getting scratch org info from Salesforce DX")

        # Call force:org:display and parse output to get instance_url and
        # access_token
        command = sarge.shell_format("sfdx force:org:display -u {0} --json",
                                     self.username)
        p = sarge.Command(
            command,
            stderr=sarge.Capture(buffer_size=-1),
            stdout=sarge.Capture(buffer_size=-1),
            shell=True,
        )
        p.run()

        org_info = None
        stderr_list = [line.strip() for line in p.stderr]
        stdout_list = [line.strip() for line in p.stdout]

        if p.returncode:
            self.logger.error("Return code: {}".format(p.returncode))
            for line in stderr_list:
                self.logger.error(line)
            for line in stdout_list:
                self.logger.error(line)
            message = "\nstderr:\n{}".format("\n".join(stderr_list))
            message += "\nstdout:\n{}".format("\n".join(stdout_list))
            raise ScratchOrgException(message)

        else:
            json_txt = "".join(stdout_list)

            try:
                org_info = json.loads("".join(stdout_list))
            except Exception as e:
                raise ScratchOrgException(
                    "Failed to parse json from output. This can happen if "
                    "your scratch org gets deleted.\n  "
                    "Exception: {}\n  Output: {}".format(
                        e.__class__.__name__, "".join(stdout_list)))
            org_id = org_info["result"]["accessToken"].split("!")[0]

        if "password" in org_info["result"] and org_info["result"]["password"]:
            password = org_info["result"]["password"]
        else:
            password = self.config.get("password")

        self._scratch_info = {
            "instance_url": org_info["result"]["instanceUrl"],
            "access_token": org_info["result"]["accessToken"],
            "org_id": org_id,
            "username": org_info["result"]["username"],
            "password": password,
        }

        self.config.update(self._scratch_info)

        self._scratch_info_date = datetime.datetime.utcnow()

        return self._scratch_info
Ejemplo n.º 15
0
    def create_org(self):
        """ Uses sfdx force:org:create to create the org """
        if not self.config_file:
            # FIXME: raise exception
            return
        if not self.scratch_org_type:
            self.config['scratch_org_type'] = 'workspace'

        devhub = ''
        if self.devhub:
            devhub = ' --targetdevhubusername {}'.format(self.devhub)

        # This feels a little dirty, but the use cases for extra args would mostly
        # work best with env vars
        extraargs = os.environ.get('SFDX_ORG_CREATE_ARGS', '')
        command = 'sfdx force:org:create -f {}{} {}'.format(
            self.config_file, devhub, extraargs)
        self.logger.info(
            'Creating scratch org with command {}'.format(command))
        p = sarge.Command(command, stdout=sarge.Capture(buffer_size=-1))
        p.run()

        org_info = None
        re_obj = re.compile(
            'Successfully created scratch org: (.+), username: (.+)')
        stdout = []
        for line in p.stdout:
            match = re_obj.search(line)
            if match:
                self.config['org_id'] = match.group(1)
                self.config['username'] = match.group(2)
            stdout.append(line)
            self.logger.info(line)

        if p.returncode:
            message = 'Failed to create scratch org: \n{}'.format(
                ''.join(stdout))
            raise ScratchOrgException(message)

        # Set a random password so it's available via cci org info
        command = 'sfdx force:user:password:generate -u {}'.format(
            self.username)
        self.logger.info(
            'Generating scratch org user password with command {}'.format(
                command))
        p = sarge.Command(command,
                          stdout=sarge.Capture(buffer_size=-1),
                          stderr=sarge.Capture(buffer_size=-1))
        p.run()

        stdout = []
        for line in p.stdout:
            stdout.append(line)
        stderr = []
        for line in p.stderr:
            stderr.append(line)

        if p.returncode:
            # Don't throw an exception because of failure creating the password, just notify in a log message
            self.logger.warn('Failed to set password: \n{}\n{}'.format(
                '\n'.join(stdout), '\n'.join(stderr)))

        # Flag that this org has been created
        self.config['created'] = True
Ejemplo n.º 16
0
    def scratch_info(self):
        if hasattr(self, '_scratch_info'):
            return self._scratch_info

        # Create the org if it hasn't already been created
        if not self.created:
            self.create_org()

        self.logger.info('Getting scratch org info from Salesforce DX')

        # Call force:org:display and parse output to get instance_url and
        # access_token
        command = 'sfdx force:org:display -u {} --json'.format(self.username)
        p = sarge.Command(
            command,
            stderr=sarge.Capture(buffer_size=-1),
            stdout=sarge.Capture(buffer_size=-1),
        )
        p.run()

        org_info = None
        stderr_list = [line.strip() for line in p.stderr]
        stdout_list = [line.strip() for line in p.stdout]

        if p.returncode:
            self.logger.error('Return code: {}'.format(p.returncode))
            for line in stderr_list:
                self.logger.error(line)
            for line in stdout_list:
                self.logger.error(line)
            message = '\nstderr:\n{}'.format('\n'.join(stderr_list))
            message += '\nstdout:\n{}'.format('\n'.join(stdout_list))
            raise ScratchOrgException(message)

        else:
            json_txt = ''.join(stdout_list)

            try:
                org_info = json.loads(''.join(stdout_list))
            except Exception as e:
                raise ScratchOrgException(
                    'Failed to parse json from output. This can happen if '
                    'your scratch org gets deleted.\n  '
                    'Exception: {}\n  Output: {}'.format(
                        e.__class__.__name__,
                        ''.join(stdout_list),
                    ))
            org_id = org_info['result']['accessToken'].split('!')[0]

        if org_info['result'].get('password', None) is None:
            self.generate_password()
            return self.scratch_info

        self._scratch_info = {
            'instance_url': org_info['result']['instanceUrl'],
            'access_token': org_info['result']['accessToken'],
            'org_id': org_id,
            'username': org_info['result']['username'],
            'password': org_info['result'].get('password', None),
        }

        self.config.update(self._scratch_info)

        self._scratch_info_date = datetime.datetime.utcnow()

        return self._scratch_info
Ejemplo n.º 17
0
    def create_org(self):
        """ Uses sfdx force:org:create to create the org """
        if not self.config_file:
            raise ScratchOrgException(
                f"Scratch org config {self.name} is missing a config_file")
        if not self.scratch_org_type:
            self.config["scratch_org_type"] = "workspace"

        # If the scratch org definition itself contains an `adminEmail` entry,
        # we don't want to override it from our own configuration, which may
        # simply come from the user's Git config.

        with open(self.config_file, "r") as org_def:
            org_def_data = json.load(org_def)
            org_def_has_email = "adminEmail" in org_def_data

        devhub = self._choose_devhub()
        instance = self.instance or os.environ.get("SFDX_SIGNUP_INSTANCE")
        options = {
            "config_file":
            self.config_file,
            "devhub":
            f" --targetdevhubusername {devhub}" if devhub else "",
            "namespaced":
            " -n" if not self.namespaced else "",
            "days":
            f" --durationdays {self.days}" if self.days else "",
            "wait":
            " -w 120",
            "alias":
            sarge.shell_format(' -a "{0!s}"', self.sfdx_alias)
            if self.sfdx_alias else "",
            "email":
            sarge.shell_format(' adminEmail="{0!s}"', self.email_address)
            if self.email_address and not org_def_has_email else "",
            "default":
            " -s" if self.default else "",
            "instance":
            f" instance={instance}" if instance else "",
            "extraargs":
            os.environ.get("SFDX_ORG_CREATE_ARGS", ""),
        }

        # This feels a little dirty, but the use cases for extra args would mostly
        # work best with env vars
        command = "force:org:create -f {config_file}{devhub}{namespaced}{days}{alias}{default}{wait}{email}{instance} {extraargs}".format(
            **options)
        p = sfdx(command, username=None, log_note="Creating scratch org")

        stderr = [line.strip() for line in p.stderr_text]
        stdout = [line.strip() for line in p.stdout_text]

        if p.returncode:
            message = f"{FAILED_TO_CREATE_SCRATCH_ORG}: \n{nl.join(stdout)}\n{nl.join(stderr)}"
            raise ScratchOrgException(message)

        re_obj = re.compile(
            "Successfully created scratch org: (.+), username: (.+)")
        username = None
        for line in stdout:
            match = re_obj.search(line)
            if match:
                self.config["org_id"] = match.group(1)
                self.config["username"] = username = match.group(2)
            self.logger.info(line)
        for line in stderr:
            self.logger.error(line)

        if username is None:
            raise ScratchOrgException(
                "SFDX claimed to be successful but there was no username "
                "in the output...maybe there was a gack?")

        self.config["date_created"] = datetime.datetime.utcnow()

        if self.config.get("set_password"):
            self.generate_password()

        # Flag that this org has been created
        self.config["created"] = True
Ejemplo n.º 18
0
    def scratch_info(self):
        if hasattr(self, '_scratch_info'):
            return self._scratch_info

        # Create the org if it hasn't already been created
        if not self.created:
            self.create_org()

        self.logger.info('Getting scratch org info from Salesforce DX')

        # Call force:org:open and parse output to get instance_url and access_token
        command = 'heroku force:org:open -d -u {}'.format(self.username)
        p = sarge.Command(command, stdout=sarge.Capture(buffer_size=-1))
        p.run()

        org_info = None
        stdout_list = []
        for line in p.stdout:
            if line.startswith('Access org'):
                org_info = line.strip()
            stdout_list.append(line.strip())

        if p.returncode:
            message = 'Return code: {}\nstdout: {}\nstderr: {}'.format(
                p.returncode,
                '\n'.join(stdout_list),
                p.stderr,
            )
            self.logger.error(message)
            raise ScratchOrgException(message)

        if not org_info:
            message = 'Did not find org info in command output:\n{}'.format(
                p.stdout)
            self.logger.error(message)
            raise ScratchOrgException(message)

        # OrgID is the third word of the output
        org_id = org_info.split(' ')[2]

        # Username is the sixth word of the output
        username = org_info.split(' ')[5]

        info_parts = org_info.split('following URL: ')
        if len(info_parts) == 1:
            message = 'Did not find org info in command output:\n{}'.format(
                p.stdout)
            self.logger.error(message)
            raise ScratchOrgException(message)

        instance_url, access_token = info_parts[1].split(
            '/secur/frontdoor.jsp?sid=')
        self._scratch_info = {
            'instance_url': instance_url,
            'access_token': access_token,
            'org_id': org_id,
            'username': username,
        }

        self._scratch_info_date = datetime.datetime.now()

        return self._scratch_info