Esempio n. 1
0
 def test_with_context(self):
     with ConsulServiceController().start_service() as service:
         consul_client = service.create_consul_client()
         lock_manager = ConsulLockManager(consul_client=consul_client)
         with lock_manager.acquire(KEY_1) as lock_information:
             self.assertEqual(lock_information, lock_manager.find(KEY_1))
         self.assertIsNone(lock_manager.find(KEY_1))
Esempio n. 2
0
 def test_find_regex_when_no_locks(self):
     with ConsulServiceController().start_service() as service:
         lock_manager = ConsulLockManager(
             consul_client=service.create_consul_client())
         found_locks = lock_manager.find_regex(
             f"{KEY_1}{KEY_DIRECTORY_SEPARATOR}[0-9]+")
         self.assertEqual(0, len(found_locks))
Esempio n. 3
0
def main(cli_arguments: List[str]):
    """
    Entrypoint.
    :param cli_arguments: arguments passed in via the CLI
    :raises SystemExit: always raised
    """
    cli_configuration: CliConfiguration
    try:
        cli_configuration = parse_cli_configuration(cli_arguments)
    except InvalidCliArgumentError as e:
        logger.error(e)
        exit(INVALID_CLI_ARGUMENT_EXIT_CODE)
    except SystemExit as e:
        exit(e.code)

    if cli_configuration.log_verbosity:
        logging.getLogger(PACKAGE_NAME).setLevel(cli_configuration.log_verbosity)

    consul_configuration: ConsulConfiguration
    try:
        consul_configuration = get_consul_configuration_from_environment()
    except KeyError as e:
        logger.error(f"Cannot connect to Consul - the environment variable {e.args[0]} must be set")
        exit(MISSING_REQUIRED_ENVIRONMENT_VARIABLE_EXIT_CODE)
    except InvalidEnvironmentVariableError as e:
        logger.error(e)
        exit(INVALID_ENVIRONMENT_VARIABLE_EXIT_CODE)

    lock_manager: ConsulLockManager
    try:
        lock_manager = ConsulLockManager(
            consul_configuration=consul_configuration, session_ttl_in_seconds=cli_configuration.session_ttl)
    except InvalidSessionTtlValueError as e:
        logger.error(e)
        exit(INVALID_SESSION_TTL_EXIT_CODE)

    try:
        {
            CliLockConfiguration: _acquire_lock_and_exit,
            CliLockAndExecuteConfiguration: _acquire_lock_and_execute,
            CliUnlockConfiguration: _release_lock
        }[type(cli_configuration)](lock_manager, cli_configuration)
    except PermissionDeniedConsulError as e:
        error_message = f"Invalid credentials - are you sure you have set {CONSUL_TOKEN_ENVIRONMENT_VARIABLE} " \
                        f"correctly?"
        logger.debug(e)
        logger.error(error_message)
        exit(PERMISSION_DENIED_EXIT_CODE)
    except DoubleSlashKeyError as e:
        logger.debug(e)
        logger.error(f"Double slashes \"//\" in keys get converted into single slashes \"/\" - please use a "
                     f"single slash if this is intended: {cli_configuration.key}")
        exit(INVALID_KEY_EXIT_CODE)
    except NonNormalisedKeyError as e:
        logger.debug(e)
        logger.error(f"Key paths must be normalised - use \"{normpath(e.key)}\" if this key was intended: "
                     f"{cli_configuration.key}")
        exit(INVALID_KEY_EXIT_CODE)
Esempio n. 4
0
 def find_regex(service: ConsulDockerisedService):
     consul_client = service.create_consul_client()
     lock_manager = ConsulLockManager(consul_client=consul_client)
     consul_client.kv.put(KEYS_1[1], "unrelated")
     found_locks = lock_manager.find_regex(KEYS_1_REGEX)
     self.assertEqual(2, len(found_locks))
     self.assertIsInstance(found_locks[KEYS_1[0]],
                           ConsulLockInformation)
     self.assertIsNone(found_locks[KEYS_1[1]])
Esempio n. 5
0
 def action_executor(key: str,
                     service: ConsulDockerisedService) -> CaptureResult:
     nonlocal init_args_generator, init_kwargs_generator, action_args, action_kwargs, action_property
     lock_manager = ConsulLockManager(
         *init_args_generator(key, service),
         **init_kwargs_generator(key, service))
     action_args = action_args if action_args is not None else []
     action_kwargs = action_kwargs if action_kwargs is not None else {}
     return TestConsulLockManager._CAPTURE_WRAP_BUILDER.build(
         getattr(lock_manager, action_property))(key, *action_args,
                                                 **action_kwargs)
Esempio n. 6
0
 def test_unlock_all(self):
     test_keys = [f"{KEY_1}_{i}" for i in range(5)]
     with ConsulServiceController().start_service() as service:
         lock_manager = ConsulLockManager(
             consul_client=service.create_consul_client())
         for key in test_keys:
             lock = lock_manager.acquire(key)
             assert isinstance(lock, ConsulLockInformation)
         unlock_results = lock_manager.release_all(test_keys)
     for unlock_result in unlock_results:
         self.assertTrue(unlock_result)
