forked from cerc-io/stack-orchestrator
Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88db2ff766 | ||
|
|
5f556e127a | ||
|
|
926997b21c | ||
|
|
0d91a62f84 | ||
|
|
7d27eaef0f | ||
|
|
8ad2b692ec | ||
|
|
54cc993fa4 | ||
|
|
f1f618c57a | ||
|
|
0aca087558 | ||
|
|
a04730e7ac | ||
|
|
95e881ba19 | ||
|
|
414b887036 | ||
|
|
042b413598 | ||
|
|
8384e95049 | ||
|
|
a27cf86748 | ||
|
|
ce587457d7 | ||
|
|
5e91c2224e | ||
|
|
36e13f7199 | ||
|
|
d9bcc088a8 | ||
|
|
660326f713 |
@@ -0,0 +1,55 @@
|
|||||||
|
name: K8s Deploy Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- ci-test
|
||||||
|
paths-ignore:
|
||||||
|
- '.gitea/workflows/triggers/*'
|
||||||
|
|
||||||
|
# Needed until we can incorporate docker startup into the executor container
|
||||||
|
env:
|
||||||
|
DOCKER_HOST: unix:///var/run/dind.sock
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run deploy test suite"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: Start dockerd # Also needed until we can incorporate into the executor
|
||||||
|
run: |
|
||||||
|
dockerd -H $DOCKER_HOST --userland-proxy=false &
|
||||||
|
sleep 5
|
||||||
|
- name: "Install Go"
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: '1.21'
|
||||||
|
- name: "Install Kind"
|
||||||
|
run: go install sigs.k8s.io/kind@v0.20.0
|
||||||
|
- name: "Debug Kind"
|
||||||
|
run: kind create cluster --retain && docker logs kind-control-plane
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
name: Webapp Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- ci-test
|
||||||
|
paths-ignore:
|
||||||
|
- '.gitea/workflows/triggers/*'
|
||||||
|
|
||||||
|
# Needed until we can incorporate docker startup into the executor container
|
||||||
|
env:
|
||||||
|
DOCKER_HOST: unix:///var/run/dind.sock
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run webapp test suite"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
# At present the stock setup-python action fails on Linux/aarch64
|
||||||
|
# Conditional steps below workaroud this by using deadsnakes for that case only
|
||||||
|
- name: "Install Python for ARM on Linux"
|
||||||
|
if: ${{ runner.arch == 'arm64' && runner.os == 'Linux' }}
|
||||||
|
uses: deadsnakes/action@v3.0.1
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Install Python cases other than ARM on Linux"
|
||||||
|
if: ${{ ! (runner.arch == 'arm64' && runner.os == 'Linux') }}
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: Start dockerd # Also needed until we can incorporate into the executor
|
||||||
|
run: |
|
||||||
|
dockerd -H $DOCKER_HOST --userland-proxy=false &
|
||||||
|
sleep 5
|
||||||
|
- name: "Run webapp tests"
|
||||||
|
run: ./tests/webapp-test/run-webapp-test.sh
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
name: Webapp Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: '*'
|
||||||
|
push:
|
||||||
|
branches: '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Run webapp test suite"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Clone project repository"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: "Install Python"
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.8'
|
||||||
|
- name: "Print Python version"
|
||||||
|
run: python3 --version
|
||||||
|
- name: "Install shiv"
|
||||||
|
run: pip install shiv
|
||||||
|
- name: "Generate build version file"
|
||||||
|
run: ./scripts/create_build_tag_file.sh
|
||||||
|
- name: "Build local shiv package"
|
||||||
|
run: ./scripts/build_shiv_package.sh
|
||||||
|
- name: "Run webapp tests"
|
||||||
|
run: ./tests/webapp-test/run-webapp-test.sh
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
python-decouple>=3.8
|
python-decouple>=3.8
|
||||||
|
python-dotenv==1.0.0
|
||||||
GitPython>=3.1.32
|
GitPython>=3.1.32
|
||||||
tqdm>=4.65.0
|
tqdm>=4.65.0
|
||||||
python-on-whales>=0.64.0
|
python-on-whales>=0.64.0
|
||||||
|
|||||||
@@ -33,6 +33,73 @@ from stack_orchestrator.base import get_npm_registry_url
|
|||||||
# TODO: find a place for this
|
# TODO: find a place for this
|
||||||
# epilog="Config provided either in .env or settings.ini or env vars: CERC_REPO_BASE_DIR (defaults to ~/cerc)"
|
# epilog="Config provided either in .env or settings.ini or env vars: CERC_REPO_BASE_DIR (defaults to ~/cerc)"
|
||||||
|
|
||||||
|
def make_container_build_env(dev_root_path: str,
|
||||||
|
container_build_dir: str,
|
||||||
|
debug: bool,
|
||||||
|
force_rebuild: bool,
|
||||||
|
extra_build_args: str):
|
||||||
|
container_build_env = {
|
||||||
|
"CERC_NPM_REGISTRY_URL": get_npm_registry_url(),
|
||||||
|
"CERC_GO_AUTH_TOKEN": config("CERC_GO_AUTH_TOKEN", default=""),
|
||||||
|
"CERC_NPM_AUTH_TOKEN": config("CERC_NPM_AUTH_TOKEN", default=""),
|
||||||
|
"CERC_REPO_BASE_DIR": dev_root_path,
|
||||||
|
"CERC_CONTAINER_BASE_DIR": container_build_dir,
|
||||||
|
"CERC_HOST_UID": f"{os.getuid()}",
|
||||||
|
"CERC_HOST_GID": f"{os.getgid()}",
|
||||||
|
"DOCKER_BUILDKIT": config("DOCKER_BUILDKIT", default="0")
|
||||||
|
}
|
||||||
|
container_build_env.update({"CERC_SCRIPT_DEBUG": "true"} if debug else {})
|
||||||
|
container_build_env.update({"CERC_FORCE_REBUILD": "true"} if force_rebuild else {})
|
||||||
|
container_build_env.update({"CERC_CONTAINER_EXTRA_BUILD_ARGS": extra_build_args} if extra_build_args else {})
|
||||||
|
docker_host_env = os.getenv("DOCKER_HOST")
|
||||||
|
if docker_host_env:
|
||||||
|
container_build_env.update({"DOCKER_HOST": docker_host_env})
|
||||||
|
|
||||||
|
return container_build_env
|
||||||
|
|
||||||
|
|
||||||
|
def process_container(container,
|
||||||
|
container_build_dir: str,
|
||||||
|
container_build_env: dict,
|
||||||
|
dev_root_path: str,
|
||||||
|
quiet: bool,
|
||||||
|
verbose: bool,
|
||||||
|
dry_run: bool,
|
||||||
|
continue_on_error: bool,
|
||||||
|
):
|
||||||
|
if not quiet:
|
||||||
|
print(f"Building: {container}")
|
||||||
|
build_dir = os.path.join(container_build_dir, container.replace("/", "-"))
|
||||||
|
build_script_filename = os.path.join(build_dir, "build.sh")
|
||||||
|
if verbose:
|
||||||
|
print(f"Build script filename: {build_script_filename}")
|
||||||
|
if os.path.exists(build_script_filename):
|
||||||
|
build_command = build_script_filename
|
||||||
|
else:
|
||||||
|
if verbose:
|
||||||
|
print(f"No script file found: {build_script_filename}, using default build script")
|
||||||
|
repo_dir = container.split('/')[1]
|
||||||
|
# TODO: make this less of a hack -- should be specified in some metadata somewhere
|
||||||
|
# Check if we have a repo for this container. If not, set the context dir to the container-build subdir
|
||||||
|
repo_full_path = os.path.join(dev_root_path, repo_dir)
|
||||||
|
repo_dir_or_build_dir = repo_full_path if os.path.exists(repo_full_path) else build_dir
|
||||||
|
build_command = os.path.join(container_build_dir,
|
||||||
|
"default-build.sh") + f" {container}:local {repo_dir_or_build_dir}"
|
||||||
|
if not dry_run:
|
||||||
|
if verbose:
|
||||||
|
print(f"Executing: {build_command} with environment: {container_build_env}")
|
||||||
|
build_result = subprocess.run(build_command, shell=True, env=container_build_env)
|
||||||
|
if verbose:
|
||||||
|
print(f"Return code is: {build_result.returncode}")
|
||||||
|
if build_result.returncode != 0:
|
||||||
|
print(f"Error running build for {container}")
|
||||||
|
if not continue_on_error:
|
||||||
|
print("FATAL Error: container build failed and --continue-on-error not set, exiting")
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
print("****** Container Build Error, continuing because --continue-on-error is set")
|
||||||
|
else:
|
||||||
|
print("Skipped")
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.option('--include', help="only build these containers")
|
@click.option('--include', help="only build these containers")
|
||||||
@@ -83,61 +150,16 @@ def command(ctx, include, exclude, force_rebuild, extra_build_args):
|
|||||||
if stack:
|
if stack:
|
||||||
print(f"Stack: {stack}")
|
print(f"Stack: {stack}")
|
||||||
|
|
||||||
# TODO: make this configurable
|
container_build_env = make_container_build_env(dev_root_path,
|
||||||
container_build_env = {
|
container_build_dir,
|
||||||
"CERC_NPM_REGISTRY_URL": get_npm_registry_url(),
|
debug,
|
||||||
"CERC_GO_AUTH_TOKEN": config("CERC_GO_AUTH_TOKEN", default=""),
|
force_rebuild,
|
||||||
"CERC_NPM_AUTH_TOKEN": config("CERC_NPM_AUTH_TOKEN", default=""),
|
extra_build_args)
|
||||||
"CERC_REPO_BASE_DIR": dev_root_path,
|
|
||||||
"CERC_CONTAINER_BASE_DIR": container_build_dir,
|
|
||||||
"CERC_HOST_UID": f"{os.getuid()}",
|
|
||||||
"CERC_HOST_GID": f"{os.getgid()}",
|
|
||||||
"DOCKER_BUILDKIT": config("DOCKER_BUILDKIT", default="0")
|
|
||||||
}
|
|
||||||
container_build_env.update({"CERC_SCRIPT_DEBUG": "true"} if debug else {})
|
|
||||||
container_build_env.update({"CERC_FORCE_REBUILD": "true"} if force_rebuild else {})
|
|
||||||
container_build_env.update({"CERC_CONTAINER_EXTRA_BUILD_ARGS": extra_build_args} if extra_build_args else {})
|
|
||||||
docker_host_env = os.getenv("DOCKER_HOST")
|
|
||||||
if docker_host_env:
|
|
||||||
container_build_env.update({"DOCKER_HOST": docker_host_env})
|
|
||||||
|
|
||||||
def process_container(container):
|
|
||||||
if not quiet:
|
|
||||||
print(f"Building: {container}")
|
|
||||||
build_dir = os.path.join(container_build_dir, container.replace("/", "-"))
|
|
||||||
build_script_filename = os.path.join(build_dir, "build.sh")
|
|
||||||
if verbose:
|
|
||||||
print(f"Build script filename: {build_script_filename}")
|
|
||||||
if os.path.exists(build_script_filename):
|
|
||||||
build_command = build_script_filename
|
|
||||||
else:
|
|
||||||
if verbose:
|
|
||||||
print(f"No script file found: {build_script_filename}, using default build script")
|
|
||||||
repo_dir = container.split('/')[1]
|
|
||||||
# TODO: make this less of a hack -- should be specified in some metadata somewhere
|
|
||||||
# Check if we have a repo for this container. If not, set the context dir to the container-build subdir
|
|
||||||
repo_full_path = os.path.join(dev_root_path, repo_dir)
|
|
||||||
repo_dir_or_build_dir = repo_full_path if os.path.exists(repo_full_path) else build_dir
|
|
||||||
build_command = os.path.join(container_build_dir, "default-build.sh") + f" {container}:local {repo_dir_or_build_dir}"
|
|
||||||
if not dry_run:
|
|
||||||
if verbose:
|
|
||||||
print(f"Executing: {build_command} with environment: {container_build_env}")
|
|
||||||
build_result = subprocess.run(build_command, shell=True, env=container_build_env)
|
|
||||||
if verbose:
|
|
||||||
print(f"Return code is: {build_result.returncode}")
|
|
||||||
if build_result.returncode != 0:
|
|
||||||
print(f"Error running build for {container}")
|
|
||||||
if not continue_on_error:
|
|
||||||
print("FATAL Error: container build failed and --continue-on-error not set, exiting")
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
print("****** Container Build Error, continuing because --continue-on-error is set")
|
|
||||||
else:
|
|
||||||
print("Skipped")
|
|
||||||
|
|
||||||
for container in containers_in_scope:
|
for container in containers_in_scope:
|
||||||
if include_exclude_check(container, include, exclude):
|
if include_exclude_check(container, include, exclude):
|
||||||
process_container(container)
|
process_container(container, container_build_dir, container_build_env,
|
||||||
|
dev_root_path, quiet, verbose, dry_run, continue_on_error)
|
||||||
else:
|
else:
|
||||||
if verbose:
|
if verbose:
|
||||||
print(f"Excluding: {container}")
|
print(f"Excluding: {container}")
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
# Copyright © 2022, 2023 Vulcanize
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Builds webapp containers
|
||||||
|
|
||||||
|
# env vars:
|
||||||
|
# CERC_REPO_BASE_DIR defaults to ~/cerc
|
||||||
|
|
||||||
|
# TODO: display the available list of containers; allow re-build of either all or specific containers
|
||||||
|
|
||||||
|
import os
|
||||||
|
from decouple import config
|
||||||
|
import click
|
||||||
|
from pathlib import Path
|
||||||
|
from stack_orchestrator.build import build_containers
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.option('--base-container', default="cerc/nextjs-base")
|
||||||
|
@click.option('--source-repo', help="directory containing the webapp to build", required=True)
|
||||||
|
@click.option("--force-rebuild", is_flag=True, default=False, help="Override dependency checking -- always rebuild")
|
||||||
|
@click.option("--extra-build-args", help="Supply extra arguments to build")
|
||||||
|
@click.pass_context
|
||||||
|
def command(ctx, base_container, source_repo, force_rebuild, extra_build_args):
|
||||||
|
'''build the specified webapp container'''
|
||||||
|
|
||||||
|
quiet = ctx.obj.quiet
|
||||||
|
verbose = ctx.obj.verbose
|
||||||
|
dry_run = ctx.obj.dry_run
|
||||||
|
debug = ctx.obj.debug
|
||||||
|
local_stack = ctx.obj.local_stack
|
||||||
|
stack = ctx.obj.stack
|
||||||
|
continue_on_error = ctx.obj.continue_on_error
|
||||||
|
|
||||||
|
# See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure
|
||||||
|
container_build_dir = Path(__file__).absolute().parent.parent.joinpath("data", "container-build")
|
||||||
|
|
||||||
|
if local_stack:
|
||||||
|
dev_root_path = os.getcwd()[0:os.getcwd().rindex("stack-orchestrator")]
|
||||||
|
print(f'Local stack dev_root_path (CERC_REPO_BASE_DIR) overridden to: {dev_root_path}')
|
||||||
|
else:
|
||||||
|
dev_root_path = os.path.expanduser(config("CERC_REPO_BASE_DIR", default="~/cerc"))
|
||||||
|
|
||||||
|
if not quiet:
|
||||||
|
print(f'Dev Root is: {dev_root_path}')
|
||||||
|
|
||||||
|
# First build the base container.
|
||||||
|
container_build_env = build_containers.make_container_build_env(dev_root_path, container_build_dir, debug,
|
||||||
|
force_rebuild, extra_build_args)
|
||||||
|
|
||||||
|
build_containers.process_container(base_container, container_build_dir, container_build_env, dev_root_path, quiet,
|
||||||
|
verbose, dry_run, continue_on_error)
|
||||||
|
|
||||||
|
|
||||||
|
# Now build the target webapp. We use the same build script, but with a different Dockerfile and work dir.
|
||||||
|
container_build_env["CERC_WEBAPP_BUILD_RUNNING"] = "true"
|
||||||
|
container_build_env["CERC_CONTAINER_BUILD_WORK_DIR"] = os.path.abspath(source_repo)
|
||||||
|
container_build_env["CERC_CONTAINER_BUILD_DOCKERFILE"] = os.path.join(container_build_dir,
|
||||||
|
base_container.replace("/", "-"),
|
||||||
|
"Dockerfile.webapp")
|
||||||
|
webapp_name = os.path.abspath(source_repo).split(os.path.sep)[-1]
|
||||||
|
container_build_env["CERC_CONTAINER_BUILD_TAG"] = f"cerc/{webapp_name}:local"
|
||||||
|
|
||||||
|
build_containers.process_container(base_container, container_build_dir, container_build_env, dev_root_path, quiet,
|
||||||
|
verbose, dry_run, continue_on_error)
|
||||||
@@ -2,7 +2,7 @@ version: "3.2"
|
|||||||
# See: https://docs.ipfs.tech/install/run-ipfs-inside-docker/#set-up
|
# See: https://docs.ipfs.tech/install/run-ipfs-inside-docker/#set-up
|
||||||
services:
|
services:
|
||||||
ipfs:
|
ipfs:
|
||||||
image: ipfs/kubo:master-2023-02-20-714a968
|
image: ipfs/kubo:v0.24.0
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./ipfs/import:/import
|
- ./ipfs/import:/import
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
version: "3.2"
|
||||||
|
|
||||||
|
services:
|
||||||
|
osmosis-front-end:
|
||||||
|
image: cerc/osmosis-front-end:local
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "3002:3002" #TODO make `3000` when using the deployment feature
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
version: '3.2'
|
||||||
|
|
||||||
|
services:
|
||||||
|
merkl-sushiswap-v3-watcher-db:
|
||||||
|
restart: unless-stopped
|
||||||
|
image: postgres:14-alpine
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=vdbm
|
||||||
|
- POSTGRES_MULTIPLE_DATABASES=merkl-sushiswap-v3-watcher,merkl-sushiswap-v3-watcher-job-queue
|
||||||
|
- POSTGRES_EXTENSION=merkl-sushiswap-v3-watcher-job-queue:pgcrypto
|
||||||
|
- POSTGRES_PASSWORD=password
|
||||||
|
volumes:
|
||||||
|
- ../config/postgresql/multiple-postgressql-databases.sh:/docker-entrypoint-initdb.d/multiple-postgressql-databases.sh
|
||||||
|
- merkl_sushiswap_v3_watcher_db_data:/var/lib/postgresql/data
|
||||||
|
ports:
|
||||||
|
- "5432"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "nc", "-v", "localhost", "5432"]
|
||||||
|
interval: 20s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 15
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
|
merkl-sushiswap-v3-watcher-job-runner:
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
merkl-sushiswap-v3-watcher-db:
|
||||||
|
condition: service_healthy
|
||||||
|
image: cerc/watcher-merkl-sushiswap-v3:local
|
||||||
|
environment:
|
||||||
|
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
||||||
|
CERC_ETH_RPC_ENDPOINT: ${CERC_ETH_RPC_ENDPOINT}
|
||||||
|
command: ["bash", "./start-job-runner.sh"]
|
||||||
|
volumes:
|
||||||
|
- ../config/watcher-merkl-sushiswap-v3/watcher-config-template.toml:/app/environments/watcher-config-template.toml
|
||||||
|
- ../config/watcher-merkl-sushiswap-v3/start-job-runner.sh:/app/start-job-runner.sh
|
||||||
|
ports:
|
||||||
|
- "9000"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "nc", "-v", "localhost", "9000"]
|
||||||
|
interval: 20s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 15
|
||||||
|
start_period: 5s
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
|
||||||
|
merkl-sushiswap-v3-watcher-server:
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
merkl-sushiswap-v3-watcher-db:
|
||||||
|
condition: service_healthy
|
||||||
|
merkl-sushiswap-v3-watcher-job-runner:
|
||||||
|
condition: service_healthy
|
||||||
|
image: cerc/watcher-merkl-sushiswap-v3:local
|
||||||
|
environment:
|
||||||
|
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
||||||
|
CERC_ETH_RPC_ENDPOINT: ${CERC_ETH_RPC_ENDPOINT}
|
||||||
|
SUSHISWAP_START_BLOCK: ${SUSHISWAP_START_BLOCK:- 2867560}
|
||||||
|
command: ["bash", "./start-server.sh"]
|
||||||
|
volumes:
|
||||||
|
- ../config/watcher-merkl-sushiswap-v3/watcher-config-template.toml:/app/environments/watcher-config-template.toml
|
||||||
|
- ../config/watcher-merkl-sushiswap-v3/start-server.sh:/app/start-server.sh
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:3007:3008"
|
||||||
|
- "9001"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "nc", "-v", "localhost", "3008"]
|
||||||
|
interval: 20s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 15
|
||||||
|
start_period: 5s
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
merkl_sushiswap_v3_watcher_db_data:
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
version: '3.2'
|
||||||
|
|
||||||
|
services:
|
||||||
|
sushiswap-v3-watcher-db:
|
||||||
|
restart: unless-stopped
|
||||||
|
image: postgres:14-alpine
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=vdbm
|
||||||
|
- POSTGRES_MULTIPLE_DATABASES=sushiswap-v3-watcher,sushiswap-v3-watcher-job-queue
|
||||||
|
- POSTGRES_EXTENSION=sushiswap-v3-watcher-job-queue:pgcrypto
|
||||||
|
- POSTGRES_PASSWORD=password
|
||||||
|
volumes:
|
||||||
|
- ../config/postgresql/multiple-postgressql-databases.sh:/docker-entrypoint-initdb.d/multiple-postgressql-databases.sh
|
||||||
|
- sushiswap_v3_watcher_db_data:/var/lib/postgresql/data
|
||||||
|
ports:
|
||||||
|
- "5432"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "nc", "-v", "localhost", "5432"]
|
||||||
|
interval: 20s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 15
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
|
sushiswap-v3-watcher-job-runner:
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
sushiswap-v3-watcher-db:
|
||||||
|
condition: service_healthy
|
||||||
|
image: cerc/watcher-sushiswap-v3:local
|
||||||
|
environment:
|
||||||
|
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
||||||
|
CERC_ETH_RPC_ENDPOINT: ${CERC_ETH_RPC_ENDPOINT}
|
||||||
|
command: ["bash", "./start-job-runner.sh"]
|
||||||
|
volumes:
|
||||||
|
- ../config/watcher-sushiswap-v3/watcher-config-template.toml:/app/environments/watcher-config-template.toml
|
||||||
|
- ../config/watcher-sushiswap-v3/start-job-runner.sh:/app/start-job-runner.sh
|
||||||
|
ports:
|
||||||
|
- "9000"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "nc", "-v", "localhost", "9000"]
|
||||||
|
interval: 20s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 15
|
||||||
|
start_period: 5s
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
|
||||||
|
sushiswap-v3-watcher-server:
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
sushiswap-v3-watcher-db:
|
||||||
|
condition: service_healthy
|
||||||
|
sushiswap-v3-watcher-job-runner:
|
||||||
|
condition: service_healthy
|
||||||
|
image: cerc/watcher-sushiswap-v3:local
|
||||||
|
environment:
|
||||||
|
CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG}
|
||||||
|
CERC_ETH_RPC_ENDPOINT: ${CERC_ETH_RPC_ENDPOINT}
|
||||||
|
SUSHISWAP_START_BLOCK: ${SUSHISWAP_START_BLOCK:- 2867560}
|
||||||
|
command: ["bash", "./start-server.sh"]
|
||||||
|
volumes:
|
||||||
|
- ../config/watcher-sushiswap-v3/watcher-config-template.toml:/app/environments/watcher-config-template.toml
|
||||||
|
- ../config/watcher-sushiswap-v3/start-server.sh:/app/start-server.sh
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:3008:3008"
|
||||||
|
- "9001"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "nc", "-v", "localhost", "3008"]
|
||||||
|
interval: 20s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 15
|
||||||
|
start_period: 5s
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
sushiswap_v3_watcher_db_data:
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
set -u
|
||||||
|
|
||||||
|
echo "Using ETH RPC endpoint ${CERC_ETH_RPC_ENDPOINT}"
|
||||||
|
|
||||||
|
# Read in the config template TOML file and modify it
|
||||||
|
WATCHER_CONFIG_TEMPLATE=$(cat environments/watcher-config-template.toml)
|
||||||
|
WATCHER_CONFIG=$(echo "$WATCHER_CONFIG_TEMPLATE" | \
|
||||||
|
sed -E "s|REPLACE_WITH_CERC_ETH_RPC_ENDPOINT|${CERC_ETH_RPC_ENDPOINT}| ")
|
||||||
|
|
||||||
|
# Write the modified content to a new file
|
||||||
|
echo "$WATCHER_CONFIG" > environments/local.toml
|
||||||
|
|
||||||
|
echo "Running job-runner..."
|
||||||
|
DEBUG=vulcanize:* exec node --enable-source-maps dist/job-runner.js
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
set -u
|
||||||
|
|
||||||
|
echo "Using ETH RPC endpoint ${CERC_ETH_RPC_ENDPOINT}"
|
||||||
|
|
||||||
|
# Read in the config template TOML file and modify it
|
||||||
|
WATCHER_CONFIG_TEMPLATE=$(cat environments/watcher-config-template.toml)
|
||||||
|
WATCHER_CONFIG=$(echo "$WATCHER_CONFIG_TEMPLATE" | \
|
||||||
|
sed -E "s|REPLACE_WITH_CERC_ETH_RPC_ENDPOINT|${CERC_ETH_RPC_ENDPOINT}| ")
|
||||||
|
|
||||||
|
# Write the modified content to a new file
|
||||||
|
echo "$WATCHER_CONFIG" > environments/local.toml
|
||||||
|
|
||||||
|
echo "Initializing watcher..."
|
||||||
|
yarn fill --start-block $SUSHISWAP_START_BLOCK --end-block $((SUSHISWAP_START_BLOCK + 1))
|
||||||
|
|
||||||
|
echo "Running server..."
|
||||||
|
DEBUG=vulcanize:* exec node --enable-source-maps dist/server.js
|
||||||
+99
@@ -0,0 +1,99 @@
|
|||||||
|
[server]
|
||||||
|
host = "0.0.0.0"
|
||||||
|
port = 3008
|
||||||
|
kind = "active"
|
||||||
|
|
||||||
|
# Checkpointing state.
|
||||||
|
checkpointing = true
|
||||||
|
|
||||||
|
# Checkpoint interval in number of blocks.
|
||||||
|
checkpointInterval = 2000
|
||||||
|
|
||||||
|
# Enable state creation
|
||||||
|
# CAUTION: Disable only if state creation is not desired or can be filled subsequently
|
||||||
|
enableState = false
|
||||||
|
|
||||||
|
subgraphPath = "./subgraph-build"
|
||||||
|
|
||||||
|
# Interval to restart wasm instance periodically
|
||||||
|
wasmRestartBlocksInterval = 20
|
||||||
|
|
||||||
|
# Interval in number of blocks at which to clear entities cache.
|
||||||
|
clearEntitiesCacheInterval = 1000
|
||||||
|
|
||||||
|
# Max block range for which to return events in eventsInRange GQL query.
|
||||||
|
# Use -1 for skipping check on block range.
|
||||||
|
maxEventsBlockRange = 1000
|
||||||
|
|
||||||
|
# Flag to specify whether RPC endpoint supports block hash as block tag parameter
|
||||||
|
rpcSupportsBlockHashParam = false
|
||||||
|
|
||||||
|
# GQL cache settings
|
||||||
|
[server.gqlCache]
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
# Max in-memory cache size (in bytes) (default 8 MB)
|
||||||
|
# maxCacheSize
|
||||||
|
|
||||||
|
# GQL cache-control max-age settings (in seconds)
|
||||||
|
maxAge = 15
|
||||||
|
timeTravelMaxAge = 86400 # 1 day
|
||||||
|
|
||||||
|
[metrics]
|
||||||
|
host = "127.0.0.1"
|
||||||
|
port = 9000
|
||||||
|
[metrics.gql]
|
||||||
|
port = 9001
|
||||||
|
|
||||||
|
[database]
|
||||||
|
type = "postgres"
|
||||||
|
host = "merkl-sushiswap-v3-watcher-db"
|
||||||
|
port = 5432
|
||||||
|
database = "merkl-sushiswap-v3-watcher"
|
||||||
|
username = "vdbm"
|
||||||
|
password = "password"
|
||||||
|
synchronize = true
|
||||||
|
logging = false
|
||||||
|
|
||||||
|
[upstream]
|
||||||
|
[upstream.ethServer]
|
||||||
|
rpcProviderEndpoint = "REPLACE_WITH_CERC_ETH_RPC_ENDPOINT"
|
||||||
|
|
||||||
|
# Boolean flag to specify if rpc-eth-client should be used for RPC endpoint instead of ipld-eth-client (ipld-eth-server GQL client)
|
||||||
|
rpcClient = true
|
||||||
|
|
||||||
|
# Boolean flag to specify if rpcProviderEndpoint is an FEVM RPC endpoint
|
||||||
|
isFEVM = true
|
||||||
|
|
||||||
|
# Boolean flag to filter event logs by contracts
|
||||||
|
filterLogsByAddresses = true
|
||||||
|
# Boolean flag to filter event logs by topics
|
||||||
|
filterLogsByTopics = false
|
||||||
|
|
||||||
|
[upstream.cache]
|
||||||
|
name = "requests"
|
||||||
|
enabled = false
|
||||||
|
deleteOnStart = false
|
||||||
|
|
||||||
|
[jobQueue]
|
||||||
|
dbConnectionString = "postgres://vdbm:password@merkl-sushiswap-v3-watcher-db/merkl-sushiswap-v3-watcher-job-queue"
|
||||||
|
maxCompletionLagInSecs = 300
|
||||||
|
jobDelayInMilliSecs = 100
|
||||||
|
eventsInBatch = 50
|
||||||
|
subgraphEventsOrder = true
|
||||||
|
# Filecoin block time: https://docs.filecoin.io/basics/the-blockchain/blocks-and-tipsets#blocktime
|
||||||
|
blockDelayInMilliSecs = 30000
|
||||||
|
prefetchBlocksInMem = false
|
||||||
|
prefetchBlockCount = 10
|
||||||
|
|
||||||
|
# Boolean to switch between modes of processing events when starting the server.
|
||||||
|
# Setting to true will fetch filtered events and required blocks in a range of blocks and then process them.
|
||||||
|
# Setting to false will fetch blocks consecutively with its events and then process them (Behaviour is followed in realtime processing near head).
|
||||||
|
useBlockRanges = true
|
||||||
|
|
||||||
|
# Block range in which logs are fetched during historical blocks processing
|
||||||
|
historicalLogsBlockRange = 2000
|
||||||
|
|
||||||
|
# Max block range of historical processing after which it waits for completion of events processing
|
||||||
|
# If set to -1 historical processing does not wait for events processing and completes till latest canonical block
|
||||||
|
historicalMaxFetchAhead = 10000
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
set -u
|
||||||
|
|
||||||
|
echo "Using ETH RPC endpoint ${CERC_ETH_RPC_ENDPOINT}"
|
||||||
|
|
||||||
|
# Read in the config template TOML file and modify it
|
||||||
|
WATCHER_CONFIG_TEMPLATE=$(cat environments/watcher-config-template.toml)
|
||||||
|
WATCHER_CONFIG=$(echo "$WATCHER_CONFIG_TEMPLATE" | \
|
||||||
|
sed -E "s|REPLACE_WITH_CERC_ETH_RPC_ENDPOINT|${CERC_ETH_RPC_ENDPOINT}| ")
|
||||||
|
|
||||||
|
# Write the modified content to a new file
|
||||||
|
echo "$WATCHER_CONFIG" > environments/local.toml
|
||||||
|
|
||||||
|
echo "Running job-runner..."
|
||||||
|
DEBUG=vulcanize:* exec node --enable-source-maps dist/job-runner.js
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
set -u
|
||||||
|
|
||||||
|
echo "Using ETH RPC endpoint ${CERC_ETH_RPC_ENDPOINT}"
|
||||||
|
|
||||||
|
# Read in the config template TOML file and modify it
|
||||||
|
WATCHER_CONFIG_TEMPLATE=$(cat environments/watcher-config-template.toml)
|
||||||
|
WATCHER_CONFIG=$(echo "$WATCHER_CONFIG_TEMPLATE" | \
|
||||||
|
sed -E "s|REPLACE_WITH_CERC_ETH_RPC_ENDPOINT|${CERC_ETH_RPC_ENDPOINT}| ")
|
||||||
|
|
||||||
|
# Write the modified content to a new file
|
||||||
|
echo "$WATCHER_CONFIG" > environments/local.toml
|
||||||
|
|
||||||
|
echo "Initializing watcher..."
|
||||||
|
yarn fill --start-block $SUSHISWAP_START_BLOCK --end-block $((SUSHISWAP_START_BLOCK + 1))
|
||||||
|
|
||||||
|
echo "Running server..."
|
||||||
|
DEBUG=vulcanize:* exec node --enable-source-maps dist/server.js
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
[server]
|
||||||
|
host = "0.0.0.0"
|
||||||
|
port = 3008
|
||||||
|
kind = "active"
|
||||||
|
|
||||||
|
# Checkpointing state.
|
||||||
|
checkpointing = true
|
||||||
|
|
||||||
|
# Checkpoint interval in number of blocks.
|
||||||
|
checkpointInterval = 2000
|
||||||
|
|
||||||
|
# Enable state creation
|
||||||
|
# CAUTION: Disable only if state creation is not desired or can be filled subsequently
|
||||||
|
enableState = false
|
||||||
|
|
||||||
|
subgraphPath = "./subgraph-build"
|
||||||
|
|
||||||
|
# Interval to restart wasm instance periodically
|
||||||
|
wasmRestartBlocksInterval = 20
|
||||||
|
|
||||||
|
# Interval in number of blocks at which to clear entities cache.
|
||||||
|
clearEntitiesCacheInterval = 1000
|
||||||
|
|
||||||
|
# Max block range for which to return events in eventsInRange GQL query.
|
||||||
|
# Use -1 for skipping check on block range.
|
||||||
|
maxEventsBlockRange = 1000
|
||||||
|
|
||||||
|
# Flag to specify whether RPC endpoint supports block hash as block tag parameter
|
||||||
|
rpcSupportsBlockHashParam = false
|
||||||
|
|
||||||
|
# GQL cache settings
|
||||||
|
[server.gqlCache]
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
# Max in-memory cache size (in bytes) (default 8 MB)
|
||||||
|
# maxCacheSize
|
||||||
|
|
||||||
|
# GQL cache-control max-age settings (in seconds)
|
||||||
|
maxAge = 15
|
||||||
|
timeTravelMaxAge = 86400 # 1 day
|
||||||
|
|
||||||
|
[metrics]
|
||||||
|
host = "127.0.0.1"
|
||||||
|
port = 9000
|
||||||
|
[metrics.gql]
|
||||||
|
port = 9001
|
||||||
|
|
||||||
|
[database]
|
||||||
|
type = "postgres"
|
||||||
|
host = "sushiswap-v3-watcher-db"
|
||||||
|
port = 5432
|
||||||
|
database = "sushiswap-v3-watcher"
|
||||||
|
username = "vdbm"
|
||||||
|
password = "password"
|
||||||
|
synchronize = true
|
||||||
|
logging = false
|
||||||
|
|
||||||
|
[upstream]
|
||||||
|
[upstream.ethServer]
|
||||||
|
rpcProviderEndpoint = "REPLACE_WITH_CERC_ETH_RPC_ENDPOINT"
|
||||||
|
|
||||||
|
# Boolean flag to specify if rpc-eth-client should be used for RPC endpoint instead of ipld-eth-client (ipld-eth-server GQL client)
|
||||||
|
rpcClient = true
|
||||||
|
|
||||||
|
# Boolean flag to specify if rpcProviderEndpoint is an FEVM RPC endpoint
|
||||||
|
isFEVM = true
|
||||||
|
|
||||||
|
# Boolean flag to filter event logs by contracts
|
||||||
|
filterLogsByAddresses = true
|
||||||
|
# Boolean flag to filter event logs by topics
|
||||||
|
filterLogsByTopics = true
|
||||||
|
|
||||||
|
[upstream.cache]
|
||||||
|
name = "requests"
|
||||||
|
enabled = false
|
||||||
|
deleteOnStart = false
|
||||||
|
|
||||||
|
[jobQueue]
|
||||||
|
dbConnectionString = "postgres://vdbm:password@sushiswap-v3-watcher-db/sushiswap-v3-watcher-job-queue"
|
||||||
|
maxCompletionLagInSecs = 300
|
||||||
|
jobDelayInMilliSecs = 100
|
||||||
|
eventsInBatch = 50
|
||||||
|
subgraphEventsOrder = true
|
||||||
|
# Filecoin block time: https://docs.filecoin.io/basics/the-blockchain/blocks-and-tipsets#blocktime
|
||||||
|
blockDelayInMilliSecs = 30000
|
||||||
|
prefetchBlocksInMem = false
|
||||||
|
prefetchBlockCount = 10
|
||||||
|
|
||||||
|
# Boolean to switch between modes of processing events when starting the server.
|
||||||
|
# Setting to true will fetch filtered events and required blocks in a range of blocks and then process them.
|
||||||
|
# Setting to false will fetch blocks consecutively with its events and then process them (Behaviour is followed in realtime processing near head).
|
||||||
|
useBlockRanges = true
|
||||||
|
|
||||||
|
# Block range in which logs are fetched during historical blocks processing
|
||||||
|
historicalLogsBlockRange = 2000
|
||||||
|
|
||||||
|
# Max block range of historical processing after which it waits for completion of events processing
|
||||||
|
# If set to -1 historical processing does not wait for events processing and completes till latest canonical block
|
||||||
|
historicalMaxFetchAhead = 10000
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# Originally from: https://github.com/devcontainers/images/blob/main/src/javascript-node/.devcontainer/Dockerfile
|
||||||
|
# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster
|
||||||
|
ARG VARIANT=20-bullseye
|
||||||
|
FROM node:${VARIANT}
|
||||||
|
|
||||||
|
ARG USERNAME=node
|
||||||
|
ARG NPM_GLOBAL=/usr/local/share/npm-global
|
||||||
|
|
||||||
|
# Add NPM global to PATH.
|
||||||
|
ENV PATH=${NPM_GLOBAL}/bin:${PATH}
|
||||||
|
# Prevents npm from printing version warnings
|
||||||
|
ENV NPM_CONFIG_UPDATE_NOTIFIER=false
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
# Configure global npm install location, use group to adapt to UID/GID changes
|
||||||
|
if ! cat /etc/group | grep -e "^npm:" > /dev/null 2>&1; then groupadd -r npm; fi \
|
||||||
|
&& usermod -a -G npm ${USERNAME} \
|
||||||
|
&& umask 0002 \
|
||||||
|
&& mkdir -p ${NPM_GLOBAL} \
|
||||||
|
&& touch /usr/local/etc/npmrc \
|
||||||
|
&& chown ${USERNAME}:npm ${NPM_GLOBAL} /usr/local/etc/npmrc \
|
||||||
|
&& chmod g+s ${NPM_GLOBAL} \
|
||||||
|
&& npm config -g set prefix ${NPM_GLOBAL} \
|
||||||
|
&& su ${USERNAME} -c "npm config -g set prefix ${NPM_GLOBAL}" \
|
||||||
|
# Install eslint
|
||||||
|
&& su ${USERNAME} -c "umask 0002 && npm install -g eslint" \
|
||||||
|
&& npm cache clean --force > /dev/null 2>&1
|
||||||
|
|
||||||
|
# [Optional] Uncomment this section to install additional OS packages.
|
||||||
|
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||||
|
&& apt-get -y install --no-install-recommends jq gettext-base moreutils
|
||||||
|
|
||||||
|
# [Optional] Uncomment if you want to install more global node modules
|
||||||
|
# RUN su node -c "npm install -g <your-package-list-here>"
|
||||||
|
|
||||||
|
# Expose port for http
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
COPY /scripts /scripts
|
||||||
|
|
||||||
|
# Default command sleeps forever so docker doesn't kill it
|
||||||
|
CMD ["/scripts/start-serving-app.sh"]
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
FROM cerc/nextjs-base:local
|
||||||
|
|
||||||
|
ARG CERC_NEXT_VERSION=keep
|
||||||
|
ARG CERC_BUILD_TOOL
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . .
|
||||||
|
RUN rm -rf node_modules build .next*
|
||||||
|
RUN /scripts/build-app.sh /app
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build cerc/laconic-registry-cli
|
||||||
|
|
||||||
|
source ${CERC_CONTAINER_BASE_DIR}/build-base.sh
|
||||||
|
|
||||||
|
# See: https://stackoverflow.com/a/246128/1701505
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
|
||||||
|
CERC_CONTAINER_BUILD_WORK_DIR=${CERC_CONTAINER_BUILD_WORK_DIR:-$SCRIPT_DIR}
|
||||||
|
CERC_CONTAINER_BUILD_DOCKERFILE=${CERC_CONTAINER_BUILD_DOCKERFILE:-$SCRIPT_DIR/Dockerfile}
|
||||||
|
CERC_CONTAINER_BUILD_TAG=${CERC_CONTAINER_BUILD_TAG:-cerc/nextjs-base:local}
|
||||||
|
|
||||||
|
docker build -t $CERC_CONTAINER_BUILD_TAG ${build_command_args} -f $CERC_CONTAINER_BUILD_DOCKERFILE $CERC_CONTAINER_BUILD_WORK_DIR
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
|
WORK_DIR="${1:-./}"
|
||||||
|
SRC_DIR="${2:-.next}"
|
||||||
|
TRG_DIR="${3:-.next-r}"
|
||||||
|
|
||||||
|
CERC_BUILD_TOOL="${CERC_BUILD_TOOL}"
|
||||||
|
if [ -z "$CERC_BUILD_TOOL" ]; then
|
||||||
|
if [ -f "yarn.lock" ]; then
|
||||||
|
CERC_BUILD_TOOL=npm
|
||||||
|
else
|
||||||
|
CERC_BUILD_TOOL=yarn
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "${WORK_DIR}" || exit 1
|
||||||
|
|
||||||
|
rm -rf "$TRG_DIR"
|
||||||
|
mkdir -p "$TRG_DIR"
|
||||||
|
cp -rp "$SRC_DIR" "$TRG_DIR/"
|
||||||
|
|
||||||
|
if [ -f ".env" ]; then
|
||||||
|
TMP_ENV=`mktemp`
|
||||||
|
declare -px > $TMP_ENV
|
||||||
|
set -a
|
||||||
|
source .env
|
||||||
|
source $TMP_ENV
|
||||||
|
set +a
|
||||||
|
rm -f $TMP_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
|
for f in $(find "$TRG_DIR" -regex ".*.[tj]sx?$" -type f | grep -v 'node_modules'); do
|
||||||
|
for e in $(cat "${f}" | tr -s '[:blank:]' '\n' | tr -s '[{},();]' '\n' | egrep -o '^"CERC_RUNTIME_ENV_[^\"]+"'); do
|
||||||
|
orig_name=$(echo -n "${e}" | sed 's/"//g')
|
||||||
|
cur_name=$(echo -n "${orig_name}" | sed 's/CERC_RUNTIME_ENV_//g')
|
||||||
|
cur_val=$(echo -n "\$${cur_name}" | envsubst)
|
||||||
|
esc_val=$(sed 's/[&/\]/\\&/g' <<< "$cur_val")
|
||||||
|
echo "$f: $cur_name=$cur_val"
|
||||||
|
sed -i "s/$orig_name/$esc_val/g" $f
|
||||||
|
done
|
||||||
|
done
|
||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
|
CERC_NEXT_VERSION="${CERC_NEXT_VERSION:-keep}"
|
||||||
|
CERC_BUILD_TOOL="${CERC_BUILD_TOOL}"
|
||||||
|
if [ -z "$CERC_BUILD_TOOL" ]; then
|
||||||
|
if [ -f "yarn.lock" ] && [ ! -f "package-lock.json" ]; then
|
||||||
|
CERC_BUILD_TOOL=yarn
|
||||||
|
else
|
||||||
|
CERC_BUILD_TOOL=npm
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
WORK_DIR="${1:-/app}"
|
||||||
|
|
||||||
|
cd "${WORK_DIR}" || exit 1
|
||||||
|
|
||||||
|
if [ ! -f "next.config.dist" ]; then
|
||||||
|
cp next.config.js next.config.dist
|
||||||
|
fi
|
||||||
|
|
||||||
|
which js-beautify >/dev/null
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
npm i -g js-beautify
|
||||||
|
fi
|
||||||
|
|
||||||
|
js-beautify next.config.dist > next.config.js
|
||||||
|
echo "" >> next.config.js
|
||||||
|
|
||||||
|
WEBPACK_REQ_LINE=$(grep -n "require([\'\"]webpack[\'\"])" next.config.js | cut -d':' -f1)
|
||||||
|
if [ -z "$WEBPACK_REQ_LINE" ]; then
|
||||||
|
cat > next.config.js.0 <<EOF
|
||||||
|
const webpack = require('webpack');
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > next.config.js.1 <<EOF
|
||||||
|
let envMap;
|
||||||
|
try {
|
||||||
|
// .env-list.json provides us a list of identifiers which should be replaced at runtime.
|
||||||
|
envMap = require('./.env-list.json').reduce((a, v) => {
|
||||||
|
a[v] = \`"CERC_RUNTIME_ENV_\${v.split(/\./).pop()}"\`;
|
||||||
|
return a;
|
||||||
|
}, {});
|
||||||
|
} catch {
|
||||||
|
// If .env-list.json cannot be loaded, we are probably running in dev mode, so use process.env instead.
|
||||||
|
envMap = Object.keys(process.env).reduce((a, v) => {
|
||||||
|
if (v.startsWith('CERC_')) {
|
||||||
|
a[\`process.env.\${v}\`] = JSON.stringify(process.env[v]);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
CONFIG_LINES=$(wc -l next.config.js | awk '{ print $1 }')
|
||||||
|
ENV_LINE=$(grep -n 'env:' next.config.js | cut -d':' -f1)
|
||||||
|
WEBPACK_CONF_LINE=$(egrep -n 'webpack:\s+\([^,]+,' next.config.js | cut -d':' -f1)
|
||||||
|
NEXT_SECTION_ADJUSTMENT=0
|
||||||
|
|
||||||
|
if [ -n "$WEBPACK_CONF_LINE" ]; then
|
||||||
|
WEBPACK_CONF_VAR=$(egrep -n 'webpack:\s+\([^,]+,' next.config.js | cut -d',' -f1 | cut -d'(' -f2)
|
||||||
|
head -$(( ${WEBPACK_CONF_LINE} )) next.config.js > next.config.js.2
|
||||||
|
cat > next.config.js.3 <<EOF
|
||||||
|
$WEBPACK_CONF_VAR.plugins.push(new webpack.DefinePlugin(envMap));
|
||||||
|
EOF
|
||||||
|
NEXT_SECTION_LINE=$((WEBPACK_CONF_LINE))
|
||||||
|
elif [ -n "$ENV_LINE" ]; then
|
||||||
|
head -$(( ${ENV_LINE} - 1 )) next.config.js > next.config.js.2
|
||||||
|
cat > next.config.js.3 <<EOF
|
||||||
|
webpack: (config) => {
|
||||||
|
config.plugins.push(new webpack.DefinePlugin(envMap));
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
EOF
|
||||||
|
NEXT_SECTION_ADJUSTMENT=1
|
||||||
|
NEXT_SECTION_LINE=$ENV_LINE
|
||||||
|
else
|
||||||
|
echo "WARNING: Cannot find location to insert environment variable map in next.config.js" 1>&2
|
||||||
|
rm -f next.config.js.*
|
||||||
|
NEXT_SECTION_LINE=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
tail -$(( ${CONFIG_LINES} - ${NEXT_SECTION_LINE} + ${NEXT_SECTION_ADJUSTMENT} )) next.config.js > next.config.js.5
|
||||||
|
|
||||||
|
cat next.config.js.* | sed 's/^ *//g' | js-beautify | grep -v 'process\.\env\.' | js-beautify > next.config.js
|
||||||
|
rm next.config.js.*
|
||||||
|
|
||||||
|
"${SCRIPT_DIR}/find-env.sh" "$(pwd)" > .env-list.json
|
||||||
|
|
||||||
|
if [ ! -f "package.dist" ]; then
|
||||||
|
cp package.json package.dist
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat package.dist | jq '.scripts.cerc_compile = "next experimental-compile"' | jq '.scripts.cerc_generate = "next experimental-generate"' > package.json
|
||||||
|
|
||||||
|
CUR_NEXT_VERSION="`jq -r '.dependencies.next' package.json`"
|
||||||
|
|
||||||
|
if [ "$CERC_NEXT_VERSION" != "keep" ] && [ "$CUR_NEXT_VERSION" != "$CERC_NEXT_VERSION" ]; then
|
||||||
|
echo "Changing 'next' version specifier from '$CUR_NEXT_VERSION' to '$CERC_NEXT_VERSION' (set with --build-arg CERC_NEXT_VERSION)"
|
||||||
|
cat package.json | jq ".dependencies.next = \"$CERC_NEXT_VERSION\"" | sponge package.json
|
||||||
|
else
|
||||||
|
echo "'next' version specifier '$CUR_NEXT_VERSION' (override with --build-arg CERC_NEXT_VERSION)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
$CERC_BUILD_TOOL install || exit 1
|
||||||
|
$CERC_BUILD_TOOL run cerc_compile || exit 1
|
||||||
|
|
||||||
|
exit 0
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
|
WORK_DIR="${1:-./}"
|
||||||
|
TMPF=$(mktemp)
|
||||||
|
|
||||||
|
cd "$WORK_DIR" || exit 1
|
||||||
|
|
||||||
|
for d in $(find . -maxdepth 1 -type d | grep -v '\./\.' | grep '/' | cut -d'/' -f2); do
|
||||||
|
egrep "/$d[/$]?" .gitignore >/dev/null 2>/dev/null
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
for f in $(find "$d" -regex ".*.[tj]sx?$" -type f); do
|
||||||
|
cat "$f" | tr -s '[:blank:]' '\n' | tr -s '[{},()]' '\n' | egrep -o 'process.env.[A-Za-z0-9_]+' >> $TMPF
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
NEXT_CONF="next.config.js next.config.dist"
|
||||||
|
for f in $NEXT_CONF; do
|
||||||
|
cat "$f" | tr -s '[:blank:]' '\n' | tr -s '[{},()]' '\n' | egrep -o 'process.env.[A-Za-z0-9_]+' >> $TMPF
|
||||||
|
done
|
||||||
|
|
||||||
|
cat $TMPF | sort -u | jq --raw-input . | jq --slurp .
|
||||||
|
rm -f $TMPF
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
|
||||||
|
CERC_BUILD_TOOL="${CERC_BUILD_TOOL}"
|
||||||
|
if [ -z "$CERC_BUILD_TOOL" ]; then
|
||||||
|
if [ -f "yarn.lock" ] && [ ! -f "package-lock.json" ]; then
|
||||||
|
CERC_BUILD_TOOL=yarn
|
||||||
|
else
|
||||||
|
CERC_BUILD_TOOL=npm
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
CERC_WEBAPP_FILES_DIR="${CERC_WEBAPP_FILES_DIR:-/app}"
|
||||||
|
cd "$CERC_WEBAPP_FILES_DIR"
|
||||||
|
|
||||||
|
"$SCRIPT_DIR/apply-runtime-env.sh" "`pwd`" .next .next-r
|
||||||
|
mv .next .next.old
|
||||||
|
mv .next-r/.next .
|
||||||
|
|
||||||
|
if [ "$CERC_NEXTJS_SKIP_GENERATE" != "true" ]; then
|
||||||
|
jq -e '.scripts.cerc_generate' package.json >/dev/null
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
npm run cerc_generate > gen.out 2>&1 &
|
||||||
|
tail -n0 -f gen.out | sed '/rendered as static HTML/ q'
|
||||||
|
count=0
|
||||||
|
while [ $count -lt 10 ]; do
|
||||||
|
sleep 1
|
||||||
|
ps -ef | grep 'node' | grep 'next' | grep 'generate' >/dev/null
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
count=$((count + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
kill $(ps -ef |grep node | grep next | grep generate | awk '{print $2}') 2>/dev/null
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
$CERC_BUILD_TOOL start . -p ${CERC_LISTEN_PORT:-3000}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build the osmosis front end image
|
||||||
|
source ${CERC_CONTAINER_BASE_DIR}/build-base.sh
|
||||||
|
docker build -t cerc/osmosis-front-end:local -f ${CERC_REPO_BASE_DIR}/osmosis-frontend/docker/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/osmosis-frontend
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
FROM node:18.17.1-alpine3.18
|
||||||
|
|
||||||
|
RUN apk --update --no-cache add git python3 alpine-sdk bash curl jq
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN echo "Installing dependencies and building merkl-sushiswap-v3-watcher-ts" && \
|
||||||
|
yarn && yarn build
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build cerc/watcher-merkl-sushiswap-v3
|
||||||
|
|
||||||
|
source ${CERC_CONTAINER_BASE_DIR}/build-base.sh
|
||||||
|
|
||||||
|
# See: https://stackoverflow.com/a/246128/1701505
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
|
||||||
|
docker build -t cerc/my-new-stack:local -f ${CERC_REPO_BASE_DIR}/my-new-stack/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/my-new-stack
|
||||||
|
|
||||||
|
docker build -t cerc/watcher-merkl-sushiswap-v3:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/merkl-sushiswap-v3-watcher-ts
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
FROM node:18.17.1-alpine3.18
|
||||||
|
|
||||||
|
RUN apk --update --no-cache add git python3 alpine-sdk bash curl jq
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN echo "Installing dependencies and building sushiswap-v3-watcher-ts" && \
|
||||||
|
yarn && yarn build
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build cerc/watcher-sushiswap-v3
|
||||||
|
|
||||||
|
source ${CERC_CONTAINER_BASE_DIR}/build-base.sh
|
||||||
|
|
||||||
|
# See: https://stackoverflow.com/a/246128/1701505
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
|
||||||
|
docker build -t cerc/watcher-sushiswap-v3:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} ${CERC_REPO_BASE_DIR}/sushiswap-v3-watcher-ts
|
||||||
@@ -57,3 +57,5 @@ cerc/nitro-contracts
|
|||||||
cerc/mobymask-snap
|
cerc/mobymask-snap
|
||||||
cerc/ponder
|
cerc/ponder
|
||||||
cerc/nitro-rpc-client
|
cerc/nitro-rpc-client
|
||||||
|
cerc/watcher-merkl-sushiswap-v3
|
||||||
|
cerc/watcher-sushiswap-v3
|
||||||
|
|||||||
@@ -43,3 +43,5 @@ nitro-contracts
|
|||||||
mobymask-snap
|
mobymask-snap
|
||||||
ponder
|
ponder
|
||||||
ipld-eth-server-payments
|
ipld-eth-server-payments
|
||||||
|
merkl-sushiswap-v3
|
||||||
|
sushiswap-v3
|
||||||
|
|||||||
@@ -47,3 +47,5 @@ github.com/cerc-io/go-nitro
|
|||||||
github.com/cerc-io/ts-nitro
|
github.com/cerc-io/ts-nitro
|
||||||
github.com/cerc-io/mobymask-snap
|
github.com/cerc-io/mobymask-snap
|
||||||
github.com/cerc-io/ponder
|
github.com/cerc-io/ponder
|
||||||
|
github.com/cerc-io/merkl-sushiswap-v3-watcher-ts
|
||||||
|
github.com/cerc-io/sushiswap-v3-watcher-ts
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ ports:
|
|||||||
Create deployment:
|
Create deployment:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
laconic-so deploy create --spec-file graph-node-spec.yml --deployment-dir graph-node-deployment
|
laconic-so --stack graph-node deploy create --spec-file graph-node-spec.yml --deployment-dir graph-node-deployment
|
||||||
```
|
```
|
||||||
|
|
||||||
## Start the stack
|
## Start the stack
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
# Merkl SushiSwap v3 Watcher
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Clone required repositories:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack merkl-sushiswap-v3 setup-repositories --git-ssh --pull
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the container images:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack merkl-sushiswap-v3 build-containers
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Create and update an env file to be used in the next step:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# External Filecoin (ETH RPC) endpoint to point the watcher
|
||||||
|
CERC_ETH_RPC_ENDPOINT=
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy the stack
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack merkl-sushiswap-v3 deploy --cluster merkl_sushiswap_v3 --env-file <PATH_TO_ENV_FILE> up
|
||||||
|
```
|
||||||
|
|
||||||
|
* To list down and monitor the running containers:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack merkl-sushiswap-v3 deploy --cluster merkl_sushiswap_v3 ps
|
||||||
|
|
||||||
|
# With status
|
||||||
|
docker ps -a
|
||||||
|
|
||||||
|
# Check logs for a container
|
||||||
|
docker logs -f <CONTAINER_ID>
|
||||||
|
```
|
||||||
|
|
||||||
|
* Open the GQL playground at http://localhost:3007/graphql
|
||||||
|
|
||||||
|
```graphql
|
||||||
|
{
|
||||||
|
_meta {
|
||||||
|
block {
|
||||||
|
number
|
||||||
|
timestamp
|
||||||
|
}
|
||||||
|
hasIndexingErrors
|
||||||
|
}
|
||||||
|
|
||||||
|
factories {
|
||||||
|
id
|
||||||
|
poolCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Clean up
|
||||||
|
|
||||||
|
Stop all the services running in background:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack merkl-sushiswap-v3 deploy --cluster merkl_sushiswap_v3 down
|
||||||
|
```
|
||||||
|
|
||||||
|
Clear volumes created by this stack:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all relevant volumes
|
||||||
|
docker volume ls -q --filter "name=merkl_sushiswap_v3"
|
||||||
|
|
||||||
|
# Remove all the listed volumes
|
||||||
|
docker volume rm $(docker volume ls -q --filter "name=merkl_sushiswap_v3")
|
||||||
|
```
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
version: "1.0"
|
||||||
|
name: merkl-sushiswap-v3
|
||||||
|
description: "SushiSwap v3 watcher stack"
|
||||||
|
repos:
|
||||||
|
- github.com/cerc-io/merkl-sushiswap-v3-watcher-ts@v0.1.1
|
||||||
|
containers:
|
||||||
|
- cerc/watcher-merkl-sushiswap-v3
|
||||||
|
pods:
|
||||||
|
- watcher-merkl-sushiswap-v3
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# self-hosted osmosis
|
||||||
|
|
||||||
|
Build and deploy:
|
||||||
|
- 1) self-hosted gitea,
|
||||||
|
- 2) an ipfs node,
|
||||||
|
- 3) the osmosis front end,
|
||||||
|
- 4) a laconicd chain
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
# support image for the gitea package registry
|
||||||
|
laconic-so --stack build-support build-containers
|
||||||
|
|
||||||
|
# todo: pre-run clone
|
||||||
|
|
||||||
|
# clones and builds several things
|
||||||
|
laconic-so --stack osmosis setup-repositories
|
||||||
|
laconic-so --stack osmosis build-containers
|
||||||
|
laconic-so --stack osmosis deploy up
|
||||||
|
```
|
||||||
|
|
||||||
|
Setup a test chain:
|
||||||
|
```
|
||||||
|
export CERC_NPM_REGISTRY_URL=https://git.vdb.to/api/packages/cerc-io/npm/
|
||||||
|
|
||||||
|
laconic-so --stack fixturenet-laconic-loaded setup-repositories --include git.vdb.to/cerc-io/laconicd,git.vdb.to/cerc-io/laconic-sdk,git.vdb.to/cerc-io/laconic-registry-cli,git.vdb.to/cerc-io/laconic-console
|
||||||
|
|
||||||
|
laconic-so --stack fixturenet-laconic-loaded build-containers
|
||||||
|
|
||||||
|
export LACONIC_HOSTED_ENDPOINT=http://<your-IP>
|
||||||
|
|
||||||
|
laconic-so --stack fixturenet-laconic-loaded deploy up
|
||||||
|
```
|
||||||
|
|
||||||
|
then `docker exec` into the `laconicd` container and either export the private key or create a new one and send funds to it. Use that private key for `LACONIC_HOTWALLET_KEY`.
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
version: "0.1"
|
||||||
|
name: osmosis
|
||||||
|
repos:
|
||||||
|
# these are for gitea
|
||||||
|
- git.vdb.to/cerc-io/hosting@names-for-so
|
||||||
|
- gitea.com/gitea/act_runner
|
||||||
|
# add the osmosis FE
|
||||||
|
- github.com/osmosis-labs/osmosis-frontend
|
||||||
|
containers:
|
||||||
|
- cerc/act-runner
|
||||||
|
- cerc/act-runner-task-executor
|
||||||
|
# note: osmosis builds but doesn't run
|
||||||
|
- cerc/osmosis-front-end
|
||||||
|
pods:
|
||||||
|
- name: gitea
|
||||||
|
repository: cerc-io/hosting
|
||||||
|
path: gitea
|
||||||
|
pre_start_command: "run-this-first.sh"
|
||||||
|
post_start_command: "initialize-gitea.sh"
|
||||||
|
# todo, e.g., mirroring all of osmosis repos: https://git.vdb.to/cerc-io/hosting/pulls/42
|
||||||
|
- name: act-runner
|
||||||
|
repository: cerc-io/hosting
|
||||||
|
path: act-runner
|
||||||
|
pre_start_command: "pre_start.sh"
|
||||||
|
post_start_command: "post_start.sh"
|
||||||
|
- osmosis-front-end
|
||||||
|
- kubo
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# SushiSwap v3 Watcher
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Clone required repositories:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack sushiswap-v3 setup-repositories --git-ssh --pull
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the container images:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack sushiswap-v3 build-containers
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Create and update an env file to be used in the next step:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# External Filecoin (ETH RPC) endpoint to point the watcher
|
||||||
|
CERC_ETH_RPC_ENDPOINT=
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy the stack
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack sushiswap-v3 deploy --cluster sushiswap_v3 --env-file <PATH_TO_ENV_FILE> up
|
||||||
|
```
|
||||||
|
|
||||||
|
* To list down and monitor the running containers:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack sushiswap-v3 deploy --cluster sushiswap_v3 ps
|
||||||
|
|
||||||
|
# With status
|
||||||
|
docker ps -a
|
||||||
|
|
||||||
|
# Check logs for a container
|
||||||
|
docker logs -f <CONTAINER_ID>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Clean up
|
||||||
|
|
||||||
|
Stop all the services running in background:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so --stack sushiswap-v3 deploy --cluster sushiswap_v3 down
|
||||||
|
```
|
||||||
|
|
||||||
|
Clear volumes created by this stack:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all relevant volumes
|
||||||
|
docker volume ls -q --filter "name=sushiswap_v3"
|
||||||
|
|
||||||
|
# Remove all the listed volumes
|
||||||
|
docker volume rm $(docker volume ls -q --filter "name=sushiswap_v3")
|
||||||
|
```
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
version: "1.0"
|
||||||
|
name: sushiswap-v3
|
||||||
|
description: "SushiSwap v3 watcher stack"
|
||||||
|
repos:
|
||||||
|
- github.com/cerc-io/sushiswap-v3-watcher-ts@v0.1.1
|
||||||
|
containers:
|
||||||
|
- cerc/watcher-sushiswap-v3
|
||||||
|
pods:
|
||||||
|
- watcher-sushiswap-v3
|
||||||
@@ -21,7 +21,7 @@ from stack_orchestrator.deploy.deployer import Deployer, DeployerException, Depl
|
|||||||
class DockerDeployer(Deployer):
|
class DockerDeployer(Deployer):
|
||||||
name: str = "compose"
|
name: str = "compose"
|
||||||
|
|
||||||
def __init__(self, compose_files, compose_project_name, compose_env_file) -> None:
|
def __init__(self, deployment_dir, compose_files, compose_project_name, compose_env_file) -> None:
|
||||||
self.docker = DockerClient(compose_files=compose_files, compose_project_name=compose_project_name,
|
self.docker = DockerClient(compose_files=compose_files, compose_project_name=compose_project_name,
|
||||||
compose_env_file=compose_env_file)
|
compose_env_file=compose_env_file)
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ from stack_orchestrator.util import include_exclude_check, get_parsed_stack_conf
|
|||||||
from stack_orchestrator.deploy.deployer import Deployer, DeployerException
|
from stack_orchestrator.deploy.deployer import Deployer, DeployerException
|
||||||
from stack_orchestrator.deploy.deployer_factory import getDeployer
|
from stack_orchestrator.deploy.deployer_factory import getDeployer
|
||||||
from stack_orchestrator.deploy.deploy_types import ClusterContext, DeployCommandContext
|
from stack_orchestrator.deploy.deploy_types import ClusterContext, DeployCommandContext
|
||||||
|
from stack_orchestrator.deploy.deployment_context import DeploymentContext
|
||||||
from stack_orchestrator.deploy.deployment_create import create as deployment_create
|
from stack_orchestrator.deploy.deployment_create import create as deployment_create
|
||||||
from stack_orchestrator.deploy.deployment_create import init as deployment_init
|
from stack_orchestrator.deploy.deployment_create import init as deployment_init
|
||||||
from stack_orchestrator.deploy.deployment_create import setup as deployment_setup
|
from stack_orchestrator.deploy.deployment_create import setup as deployment_setup
|
||||||
@@ -56,14 +57,17 @@ def command(ctx, include, exclude, env_file, cluster, deploy_to):
|
|||||||
if deploy_to is None:
|
if deploy_to is None:
|
||||||
deploy_to = "compose"
|
deploy_to = "compose"
|
||||||
|
|
||||||
ctx.obj = create_deploy_context(global_options2(ctx), stack, include, exclude, cluster, env_file, deploy_to)
|
ctx.obj = create_deploy_context(global_options2(ctx), None, stack, include, exclude, cluster, env_file, deploy_to)
|
||||||
# Subcommand is executed now, by the magic of click
|
# Subcommand is executed now, by the magic of click
|
||||||
|
|
||||||
|
|
||||||
def create_deploy_context(global_context, stack, include, exclude, cluster, env_file, deployer):
|
def create_deploy_context(
|
||||||
|
global_context, deployment_context: DeploymentContext, stack, include, exclude, cluster, env_file, deployer):
|
||||||
cluster_context = _make_cluster_context(global_context, stack, include, exclude, cluster, env_file)
|
cluster_context = _make_cluster_context(global_context, stack, include, exclude, cluster, env_file)
|
||||||
|
deployment_dir = deployment_context.deployment_dir if deployment_context else None
|
||||||
# See: https://gabrieldemarmiesse.github.io/python-on-whales/sub-commands/compose/
|
# See: https://gabrieldemarmiesse.github.io/python-on-whales/sub-commands/compose/
|
||||||
deployer = getDeployer(deployer, compose_files=cluster_context.compose_files, compose_project_name=cluster_context.cluster,
|
deployer = getDeployer(deployer, deployment_dir, compose_files=cluster_context.compose_files,
|
||||||
|
compose_project_name=cluster_context.cluster,
|
||||||
compose_env_file=cluster_context.env_file)
|
compose_env_file=cluster_context.env_file)
|
||||||
return DeployCommandContext(stack, cluster_context, deployer)
|
return DeployCommandContext(stack, cluster_context, deployer)
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,8 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from typing import List
|
from typing import List, Mapping
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
|
||||||
from stack_orchestrator.command_types import CommandOptions
|
from stack_orchestrator.command_types import CommandOptions
|
||||||
from stack_orchestrator.deploy.deployer import Deployer
|
from stack_orchestrator.deploy.deployer import Deployer
|
||||||
|
|
||||||
@@ -38,12 +37,6 @@ class DeployCommandContext:
|
|||||||
deployer: Deployer
|
deployer: Deployer
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class DeploymentContext:
|
|
||||||
deployment_dir: Path
|
|
||||||
command_context: DeployCommandContext
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class VolumeMapping:
|
class VolumeMapping:
|
||||||
host_path: str
|
host_path: str
|
||||||
@@ -66,3 +59,8 @@ class LaconicStackSetupCommand:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class LaconicStackCreateCommand:
|
class LaconicStackCreateCommand:
|
||||||
network_dir: str
|
network_dir: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DeployEnvVars:
|
||||||
|
map: Mapping[str, str]
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ def getDeployerConfigGenerator(type: str):
|
|||||||
print(f"ERROR: deploy-to {type} is not valid")
|
print(f"ERROR: deploy-to {type} is not valid")
|
||||||
|
|
||||||
|
|
||||||
def getDeployer(type: str, compose_files, compose_project_name, compose_env_file):
|
def getDeployer(type: str, deployment_dir, compose_files, compose_project_name, compose_env_file):
|
||||||
if type == "compose" or type is None:
|
if type == "compose" or type is None:
|
||||||
return DockerDeployer(compose_files, compose_project_name, compose_env_file)
|
return DockerDeployer(deployment_dir, compose_files, compose_project_name, compose_env_file)
|
||||||
elif type == "k8s":
|
elif type == "k8s":
|
||||||
return K8sDeployer(compose_files, compose_project_name, compose_env_file)
|
return K8sDeployer(deployment_dir, compose_files, compose_project_name, compose_env_file)
|
||||||
else:
|
else:
|
||||||
print(f"ERROR: deploy-to {type} is not valid")
|
print(f"ERROR: deploy-to {type} is not valid")
|
||||||
|
|||||||
@@ -18,34 +18,7 @@ from pathlib import Path
|
|||||||
import sys
|
import sys
|
||||||
from stack_orchestrator.deploy.deploy import up_operation, down_operation, ps_operation, port_operation
|
from stack_orchestrator.deploy.deploy import up_operation, down_operation, ps_operation, port_operation
|
||||||
from stack_orchestrator.deploy.deploy import exec_operation, logs_operation, create_deploy_context
|
from stack_orchestrator.deploy.deploy import exec_operation, logs_operation, create_deploy_context
|
||||||
from stack_orchestrator.deploy.stack import Stack
|
from stack_orchestrator.deploy.deployment_context import DeploymentContext
|
||||||
from stack_orchestrator.deploy.spec import Spec
|
|
||||||
|
|
||||||
|
|
||||||
class DeploymentContext:
|
|
||||||
dir: Path
|
|
||||||
spec: Spec
|
|
||||||
stack: Stack
|
|
||||||
|
|
||||||
def get_stack_file(self):
|
|
||||||
return self.dir.joinpath("stack.yml")
|
|
||||||
|
|
||||||
def get_spec_file(self):
|
|
||||||
return self.dir.joinpath("spec.yml")
|
|
||||||
|
|
||||||
def get_env_file(self):
|
|
||||||
return self.dir.joinpath("config.env")
|
|
||||||
|
|
||||||
# TODO: implement me
|
|
||||||
def get_cluster_name(self):
|
|
||||||
return None
|
|
||||||
|
|
||||||
def init(self, dir):
|
|
||||||
self.dir = dir
|
|
||||||
self.stack = Stack()
|
|
||||||
self.stack.init_from_file(self.get_stack_file())
|
|
||||||
self.spec = Spec()
|
|
||||||
self.spec.init_from_file(self.get_spec_file())
|
|
||||||
|
|
||||||
|
|
||||||
@click.group()
|
@click.group()
|
||||||
@@ -77,7 +50,7 @@ def make_deploy_context(ctx):
|
|||||||
stack_file_path = context.get_stack_file()
|
stack_file_path = context.get_stack_file()
|
||||||
env_file = context.get_env_file()
|
env_file = context.get_env_file()
|
||||||
cluster_name = context.get_cluster_name()
|
cluster_name = context.get_cluster_name()
|
||||||
return create_deploy_context(ctx.parent.parent.obj, stack_file_path, None, None, cluster_name, env_file,
|
return create_deploy_context(ctx.parent.parent.obj, context, stack_file_path, None, None, cluster_name, env_file,
|
||||||
context.spec.obj["deploy-to"])
|
context.spec.obj["deploy-to"])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
# Copyright © 2022, 2023 Vulcanize
|
||||||
|
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from stack_orchestrator.deploy.stack import Stack
|
||||||
|
from stack_orchestrator.deploy.spec import Spec
|
||||||
|
|
||||||
|
|
||||||
|
class DeploymentContext:
|
||||||
|
deployment_dir: Path
|
||||||
|
spec: Spec
|
||||||
|
stack: Stack
|
||||||
|
|
||||||
|
def get_stack_file(self):
|
||||||
|
return self.deployment_dir.joinpath("stack.yml")
|
||||||
|
|
||||||
|
def get_spec_file(self):
|
||||||
|
return self.deployment_dir.joinpath("spec.yml")
|
||||||
|
|
||||||
|
def get_env_file(self):
|
||||||
|
return self.deployment_dir.joinpath("config.env")
|
||||||
|
|
||||||
|
# TODO: implement me
|
||||||
|
def get_cluster_name(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def init(self, dir):
|
||||||
|
self.deployment_dir = dir
|
||||||
|
self.spec = Spec()
|
||||||
|
self.spec.init_from_file(self.get_spec_file())
|
||||||
|
self.stack = Stack(self.spec.obj["stack"])
|
||||||
|
self.stack.init_from_file(self.get_stack_file())
|
||||||
@@ -24,8 +24,9 @@ import sys
|
|||||||
from stack_orchestrator.util import (get_stack_file_path, get_parsed_deployment_spec, get_parsed_stack_config,
|
from stack_orchestrator.util import (get_stack_file_path, get_parsed_deployment_spec, get_parsed_stack_config,
|
||||||
global_options, get_yaml, get_pod_list, get_pod_file_path, pod_has_scripts,
|
global_options, get_yaml, get_pod_list, get_pod_file_path, pod_has_scripts,
|
||||||
get_pod_script_paths, get_plugin_code_paths)
|
get_pod_script_paths, get_plugin_code_paths)
|
||||||
from stack_orchestrator.deploy.deploy_types import DeploymentContext, DeployCommandContext, LaconicStackSetupCommand
|
from stack_orchestrator.deploy.deploy_types import LaconicStackSetupCommand
|
||||||
from stack_orchestrator.deploy.deployer_factory import getDeployerConfigGenerator
|
from stack_orchestrator.deploy.deployer_factory import getDeployerConfigGenerator
|
||||||
|
from stack_orchestrator.deploy.deployment_context import DeploymentContext
|
||||||
|
|
||||||
|
|
||||||
def _make_default_deployment_dir():
|
def _make_default_deployment_dir():
|
||||||
@@ -108,8 +109,8 @@ def _fixup_pod_file(pod, spec, compose_dir):
|
|||||||
pod["services"][container_name]["ports"] = container_ports
|
pod["services"][container_name]["ports"] = container_ports
|
||||||
|
|
||||||
|
|
||||||
def _commands_plugin_paths(ctx: DeployCommandContext):
|
def _commands_plugin_paths(stack_name: str):
|
||||||
plugin_paths = get_plugin_code_paths(ctx.stack)
|
plugin_paths = get_plugin_code_paths(stack_name)
|
||||||
ret = [p.joinpath("deploy", "commands.py") for p in plugin_paths]
|
ret = [p.joinpath("deploy", "commands.py") for p in plugin_paths]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@@ -123,7 +124,7 @@ def call_stack_deploy_init(deploy_command_context):
|
|||||||
# Link with the python file in the stack
|
# Link with the python file in the stack
|
||||||
# Call a function in it
|
# Call a function in it
|
||||||
# If no function found, return None
|
# If no function found, return None
|
||||||
python_file_paths = _commands_plugin_paths(deploy_command_context)
|
python_file_paths = _commands_plugin_paths(deploy_command_context.stack)
|
||||||
|
|
||||||
ret = None
|
ret = None
|
||||||
init_done = False
|
init_done = False
|
||||||
@@ -147,7 +148,7 @@ def call_stack_deploy_setup(deploy_command_context, parameters: LaconicStackSetu
|
|||||||
# Link with the python file in the stack
|
# Link with the python file in the stack
|
||||||
# Call a function in it
|
# Call a function in it
|
||||||
# If no function found, return None
|
# If no function found, return None
|
||||||
python_file_paths = _commands_plugin_paths(deploy_command_context)
|
python_file_paths = _commands_plugin_paths(deploy_command_context.stack)
|
||||||
for python_file_path in python_file_paths:
|
for python_file_path in python_file_paths:
|
||||||
if python_file_path.exists():
|
if python_file_path.exists():
|
||||||
spec = util.spec_from_file_location("commands", python_file_path)
|
spec = util.spec_from_file_location("commands", python_file_path)
|
||||||
@@ -162,7 +163,7 @@ def call_stack_deploy_create(deployment_context, extra_args):
|
|||||||
# Link with the python file in the stack
|
# Link with the python file in the stack
|
||||||
# Call a function in it
|
# Call a function in it
|
||||||
# If no function found, return None
|
# If no function found, return None
|
||||||
python_file_paths = _commands_plugin_paths(deployment_context.command_context)
|
python_file_paths = _commands_plugin_paths(deployment_context.stack.name)
|
||||||
for python_file_path in python_file_paths:
|
for python_file_path in python_file_paths:
|
||||||
if python_file_path.exists():
|
if python_file_path.exists():
|
||||||
spec = util.spec_from_file_location("commands", python_file_path)
|
spec = util.spec_from_file_location("commands", python_file_path)
|
||||||
@@ -311,7 +312,7 @@ def _copy_files_to_directory(file_paths: List[Path], directory: Path):
|
|||||||
def create(ctx, spec_file, deployment_dir, network_dir, initial_peers):
|
def create(ctx, spec_file, deployment_dir, network_dir, initial_peers):
|
||||||
# This function fails with a useful error message if the file doens't exist
|
# This function fails with a useful error message if the file doens't exist
|
||||||
parsed_spec = get_parsed_deployment_spec(spec_file)
|
parsed_spec = get_parsed_deployment_spec(spec_file)
|
||||||
stack_name = parsed_spec['stack']
|
stack_name = parsed_spec["stack"]
|
||||||
stack_file = get_stack_file_path(stack_name)
|
stack_file = get_stack_file_path(stack_name)
|
||||||
parsed_stack = get_parsed_stack_config(stack_name)
|
parsed_stack = get_parsed_stack_config(stack_name)
|
||||||
if global_options(ctx).debug:
|
if global_options(ctx).debug:
|
||||||
@@ -367,7 +368,8 @@ def create(ctx, spec_file, deployment_dir, network_dir, initial_peers):
|
|||||||
# stack member here.
|
# stack member here.
|
||||||
deployment_command_context = ctx.obj
|
deployment_command_context = ctx.obj
|
||||||
deployment_command_context.stack = stack_name
|
deployment_command_context.stack = stack_name
|
||||||
deployment_context = DeploymentContext(Path(deployment_dir), deployment_command_context)
|
deployment_context = DeploymentContext()
|
||||||
|
deployment_context.init(Path(deployment_dir))
|
||||||
# Call the deployer to generate any deployer-specific files (e.g. for kind)
|
# Call the deployer to generate any deployer-specific files (e.g. for kind)
|
||||||
deployer_config_generator = getDeployerConfigGenerator(parsed_spec["deploy-to"])
|
deployer_config_generator = getDeployerConfigGenerator(parsed_spec["deploy-to"])
|
||||||
# TODO: make deployment_dir a Path above
|
# TODO: make deployment_dir a Path above
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ from typing import Any, List, Set
|
|||||||
|
|
||||||
from stack_orchestrator.opts import opts
|
from stack_orchestrator.opts import opts
|
||||||
from stack_orchestrator.deploy.k8s.helpers import named_volumes_from_pod_files, volume_mounts_for_service, volumes_for_pod_files
|
from stack_orchestrator.deploy.k8s.helpers import named_volumes_from_pod_files, volume_mounts_for_service, volumes_for_pod_files
|
||||||
from stack_orchestrator.deploy.k8s.helpers import parsed_pod_files_map_from_file_names
|
from stack_orchestrator.deploy.k8s.helpers import parsed_pod_files_map_from_file_names, get_node_pv_mount_path
|
||||||
|
from stack_orchestrator.deploy.k8s.helpers import env_var_map_from_file, envs_from_environment_variables_map
|
||||||
|
from stack_orchestrator.deploy.deploy_types import DeployEnvVars
|
||||||
|
|
||||||
|
|
||||||
class ClusterInfo:
|
class ClusterInfo:
|
||||||
@@ -26,11 +28,12 @@ class ClusterInfo:
|
|||||||
image_set: Set[str] = set()
|
image_set: Set[str] = set()
|
||||||
app_name: str = "test-app"
|
app_name: str = "test-app"
|
||||||
deployment_name: str = "test-deployment"
|
deployment_name: str = "test-deployment"
|
||||||
|
environment_variables: DeployEnvVars
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def int_from_pod_files(self, pod_files: List[str]):
|
def int(self, pod_files: List[str], compose_env_file):
|
||||||
self.parsed_pod_yaml_map = parsed_pod_files_map_from_file_names(pod_files)
|
self.parsed_pod_yaml_map = parsed_pod_files_map_from_file_names(pod_files)
|
||||||
# Find the set of images in the pods
|
# Find the set of images in the pods
|
||||||
for pod_name in self.parsed_pod_yaml_map:
|
for pod_name in self.parsed_pod_yaml_map:
|
||||||
@@ -42,6 +45,9 @@ class ClusterInfo:
|
|||||||
self.image_set.add(image)
|
self.image_set.add(image)
|
||||||
if opts.o.debug:
|
if opts.o.debug:
|
||||||
print(f"image_set: {self.image_set}")
|
print(f"image_set: {self.image_set}")
|
||||||
|
self.environment_variables = DeployEnvVars(env_var_map_from_file(compose_env_file))
|
||||||
|
if (opts.o.debug):
|
||||||
|
print(f"Env vars: {self.environment_variables.map}")
|
||||||
|
|
||||||
def get_pvcs(self):
|
def get_pvcs(self):
|
||||||
result = []
|
result = []
|
||||||
@@ -50,11 +56,12 @@ class ClusterInfo:
|
|||||||
print(f"Volumes: {volumes}")
|
print(f"Volumes: {volumes}")
|
||||||
for volume_name in volumes:
|
for volume_name in volumes:
|
||||||
spec = client.V1PersistentVolumeClaimSpec(
|
spec = client.V1PersistentVolumeClaimSpec(
|
||||||
storage_class_name="standard",
|
|
||||||
access_modes=["ReadWriteOnce"],
|
access_modes=["ReadWriteOnce"],
|
||||||
|
storage_class_name="manual",
|
||||||
resources=client.V1ResourceRequirements(
|
resources=client.V1ResourceRequirements(
|
||||||
requests={"storage": "2Gi"}
|
requests={"storage": "2Gi"}
|
||||||
)
|
),
|
||||||
|
volume_name=volume_name
|
||||||
)
|
)
|
||||||
pvc = client.V1PersistentVolumeClaim(
|
pvc = client.V1PersistentVolumeClaim(
|
||||||
metadata=client.V1ObjectMeta(name=volume_name,
|
metadata=client.V1ObjectMeta(name=volume_name,
|
||||||
@@ -64,6 +71,24 @@ class ClusterInfo:
|
|||||||
result.append(pvc)
|
result.append(pvc)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def get_pvs(self):
|
||||||
|
result = []
|
||||||
|
volumes = named_volumes_from_pod_files(self.parsed_pod_yaml_map)
|
||||||
|
for volume_name in volumes:
|
||||||
|
spec = client.V1PersistentVolumeSpec(
|
||||||
|
storage_class_name="manual",
|
||||||
|
access_modes=["ReadWriteOnce"],
|
||||||
|
capacity={"storage": "2Gi"},
|
||||||
|
host_path=client.V1HostPathVolumeSource(path=get_node_pv_mount_path(volume_name))
|
||||||
|
)
|
||||||
|
pv = client.V1PersistentVolume(
|
||||||
|
metadata=client.V1ObjectMeta(name=volume_name,
|
||||||
|
labels={"volume-label": volume_name}),
|
||||||
|
spec=spec,
|
||||||
|
)
|
||||||
|
result.append(pv)
|
||||||
|
return result
|
||||||
|
|
||||||
# to suit the deployment, and also annotate the container specs to point at said volumes
|
# to suit the deployment, and also annotate the container specs to point at said volumes
|
||||||
def get_deployment(self):
|
def get_deployment(self):
|
||||||
containers = []
|
containers = []
|
||||||
@@ -78,6 +103,7 @@ class ClusterInfo:
|
|||||||
container = client.V1Container(
|
container = client.V1Container(
|
||||||
name=container_name,
|
name=container_name,
|
||||||
image=image,
|
image=image,
|
||||||
|
env=envs_from_environment_variables_map(self.environment_variables.map),
|
||||||
ports=[client.V1ContainerPort(container_port=80)],
|
ports=[client.V1ContainerPort(container_port=80)],
|
||||||
volume_mounts=volume_mounts,
|
volume_mounts=volume_mounts,
|
||||||
resources=client.V1ResourceRequirements(
|
resources=client.V1ResourceRequirements(
|
||||||
|
|||||||
@@ -30,15 +30,18 @@ class K8sDeployer(Deployer):
|
|||||||
k8s_namespace: str = "default"
|
k8s_namespace: str = "default"
|
||||||
kind_cluster_name: str
|
kind_cluster_name: str
|
||||||
cluster_info : ClusterInfo
|
cluster_info : ClusterInfo
|
||||||
|
deployment_dir: Path
|
||||||
|
|
||||||
def __init__(self, compose_files, compose_project_name, compose_env_file) -> None:
|
def __init__(self, deployment_dir, compose_files, compose_project_name, compose_env_file) -> None:
|
||||||
if (opts.o.debug):
|
if (opts.o.debug):
|
||||||
|
print(f"Deployment dir: {deployment_dir}")
|
||||||
print(f"Compose files: {compose_files}")
|
print(f"Compose files: {compose_files}")
|
||||||
print(f"Project name: {compose_project_name}")
|
print(f"Project name: {compose_project_name}")
|
||||||
print(f"Env file: {compose_env_file}")
|
print(f"Env file: {compose_env_file}")
|
||||||
|
self.deployment_dir = deployment_dir
|
||||||
self.kind_cluster_name = compose_project_name
|
self.kind_cluster_name = compose_project_name
|
||||||
self.cluster_info = ClusterInfo()
|
self.cluster_info = ClusterInfo()
|
||||||
self.cluster_info.int_from_pod_files(compose_files)
|
self.cluster_info.int(compose_files, compose_env_file)
|
||||||
|
|
||||||
def connect_api(self):
|
def connect_api(self):
|
||||||
config.load_kube_config(context=f"kind-{self.kind_cluster_name}")
|
config.load_kube_config(context=f"kind-{self.kind_cluster_name}")
|
||||||
@@ -47,16 +50,26 @@ class K8sDeployer(Deployer):
|
|||||||
|
|
||||||
def up(self, detach, services):
|
def up(self, detach, services):
|
||||||
# Create the kind cluster
|
# Create the kind cluster
|
||||||
# HACK: pass in the config file path here
|
create_cluster(self.kind_cluster_name, self.deployment_dir.joinpath("kind-config.yml"))
|
||||||
create_cluster(self.kind_cluster_name, "./test-deployment-dir/kind-config.yml")
|
|
||||||
self.connect_api()
|
self.connect_api()
|
||||||
# Ensure the referenced containers are copied into kind
|
# Ensure the referenced containers are copied into kind
|
||||||
load_images_into_kind(self.kind_cluster_name, self.cluster_info.image_set)
|
load_images_into_kind(self.kind_cluster_name, self.cluster_info.image_set)
|
||||||
|
|
||||||
|
# Create the host-path-mounted PVs for this deployment
|
||||||
|
pvs = self.cluster_info.get_pvs()
|
||||||
|
for pv in pvs:
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"Sending this pv: {pv}")
|
||||||
|
pv_resp = self.core_api.create_persistent_volume(body=pv)
|
||||||
|
if opts.o.debug:
|
||||||
|
print("PVs created:")
|
||||||
|
print(f"{pv_resp}")
|
||||||
|
|
||||||
# Figure out the PVCs for this deployment
|
# Figure out the PVCs for this deployment
|
||||||
pvcs = self.cluster_info.get_pvcs()
|
pvcs = self.cluster_info.get_pvcs()
|
||||||
for pvc in pvcs:
|
for pvc in pvcs:
|
||||||
if opts.o.debug:
|
if opts.o.debug:
|
||||||
print(f"Sending this: {pvc}")
|
print(f"Sending this pvc: {pvc}")
|
||||||
pvc_resp = self.core_api.create_namespaced_persistent_volume_claim(body=pvc, namespace=self.k8s_namespace)
|
pvc_resp = self.core_api.create_namespaced_persistent_volume_claim(body=pvc, namespace=self.k8s_namespace)
|
||||||
if opts.o.debug:
|
if opts.o.debug:
|
||||||
print("PVCs created:")
|
print("PVCs created:")
|
||||||
@@ -65,7 +78,7 @@ class K8sDeployer(Deployer):
|
|||||||
deployment = self.cluster_info.get_deployment()
|
deployment = self.cluster_info.get_deployment()
|
||||||
# Create the k8s objects
|
# Create the k8s objects
|
||||||
if opts.o.debug:
|
if opts.o.debug:
|
||||||
print(f"Sending this: {deployment}")
|
print(f"Sending this deployment: {deployment}")
|
||||||
deployment_resp = self.apps_api.create_namespaced_deployment(
|
deployment_resp = self.apps_api.create_namespaced_deployment(
|
||||||
body=deployment, namespace=self.k8s_namespace
|
body=deployment, namespace=self.k8s_namespace
|
||||||
)
|
)
|
||||||
@@ -122,6 +135,8 @@ class K8sDeployerConfigGenerator(DeployerConfigGenerator):
|
|||||||
# Check the file isn't already there
|
# Check the file isn't already there
|
||||||
# Get the config file contents
|
# Get the config file contents
|
||||||
content = generate_kind_config(deployment_dir)
|
content = generate_kind_config(deployment_dir)
|
||||||
|
if opts.o.debug:
|
||||||
|
print(f"kind config is: {content}")
|
||||||
config_file = deployment_dir.joinpath(self.config_file_name)
|
config_file = deployment_dir.joinpath(self.config_file_name)
|
||||||
# Write the file
|
# Write the file
|
||||||
with open(config_file, "w") as output_file:
|
with open(config_file, "w") as output_file:
|
||||||
|
|||||||
@@ -14,9 +14,11 @@
|
|||||||
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
# along with this program. If not, see <http:#www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from kubernetes import client
|
from kubernetes import client
|
||||||
|
from dotenv import dotenv_values
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import subprocess
|
import subprocess
|
||||||
from typing import Any, Set
|
from typing import Any, Set, Mapping, List
|
||||||
|
|
||||||
from stack_orchestrator.opts import opts
|
from stack_orchestrator.opts import opts
|
||||||
from stack_orchestrator.util import get_yaml
|
from stack_orchestrator.util import get_yaml
|
||||||
@@ -73,6 +75,10 @@ def named_volumes_from_pod_files(parsed_pod_files):
|
|||||||
return named_volumes
|
return named_volumes
|
||||||
|
|
||||||
|
|
||||||
|
def get_node_pv_mount_path(volume_name: str):
|
||||||
|
return f"/mnt/{volume_name}"
|
||||||
|
|
||||||
|
|
||||||
def volume_mounts_for_service(parsed_pod_files, service):
|
def volume_mounts_for_service(parsed_pod_files, service):
|
||||||
result = []
|
result = []
|
||||||
# Find the service
|
# Find the service
|
||||||
@@ -119,6 +125,14 @@ def _get_host_paths_for_volumes(parsed_pod_files):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _make_absolute_host_path(data_mount_path: Path, deployment_dir: Path) -> Path:
|
||||||
|
if os.path.isabs(data_mount_path):
|
||||||
|
return data_mount_path
|
||||||
|
else:
|
||||||
|
# Python Path voodo that looks pretty odd:
|
||||||
|
return Path.cwd().joinpath(deployment_dir.joinpath("compose").joinpath(data_mount_path)).resolve()
|
||||||
|
|
||||||
|
|
||||||
def parsed_pod_files_map_from_file_names(pod_files):
|
def parsed_pod_files_map_from_file_names(pod_files):
|
||||||
parsed_pod_yaml_map : Any = {}
|
parsed_pod_yaml_map : Any = {}
|
||||||
for pod_file in pod_files:
|
for pod_file in pod_files:
|
||||||
@@ -130,9 +144,12 @@ def parsed_pod_files_map_from_file_names(pod_files):
|
|||||||
return parsed_pod_yaml_map
|
return parsed_pod_yaml_map
|
||||||
|
|
||||||
|
|
||||||
def _generate_kind_mounts(parsed_pod_files):
|
def _generate_kind_mounts(parsed_pod_files, deployment_dir):
|
||||||
volume_definitions = []
|
volume_definitions = []
|
||||||
volume_host_path_map = _get_host_paths_for_volumes(parsed_pod_files)
|
volume_host_path_map = _get_host_paths_for_volumes(parsed_pod_files)
|
||||||
|
# Note these paths are relative to the location of the pod files (at present)
|
||||||
|
# So we need to fix up to make them correct and absolute because kind assumes
|
||||||
|
# relative to the cwd.
|
||||||
for pod in parsed_pod_files:
|
for pod in parsed_pod_files:
|
||||||
parsed_pod_file = parsed_pod_files[pod]
|
parsed_pod_file = parsed_pod_files[pod]
|
||||||
if "services" in parsed_pod_file:
|
if "services" in parsed_pod_file:
|
||||||
@@ -145,7 +162,8 @@ def _generate_kind_mounts(parsed_pod_files):
|
|||||||
# Looks like: test-data:/data
|
# Looks like: test-data:/data
|
||||||
(volume_name, mount_path) = mount_string.split(":")
|
(volume_name, mount_path) = mount_string.split(":")
|
||||||
volume_definitions.append(
|
volume_definitions.append(
|
||||||
f" - hostPath: {volume_host_path_map[volume_name]}\n containerPath: /var/local-path-provisioner"
|
f" - hostPath: {_make_absolute_host_path(volume_host_path_map[volume_name], deployment_dir)}\n"
|
||||||
|
f" containerPath: {get_node_pv_mount_path(volume_name)}"
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
"" if len(volume_definitions) == 0 else (
|
"" if len(volume_definitions) == 0 else (
|
||||||
@@ -177,6 +195,13 @@ def _generate_kind_port_mappings(parsed_pod_files):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def envs_from_environment_variables_map(map: Mapping[str, str]) -> List[client.V1EnvVar]:
|
||||||
|
result = []
|
||||||
|
for env_var, env_val in map.items():
|
||||||
|
result.append(client.V1EnvVar(env_var, env_val))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
# This needs to know:
|
# This needs to know:
|
||||||
# The service ports for the cluster
|
# The service ports for the cluster
|
||||||
# The bind mounted volumes for the cluster
|
# The bind mounted volumes for the cluster
|
||||||
@@ -201,7 +226,7 @@ def generate_kind_config(deployment_dir: Path):
|
|||||||
pod_files = [p for p in compose_file_dir.iterdir() if p.is_file()]
|
pod_files = [p for p in compose_file_dir.iterdir() if p.is_file()]
|
||||||
parsed_pod_files_map = parsed_pod_files_map_from_file_names(pod_files)
|
parsed_pod_files_map = parsed_pod_files_map_from_file_names(pod_files)
|
||||||
port_mappings_yml = _generate_kind_port_mappings(parsed_pod_files_map)
|
port_mappings_yml = _generate_kind_port_mappings(parsed_pod_files_map)
|
||||||
mounts_yml = _generate_kind_mounts(parsed_pod_files_map)
|
mounts_yml = _generate_kind_mounts(parsed_pod_files_map, deployment_dir)
|
||||||
return (
|
return (
|
||||||
"kind: Cluster\n"
|
"kind: Cluster\n"
|
||||||
"apiVersion: kind.x-k8s.io/v1alpha4\n"
|
"apiVersion: kind.x-k8s.io/v1alpha4\n"
|
||||||
@@ -210,3 +235,7 @@ def generate_kind_config(deployment_dir: Path):
|
|||||||
f"{port_mappings_yml}\n"
|
f"{port_mappings_yml}\n"
|
||||||
f"{mounts_yml}\n"
|
f"{mounts_yml}\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def env_var_map_from_file(file: Path) -> Mapping[str, str]:
|
||||||
|
return dotenv_values(file)
|
||||||
|
|||||||
@@ -20,10 +20,11 @@ from stack_orchestrator.util import get_yaml
|
|||||||
|
|
||||||
class Stack:
|
class Stack:
|
||||||
|
|
||||||
|
name: str
|
||||||
obj: typing.Any
|
obj: typing.Any
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self, name: str) -> None:
|
||||||
pass
|
self.name = name
|
||||||
|
|
||||||
def init_from_file(self, file_path: Path):
|
def init_from_file(self, file_path: Path):
|
||||||
with file_path:
|
with file_path:
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ from stack_orchestrator.command_types import CommandOptions
|
|||||||
from stack_orchestrator.repos import setup_repositories
|
from stack_orchestrator.repos import setup_repositories
|
||||||
from stack_orchestrator.build import build_containers
|
from stack_orchestrator.build import build_containers
|
||||||
from stack_orchestrator.build import build_npms
|
from stack_orchestrator.build import build_npms
|
||||||
|
from stack_orchestrator.build import build_webapp
|
||||||
from stack_orchestrator.deploy import deploy
|
from stack_orchestrator.deploy import deploy
|
||||||
from stack_orchestrator import version
|
from stack_orchestrator import version
|
||||||
from stack_orchestrator.deploy import deployment
|
from stack_orchestrator.deploy import deployment
|
||||||
@@ -48,6 +49,7 @@ def cli(ctx, stack, quiet, verbose, dry_run, local_stack, debug, continue_on_err
|
|||||||
cli.add_command(setup_repositories.command, "setup-repositories")
|
cli.add_command(setup_repositories.command, "setup-repositories")
|
||||||
cli.add_command(build_containers.command, "build-containers")
|
cli.add_command(build_containers.command, "build-containers")
|
||||||
cli.add_command(build_npms.command, "build-npms")
|
cli.add_command(build_npms.command, "build-npms")
|
||||||
|
cli.add_command(build_webapp.command, "build-webapp")
|
||||||
cli.add_command(deploy.command, "deploy") # deploy is an alias for deploy-system
|
cli.add_command(deploy.command, "deploy") # deploy is an alias for deploy-system
|
||||||
cli.add_command(deploy.command, "deploy-system")
|
cli.add_command(deploy.command, "deploy-system")
|
||||||
cli.add_command(deployment.command, "deployment")
|
cli.add_command(deployment.command, "deployment")
|
||||||
|
|||||||
Executable
+76
@@ -0,0 +1,76 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
# Note: eventually this test should be folded into ../deploy/
|
||||||
|
# but keeping it separate for now for convenience
|
||||||
|
TEST_TARGET_SO=$( ls -t1 ./package/laconic-so* | head -1 )
|
||||||
|
# Dump environment variables for debugging
|
||||||
|
echo "Environment variables:"
|
||||||
|
env
|
||||||
|
# Set a non-default repo dir
|
||||||
|
export CERC_REPO_BASE_DIR=~/stack-orchestrator-test/repo-base-dir
|
||||||
|
echo "Testing this package: $TEST_TARGET_SO"
|
||||||
|
echo "Test version command"
|
||||||
|
reported_version_string=$( $TEST_TARGET_SO version )
|
||||||
|
echo "Version reported is: ${reported_version_string}"
|
||||||
|
echo "Cloning repositories into: $CERC_REPO_BASE_DIR"
|
||||||
|
rm -rf $CERC_REPO_BASE_DIR
|
||||||
|
mkdir -p $CERC_REPO_BASE_DIR
|
||||||
|
# Test basic stack-orchestrator deploy
|
||||||
|
test_deployment_dir=$CERC_REPO_BASE_DIR/test-deployment-dir
|
||||||
|
test_deployment_spec=$CERC_REPO_BASE_DIR/test-deployment-spec.yml
|
||||||
|
$TEST_TARGET_SO --stack test deploy --deploy-to k8s init --output $test_deployment_spec --config CERC_TEST_PARAM_1=PASSED
|
||||||
|
# Check the file now exists
|
||||||
|
if [ ! -f "$test_deployment_spec" ]; then
|
||||||
|
echo "deploy init test: spec file not present"
|
||||||
|
echo "deploy init test: FAILED"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "deploy init test: passed"
|
||||||
|
$TEST_TARGET_SO --stack test deploy create --spec-file $test_deployment_spec --deployment-dir $test_deployment_dir
|
||||||
|
# Check the deployment dir exists
|
||||||
|
if [ ! -d "$test_deployment_dir" ]; then
|
||||||
|
echo "deploy create test: deployment directory not present"
|
||||||
|
echo "deploy create test: FAILED"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "deploy create test: passed"
|
||||||
|
# Check the file writted by the create command in the stack now exists
|
||||||
|
if [ ! -f "$test_deployment_dir/create-file" ]; then
|
||||||
|
echo "deploy create test: create output file not present"
|
||||||
|
echo "deploy create test: FAILED"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# And has the right content
|
||||||
|
create_file_content=$(<$test_deployment_dir/create-file)
|
||||||
|
if [ ! "$create_file_content" == "create-command-output-data" ]; then
|
||||||
|
echo "deploy create test: create output file contents not correct"
|
||||||
|
echo "deploy create test: FAILED"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "deploy create output file test: passed"
|
||||||
|
# Try to start the deployment
|
||||||
|
$TEST_TARGET_SO deployment --dir $test_deployment_dir start
|
||||||
|
# TODO: add a check to see if the container is up
|
||||||
|
# Sleep because k8s not up yet
|
||||||
|
sleep 30
|
||||||
|
# Check logs command works
|
||||||
|
log_output_3=$( $TEST_TARGET_SO deployment --dir $test_deployment_dir logs )
|
||||||
|
if [[ "$log_output_3" == *"Filesystem is fresh"* ]]; then
|
||||||
|
echo "deployment logs test: passed"
|
||||||
|
else
|
||||||
|
echo "deployment logs test: FAILED"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Check the config variable CERC_TEST_PARAM_1 was passed correctly
|
||||||
|
if [[ "$log_output_3" == *"Test-param-1: PASSED"* ]]; then
|
||||||
|
echo "deployment config test: passed"
|
||||||
|
else
|
||||||
|
echo "deployment config test: FAILED"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Stop and clean up
|
||||||
|
$TEST_TARGET_SO deployment --dir $test_deployment_dir stop --delete-volumes
|
||||||
|
echo "Test passed"
|
||||||
Executable
+62
@@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
if [ -n "$CERC_SCRIPT_DEBUG" ]; then
|
||||||
|
set -x
|
||||||
|
fi
|
||||||
|
# Dump environment variables for debugging
|
||||||
|
echo "Environment variables:"
|
||||||
|
env
|
||||||
|
# Test basic stack-orchestrator webapp
|
||||||
|
echo "Running stack-orchestrator webapp test"
|
||||||
|
# Bit of a hack, test the most recent package
|
||||||
|
TEST_TARGET_SO=$( ls -t1 ./package/laconic-so* | head -1 )
|
||||||
|
# Set a non-default repo dir
|
||||||
|
export CERC_REPO_BASE_DIR=~/stack-orchestrator-test/repo-base-dir
|
||||||
|
echo "Testing this package: $TEST_TARGET_SO"
|
||||||
|
echo "Test version command"
|
||||||
|
reported_version_string=$( $TEST_TARGET_SO version )
|
||||||
|
echo "Version reported is: ${reported_version_string}"
|
||||||
|
echo "Cloning repositories into: $CERC_REPO_BASE_DIR"
|
||||||
|
rm -rf $CERC_REPO_BASE_DIR
|
||||||
|
mkdir -p $CERC_REPO_BASE_DIR
|
||||||
|
git clone https://git.vdb.to/cerc-io/test-progressive-web-app.git $CERC_REPO_BASE_DIR/test-progressive-web-app
|
||||||
|
|
||||||
|
# Test webapp command execution
|
||||||
|
$TEST_TARGET_SO build-webapp --source-repo $CERC_REPO_BASE_DIR/test-progressive-web-app
|
||||||
|
|
||||||
|
CHECK="SPECIAL_01234567890_TEST_STRING"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
|
||||||
|
CONTAINER_ID=$(docker run -p 3000:3000 -d cerc/test-progressive-web-app:local)
|
||||||
|
sleep 3
|
||||||
|
wget -O test.before -m http://localhost:3000
|
||||||
|
|
||||||
|
docker remove -f $CONTAINER_ID
|
||||||
|
|
||||||
|
CONTAINER_ID=$(docker run -p 3000:3000 -e CERC_WEBAPP_DEBUG=$CHECK -d cerc/test-progressive-web-app:local)
|
||||||
|
sleep 3
|
||||||
|
wget -O test.after -m http://localhost:3000
|
||||||
|
|
||||||
|
docker remove -f $CONTAINER_ID
|
||||||
|
|
||||||
|
echo "###########################################################################"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
grep "$CHECK" test.before > /dev/null
|
||||||
|
if [ $? -ne 1 ]; then
|
||||||
|
echo "BEFORE: FAILED"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "BEFORE: PASSED"
|
||||||
|
fi
|
||||||
|
|
||||||
|
grep "$CHECK" test.after > /dev/null
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "AFTER: FAILED"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "AFTER: PASSED"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
Reference in New Issue
Block a user