diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..fc3ab30a7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,37 @@ +### Go template +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories +vendor/ + +# Go workspace file +go.work +go.work.sum + +### CDK template +# CDK asset staging directory. +# For more information about AWS-CDK, see https://docs.aws.amazon.com/cdk/ +.cdk.staging/ +**/cdk.out/ + +### Misc +.build +.github +.idea + +### Things that doesn't produce code or seed +*.md +scripts/temp_* +scripts/produce_source_maps/all_tables.csv +scripts/composed_streams.csv \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fac7bc617..6b74fe56e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -48,24 +48,49 @@ jobs: go test ./internal/extensions/... - name: Docker Compose Up + # docker compose up --wait makes it exit with 1 even for a successful run + continue-on-error: true uses: isbang/compose-action@v1.5.1 with: compose-file: "./compose.yaml" + # waits every container to be ready, so we're sure there's data already + up-flags: '--wait' + env: + # This is not a secret, it's hardcoded for the CI testing + PRIVATE_KEY: "0000000000000000000000000000000000000000000000000000000000000001" + WHITELIST_WALLETS: "0x304e893AdB2Ad8E8C37F4884Ad1EC3df8bA9bDcf" - - name: setup python - uses: actions/setup-python@v5 - with: - python-version: '3.10' - - name: Install Python dependencies - run: python -m pip install --upgrade pip pandas + # we need it to be manually checked, as above action will always exit with 1 even if it's successful + - name: Check compose status + run: | + output=$(docker ps -a --format "{{.Names}},{{.Image}},{{.Status}}") + + function expect_status() { + image_name=$1 + expected_status=$2 + image_row=$(echo "$output" | grep "$image_name") + if echo "$image_row" | grep -q "$expected_status"; then + echo "$image_name exited with 0" + else + echo -e "$image_name isn't with expected status $expected_status\n" + echo -e "docker ps output: \n$output\n\n" + + # extract the container name, knowing it's the first column + container_name=$(echo "$image_row" | cut -d ',' -f 1) + + echo -e "docker logs for $image_name: \n" + docker logs $container_name | tail -n 500 + + exit 1 + fi + } + + # we ensure both containers are exited with 0 + # if you are running locally, make sure any previous postgres volume state is clean + # otherwise, tsn-db will error for out for block state being out of sync. + expect_status "tsn-db:local" "Up " + expect_status "push-tsn-data:local" "Exited (0)" - # It takes time to download the kwil binary and extract kwil-cli so I push kwil-cli to the repo. - # It needed to seed database. Are there any better way to do this? - # PRIVATE_KEY and WHITELIST_WALLETS are hardcoded for testing reasons - - name: Seed Database and Run Tests + - name: Run Tests run: | - timeout 300 docker logs tsn-db-tsn-db-1 -f | grep -m1 -oP '"Health check state changed","state":"up"' || { ec=$?; [ $ec -eq 141 ] && true || (exit $ec); } - export PRIVATE_KEY="0000000000000000000000000000000000000000000000000000000000000001" - export WHITELIST_WALLETS="0x304e893AdB2Ad8E8C37F4884Ad1EC3df8bA9bDcf" - scripts/setup.sh scripts/ci-tests.sh diff --git a/.gitignore b/.gitignore index 212683dfb..9d790622a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,13 @@ .git -.env +.env* +!.env.example .idea .build/kwild +go.work* +vendor + scripts/temp_csv scripts/composed_streams.csv scripts/temp_composed_schemas diff --git a/README.md b/README.md index 63a720711..45c514988 100644 --- a/README.md +++ b/README.md @@ -48,26 +48,15 @@ For more information on running nodes, and how to run a multi-node network, refe ### Resetting local deployments -By default, `kwild` stores all data in `~/.kwild`. To reset the data on a deployment, remove the data directory while the node is stopped: +You can clear the local Kwil data by running the following command: ```shell -rm -r ~/.kwild +task clear-data ``` -## Docker Compose Deployment - -### Run TSN-DB with Postgres using Docker Compose - -To run the TSN-DB with Postgres using Docker Compose, run the following command: -```shell -task compose -``` - -### Seed Data +### Configure the kwil-cli -#### Configure the kwil-cli - -To seed data into the TSN-DB, you will need to configure the kwil-cli. +To interact with the the TSN-DB, you will need to configure the kwil-cli. ```shell kwil-cli configure @@ -78,10 +67,19 @@ Private Key: # use private key 0000000000000000000000000000000000000000000000000000000000000001 for testing ``` +## Docker Compose Deployment + +### Run TSN-DB with Postgres using Docker Compose + +To run the TSN-DB with Postgres using Docker Compose, run the following command: +```shell +task compose +``` +This will start the TSN-DB and Postgres in Docker containers, which is already seeded. #### Seed Data -To seed data into the TSN-DB, run the following command: +If you need to manually seed data into the TSN-DB, run the following command: ```shell task seed ``` diff --git a/Taskfile.yml b/Taskfile.yml index 1e68605ff..94a0eb1c9 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -54,6 +54,11 @@ tasks: && mv ./kwil-cli .build && rm ./kwil-db.tar.gz + clear-data: + cmds: + - rm -r ~/.kwild || true + - docker volume rm tsn-db_data-kwil-postgres tsn-db_data-push-tsn-data -f + seed: desc: Seed the database cmds: diff --git a/compose.yaml b/compose.yaml index a1f30acc5..7e45af701 100644 --- a/compose.yaml +++ b/compose.yaml @@ -10,8 +10,20 @@ services: interval: 5s timeout: 5s retries: 5 + # persis data + volumes: + - type: volume + source: data-kwil-postgres + target: /var/lib/postgresql/data + volume: + nocopy: true + networks: + - tsn-network tsn-db: + container_name: tsn-db + hostname: tsn-db + image: "tsn-db:local" build: context: . dockerfile: ./deployments/Dockerfile @@ -20,3 +32,44 @@ services: depends_on: kwil-postgres: condition: service_healthy + networks: + - tsn-network + + push-tsn-data: + image: "push-tsn-data:local" + build: + context: . + dockerfile: ./deployments/push-tsn-data.dockerfile + volumes: + - type: volume + source: data-push-tsn-data + # should only run once at deployment + target: /firstrun + volume: + nocopy: false + depends_on: + tsn-db: + condition: service_started + networks: + - tsn-network + environment: + # should come from environment + - PRIVATE_KEY=${PRIVATE_KEY:?PRIVATE_KEY is necessary for deployment} + # this is not required, but if it is set, it should be a comma separated list of wallet addresses (e.g. 0x1234,0x5678) + # if not set, only the owner of the private key will be able to query + - WHITELIST_WALLETS=${WHITELIST_WALLETS} + + finisher: + container_name: wait-for-completion + image: hello-world + depends_on: + push-tsn-data: + condition: service_completed_successfully + +networks: + tsn-network: + driver: bridge + +volumes: + data-kwil-postgres: + data-push-tsn-data: \ No newline at end of file diff --git a/deployments/infra/.gitignore b/deployments/infra/.gitignore new file mode 100644 index 000000000..781b16774 --- /dev/null +++ b/deployments/infra/.gitignore @@ -0,0 +1,21 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +cdk.iml + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# go.sum should be committed +!go.sum + +# CDK asset staging directory +.cdk.staging +cdk.out diff --git a/deployments/infra/README.md b/deployments/infra/README.md new file mode 100644 index 000000000..79e5c4555 --- /dev/null +++ b/deployments/infra/README.md @@ -0,0 +1,12 @@ +# Welcome to your CDK Go project! + +This is a blank project for CDK development with Go. + +The `cdk.json` file tells the CDK toolkit how to execute your app. + +## Useful commands + + * `cdk deploy` deploy this stack to your default AWS account/region + * `cdk diff` compare deployed stack with current state + * `cdk synth` emits the synthesized CloudFormation template + * `go test` run unit tests diff --git a/deployments/infra/buildx.sh b/deployments/infra/buildx.sh new file mode 100755 index 000000000..45c03b916 --- /dev/null +++ b/deployments/infra/buildx.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# covert docker build to docker buildx build --load +if [[ "$1" == "build" ]]; then + docker buildx build --load "${@:2}" +else + docker "$@" +fi \ No newline at end of file diff --git a/deployments/infra/cdk.context.json b/deployments/infra/cdk.context.json new file mode 100644 index 000000000..5689c5bae --- /dev/null +++ b/deployments/infra/cdk.context.json @@ -0,0 +1,42 @@ +{ + "availability-zones:account=344375646931:region=us-east-1": [ + "us-east-1a", + "us-east-1b", + "us-east-1c", + "us-east-1d", + "us-east-1e", + "us-east-1f" + ], + "vpc-provider:account=344375646931:filter.isDefault=true:region=us-east-2:returnAsymmetricSubnets=true": { + "vpcId": "vpc-031fd5cc4065f5693", + "vpcCidrBlock": "172.31.0.0/16", + "ownerAccountId": "344375646931", + "availabilityZones": [], + "subnetGroups": [ + { + "name": "Public", + "type": "Public", + "subnets": [ + { + "subnetId": "subnet-02a0a112084190fa9", + "cidr": "172.31.0.0/20", + "availabilityZone": "us-east-2a", + "routeTableId": "rtb-06027a22f2823df2a" + }, + { + "subnetId": "subnet-00182b35be3ac1e96", + "cidr": "172.31.16.0/20", + "availabilityZone": "us-east-2b", + "routeTableId": "rtb-06027a22f2823df2a" + }, + { + "subnetId": "subnet-030496ef398fbf3ce", + "cidr": "172.31.32.0/20", + "availabilityZone": "us-east-2c", + "routeTableId": "rtb-06027a22f2823df2a" + } + ] + } + ] + } +} diff --git a/deployments/infra/cdk.json b/deployments/infra/cdk.json new file mode 100644 index 000000000..3ec380110 --- /dev/null +++ b/deployments/infra/cdk.json @@ -0,0 +1,67 @@ +{ + "app": "go mod download && go run cdk_main.go", + "watch": { + "include": [ + "**" + ], + "exclude": [ + "README.md", + "cdk*.json", + "go.mod", + "go.sum", + "**/*test.go" + ] + }, + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ], + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, + "@aws-cdk/aws-iam:standardizedServicePrincipals": true, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, + "@aws-cdk/aws-route53-patters:useCertificate": true, + "@aws-cdk/customresources:installLatestAwsSdkDefault": false, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, + "@aws-cdk/aws-redshift:columnId": true, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, + "@aws-cdk/aws-kms:aliasNameRef": true, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": true, + "@aws-cdk/aws-efs:denyAnonymousAccess": true, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true, + + "stackName": "TSN-DB-Stack", + "imageRepoName": "tsn-db-repo", + "deploymentStage": "STAGING", + "keyPairName": "tsn-key-pair" + } +} diff --git a/deployments/infra/cdk_main.go b/deployments/infra/cdk_main.go index 06aa59ef7..26818499d 100644 --- a/deployments/infra/cdk_main.go +++ b/deployments/infra/cdk_main.go @@ -2,10 +2,10 @@ package main import ( "github.com/aws/aws-cdk-go/awscdk/v2" - "github.com/aws/aws-cdk-go/awscdk/v2/awsecr" "github.com/aws/aws-cdk-go/awscdk/v2/awsecrassets" + "github.com/aws/aws-cdk-go/awscdk/v2/awss3assets" "github.com/aws/jsii-runtime-go" - "infra/config" + "github.com/truflation/tsn-db/infra/config" "os" "github.com/aws/aws-cdk-go/awscdk/v2/awsec2" @@ -43,33 +43,9 @@ func TsnDBCdkStack(scope constructs.Construct, id string, props *CdkStackProps) // }, //}) - buildArgs := make(map[string]*string) - - // git commit should come from the environment variable, else it will execute git rev-parse HEAD - if len(os.Getenv("GIT_COMMIT")) == 0 { - buildArgs["git_commit"] = jsii.String("$(git rev-parse HEAD)") - } else { - buildArgs["git_commit"] = jsii.String(os.Getenv("GIT_COMMIT")) - } - - // git version will be added only if it's available - if len(os.Getenv("GIT_VERSION")) > 0 { - buildArgs["version"] = jsii.String(os.Getenv("GIT_VERSION")) - } - - // build time will be added only if it's available - if len(os.Getenv("BUILD_TIME")) > 0 { - buildArgs["build_time"] = jsii.String(os.Getenv("BUILD_TIME")) - } - - // whitelist_wallets will be added only if it's available - if len(os.Getenv("WHITELIST_WALLETS")) > 0 { - buildArgs["whitelist_wallets"] = jsii.String(os.Getenv("WHITELIST_WALLETS")) - } - - imageAsset := awsecrassets.NewDockerImageAsset(stack, jsii.String("DockerImageAsset"), &awsecrassets.DockerImageAssetProps{ + tsnImageAsset := awsecrassets.NewDockerImageAsset(stack, jsii.String("DockerImageAsset"), &awsecrassets.DockerImageAssetProps{ AssetName: nil, - BuildArgs: &buildArgs, + BuildArgs: nil, CacheFrom: &[]*awsecrassets.DockerCacheOption{ { Type: jsii.String("local"), @@ -85,27 +61,58 @@ func TsnDBCdkStack(scope constructs.Construct, id string, props *CdkStackProps) }, }, BuildSecrets: nil, - File: jsii.String("truflation/docker/tsn.dockerfile"), + File: jsii.String("deployments/Dockerfile"), NetworkMode: nil, Platform: nil, Target: nil, Directory: jsii.String("../../"), }) - repo := imageAsset.Repository() + + pushDataImageAsset := awsecrassets.NewDockerImageAsset(stack, jsii.String("PushDataImageAsset"), &awsecrassets.DockerImageAssetProps{ + AssetName: nil, + BuildArgs: nil, + CacheFrom: &[]*awsecrassets.DockerCacheOption{ + { + Type: jsii.String("local"), + Params: &map[string]*string{ + "src": jsii.String("/tmp/.buildx-cache-push-data-tsn"), + }, + }, + }, + CacheTo: &awsecrassets.DockerCacheOption{ + Type: jsii.String("local"), + Params: &map[string]*string{ + "dest": jsii.String("/tmp/.buildx-cache-push-data-tsn-new"), + }, + }, + File: jsii.String("deployments/push-tsn-data.dockerfile"), + Directory: jsii.String("../../"), + }) + + // Adding our docker compose file to the instance + dockerComposeAsset := awss3assets.NewAsset(stack, jsii.String("DockerComposeAsset"), &awss3assets.AssetProps{ + Path: jsii.String("../../compose.yaml"), + }) + + initElements := []awsec2.InitElement{ + awsec2.InitFile_FromExistingAsset(jsii.String("/home/ec2-user/docker-compose.yaml"), dockerComposeAsset, nil), + } // default vpc vpcInstance := awsec2.Vpc_FromLookup(stack, jsii.String("VPC"), &awsec2.VpcLookupOptions{ IsDefault: jsii.Bool(true), }) - // Create instance using imageAsset hash so that the instance is recreated when the image changes. - newName := "TsnDBInstance" + *imageAsset.AssetHash() - instance, instanceRole := createInstance(stack, newName, vpcInstance) + // Create instance using tsnImageAsset hash so that the instance is recreated when the image changes. + newName := "TsnDBInstance" + *tsnImageAsset.AssetHash() + instance, instanceRole := createInstance(stack, newName, vpcInstance, &initElements) - deployImageOnInstance(stack, instance, imageAsset, repo) + deployImageOnInstance(stack, instance, tsnImageAsset, pushDataImageAsset) // make ecr repository available to the instance - repo.GrantPull(instanceRole) + tsnImageAsset.Repository().GrantPull(instanceRole) + pushDataImageAsset.Repository().GrantPull(instanceRole) + dockerComposeAsset.GrantRead(instanceRole) // Output info. awscdk.NewCfnOutput(stack, jsii.String("public-address"), &awscdk.CfnOutputProps{ @@ -115,7 +122,7 @@ func TsnDBCdkStack(scope constructs.Construct, id string, props *CdkStackProps) return stack } -func createInstance(stack awscdk.Stack, name string, vpc awsec2.IVpc) (awsec2.Instance, awsiam.IRole) { +func createInstance(stack awscdk.Stack, name string, vpc awsec2.IVpc, initElements *[]awsec2.InitElement) (awsec2.Instance, awsiam.IRole) { // Create security group. instanceSG := awsec2.NewSecurityGroup(stack, jsii.String("NodeSG"), &awsec2.SecurityGroupProps{ Vpc: vpc, @@ -164,11 +171,16 @@ func createInstance(stack awscdk.Stack, name string, vpc awsec2.IVpc) (awsec2.In AssumedBy: awsiam.NewServicePrincipal(jsii.String("ec2.amazonaws.com"), nil), }) + initData := awsec2.CloudFormationInit_FromElements( + *initElements..., + ) + + // comes with pre-installed cloud init requirements + AWSLinux2MachineImage := awsec2.MachineImage_LatestAmazonLinux2(nil) instance := awsec2.NewInstance(stack, jsii.String(name), &awsec2.InstanceProps{ InstanceType: awsec2.InstanceType_Of(awsec2.InstanceClass_T3, awsec2.InstanceSize_SMALL), - // ubuntu 22.04 - // https://cloud-images.ubuntu.com/locator/ec2/ - MachineImage: awsec2.MachineImage_FromSsmParameter(jsii.String("/aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id"), nil), + Init: initData, + MachineImage: AWSLinux2MachineImage, Vpc: vpc, VpcSubnets: &awsec2.SubnetSelection{ SubnetType: subnetType, @@ -195,35 +207,54 @@ func createInstance(stack awscdk.Stack, name string, vpc awsec2.IVpc) (awsec2.In return instance, instanceRole } -func deployImageOnInstance(stack awscdk.Stack, instance awsec2.Instance, imageAsset awsecrassets.DockerImageAsset, repo awsecr.IRepository) { +func deployImageOnInstance(stack awscdk.Stack, instance awsec2.Instance, tsnImageAsset awsecrassets.DockerImageAsset, pushDataImageAsset awsecrassets.DockerImageAsset) { + + // we could improve this script by adding a ResourceSignal, which would signalize to CDK that the instance is ready + // and fail the deployment otherwise + // create a script from the asset script1Content := `#!/bin/bash set -e set -x -# lets add repo, region and image uri to /tmp/init-vars just for easier debug -echo "repo=` + *repo.RepositoryUri() + `" > /tmp/init-vars -echo "region=` + *stack.Region() + `" >> /tmp/init-vars -echo "imageUri=` + *imageAsset.ImageUri() + `" >> /tmp/init-vars +# Update the system +yum update -y -# install docker -apt-get update -apt-get install -y docker.io +# Install Docker +amazon-linux-extras install docker -# add the ubuntu user to the docker group -usermod -aG docker ubuntu -# flush changes +# Start Docker and enable it to start at boot +systemctl start docker +systemctl enable docker + +mkdir -p /usr/local/lib/docker/cli-plugins/ +curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose +chmod a+x /usr/local/lib/docker/cli-plugins/docker-compose + +# Add the ec2-user to the docker group (ec2-user is the default user in Amazon Linux 2) +usermod -aG docker ec2-user + +# reload the group newgrp docker -# install aws cli -apt-get install -y awscli +# Install the AWS CLI +yum install -y aws-cli -# login to ecr -aws ecr get-login-password --region ` + *stack.Region() + ` | docker login --username AWS --password-stdin ` + *repo.RepositoryUri() + ` -# pull the image -docker pull ` + *imageAsset.ImageUri() + ` +# Login to ECR +aws ecr get-login-password --region ` + *stack.Region() + ` | docker login --username AWS --password-stdin ` + *tsnImageAsset.Repository().RepositoryUri() + ` +# Pull the image +docker pull ` + *tsnImageAsset.ImageUri() + ` +# Tag the image as tsn-db:local, as the docker-compose file expects that +docker tag ` + *tsnImageAsset.ImageUri() + ` tsn-db:local -# create a systemd service file +# Login to ECR again for the second repository +aws ecr get-login-password --region ` + *stack.Region() + ` | docker login --username AWS --password-stdin ` + *pushDataImageAsset.Repository().RepositoryUri() + ` +# Pull the image +docker pull ` + *pushDataImageAsset.ImageUri() + ` +# Tag the image as push-tsn-data:local, as the docker-compose file expects that +docker tag ` + *pushDataImageAsset.ImageUri() + ` push-tsn-data:local + +# Create a systemd service file cat < /etc/systemd/system/tsn-db-app.service [Unit] Description=My Docker Application @@ -231,24 +262,47 @@ Requires=docker.service After=docker.service [Service] -Restart=always -ExecStart=/usr/bin/docker run --network host --name tsn-db-app ` + *imageAsset.ImageUri() + ` -ExecStop=/usr/bin/docker stop tsn-db-app -ExecStopPost=/usr/bin/docker rm tsn-db-app +Type=oneshot +RemainAfterExit=yes +# This path comes from the init asset +ExecStart=/bin/bash -c "docker compose -f /home/ec2-user/docker-compose.yaml up -d" +ExecStop=/bin/bash -c "docker compose -f /home/ec2-user/docker-compose.yaml down" +` + getEnvStringsForService(getEnvVars("WHITELIST_WALLETS", "PRIVATE_KEY")) + ` [Install] WantedBy=multi-user.target EOF -# reload systemd to recognize the new service, enable it to start on boot, and start the service +# Reload systemd to recognize the new service, enable it to start on boot, and start the service systemctl daemon-reload systemctl enable tsn-db-app.service -systemctl start tsn-db-app.service -` +systemctl start tsn-db-app.service` instance.AddUserData(&script1Content) } +// Warning: Used environment variables are not encrypted in the CloudFormation template, +// nor to who have access to the instance if it used on a service configuration file. +// Switch for encryption if necessary. +func getEnvStringsForService(envDict map[string]string) string { + envStrings := "" + for k, v := range envDict { + envStrings += "Environment=\"" + k + "=" + v + "\"\n" + } + return envStrings +} + +// getEnvVars returns a map of environment variables from the given list of +// environment variable names. If an environment variable is not set, it will +// be an empty string in the map. +func getEnvVars(envNames ...string) map[string]string { + envDict := make(map[string]string) + for _, envName := range envNames { + envDict[envName] = os.Getenv(envName) + } + return envDict +} + func main() { app := awscdk.NewApp(nil) diff --git a/deployments/infra/config/config.go b/deployments/infra/config/config.go new file mode 100644 index 000000000..49ce9bc65 --- /dev/null +++ b/deployments/infra/config/config.go @@ -0,0 +1,63 @@ +package config + +import ( + "github.com/aws/constructs-go/constructs/v10" + "github.com/aws/jsii-runtime-go" +) + +// DO NOT modify this function, change stack name by 'cdk.json/context/stackName'. +func StackName(scope constructs.Construct) string { + stackName := "MyEKSClusterStack" + + ctxValue := scope.Node().TryGetContext(jsii.String("stackName")) + if v, ok := ctxValue.(string); ok { + stackName = v + } + + return stackName +} + +// DO NOT modify this function, change EC2 key pair name by 'cdk.json/context/keyPairName'. +func KeyPairName(scope constructs.Construct) string { + keyPairName := "MyKeyPair" + + ctxValue := scope.Node().TryGetContext(jsii.String("keyPairName")) + if v, ok := ctxValue.(string); ok { + keyPairName = v + } + + return keyPairName +} + +// DO NOT modify this function, change ECR repository name by 'cdk.json/context/imageRepoName'. +func EcrRepoName(scope constructs.Construct) string { + ecrRepoName := "MyRepository" + + ctxValue := scope.Node().TryGetContext(jsii.String("imageRepoName")) + if v, ok := ctxValue.(string); ok { + ecrRepoName = v + } + + return ecrRepoName +} + +// Deployment stage config +type DeploymentStageType string + +const ( + DeploymentStage_DEV DeploymentStageType = "DEV" + DeploymentStage_STAGING DeploymentStageType = "STAGING" + DeploymentStage_PROD DeploymentStageType = "PROD" +) + +// DO NOT modify this function, change EKS cluster name by 'cdk-cli-wrapper-dev.sh/--context deploymentStage='. +func DeploymentStage(scope constructs.Construct) DeploymentStageType { + deploymentStage := DeploymentStage_PROD + + ctxValue := scope.Node().TryGetContext(jsii.String("deploymentStage")) + if v, ok := ctxValue.(string); ok { + deploymentStage = DeploymentStageType(v) + } + + return deploymentStage +} diff --git a/deployments/infra/go.mod b/deployments/infra/go.mod new file mode 100644 index 000000000..2982884ac --- /dev/null +++ b/deployments/infra/go.mod @@ -0,0 +1,26 @@ +module github.com/truflation/tsn-db/infra + +go 1.22.1 + +require ( + github.com/aws/aws-cdk-go/awscdk/v2 v2.131.0 + github.com/aws/constructs-go/constructs/v10 v10.3.0 + github.com/aws/jsii-runtime-go v1.94.0 +) + +require ( + github.com/Masterminds/semver/v3 v3.2.1 // indirect + github.com/cdklabs/awscdk-asset-awscli-go/awscliv1/v2 v2.2.202 // indirect + github.com/cdklabs/awscdk-asset-kubectl-go/kubectlv20/v2 v2.1.2 // indirect + github.com/cdklabs/awscdk-asset-node-proxy-agent-go/nodeproxyagentv6/v2 v2.0.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/yuin/goldmark v1.4.13 // indirect + golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/tools v0.16.1 // indirect +) diff --git a/deployments/infra/go.sum b/deployments/infra/go.sum new file mode 100644 index 000000000..676a78eac --- /dev/null +++ b/deployments/infra/go.sum @@ -0,0 +1,54 @@ +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/aws/aws-cdk-go/awscdk/v2 v2.131.0 h1:U/sGMzodvu5mVQpFBWI/BGkdZ3el/sb7J3pF3HBjQLQ= +github.com/aws/aws-cdk-go/awscdk/v2 v2.131.0/go.mod h1:TpmJwOnoajvRtwnLlJoxEoppb9sVoCLfPGLdgoTDH7o= +github.com/aws/constructs-go/constructs/v10 v10.3.0 h1:LsjBIMiaDX/vqrXWhzTquBJ9pPdi02/H+z1DCwg0PEM= +github.com/aws/constructs-go/constructs/v10 v10.3.0/go.mod h1:GgzwIwoRJ2UYsr3SU+JhAl+gq5j39bEMYf8ev3J+s9s= +github.com/aws/jsii-runtime-go v1.94.0 h1:VuVDx0xL2gbsJthUMfP+SwAXGkSEQd0GKm0ydZ8xga8= +github.com/aws/jsii-runtime-go v1.94.0/go.mod h1:tQOz8aAMzM2XsRUDsnUgPvGcHNAzR/xtH0OgeM0lTWo= +github.com/cdklabs/awscdk-asset-awscli-go/awscliv1/v2 v2.2.202 h1:VixXB9DnHN8oP7pXipq8GVFPjWCOdeNxIaS/ZyUwTkI= +github.com/cdklabs/awscdk-asset-awscli-go/awscliv1/v2 v2.2.202/go.mod h1:iPUti/SWjA3XAS3CpnLciFjS8TN9Y+8mdZgDfSgcyus= +github.com/cdklabs/awscdk-asset-kubectl-go/kubectlv20/v2 v2.1.2 h1:k+WD+6cERd59Mao84v0QtRrcdZuuSMfzlEmuIypKnVs= +github.com/cdklabs/awscdk-asset-kubectl-go/kubectlv20/v2 v2.1.2/go.mod h1:CvFHBo0qcg8LUkJqIxQtP1rD/sNGv9bX3L2vHT2FUAo= +github.com/cdklabs/awscdk-asset-node-proxy-agent-go/nodeproxyagentv6/v2 v2.0.1 h1:MBBQNKKPJ5GArbctgwpiCy7KmwGjHDjUUH5wEzwIq8w= +github.com/cdklabs/awscdk-asset-node-proxy-agent-go/nodeproxyagentv6/v2 v2.0.1/go.mod h1:/2WiXEft9s8ViJjD01CJqDuyJ8HXBjhBLtK5OvJfdSc= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/deployments/push-tsn-data.dockerfile b/deployments/push-tsn-data.dockerfile new file mode 100644 index 000000000..26a721215 --- /dev/null +++ b/deployments/push-tsn-data.dockerfile @@ -0,0 +1,46 @@ +FROM golang:1.22.1-alpine3.19 AS build + +RUN mkdir /firstrun + +WORKDIR /app + +# install dependencies +RUN apk add --no-cache bash uuidgen python3~3.11 py3-pip~23 py3-pandas~2 + +# download kwil-cli +RUN wget -O kwil-db.tar.gz https://github.com/kwilteam/kwil-db/releases/download/v0.7.0/kwil-db_0.7.0_linux_amd64.tar.gz\ + && tar -xzvf kwil-db.tar.gz 'kwil-cli'\ + && mkdir -p ./.build\ + && mv ./kwil-cli .build\ + && rm ./kwil-db.tar.gz + + +COPY go.mod . +COPY go.sum . + +COPY ./go.mod ./go.sum ./ +COPY ./scripts/ ./scripts/ + +COPY ./internal/schemas/ ./internal/schemas/ + +RUN go mod download +RUN go mod verify + +ENV GRPC_URL="http://tsn-db:8080" + +RUN echo -e "#!/bin/sh\n\ +\n\ +set -e\n\ +CONTAINER_ALREADY_STARTED=\"/firstrun/CONTAINER_ALREADY_STARTED_PLACEHOLDER\"\n\ +if [ ! -e \$CONTAINER_ALREADY_STARTED ]; then\n\ + echo \"-- First container startup. Let's add data --\"\n\ + /app/scripts/setup.sh\n\ + touch \$CONTAINER_ALREADY_STARTED\n\ +else\n\ + echo \"-- Not first container startup. Let's just make sure it's working --\"\n\ + ./scripts/wait-kwild.sh\n\ +fi" > ./start-in-docker.sh + +RUN chmod +x ./start-in-docker.sh + +CMD ["./start-in-docker.sh"] \ No newline at end of file diff --git a/go.mod b/go.mod index 61edbd41f..6f0943e62 100644 --- a/go.mod +++ b/go.mod @@ -74,6 +74,7 @@ require ( github.com/lib/pq v1.10.7 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -118,7 +119,7 @@ require ( golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.15.0 // indirect + golang.org/x/tools v0.16.1 // indirect google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect diff --git a/go.sum b/go.sum index 28f754118..8c0edea86 100644 --- a/go.sum +++ b/go.sum @@ -286,8 +286,7 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -526,8 +525,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= -golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/scripts/ci-tests.sh b/scripts/ci-tests.sh index bc3d8c7f0..aa379323a 100755 --- a/scripts/ci-tests.sh +++ b/scripts/ci-tests.sh @@ -51,11 +51,16 @@ not_allowed_private_key="26aff20bde5606467627557793ebbb6162e9faf9f2d0830fd98a6f2 owner_private_key="0000000000000000000000000000000000000000000000000000000000000001" owner_address="7e5f4552091a69125d5dfcb7b8c2659029395bdf" +# note: inside gh action, localhost is not available +grpc_url=${GRPC_URL:-"http://127.0.0.1:8080"} + +common_config="--kwil-provider $grpc_url --owner=$owner_address" + echo -e "❓ Making sure we're able to call the database from own private key\n" -expect_success "$(../.build/kwil-cli database call -a=get_index date:"2023-12-25" date_to:"2023-12-31" -n=cpi --private-key="$owner_private_key" --owner="$owner_address" 2>&1)" +expect_success "$(../.build/kwil-cli database call -a=get_index date:"2023-12-25" date_to:"2023-12-31" -n=cpi --private-key="$owner_private_key" $common_config 2>&1)" echo -e "❓ Making sure we're able to call the database from an allowed private key\n" -expect_success "$(../.build/kwil-cli database call -a=get_index date:"2023-12-25" date_to:"2023-12-31" -n=cpi --owner="$owner_address" --private-key="$allowed_private_key" 2>&1)" +expect_success "$(../.build/kwil-cli database call -a=get_index date:"2023-12-25" date_to:"2023-12-31" -n=cpi --private-key="$allowed_private_key" $common_config 2>&1)" echo -e "❓ Making sure we're not able to call the database from a different private key\n" -expect_error "$(../.build/kwil-cli database call -a=get_index date:"2023-12-25" date_to:"2023-12-31" -n=cpi --owner="$owner_address" --private-key="$not_allowed_private_key" 2>&1)" +expect_error "$(../.build/kwil-cli database call -a=get_index date:"2023-12-25" date_to:"2023-12-31" -n=cpi --private-key="$not_allowed_private_key" $common_config 2>&1)" diff --git a/scripts/setup.sh b/scripts/setup.sh index 6695b3669..6e7711832 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -33,22 +33,24 @@ if [ "$isLocal" = true ]; then fi fi +# comes from env variable, but defaults to localhost:8080 +grpc_url=${GRPC_URL:-"http://localhost:8080"} + +./wait_kwild.sh # if $PRIVATE_KEY is setup and config does not exist, we create with if [ -n "$PRIVATE_KEY" ] && [ ! -f ~/.kwil_cli/config.json ]; then mkdir -p ~/.kwil_cli - echo "{\"private_key\":\"$PRIVATE_KEY\",\"grpc_url\":\"http://localhost:8080\",\"chain_id\":\"\"}" > ~/.kwil_cli/config.json + echo "{\"private_key\":\"$PRIVATE_KEY\",\"grpc_url\":\"$grpc_url\",\"chain_id\":\"\"}" > ~/.kwil_cli/config.json fi -# to make sure kwild is ready -for i in {1..10}; do -# check kwil-cli is exist - if ../.build/kwil-cli utils ping &> /dev/null; then - break - fi - echo "Waiting for kwild to be ready" - sleep 5 -done +# ensure there's a config file +if [ ! -f ~/.kwil_cli/config.json ]; then + echo "No config file found. Please set PRIVATE_KEY or create a config file at ~/.kwil_cli/config.json" + exit 1 +fi + + # smoke test about kwil-cli test_content=$(./../.build/kwil-cli database list --self) diff --git a/scripts/wait_kwild.sh b/scripts/wait_kwild.sh new file mode 100755 index 000000000..fe15f4afc --- /dev/null +++ b/scripts/wait_kwild.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -e + +grpc_url=${GRPC_URL:-"http://localhost:8080"} + +# to make sure kwild is ready +for i in {1..10}; do +# check kwil-cli is exist + if ../.build/kwil-cli utils ping --kwil-provider=$grpc_url &> /dev/null; then + break + fi + echo "Waiting for kwild to be ready" + sleep 5 +done \ No newline at end of file