Skip to content
Merged
9 changes: 8 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,11 @@ kurtosis run . --args-file network_params.yaml
- All orchestration logic is written in Starlark (.star files)
- Configuration templates are stored in static_files/
- Each service runs in isolated containers managed by Kurtosis
- Resource limits and network parameters are highly configurable
- Resource limits and network parameters are highly configurable

## Required Development Workflow
**CRITICAL:** Before any git commits or pushes, Claude MUST run:
```bash
kurtosis lint --format
```
This command formats Starlark code and validates syntax. All changes must pass linting before being committed or pushed to any branch.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1349,6 +1349,14 @@ First, install prerequisites:
Then, run the dev loop:

1. Make your code changes
1. **Run the linter to format and check your code:**

```bash
kurtosis lint --format
```

This ensures your Starlark code follows the project's formatting standards and catches any syntax issues.

1. Rebuild and re-run the package by running the following from the root of the repo:

```bash
Expand Down
16 changes: 16 additions & 0 deletions main.star
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ blobscan = import_module("./src/blobscan/blobscan_launcher.star")
forky = import_module("./src/forky/forky_launcher.star")
tracoor = import_module("./src/tracoor/tracoor_launcher.star")
apache = import_module("./src/apache/apache_launcher.star")
nginx = import_module("./src/nginx/nginx_launcher.star")
full_beaconchain_explorer = import_module(
"./src/full_beaconchain/full_beaconchain_launcher.star"
)
Expand Down Expand Up @@ -87,6 +88,7 @@ def run(plan, args={}):
global_node_selectors = args_with_right_defaults.global_node_selectors
keymanager_enabled = args_with_right_defaults.keymanager_enabled
apache_port = args_with_right_defaults.apache_port
nginx_port = args_with_right_defaults.nginx_port
docker_cache_params = args_with_right_defaults.docker_cache_params

prefunded_accounts = genesis_constants.PRE_FUNDED_ACCOUNTS
Expand Down Expand Up @@ -624,6 +626,20 @@ def run(plan, args={}):
args_with_right_defaults.docker_cache_params,
)
plan.print("Successfully launched apache")
elif additional_service == "nginx":
plan.print("Launching nginx")
nginx.launch_nginx(
plan,
el_cl_data_files_artifact_uuid,
nginx_port,
all_participants,
args_with_right_defaults.participants,
args_with_right_defaults.port_publisher,
index,
global_node_selectors,
args_with_right_defaults.docker_cache_params,
)
plan.print("Successfully launched nginx")
elif additional_service == "full_beaconchain_explorer":
plan.print("Launching full-beaconchain-explorer")
full_beaconchain_explorer_config_template = read_file(
Expand Down
1 change: 1 addition & 0 deletions network_params.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ xatu_sentry_params:
- contribution_and_proof
- blob_sidecar
apache_port: 40000
nginx_port: 50000
global_tolerations: []
global_node_selectors: {}
keymanager_enabled: false
Expand Down
189 changes: 189 additions & 0 deletions src/nginx/nginx_launcher.star
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
shared_utils = import_module("../shared_utils/shared_utils.star")
static_files = import_module("../static_files/static_files.star")
constants = import_module("../package_io/constants.star")
SERVICE_NAME = "nginx"
HTTP_PORT_ID = "http"
HTTP_PORT_NUMBER = 80
NGINX_CONFIG_FILENAME = "index.html"
NGINX_ENR_FILENAME = "boot_enr.yaml"
NGINX_ENODE_FILENAME = "bootnode.txt"
NGINX_ENR_LIST_FILENAME = "bootstrap_nodes.txt"

NGINX_CONFIG_MOUNT_DIRPATH_ON_SERVICE = "/usr/share/nginx/html/"

IMAGE_NAME = "nginx:latest"
# The min/max CPU/memory that nginx can use
MIN_CPU = 100
MAX_CPU = 300
MIN_MEMORY = 128
MAX_MEMORY = 256

USED_PORTS = {
HTTP_PORT_ID: shared_utils.new_port_spec(
HTTP_PORT_NUMBER,
shared_utils.TCP_PROTOCOL,
shared_utils.HTTP_APPLICATION_PROTOCOL,
)
}


def launch_nginx(
plan,
el_cl_genesis_data,
nginx_port,
participant_contexts,
participant_configs,
port_publisher,
index,
global_node_selectors,
docker_cache_params,
):
config_files_artifact_name = plan.upload_files(
src=static_files.NGINX_CONFIG_FILEPATH, name="nginx-config"
)

public_ports = shared_utils.get_additional_service_standard_public_port(
port_publisher,
constants.HTTP_PORT_ID,
index,
0,
)

all_cl_client_info = []
all_el_client_info = []
for index, participant in enumerate(participant_contexts):
_, cl_client, el_client, _ = shared_utils.get_client_names(
participant, index, participant_contexts, participant_configs
)
all_cl_client_info.append(new_cl_client_info(cl_client.enr))
all_el_client_info.append(new_el_client_info(el_client.enode))

template_data = new_config_template_data(
all_cl_client_info,
all_el_client_info,
)

enr_template_and_data = shared_utils.new_template_and_data(
read_file(static_files.NGINX_ENR_FILEPATH),
template_data,
)

enr_list_template_and_data = shared_utils.new_template_and_data(
read_file(static_files.NGINX_ENR_LIST_FILEPATH),
template_data,
)

enode_template_and_data = shared_utils.new_template_and_data(
read_file(static_files.NGINX_ENODE_FILEPATH),
template_data,
)

template_and_data_by_rel_dest_filepath = {}
template_and_data_by_rel_dest_filepath[NGINX_ENR_FILENAME] = enr_template_and_data
template_and_data_by_rel_dest_filepath[
NGINX_ENR_LIST_FILENAME
] = enr_list_template_and_data
template_and_data_by_rel_dest_filepath[
NGINX_ENODE_FILENAME
] = enode_template_and_data

bootstrap_info_files_artifact_name = plan.render_templates(
template_and_data_by_rel_dest_filepath, "nginx-bootstrap-info"
)

if nginx_port != None:
public_ports = {
HTTP_PORT_ID: shared_utils.new_port_spec(
nginx_port, shared_utils.TCP_PROTOCOL
)
}

config = get_config(
config_files_artifact_name,
el_cl_genesis_data,
public_ports,
bootstrap_info_files_artifact_name,
global_node_selectors,
docker_cache_params,
)

plan.add_service(SERVICE_NAME, config)


def get_config(
config_files_artifact_name,
el_cl_genesis_data,
public_ports,
bootstrap_info_files_artifact_name,
node_selectors,
docker_cache_params,
):
files = {
constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data,
constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS
+ "/boot": bootstrap_info_files_artifact_name,
NGINX_CONFIG_MOUNT_DIRPATH_ON_SERVICE: config_files_artifact_name,
}

cmd = [
"mv",
"/network-configs/boot/" + NGINX_ENR_FILENAME,
"/network-configs/" + NGINX_ENR_FILENAME,
"&&",
"mv",
"/network-configs/boot/" + NGINX_ENODE_FILENAME,
"/network-configs/" + NGINX_ENODE_FILENAME,
"&&",
"mv",
"/network-configs/boot/" + NGINX_ENR_LIST_FILENAME,
"/network-configs/" + NGINX_ENR_LIST_FILENAME,
"&&",
"cp -R /network-configs /usr/share/nginx/html/",
"&&",
"tar",
"-czvf",
"/usr/share/nginx/html/network-config.tar",
"-C",
"/network-configs/",
".",
"&&",
'nginx -g "daemon off;"',
]

cmd_str = " ".join(cmd)

return ServiceConfig(
image=shared_utils.docker_cache_image_calc(
docker_cache_params,
IMAGE_NAME,
),
ports=USED_PORTS,
public_ports=public_ports,
cmd=[cmd_str],
entrypoint=["sh", "-c"],
files=files,
min_cpu=MIN_CPU,
max_cpu=MAX_CPU,
min_memory=MIN_MEMORY,
max_memory=MAX_MEMORY,
node_selectors=node_selectors,
)


def new_config_template_data(cl_client, el_client):
return {
"CLClient": cl_client,
"ELClient": el_client,
}


def new_cl_client_info(enr):
return {
"Enr": enr,
}


def new_el_client_info(enode):
return {
"Enode": enode,
}
2 changes: 2 additions & 0 deletions src/package_io/input_parser.star
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ def input_parser(plan, input_args):
image=result["grafana_params"]["image"],
),
apache_port=result["apache_port"],
nginx_port=result["nginx_port"],
assertoor_params=struct(
image=result["assertoor_params"]["image"],
run_stability_check=result["assertoor_params"]["run_stability_check"],
Expand Down Expand Up @@ -972,6 +973,7 @@ def default_input_args(input_args):
"mev_type": None,
"xatu_sentry_enabled": False,
"apache_port": None,
"nginx_port": None,
"global_tolerations": [],
"global_node_selectors": {},
"use_remote_signer": False,
Expand Down
2 changes: 2 additions & 0 deletions src/package_io/sanity_check.star
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ ADDITIONAL_SERVICES_PARAMS = [
"blutgang",
"forky",
"apache",
"nginx",
"tracoor",
"spamoor",
]
Expand All @@ -340,6 +341,7 @@ ADDITIONAL_CATEGORY_PARAMS = {
"mev_type": "",
"xatu_sentry_enabled": "",
"apache_port": "",
"nginx_port": "",
"global_tolerations": "",
"global_node_selectors": "",
"keymanager_enabled": "",
Expand Down
5 changes: 5 additions & 0 deletions src/static_files/static_files.star
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ APACHE_ENR_FILEPATH = STATIC_FILES_DIRPATH + "/apache-config/enr.txt.tmpl"
APACHE_ENR_LIST_FILEPATH = STATIC_FILES_DIRPATH + "/apache-config/enr_list.txt.tmpl"
APACHE_ENODE_FILEPATH = STATIC_FILES_DIRPATH + "/apache-config/enode.txt.tmpl"

NGINX_CONFIG_FILEPATH = STATIC_FILES_DIRPATH + "/nginx-config/index.html"
NGINX_ENR_FILEPATH = STATIC_FILES_DIRPATH + "/nginx-config/enr.txt.tmpl"
NGINX_ENR_LIST_FILEPATH = STATIC_FILES_DIRPATH + "/nginx-config/enr_list.txt.tmpl"
NGINX_ENODE_FILEPATH = STATIC_FILES_DIRPATH + "/nginx-config/enode.txt.tmpl"

DORA_CONFIG_TEMPLATE_FILEPATH = STATIC_FILES_DIRPATH + "/dora-config/config.yaml.tmpl"
DUGTRIO_CONFIG_TEMPLATE_FILEPATH = (
STATIC_FILES_DIRPATH + "/dugtrio-config/config.yaml.tmpl"
Expand Down
3 changes: 3 additions & 0 deletions static_files/nginx-config/enode.txt.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{{ range $elClient := .ELClient }}
{{ $elClient.Enode }}
{{- end }}
3 changes: 3 additions & 0 deletions static_files/nginx-config/enr.txt.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{{ range $clClient := .CLClient }}
- {{ $clClient.Enr }}
{{- end }}
3 changes: 3 additions & 0 deletions static_files/nginx-config/enr_list.txt.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{{ range $clClient := .CLClient }}
{{ $clClient.Enr }}
{{- end }}
50 changes: 50 additions & 0 deletions static_files/nginx-config/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to My Website</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
}
.container {
max-width: 800px;
margin: 20px auto;
padding: 20px;
background-color: #fff;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
h1 {
color: #333;
text-align: center;
}
.download-btn {
display: block;
width: 200px;
margin: 20px auto;
padding: 10px;
text-align: center;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
text-decoration: none; /* Remove underline */
}
.download-btn:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="container">
<h1>Welcome to Kurtosis File sharing site</h1>
<a href="network-config.tar" class="download-btn">Download network configs</a>
</div>
</body>
</html>
Loading