diff --git a/.github/workflows-helpers/run-e2e-test-job-template.yaml b/.github/workflows-helpers/run-e2e-test-job-template.yaml index 1efdfe5fb..b1c54f237 100644 --- a/.github/workflows-helpers/run-e2e-test-job-template.yaml +++ b/.github/workflows-helpers/run-e2e-test-job-template.yaml @@ -51,6 +51,8 @@ spec: value: /root/.poktroll - name: APPGATE_SERVER_URL value: http://${NAMESPACE}-appgate-server:80 + - name: PATH_URL + value: http://${NAMESPACE}-path:80 - name: GATEWAY_URL value: http://${NAMESPACE}-gateway:80 volumeMounts: diff --git a/Tiltfile b/Tiltfile index 58f0e3301..53e700c92 100644 --- a/Tiltfile +++ b/Tiltfile @@ -61,6 +61,9 @@ localnet_config_defaults = { # By default, we use the `helm_repo` function below to point to the remote repository # but can update it to the locally cloned repo for testing & development "helm_chart_local_repo": {"enabled": False, "path": "../helm-charts"}, + # By default, we use a pre-built PATH image, but can update it to use a local + # repo instead. + "path_local_repo": {"enabled": False, "path": "../path"}, } localnet_config_file = read_yaml(localnet_config_path, default=localnet_config_defaults) # Initial empty config @@ -76,7 +79,8 @@ if (localnet_config_file != localnet_config) or (not os.path.exists(localnet_con print("Updating " + localnet_config_path + " with defaults") local("cat - > " + localnet_config_path, stdin=encode_yaml(localnet_config)) -# Configure helm chart reference. If using a local repo, set the path to the local repo; otherwise, use our own helm repo. +# Configure helm chart reference. +# If using a local repo, set the path to the local repo; otherwise, use our own helm repo. helm_repo("pokt-network", "https://pokt-network.github.io/helm-charts/") chart_prefix = "pokt-network/" if localnet_config["helm_chart_local_repo"]["enabled"]: @@ -85,6 +89,14 @@ if localnet_config["helm_chart_local_repo"]["enabled"]: print("Using local helm chart repo " + helm_chart_local_repo) chart_prefix = helm_chart_local_repo + "/charts/" +# Configure PATH reference. +# If using a local repo, set the path to the local repo; otherwise, use our own helm repo. +# path_repo("pokt-network", "https://pokt-network.github.io/helm-charts/") +path_local_repo = "" +if localnet_config["path_local_repo"]["enabled"]: + path_local_repo = localnet_config["path_local_repo"]["path"] + hot_reload_dirs.append(path_local_repo) + print("Using local PATH repo " + path_local_repo) # Observability print("Observability enabled: " + str(localnet_config["observability"]["enabled"])) @@ -345,22 +357,43 @@ for x in range(localnet_config["gateways"]["count"]): ) # Provision PATH Gateway -path_deployment_yaml = str(read_file("./localnet/kubernetes/path.yaml", "r")) +# Build the Docker image with Tilt (local build) +docker_build("path-gateway-local", path_local_repo) + +# TODO_IN_THIS_PR(@okdas): Move configs to values and add helm charts for PATH +path_deployment_yaml = str(read_file("./localnet/kubernetes/path-local.yaml", "r")) actor_number = 0 +# Loop to configure and apply multiple PATH gateway deployments for x in range(localnet_config["path_gateways"]["count"]): - actor_number = actor_number + 1 + actor_number += 1 + + # Create the ConfigMap for each gateway instance configmap_create( "path-config" + str(actor_number), from_file="localnet/kubernetes/path-config-" + str(actor_number) + ".yaml" ) + + # Format the YAML deployment with the actor number and port formatted_path_deployment_yaml = path_deployment_yaml.format(actor_number=actor_number, port=2999 + actor_number) + + # Apply the deployment to Kubernetes using Tilt k8s_yaml(blob(formatted_path_deployment_yaml)) k8s_resource( "path-gateway" + str(actor_number), labels=["gateways"], resource_deps=["validator"], + # TODO_IMPROVE(, @HebertCL): Update this once PATH has grafana dashboards + # links=[ + # link( + # "http://localhost:3003/d/path/protocol-path?orgId=1&refresh=5s&var-path=gateway" + # + str(actor_number), + # "Grafana dashboard", + # ), + # ], + # TODO_IMPROVE(@HebertCL): Add port forwards to grafana, pprof, like the other resources port_forwards=[str(2999 + actor_number) + ":3000"], ) + # Provision Validators k8s_resource( "validator", diff --git a/config.yml b/config.yml index d555511c5..162d70132 100644 --- a/config.yml +++ b/config.yml @@ -170,9 +170,10 @@ genesis: amount: "100000000" # 100 POKT denom: upokt applicationList: - - address: pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4 - delegatee_gateway_addresses: - [pokt15vzxjqklzjtlz7lahe8z2dfe9nm5vxwwmscne4] + - address: pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4 # app1 + delegatee_gateway_addresses: [ + pokt15vzxjqklzjtlz7lahe8z2dfe9nm5vxwwmscne4, # gateway1 + ] service_configs: - service_id: "anvil" - service_id: rest @@ -182,7 +183,7 @@ genesis: # `supplier1_stake_config.yaml` so that the stake command causes a state change. amount: "100000068" # ~100 POKT denom: upokt - - address: pokt1ad28jdap2zfanjd7hpkh984yveney6k9a42man + - address: pokt1ad28jdap2zfanjd7hpkh984yveney6k9a42man # apptiny delegatee_gateway_addresses: [] service_configs: - service_id: "anvil" diff --git a/e2e/tests/init_test.go b/e2e/tests/init_test.go index 1bed0c510..10739814a 100644 --- a/e2e/tests/init_test.go +++ b/e2e/tests/init_test.go @@ -61,7 +61,8 @@ var ( flagFeaturesPath string keyRingFlag = "--keyring-backend=test" chainIdFlag = "--chain-id=poktroll" - appGateServerUrl = "localhost:3000" // Keeping localhost by default because that is how we run the tests on our machines locally + appGateServerUrl = "http://localhost:42069" // Keeping localhost by default because that is how we run the tests on our machines locally + pathUrl = "localhost:3000" // Keeping localhost by default because that is how we run the tests on our machines locally ) func init() { @@ -75,6 +76,11 @@ func init() { if url := os.Getenv("APPGATE_SERVER_URL"); url != "" { appGateServerUrl = url } + + // If "APPGATE_SERVER_URL" envar is present, use it for pathUrl + if url := os.Getenv("PATH_URL"); url != "" { + pathUrl = url + } } func TestMain(m *testing.M) { @@ -463,7 +469,9 @@ func (s *suite) TheApplicationSendsTheSupplierASuccessfulRequestForServiceWithPa method = "GET" } - res, err := s.pocketd.RunCurlWithRetry(appGateServerUrl, serviceId, method, path, requestData, 5) + // TODO_IN_THIS_PR: Figure out a plan for deprecating appGateServerUrl in a followup (cleaner) PR + // res, err := s.pocketd.RunCurlWithRetry(appGateServerUrl, serviceId, method, path, requestData, 5) + res, err := s.pocketd.RunCurlWithRetry(pathUrl, serviceId, method, path, requestData, 5) require.NoError(s, err, "error sending relay request from app %q to supplier %q for service %q", appName, supplierOperatorName, serviceId) var jsonContent json.RawMessage diff --git a/e2e/tests/node.go b/e2e/tests/node.go index f314eb5d3..e82704a7d 100644 --- a/e2e/tests/node.go +++ b/e2e/tests/node.go @@ -27,11 +27,15 @@ var ( // defaultDebugOutput provides verbose output on manipulations with binaries (cli command, stdout, stderr) defaultDebugOutput = os.Getenv("E2E_DEBUG_OUTPUT") // serviceIdToAliasMap maps service IDs to their respective aliases + // This is useful for gateway operators that map static on-chain names + // to semantic, easier to understand, off-chain names. serviceIdToAliasMap = map[string]string{ "anvil": "anvil", } ) +const () + func isVerbose() bool { return defaultDebugOutput == "true" } @@ -177,7 +181,7 @@ func (p *pocketdBin) runPocketCmd(args ...string) (*commandResult, error) { // runCurlPostCmd is a helper to run a command using the local pocketd binary with the flags provided func (p *pocketdBin) runCurlCmd(rpcUrl, service, method, path, data string, args ...string) (*commandResult, error) { serviceAlias := serviceIdToAliasMap[service] - urlStr := fmt.Sprintf("http://%s.%s/v1%s", serviceAlias, rpcUrl, path) + urlStr := formatURLString(serviceAlias, rpcUrl, path) base := []string{ "-v", // verbose output "-sS", // silent with error @@ -189,8 +193,7 @@ func (p *pocketdBin) runCurlCmd(rpcUrl, service, method, path, data string, args if method == "POST" { base = append(base, "--data", data) } else if len(data) > 0 { - fmt.Println(fmt.Sprintf("WARN: data provided but not being included in the %s request", method)) - + fmt.Printf("WARN: data provided but not being included in the %s request", method) } args = append(base, args...) commandStr := "curl " + strings.Join(args, " ") // Create a string representation of the command @@ -219,3 +222,19 @@ func (p *pocketdBin) runCurlCmd(rpcUrl, service, method, path, data string, args return r, err } + +// formatURLString returns RESTful or JSON-RPC API endpoint URL depending +// on the parameters provided. +func formatURLString(serviceAlias, rpcUrl, path string) string { + // For JSON-RPC APIs, the path should be empty + if len(path) == 0 { + return fmt.Sprintf("http://%s.%s/v1", serviceAlias, rpcUrl) + } + + // For RESTful APIs, the path should not be empty. + // We remove the leading / to make the format string below easier to read. + if path[0] == '/' { + path = path[1:] + } + return fmt.Sprintf("http://%s.%s/v1/%s", serviceAlias, rpcUrl, path) +} diff --git a/localnet/kubernetes/path-config-1.yaml b/localnet/kubernetes/path-config-1.yaml index 46276ec35..f139306b0 100644 --- a/localnet/kubernetes/path-config-1.yaml +++ b/localnet/kubernetes/path-config-1.yaml @@ -5,11 +5,11 @@ shannon_config: host_port: validator-poktroll-validator:9090 insecure: true # TODO: Allow sovereign soverign apps to sign their own relay requests. - gateway_address: pokt15vzxjqklzjtlz7lahe8z2dfe9nm5vxwwmscne4 + gateway_address: pokt15vzxjqklzjtlz7lahe8z2dfe9nm5vxwwmscne4 # gateway1 gateway_private_key: cf09805c952fa999e9a63a9f434147b0a5abfd10f268879694c6b5a70e1ae177 - # TODO: Populate delegated_app_addresses from on-chain records. + # TODO: Populate delegated_app_addres ses from on-chain records. delegated_app_addresses: - - pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4 + - pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4 # app1 services: # Path needs 0021 service ID to handle EVM relays. diff --git a/localnet/kubernetes/path-config-2.yaml b/localnet/kubernetes/path-config-2.yaml index 1c9a856db..3e6cecde0 100644 --- a/localnet/kubernetes/path-config-2.yaml +++ b/localnet/kubernetes/path-config-2.yaml @@ -4,10 +4,10 @@ shannon_config: grpc_config: host_port: validator-poktroll-validator:9090 insecure: true - gateway_address: pokt15w3fhfyc0lttv7r585e2ncpf6t2kl9uh8rsnyz + gateway_address: pokt15w3fhfyc0lttv7r585e2ncpf6t2kl9uh8rsnyz # gateway2 gateway_private_key: 177ba43cec962ea407f71da9c3994ba685708e82d5d7a6d7da3268e74119bf88 delegated_app_addresses: - - pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4 + - pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4 # app1 services: "anvil": diff --git a/localnet/kubernetes/path-config-3.yaml b/localnet/kubernetes/path-config-3.yaml index 32f64f2f1..06c6f647a 100644 --- a/localnet/kubernetes/path-config-3.yaml +++ b/localnet/kubernetes/path-config-3.yaml @@ -4,10 +4,10 @@ shannon_config: grpc_config: host_port: validator-poktroll-validator:9090 insecure: true - gateway_address: pokt1zhmkkd0rh788mc9prfq0m2h88t9ge0j83gnxya + gateway_address: pokt1zhmkkd0rh788mc9prfq0m2h88t9ge0j83gnxya # gateway3 gateway_private_key: f73b6f7f0b9c99603c7eeddbf1c419c6f6bbc241f3798e3e4c8da9769ca81c26 delegated_app_addresses: - - pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4 + - pokt1mrqt5f7qh8uxs27cjm9t7v9e74a9vvdnq5jva4 # app3 services: "anvil": diff --git a/localnet/kubernetes/path-local.yaml b/localnet/kubernetes/path-local.yaml new file mode 100644 index 000000000..f08158da2 --- /dev/null +++ b/localnet/kubernetes/path-local.yaml @@ -0,0 +1,45 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: path-gateway{actor_number} +spec: + replicas: 1 + selector: + matchLabels: + app: path-gateway{actor_number} + template: + metadata: + labels: + app: path-gateway{actor_number} + spec: + containers: + - name: path-gateway + image: path-gateway-local:latest # Local image tag + imagePullPolicy: Never # Ensure Kubernetes uses local image + ports: + - containerPort: 3000 + volumeMounts: + - name: path-config{actor_number} + mountPath: /app/.config.yaml + subPath: .config.yaml + volumes: + - name: path-config{actor_number} + configMap: + name: path-config{actor_number} + items: + - key: path-config-{actor_number}.yaml + path: .config.yaml +--- +apiVersion: v1 +kind: Service +metadata: + name: path-gateway{actor_number} +spec: + selector: + app: path-gateway{actor_number} + ports: + - protocol: TCP + name: rpc + port: {port} + targetPort: 3000 diff --git a/localnet/kubernetes/path.yaml b/localnet/kubernetes/path.yaml index 2d46ddcc4..928f72351 100644 --- a/localnet/kubernetes/path.yaml +++ b/localnet/kubernetes/path.yaml @@ -13,7 +13,7 @@ spec: labels: app: path-gateway{actor_number} spec: - # TODO: Add resource limits + # TODO_IMPROVE(@okdas): Add resource limits containers: - name: path-gateway image: ghcr.io/buildwithgrove/path:sha-fcf75fe-rc @@ -42,4 +42,4 @@ spec: - protocol: TCP name: rpc port: {port} - targetPort: 3000 \ No newline at end of file + targetPort: 3000 diff --git a/localnet/kubernetes/values-relayminer-1.yaml b/localnet/kubernetes/values-relayminer-1.yaml index 8096c58a0..b17bd5765 100644 --- a/localnet/kubernetes/values-relayminer-1.yaml +++ b/localnet/kubernetes/values-relayminer-1.yaml @@ -5,7 +5,7 @@ config: default_signing_key_names: [supplier1] suppliers: - - service_id: "anvil" + - service_id: anvil listen_url: http://0.0.0.0:8545 service_config: backend_url: http://anvil:8547/