Пример #1
0
def update_poll_message(poll):
    # get a reference to the DynamoDB resource
    dynamodb_resource = boto3.resource('dynamodb')

    # create the lock-client
    lock_client = DynamoDBLockClient(dynamodb_resource)
    with lock_client.acquire_lock(
            DYNAMO_DB_TABLE_NAME + ":" + poll.key,
            retry_period=timedelta(seconds=UPDATING_POLL_MESSAGE_DELAY/3),
            retry_timeout=timedelta(seconds=UPDATING_POLL_MESSAGE_DELAY*5),
            raise_context_exception=True,
    ):
        poll.refresh()

        if poll.version == poll.telegram_version:
            # no need to update
            logger.debug("Poll was already updated. Exit")
            return

        now = get_now()
        logger.debug("Checking for sleep: now is %s, last update is %s", now, poll.telegram_datetime)
        since_last_update = (now - poll.telegram_datetime).total_seconds()
        if since_last_update < UPDATING_POLL_MESSAGE_DELAY:
            sleep = UPDATING_POLL_MESSAGE_DELAY - since_last_update
            logger.debug("Sleep for %ssec", poll)
            time.sleep(sleep)
            poll.refresh()

        chat_id, message_id = poll2chat_message_ids(poll)
        # Update text
        try:
            bot.editMessageText(
                poll2text(poll),
                chat_id,
                message_id,
                parse_mode='HTML',
            )
        except telegram.error.BadRequest as e:
            if e.message != "Message is not modified: specified new message content and reply markup are exactly the same as a current content and reply markup of the message":
                raise

        # Update Markup
        bot.editMessageReplyMarkup(
            chat_id,
            message_id,
            reply_markup=poll2markup(poll),
        )
        poll.telegram_version = poll.version + 1
        poll.telegram_datetime = get_now()
        poll.save()
Пример #2
0
def main(repo, output_folder, user):
    global INSTANCE_ID
    # Notify the ASG LifeCycle hook that we are now In Service and ready to
    # process requests/safe to be shut down

    # Fetch current instance ID from where cloutinit writes it to
    if not INSTANCE_ID:
        with open('/var/lib/cloud/data/instance-id') as fh:
            INSTANCE_ID = fh.readline().strip()

    log.info("Starting on %s...", INSTANCE_ID)

    output_folder = os.path.expanduser(output_folder)

    short_time = datetime.timedelta(microseconds=1)

    dynamodb = boto3.resource('dynamodb')
    client = DynamoDBLockClient(
        dynamodb,
        table_name='GitHubRunnerLocks',
        expiry_period=datetime.timedelta(0, 300),
        heartbeat_period=datetime.timedelta(seconds=10),
    )

    # Just keep trying until we get some credentials.
    while True:
        # Have each runner try to get a credential in a random order.
        possibles = get_possible_credentials(repo)
        random.shuffle(possibles)

        log.info("Trying to get a set of credentials in this order: %r",
                 possibles)

        notify = get_sd_notify_func()

        for index in possibles:
            try:
                lock = client.acquire_lock(
                    f'{repo}/{index}',
                    retry_period=short_time,
                    retry_timeout=short_time,
                    raise_context_exception=True,
                )
            except DynamoDBLockError as e:
                log.info("Could not lock %s (%s)", index, e)
                continue

            with lock:
                log.info("Obtained lock on %s", index)
                write_credentials_to_files(repo, index, output_folder, user)
                merge_in_settings(repo, output_folder)
                notify(f"STATUS=Obtained lock on {index}")

                if get_lifecycle_state() == "Pending:Wait":
                    complete_asg_lifecycle_hook()

                notify("READY=1")
                log.info("Watching for Runner.Worker processes")
                ProcessWatcher().run()

            client.close()

            exit()
class AwsStateStorage:
    def __init__(self, s3_bucket, s3_key, *, locking=True):
        self._s3_bucket_name = s3_bucket
        self._s3_key = s3_key
        # self._timeout = timeout
        self._opened = False

        self._s3_bucket = boto3.resource('s3').Bucket(self._s3_bucket_name)
        if self._s3_bucket.creation_date is None:
            raise KeyError("No such bucket: %s" % self._s3_bucket_name)

        ddb_client = boto3.client('dynamodb')
        try:
            DynamoDBLockClient.create_dynamodb_table(ddb_client)
        except ddb_client.exceptions.ResourceInUseException:
            # the table already exists -- ok with us
            pass

        if locking:
            self._lock_client = DynamoDBLockClient(boto3.resource('dynamodb'))
            self._lock = None
        else:
            self._lock_client = None

    def open_and_read(self, read_cb):
        assert not self._opened

        if self._lock_client:
            self._lock = self._lock_client.acquire_lock("{}/{}".format(
                self._s3_bucket_name, self._s3_key))

        try:
            with io.BytesIO() as f:
                try:
                    self._s3_bucket.download_fileobj(self._s3_key, f)
                    f.seek(0)
                    read_cb(f)
                except botocore.exceptions.ClientError as e:
                    if e.response["Error"]["Code"] == "404":
                        read_cb(None)
                    else:
                        raise

            self._opened = True

            return self

        except:  # noqa: E722
            if self._lock_client:
                self._lock.release()

            raise

    def close(self):
        assert self._opened
        self._opened = False
        if self._lock_client:
            self._lock.release()
            self._lock_client.close()

    def write(self, write_cb):
        assert self._opened

        with io.StringIO() as f:
            write_cb(f)

            self._s3_bucket.put_object(Key=self._s3_key,
                                       Body=f.getvalue().encode())