Skip to content

Commit c9b423a

Browse files
feat: update to use the localnet specific conduit algod importer (#700)
* feat: updating to use new localnet conduit importer * chore: removing nginx proxy as it is no longer needed * chore: removing version from the generated algod_config.json so we always use the latest version. --------- Co-authored-by: Aidan Morgan <[email protected]>
1 parent 53c8e2e commit c9b423a

25 files changed

+110
-406
lines changed

src/algokit/cli/localnet.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ def reset_localnet(*, update: bool, config_path: Path | None, check: bool) -> No
273273
sandbox.up()
274274

275275

276-
SERVICE_NAMES = ("algod", "conduit", "indexer-db", "indexer", "proxy")
276+
SERVICE_NAMES = ("algod", "conduit", "indexer-db", "indexer")
277277

278278

279279
@localnet_group.command("status", short_help="Check the status of the AlgoKit LocalNet.")
@@ -303,10 +303,10 @@ def localnet_status(*, check: bool) -> None:
303303
}
304304
# fill out remaining output_by_name["algod"] values
305305
if output_by_name["algod"]["Status"] == "Running":
306-
output_by_name["algod"].update(fetch_algod_status_data(ps_by_name["proxy"]))
306+
output_by_name["algod"].update(fetch_algod_status_data(ps_by_name["algod"]))
307307
# fill out remaining output_by_name["indexer"] values
308308
if output_by_name["indexer"]["Status"] == "Running":
309-
output_by_name["indexer"].update(fetch_indexer_status_data(ps_by_name["proxy"]))
309+
output_by_name["indexer"].update(fetch_indexer_status_data(ps_by_name["indexer"]))
310310

311311
# Print the status details
312312
for service_name, service_info in output_by_name.items():

src/algokit/core/sandbox.py