Esempio n. 7
0
    def __init__(self,
                 data_key: str,
                 lock_key: str,
                 url: str = None,
                 token: str = None,
                 consul_client=None,
                 configuration_checksum_mappings: Mapping[str, str] = None):
        Consul = ConsulChecksumStorage._load_consul_class()
        ConsulLockManager = ConsulChecksumStorage._load_consul_lock_manager()

        if url is not None and consul_client is not None:
            raise ValueError("Cannot use both `url` and `consul_client`")

        self.data_key = data_key
        self.lock_key = lock_key

        consul_client_kwargs: Dict = {}
        if url is not None:
            parsed_url = urlparse(url)
            consul_client_kwargs["host"] = parsed_url.hostname
            consul_client_kwargs["port"] = parsed_url.port
            consul_client_kwargs["scheme"] = parsed_url.scheme if len(
                parsed_url.scheme) > 0 else "http"
        self._consul_client = consul_client if consul_client is not None else Consul(
            **consul_client_kwargs)

        if token is None:
            token = os.environ.get(
                ConsulChecksumStorage.CONSUL_HTTP_TOKEN_ENVIRONMENT_VARIABLE,
                None)
        if token is not None:
            # Work around for https://github.com/cablehead/python-consul/issues/170
            self._consul_client.token = token
            self._consul_client.http.session.headers.update(
                {"X-Consul-Token": token})

        self._lock_manager = ConsulLockManager(
            consul_client=self._consul_client,
            session_ttl_in_seconds=ConsulChecksumStorage.
            CONSUL_SESSION_LOCK_DEFAULT_TIMEOUT)

        super().__init__(configuration_checksum_mappings)
Esempio n. 8
0
def main(lock_key: str):
    lock_manager = ConsulLockManager()
    lock = lock_manager.find(lock_key)
    logger.debug(f"Lock with key \"{lock_key}\": {lock}")

    if lock is not None and lock.metadata is not None and JOB_ID_LOCK_METADATA_KEY in lock.metadata:
        job_id = lock.metadata[JOB_ID_LOCK_METADATA_KEY]
        logger.info(f"Lock currently held by CI job with ID: {job_id}")

        job_running = is_ci_job_running(job_id)
        logger.info(
            f"CI job with ID {job_id} {'is' if job_running else 'is not'} running"
        )
        if not job_running:
            logger.info(
                f"Releasing lock for {lock.key} held by non-running job {job_id}"
            )
            released = lock_manager.release(lock.key)
            logger.info("Released lock!" if released is not None else
                        "Did not manage to release lock (someone else "
                        "probably else released it before me)")
Esempio n. 9
0
 def first_locker(key: str,
                  service: ConsulDockerisedService) -> CaptureResult:
     lock_manager = ConsulLockManager(
         consul_client=service.create_consul_client())
     lock_information = lock_manager.acquire(KEY_1)
     return CaptureResult(return_value=lock_information)
Esempio n. 10
0
 def test_can_get_configuration_from_environment(self):
     with ConsulServiceController().start_service() as service:
         set_consul_env(service)
         lock_manager = ConsulLockManager()
         self.assertIsNone(lock_manager.release(KEY_1))
Esempio n. 11
0
 def test_lock_with_non_normalised_path(self):
     lock_manager = ConsulLockManager(
         consul_configuration=_DUMMY_CONSUL_CONFIGURATION)
     self.assertRaises(NonNormalisedKeyError, lock_manager.acquire,
                       NON_NORMALISED_KEY)
Esempio n. 12
0
 def find(service: ConsulDockerisedService):
     lock_manager = ConsulLockManager(
         consul_client=service.create_consul_client())
     found_lock = lock_manager.find(KEYS_1[0])
     self.assertEqual(KEYS_1[0], found_lock.key)
Esempio n. 13
0
 def test_find_when_no_locks(self):
     with ConsulServiceController().start_service() as service:
         lock_manager = ConsulLockManager(
             consul_client=service.create_consul_client())
         self.assertIsNone(lock_manager.find(KEY_1))
Esempio n. 14
0
 def test_cannot_use_after_teardown(self):
     lock_manager = ConsulLockManager(
         consul_configuration=_DUMMY_CONSUL_CONFIGURATION)
     lock_manager.teardown()
     self.assertRaises(UnusableStateError, lock_manager.acquire)
Esempio n. 15
0
 def release(service: ConsulDockerisedService):
     lock_manager = ConsulLockManager(
         consul_client=service.create_consul_client())
     released_locks = lock_manager.release_regex(KEYS_1_REGEX)
     self.assertCountEqual(KEYS_1, released_locks)
Esempio n. 16
0
 def find_regex(service: ConsulDockerisedService):
     lock_manager = ConsulLockManager(
         consul_client=service.create_consul_client())
     found_locks = lock_manager.find_regex(KEYS_1_REGEX)
     self.assertCountEqual(KEYS_1,
                           [lock.key for lock in found_locks.values()])
Esempio n. 17
0
 def test_lock_with_double_slash_path(self):
     lock_manager = ConsulLockManager(
         consul_configuration=_DUMMY_CONSUL_CONFIGURATION)
     self.assertRaises(DoubleSlashKeyError, lock_manager.acquire,
                       DOUBLE_SLASH_KEY)