#!/usr/bin/env python3 """tests/sdk_test.py — программная проверка SQS API через boto3 (как реальное приложение). Использование: AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... \ ENDPOINT_URL=https://sqs.containerk8s.dev.nubes.ru python3 tests/sdk_test.py """ import os import sys import time import boto3 from botocore.config import Config ENDPOINT = os.environ.get("ENDPOINT_URL", "https://sqs.containerk8s.dev.nubes.ru") REGION = os.environ.get("REGION", "us-east-1") PASS = 0 FAIL = 0 def ok(name): global PASS PASS += 1 print(f" OK {name}") def bad(name, err=""): global FAIL FAIL += 1 print(f" FAIL {name} {err}") def main(): if not os.environ.get("AWS_ACCESS_KEY_ID") or not os.environ.get("AWS_SECRET_ACCESS_KEY"): print("Нужны AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY") return 1 # Таймауты на уровне SDK: запросы не зависают. cfg = Config(connect_timeout=10, read_timeout=20, retries={"max_attempts": 2}) sqs = boto3.client("sqs", endpoint_url=ENDPOINT, region_name=REGION, config=cfg) q = f"sdk-test-{int(time.time())}" qf = q + ".fifo" def step(name, fn): try: fn() ok(name) except Exception as e: bad(name, f"— {type(e).__name__}: {e}") url = {} def list_queues(): resp = sqs.list_queues() assert isinstance(resp.get("QueueUrls"), list) def create_queue(): url["u"] = sqs.create_queue(QueueName=q)["QueueUrl"] def get_queue_url(): assert sqs.get_queue_url(QueueName=q)["QueueUrl"] == url["u"] def get_queue_attributes(): attrs = sqs.get_queue_attributes(QueueUrl=url["u"], AttributeNames=["All"])["Attributes"] assert "VisibilityTimeout" in attrs def set_queue_attributes(): sqs.set_queue_attributes(QueueUrl=url["u"], Attributes={"VisibilityTimeout": "42"}) vt = sqs.get_queue_attributes(QueueUrl=url["u"], AttributeNames=["VisibilityTimeout"])["Attributes"]["VisibilityTimeout"] assert vt == "42", f"VisibilityTimeout={vt}" def send_message(): sqs.send_message(QueueUrl=url["u"], MessageBody="sdk-single") def send_message_batch(): resp = sqs.send_message_batch( QueueUrl=url["u"], Entries=[{"Id": "1", "MessageBody": "sdk-batch-1"}, {"Id": "2", "MessageBody": "sdk-batch-2"}], ) assert len(resp["Successful"]) == 2 received = {} def receive_messages(): msgs = None for _ in range(5): msgs = sqs.receive_message(QueueUrl=url["u"], MaxNumberOfMessages=10).get("Messages", []) if msgs: break time.sleep(1) assert len(msgs) == 3, f"получено {len(msgs)}" received["m"] = msgs def change_visibility(): sqs.change_message_visibility( QueueUrl=url["u"], ReceiptHandle=received["m"][0]["ReceiptHandle"], VisibilityTimeout=1 ) def delete_message(): sqs.delete_message(QueueUrl=url["u"], ReceiptHandle=received["m"][0]["ReceiptHandle"]) def delete_message_batch(): resp = sqs.delete_message_batch( QueueUrl=url["u"], Entries=[ {"Id": "1", "ReceiptHandle": received["m"][1]["ReceiptHandle"]}, {"Id": "2", "ReceiptHandle": received["m"][2]["ReceiptHandle"]}, ], ) assert len(resp["Successful"]) == 2 def tag_queue(): sqs.tag_queue(QueueUrl=url["u"], Tags={"env": "sdk", "owner": "test"}) tags = sqs.list_queue_tags(QueueUrl=url["u"]).get("Tags", {}) assert tags.get("env") == "sdk" sqs.untag_queue(QueueUrl=url["u"], TagKeys=["env", "owner"]) def purge_queue(): sqs.purge_queue(QueueUrl=url["u"]) def delete_queue(): sqs.delete_queue(QueueUrl=url["u"]) def fifo_cycle(): furl = sqs.create_queue(QueueName=qf, Attributes={"FifoQueue": "true"})["QueueUrl"] try: sqs.send_message( QueueUrl=furl, MessageBody="sdk-fifo", MessageGroupId="g1", MessageDeduplicationId="d1", ) msgs = sqs.receive_message(QueueUrl=furl, MaxNumberOfMessages=1).get("Messages", []) assert msgs and msgs[0]["Body"] == "sdk-fifo" sqs.delete_message(QueueUrl=furl, ReceiptHandle=msgs[0]["ReceiptHandle"]) finally: sqs.delete_queue(QueueUrl=furl) print("== Стандартная очередь ==") step("list_queues", list_queues) step("create_queue", create_queue) step("get_queue_url", get_queue_url) step("get_queue_attributes", get_queue_attributes) step("set_queue_attributes", set_queue_attributes) step("send_message", send_message) step("send_message_batch", send_message_batch) step("receive_message (3)", receive_messages) step("change_message_visibility", change_visibility) step("delete_message", delete_message) step("delete_message_batch", delete_message_batch) step("tag/list/untag", tag_queue) step("purge_queue", purge_queue) step("delete_queue", delete_queue) print("== FIFO-очередь ==") step("fifo: create/send/receive/delete", fifo_cycle) print(f"\nИтог: PASS={PASS} FAIL={FAIL}") return 1 if FAIL else 0 if __name__ == "__main__": sys.exit(main())