From 655902a2f340b5838cc5904f860ad69a66b1c209 Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Tue, 9 Jul 2024 23:25:58 -0400 Subject: [PATCH 01/11] feat: bootstrap nodes for ansible, tnet and mainnet --- ansible/inventory-bootstrap.yaml | 60 ++++++++++++++++++++++++++++++++ ansible/playbooks/bootstrap.yaml | 17 +++++++++ 2 files changed, 77 insertions(+) create mode 100644 ansible/inventory-bootstrap.yaml create mode 100644 ansible/playbooks/bootstrap.yaml diff --git a/ansible/inventory-bootstrap.yaml b/ansible/inventory-bootstrap.yaml new file mode 100644 index 0000000..15250db --- /dev/null +++ b/ansible/inventory-bootstrap.yaml @@ -0,0 +1,60 @@ +all: + children: + tnet: + hosts: + bootstrap-tnet-rust-ceramic-1.3box.io: + peers: + - /dns4/bootstrap-tnet-rust-ceramic-2.3box.io/tcp/4101/p2p/12D3KooWPFGbRHWfDaWt5MFFeqAHBBq3v5BqeJ4X7pmn2V1t6uNs + bootstrap-tnet-rust-ceramic-2.3box.io: + peers: + - /dns4/bootstrap-tnet-rust-ceramic-1.3box.io/tcp/4101/p2p/12D3KooWMqCFj5bnwuNi6D6KLhYiK4C8Eh9xSUKv2E6Jozs4nWEE + vars: + ceramic_network: testnet-clay + mainnet: + hosts: + bootstrap-mainnet-rust-ceramic-1.3box.io: + peers: + - /dns4/bootstrap-mainnet-rust-ceramic-2.3box.io/tcp/4101/p2p/12D3KooWCuS388c1im7KkmdrpsLMziihF8mbcv2w6HPCp4Qmww6m + bootstrap-mainnet-rust-ceramic-2.3box.io: + peers: + - /dns4/bootstrap-mainnet-rust-ceramic-1.3box.io/tcp/4101/p2p/12D3KooWJC1yR4KiCnocV9kuAEwtsMNh7Xmu2vzqpBvk2o3MrYd6 + vars: + ceramic_network: mainnet + + vars: + internal_hostname: "{{ inventory_hostname.split('.')[0].replace('gitcoin-gcp-', '') }}" + ceramic_versions_path: /tmp + grafana_prom_username: 656697 + grafana_prom_password: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 34666635306162363830633761333437353636396238666231386232343633306332376261666461 + 3635646232613663356436336163383730636636633337350a393730353034316333326263333834 + 31643336656264343264353032336538313239663063316536356265636565303535636633343130 + 3335623535373566320a633166643832396465353564613163303438386435363236353438643739 + 39353632336339346534656530653037613834633032353735323434343764613235303062343531 + 39393165613935626438356563343536323833646131386365316134356465353261633837386431 + 39346230323761306664626138356264303330323931346335353737643961333537643066613866 + 62653933303762646332326265393138613462636165653066306237626432656539393563623430 + 39323563316432336332663265303365346434316661386633623961613962303132386363313336 + 38373534313733343139326431363732383037616438333461343438663637666136366562623663 + 65336266313633653939613434393334636435633330643861363966616531363639346266623761 + 31353433373462616233 + grafana_loki_username: 327319 + grafana_loki_password: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 66343436616635383965353933333262626332386165373534386261626138613761363366303563 + 3530323964336336353634353032376165323462396234380a303539363135656331303732393339 + 61666466336137653535316539383930346364356661623666343662386332353731343230306438 + 3336356539656130620a623130613263623364326431366139316437336636316335643937653666 + 33633036366134383366393061623736313433326638663139333661383432653633616539373335 + 36333335393337336362653765396538306566656533343437393432333864356139643834353336 + 63363263633433636531646166313534613032326664386363333131386431356139663565306665 + 39386661663036363034323237653232353430376438653839333131396239363436646166616234 + 37626639636437656632373766373237356130653165613436653866633564353739663235383937 + 66646365366530336638653037353136316637383831383238393664623030633830636166656130 + 623733656639343530396637393162663464 + rust_ceramic_data_block_path: /dev/disk/by-id/google-rust-ceramic-data + rust_ceramic_data_mount_path: /rust_ceramic_data_disk + rust_ceramic_store_path: /rust_ceramic_data_disk/ceramic-one + rust_ceramic_version: v0.25.0 + rust_ceramic_download_url: "https://github.com/ceramicnetwork/rust-ceramic/releases/download/{{ rust_ceramic_version }}/ceramic-one_x86_64-unknown-linux-gnu.tar.gz" diff --git a/ansible/playbooks/bootstrap.yaml b/ansible/playbooks/bootstrap.yaml new file mode 100644 index 0000000..dca0efc --- /dev/null +++ b/ansible/playbooks/bootstrap.yaml @@ -0,0 +1,17 @@ +--- +- hosts: all + become: true + roles: + - name: ceramic-prep + import_role: + name: ceramic-prep + tags: ceramic-prep + +- hosts: tnet, mainnet + become: true + roles: + - name: rust-ceramic + import_role: + name: rust-ceramic + tags: rust-ceramic + From 7650409868a92fc4244b05106f4c7a81d2ad4633 Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Thu, 11 Jul 2024 08:21:11 -0400 Subject: [PATCH 02/11] chore: template Caddyfile --- ansible/inventory-bootstrap.yaml | 2 ++ ansible/playbooks/bootstrap.yaml | 9 +++++++++ ansible/roles/caddy/templates/Caddyfile.j2 | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/ansible/inventory-bootstrap.yaml b/ansible/inventory-bootstrap.yaml index 15250db..b422c31 100644 --- a/ansible/inventory-bootstrap.yaml +++ b/ansible/inventory-bootstrap.yaml @@ -22,6 +22,8 @@ all: ceramic_network: mainnet vars: + caddy_proxy_port: 8000 + caddy_tls_email: infra@3box.io internal_hostname: "{{ inventory_hostname.split('.')[0].replace('gitcoin-gcp-', '') }}" ceramic_versions_path: /tmp grafana_prom_username: 656697 diff --git a/ansible/playbooks/bootstrap.yaml b/ansible/playbooks/bootstrap.yaml index dca0efc..9c2c93a 100644 --- a/ansible/playbooks/bootstrap.yaml +++ b/ansible/playbooks/bootstrap.yaml @@ -15,3 +15,12 @@ name: rust-ceramic tags: rust-ceramic + - name: bootstrap-ui + import_role: + name: bootstrap-ui + tags: bootstrap-ui + + - name: caddy + import_role: + name: caddy + tags: caddy \ No newline at end of file diff --git a/ansible/roles/caddy/templates/Caddyfile.j2 b/ansible/roles/caddy/templates/Caddyfile.j2 index 4753678..87df1fc 100644 --- a/ansible/roles/caddy/templates/Caddyfile.j2 +++ b/ansible/roles/caddy/templates/Caddyfile.j2 @@ -1,4 +1,4 @@ {{ inventory_hostname }} { - reverse_proxy localhost:7007 - tls infra@3box.io + reverse_proxy localhost:{{ caddy_proxy_port }} + tls {{ caddy_tls_email }} } From bc951bfd3b2f22227a6ee916a6e98434dc9f3fae Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Thu, 11 Jul 2024 08:23:27 -0400 Subject: [PATCH 03/11] chore: remove grafana vars from bootstrap --- ansible/inventory-bootstrap.yaml | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/ansible/inventory-bootstrap.yaml b/ansible/inventory-bootstrap.yaml index b422c31..53defb8 100644 --- a/ansible/inventory-bootstrap.yaml +++ b/ansible/inventory-bootstrap.yaml @@ -26,35 +26,6 @@ all: caddy_tls_email: infra@3box.io internal_hostname: "{{ inventory_hostname.split('.')[0].replace('gitcoin-gcp-', '') }}" ceramic_versions_path: /tmp - grafana_prom_username: 656697 - grafana_prom_password: !vault | - $ANSIBLE_VAULT;1.1;AES256 - 34666635306162363830633761333437353636396238666231386232343633306332376261666461 - 3635646232613663356436336163383730636636633337350a393730353034316333326263333834 - 31643336656264343264353032336538313239663063316536356265636565303535636633343130 - 3335623535373566320a633166643832396465353564613163303438386435363236353438643739 - 39353632336339346534656530653037613834633032353735323434343764613235303062343531 - 39393165613935626438356563343536323833646131386365316134356465353261633837386431 - 39346230323761306664626138356264303330323931346335353737643961333537643066613866 - 62653933303762646332326265393138613462636165653066306237626432656539393563623430 - 39323563316432336332663265303365346434316661386633623961613962303132386363313336 - 38373534313733343139326431363732383037616438333461343438663637666136366562623663 - 65336266313633653939613434393334636435633330643861363966616531363639346266623761 - 31353433373462616233 - grafana_loki_username: 327319 - grafana_loki_password: !vault | - $ANSIBLE_VAULT;1.1;AES256 - 66343436616635383965353933333262626332386165373534386261626138613761363366303563 - 3530323964336336353634353032376165323462396234380a303539363135656331303732393339 - 61666466336137653535316539383930346364356661623666343662386332353731343230306438 - 3336356539656130620a623130613263623364326431366139316437336636316335643937653666 - 33633036366134383366393061623736313433326638663139333661383432653633616539373335 - 36333335393337336362653765396538306566656533343437393432333864356139643834353336 - 63363263633433636531646166313534613032326664386363333131386431356139663565306665 - 39386661663036363034323237653232353430376438653839333131396239363436646166616234 - 37626639636437656632373766373237356130653165613436653866633564353739663235383937 - 66646365366530336638653037353136316637383831383238393664623030633830636166656130 - 623733656639343530396637393162663464 rust_ceramic_data_block_path: /dev/disk/by-id/google-rust-ceramic-data rust_ceramic_data_mount_path: /rust_ceramic_data_disk rust_ceramic_store_path: /rust_ceramic_data_disk/ceramic-one From 27340008a8036e3dc417a3619001ee15cce0bbaa Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Thu, 11 Jul 2024 08:47:02 -0400 Subject: [PATCH 04/11] feat: role for bootstrap-ui --- .../bootstrap-ui/files/bootstrap-ui.service | 14 ++ ansible/roles/bootstrap-ui/files/main.py | 165 ++++++++++++++++++ ansible/roles/bootstrap-ui/files/peers.py | 36 ++++ .../roles/bootstrap-ui/files/requirements.txt | 39 +++++ ansible/roles/bootstrap-ui/files/version.py | 38 ++++ ansible/roles/bootstrap-ui/tasks/main.yaml | 49 ++++++ 6 files changed, 341 insertions(+) create mode 100644 ansible/roles/bootstrap-ui/files/bootstrap-ui.service create mode 100644 ansible/roles/bootstrap-ui/files/main.py create mode 100644 ansible/roles/bootstrap-ui/files/peers.py create mode 100644 ansible/roles/bootstrap-ui/files/requirements.txt create mode 100644 ansible/roles/bootstrap-ui/files/version.py create mode 100644 ansible/roles/bootstrap-ui/tasks/main.yaml diff --git a/ansible/roles/bootstrap-ui/files/bootstrap-ui.service b/ansible/roles/bootstrap-ui/files/bootstrap-ui.service new file mode 100644 index 0000000..a9c876b --- /dev/null +++ b/ansible/roles/bootstrap-ui/files/bootstrap-ui.service @@ -0,0 +1,14 @@ +[Unit] +Description=Bootstrap UI +After=network.target + +[Service] +WorkingDirectory=/opt/ceramic-one-ui +ExecStart=/opt/ceramic-one-ui/.venv/bin/python /opt/ceramic-one-ui/main.py +Restart=always +RestartSec=10 +Environment=PYTHONUNBUFFERED=1 +MemoryLimit=100M + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/ansible/roles/bootstrap-ui/files/main.py b/ansible/roles/bootstrap-ui/files/main.py new file mode 100644 index 0000000..0c96c6e --- /dev/null +++ b/ansible/roles/bootstrap-ui/files/main.py @@ -0,0 +1,165 @@ +import asyncio +import signal +from datetime import datetime +from version import get_ceramic_one_version +from peers import get_swarm_peers +from fastapi import FastAPI +from fastapi.responses import JSONResponse, HTMLResponse +import uvicorn +import aiohttp + +# Add configuration option for sleep interval (in seconds) +CACHE_UPDATE_INTERVAL = 60 # Default: 30 seconds + +# Create a global event to signal shutdown +shutdown_event = asyncio.Event() + +# Create a global dictionary to store the cache state +cache_state = {} + +app = FastAPI() + + +def handle_shutdown_signal(): + print("Shutdown signal received. Exiting gracefully...") + shutdown_event.set() + + +async def get_ceramic_id(): + async with aiohttp.ClientSession() as session: + try: + async with session.post('http://localhost:5101/api/v0/id') as response: + if response.status == 200: + data = await response.json() + return { + "ID": data.get("ID"), + "Addresses": data.get("Addresses", []) + } + else: + return {"error": f"Failed to get Ceramic ID. Status: {response.status}"} + except aiohttp.ClientError as e: + return {"error": f"Failed to connect to Ceramic node: {str(e)}"} + + +async def update_cache(): + while not shutdown_event.is_set(): + timestamp = datetime.now().isoformat() + + # Get Ceramic version + ceramic_version = get_ceramic_one_version() + + # Get swarm peers + swarm_peers = get_swarm_peers() + + # Get Ceramic ID + ceramic_id = await get_ceramic_id() + + # Create cache entry + cache_entry = { + "timestamp": timestamp, + "ceramic_version": ceramic_version, + "swarm_peers": swarm_peers, + "ceramic_id": ceramic_id + } + # Save cache entry to global dictionary + cache_state[timestamp] = cache_entry + print(f"Cache updated at {timestamp}") + + # Use the configured interval + await asyncio.sleep(CACHE_UPDATE_INTERVAL) + + +@app.get("/latest") +async def get_latest_cache(): + if not cache_state: + return JSONResponse(content={"error": "Cache is empty"}, status_code=404) + latest_timestamp = max(cache_state.keys()) + return JSONResponse(content=cache_state[latest_timestamp]) + + +@app.get("/", response_class=HTMLResponse) +async def get_root(): + html_content = """ + + + + + + Ceramic bootstrap node + + + +

