Package: pop-beacon
A system to continually watch interfaces for events and forward them respectively through the event busINSTALLATIONpipinstallpop-beaconUSAGEbeaconis mainly an app-merge component for larger projects.
However, it includes a script that can be useful for testing your beacons.
This testing script will listen to all beacons and print out events that any of them receive.
A listener iterates over the internal beacon queues and prints everything that gets posted to them.
The the outputter to format the printed data can be specified with–output.beacon_test--outputjsonTESTINGInstallbeaconlocally with testing libraries:$gitclonegit@gitlab.com:saltstack/pop/beacon.git$pipinstall-ebeacon-rrequirements-test.txtIf you have a rabbitmq-server binary installed via your system’s package manager, the pika tests won’t be skipped.
Start a local rabbitmq-server with the default parameters:sudorabbitmq-serverRun the tests with pytest:$pytestbeacon/testsACCT PROFILESbeaconwill read credentials that are encrypted using theacctsystem.
To use this system, create a yaml file that has the plaintext credentials and information needed
to connect with the various beacon plugins.
For example, to connect to a rabbitmq server, or any amqp implementation,
have a profile in youracctcredentials file that specifies the “pika” acct plugin:credentials.ymlpika:profile_name:host:localhostport:5672username:XXXXXXXXXXXXpassword:XXXXXXXXXXXXbeacon_channels:-channel1-channel2Next use theacctcommand to encrypt this file using the fernet algorithm:$acctencryptcredentials.ymlYeckEnWEGOjBDVxxytw13AsdLgquzhCtFHOs7kDsna8=Theacctinformation can now be stored in environment variables:$exportACCT_FILE=$PWD/credentials.yml.fernet$exportACCT_KEY="YeckEnWEGOjBDVxxytw13AsdLgquzhCtFHOs7kDsna8="They can also be used on the command line:$beacon_test--acct-file=credentials.yml.fernet--acct-key="YeckEnWEGOjBDVxxytw13AsdLgquzhCtFHOs7kDsna8="INTEGRATIONYour own app can extendacct’s command line interface to use the–acct-fileand–acct-keyoptions for beacon:my_project/conf.pyCLI_CONFIG={"acct_file":{"source":"acct","os":"ACCT_FILE"},"acct_key":{"source":"acct","os":"ACCT_KEY"},"beacon_profiles":{"source":"beacon"},}In your own project, you can vertically mergebeaconand extend it with your own beacon plugins:my_project/conf.pyDYNE={"acct":["acct"],"beacon":["beacon"],"my_project":["my_project"],}Create the directorymy_project/beaconand add your beacon plugins there.Beacon plugins need a function called “listen” that is an asynchronous generator.my_project/beacon/my_plugin.pyfromtypingimportAsyncGeneratorasyncdeflisten(hub)->AsyncGenerator:asyncforeventinmy_queue:yieldeventThe “listen” function can optionally have actxparameter if your beacon plugin requires login credentials.
Thectxparameter will be automatically be populated byacctandevbusif a profile that specifies your
plugin is included in the encrypted acct file.my_project/beacon/my_plugin.pyfromtypingimportAsyncGeneratorasyncdeflisten(hub,ctx)->AsyncGenerator:ifnotctx.connected:return# Many message queues have named channels that can be specified# Create a listener for every channel on this connection# A listener is another function that returns an async generatorchannel_listeners=[awaitctx.connection.channel_listener(channel)forchannelinctx.channels]# Use hub.pop.loop.as_yielded to combine all the channel async generators into a single async generatorgenerator=hub.pop.loop.as_yielded(channel_listeners)# Listen for events as they come from any of the channelsasyncforeventingenerator:yieldeventCreate the directorymy_project/acct/beaconand add your acct plugins there.acctplugins need to implement agatherfunction, which reads the appropriate information fromhub.acct.PROFILESand turns it into processed profile information inhub.acct.SUB_PROFILES.
This processing can include operations such as opening a connection to a remote server.my_project/acct/beacon/my_plugin.pyasyncdefgather(hub):"""
    Get [my_plugin] profiles from an encrypted file

    Example:

    .. code-block:: yaml

        my_plugin:
          profile_name:
            host: localhost
            port: 12345
            username: XXXXXXXXXXXX
            password: XXXXXXXXXXXX
            beacon_channels:
              - channel1
              - channel2
    """sub_profiles={}forprofile,ctxinhub.acct.PROFILES.get("my_plugin",{}).items():# Create a connection through [some_library] for each of the profilessub_profiles[profile]={"connected":False,"connection":awaitsome_library.connect(**ctx),"channels":ctx.pop("beacon_channels",[]),}# Return these to be automatically processed by acct and injected into the `ctx` parameter of appropriate beacon publish calls.returnsub_profilesAdd beacon startup code to your project’s initializer:my_project/my_project/init.pydef__init__(hub):# Horizontally merge the beacon dynamic namespace into your projecthub.pop.sub.add(dyne_name="beacon")defcli(hub):# Load the config from beacon onto hub.OPThub.pop.config.load(["my_project","beacon","evbus","acct"],cli="my_project")# Create the asyncio loophub.pop.loop.create()# Create the beacon coroutinecoro=hub.beacon.init.start(format_plugin=hub.OPT.beacon.format,acct_file=hub.OPT.acct.acct_file,acct_key=hub.OPT.acct.acct_key,beacon_profiles=hub.OPT.beacon.beacon_profiles,)# Start the main beacon listenerhub.pop.Loop.run_until_complete(coro)