Handle deployment auction stages
Some checks failed
Lint Checks / Run linter (pull_request) Successful in 32s
Deploy Test / Run deploy test suite (pull_request) Failing after 1m22s
K8s Deploy Test / Run deploy test suite on kind/k8s (pull_request) Failing after 1m24s
K8s Deployment Control Test / Run deployment control suite on kind/k8s (pull_request) Failing after 1m17s
Webapp Test / Run webapp test suite (pull_request) Failing after 1m20s
Smoke Test / Run basic test suite (pull_request) Failing after 1m12s

This commit is contained in:
Prathamesh Musale 2024-10-01 17:36:17 +05:30
parent d79834a182
commit 08109355bc
3 changed files with 108 additions and 16 deletions

View File

@ -22,6 +22,8 @@ from stack_orchestrator.deploy.webapp.util import (
LaconicRegistryClient, LaconicRegistryClient,
TimedLogger, TimedLogger,
load_known_requests, load_known_requests,
AUCTION_KIND_PROVIDER,
AuctionStatus,
) )
@ -30,20 +32,65 @@ def process_app_deployment_auction(
laconic: LaconicRegistryClient, laconic: LaconicRegistryClient,
request, request,
current_status, current_status,
reveal_file_path,
bid_amount, bid_amount,
logger, logger,
): ):
logger.log("BEGIN - process_app_deployment_auction") # Fetch auction details
status = current_status auction_id = request.auction
auction = laconic.get_auction(auction_id)
if not auction:
raise Exception(f"Unable to locate auction: {auction_id}")
# TODO: # Check auction kind
# Check max_price, skip if bid_amount > max_price if auction.kind != AUCTION_KIND_PROVIDER:
# Check auction status raise Exception(f"Auction kind needs to be ${AUCTION_KIND_PROVIDER}, got {auction.kind}")
# Commit bid if auction in commit state
# Reveal bid if auction in reveal state
logger.log("END - process_app_deployment_auction") if current_status == "PENDING":
return status, "" # Skip if pending auction not in commit state
if auction.status != AuctionStatus.COMMIT:
logger(f"Skipping pending request, auction {auction_id} status: {auction.status}")
return "SKIP", ""
# Check max_price
if auction.max_price < bid_amount:
logger(f"Skipping auction {auction_id} with max_price ({auction.max_price}) less than bid_amount {bid_amount}")
return "SKIP", ""
# Bid on the auction
reveal_file_path = laconic.commit_bid(auction_id, bid_amount)
logger(f"Commited bid on auction {auction_id} with amount {bid_amount}")
return "COMMIT", reveal_file_path
if current_status == "COMMIT":
# Return if auction still in commit state
if auction.status == AuctionStatus.COMMIT:
logger(f"Auction {auction_id} status: {auction.status}")
return current_status, reveal_file_path
# Reveal bid
if auction.status == AuctionStatus.REVEAL:
laconic.reveal_bid(auction_id, reveal_file_path)
logger(f"Revealed bid on auction {auction_id}")
return "REVEAL", reveal_file_path
raise Exception(f"Unexpected auction {auction_id} status: {auction.status}")
if current_status == "REVEAL":
# Return if auction still in reveal state
if auction.status == AuctionStatus.REVEAL:
logger(f"Auction {auction_id} status: {auction.status}")
return current_status, reveal_file_path
# Return if auction still in completed state
if auction.status == AuctionStatus.COMPLETED:
return "COMPLETED", ""
raise Exception(f"Unexpected auction {auction_id} status: {auction.status}")
raise Exception(f"Got request with unexpected status: {current_status}")
def dump_known_auction_requests(filename, requests, status="SEEN"): def dump_known_auction_requests(filename, requests, status="SEEN"):
@ -103,6 +150,7 @@ def command(
for r in auctions_requests: for r in auctions_requests:
logger.log(f"BEGIN: Examining request {r.id}") logger.log(f"BEGIN: Examining request {r.id}")
result_status = "PENDING" result_status = "PENDING"
reveal_file_path = ""
try: try:
application = r.attributes.application application = r.attributes.application
@ -115,7 +163,8 @@ def command(
logger.log(f"Skipping request {r.id}, we've already seen it.") logger.log(f"Skipping request {r.id}, we've already seen it.")
continue continue
logger.log(f"Found existing auction {r.id} for application ${application}, status {current_status}.") reveal_file_path = previous_requests[r.id].get("revealFile", "")
logger.log(f"Found existing auction request {r.id} for application {application}, status {current_status}.")
else: else:
# It's a fresh request, check application record # It's a fresh request, check application record
app = laconic.get_record(application) app = laconic.get_record(application)
@ -127,7 +176,7 @@ def command(
logger.log(f"Found pending auction request {r.id} for application {application}.") logger.log(f"Found pending auction request {r.id} for application {application}.")
# Add requests to be processed # Add requests to be processed
requests_to_execute.append((r, result_status)) requests_to_execute.append((r, result_status, reveal_file_path))
except Exception as e: except Exception as e:
result_status = "ERROR" result_status = "ERROR"
@ -135,12 +184,16 @@ def command(
finally: finally:
logger.log(f"DONE Examining request {r.id} with result {result_status}.") logger.log(f"DONE Examining request {r.id} with result {result_status}.")
if result_status in ["ERROR"]: if result_status in ["ERROR"]:
dump_known_auction_requests(state_file, [AttrDict({"id": r.id, "revealFile": ""})], status=result_status) dump_known_auction_requests(
state_file,
[AttrDict({"id": r.id, "revealFile": reveal_file_path})],
status=result_status
)
logger.log(f"Found {len(requests_to_execute)} request(s) to process.") logger.log(f"Found {len(requests_to_execute)} request(s) to process.")
if not dry_run: if not dry_run:
for r, current_status in requests_to_execute: for r, current_status, reveal_file_path in requests_to_execute:
logger.log(f"Processing {r.id}: BEGIN") logger.log(f"Processing {r.id}: BEGIN")
result_status = "ERROR" result_status = "ERROR"
try: try:
@ -149,6 +202,7 @@ def command(
laconic, laconic,
r, r,
current_status, current_status,
reveal_file_path,
bid_amount, bid_amount,
logger, logger,
) )

View File

@ -187,14 +187,13 @@ def command( # noqa: C901
"application": app, "application": app,
"version": "1.0.0", "version": "1.0.0",
"name": f"{app_record.attributes.name}@{app_record.attributes.version}", "name": f"{app_record.attributes.name}@{app_record.attributes.version}",
"deployer": deployer,
"meta": {"when": str(datetime.utcnow())}, "meta": {"when": str(datetime.utcnow())},
} }
} }
if auction_id: if auction_id:
deployment_request["record"]["auction"] = auction_id deployment_request["record"]["auction"] = auction_id
else:
deployment_request["record"]["deployer"] = deployer
if config_ref: if config_ref:
deployment_request["record"]["config"] = {"ref": config_ref} deployment_request["record"]["config"] = {"ref": config_ref}