Ceramic bootstrap node Cache Status

+
Loading...
+ + + """ + return HTMLResponse(content=html_content) + + +async def run_fastapi(): + config = uvicorn.Config(app, host="127.0.0.1", port=8000, loop="asyncio") + server = uvicorn.Server(config) + await server.serve() + + +async def main(): + update_task = asyncio.create_task(update_cache()) + fastapi_task = asyncio.create_task(run_fastapi()) + await asyncio.gather(update_task, fastapi_task) + +if __name__ == "__main__": + print("Starting cache updater and FastAPI server...") + print(f"Cache update interval: {CACHE_UPDATE_INTERVAL} seconds") + + # Register signal handlers + signal.signal(signal.SIGTERM, lambda s, f: handle_shutdown_signal()) + signal.signal(signal.SIGINT, lambda s, f: handle_shutdown_signal()) + + try: + asyncio.run(main()) + except KeyboardInterrupt: + print("Keyboard interrupt received. Exiting gracefully...") diff --git a/ansible/roles/bootstrap-ui/files/peers.py b/ansible/roles/bootstrap-ui/files/peers.py new file mode 100644 index 0000000..4d760d8 --- /dev/null +++ b/ansible/roles/bootstrap-ui/files/peers.py @@ -0,0 +1,36 @@ +import requests +import json + + +def get_swarm_peers(): + url = "http://localhost:5101/api/v0/swarm/peers" + + try: + # Send POST request + response = requests.post(url, timeout=10) + + # Raise an exception for bad status codes + response.raise_for_status() + + # Parse JSON response + json_response = response.json() + + return json_response + + except requests.exceptions.RequestException as e: + print(f"An error occurred while making the request: {e}") + return None + + except json.JSONDecodeError as e: + print(f"Error decoding JSON response: {e}") + return None + + +if __name__ == "__main__": + result = get_swarm_peers() + + if result is not None: + print("Response received:") + print(json.dumps(result, indent=2)) + else: + print("Failed to get a valid response.") diff --git a/ansible/roles/bootstrap-ui/files/requirements.txt b/ansible/roles/bootstrap-ui/files/requirements.txt new file mode 100644 index 0000000..91eddd2 --- /dev/null +++ b/ansible/roles/bootstrap-ui/files/requirements.txt @@ -0,0 +1,39 @@ +annotated-types==0.7.0 +anyio==4.4.0 +certifi==2024.7.4 +charset-normalizer==3.3.2 +click==8.1.7 +dnspython==2.6.1 +email_validator==2.2.0 +fastapi==0.111.0 +fastapi-cli==0.0.4 +h11==0.14.0 +httpcore==1.0.5 +httptools==0.6.1 +httpx==0.27.0 +idna==3.7 +Jinja2==3.1.4 +markdown-it-py==3.0.0 +MarkupSafe==2.1.5 +mdurl==0.1.2 +orjson==3.10.6 +pydantic==2.8.2 +pydantic_core==2.20.1 +Pygments==2.18.0 +python-dotenv==1.0.1 +python-multipart==0.0.9 +PyYAML==6.0.1 +requests==2.32.3 +rich==13.7.1 +shellingham==1.5.4 +sniffio==1.3.1 +starlette==0.37.2 +typer==0.12.3 +typing_extensions==4.12.2 +ujson==5.10.0 +urllib3==2.2.2 +uvicorn==0.30.1 +uvloop==0.19.0 +watchfiles==0.22.0 +websockets==12.0 +aiohttp==3.9.5 diff --git a/ansible/roles/bootstrap-ui/files/version.py b/ansible/roles/bootstrap-ui/files/version.py new file mode 100644 index 0000000..720fe67 --- /dev/null +++ b/ansible/roles/bootstrap-ui/files/version.py @@ -0,0 +1,38 @@ +import subprocess +import re + + +def get_ceramic_one_version(): + try: + # Execute the command and capture the output + result = subprocess.run(['ceramic-one', '--version'], capture_output=True, text=True, check=True) + + # Parse the output + match = re.search(r'ceramic-one (\d+\.\d+\.\d+)', result.stdout) + + if match: + version = match.group(1) + return version + else: + raise ValueError("Unable to parse version from output") + + except subprocess.CalledProcessError as e: + print(f"Error executing command: {e}") + return None + except FileNotFoundError: + print("ceramic-one command not found. Make sure it's installed and in your PATH.") + return None + except ValueError as e: + print(f"Error parsing version: {e}") + return None + + +if __name__ == "__main__": + + # Call the function and store the result + ceramic_one_version = get_ceramic_one_version() + + if ceramic_one_version: + print(f"Ceramic One version: {ceramic_one_version}") + else: + print("Failed to retrieve Ceramic One version.") diff --git a/ansible/roles/bootstrap-ui/tasks/main.yaml b/ansible/roles/bootstrap-ui/tasks/main.yaml new file mode 100644 index 0000000..561ae56 --- /dev/null +++ b/ansible/roles/bootstrap-ui/tasks/main.yaml @@ -0,0 +1,49 @@ +--- +- name: Install python venv + apt: + name: python3-venv + state: present + +- name: Create app directory + file: + path: /opt/ceramic-one-ui + state: directory + owner: root + group: root + mode: 0755 + +- name: Copy app files + copy: + src: "{{ item }}" + dest: /opt/ceramic-one-ui + with_items: + - files/ + register: copy_result + +- name: Create a virtual environment + shell: python3 -m venv /opt/ceramic-one-ui/.venv + args: + creates: /opt/ceramic-one-ui/.venv + +- name: Install requirements + pip: + requirements: /opt/ceramic-one-ui/requirements.txt + virtualenv: /opt/ceramic-one-ui/.venv + register: pip_result + +- name: Template systemd service file + copy: + src: bootstrap-ui.service + dest: /etc/systemd/system/bootstrap-ui.service + +- name: Enable and start the service + systemd: + name: bootstrap-ui + state: started + enabled: true + +- name: Restart the service when changed + systemd: + name: bootstrap-ui + state: restarted + when: copy_result.changed or pip_result.changed \ No newline at end of file From 958993586347946ab54ca7d98f42b455e7d76a34 Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Thu, 11 Jul 2024 13:25:06 -0400 Subject: [PATCH 05/11] feat: added devqa --- ansible/inventory-bootstrap.yaml | 10 ++++++++++ ansible/playbooks/bootstrap.yaml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ansible/inventory-bootstrap.yaml b/ansible/inventory-bootstrap.yaml index 53defb8..0e08c6e 100644 --- a/ansible/inventory-bootstrap.yaml +++ b/ansible/inventory-bootstrap.yaml @@ -20,6 +20,16 @@ all: - /dns4/bootstrap-mainnet-rust-ceramic-1.3box.io/tcp/4101/p2p/12D3KooWJC1yR4KiCnocV9kuAEwtsMNh7Xmu2vzqpBvk2o3MrYd6 vars: ceramic_network: mainnet + devqa: + hosts: + bootstrap-devqa-rust-ceramic-1.3box.io: + peers: + - /dns4/bootstrap-devqa-rust-ceramic-2.3box.io/tcp/4101/p2p/12D3KooWFCf7sKeW8NHoT35EutjJX5vCpPekYqa4hB4tTUpYrcam + bootstrap-devqa-rust-ceramic-2.3box.io: + peers: + - /dns4/bootstrap-devqa-rust-ceramic-1.3box.io/tcp/4101/p2p/12D3KooWJmYPnXgst4gW5GoyAYzRB3upLgLVR1oDVGwjiS9Ce7sA + vars: + ceramic_network: dev-unstable vars: caddy_proxy_port: 8000 diff --git a/ansible/playbooks/bootstrap.yaml b/ansible/playbooks/bootstrap.yaml index 9c2c93a..529c0a0 100644 --- a/ansible/playbooks/bootstrap.yaml +++ b/ansible/playbooks/bootstrap.yaml @@ -7,7 +7,7 @@ name: ceramic-prep tags: ceramic-prep -- hosts: tnet, mainnet +- hosts: all become: true roles: - name: rust-ceramic From bf5fa9f6b2fe2fec31bcbe31d5069a605c195b21 Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Thu, 11 Jul 2024 15:26:09 -0400 Subject: [PATCH 06/11] feat: add lookup plugin for GCP secrets --- ansible/inventory-bootstrap.yaml | 10 ++++++ ansible/pip.requirements.txt | 19 ++++++++++ .../playbooks/lookup_plugins/gcp_secret.py | 36 +++++++++++++++++++ ansible/roles/rust-ceramic/tasks/main.yaml | 13 +++++-- 4 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 ansible/playbooks/lookup_plugins/gcp_secret.py diff --git a/ansible/inventory-bootstrap.yaml b/ansible/inventory-bootstrap.yaml index 0e08c6e..5ba25a5 100644 --- a/ansible/inventory-bootstrap.yaml +++ b/ansible/inventory-bootstrap.yaml @@ -5,31 +5,40 @@ all: bootstrap-tnet-rust-ceramic-1.3box.io: peers: - /dns4/bootstrap-tnet-rust-ceramic-2.3box.io/tcp/4101/p2p/12D3KooWPFGbRHWfDaWt5MFFeqAHBBq3v5BqeJ4X7pmn2V1t6uNs + rust_ceramic_pk_name: "bootstrap-tnet-rust-ceramic-1-pk" bootstrap-tnet-rust-ceramic-2.3box.io: peers: - /dns4/bootstrap-tnet-rust-ceramic-1.3box.io/tcp/4101/p2p/12D3KooWMqCFj5bnwuNi6D6KLhYiK4C8Eh9xSUKv2E6Jozs4nWEE + rust_ceramic_pk_name: "bootstrap-tnet-rust-ceramic-2-pk" vars: ceramic_network: testnet-clay + gcp_project: tnet-prod-2024 mainnet: hosts: bootstrap-mainnet-rust-ceramic-1.3box.io: peers: - /dns4/bootstrap-mainnet-rust-ceramic-2.3box.io/tcp/4101/p2p/12D3KooWCuS388c1im7KkmdrpsLMziihF8mbcv2w6HPCp4Qmww6m + rust_ceramic_pk_name: "bootstrap-mainnet-rust-ceramic-1-pk" bootstrap-mainnet-rust-ceramic-2.3box.io: peers: - /dns4/bootstrap-mainnet-rust-ceramic-1.3box.io/tcp/4101/p2p/12D3KooWJC1yR4KiCnocV9kuAEwtsMNh7Xmu2vzqpBvk2o3MrYd6 + rust_ceramic_pk_name: "bootstrap-mainnet-rust-ceramic-2-pk" vars: ceramic_network: mainnet + gcp_project: tnet-prod-2024 devqa: hosts: bootstrap-devqa-rust-ceramic-1.3box.io: peers: - /dns4/bootstrap-devqa-rust-ceramic-2.3box.io/tcp/4101/p2p/12D3KooWFCf7sKeW8NHoT35EutjJX5vCpPekYqa4hB4tTUpYrcam + rust_ceramic_pk_name: "bootstrap-devqa-rust-ceramic-1-pk" bootstrap-devqa-rust-ceramic-2.3box.io: peers: - /dns4/bootstrap-devqa-rust-ceramic-1.3box.io/tcp/4101/p2p/12D3KooWJmYPnXgst4gW5GoyAYzRB3upLgLVR1oDVGwjiS9Ce7sA + rust_ceramic_pk_name: "bootstrap-devqa-rust-ceramic-2-pk" vars: ceramic_network: dev-unstable + gcp_project: dev-qa-2023 vars: caddy_proxy_port: 8000 @@ -39,5 +48,6 @@ all: rust_ceramic_data_block_path: /dev/disk/by-id/google-rust-ceramic-data rust_ceramic_data_mount_path: /rust_ceramic_data_disk rust_ceramic_store_path: /rust_ceramic_data_disk/ceramic-one + rust_ceramic_pk_dir: /rust_ceramic_data_disk/keys rust_ceramic_version: v0.25.0 rust_ceramic_download_url: "https://github.com/ceramicnetwork/rust-ceramic/releases/download/{{ rust_ceramic_version }}/ceramic-one_x86_64-unknown-linux-gnu.tar.gz" diff --git a/ansible/pip.requirements.txt b/ansible/pip.requirements.txt index 07d2c59..72f6287 100644 --- a/ansible/pip.requirements.txt +++ b/ansible/pip.requirements.txt @@ -1,10 +1,29 @@ ansible==7.2.0 ansible-core==2.14.2 +base58==2.1.1 +cachetools==5.3.3 +certifi==2024.7.4 cffi==1.15.1 +charset-normalizer==3.3.2 cryptography==39.0.1 +google-api-core==2.19.1 +google-auth==2.32.0 +google-cloud-secret-manager==2.20.1 +googleapis-common-protos==1.63.2 +grpc-google-iam-v1==0.13.1 +grpcio==1.65.0 +grpcio-status==1.65.0 +idna==3.7 Jinja2==3.1.2 MarkupSafe==2.1.2 packaging==23.0 +proto-plus==1.24.0 +protobuf==5.27.2 +pyasn1==0.6.0 +pyasn1_modules==0.4.0 pycparser==2.21 PyYAML==6.0 +requests==2.32.3 resolvelib==0.8.1 +rsa==4.9 +urllib3==2.2.2 diff --git a/ansible/playbooks/lookup_plugins/gcp_secret.py b/ansible/playbooks/lookup_plugins/gcp_secret.py new file mode 100644 index 0000000..a8b381a --- /dev/null +++ b/ansible/playbooks/lookup_plugins/gcp_secret.py @@ -0,0 +1,36 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import subprocess +from ansible.errors import AnsibleError +from ansible.plugins.lookup import LookupBase +from ansible.utils.display import Display + +display = Display() + +class LookupModule(LookupBase): + + def run(self, terms, variables=None, **kwargs): + display.debug("GCP Secret lookup plugin called") + if len(terms) != 2: + raise AnsibleError("gcp_secret lookup expects 2 arguments: [project_id, secret_name]") + + project_id, secret_name = terms + display.debug(f"Looking up secret {secret_name} in project {project_id}") + + try: + cmd = [ + "gcloud", "secrets", "versions", "access", "latest", + f"--secret={secret_name}", + f"--project={project_id}", + "--quiet" + ] + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + display.debug("Secret accessed successfully using gcloud") + except subprocess.CalledProcessError as e: + display.error(f"Error accessing secret: {e}") + raise AnsibleError(f"Error accessing secret: {e.stderr}") + + secret_value = result.stdout.strip() + display.v(f"Retrieved secret '{secret_name}' from project '{project_id}'") + return [secret_value] diff --git a/ansible/roles/rust-ceramic/tasks/main.yaml b/ansible/roles/rust-ceramic/tasks/main.yaml index 7c33feb..4199e25 100644 --- a/ansible/roles/rust-ceramic/tasks/main.yaml +++ b/ansible/roles/rust-ceramic/tasks/main.yaml @@ -6,12 +6,21 @@ state: directory mode: '0755' -- name: Create the rust-ceramic store directory if it doesn't exist +- name: Create the rust-ceramic directories if they don't exist ansible.builtin.file: - path: "{{ rust_ceramic_store_path }}" + path: "{{ item }}" state: directory mode: '0755' owner: ceramic + loop: + - "{{ rust_ceramic_store_path }}" + - "{{ rust_ceramic_pk_dir }}" + +- name: Write the rust-ceramic pk to the pk dir + ansible.builtin.copy: + content: "{{ lookup('gcp_secret', gcp_project, rust_ceramic_pk_name) }}" + dest: "{{ rust_ceramic_pk_dir }}/id_ed25519_0" + no_log: true # Don't log the private key - name: Download the Ceramic package ansible.builtin.get_url: From aaee30bf9a9d5646a4e33405dba93cb1b12a7a81 Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Fri, 12 Jul 2024 12:08:18 -0400 Subject: [PATCH 07/11] feat: add ansible ssh user for CD --- ansible/inventory-bootstrap.yaml | 3 +++ ansible/playbooks/bootstrap-update.yaml | 18 ++++++++++++++++++ ansible/roles/ceramic-prep/tasks/main.yaml | 19 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 ansible/playbooks/bootstrap-update.yaml diff --git a/ansible/inventory-bootstrap.yaml b/ansible/inventory-bootstrap.yaml index 5ba25a5..d927c21 100644 --- a/ansible/inventory-bootstrap.yaml +++ b/ansible/inventory-bootstrap.yaml @@ -13,6 +13,7 @@ all: vars: ceramic_network: testnet-clay gcp_project: tnet-prod-2024 + ssh_key_cd_pub: "{{ lookup('gcp_secret', gcp_project, 'bootstrap-tnet-prod-id_rsa-pub') }}" mainnet: hosts: bootstrap-mainnet-rust-ceramic-1.3box.io: @@ -26,6 +27,7 @@ all: vars: ceramic_network: mainnet gcp_project: tnet-prod-2024 + ssh_key_cd_pub: "{{ lookup('gcp_secret', gcp_project, 'bootstrap-tnet-prod-id_rsa-pub') }}" devqa: hosts: bootstrap-devqa-rust-ceramic-1.3box.io: @@ -39,6 +41,7 @@ all: vars: ceramic_network: dev-unstable gcp_project: dev-qa-2023 + ssh_key_cd_pub: "{{ lookup('gcp_secret', gcp_project, 'bootstrap-devqa-id_rsa-pub') }}" vars: caddy_proxy_port: 8000 diff --git a/ansible/playbooks/bootstrap-update.yaml b/ansible/playbooks/bootstrap-update.yaml new file mode 100644 index 0000000..0809ed4 --- /dev/null +++ b/ansible/playbooks/bootstrap-update.yaml @@ -0,0 +1,18 @@ +--- +- hosts: devqa + serial: 1 + become: true + roles: + - rust-ceramic + +- hosts: tnet + serial: 1 + become: true + roles: + - rust-ceramic + +- hosts: mainnet + serial: 1 + become: true + roles: + - rust-ceramic diff --git a/ansible/roles/ceramic-prep/tasks/main.yaml b/ansible/roles/ceramic-prep/tasks/main.yaml index ce856ea..b8ee1c3 100644 --- a/ansible/roles/ceramic-prep/tasks/main.yaml +++ b/ansible/roles/ceramic-prep/tasks/main.yaml @@ -63,3 +63,22 @@ state: directory owner: ceramic when: rust_ceramic_data_block_path is defined + +- name: Add CD user + block: + - name: Add Ansible user + ansible.builtin.user: + name: ansible + state: present + shell: /bin/bash + home: /home/ansible + - name: Add Ansible user to sudoers + ansible.builtin.lineinfile: + path: /etc/sudoers + line: "ansible ALL=(ALL) NOPASSWD:ALL" + state: present + - name: Update user's authorized_keys + ansible.builtin.authorized_key: + user: ansible + key: "{{ ssh_key_cd_pub }}" + when: ssh_key_cd_pub is defined From e7e4e4d00ae818db33380f222f753be3b543545e Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Fri, 12 Jul 2024 15:57:37 -0400 Subject: [PATCH 08/11] feat: add github_latest_release lookup and restarts --- ansible/inventory-bootstrap.yaml | 1 - .../lookup_plugins/github_latest_release.py | 34 +++++++++++++++++++ ansible/roles/rust-ceramic/handlers/main.yml | 5 +++ ansible/roles/rust-ceramic/tasks/main.yaml | 6 ++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 ansible/playbooks/lookup_plugins/github_latest_release.py create mode 100644 ansible/roles/rust-ceramic/handlers/main.yml diff --git a/ansible/inventory-bootstrap.yaml b/ansible/inventory-bootstrap.yaml index d927c21..cd4fb56 100644 --- a/ansible/inventory-bootstrap.yaml +++ b/ansible/inventory-bootstrap.yaml @@ -52,5 +52,4 @@ all: rust_ceramic_data_mount_path: /rust_ceramic_data_disk rust_ceramic_store_path: /rust_ceramic_data_disk/ceramic-one rust_ceramic_pk_dir: /rust_ceramic_data_disk/keys - rust_ceramic_version: v0.25.0 rust_ceramic_download_url: "https://github.com/ceramicnetwork/rust-ceramic/releases/download/{{ rust_ceramic_version }}/ceramic-one_x86_64-unknown-linux-gnu.tar.gz" diff --git a/ansible/playbooks/lookup_plugins/github_latest_release.py b/ansible/playbooks/lookup_plugins/github_latest_release.py new file mode 100644 index 0000000..235b4f7 --- /dev/null +++ b/ansible/playbooks/lookup_plugins/github_latest_release.py @@ -0,0 +1,34 @@ +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import requests +from ansible.errors import AnsibleError +from ansible.plugins.lookup import LookupBase +from ansible.utils.display import Display + +display = Display() + + +class LookupModule(LookupBase): + + def run(self, terms, variables=None, **kwargs): + display.debug("GitHub Latest Release lookup plugin called") + if len(terms) != 1: + raise AnsibleError("github_latest_release lookup expects 1 argument: [repo_name]") + + repo_name = terms[0] + display.debug(f"Looking up latest release for repository {repo_name}") + + try: + url = f"https://api.github.com/repos/{repo_name}/releases/latest" + response = requests.get(url) + response.raise_for_status() + data = response.json() + latest_version = data['tag_name'] + display.debug(f"Latest release version retrieved: {latest_version}") + except requests.RequestException as e: + display.error(f"Error accessing GitHub API: {e}") + raise AnsibleError(f"Error accessing GitHub API: {str(e)}") + + display.v(f"Retrieved latest release version '{latest_version}' for repository '{repo_name}'") + return [latest_version] diff --git a/ansible/roles/rust-ceramic/handlers/main.yml b/ansible/roles/rust-ceramic/handlers/main.yml new file mode 100644 index 0000000..ed0bbe6 --- /dev/null +++ b/ansible/roles/rust-ceramic/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart-rust-ceramic + ansible.builtin.systemd: + name: rust-ceramic + state: restarted diff --git a/ansible/roles/rust-ceramic/tasks/main.yaml b/ansible/roles/rust-ceramic/tasks/main.yaml index 4199e25..ca14ed3 100644 --- a/ansible/roles/rust-ceramic/tasks/main.yaml +++ b/ansible/roles/rust-ceramic/tasks/main.yaml @@ -22,10 +22,15 @@ dest: "{{ rust_ceramic_pk_dir }}/id_ed25519_0" no_log: true # Don't log the private key +- name: Get latest rust-ceramic release + ansible.builtin.set_fact: + rust_ceramic_version: "{{ lookup('github_latest_release', 'ceramicnetwork/rust-ceramic') }}" + - name: Download the Ceramic package ansible.builtin.get_url: url: "{{ rust_ceramic_download_url }}" dest: "{{ ceramic_versions_path }}/ceramic-one_{{ rust_ceramic_version }}.tar.gz" + notify: restart-rust-ceramic - name: Extract the Ceramic package ansible.builtin.unarchive: @@ -40,6 +45,7 @@ state: present when: rust_ceramic_extract.changed register: rust_ceramic_install + notify: restart-rust-ceramic - name: "Setup Ceramic systemd unit" become: yes From 4be7f0ed884abbb42f6e7027a30dd62501fbd47d Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Tue, 16 Jul 2024 08:48:04 -0400 Subject: [PATCH 09/11] chore: add EOF spaces --- ansible/playbooks/bootstrap.yaml | 2 +- ansible/roles/bootstrap-ui/files/bootstrap-ui.service | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ansible/playbooks/bootstrap.yaml b/ansible/playbooks/bootstrap.yaml index 529c0a0..d3a5c6b 100644 --- a/ansible/playbooks/bootstrap.yaml +++ b/ansible/playbooks/bootstrap.yaml @@ -23,4 +23,4 @@ - name: caddy import_role: name: caddy - tags: caddy \ No newline at end of file + tags: caddy diff --git a/ansible/roles/bootstrap-ui/files/bootstrap-ui.service b/ansible/roles/bootstrap-ui/files/bootstrap-ui.service index a9c876b..33d6287 100644 --- a/ansible/roles/bootstrap-ui/files/bootstrap-ui.service +++ b/ansible/roles/bootstrap-ui/files/bootstrap-ui.service @@ -11,4 +11,4 @@ Environment=PYTHONUNBUFFERED=1 MemoryLimit=100M [Install] -WantedBy=multi-user.target \ No newline at end of file +WantedBy=multi-user.target From c95844ef51eb4c7e5ed8e69abfb2a433adaa2521 Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Tue, 16 Jul 2024 09:37:22 -0400 Subject: [PATCH 10/11] fix: updated rust-ceramic env CERAMIC_ONE_P2P_KEY_DIR --- ansible/roles/rust-ceramic/templates/rust-ceramic.env.j2 | 1 + 1 file changed, 1 insertion(+) diff --git a/ansible/roles/rust-ceramic/templates/rust-ceramic.env.j2 b/ansible/roles/rust-ceramic/templates/rust-ceramic.env.j2 index edf4b33..cefe48d 100644 --- a/ansible/roles/rust-ceramic/templates/rust-ceramic.env.j2 +++ b/ansible/roles/rust-ceramic/templates/rust-ceramic.env.j2 @@ -5,5 +5,6 @@ CERAMIC_ONE_LOG_FORMAT=json CERAMIC_ONE_METRICS_BIND_ADDRESS=0.0.0.0:9465 CERAMIC_ONE_NETWORK={{ ceramic_network }} CERAMIC_ONE_STORE_DIR={{ rust_ceramic_store_path }} +CERAMIC_ONE_P2P_KEY_DIR={{ rust_ceramic_pk_dir }} CERAMIC_ONE_SWARM_ADDRESSES=/ip4/0.0.0.0/tcp/4101 CERAMIC_ONE_EXTRA_CERAMIC_PEER_ADDRESSES={{ peers | join(',') }} From f7f06571dfdb5ae7a53ac5d39539c7f5437ca00f Mon Sep 17 00:00:00 2001 From: Ben Wilson Date: Fri, 2 Aug 2024 07:58:26 -0400 Subject: [PATCH 11/11] fix: added ansible secrets for monitoring playbook --- ansible/playbooks/monitoring.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ansible/playbooks/monitoring.yaml b/ansible/playbooks/monitoring.yaml index 6718688..9c944a4 100644 --- a/ansible/playbooks/monitoring.yaml +++ b/ansible/playbooks/monitoring.yaml @@ -6,3 +6,8 @@ import_role: name: grafana-alloy tags: grafana-alloy + vars: + grafana_prom_username: "{{ lookup('gcp_secret', gcp_project, 'grafana-prom-username') }}" + grafana_prom_password: "{{ lookup('gcp_secret', gcp_project, 'grafana-prom-password') }}" + grafana_loki_username: "{{ lookup('gcp_secret', gcp_project, 'grafana-loki-username') }}" + grafana_loki_password: "{{ lookup('gcp_secret', gcp_project, 'grafana-loki-password') }}"