Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/typedb.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: LocalStack TypeDB Extension Tests

on:
pull_request:
workflow_dispatch:

env:
LOCALSTACK_DISABLE_EVENTS: "1"
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}

jobs:
integration-tests:
name: Run Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup LocalStack and extension
run: |
cd typedb

docker pull localstack/localstack-pro &
docker pull typedb/typedb &
pip install localstack

make install
make dist
localstack extensions -v install file://$(ls ./dist/localstack_extension_typedb-*.tar.gz)

DEBUG=1 localstack start -d
localstack wait

- name: Run integration tests
run: |
cd typedb
make test

- name: Print logs
if: always()
run: |
localstack logs
localstack stop
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ $ localstack extensions install "git+https://github.com/localstack/localstack-ex
## Official LocalStack Extensions

Here is the current list of extensions developed by the LocalStack team and their support status.
You can install the respective extension by calling `localstack install <Install name>`.
You can install the respective extension by calling `localstack extensions install <Install name>`.

| Extension | Install name | Version | Support status |
|----------------------------------------------------------------------------------------------------| ------------ |---------| -------------- |
Expand All @@ -75,6 +75,7 @@ You can install the respective extension by calling `localstack install <Install
| [Miniflare](https://github.com/localstack/localstack-extensions/tree/main/miniflare) | localstack-extension-miniflare | 0.1.0 | Experimental |
| [Stripe](https://github.com/localstack/localstack-extensions/tree/main/stripe) | localstack-extension-stripe | 0.2.0 | Stable |
| [Terraform Init](https://github.com/localstack/localstack-extensions/tree/main/terraform-init) | localstack-extension-terraform-init | 0.2.0 | Experimental |
| [TypeDB](https://github.com/localstack/localstack-extensions/tree/main/typedb) | localstack-extension-typedb | 0.1.0 | Experimental |


## Developing Extensions
Expand Down Expand Up @@ -168,7 +169,7 @@ class ReadyAnnouncerExtension(Extension):
name = "my_ready_announcer"

def on_platform_ready(self):
LOG.info("my plugin is loaded and localstack is ready to roll!")
LOG.info("my plugin is loaded and localstack is ready to roll!")
```

