def _delete_dir(dir_path, dir_type): try: EdgeUtils.delete_dir(dir_path) except OSError as ex: msg = 'Error deleting {0} directory {1}'.format(dir_type, dir_path) log.error(msg) raise edgectl.errors.EdgeFileAccessError(msg, dir_path)
def _create_dir(dir_path, dir_type): try: EdgeUtils.mkdir_if_needed(dir_path) except OSError as ex: msg = 'Error creating {0} directory {1}'.format(dir_type, dir_path) log.error(msg) raise edgectl.errors.EdgeFileAccessError(msg, dir_path)
def _insert_file_in_volume_mount(self, volume_name, host_src_file, volume_dest_file_name): """ Use volume introspection to place files into the host mountpoint in order to work around issues with Docker filesystem operations on Windows Hyper-V containers and container mountpoints """ try: volume_name = (volume_name.split('/'))[-1] volume_info = self._client.api.inspect_volume(volume_name) EdgeUtils.copy_files( host_src_file.replace('\\\\', '\\'), os.path.join(volume_info['Mountpoint'].replace('\\\\', '\\'), volume_dest_file_name)) except docker.errors.APIError as docker_ex: msg = 'Docker volume inspect failed for: {0}'.format(volume_name) logging.error(msg) print(docker_ex) raise edgectl.errors.EdgeDeploymentError(msg, docker_ex) except (OSError, IOError) as ex_os: msg = 'File IO error seen copying files to volume: {0}. ' \ 'Errno: {1}, Error {2}'.format(volume_name, str(ex_os.errno), ex_os.strerror) logging.error(msg) print(ex_os) raise edgectl.errors.EdgeDeploymentError(msg, ex_os)
def test_get_hostname_raises_ioerror_when_getfqdn_raises_ioerror( self, mock_hostname): """ Tests invocation of API get_hostname raises IOError when getfqdn raises IOError""" # arrange mock_hostname.side_effect = IOError('getfqdn IO error') # act, assert with self.assertRaises(IOError): EdgeUtils.get_hostname()
def test_mkdir_if_needed_when_dir_does_not_exist(self, mock_mkdirs): """ Test a valid invocation of API mkdir_if_needed when dir to be made does not exist """ # arrange dir_path = 'blah' # act EdgeUtils.mkdir_if_needed(dir_path) # assert mock_mkdirs.assert_called_with(dir_path)
def test_copy_files_raises_oserror_when_cop2_raises_oserror( self, mock_copy): """ Tests invocation of API copy_files raises OSError when copy2 raises OSError""" # arrange src_path = 'src' dest_path = 'dest' mock_copy.side_effect = OSError('copy2 OS error') # act, assert with self.assertRaises(OSError): EdgeUtils.copy_files(src_path, dest_path)
def test_copy_files_valid(self, mock_copy): """ Test a valid invocation of API copy_files """ # arrange src_path = 'src' dest_path = 'dest' # act EdgeUtils.copy_files(src_path, dest_path) # assert mock_copy.assert_called_with(src_path, dest_path)
def test_delete_dir_raises_oserror_when_rmtree_fails( self, mock_exists, mock_rmtree): """ Tests invocation of API delete_dir raises OSError when rmtree raises OSError""" # arrange dir_path = 'blah' mock_exists.return_value = True mock_rmtree.side_effect = OSError('rmtree error') # act, assert with self.assertRaises(OSError): EdgeUtils.delete_dir(dir_path)
def test_mkdir_if_needed_when_dir_exists(self, mock_mkdirs): """ Test a valid invocation of API mkdir_if_needed when dir to be made already exists """ # arrange dir_path = 'blah' mock_mkdirs.side_effect = OSError(errno.EEXIST, 'Directory exists.') # act EdgeUtils.mkdir_if_needed(dir_path) # assert mock_mkdirs.assert_called_with(dir_path)
def test_mkdir_if_needed_raises_oserror_when_mkdir_fails( self, mock_mkdirs): """ Tests invocation of API mkdir_if_needed raises OSError when makedirs raises OSError""" # arrange dir_path = 'blah' mock_mkdirs.side_effect = OSError(errno.EACCES, 'Directory permission error') # act, assert with self.assertRaises(OSError): EdgeUtils.mkdir_if_needed(dir_path)
def test_delete_dir_execute_onerror_callback(self, mock_chmod, mock_unlink): """ Test rmtree onerror callback invocation""" # arrange dir_path = 'blah' ignored = 0 # act EdgeUtils._remove_readonly_callback(ignored, dir_path, ignored) # assert mock_chmod.assert_called_with(dir_path, stat.S_IWRITE) mock_unlink.assert_called_with(dir_path)
def test_delete_dir_when_dir_does_not_exist(self, mock_exists, mock_rmtree): """ Test a valid invocation of API delete_dir when dir to be deleted does not exist""" # arrange dir_path = 'blah' mock_exists.return_value = False # act EdgeUtils.delete_dir(dir_path) # assert mock_exists.assert_called_with(dir_path) mock_rmtree.assert_not_called()
def test_delete_dir_when_dir_exists(self, mock_exists, mock_rmtree): """ Test a valid invocation of API delete_dir when dir to be deleted exists""" # arrange dir_path = 'blah' mock_exists.return_value = True # act EdgeUtils.delete_dir(dir_path) # assert mock_exists.assert_called_with(dir_path) mock_rmtree.assert_called_with( dir_path, onerror=EdgeUtils._remove_readonly_callback)
def _prompt_password(cert_type, bypass_options, config_file_setting): options_str = '' options_len = len(bypass_options) index = 0 for option in bypass_options: options_str += option if index < options_len - 1: options_str += ' or ' else: options_str += '.' index += 1 config_file_setting = '"security.certificates.<option>.' + config_file_setting + '"' print('\n', '\n********************************************************************************' '\nPlease enter a passphrase for the', cert_type, 'private key.', '\n\nTo prevent this prompt from appearing, input the required passphrase', '\nor generate the private key without a passphrase.', '\n\n When using the command line options to setup the IoT Edge runtime:', '\n - Enter the passphrase via the command line options:', '\n ', options_str, '\n - When opting not to use a passphrase, use command line option:', '\n --auto-cert-gen-force-no-passwords.', '\n\n When using the --config-file to setup the runtime:', '\n - Set the input passphrase file via JSON configuration item:', '\n ', config_file_setting, '\n - When opting not to use a passphrase, set JSON configuration item:', '\n "security.certificates.<option>.forceNoPasswords" to true.' '\n********************************************************************************') return EdgeUtils.prompt_password(cert_type, EdgeCertUtil.MIN_PASSPHRASE_LENGTH, EdgeCertUtil.MAX_PASSPHRASE_LENGTH)
def test_sanitize_registry(self): """ Test a valid invocation of API sanitize_registry_data """ result = EdgeUtils.sanitize_registry_data('test_address', 'test_username', 'test_password') pattern = re.compile( r'^Address: test_address, Username: test_username, Password:[\*]+$' ) self.assertTrue(pattern.match(result))
def test_sanitize_connection_string(self): """ Test a valid invocation of API sanitize_connection_string """ result = EdgeUtils.sanitize_connection_string( 'HostName=aa;DeviceId=bb;SharedAccessKey=cc') pattern = re.compile( r'^HostName=aa;DeviceId=bb;SharedAccessKey=[\*]+$') self.assertTrue(pattern.match(result)) result = EdgeUtils.sanitize_connection_string( 'HostName=aa;DeviceId=bb;sharedaccesskey=cc') pattern = re.compile( r'^HostName=aa;DeviceId=bb;sharedaccesskey=[\*]+$') self.assertTrue(pattern.match(result)) result = EdgeUtils.sanitize_connection_string( 'HostName=aaa;DeviceId=bbb') pattern = re.compile(r'^HostName=aaa;DeviceId=bbb+$') self.assertTrue(pattern.match(result))
def test_get_hostname_valid(self, mock_hostname): """ Test a valid invocation of API get_hostname """ # arrange hostname = 'test_hostname' mock_hostname.return_value = hostname # act result = EdgeUtils.get_hostname() # assert mock_hostname.assert_called_with() self.assertEqual(hostname, result)
def __str__(self): result = 'Schema Version:\t\t' + self.schema_version + '\n' conn_str = EdgeUtils.sanitize_connection_string(self.connection_string) result += 'Connection String:\t' + conn_str + '\n' result += 'Config Directory:\t' + self.config_dir + '\n' result += 'Home Directory:\t\t' + self.home_dir + '\n' result += 'Hostname:\t\t' + self.hostname + '\n' result += 'Log Level:\t\t' + self.log_level + '\n' if self.certificate_config: result += str(self.certificate_config) if self.deployment_config: result += str(self.deployment_config) return result
def test_check_if_file_exists_returns_true(self, mock_exists, mock_isfile): """ Test a valid invocation of API check_if_file_exists """ # arrange #1 file_path = 'blah' mock_exists.return_value = True mock_isfile.return_value = True # act result = EdgeUtils.check_if_file_exists(file_path) # assert mock_exists.assert_called_with(file_path) mock_isfile.assert_called_with(file_path) self.assertTrue(result)
def test_check_if_dir_exists_returns_true(self, mock_exists, mock_isdir): """ Test a valid invocation of API check_if_directory_exists """ # arrange #1 dir_path = 'blah' mock_exists.return_value = True mock_isdir.return_value = True # act result = EdgeUtils.check_if_directory_exists(dir_path) # assert mock_exists.assert_called_with(dir_path) mock_isdir.assert_called_with(dir_path) self.assertTrue(result)
def test_check_if_dir_exists_returns_false_path_is_none( self, mock_exists, mock_isdir): """ Test a valid invocation of API check_if_directory_exists """ # arrange dir_path = None # act result = EdgeUtils.check_if_directory_exists(dir_path) # assert mock_exists.assert_not_called() mock_isdir.assert_not_called() self.assertFalse(result)
def __str__(self): result = 'Deployment Type:\t' + self.deployment_type + '\n' result += 'Docker Engine URI:\t' + self.uri + '\n' result += 'Edge Agent Image:\t' + self.edge_image + '\n' result += 'Registries:' + '\n' for registry in self.registries: result += '\t\t\t' reg_str = EdgeUtils.sanitize_registry_data(registry[EC.REGISTRY_ADDRESS_KEY], registry[EC.REGISTRY_USERNAME_KEY], registry[EC.REGISTRY_PASSWORD_KEY]) result += reg_str + '\n' result += 'Logging Driver:\t\t' + self.logging_driver + '\n' options = self.logging_options for key in options: result += '\t\t\t' + str(key) + ': ' + options[key] + '\n' return result
def _set_dca_file(self, kwargs, file_key): """Helper method to store one of the many device CA certificate and private key files required to operate the Edge as a gateway. Args: kwargs (dict): User supplied KW args file_key (str): Key to retrieve and store the file Raises: ValueError if retrieved file path is None or if the file does not exist. """ file_path = kwargs[file_key] if EdgeUtils.check_if_file_exists(file_path): self._dca_files_dict[file_key] = file_path else: raise ValueError('Invalid {0} file: {1}'.format( file_key, file_path))
def _parse_login_options(self, args): is_valid = self._parse_command_options_common(args) if is_valid: try: self.edge_config.deployment_config.add_registry( args.address, args.username, args.password) except ValueError as ex: log.error('%s', str(ex)) msg = EdgeUtils.sanitize_registry_data(args.address, args.username, args.password) log.error('Error setting login data: [%s].', msg) raise edgectl.errors.EdgeError('Error setting login data', ex) EdgeHostPlatform.install_edge_by_json_data(self.edge_config, False) config_file = EdgeHostPlatform.get_host_config_file_path() log.info('The runtime configuration file %s was updated with' \ ' the credentials for registry: %s', config_file, args.address) return is_valid
def parse(self, ignored=None): args = self._input_args try: defaults_json = EdgeDefault.get_default_settings_json() cs = args.connection_string if cs is None or len(cs) == 0: raise ValueError('Please specify the device connection string' \ ' using the --connection-string option') config = EdgeHostConfig() config.schema_version = defaults_json[EC.SCHEMA_KEY] config.connection_string = cs cfg_src = EdgeConfigDirInputSource.USER_PROVIDED cfg_dir_opt = EdgeHostPlatform.choose_platform_config_dir(args.edge_config_dir, cfg_src) config.config_dir = cfg_dir_opt[0] config.config_dir_source = cfg_dir_opt[1] home_dir = args.edge_home_dir if home_dir is None: home_dir = EdgeHostPlatform.get_home_dir() config.home_dir = home_dir hostname = args.edge_hostname if hostname is None: hostname = EdgeUtils.get_hostname() config.hostname = hostname log_level = args.runtime_log_level if log_level is None: log_level = EdgeDefault.get_default_runtime_log_level() config.log_level = log_level upstream_protocol = args.upstream_protocol if upstream_protocol is None: config.upstream_protocol = EdgeUpstreamProtocol.NONE else: config.upstream_protocol = upstream_protocol deploy_cfg = None if self._deployment_type == EC.DEPLOYMENT_DOCKER: deploy_cfg = EdgeDeploymentConfigDocker() docker_deploy_data = \ defaults_json[EC.DEPLOYMENT_KEY][EC.DEPLOYMENT_DOCKER_KEY] registries = args.docker_registries if registries is None: registries = docker_deploy_data[EC.REGISTRIES_KEY] for registry in registries: deploy_cfg.add_registry(registry[EC.REGISTRY_ADDRESS_KEY], registry[EC.REGISTRY_USERNAME_KEY], registry[EC.REGISTRY_PASSWORD_KEY]) else: idx = 0 address = '' username = '' password = '' for item in registries: if idx == 0: address = item elif idx == 1: username = item else: password = item deploy_cfg.add_registry(address, username, password) idx = (idx + 1) % 3 image = args.image if image is None: image = docker_deploy_data[EC.EDGE_RUNTIME_IMAGE_KEY] deploy_cfg.edge_image = image uri = args.docker_uri if uri is None: uri = EdgeHostPlatform.get_docker_uri() deploy_cfg.uri = uri docker_log_cfg = docker_deploy_data[EC.DOCKER_LOGGING_OPTS_KEY] deploy_cfg.logging_driver = \ docker_log_cfg[EC.DOCKER_LOGGING_DRIVER_KEY] driver_log_opts = \ docker_log_cfg[EC.DOCKER_LOGGING_DRIVER_OPTS_KEY] for opt_key, opt_val in list(driver_log_opts.items()): deploy_cfg.add_logging_option(opt_key, opt_val) if deploy_cfg is None: raise ValueError('Unsupported deployment type: %s', self._deployment_type) config.deployment_config = deploy_cfg subj_dict = {} if args.country: subj_dict[EC.SUBJECT_COUNTRY_KEY] = args.country if args.state: subj_dict[EC.SUBJECT_STATE_KEY] = args.state if args.locality: subj_dict[EC.SUBJECT_LOCALITY_KEY] = args.locality if args.organization: subj_dict[EC.SUBJECT_ORGANIZATION_KEY] = args.organization if args.organization_unit: subj_dict[EC.SUBJECT_ORGANIZATION_UNIT_KEY] = args.organization_unit if args.common_name: subj_dict[EC.SUBJECT_COMMON_NAME_KEY] = args.common_name cert_config = EdgeCertConfig() cert_config.set_options(args.auto_cert_gen_force_no_passwords, subj_dict, owner_ca_cert_file=args.owner_ca_cert_file, device_ca_cert_file=args.device_ca_cert_file, device_ca_chain_cert_file=args.device_ca_chain_cert_file, device_ca_private_key_file=args.device_ca_private_key_file, device_ca_passphrase=args.device_ca_passphrase, device_ca_passphrase_file=args.device_ca_passphrase_file, agent_ca_passphrase=args.agent_ca_passphrase, agent_ca_passphrase_file=args.agent_ca_passphrase_file) config.certificate_config = cert_config return config except ValueError as ex_value: log.error('Error parsing user input data: %s.', str(ex_value)) raise edgectl.errors.EdgeValueError('Error parsing user input data')
def test_prompt_password(self, mock_getpass): """ Test a valid invocation of API prompt_password """ valid_pass = '******' mock_getpass.return_value = valid_pass result = EdgeUtils.prompt_password('test password', 5, 8) self.assertTrue(valid_pass, result)