def __init__(self, config): deployConfig = jobs_configure.init_config(config) self.deployConfig = deployConfig self.alarm_interface = AlarmInterface( deployConfig['defaultConfig']['region']) self.iot_interface = IotInterface( deployConfig['defaultConfig']['region']) self.clean_up(deployConfig)
def __init__(self): thingArnList, deviceCount, thingNameList = parse_thingList(thingListFilePath) if deviceCount < 1: raise Exception('thing list should not be empty') self.thingArnList = thingArnList self.deviceCount = deviceCount self.thingNameList = thingNameList self.thingListUpdateTime = 0 self.iot_interface = IotInterface(region)
def setUp(self): self.iot_interface = IotInterface(REGION) self.iot_interface.client.create_stream = Mock(return_value=None) self.iot_interface.client.create_job = Mock(return_value=None) self.iot_interface.client.describe_job = Mock( return_value=TEST_EXPTECTED_DSB_JOB_RSP) self.iot_interface.client.describe_job_execution = Mock( return_value=TEST_EXPTECTED_DSB_JOB_EXEC_RSP) self.iot_interface.client.describe_stream = Mock( return_value=TEST_EXPTECTED_DSB_STREAM_RSP) self.iot_interface.client.cancel_job = Mock(return_value=None) self.iot_interface.client.delete_job = Mock(return_value=None) self.iot_interface.client.delete_stream = Mock(return_value=None)
class ota_deployment_tool(): def __init__(self, config): deployConfig = jobs_configure.init_config(config) self.deployConfig = deployConfig self.alarm_interface = AlarmInterface( deployConfig['defaultConfig']['region']) self.iot_interface = IotInterface( deployConfig['defaultConfig']['region']) self.clean_up(deployConfig) def clean_up(self, deployConfig): cleanUpCfg = deployConfig['defaultConfig']['cleanUpCfg'] streamId = deployConfig['defaultConfig']['streamId'] jobId = deployConfig['defaultConfig']['jobId'] if cleanUpCfg: logging.info('deleting old job') self.iot_interface.delete_job(jobId) logging.info('deleting old stream') self.iot_interface.delete_stream(streamId) logging.info('deleting old alarms') if 'alarmConfigs' in deployConfig: self.alarm_interface.delete_alarms( deployConfig['alarmConfigs']) else: logging.info('skipping clean_up due to cleanUpCfg set to false') def schedule_jobs(self, deployConfig): logging.info('creating new stream') streamId = deployConfig['defaultConfig']['streamId'] fileId = deployConfig['defaultConfig']['fileId'] bucket = deployConfig['defaultConfig']['bucket'] binFileKey = deployConfig['defaultConfig']['binFileKey'] roleArn = deployConfig['defaultConfig']['roleArn'] jobId = deployConfig['defaultConfig']['jobId'] thingArnList = deployConfig['defaultConfig']['thingArnList'] jobDocumentSrc = deployConfig['defaultConfig']['jobDocumentSrc'] deviceCount = deployConfig['defaultConfig']['deviceCount'] defaultDelay = deployConfig['defaultConfig']['defaultDelay'] rounds = deployConfig['defaultConfig']['rounds'] if 'alarmConfigs' in deployConfig: status, err = self.alarm_interface.create_alarms( deployConfig['alarmConfigs']) if not status: logging.error(err) return status, err = self.iot_interface.create_stream(streamId, fileId, bucket, binFileKey, roleArn) if not status: logging.error(err) return status, err = self.iot_interface.create_job(deployConfig) if not status: logging.error(err) return job_complete_counter = 0 while job_complete_counter < rounds: job_dsb, err = self.iot_interface.get_job_info(jobId) status = job_dsb.get('status') if err: logging.error(err) return if status == 'COMPLETED': numberOfSucceededThings = job_dsb.get( 'jobProcessDetails', {}).get('numberOfSucceededThings') if numberOfSucceededThings == deviceCount: job_complete_counter = job_complete_counter + 1 logging.info( 'deviceCount: %d matches numberOfSucceededThings: %d job completed with success', deviceCount, numberOfSucceededThings) logging.info( 'jobId : %s completed , job_complete_counter: %d', jobId, job_complete_counter) logging.info('jobId %s completed', jobId) self.clean_up(deployConfig) if job_complete_counter < rounds: logging.info('creating new stream') status, err = self.iot_interface.create_stream( streamId, fileId, bucket, binFileKey, roleArn) if not status: logging.error(err) return logging.info('creating new job, thingArnList: %s', thingArnList) status, err = self.iot_interface.create_job( deployConfig) if not status: logging.error(err) return else: logging.info( 'deviceCount: %d does not matches numberOfSucceededThings: %d job completed with failure', deviceCount, numberOfSucceededThings) break elif status == 'IN_PROGRESS': logging.info('jobId: %s IN_PROGRESS: ', jobId) elif status == 'CANCELED' or status == 'DELETION_IN_PROGRESS' or status == 'DELETION_IN_PROGRESS': logging.info('unexpected failure with status: %s', status) break else: logging.info('unexpected status: %s', status) break time.sleep(defaultDelay)
class IotInterfaceTests(unittest.TestCase): def setUp(self): self.iot_interface = IotInterface(REGION) self.iot_interface.client.create_stream = Mock(return_value=None) self.iot_interface.client.create_job = Mock(return_value=None) self.iot_interface.client.describe_job = Mock( return_value=TEST_EXPTECTED_DSB_JOB_RSP) self.iot_interface.client.describe_job_execution = Mock( return_value=TEST_EXPTECTED_DSB_JOB_EXEC_RSP) self.iot_interface.client.describe_stream = Mock( return_value=TEST_EXPTECTED_DSB_STREAM_RSP) self.iot_interface.client.cancel_job = Mock(return_value=None) self.iot_interface.client.delete_job = Mock(return_value=None) self.iot_interface.client.delete_stream = Mock(return_value=None) def test_create_stream(self): self.iot_interface.client.create_stream = Mock( return_value=TEST_EXPTECTED_DSB_JOB_RSP) # Given these inputs and expected outputs createStreamArgs = { 'streamId': STREAM_ID, 'fileId': FILE_ID, 'bucket': BUCKET, 'key': KEY, 'role_arn': ROLE_ARN } iotCreateStreamArgs = { 'streamId': STREAM_ID, 'description': 'testing', 'files': [{ "fileId": FILE_ID, "s3Location": { "bucket": BUCKET, "key": KEY } }], 'roleArn': ROLE_ARN } # When this happens status, err = self.iot_interface.create_stream(**createStreamArgs) # Expect these behaviors self.assertTrue(status) self.iot_interface.client.create_stream.assert_called_with( **iotCreateStreamArgs) def test_create_stream_exception(self): self.iot_interface.client.create_stream = Mock( side_effect=ClientError({}, 'test')) # Given these inputs and expected outputs createStreamArgs = { 'streamId': STREAM_ID, 'fileId': FILE_ID, 'bucket': BUCKET, 'key': KEY, 'role_arn': ROLE_ARN } iotCreateStreamArgs = { 'streamId': STREAM_ID, 'description': 'testing', 'files': [{ "fileId": FILE_ID, "s3Location": { "bucket": BUCKET, "key": KEY } }], 'roleArn': ROLE_ARN } # When this happens status, err = self.iot_interface.create_stream(**createStreamArgs) # Expect these behaviors self.assertFalse(status) self.iot_interface.client.create_stream.assert_called_with( **iotCreateStreamArgs) def test_create_job(self): # Given these inputs and expected outputs deployConfig = {} deployConfig['defaultConfig'] = configMap['defaultConfig'] kwargs = { 'jobId': TEST_DEFAULT_CONFIG['jobId'], 'targets': TEST_DEFAULT_CONFIG['thingArnList'], 'documentSource': TEST_DEFAULT_CONFIG['jobDocumentSrc'], 'targetSelection': TEST_DEFAULT_CONFIG['targetSelection'] } configList = [ 'presignedUrlConfig', 'jobExecutionsRolloutConfig', 'abortConfig', 'timeoutConfig' ] # When this happens status, err = self.iot_interface.create_job(deployConfig) # Expect these behaviors self.assertTrue(status) self.iot_interface.client.create_job.assert_called_with(**kwargs) # add nore configs into test for configName in configList: with self.subTest(configName=configName): deployConfig[configName] = configMap[configName] kwargs[configName] = configMap[configName] # When this happens status, err = self.iot_interface.create_job(deployConfig) # Expect these behaviors self.assertTrue(status) assert not err self.iot_interface.client.create_job.assert_called_with( **kwargs) def test_create_job_exception(self): self.iot_interface.client.create_job = Mock( side_effect=ClientError({}, 'test')) # Given these inputs and expected outputs deployConfig = {} deployConfig['defaultConfig'] = configMap['defaultConfig'] kwargs = { 'jobId': TEST_DEFAULT_CONFIG['jobId'], 'targets': TEST_DEFAULT_CONFIG['thingArnList'], 'documentSource': TEST_DEFAULT_CONFIG['jobDocumentSrc'], 'targetSelection': TEST_DEFAULT_CONFIG['targetSelection'] } configList = [ 'presignedUrlConfig', 'jobExecutionsRolloutConfig', 'abortConfig', 'timeoutConfig' ] for configName in configList: deployConfig[configName] = configMap[configName] kwargs[configName] = configMap[configName] # When this happens status, err = self.iot_interface.create_job(deployConfig) # Expect these behaviors self.assertFalse(status) self.iot_interface.client.create_job.assert_called_with(**kwargs) def test_get_job_info(self): # Given these inputs and expected outputs jobId = JOD_ID # When this happens job_dsb, err = self.iot_interface.get_job_info(jobId=jobId) # Expect these behaviors assert job_dsb == TEST_EXPTECTED_DSB_JOB_RSP['job'] assert not err self.iot_interface.client.describe_job.assert_called_with(jobId=jobId) def test_get_job_info_exception(self): self.iot_interface.client.describe_job = Mock( side_effect=ClientError({}, 'test')) # Given these inputs and expected outputs jobId = JOD_ID # When this happens job_dsb, err = self.iot_interface.get_job_info(jobId=jobId) # Expect these behaviors assert job_dsb is None self.iot_interface.client.describe_job.assert_called_with(jobId=jobId) def test_get_job_exe_info(self): # Given these inputs and expected outputs jobId = JOD_ID thingName = THING_NAME # When this happens job_exe_dsb, err = self.iot_interface.get_job_exe_info( jobId=jobId, thingName=thingName) # Expect these behaviors assert job_exe_dsb == TEST_EXPTECTED_DSB_JOB_EXEC_RSP['execution'] assert not err self.iot_interface.client.describe_job_execution.assert_called_with( jobId=jobId, thingName=thingName) def test_get_job_exe_info_exception(self): self.iot_interface.client.describe_job_execution = Mock( side_effect=ClientError({}, 'test')) # Given these inputs and expected outputs jobId = JOD_ID thingName = THING_NAME # When this happens job_exe_dsb, err = self.iot_interface.get_job_exe_info( jobId=jobId, thingName=thingName) # Expect these behaviors assert job_exe_dsb is None self.iot_interface.client.describe_job_execution.assert_called_with( jobId=jobId, thingName=thingName) def test_cancel_job(self): self.iot_interface.client.describe_job = Mock(side_effect=[ TEST_EXPTECTED_DSB_JOB_RSP_IN_PROGRESS, TEST_EXPTECTED_DSB_JOB_RSP_IN_PROGRESS, TEST_EXPTECTED_DSB_JOB_RSP ]) # Given these inputs and expected outputs jobId = JOD_ID expectedCalls = [ call(jobId=jobId), call(jobId=jobId), call(jobId=jobId) ] # When this happens status, err = self.iot_interface.cancel_job(jobId=jobId) # Expect these behaviors self.assertTrue(status) assert not err self.iot_interface.client.cancel_job.assert_called_with(jobId=jobId) self.iot_interface.client.describe_job.assert_has_calls(expectedCalls) def test_cancel_job_exception(self): self.iot_interface.client.cancel_job = Mock( side_effect=ClientError({}, 'test')) # Given these inputs and expected outputs jobId = JOD_ID # When this happens status, _ = self.iot_interface.cancel_job(jobId=jobId) # Expect these behaviors self.assertFalse(status) self.iot_interface.client.cancel_job.assert_called_with(jobId=jobId) def test_job_is_deleting_while_cancel_job_is_called(self): self.iot_interface.client.describe_job = Mock( side_effect=ClientError({}, 'test')) # Given these inputs and expected outputs jobId = JOD_ID # When this happens status, err = self.iot_interface.cancel_job(jobId=jobId) # Expect these behaviors self.assertTrue(status) assert not err self.iot_interface.client.cancel_job.assert_called_with(jobId=jobId) self.iot_interface.client.describe_job.assert_called_once_with( jobId=jobId) def test_delete_job(self): self.iot_interface.client.describe_job = Mock(side_effect=[ TEST_EXPTECTED_DSB_JOB_RSP, TEST_EXPTECTED_DSB_JOB_RSP, ClientError({}, 'test') ]) # Given these inputs and expected outputs jobId = JOD_ID expectedCalls = [ call(jobId=jobId), call(jobId=jobId), call(jobId=jobId) ] # When this happens status, err = self.iot_interface.delete_job(jobId=jobId) # Expect these behaviors self.assertTrue(status) assert not err self.iot_interface.client.delete_job.assert_called_with(jobId=jobId, force=True) self.iot_interface.client.describe_job.assert_has_calls(expectedCalls) def test_delete_job_exception(self): self.iot_interface.client.delete_job = Mock( side_effect=ClientError({}, 'test')) # Given these inputs and expected outputs jobId = JOD_ID # When this happens status, _ = self.iot_interface.delete_job(jobId=jobId) # Expect these behaviors self.assertFalse(status) self.iot_interface.client.delete_job.assert_called_with(jobId=jobId, force=True) def test_delete_stream(self): self.iot_interface.client.describe_stream = Mock(side_effect=[ TEST_EXPTECTED_DSB_STREAM_RSP, TEST_EXPTECTED_DSB_STREAM_RSP, ClientError({}, 'test') ]) # Given these inputs and expected outputs streamId = STREAM_ID expectedCalls = [ call(streamId=streamId), call(streamId=streamId), call(streamId=streamId) ] # When this happens status, err = self.iot_interface.delete_stream(streamId=streamId) # Expect these behaviors self.assertTrue(status) assert not err self.iot_interface.client.delete_stream.assert_called_with( streamId=streamId) self.iot_interface.client.describe_stream.assert_has_calls( expectedCalls) def test_delete_stream_exception(self): self.iot_interface.client.delete_stream = Mock( side_effect=ClientError({}, 'test')) # Given these inputs and expected outputs streamId = STREAM_ID # When this happens status, _ = self.iot_interface.delete_stream(streamId=streamId) # Expect these behaviors self.assertFalse(status) self.iot_interface.client.delete_stream.assert_called_with( streamId=streamId)
class monitor_tool(): def __init__(self): thingArnList, deviceCount, thingNameList = parse_thingList(thingListFilePath) if deviceCount < 1: raise Exception('thing list should not be empty') self.thingArnList = thingArnList self.deviceCount = deviceCount self.thingNameList = thingNameList self.thingListUpdateTime = 0 self.iot_interface = IotInterface(region) def monitor_start(self): isParseList = False job_complete_counter = 0 while True: fileUpdateTime = path.getmtime(thingListFilePath) if fileUpdateTime > self.thingListUpdateTime or isParseList is True: thingArnList, deviceCount, thingNameList = parse_thingList(thingListFilePath) self.thingListUpdateTime = path.getmtime(thingListFilePath) isParseList = False if len(thingArnList) < 1 or deviceCount < 1: raise Exception('thing list should not be empty') if deviceCount > self.deviceCount: self.thingArnList = thingArnList self.deviceCount = deviceCount self.thingNameList = thingNameList job_dsb, err = self.iot_interface.get_job_info(jobId) if job_dsb: status = job_dsb.get('status') else: continue if err: logging.error(err) return if status == 'COMPLETED': isParseList = True numberOfSucceededThings = job_dsb.get('jobProcessDetails', {}).get('numberOfSucceededThings') if numberOfSucceededThings >= self.deviceCount: job_complete_counter = job_complete_counter + 1 logging.info('deviceCount: %d matches numberOfSucceededThings: %d job completed with success', self.deviceCount, numberOfSucceededThings) logging.info('jobId : %s completed , job_complete_counter: %d', jobId, job_complete_counter) logging.info('jobId %s completed', jobId) else: logging.info('deviceCount: %d does not matches numberOfSucceededThings: %d job completed with failure', self.deviceCount, numberOfSucceededThings) break elif status == 'IN_PROGRESS': logging.info('jobId %s IN_PROGRESS', jobId) thingNameList = self.thingNameList for thingName in thingNameList: job_exe_dsb, err = self.iot_interface.get_job_exe_info(jobId, thingName) if job_exe_dsb: thing_status = job_exe_dsb.get('status') if thing_status == 'SUCCEEDED': self.thingNameList.remove(thingName) else: logging.info('thing name: %s status: %s statusDetails %s: ', thingName, thing_status, job_exe_dsb['statusDetails']) elif status == 'CANCELED' or status == 'DELETION_IN_PROGRESS' or status == 'DELETION_IN_PROGRESS': logging.info('unexpected failure with status: %s', status) isParseList = True else: logging.info('unexpected status: %s', status) break time.sleep(defaultDelay)