Package: axual-client-python
Axual Python ClientPython client library that enables interaction with the Axual platform.PrerequisitesPython 3 is required, Python 3.6 or greater is recommended.Installationpipinstallaxual-client-pythonTestingTests are located in thetests/directory.
To run all of them:python-munittestdiscovertestsUsageProducerimportjsonfromaxualclient.producerimportProducerconf={# Axual configuration'application_id':application_id,'endpoint':endpoint,'tenant':tenant,'environment':environment,# SSL configuration'ssl.certificate.location':producer_app_cert,'ssl.key.location':producer_app_key,'ssl.ca.location':root_cert,}producer=Producer(conf)producer.produce(value=json.dumps(dict(a=1,b='banana')))producer.flush()# Flushes producer before ending (triggering callbacks for delivery reports)SeeSSL Configurationfor more info on the certificates required.Consumerfromaxualclient.consumerimportConsumerconf={# Axual configuration'application_id':application_id,'endpoint':endpoint,'tenant':tenant,'environment':environment,# SSL configuration'ssl.certificate.location':producer_app_cert,'ssl.key.location':producer_app_key,'ssl.ca.location':root_cert,# Consumer configuration'auto.offset.reset':'earliest','on_commit':on_commit_callback,}consumer=Consumer(conf)try:# Subscribe to topic(s) as they appear on Self Serviceconsumer.subscribe(['your-topic'])whileTrue:msg=consumer.poll(1.0)# msg is None if no new messageifmsgisNone:continueifmsg.error():# Error handlingraiseKafkaException(msg.error())else:# Do some processing on the messageprint(f'Received message on topic{msg.topic()}partition{msg.partition()}'f'offset{msg.offset()}key{msg.key()}value{msg.value()}')# Commit message offset to the topicconsumer.commit()finally:ifconsumerisnotNone:# Cleanly unregister from cluster by closing consumerconsumer.commit()consumer.close()Producer (AVRO)Producing AVRO messages works if you have the AVRO schema available that was uploaded to self-service.
Those schemas need to be provided to the serializer via theschema_stras AvroSchema Declaration.fromaxualclient.avroimportAvroSerializerfromaxualclient.serializing_producerimportSerializingProducerkey_serializer=AvroSerializer(schema_str=Application.SCHEMA,to_dict=application_to_dict)value_serializer=AvroSerializer(schema_str=ApplicationLogEvent.SCHEMA,to_dict=application_log_event_to_dict)conf={# Axual configuration'application_id':application_id,'endpoint':endpoint,'tenant':tenant,'environment':environment,# SSL configuration'ssl.certificate.location':producer_app_cert,'ssl.key.location':producer_app_key,'ssl.ca.location':root_cert,# Producer configuration'key.serializer':key_serializer,'value.serializer':value_serializer,'acks':'all',}producer=SerializingProducer(conf)producer.produce(topic=topic,value=value,key=key)producer.flush()# Flushes producer before ending (triggering callbacks for delivery reports)Consumer (AVRO)ConsumerAvroDeserializersneed to be instantiated and passed as configuration to the AxualDeserializingConsumerlike so:fromaxualclient.avroimportAvroDeserializerfromaxualclient.deserializing_consumerimportDeserializingConsumer# Initialize Deserializers:key_deserializer=AvroDeserializer(# Optional parametersschema_str=Application.SCHEMA,from_dict=dict_to_application)value_deserializer=AvroDeserializer(# Optional parametersschema_str=ApplicationLogEvent.SCHEMA,from_dict=dict_to_application_log_event,)configuration={# Axual configuration'application_id':application_id,'endpoint':endpoint,'tenant':tenant,'environment':environment,# SSL configuration'ssl.certificate.location':producer_app_cert,'ssl.key.location':producer_app_key,'ssl.ca.location':root_cert,# Consumer configuration'key.deserializer':key_deserializer,'value.deserializer':value_deserializer,'auto.offset.reset':'earliest','on_commit':on_commit_callback,'error_cb':on_error_callback,'logger':logger}consumer=DeserializingConsumer(configuration)try:consumer.subscribe([topic])whileTrue:msg=consumer.poll()ifmsgisNone:continueifmsg.error():print(f'Error returned by poll:{msg.error()}')else:print(f'Received message on topic{msg.topic()}partition{msg.partition()}'f'offset{msg.offset()}key:{str(msg.key())}value:{str(msg.value())}')consumer.commit()exceptKeyboardInterrupt:print('Caught KeyboardInterrupt, stopping.')finally:ifconsumerisnotNone:print('Committing final offsets and leaving group.')consumer.commit()consumer.close()SSL ConfigurationThe client configuration requires a correct SSL configuration in order to communicate securely with brokers, the discovery API, and the schema registry.Each application (as defined in self-service) requires an application certificate (ssl.certificate.location) and corresponding private key (ssl.key.location).
The application certificate must match the one uploaded in self-service for that application.The file with root certificates needs to be created properly: the brokers might be using a root certificate authority different
from the authority that signed the certificates for the discovery API and schema registry.
The base64-encoded unencrypted versions of these certificates can be pasted into one file (ssl.ca.location).
This file would then look like the following example:-----BEGIN CERTIFICATE-----
MIIQdaGDAksKadksSDKNsdka5sjy8elAMsm3d .....
 ...  more base64-encoded content here ...
..... LKlmsf02mz2EWYnds=
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
MIIPmsd92nNWlasHWdwMOe92nwoa2QNinnNaZ .....
 ...  more base64-encoded content here ...
..... ldFAf02SArubBW7wVFW2i1=
-----END CERTIFICATE-----ExamplesSimple use cases using the client code can be found in theAxual Python Client Examples.Known LimitationsWe have encountered issues when usingroot_cas consisting of more than 1 intermediate certificates.
The issue originates with the underlying SSL C library implementation and results in the following exception
when authenticating:[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: path length constraint exceeded (_ssl.c:1123)Transaction support is not there. Anissueis already created and transactions will be supported in future releases.PEM as string format is not supported. Anissueis already created and will be added in future releases.ContributingAxual is interested in building the community; we would welcome any thoughts orpatches.
You can reach ushere.Seecontributing.Building locallyThis project usespoetryfor dependency management and building.
Install the tool as per the instructions on the linked page, and build the library using:poetrybuildTesting locallyUnit Tests are placed in directoryunit, to run all of them:python-munittestdiscover-stests/unit-vIntegration tests require standalone to be running, to run standalone locally you need docker compose.
Once that is present you can start standalonedockercomposeup
python-munittestdiscover-stests/integration-vFor maintainers: building a releaseThe version of the library being built will be the version specified inpyproject.tomlwhenever you
push to a branch.When tagging and building a release however, please be aware that the CI pipeline will ignore the version inpyproject.tomland
build a release based on what is specified in the tag;
for example tagging1.0.0-alpha4will produceaxual_client_python-1.0.0a4-py3-none-any.whl.This has two consequences:You have to follow the normalsemverrules when choosing a tagAfter releasing, it falls on the developer to manually update the version inpyproject.tomlin preparation for the next version.LicenseAxual Python Client is licensed under theApache License, Version 2.0.