Beispiel #1
0
    def watch_prefix(self, key_prefix, **kwargs):
        """
        Watch a range of keys with a prefix.

        :param key_prefix: prefix to watch

        :returns: tuple of ``events_iterator`` and ``cancel``.
        """
        kwargs['range_end'] = \
            utils.increment_last_byte(utils.to_bytes(key_prefix))
        return self.watch(key_prefix, **kwargs)
Beispiel #2
0
    def build_message(self):
        compare = etcdrpc.Compare()
        compare.key = utils.to_bytes(self.key)

        if self.op is None:
            raise ValueError('op must be one of =, < or >')

        compare.result = self.op

        self.build_compare(compare)
        return compare
Beispiel #3
0
 def _create_watch_request(self,
                           key,
                           range_end=None,
                           start_revision=None,
                           progress_notify=False,
                           filters=None,
                           prev_kv=False):
     create_watch = etcdrpc.WatchCreateRequest()
     create_watch.key = utils.to_bytes(key)
     if range_end is not None:
         create_watch.range_end = utils.to_bytes(range_end)
     if start_revision is not None:
         create_watch.start_revision = start_revision
     if progress_notify:
         create_watch.progress_notify = progress_notify
     if filters is not None:
         create_watch.filters = filters
     if prev_kv:
         create_watch.prev_kv = prev_kv
     return etcdrpc.WatchRequest(create_request=create_watch)
Beispiel #4
0
    def test_lease_expire(self, etcd):
        key = '/doot/lease_test_expire'
        lease = etcd.lease(1)
        etcd.put(key, 'this is a lease', lease=lease)
        assert lease.keys == [utils.to_bytes(key)]
        assert etcd.get(key) == b'this is a lease'
        assert lease.remaining_ttl <= lease.granted_ttl

        # wait for the lease to expire
        time.sleep(lease.granted_ttl + 2)
        with pytest.raises(etcd3.exceptions.KeyNotFoundError):
            etcd.get(key)
Beispiel #5
0
 def delete_prefix(self, prefix):
     """Delete a range of keys with a prefix in etcd."""
     delete_request = self._build_delete_request(
         prefix,
         range_end=utils.increment_last_byte(utils.to_bytes(prefix))
     )
     return self.kvstub.DeleteRange(
         delete_request,
         self.timeout,
         credentials=self.call_credentials,
         metadata=self.metadata
     )
Beispiel #6
0
    def test_watch_prefix(self, etcd):
        def update_etcd(v):
            etcdctl('put', '/doot/watch/prefix/' + v, v)
            out = etcdctl('get', '/doot/watch/prefix/' + v)
            assert base64.b64decode(out['kvs'][0]['value']) == \
                utils.to_bytes(v)

        def update_key():
            # sleep to make watch can get the event
            time.sleep(3)
            update_etcd('0')
            time.sleep(1)
            update_etcd('1')
            time.sleep(1)
            update_etcd('2')
            time.sleep(1)
            update_etcd('3')
            time.sleep(1)

        t = threading.Thread(name="update_key_prefix", target=update_key)
        t.start()

        change_count = 0
        events_iterator, cancel = etcd.watch_prefix('/doot/watch/prefix/')
        for event in events_iterator:
            assert event.key == \
                utils.to_bytes('/doot/watch/prefix/{}'.format(change_count))
            assert event.value == \
                utils.to_bytes(str(change_count))

            # if cancel worked, we should not receive event 3
            assert event.value != utils.to_bytes('3')

            change_count += 1
            if change_count > 2:
                # if cancel not work, we will block in this for-loop forever
                cancel()

        t.join()
Beispiel #7
0
    def test_lease_expire(self, etcd):
        key = '/doot/lease_test_expire'
        lease = etcd.lease(1)
        etcd.put(key, 'this is a lease', lease=lease)
        assert lease.keys == [utils.to_bytes(key)]
        v, _ = etcd.get(key)
        assert v == b'this is a lease'
        assert lease.remaining_ttl <= lease.granted_ttl

        # wait for the lease to expire
        time.sleep(lease.granted_ttl + 2)
        v, _ = etcd.get(key)
        assert v is None
Beispiel #8
0
 def add_callback(self, key, callback,
                  range_end=None,
                  start_revision=None,
                  progress_notify=False,
                  filters=None,
                  prev_kv=False):
     with self._watch_id_lock:
         create_watch = etcdrpc.WatchCreateRequest()
         create_watch.key = utils.to_bytes(key)
         if range_end is not None:
             create_watch.range_end = utils.to_bytes(range_end)
         if start_revision is not None:
             create_watch.start_revision = start_revision
         if progress_notify:
             create_watch.progress_notify = progress_notify
         if filters is not None:
             create_watch.filters = filters
         if prev_kv:
             create_watch.prev_kv = prev_kv
         request = etcdrpc.WatchRequest(create_request=create_watch)
         self._watch_requests_queue.put((request, callback))
         return self._watch_id_queue.get(timeout=self.timeout)
Beispiel #9
0
    def get_prefix_response(self, key_prefix, **kwargs):
        """Get a range of keys with a prefix."""
        if any(kwarg in kwargs for kwarg in ("key", "range_end")):
            raise TypeError("Don't use key or range_end with prefix")

        range_request = self._build_get_range_request(
            key=key_prefix,
            range_end=utils.prefix_range_end(utils.to_bytes(key_prefix)),
            **kwargs)

        return self.kvstub.Range(range_request,
                                 self.timeout,
                                 credentials=self.call_credentials,
                                 metadata=self.metadata)
