github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/assess_model_change_watcher.py (about) 1 #!/usr/bin/env python3 2 3 import argparse 4 import asyncio 5 import logging 6 import os 7 import sys 8 9 from juju.client.connection import Connection 10 from juju.client import watcher 11 12 from deploy_stack import ( 13 BootstrapManager, 14 until_timeout, 15 ) 16 from jujucharm import local_charm_path 17 from utility import ( 18 add_basic_testing_arguments, 19 configure_logging, 20 JujuAssertionError, 21 ) 22 23 24 log = logging.getLogger("assess_model_change_watcher") 25 TOKEN = "1234asdf" 26 27 28 def is_config_change_in_event(event): 29 message = _get_message(event) 30 return all([ 31 "application" in event, 32 "change" in event, 33 is_in_dict("config", {"token": TOKEN}, message), 34 ]) 35 36 37 def _get_message(event): 38 for message in event: 39 if isinstance(message, dict): 40 return message 41 return None 42 43 44 def is_in_dict(key, value, items): 45 return items.get(key) == value 46 47 48 async def listen_to_watcher(event_found, conn, future): 49 logging.info("Starting to listen for the watcher.") 50 all_watcher = watcher.AllWatcher() 51 all_watcher.connect(conn) 52 for _ in until_timeout(120): 53 logging.info("Listening for events...") 54 change = await all_watcher.Next() 55 for delta in change.deltas: 56 logging.info("Event received: {}".format(str(delta.deltas))) 57 if event_found(delta.deltas) is True: 58 await all_watcher.Stop() 59 await conn.close() 60 logging.info("Event found: {}".format(str(delta.deltas))) 61 future.set_result(True) 62 return 63 64 await all_watcher.Stop() 65 await conn.close() 66 logging.warning("Event not found.") 67 future.set_result(False) 68 69 70 def run_listener(client, event, juju_bin): 71 logging.info("Running listener.") 72 loop = asyncio.get_event_loop() 73 future = asyncio.Future() 74 75 logging.info("Connect to the current model.") 76 os.environ['JUJU_DATA'] = client.env.juju_home 77 os.environ['PATH'] = "{}{}{}".format( 78 juju_bin, os.pathsep, os.environ.get('PATH', '')) 79 conn = loop.run_until_complete(Connection.connect_current()) 80 logging.info("Connected to the current model.") 81 82 asyncio.ensure_future(listen_to_watcher(event, conn, future)) 83 return loop, future 84 85 86 def assess_model_change_watcher(client, charm_series, juju_bin): 87 charm = local_charm_path( 88 charm='dummy-source', juju_ver=client.version, series=charm_series, 89 platform='ubuntu') 90 client.deploy(charm) 91 client.wait_for_started() 92 93 loop, future = run_listener(client, is_config_change_in_event, juju_bin) 94 95 logging.info("Making config change.") 96 client.set_config('dummy-source', {'token': TOKEN}) 97 98 loop.run_until_complete(future) 99 result = future.result() 100 if result is not True: 101 raise JujuAssertionError("Config change event was not sent.") 102 loop.close() 103 104 105 def parse_args(argv): 106 parser = argparse.ArgumentParser(description="Assess config change.") 107 add_basic_testing_arguments(parser) 108 return parser.parse_args(argv) 109 110 111 def main(argv=None): 112 args = parse_args(argv) 113 configure_logging(args.verbose) 114 bs_manager = BootstrapManager.from_args(args) 115 with bs_manager.booted_context(args.upload_tools): 116 assess_model_change_watcher( 117 bs_manager.client, bs_manager.series, args.juju_bin) 118 return 0 119 120 121 if __name__ == '__main__': 122 sys.exit(main())