Archived
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17e860d6e4 | ||
|
|
523b5779be | ||
|
|
62f7ce649d |
@@ -11,8 +11,14 @@ CERC_CONTAINER_BUILD_DOCKERFILE=${CERC_CONTAINER_BUILD_DOCKERFILE:-$SCRIPT_DIR/D
|
||||
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
|
||||
rc=$?
|
||||
|
||||
if [ $? -eq 0 ] && [ "$CERC_CONTAINER_BUILD_TAG" != "cerc/nextjs-base:local" ]; then
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "BUILD FAILED" 1>&2
|
||||
exit $rc
|
||||
fi
|
||||
|
||||
if [ "$CERC_CONTAINER_BUILD_TAG" != "cerc/nextjs-base:local" ]; then
|
||||
cat <<EOF
|
||||
|
||||
#################################################################
|
||||
|
||||
@@ -11,8 +11,14 @@ CERC_CONTAINER_BUILD_DOCKERFILE=${CERC_CONTAINER_BUILD_DOCKERFILE:-$SCRIPT_DIR/D
|
||||
CERC_CONTAINER_BUILD_TAG=${CERC_CONTAINER_BUILD_TAG:-cerc/webapp-base:local}
|
||||
|
||||
docker build -t $CERC_CONTAINER_BUILD_TAG ${build_command_args} -f $CERC_CONTAINER_BUILD_DOCKERFILE $CERC_CONTAINER_BUILD_WORK_DIR
|
||||
rc=$?
|
||||
|
||||
if [ $? -eq 0 ] && [ "$CERC_CONTAINER_BUILD_TAG" != "cerc/webapp-base:local" ]; then
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "BUILD FAILED" 1>&2
|
||||
exit $rc
|
||||
fi
|
||||
|
||||
if [ "$CERC_CONTAINER_BUILD_TAG" != "cerc/webapp-base:local" ]; then
|
||||
cat <<EOF
|
||||
|
||||
#################################################################
|
||||
|
||||
@@ -16,26 +16,55 @@ 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
|
||||
Create a spec file for the deployment:
|
||||
|
||||
```bash
|
||||
laconic-so --stack merkl-sushiswap-v3 deploy --cluster merkl_sushiswap_v3 --env-file <PATH_TO_ENV_FILE> up
|
||||
laconic-so --stack merkl-sushiswap-v3 deploy init --output merkl-sushiswap-v3-spec.yml
|
||||
```
|
||||
|
||||
### Ports
|
||||
|
||||
Edit `network` in the spec file to map container ports to host ports as required:
|
||||
|
||||
```
|
||||
...
|
||||
network:
|
||||
ports:
|
||||
merkl-sushiswap-v3-watcher-db:
|
||||
- '5432'
|
||||
merkl-sushiswap-v3-watcher-job-runner:
|
||||
- 9002:9000
|
||||
merkl-sushiswap-v3-watcher-server:
|
||||
- 127.0.0.1:3007:3008
|
||||
- 9003:9001
|
||||
```
|
||||
|
||||
### Create a deployment
|
||||
|
||||
Create a deployment from the spec file:
|
||||
|
||||
```bash
|
||||
laconic-so --stack merkl-sushiswap-v3 deploy create --spec-file merkl-sushiswap-v3-spec.yml --deployment-dir merkl-sushiswap-v3-deployment
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
Inside deployment directory, open the `config.env` file and set following env variables:
|
||||
|
||||
```bash
|
||||
# External Filecoin (ETH RPC) endpoint to point the watcher to
|
||||
CERC_ETH_RPC_ENDPOINT=https://example-lotus-endpoint/rpc/v1
|
||||
```
|
||||
|
||||
### Start the deployment
|
||||
|
||||
```bash
|
||||
laconic-so deployment --dir merkl-sushiswap-v3-deployment start
|
||||
```
|
||||
|
||||
* 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
|
||||
|
||||
@@ -46,6 +75,7 @@ laconic-so --stack merkl-sushiswap-v3 deploy --cluster merkl_sushiswap_v3 --env-
|
||||
* Open the GQL playground at http://localhost:3007/graphql
|
||||
|
||||
```graphql
|
||||
# Example query
|
||||
{
|
||||
_meta {
|
||||
block {
|
||||
@@ -54,7 +84,7 @@ laconic-so --stack merkl-sushiswap-v3 deploy --cluster merkl_sushiswap_v3 --env-
|
||||
}
|
||||
hasIndexingErrors
|
||||
}
|
||||
|
||||
|
||||
factories {
|
||||
id
|
||||
poolCount
|
||||
@@ -64,18 +94,21 @@ laconic-so --stack merkl-sushiswap-v3 deploy --cluster merkl_sushiswap_v3 --env-
|
||||
|
||||
## Clean up
|
||||
|
||||
Stop all the services running in background:
|
||||
Stop all the merkl-sushiswap-v3 services running in background:
|
||||
|
||||
```bash
|
||||
laconic-so --stack merkl-sushiswap-v3 deploy --cluster merkl_sushiswap_v3 down
|
||||
# Only stop the docker containers
|
||||
laconic-so deployment --dir merkl-sushiswap-v3-deployment stop
|
||||
|
||||
# Run 'start' to restart the deployment
|
||||
```
|
||||
|
||||
Clear volumes created by this stack:
|
||||
To stop all the merkl-sushiswap-v3 services and also delete data:
|
||||
|
||||
```bash
|
||||
# List all relevant volumes
|
||||
docker volume ls -q --filter "name=merkl_sushiswap_v3"
|
||||
# Stop the docker containers
|
||||
laconic-so deployment --dir merkl-sushiswap-v3-deployment stop --delete-volumes
|
||||
|
||||
# Remove all the listed volumes
|
||||
docker volume rm $(docker volume ls -q --filter "name=merkl_sushiswap_v3")
|
||||
# Remove deployment directory (deployment will have to be recreated for a re-run)
|
||||
rm -r merkl-sushiswap-v3-deployment
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@ version: "1.0"
|
||||
name: merkl-sushiswap-v3
|
||||
description: "SushiSwap v3 watcher stack"
|
||||
repos:
|
||||
- github.com/cerc-io/merkl-sushiswap-v3-watcher-ts@v0.1.6
|
||||
- github.com/cerc-io/merkl-sushiswap-v3-watcher-ts@v0.1.7
|
||||
containers:
|
||||
- cerc/watcher-merkl-sushiswap-v3
|
||||
pods:
|
||||
|
||||
@@ -55,7 +55,7 @@ ports:
|
||||
Create deployment:
|
||||
|
||||
```bash
|
||||
laconic-so deploy create --spec-file sushiswap-subgraph-spec.yml --deployment-dir sushiswap-subgraph-deployment
|
||||
laconic-so --stack sushiswap-subgraph deploy create --spec-file sushiswap-subgraph-spec.yml --deployment-dir sushiswap-subgraph-deployment
|
||||
```
|
||||
|
||||
## Start the stack
|
||||
|
||||
@@ -16,26 +16,55 @@ 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
|
||||
Create a spec file for the deployment:
|
||||
|
||||
```bash
|
||||
laconic-so --stack sushiswap-v3 deploy --cluster sushiswap_v3 --env-file <PATH_TO_ENV_FILE> up
|
||||
laconic-so --stack sushiswap-v3 deploy init --output sushiswap-v3-spec.yml
|
||||
```
|
||||
|
||||
### Ports
|
||||
|
||||
Edit `network` in the spec file to map container ports to host ports as required:
|
||||
|
||||
```
|
||||
...
|
||||
network:
|
||||
ports:
|
||||
sushiswap-v3-watcher-db:
|
||||
- '5432'
|
||||
sushiswap-v3-watcher-job-runner:
|
||||
- 9000:9000
|
||||
sushiswap-v3-watcher-server:
|
||||
- 127.0.0.1:3008:3008
|
||||
- 9001:9001
|
||||
```
|
||||
|
||||
### Create a deployment
|
||||
|
||||
Create a deployment from the spec file:
|
||||
|
||||
```bash
|
||||
laconic-so --stack sushiswap-v3 deploy create --spec-file sushiswap-v3-spec.yml --deployment-dir sushiswap-v3-deployment
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
Inside deployment directory, open the `config.env` file and set following env variables:
|
||||
|
||||
```bash
|
||||
# External Filecoin (ETH RPC) endpoint to point the watcher to
|
||||
CERC_ETH_RPC_ENDPOINT=https://example-lotus-endpoint/rpc/v1
|
||||
```
|
||||
|
||||
### Start the deployment
|
||||
|
||||
```bash
|
||||
laconic-so deployment --dir sushiswap-v3-deployment start
|
||||
```
|
||||
|
||||
* To list down and monitor the running containers:
|
||||
|
||||
```bash
|
||||
laconic-so --stack sushiswap-v3 deploy --cluster sushiswap_v3 ps
|
||||
|
||||
# With status
|
||||
docker ps -a
|
||||
|
||||
@@ -43,20 +72,43 @@ laconic-so --stack sushiswap-v3 deploy --cluster sushiswap_v3 --env-file <PATH_T
|
||||
docker logs -f <CONTAINER_ID>
|
||||
```
|
||||
|
||||
* Open the GQL playground at http://localhost:3008/graphql
|
||||
|
||||
```graphql
|
||||
# Example query
|
||||
{
|
||||
_meta {
|
||||
block {
|
||||
number
|
||||
timestamp
|
||||
}
|
||||
hasIndexingErrors
|
||||
}
|
||||
|
||||
factories {
|
||||
id
|
||||
poolCount
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Clean up
|
||||
|
||||
Stop all the services running in background:
|
||||
Stop all the sushiswap-v3 services running in background:
|
||||
|
||||
```bash
|
||||
laconic-so --stack sushiswap-v3 deploy --cluster sushiswap_v3 down
|
||||
# Only stop the docker containers
|
||||
laconic-so deployment --dir sushiswap-v3-deployment stop
|
||||
|
||||
# Run 'start' to restart the deployment
|
||||
```
|
||||
|
||||
Clear volumes created by this stack:
|
||||
To stop all the sushiswap-v3 services and also delete data:
|
||||
|
||||
```bash
|
||||
# List all relevant volumes
|
||||
docker volume ls -q --filter "name=sushiswap_v3"
|
||||
# Stop the docker containers
|
||||
laconic-so deployment --dir sushiswap-v3-deployment stop --delete-volumes
|
||||
|
||||
# Remove all the listed volumes
|
||||
docker volume rm $(docker volume ls -q --filter "name=sushiswap_v3")
|
||||
# Remove deployment directory (deployment will have to be recreated for a re-run)
|
||||
rm -r sushiswap-v3-deployment
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@ version: "1.0"
|
||||
name: sushiswap-v3
|
||||
description: "SushiSwap v3 watcher stack"
|
||||
repos:
|
||||
- github.com/cerc-io/sushiswap-v3-watcher-ts@v0.1.6
|
||||
- github.com/cerc-io/sushiswap-v3-watcher-ts@v0.1.7
|
||||
containers:
|
||||
- cerc/watcher-sushiswap-v3
|
||||
pods:
|
||||
|
||||
@@ -101,7 +101,7 @@ class ClusterInfo:
|
||||
)
|
||||
return service
|
||||
|
||||
def get_ingress(self, use_tls=False):
|
||||
def get_ingress(self, use_tls=False, certificate=None, cluster_issuer="letsencrypt-prod"):
|
||||
# No ingress for a deployment that has no http-proxy defined, for now
|
||||
http_proxy_info_list = self.spec.get_http_proxy()
|
||||
ingress = None
|
||||
@@ -114,8 +114,8 @@ class ClusterInfo:
|
||||
host_name = http_proxy_info["host-name"]
|
||||
rules = []
|
||||
tls = [client.V1IngressTLS(
|
||||
hosts=[host_name],
|
||||
secret_name=f"{self.app_name}-tls"
|
||||
hosts=certificate["spec"]["dnsNames"] if certificate else [host_name],
|
||||
secret_name=certificate["spec"]["secretName"] if certificate else f"{self.app_name}-tls"
|
||||
)] if use_tls else None
|
||||
paths = []
|
||||
for route in http_proxy_info["routes"]:
|
||||
@@ -147,13 +147,17 @@ class ClusterInfo:
|
||||
tls=tls,
|
||||
rules=rules
|
||||
)
|
||||
|
||||
ingress_annotations = {
|
||||
"kubernetes.io/ingress.class": "nginx",
|
||||
}
|
||||
if not certificate:
|
||||
ingress_annotations["cert-manager.io/cluster-issuer"] = cluster_issuer
|
||||
|
||||
ingress = client.V1Ingress(
|
||||
metadata=client.V1ObjectMeta(
|
||||
name=f"{self.app_name}-ingress",
|
||||
annotations={
|
||||
"kubernetes.io/ingress.class": "nginx",
|
||||
"cert-manager.io/cluster-issuer": "letsencrypt-prod"
|
||||
}
|
||||
annotations=ingress_annotations
|
||||
),
|
||||
spec=spec
|
||||
)
|
||||
|
||||
@@ -169,6 +169,39 @@ class K8sDeployer(Deployer):
|
||||
print("Service created:")
|
||||
print(f"{service_resp}")
|
||||
|
||||
def _find_certificate_for_host_name(self, host_name):
|
||||
all_certificates = self.custom_obj_api.list_namespaced_custom_object(
|
||||
group="cert-manager.io",
|
||||
version="v1",
|
||||
namespace=self.k8s_namespace,
|
||||
plural="certificates"
|
||||
)
|
||||
|
||||
host_parts = host_name.split(".", 1)
|
||||
host_as_wild = None
|
||||
if len(host_parts) == 2:
|
||||
host_as_wild = f"*.{host_parts[1]}"
|
||||
|
||||
now = datetime.utcnow().replace(tzinfo=timezone.utc)
|
||||
fmt = "%Y-%m-%dT%H:%M:%S%z"
|
||||
|
||||
# Walk over all the configured certificates.
|
||||
for cert in all_certificates["items"]:
|
||||
dns = cert["spec"]["dnsNames"]
|
||||
# Check for an exact hostname match or a wildcard match.
|
||||
if host_name in dns or host_as_wild in dns:
|
||||
status = cert.get("status", {})
|
||||
# Check the certificate date.
|
||||
if "notAfter" in status and "notBefore" in status:
|
||||
before = datetime.strptime(status["notBefore"], fmt)
|
||||
after = datetime.strptime(status["notAfter"], fmt)
|
||||
if before < now < after:
|
||||
# Check the status is Ready
|
||||
for condition in status.get("conditions", []):
|
||||
if "True" == condition.get("status") and "Ready" == condition.get("type"):
|
||||
return cert
|
||||
return None
|
||||
|
||||
def up(self, detach, services):
|
||||
if not opts.o.dry_run:
|
||||
if self.is_kind():
|
||||
@@ -189,8 +222,15 @@ class K8sDeployer(Deployer):
|
||||
self._create_volume_data()
|
||||
self._create_deployment()
|
||||
|
||||
http_proxy_info = self.cluster_info.spec.get_http_proxy()
|
||||
# Note: at present we don't support tls for kind (and enabling tls causes errors)
|
||||
ingress: client.V1Ingress = self.cluster_info.get_ingress(use_tls=not self.is_kind())
|
||||
use_tls = http_proxy_info and not self.is_kind()
|
||||
certificate = self._find_certificate_for_host_name(http_proxy_info[0]["host-name"]) if use_tls else None
|
||||
if opts.o.debug:
|
||||
if certificate:
|
||||
print(f"Using existing certificate: {certificate}")
|
||||
|
||||
ingress: client.V1Ingress = self.cluster_info.get_ingress(use_tls=use_tls, certificate=certificate)
|
||||
if ingress:
|
||||
if opts.o.debug:
|
||||
print(f"Sending this ingress: {ingress}")
|
||||
@@ -350,9 +390,11 @@ class K8sDeployer(Deployer):
|
||||
name=ingress.spec.tls[0].secret_name
|
||||
)
|
||||
|
||||
hostname = ingress.spec.tls[0].hosts[0]
|
||||
hostname = ingress.spec.rules[0].host
|
||||
ip = ingress.status.load_balancer.ingress[0].ip
|
||||
tls = "notBefore: %s, notAfter: %s" % (cert["status"]["notBefore"], cert["status"]["notAfter"])
|
||||
tls = "notBefore: %s; notAfter: %s; names: %s" % (
|
||||
cert["status"]["notBefore"], cert["status"]["notAfter"], ingress.spec.tls[0].hosts
|
||||
)
|
||||
except: # noqa: E722
|
||||
pass
|
||||
|
||||
|
||||
@@ -27,7 +27,9 @@ class ResourceLimits:
|
||||
memory: int = None
|
||||
storage: int = None
|
||||
|
||||
def __init__(self, obj={}):
|
||||
def __init__(self, obj=None):
|
||||
if obj is None:
|
||||
obj = {}
|
||||
if "cpus" in obj:
|
||||
self.cpus = float(obj["cpus"])
|
||||
if "memory" in obj:
|
||||
@@ -50,7 +52,9 @@ class Resources:
|
||||
limits: ResourceLimits = None
|
||||
reservations: ResourceLimits = None
|
||||
|
||||
def __init__(self, obj={}):
|
||||
def __init__(self, obj=None):
|
||||
if obj is None:
|
||||
obj = {}
|
||||
if "reservations" in obj:
|
||||
self.reservations = ResourceLimits(obj["reservations"])
|
||||
if "limits" in obj:
|
||||
@@ -72,7 +76,9 @@ class Spec:
|
||||
obj: typing.Any
|
||||
file_path: Path
|
||||
|
||||
def __init__(self, file_path: Path = None, obj={}) -> None:
|
||||
def __init__(self, file_path: Path = None, obj=None) -> None:
|
||||
if obj is None:
|
||||
obj = {}
|
||||
self.file_path = file_path
|
||||
self.obj = obj
|
||||
|
||||
@@ -91,49 +97,41 @@ class Spec:
|
||||
self.file_path = file_path
|
||||
|
||||
def get_image_registry(self):
|
||||
return (self.obj[constants.image_registry_key]
|
||||
if self.obj and constants.image_registry_key in self.obj
|
||||
else None)
|
||||
return self.obj.get(constants.image_registry_key)
|
||||
|
||||
def get_volumes(self):
|
||||
return (self.obj["volumes"]
|
||||
if self.obj and "volumes" in self.obj
|
||||
else {})
|
||||
return self.obj.get(constants.volumes_key, {})
|
||||
|
||||
def get_configmaps(self):
|
||||
return (self.obj["configmaps"]
|
||||
if self.obj and "configmaps" in self.obj
|
||||
else {})
|
||||
return self.obj.get(constants.configmaps_key, {})
|
||||
|
||||
def get_container_resources(self):
|
||||
return Resources(self.obj.get("resources", {}).get("containers", {}))
|
||||
return Resources(self.obj.get(constants.resources_key, {}).get("containers", {}))
|
||||
|
||||
def get_volume_resources(self):
|
||||
return Resources(self.obj.get("resources", {}).get("volumes", {}))
|
||||
return Resources(self.obj.get(constants.resources_key, {}).get(constants.volumes_key, {}))
|
||||
|
||||
def get_http_proxy(self):
|
||||
return (self.obj[constants.network_key][constants.http_proxy_key]
|
||||
if self.obj and constants.network_key in self.obj
|
||||
and constants.http_proxy_key in self.obj[constants.network_key]
|
||||
else None)
|
||||
return self.obj.get(constants.network_key, {}).get(constants.http_proxy_key, [])
|
||||
|
||||
def get_annotations(self):
|
||||
return self.obj.get("annotations", {})
|
||||
return self.obj.get(constants.annotations_key, {})
|
||||
|
||||
def get_labels(self):
|
||||
return self.obj.get("labels", {})
|
||||
return self.obj.get(constants.labels_key, {})
|
||||
|
||||
def get_privileged(self):
|
||||
return "true" == str(self.obj.get("security", {}).get("privileged", "false")).lower()
|
||||
return "true" == str(self.obj.get(constants.security_key, {}).get("privileged", "false")).lower()
|
||||
|
||||
def get_capabilities(self):
|
||||
return self.obj.get("security", {}).get("capabilities", [])
|
||||
return self.obj.get(constants.security_key, {}).get("capabilities", [])
|
||||
|
||||
def get_deployment_type(self):
|
||||
return self.obj[constants.deploy_to_key]
|
||||
return self.obj.get(constants.deploy_to_key)
|
||||
|
||||
def is_kubernetes_deployment(self):
|
||||
return self.get_deployment_type() in [constants.k8s_kind_deploy_type, constants.k8s_deploy_type]
|
||||
return self.get_deployment_type() in [constants.k8s_kind_deploy_type,
|
||||
constants.k8s_deploy_type]
|
||||
|
||||
def is_kind_deployment(self):
|
||||
return self.get_deployment_type() in [constants.k8s_kind_deploy_type]
|
||||
|
||||
Reference in New Issue
Block a user