Lines changed: 37 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ def __init__(self, name: str = SANDBOX_BASE_NAME, config_path: Path | None = Non
5858
self._latest_yaml = get_docker_compose_yml(name=f"algokit_{self.name}")
5959
self._latest_config_json = get_config_json()
6060
self._latest_algod_network_template = get_algod_network_template()
61-
self._latest_proxy_config = get_proxy_config()
6261

6362
@property
6463
def compose_file_path(self) -> Path:
@@ -76,10 +75,6 @@ def algod_config_file_path(self) -> Path:
7675
def algod_network_template_file_path(self) -> Path:
7776
return self.directory / "algod_network_template.json"
7877

79-
@property
80-
def proxy_config_file_path(self) -> Path:
81-
return self.directory / "nginx.conf"
82-
8378
@classmethod
8479
def from_environment(cls) -> ComposeSandbox | None:
8580
try:
@@ -148,7 +143,6 @@ def compose_file_status(self) -> ComposeFileStatus:
148143
compose_content = self.compose_file_path.read_text()
149144
config_content = self.algod_config_file_path.read_text()
150145
algod_network_template_content = self.algod_network_template_file_path.read_text()
151-
proxy_config_content = self.proxy_config_file_path.read_text()
152146

153147
except FileNotFoundError:
154148
# treat as out of date if compose file exists but algod config doesn't
@@ -157,32 +151,38 @@ def compose_file_status(self) -> ComposeFileStatus:
157151
return ComposeFileStatus.OUT_OF_DATE
158152
return ComposeFileStatus.MISSING
159153
else:
160-
algod_network_json_content = json.loads(
161-
algod_network_template_content.replace("NUM_ROUNDS", '"NUM_ROUNDS"')
162-
)
163-
latest_algod_network_json_content = json.loads(
164-
self._latest_algod_network_template.replace("NUM_ROUNDS", '"NUM_ROUNDS"')
165-
)
166-
167-
del algod_network_json_content["Genesis"]["DevMode"]
168-
del latest_algod_network_json_content["Genesis"]["DevMode"]
169-
170-
if (
171-
compose_content == self._latest_yaml
172-
and config_content == self._latest_config_json
173-
and algod_network_json_content == latest_algod_network_json_content
174-
and proxy_config_content == self._latest_proxy_config
175-
):
176-
return ComposeFileStatus.UP_TO_DATE
177-
else:
154+
try:
155+
# Perform some content normalization to ensure we correctly detect up to date files
156+
157+
# Ensure the NUM_ROUNDS placeholder is the same in both files
158+
algod_network_json_content = json.loads(
159+
algod_network_template_content.replace("NUM_ROUNDS", '"NUM_ROUNDS"')
160+
)
161+
latest_algod_network_json_content = json.loads(
162+
self._latest_algod_network_template.replace("NUM_ROUNDS", '"NUM_ROUNDS"')
163+
)
164+
165+
# Remove DevMode from comparison as the value is configurable via the `--dev` option
166+
del algod_network_json_content["Genesis"]["DevMode"]
167+
del latest_algod_network_json_content["Genesis"]["DevMode"]
168+
169+
if (
170+
compose_content == self._latest_yaml
171+
and config_content == self._latest_config_json
172+
and algod_network_json_content == latest_algod_network_json_content
173+
):
174+
return ComposeFileStatus.UP_TO_DATE
175+
else:
176+
return ComposeFileStatus.OUT_OF_DATE
177+
except (json.JSONDecodeError, KeyError):
178+
# If config files are corrupted or malformed, treat as out of date
178179
return ComposeFileStatus.OUT_OF_DATE
179180

180181
def write_compose_file(self) -> None:
181182
self.conduit_file_path.write_text(self._conduit_yaml)
182183
self.compose_file_path.write_text(self._latest_yaml)
183184
self.algod_config_file_path.write_text(self._latest_config_json)
184185
self.algod_network_template_file_path.write_text(self._latest_algod_network_template)
185-
self.proxy_config_file_path.write_text(self._latest_proxy_config)
186186

187187
def _run_compose_command(
188188
self,
@@ -328,7 +328,7 @@ def check_docker_compose_for_new_image_versions(self, *, force: bool = False) ->
328328
INDEXER_HEALTH_URL = f"{DEFAULT_INDEXER_SERVER}:{DEFAULT_INDEXER_PORT}/health"
329329
INDEXER_IMAGE = "algorand/indexer:latest"
330330
ALGORAND_IMAGE = "algorand/algod:latest"
331-
CONDUIT_IMAGE = "algorand/conduit:latest"
331+
CONDUIT_IMAGE = "algorandfoundation/conduit-localnet:latest"
332332
IMAGE_VERSION_CHECK_INTERVAL = timedelta(weeks=1).total_seconds()
333333

334334

@@ -440,8 +440,9 @@ def _wait_for_indexer() -> bool:
440440

441441
def get_config_json() -> str:
442442
return (
443-
'{ "Version": 12, "GossipFanout": 1, "EndpointAddress": "0.0.0.0:8080", "DNSBootstrapID": "",'
444-
' "IncomingConnectionsLimit": 0, "Archival":true, "isIndexerActive":false, "EnableDeveloperAPI":true}'
443+
'{ "GossipFanout": 1, "EndpointAddress": "0.0.0.0:8080", "DNSBootstrapID": "",'
444+
' "IncomingConnectionsLimit": 0, "Archival":true, "isIndexerActive":false, "EnableDeveloperAPI":true,'
445+
' "EnablePrivateNetworkAccessHeader":true}'
445446
)
446447

447448

@@ -512,7 +513,7 @@ def get_conduit_yaml() -> str:
512513
retry-count: 10
513514
514515
# Time duration to wait between retry attempts.
515-
retry-delay: "1s"
516+
retry-delay: "5s"
516517
517518
# Optional filepath to use for pidfile.
518519
#pid-filepath: /path/to/pidfile
@@ -528,20 +529,10 @@ def get_conduit_yaml() -> str:
528529
529530
# The importer is typically an algod follower node.
530531
importer:
531-
name: algod
532+
name: localnet_algod
532533
config:
533-
# The mode of operation, either "archival" or "follower".
534-
# * archival mode allows you to start processing on any round but does not
535-
# contain the ledger state delta objects required for the postgres writer.
536-
# * follower mode allows you to use a lightweight non-archival node as the
537-
# data source. In addition, it will provide ledger state delta objects to
538-
# the processors and exporter.
539-
mode: "follower"
540-
541-
# Algod API address.
542-
netaddr: "http://algod:8081"
543-
544-
# Algod API token.
534+
lead-node-url: "http://algod:8080"
535+
follower-node-url: "http://algod:8081"
545536
token: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
546537
547538
# Zero or more processors may be defined to manipulate what data
@@ -563,70 +554,6 @@ def get_conduit_yaml() -> str:
563554
"""
564555

565556

566-
def get_proxy_config(algod_port: int = DEFAULT_ALGOD_PORT, kmd_port: int = 4002) -> str:
567-
return f"""worker_processes 1;
568-
569-
events {{
570-
worker_connections 1024;
571-
}}
572-
573-
http {{
574-
access_log off;
575-
576-
resolver 127.0.0.11 ipv6=off valid=10s;
577-
resolver_timeout 5s;
578-
client_max_body_size 0;
579-
580-
map $request_method$http_access_control_request_private_network $cors_allow_private_network {{
581-
"OPTIONStrue" "true";
582-
default "";
583-
}}
584-
585-
add_header Access-Control-Allow-Private-Network $cors_allow_private_network;
586-
587-
server {{
588-
listen {algod_port};
589-
590-
location / {{
591-
proxy_http_version 1.1;
592-
proxy_read_timeout 120s;
593-
proxy_set_header Host $host;
594-
proxy_set_header Connection "";
595-
proxy_pass_header Server;
596-
set $target http://algod:8080;
597-
proxy_pass $target;
598-
}}
599-
}}
600-
601-
server {{
602-
listen {kmd_port};
603-
604-
location / {{
605-
proxy_http_version 1.1;
606-
proxy_set_header Host $host;
607-
proxy_set_header Connection "";
608-
proxy_pass_header Server;
609-
set $target http://algod:7833;
610-
proxy_pass $target;
611-
}}
612-
}}
613-
614-
server {{
615-
listen 8980;
616-
617-
location / {{
618-
proxy_http_version 1.1;
619-
proxy_set_header Host $host;
620-
proxy_set_header Connection "";
621-
proxy_pass_header Server;
622-
set $target http://indexer:8980;
623-
proxy_pass $target;
624-
}}
625-
}}
626-
}}
627-
"""
628-
629-
630557
def get_docker_compose_yml(
631558
name: str = "algokit_sandbox",
632559
algod_port: int = DEFAULT_ALGOD_PORT,
@@ -640,7 +567,8 @@ def get_docker_compose_yml(
640567
container_name: "{name}_algod"
641568
image: {ALGORAND_IMAGE}
642569
ports:
643-
- 7833
570+
- {algod_port}:8080
571+
- {kmd_port}:7833
644572
- {tealdbg_port}:9392
645573
environment:
646574
START_KMD: 1
@@ -684,28 +612,14 @@ def get_docker_compose_yml(
684612
indexer:
685613
container_name: "{name}_indexer"
686614
image: {INDEXER_IMAGE}
615+
ports:
616+
- 8980:8980
687617
restart: unless-stopped
688618
command: daemon --enable-all-parameters
689619
environment:
690620
INDEXER_POSTGRES_CONNECTION_STRING: "host=indexer-db port=5432 user=algorand password=algorand dbname=indexerdb sslmode=disable"
691621
depends_on:
692622
- conduit
693-
694-
proxy:
695-
container_name: "{name}_proxy"
696-
image: nginx:1.27.0-alpine
697-
restart: unless-stopped
698-
ports:
699-
- {algod_port}:{algod_port}
700-
- {kmd_port}:{kmd_port}
701-
- 8980:8980
702-
volumes:
703-
- type: bind
704-
source: ./nginx.conf
705-
target: /etc/nginx/nginx.conf
706-
depends_on:
707-
- algod
708-
- indexer
709623
""" # noqa: E501
710624

711625

tests/goal/test_goal.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
get_algod_network_template,
1313
get_config_json,
1414
get_docker_compose_yml,
15-
get_proxy_config,
1615
)
1716
from tests.utils.app_dir_mock import AppDirs
1817
from tests.utils.approvals import verify
@@ -51,7 +50,6 @@ def _setup_latest_dummy_compose(app_dir_mock: AppDirs) -> None:
5150
(app_dir_mock.app_config_dir / "sandbox" / "docker-compose.yml").write_text(get_docker_compose_yml())
5251
(app_dir_mock.app_config_dir / "sandbox" / "algod_config.json").write_text(get_config_json())
5352
(app_dir_mock.app_config_dir / "sandbox" / "algod_network_template.json").write_text(get_algod_network_template())
54-
(app_dir_mock.app_config_dir / "sandbox" / "nginx.conf").write_text(get_proxy_config())
5553

5654

5755
@pytest.fixture

tests/localnet/test_localnet_console.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pytest
55
from pytest_mock import MockerFixture
66

7-
from algokit.core.sandbox import get_algod_network_template, get_config_json, get_docker_compose_yml, get_proxy_config
7+
from algokit.core.sandbox import get_algod_network_template, get_config_json, get_docker_compose_yml
88
from tests.goal.test_goal import _normalize_output
99
from tests.utils.app_dir_mock import AppDirs
1010
from tests.utils.approvals import verify
@@ -26,7 +26,6 @@ def test_goal_console(
2626
(app_dir_mock.app_config_dir / "sandbox" / "docker-compose.yml").write_text(get_docker_compose_yml())
2727
(app_dir_mock.app_config_dir / "sandbox" / "algod_config.json").write_text(get_config_json())
2828
(app_dir_mock.app_config_dir / "sandbox" / "algod_network_template.json").write_text(get_algod_network_template())
29-
(app_dir_mock.app_config_dir / "sandbox" / "nginx.conf").write_text(get_proxy_config())
3029

3130
mocker.patch("algokit.core.proc.subprocess_run").return_value = CompletedProcess(
3231
["docker", "exec"], 0, "STDOUT+STDERR"

tests/localnet/test_localnet_reset.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import pytest
44

5-
from algokit.core.sandbox import get_algod_network_template, get_config_json, get_docker_compose_yml, get_proxy_config
5+
from algokit.core.sandbox import get_algod_network_template, get_config_json, get_docker_compose_yml
66
from tests import get_combined_verify_output
77
from tests.utils.app_dir_mock import AppDirs
88
from tests.utils.approvals import verify
@@ -56,7 +56,6 @@ def test_localnet_reset_with_existing_sandbox_with_up_to_date_config(app_dir_moc
5656
(app_dir_mock.app_config_dir / "sandbox" / "docker-compose.yml").write_text(get_docker_compose_yml())
5757
(app_dir_mock.app_config_dir / "sandbox" / "algod_config.json").write_text(get_config_json())
5858
(app_dir_mock.app_config_dir / "sandbox" / "algod_network_template.json").write_text(get_algod_network_template())
59-
(app_dir_mock.app_config_dir / "sandbox" / "nginx.conf").write_text(get_proxy_config())
6059

6160
result = invoke("localnet reset")
6261

@@ -81,7 +80,6 @@ def test_localnet_reset_with_named_sandbox_config(proc_mock: ProcMock, app_dir_m
8180
(app_dir_mock.app_config_dir / "sandbox_test" / "algod_network_template.json").write_text(
8281
get_algod_network_template()
8382
)
84-
(app_dir_mock.app_config_dir / "sandbox_test" / "nginx.conf").write_text(get_proxy_config())
8583

8684
result = invoke("localnet reset")
8785

@@ -99,7 +97,6 @@ def test_localnet_reset_with_existing_sandbox_with_up_to_date_config_with_pull(a
9997
(app_dir_mock.app_config_dir / "sandbox" / "docker-compose.yml").write_text(get_docker_compose_yml())
10098
(app_dir_mock.app_config_dir / "sandbox" / "algod_config.json").write_text(get_config_json())
10199
(app_dir_mock.app_config_dir / "sandbox" / "algod_network_template.json").write_text(get_algod_network_template())
102-
(app_dir_mock.app_config_dir / "sandbox" / "nginx.conf").write_text(get_proxy_config())
103100

104101
result = invoke("localnet reset --update")
105102

tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_out_of_date_config.approved.txt

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ services:
3535
container_name: "algokit_sandbox_algod"
3636
image: algorand/algod:latest
3737
ports:
38-
- 7833
38+
- 4001:8080
39+
- 4002:7833
3940
- 9392:9392
4041
environment:
4142
START_KMD: 1
@@ -55,7 +56,7 @@ services:
5556

5657
conduit:
5758
container_name: "algokit_sandbox_conduit"
58-
image: algorand/conduit:latest
59+
image: algorandfoundation/conduit-localnet:latest
5960
restart: unless-stopped
6061
volumes:
6162
- type: bind
@@ -79,28 +80,14 @@ services:
7980
indexer:
8081
container_name: "algokit_sandbox_indexer"
8182
image: algorand/indexer:latest
83+
ports:
84+
- 8980:8980
8285
restart: unless-stopped
8386
command: daemon --enable-all-parameters
8487
environment:
8588
INDEXER_POSTGRES_CONNECTION_STRING: "host=indexer-db port=5432 user=algorand password=algorand dbname=indexerdb sslmode=disable"
8689
depends_on:
8790
- conduit
8891

89-
proxy:
90-
container_name: "algokit_sandbox_proxy"
91-
image: nginx:1.27.0-alpine
92-
restart: unless-stopped
93-
ports:
94-
- 4001:4001
95-
- 4002:4002
96-
- 8980:8980
97-
volumes:
98-
- type: bind
99-
source: ./nginx.conf
100-
target: /etc/nginx/nginx.conf
101-
depends_on:
102-
- algod
103-
- indexer
104-
10592
{app_config}/sandbox/algod_config.json
106-
{ "Version": 12, "GossipFanout": 1, "EndpointAddress": "0.0.0.0:8080", "DNSBootstrapID": "", "IncomingConnectionsLimit": 0, "Archival":true, "isIndexerActive":false, "EnableDeveloperAPI":true}
93+
{ "GossipFanout": 1, "EndpointAddress": "0.0.0.0:8080", "DNSBootstrapID": "", "IncomingConnectionsLimit": 0, "Archival":true, "isIndexerActive":false, "EnableDeveloperAPI":true, "EnablePrivateNetworkAccessHeader":true}

0 commit comments

Comments
 (0)