Beispiel #10
0
    def add_watch_prefix_callback(self, key_prefix, callback, **kwargs):
        """
        Watch a prefix and call a callback on every response.

        If timeout was declared during the client initialization and
        the watch cannot be created during that time the method raises
        a ``WatchTimedOut`` exception.

        :param key_prefix: prefix to watch
        :param callback: callback function

        :returns: watch_id. Later it could be used for cancelling watch.
        """
        kwargs['range_end'] = \
            utils.increment_last_byte(utils.to_bytes(key_prefix))

        return self.add_watch_callback(key_prefix, callback, **kwargs)
Beispiel #11
0
    def get_prefix_response(self, key_prefix, sort_order=None,
                            sort_target='key', keys_only=False):
        """Get a range of keys with a prefix."""
        range_request = self._build_get_range_request(
            key=key_prefix,
            range_end=utils.increment_last_byte(utils.to_bytes(key_prefix)),
            sort_order=sort_order,
            sort_target=sort_target,
            keys_only=keys_only,
        )

        return self.kvstub.Range(
            range_request,
            self.timeout,
            credentials=self.call_credentials,
            metadata=self.metadata
        )
Beispiel #12
0
    def rolerevokepermission(self, role, path, prefix):

        rolerevokepermission_request = etcdrpc.AuthRoleRevokePermissionRequest(
            role=role, key=path)

        if prefix:
            rolerevokepermission_request.range_end = utils.increment_last_byte(
                utils.to_bytes(path))

        # else:
        #     rolerevokepermission_request.range_end = utils.to_bytes(path)

        print(rolerevokepermission_request)
        rolerevokepermission_responce = self.authstub.RoleRevokePermission(
            rolerevokepermission_request,
            self.timeout,
            credentials=self.call_credentials,
            metadata=self.metadata)
        return rolerevokepermission_responce
Beispiel #13
0
def watch_range_queue(queue: Queue, db: Etcd3Client, prefix):
    kwargs = {}
    kwargs['range_end'] = \
        utils.increment_last_byte(utils.to_bytes(prefix))

    def cb(event):
        ident = event.key.decode()[len(prefix):]

        if isinstance(event, DeleteEvent):
            queue.put(
                RangeEvent(prefix, ident, Ev.Delete, event.value,
                           event.version))
        elif isinstance(event, PutEvent):
            queue.put(
                RangeEvent(prefix, ident, Ev.Put, event.value, event.version))
        else:
            logger.error(f'UnknownEvent: {event}')

    return db.add_watch_callback(key=prefix, callback=cb, **kwargs)
Beispiel #14
0
    def get_prefix(self, key_prefix, sort_order=None, sort_target='key'):
        """
        Get a range of keys with a prefix.

        :param key_prefix: first key in range

        :returns: sequence of (key, value) tuples
        """
        range_request = self._build_get_range_request(
            key=key_prefix,
            range_end=utils.increment_last_byte(utils.to_bytes(key_prefix)),
            sort_order=sort_order,
        )

        range_response = self.kvstub.Range(range_request)

        if range_response.count < 1:
            raise exceptions.KeyNotFoundError('no keys found')
        else:
            for kv in range_response.kvs:
                yield (kv.key, kv.value)
Beispiel #15
0
    def get_prefix(self, key_prefix, sort_order=None, sort_target='key'):
        """
        Get a range of keys with a prefix.

        :param key_prefix: first key in range

        :returns: sequence of (value, metadata) tuples
        """
        range_request = self._build_get_range_request(
            key=key_prefix,
            range_end=utils.increment_last_byte(utils.to_bytes(key_prefix)),
            sort_order=sort_order,
        )

        range_response = self.kvstub.Range(range_request, self.timeout)

        if range_response.count < 1:
            return
        else:
            for kv in range_response.kvs:
                yield (kv.value, KVMetadata(kv))
Beispiel #16
0
 def build_compare(self, compare):
     compare.target = etcdrpc.Compare.VALUE
     compare.value = utils.to_bytes(self.value)
Beispiel #17
0
 def delete_prefix(self, prefix):
     """Delete a range of keys with a prefix in etcd."""
     delete_request = self._build_delete_request(
         prefix,
         range_end=utils.increment_last_byte(utils.to_bytes(prefix)))
     return self.kvstub.DeleteRange(delete_request)
Beispiel #18
0
 def update_etcd(v):
     etcdctl('put', '/doot/watch/prefix/' + v, v)
     out = etcdctl('get', '/doot/watch/prefix/' + v)
     assert base64.b64decode(out['kvs'][0]['value']) == \
         utils.to_bytes(v)
Beispiel #19
0
 def update_etcd(v):
     etcdctl('put', '/watchcompation', v)
     out = etcdctl('get', '/watchcompation')
     assert base64.b64decode(out['kvs'][0]['value']) == \
         utils.to_bytes(v)
Beispiel #20
0
 def watch_prefix(self, key_prefix, **kwargs):
     """The same as ``watch``, but watches a range of keys with a prefix."""
     kwargs['range_end'] = \
         utils.increment_last_byte(utils.to_bytes(key_prefix))
     return self.watch(key_prefix, **kwargs)
Beispiel #21
0
 def _build_put_request(self, key, value, lease=None):
     put_request = etcdrpc.PutRequest()
     put_request.key = utils.to_bytes(key)
     put_request.value = utils.to_bytes(value)
     put_request.lease = utils.lease_to_id(lease)
     return put_request