def _execute_op(self, op): if isinstance(op, pipeline_ops_provisioning.SetSymmetricKeySecurityClientOperation): security_client = op.security_client operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_provisioning.SetProvisioningClientConnectionArgsOperation( provisioning_host=security_client.provisioning_host, registration_id=security_client.registration_id, id_scope=security_client.id_scope, sas_token=security_client.get_current_sas_token(), ), ) elif isinstance(op, pipeline_ops_provisioning.SetX509SecurityClientOperation): security_client = op.security_client operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_provisioning.SetProvisioningClientConnectionArgsOperation( provisioning_host=security_client.provisioning_host, registration_id=security_client.registration_id, id_scope=security_client.id_scope, client_cert=security_client.get_x509_certificate(), ), ) else: operation_flow.pass_op_to_next_stage(self, op)
def _execute_op(self, op): if isinstance(op, pipeline_ops_iothub.SetAuthProviderOperation): self.auth_provider = op.auth_provider self.auth_provider.on_sas_token_updated_handler = self.on_sas_token_updated operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_iothub.SetIoTHubConnectionArgsOperation( device_id=self.auth_provider.device_id, module_id=getattr(self.auth_provider, "module_id", None), hostname=self.auth_provider.hostname, gateway_hostname=getattr(self.auth_provider, "gateway_hostname", None), ca_cert=getattr(self.auth_provider, "ca_cert", None), sas_token=self.auth_provider.get_current_sas_token(), ), ) elif isinstance(op, pipeline_ops_iothub.SetX509AuthProviderOperation): self.auth_provider = op.auth_provider operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_iothub.SetIoTHubConnectionArgsOperation( device_id=self.auth_provider.device_id, module_id=getattr(self.auth_provider, "module_id", None), hostname=self.auth_provider.hostname, gateway_hostname=getattr(self.auth_provider, "gateway_hostname", None), ca_cert=getattr(self.auth_provider, "ca_cert", None), client_cert=self.auth_provider.get_x509_certificate(), ), ) else: operation_flow.pass_op_to_next_stage(self, op)
def test_completes_original_op_after_new_op_completes(self, stage, op, new_op, callback): op.callback = callback new_op.action = "pend" delegate_to_different_op(stage, original_op=op, new_op=new_op) assert callback.call_count == 0 # because new_op is pending complete_op(stage.next, new_op) assert_callback_succeeded(op=op)
def _execute_op(self, op): if isinstance( op, pipeline_ops_provisioning. SetProvisioningClientConnectionArgsOperation): # get security client args from above, save some, use some to build topic names, # always pass it down because MQTT protocol stage will also want to receive these args. client_id = op.registration_id query_param_seq = [ ("api-version", pkg_constant.PROVISIONING_API_VERSION), ("ClientVersion", pkg_constant.USER_AGENT), ] username = "******".format( id_scope=op.id_scope, registration_id=op.registration_id, query_params=urllib.parse.urlencode(query_param_seq), ) hostname = op.provisioning_host operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.SetMQTTConnectionArgsOperation( client_id=client_id, hostname=hostname, username=username, client_cert=op.client_cert, sas_token=op.sas_token, ), ) elif isinstance( op, pipeline_ops_provisioning.SendRegistrationRequestOperation): # Convert Sending the request into MQTT Publish operations topic = mqtt_topic.get_topic_for_register(op.request_id) operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTPublishOperation( topic=topic, payload=op.request_payload), ) elif isinstance(op, pipeline_ops_provisioning.SendQueryRequestOperation): # Convert Sending the request into MQTT Publish operations topic = mqtt_topic.get_topic_for_query(op.request_id, op.operation_id) operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTPublishOperation( topic=topic, payload=op.request_payload), ) elif isinstance(op, pipeline_ops_base.EnableFeatureOperation): # Enabling for register gets translated into an MQTT subscribe operation topic = mqtt_topic.get_topic_for_subscribe() operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTSubscribeOperation(topic=topic), ) elif isinstance(op, pipeline_ops_base.DisableFeatureOperation): # Disabling a register response gets turned into an MQTT unsubscribe operation topic = mqtt_topic.get_topic_for_subscribe() operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTUnsubscribeOperation(topic=topic), ) else: # All other operations get passed down operation_flow.pass_op_to_next_stage(self, op)
def test_returns_new_op_failure_in_original_op(self, stage, op, new_op, callback): op.callback = callback new_op.action = "fail" delegate_to_different_op(stage, original_op=op, new_op=new_op) assert_callback_failed(op=op, error=new_op.error)
def test_runs_new_op(self, mocker, stage, op, new_op): delegate_to_different_op(stage, original_op=op, new_op=new_op) assert stage.next.run_op.call_count == 1 assert stage.next.run_op.call_args == mocker.call(new_op)
def _execute_op(self, op): if isinstance(op, pipeline_ops_iothub.SetIoTHubConnectionArgsOperation): self.device_id = op.device_id self.module_id = op.module_id # if we get auth provider args from above, we save some, use some to build topic names, # and always pass it down because we know that the MQTT protocol stage will also want # to receive these args. self._set_topic_names(device_id=op.device_id, module_id=op.module_id) if op.module_id: client_id = "{}/{}".format(op.device_id, op.module_id) else: client_id = op.device_id query_param_seq = [ ("api-version", pkg_constant.IOTHUB_API_VERSION), ("DeviceClientType", pkg_constant.USER_AGENT), ] username = "******".format( hostname=op.hostname, client_id=client_id, query_params=urllib.parse.urlencode(query_param_seq), ) if op.gateway_hostname: hostname = op.gateway_hostname else: hostname = op.hostname # TODO: test to make sure client_cert and sas_token travel down correctly operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.SetMQTTConnectionArgsOperation( client_id=client_id, hostname=hostname, username=username, ca_cert=op.ca_cert, client_cert=op.client_cert, sas_token=op.sas_token, ), ) elif (isinstance(op, pipeline_ops_base.UpdateSasTokenOperation) and self.pipeline_root.connected): logger.debug( "{}({}): Connected. Passing op down and reconnecting after token is updated." .format(self.name, op.name)) # make a callback that can call the user's callback after the reconnect is complete def on_reconnect_complete(reconnect_op): if reconnect_op.error: op.error = reconnect_op.error logger.error( "{}({}) reconnection failed. returning error {}". format(self.name, op.name, op.error)) operation_flow.complete_op(stage=self, op=op) else: logger.debug( "{}({}) reconnection succeeded. returning success.". format(self.name, op.name)) operation_flow.complete_op(stage=self, op=op) # save the old user callback so we can call it later. old_callback = op.callback # make a callback that either fails the UpdateSasTokenOperation (if the lower level failed it), # or issues a ReconnectOperation (if the lower level returned success for the UpdateSasTokenOperation) def on_token_update_complete(op): op.callback = old_callback if op.error: logger.error( "{}({}) token update failed. returning failure {}". format(self.name, op.name, op.error)) operation_flow.complete_op(stage=self, op=op) else: logger.debug( "{}({}) token update succeeded. reconnecting".format( self.name, op.name)) operation_flow.pass_op_to_next_stage( stage=self, op=pipeline_ops_base.ReconnectOperation( callback=on_reconnect_complete), ) logger.debug( "{}({}): passing to next stage with updated callback.". format(self.name, op.name)) # now, pass the UpdateSasTokenOperation down with our new callback. op.callback = on_token_update_complete operation_flow.pass_op_to_next_stage(stage=self, op=op) elif isinstance( op, pipeline_ops_iothub.SendD2CMessageOperation) or isinstance( op, pipeline_ops_iothub.SendOutputEventOperation): # Convert SendTelementry and SendOutputEventOperation operations into MQTT Publish operations topic = mqtt_topic_iothub.encode_properties( op.message, self.telemetry_topic) operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTPublishOperation( topic=topic, payload=op.message.data), ) elif isinstance(op, pipeline_ops_iothub.SendMethodResponseOperation): # Sending a Method Response gets translated into an MQTT Publish operation topic = mqtt_topic_iothub.get_method_topic_for_publish( op.method_response.request_id, str(op.method_response.status)) payload = json.dumps(op.method_response.payload) operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTPublishOperation(topic=topic, payload=payload), ) elif isinstance(op, pipeline_ops_base.EnableFeatureOperation): # Enabling a feature gets translated into an MQTT subscribe operation topic = self.feature_to_topic[op.feature_name] operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTSubscribeOperation(topic=topic), ) elif isinstance(op, pipeline_ops_base.DisableFeatureOperation): # Disabling a feature gets turned into an MQTT unsubscribe operation topic = self.feature_to_topic[op.feature_name] operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTUnsubscribeOperation(topic=topic), ) elif isinstance(op, pipeline_ops_base.SendIotRequestOperation): if op.request_type == pipeline_constant.TWIN: topic = mqtt_topic_iothub.get_twin_topic_for_publish( method=op.method, resource_location=op.resource_location, request_id=op.request_id, ) operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTPublishOperation( topic=topic, payload=op.request_body), ) else: raise NotImplementedError( "SendIotRequestOperation request_type {} not supported". format(op.request_type)) else: # All other operations get passed down operation_flow.pass_op_to_next_stage(self, op)
def _run_op(self, op): if isinstance(op, pipeline_ops_iothub.SetAuthProviderArgsOperation): self.device_id = op.device_id self.module_id = op.module_id # if we get auth provider args from above, we save some, use some to build topic names, # and always pass it down because we know that the MQTT protocol stage will also want # to receive these args. self._set_topic_names(device_id=op.device_id, module_id=op.module_id) if op.module_id: client_id = "{}/{}".format(op.device_id, op.module_id) else: client_id = op.device_id username = "******".format( hostname=op.hostname, client_id=client_id) if op.gateway_hostname: hostname = op.gateway_hostname else: hostname = op.hostname operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.SetMQTTConnectionArgsOperation( client_id=client_id, hostname=hostname, username=username, ca_cert=op.ca_cert), ) elif isinstance( op, pipeline_ops_iothub.SendD2CMessageOperation) or isinstance( op, pipeline_ops_iothub.SendOutputEventOperation): # Convert SendTelementry and SendOutputEventOperation operations into MQTT Publish operations topic = mqtt_topic_iothub.encode_properties( op.message, self.telemetry_topic) operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTPublishOperation( topic=topic, payload=op.message.data), ) elif isinstance(op, pipeline_ops_iothub.SendMethodResponseOperation): # Sending a Method Response gets translated into an MQTT Publish operation topic = mqtt_topic_iothub.get_method_topic_for_publish( op.method_response.request_id, str(op.method_response.status)) payload = json.dumps(op.method_response.payload) operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTPublishOperation(topic=topic, payload=payload), ) elif isinstance(op, pipeline_ops_base.EnableFeatureOperation): # Enabling a feature gets translated into an MQTT subscribe operation topic = self.feature_to_topic[op.feature_name] operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTSubscribeOperation(topic=topic), ) elif isinstance(op, pipeline_ops_base.DisableFeatureOperation): # Disabling a feature gets turned into an MQTT unsubscribe operation topic = self.feature_to_topic[op.feature_name] operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTUnsubscribeOperation(topic=topic), ) elif isinstance(op, pipeline_ops_base.SendIotRequestOperation): if op.request_type == constant.TWIN: topic = mqtt_topic_iothub.get_twin_topic_for_publish( method=op.method, resource_location=op.resource_location, request_id=op.request_id, ) operation_flow.delegate_to_different_op( stage=self, original_op=op, new_op=pipeline_ops_mqtt.MQTTPublishOperation( topic=topic, payload=op.request_body), ) else: raise NotImplementedError( "SendIotRequestOperation request_type {} not supported". format(op.request_type)) else: # All other operations get passed down operation_flow.pass_op_to_next_stage(self, op)