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
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
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
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
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)
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)
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)
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
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)
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)
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
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
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
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
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
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
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