diff --git a/.github/workflows/update-paev.yaml b/.github/workflows/update-paev.yaml index 4e1ebb7b..817a0622 100644 --- a/.github/workflows/update-paev.yaml +++ b/.github/workflows/update-paev.yaml @@ -8,40 +8,43 @@ on: default: 'odin' type: choice options: - - odin - - heimdall - - thor + - odin + - heimdall + - thor description: 'Choose the mainnet network to update the appsettings.json' - previous_version_block_index: + new_start_value: required: true - description: 'Insert the ending tip index of the previous version (e.g. 1115268)' - previous_version_lib9c_commit: + description: 'The new start index (e.g. 20000000)' + new_plugin_url: required: true - description: 'Insert the lib9c commit of the previous version (e.g. ff2c8ae6cfd030ffd20020e1a5bbc4e0caadfe97)' + description: 'The plugin URL for the newly added evaluator (e.g. https://lib9c-plugin.s3.us-east-2.amazonaws.com/678ac90398f376698ee75da63ed089fe678d11e6/linux-arm64.zip)' jobs: update-paev: runs-on: ubuntu-latest steps: - - name: Checkout Repository - uses: actions/checkout@v2 + - name: Checkout Repository + uses: actions/checkout@v2 - - uses: actions/setup-python@v2.2.2 - with: - python-version: 3.10.13 + - uses: actions/setup-python@v2.2.2 + with: + python-version: 3.10.13 - - run: | - python -m pip install -r requirements.txt - flit install - name: install dependencies - working-directory: ./scripts + - name: install dependencies + run: | + python -m pip install -r requirements.txt + flit install + working-directory: ./scripts - - name: Update Pluggable Action Evaluator - run: | - python cli.py update-paev ${{ github.event.inputs.network_type }} ${{ github.event.inputs.previous_version_block_index }} ${{ github.event.inputs.previous_version_lib9c_commit }} - working-directory: ./scripts - env: - GITHUB_TOKEN: ${{ secrets.P_GITHUB_TOKEN }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + - name: Update Pluggable Action Evaluator + run: | + python cli.py update-paev \ + ${{ github.event.inputs.network_type }} \ + ${{ github.event.inputs.new_start_value }} \ + ${{ github.event.inputs.new_plugin_url }} + working-directory: ./scripts + env: + GITHUB_TOKEN: ${{ secrets.P_GITHUB_TOKEN }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} diff --git a/scripts/app/update_paev.py b/scripts/app/update_paev.py index 2ba9825d..ae16577f 100644 --- a/scripts/app/update_paev.py +++ b/scripts/app/update_paev.py @@ -14,92 +14,100 @@ def __init__(self) -> None: def prep_update( self, - network_type, - previous_version_block_index, - previous_version_lib9c_commit): + network_type: str, + new_start_value: int, + new_plugin_url: str + ): + """ + Prepares and updates the PAEV configuration for both appsettings.json + and appsettings-nodeinfra.json by computing cutoff_value automatically. + """ + cutoff_value = new_start_value - 1 # always set cutoff_value to new_start_value - 1 - # Define base URL and suffixes - base_url = "https://lib9c-plugin.s3.us-east-2.amazonaws.com/" - arm64_suffix = "/linux-arm64.zip" - x64_suffix = "/linux-x64.zip" - - # Define URLs based on network type paev_urls = [ f"https://9c-cluster-config.s3.us-east-2.amazonaws.com/9c-main/{network_type}/appsettings.json", f"https://9c-cluster-config.s3.us-east-2.amazonaws.com/9c-main/{network_type}/appsettings-nodeinfra.json", ] - # Iterate over each URL in the list for url in paev_urls: - # Choose the suffix based on the presence of "nodeinfra" - suffix = x64_suffix if "nodeinfra" in url else arm64_suffix - - # Construct the plugin URL - plugin_url = f"{base_url}{previous_version_lib9c_commit}{suffix}" - - # Call update function - self.update(url, previous_version_block_index, plugin_url) + self.update(url, cutoff_value, new_start_value, new_plugin_url) def update( self, - paev_url, - end_value, - lib9c_plugin_url): - - # Check if both URLs exist - if url_exists(paev_url) and url_exists(lib9c_plugin_url): - print("Both URLs are valid and accessible.") - - # Download the file - url = paev_url - response = requests.get(url) - data = response.json() - - # Define new values for appending and updating - start_value = 0 - new_start_value = end_value + 1 - - # Navigate to the correct location - if 'pairs' in data['Headless']['ActionEvaluator']: - - # Append the new value - pairs = data['Headless']['ActionEvaluator']['pairs'] - insert_index = next((i for i, pair in enumerate(pairs) if pair['actionEvaluator'].get('type') == 'Default'), None) - start_value = pairs[insert_index - 1]['range']['end'] + 1 - - value_to_append = { - "range": { - "start": start_value, - "end": end_value - }, - "actionEvaluator": { - "type": "PluggedActionEvaluator", - "pluginPath": lib9c_plugin_url - } - } - - if insert_index is not None: - pairs[insert_index]['range']['start'] = new_start_value - pairs.insert(insert_index, value_to_append) - else: - raise Exception("The specified range was not found in the pairs.") - - else: - raise Exception("The specified structure does not exist in the provided JSON data.") - - # Upload the modified file back to S3 - s3_resource = boto3.resource('s3') - bucket_name = '9c-cluster-config' # Replace with your actual bucket name - file_name = extract_path_from_url(paev_url) # Replace with the S3 path for the upload - - # Convert the modified data back to JSON string - file_content = json.dumps(data, indent=4) - s3_resource.Object(bucket_name, file_name).put(Body=file_content, ContentType='application/json') - - print(data) - print(f"File uploaded successfully to {paev_url}.") - else: - raise Exception("One or both URLs are not accessible. Please check the URLs and try again.") + paev_url: str, + cutoff_value: int, + new_start_value: int, + new_plugin_url: str, + bucket_name: str = "9c-cluster-config" + ): + """ + 1. Download the appsettings.json from paev_url. + 2. Modify the last evaluator so that its end = cutoff_value. + 3. Append a new evaluator that starts at new_start_value and ends at a very large number. + 4. Upload updated JSON back to S3. + """ + + # Example logic adapted to your code: + import boto3 + import requests + import json + from urllib.parse import urlparse + + def url_exists(url): + try: + resp = requests.head(url, allow_redirects=True) + return resp.status_code == 200 + except requests.exceptions.RequestException as e: + print(f"Error checking URL {url}: {e}") + return False + + def extract_path_from_url(url): + parsed = urlparse(url) + return parsed.path.lstrip('/') + + if not url_exists(paev_url): + raise Exception(f"URL not accessible: {paev_url}") + if not url_exists(new_plugin_url): + raise Exception(f"Plugin URL not accessible: {new_plugin_url}") + + resp = requests.get(paev_url) + if resp.status_code != 200: + raise Exception(f"Failed to download JSON from {paev_url}, status: {resp.status_code}") + + data = resp.json() + + pairs = data.get('Headless', {}).get('ActionEvaluator', {}).get('pairs', []) + if not pairs: + raise Exception("No pairs found in ActionEvaluator configuration.") + + # Modify the last pair + last_pair = pairs[-1] + last_pair['range']['end'] = cutoff_value + + # Append the new pair + new_pair = { + "range": { + "start": new_start_value, + "end": 9223372036854775807 + }, + "actionEvaluator": { + "type": "PluggedActionEvaluator", + "pluginPath": new_plugin_url + } + } + pairs.append(new_pair) + + # Upload updated JSON back to S3 + s3_resource = boto3.resource('s3') + file_content = json.dumps(data, indent=4) + file_name = extract_path_from_url(paev_url) + + s3_resource.Object(bucket_name, file_name).put( + Body=file_content, + ContentType='application/json' + ) + + print(f"Successfully updated {paev_url} with new evaluator from {cutoff_value} to {new_start_value}.") def url_exists(url): try: diff --git a/scripts/cli.py b/scripts/cli.py index 22dfb089..7b2e290d 100644 --- a/scripts/cli.py +++ b/scripts/cli.py @@ -86,21 +86,16 @@ def update_apv( @k8s_app.command() def update_paev( - network_type: str = typer.Argument( - ..., - ), - previous_version_block_index: int = typer.Argument( - ..., - ), - previous_version_lib9c_commit: str = typer.Argument( - ..., - ), + network_type: str = typer.Argument(..., help="e.g. mainnet, internal, etc."), + new_start_value: int = typer.Argument(..., help="The start index for the newly added evaluator (e.g. 20000000)"), + new_plugin_url: str = typer.Argument(..., help="The plugin URL for the newly added evaluator"), ): """ - Run post deploy script + Update the PluggableActionEvaluator (PAEV) configuration. + This modifies the last evaluator so that it ends at new_start_value - 1, + then appends a new evaluator starting at new_start_value. """ - - PluggableActionEvaluatorUpdater().prep_update(network_type, previous_version_block_index, previous_version_lib9c_commit) + PluggableActionEvaluatorUpdater().prep_update(network_type, new_start_value, new_plugin_url) if __name__ == "__main__": k8s_app()