Update request-webapp-deployment command to handle deployment auction

This commit is contained in:
Prathamesh Musale 2024-09-27 15:53:47 +05:30
parent 8051a3fc6b
commit 61e1116e33
3 changed files with 166 additions and 77 deletions

View File

@ -107,6 +107,7 @@ def command(
"num_providers": num_providers, "num_providers": num_providers,
} }
auction_id = laconic.create_auction(provider_auction_params) auction_id = laconic.create_auction(provider_auction_params)
print("Deployment auction created:", auction_id)
if not auction_id: if not auction_id:
fatal("Unable to create a provider auction") fatal("Unable to create a provider auction")

View File

@ -24,16 +24,16 @@ import requests
import yaml import yaml
from stack_orchestrator.deploy.webapp.util import ( from stack_orchestrator.deploy.webapp.util import (
AUCTION_STATUS_COMPLETED,
AUCTION_KIND_PROVIDER,
LaconicRegistryClient, LaconicRegistryClient,
) )
from dotenv import dotenv_values from dotenv import dotenv_values
def fatal(msg: str): def fatal(msg: str):
print(msg, file=sys.stderr) print(msg, file=sys.stderr)
sys.exit(1) sys.exit(1)
@click.command() @click.command()
@click.option( @click.option(
"--laconic-config", help="Provide a config file for laconicd", required=True "--laconic-config", help="Provide a config file for laconicd", required=True
@ -43,10 +43,13 @@ def fatal(msg: str):
help="The LRN of the application to deploy.", help="The LRN of the application to deploy.",
required=True, required=True,
) )
@click.option(
"--auction-id",
help="Deployment auction id. Can be used instead of deployer and payment.",
)
@click.option( @click.option(
"--deployer", "--deployer",
help="The LRN of the deployer to process this request.", help="The LRN of the deployer to process this request.",
required=True,
) )
@click.option("--env-file", help="environment file for webapp") @click.option("--env-file", help="environment file for webapp")
@click.option("--config-ref", help="The ref of an existing config upload to use.") @click.option("--config-ref", help="The ref of an existing config upload to use.")
@ -68,6 +71,7 @@ def command(
ctx, ctx,
laconic_config, laconic_config,
app, app,
auction_id,
deployer, deployer,
env_file, env_file,
config_ref, config_ref,
@ -76,6 +80,17 @@ def command(
dns, dns,
dry_run, dry_run,
): # noqa: C901 ): # noqa: C901
if auction_id and deployer:
print("Cannot specify both --auction-id and --deployer", file=sys.stderr)
sys.exit(2)
if auction_id and (make_payment or use_payment):
print("Cannot specify --auction-id with --make-payment or --use-payment", file=sys.stderr)
sys.exit(2)
if env_file and config_ref:
fatal("Cannot use --env-file and --config-ref at the same time.")
tempdir = tempfile.mkdtemp() tempdir = tempfile.mkdtemp()
try: try:
laconic = LaconicRegistryClient(laconic_config) laconic = LaconicRegistryClient(laconic_config)
@ -84,13 +99,47 @@ def command(
if not app_record: if not app_record:
fatal(f"Unable to locate app: {app}") fatal(f"Unable to locate app: {app}")
# Deployers to send requests to
deployer_records = []
auction = None
auction_winners = None
if auction_id:
# Fetch auction details
auction = laconic.get_auction(auction_id)
if not auction:
fatal(f"Unable to locate auction: {auction_id}")
# Check auction kind
if auction.kind != AUCTION_KIND_PROVIDER:
fatal(f"Auction kind needs to be ${AUCTION_KIND_PROVIDER}, got {auction.kind}")
# Check auction status
if auction.status != AUCTION_STATUS_COMPLETED:
fatal(f"Auction {auction_id} not completed yet, status {auction.status}")
# Check that winner list is not empty
if len(auction.winnerAddresses) == 0:
fatal(f"Auction {auction_id} has no winners")
auction_winners = auction.winnerAddresses
# Get deloyer record for all the auction winners
for auction_winner in auction_winners:
deployer_records_by_owner = laconic.webapp_deployers({ "owner": auction_winner })
if len(deployer_records_by_owner) == 0:
print(f"WARNING: Unable to locate deployer for auction winner {auction_winner}")
deployer_records.append(deployer_records_by_owner[0])
else:
deployer_record = laconic.get_record(deployer) deployer_record = laconic.get_record(deployer)
if not deployer_record: if not deployer_record:
fatal(f"Unable to locate deployer: {deployer}") fatal(f"Unable to locate deployer: {deployer}")
if env_file and config_ref: deployer_records.append(deployer_records_by_owner[0])
fatal("Cannot use --env-file and --config-ref at the same time.")
# Create and send request to each deployer
for deployer_record in deployer_records:
# If env_file # If env_file
if env_file: if env_file:
gpg = gnupg.GPG(gnupghome=tempdir) gpg = gnupg.GPG(gnupghome=tempdir)

View File

@ -24,6 +24,10 @@ import tempfile
import uuid import uuid
import yaml import yaml
TOKEN_DENOM = "alnt"
AUCTION_KIND_PROVIDER = "provider"
AUCTION_STATUS_COMPLETED = "completed"
class AttrDict(dict): class AttrDict(dict):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs) super(AttrDict, self).__init__(*args, **kwargs)
@ -300,6 +304,34 @@ class LaconicRegistryClient:
if require: if require:
raise Exception("Cannot locate tx:", hash) raise Exception("Cannot locate tx:", hash)
def get_auction(self, auction_id, require=False):
args = [
"laconic",
"-c",
self.config_file,
"registry",
"auction",
"get",
"--id",
auction_id,
]
results = None
try:
results = [
AttrDict(r) for r in json.loads(logged_cmd(self.log_file, *args)) if r
]
except:
pass
if len(results):
return results[0]
if require:
raise Exception("Cannot locate auction:", auction_id)
return None
def app_deployment_requests(self, criteria=None, all=True): def app_deployment_requests(self, criteria=None, all=True):
if criteria is None: if criteria is None:
criteria = {} criteria = {}
@ -328,6 +360,13 @@ class LaconicRegistryClient:
criteria["type"] = "ApplicationDeploymentRemovalRecord" criteria["type"] = "ApplicationDeploymentRemovalRecord"
return self.list_records(criteria, all) return self.list_records(criteria, all)
def webapp_deployers(self, criteria=None, all=True):
if criteria is None:
criteria = {}
criteria = criteria.copy()
criteria["type"] = "WebappDeployer"
return self.list_records(criteria, all)
def publish(self, record, names=None): def publish(self, record, names=None):
if names is None: if names is None:
names = [] names = []