### Package your Extension
Expand Down Expand Up @@ -227,9 +228,9 @@ Commands:
new Create a new LocalStack extension from the official extension...
```

#### Creating a new extensions
#### Creating a new extension

First, create a new extensions from a template:
First, create a new extension from a template:

```console
% localstack extensions dev new
Expand Down
5 changes: 5 additions & 0 deletions typedb/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.venv
dist
build
**/*.egg-info
.eggs
44 changes: 44 additions & 0 deletions typedb/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
VENV_BIN = python3 -m venv
VENV_DIR ?= .venv
VENV_ACTIVATE = $(VENV_DIR)/bin/activate
VENV_RUN = . $(VENV_ACTIVATE)

usage: ## Shows usage for this Makefile
@cat Makefile | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'

venv: $(VENV_ACTIVATE)

$(VENV_ACTIVATE): pyproject.toml
test -d .venv || $(VENV_BIN) .venv
$(VENV_RUN); pip install --upgrade pip setuptools plux
$(VENV_RUN); pip install -e .[dev]
touch $(VENV_DIR)/bin/activate

clean:
rm -rf .venv/
rm -rf build/
rm -rf .eggs/
rm -rf *.egg-info/

install: venv ## Install dependencies
$(VENV_RUN); python -m plux entrypoints

dist: venv ## Create distribution
$(VENV_RUN); python -m build

publish: clean-dist venv dist ## Publish extension to pypi
$(VENV_RUN); pip install --upgrade twine; twine upload dist/*

entrypoints: venv ## Generate plugin entrypoints for Python package
$(VENV_RUN); python -m plux entrypoints

format: ## Run ruff to format the codebase
$(VENV_RUN); python -m ruff format .; python -m ruff check --output-format=full --fix .

test: ## Run integration tests (requires LocalStack running with the Extension installed)
$(VENV_RUN); pytest tests $(PYTEST_ARGS)

clean-dist: clean
rm -rf dist/

.PHONY: clean clean-dist dist install publish usage venv format test
38 changes: 38 additions & 0 deletions typedb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
TypeDB on LocalStack
=====================

This repo contains a [LocalStack Extension](https://github.com/localstack/localstack-extensions) that facilitates developing [TypeDB](https://typedb.com)-based applications locally.

After installing the extension, a TypeDB server instance will become available under `typedb.localhost.localstack.cloud:4566`, allowing you to create and manage TypeDB databases directly from your AWS applications running in LocalStack.

For example, you could create a microservice backed by a Lambda function that connects to a TypeDB database upon invocation. See [here](https://github.com/typedb-osi/typedb-localstack-demo) for a simple example application that makes use of this extension.

## Configuration

The following environment variables can be passed to the LocalStack container (make sure to prefix them with `LOCALSTACK_...` when using the `localstack start` CLI), to steer the behavior of the extension:

* `TYPEDB_FLAGS`: Additional user-defined command args to pass to the TypeDB container.
* `TYPEDB_HTTP2_PROXY`: Flag to enable/disable HTTP2 proxy for gRPC traffic (use this if you experience network issues, and use the HTTP variant of the TypeDB driver).

## Prerequisites

* Docker
* LocalStack Pro (free trial available)
* `localstack` CLI
* `make`

## Install from GitHub repository

This extension can be installed directly from this Github repo via:

```bash
localstack extensions install "git+https://github.com/localstack/localstack-extensions.git#egg=typedb&subdirectory=typedb"
```

## Install local development version

Please refer to the docs [here](https://github.com/localstack/localstack-extensions?tab=readme-ov-file#start-localstack-with-the-extension) for instructions on how to start the extension in developer mode.

## License

The code in this repo is available under the Apache 2.0 license.
1 change: 1 addition & 0 deletions typedb/localstack_typedb/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name = "localstack_typedb"
58 changes: 58 additions & 0 deletions typedb/localstack_typedb/extension.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import os
import shlex

from localstack.config import is_env_not_false
from localstack.utils.docker_utils import DOCKER_CLIENT
from localstack_typedb.utils.docker import ProxiedDockerContainerExtension
from rolo import Request
from werkzeug.datastructures import Headers

# environment variable for user-defined command args to pass to TypeDB
ENV_CMD_FLAGS = "TYPEDB_FLAGS"
# environment variable for flag to enable/disable HTTP2 proxy for gRPC traffic
ENV_HTTP2_PROXY = "TYPEDB_HTTP2_PROXY"


class TypeDbExtension(ProxiedDockerContainerExtension):
name = "typedb"

# pattern of the hostname under which the extension is accessible
HOST = "typedb.<domain>"
# name of the Docker image to spin up
DOCKER_IMAGE = "typedb/typedb"
# default command args to pass to TypeDB
DEFAULT_CMD_FLAGS = ["--diagnostics.reporting.metrics=false"]
# default port for TypeDB HTTP2/gRPC endpoint
TYPEDB_PORT = 1729

def __init__(self):
command_flags = (os.environ.get(ENV_CMD_FLAGS) or "").strip()
command_flags = self.DEFAULT_CMD_FLAGS + shlex.split(command_flags)
command = self._get_image_command() + command_flags
http2_ports = [self.TYPEDB_PORT] if is_env_not_false(ENV_HTTP2_PROXY) else []
super().__init__(
image_name=self.DOCKER_IMAGE,
container_ports=[8000, 1729],
host=self.HOST,
request_to_port_router=self.request_to_port_router,
command=command,
http2_ports=http2_ports,
)

def _get_image_command(self) -> list[str]:
result = DOCKER_CLIENT.inspect_image(self.DOCKER_IMAGE)
image_command = result["Config"]["Cmd"]
return image_command

def should_proxy_request(self, headers: Headers) -> bool:
# determine if this is a gRPC request targeting TypeDB
content_type = headers.get("content-type") or ""
req_path = headers.get(":path") or ""
is_typedb_grpc_request = (
"grpc" in content_type and "/typedb.protocol.TypeDB" in req_path
)
return is_typedb_grpc_request

def request_to_port_router(self, request: Request) -> int:
# TODO add REST API / gRPC routing based on request
return 1729
Empty file.
Loading