View File

@ -24,9 +24,18 @@ import tempfile
import uuid import uuid
import yaml import yaml
from enum import Enum
class AuctionStatus(str, Enum):
COMMIT = "commit"
REVEAL = "reveal"
COMPLETED = "completed"
EXPIRED = "expired"
TOKEN_DENOM = "alnt" TOKEN_DENOM = "alnt"
AUCTION_KIND_PROVIDER = "provider" AUCTION_KIND_PROVIDER = "provider"
AUCTION_STATUS_COMPLETED = "completed"
class AttrDict(dict): class AttrDict(dict):
@ -507,6 +516,36 @@ class LaconicRegistryClient:
return json.loads(logged_cmd(self.log_file, *args))["auctionId"] return json.loads(logged_cmd(self.log_file, *args))["auctionId"]
def commit_bid(self, auction_id, amount, type="alnt"):
args = [
"laconic",
"-c",
self.config_file,
"registry",
"auction",
"bid",
"commit",
auction_id,
str(amount),
type,
]
return json.loads(logged_cmd(self.log_file, *args))["reveal_file"]
def reveal_bid(self, auction_id, reveal_file_path):
logged_cmd(
self.log_file,
"laconic",
"-c",
self.config_file,
"registry",
"auction",
"bid",
"reveal",
auction_id,
reveal_file_path,
)
def file_hash(filename): def file_hash(filename):
return hashlib.sha1(open(filename).read().encode()).hexdigest() return hashlib.sha1(open(filename).read().encode()).hexdigest()