diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Dockerfile b/Dockerfile index 8e815b5..ebcd341 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,8 @@ -FROM metabase/metabase:latest -ADD https://github.com/MaterializeInc/metabase-materialize-driver/releases/download/0.0.1/materialize-driver-0.0.3-SNAPSHOT-standalone.jar /plugins/ -RUN chmod 744 /plugins/materialize-driver-0.0.3-SNAPSHOT-standalone.jar +ARG METABASE_VERSION=latest +FROM metabase/metabase:${METABASE_VERSION} + +ARG METABASE_VERSION +LABEL io.materialize.metabase-version=${METABASE_VERSION} + +ADD target/dist/materialize-driver.jar /plugins/ +RUN chmod 744 /plugins/materialize-driver.jar diff --git a/README.md b/README.md index 4200e18..b40ba2b 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,17 @@ The `metabase-materialize-driver` lets ## To Use the Driver -To use the `metabase-materialize-driver`, copy the driver's `.jar` file into the +We provide a pre-built docker image of metabase including this driver as +[materialize/metabase][] + +To use the `metabase-materialize-driver` with an existing Metabase +installation, copy a `.jar` file from one of our [releases][] into the `/plugins` directory of your Metabase instance. Metabase will register the driver automatically! (For deployment-specific details, please consult the following sections.) Once the Materialize driver is registered, use the following information to -connect: +connect: | Field | Value | | ----------------- |:---------:| @@ -23,6 +27,9 @@ connect: | Database username | default | | Database password | default | +[releases]: https://github.com/MaterializeInc/metabase-materialize-driver/releases +[materialize/metabase]: https://hub.docker.com/repository/docker/materialize/metabase + ### With Docker @@ -31,12 +38,12 @@ Dockerfile](Dockerfile) and run the following command from your terminal: ```shell script cd /path/to/metabase-materialize-driver -docker build -f Dockerfile -t metabase-with-materialize . +bin/build-docker.sh ``` Then, to start the container, run: ```shell script -docker run --rm -p 3000:3000 --name metabase metabase-with-materialize:latest +docker run --rm -p 3000:3000 --name metabase materialize/metabase:latest ``` Once it's finished loading, you can access Metabase at . @@ -55,17 +62,18 @@ Use this driver in two steps: 1. Download a copy of the driver by running: ```shell script - curl -L "https://github.com/MaterializeInc/metabase-materialize-driver/releases/download/0.0.1/materialize-driver-0.0.1-SNAPSHOT-standalone.jar" -o materialize-driver-0.0.1-SNAPSHOT-standalone.jar + bin/build.sh --release v0.0.5 --no-docker ``` -1. Move the downloaded copy of the driver (from the previous step) into the - `/plugins` directory of your Metabase instance. + or visiting the [releases](./releases) page and downloading one of the + jars + +1. Move the downloaded copy of the plugin (from the previous step) into the + `/plugins` directory of your Metabase instance. For more info, check out these resources: -* [Managing databases in - Metabase](https://www.metabase.com/docs/latest/administration-guide/01-managing-databases.html) -* [Driver plugins in - Metabase](https://github.com/metabase/metabase/wiki/Writing-a-Driver:-Packaging-a-Driver-&-Metabase-Plugin-Basics) - +* [Managing databases in Metabase](https://www.metabase.com/docs/latest/administration-guide/01-managing-databases.html) +* [Driver plugins in Metabase](https://github.com/metabase/metabase/wiki/Writing-a-Driver:-Packaging-a-Driver-&-Metabase-Plugin-Basics) + ## To Build the Driver @@ -81,19 +89,19 @@ fork](https://github.com/MaterializeInc/pgjdbc) to provide the underlying SQL Driver. To use the forked Driver, we go through the following steps: -1. Check out the forked `pgjdbc` repo locally. +1. Check out the forked `MaterializeInc/pgjdbc` repo locally. 1. Build a shaded jar with: ```shell script mvn clean && mvn package -DskipTests -Dmaven.javadoc.skip=true -P release-artifacts - ``` + ``` 1. Check out this repo locally and move the resulting jar into the `/src` folder. ```shell script mv /path/to/postgresql-1-MZ-SNAPSHOT.jar /path/to/metabase-materialize-driver/src/ - ``` + ``` 1. Extract the files from the jarfile **into** the `/src` directory. @@ -106,7 +114,7 @@ To use the forked Driver, we go through the following steps: rm -rf /path/to/metabase-materialize-driver/src/META-INF/ ``` -### Step 2: Build and move the metabase-materialize-driver +### Step 2: Build and move the metabase-materialize-driver 1. Once we've successfully completed copying over the code from the forked Driver, we're ready to build the `metabase-materialize-driver`. @@ -116,7 +124,7 @@ To use the forked Driver, we go through the following steps: lein clean && lein uberjar ``` When the `uberjar` command finishes executing, it will output the path to - the newly created uberjar like: + the newly created uberjar like: ```shell script Compiling metabase.driver.materialize diff --git a/bin/build.sh b/bin/build.sh new file mode 100755 index 0000000..0fecd1b --- /dev/null +++ b/bin/build.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env bash + +set -euo pipefail + +usage() { + echo "usage: $0 [--release [VERSION]] [--mbv VERSION] [--build] + +Build a docker image. + +Options: + + --release Pull from the current tagged release in github + --release VERSION Pull VERSION from the tagged release in github + --mbv VERSION Specify a metabase version, default is latest. Required for --release + --build Build the jar and create a docker image from using that + --no-docker Don't run docker build" + + exit "${1:-1}" +} + +# constants +EXEC_DIR="$(dirname "$0")" +OUTPUT_FILE=target/dist/materialize-driver.jar +NOW="$(date +%Y%m%d_%H%M%S)" + +# options +RELEASE=n +VERSION=_ +METABASE_VERSION=latest +BUILD=n +DOCKER=y + +main() { + cd "$EXEC_DIR/.." || exit 1 + parse_args "$@" + if [[ $VERSION == _ ]]; then + VERSION=$(current_version) + fi + ensure_jar "$VERSION" + if [[ $DOCKER == y ]]; then + runv docker build \ + -t materialize/metabase:"$NOW" \ + -t materialize/metabase:"$VERSION" \ + -t materialize/metabase:latest \ + --build-arg METABASE_VERSION="$METABASE_VERSION" \ + . + fi +} + +parse_args() { + local arg + while [[ $# -gt 0 ]]; do + arg="$1" && shift + case "$arg" in + --release) + RELEASE=y + if [[ ${1:-_} =~ ^.+\..+\..+ ]]; then + VERSION="$1" && shift + fi + ;; + --mbv) + if [[ $# -eq 0 ]]; then + echo "--mbv requires a VERSION" + usage 1 + fi + METABASE_VERSION="$1" && shift + ;; + --build) + BUILD=y + ;; + -h|--help) + usage 0 + ;; + --no-docker) + DOCKER=n + ;; + *) + echo "Unexpected argument: $arg" + usage 1 + ;; + esac + done + if [[ $RELEASE == y && $BUILD == y ]]; then + echo "error: --release and --build don't make sense together" + exit 1 + fi + if [[ $RELEASE == y && $METABASE_VERSION == latest ]]; then + echo "error: --mbv is required for --release" + exit 1 + fi +} + +ensure_jar() { + local version + version="$1" + if [[ $RELEASE == y ]]; then + # first arg is the version + mkdir -p target/dist + runv curl -s \ + --output "$OUTPUT_FILE" \ + "https://github.com/MaterializeInc/metabase-materialize-driver/releases/download/$version/materialize-driver.jar" + echo "downloaded $OUTPUT_FILE" + elif [[ $BUILD == y ]]; then + build_jar + elif [[ ! -f $OUTPUT_FILE ]]; then + echo "neither --build nor --release, and $OUTPUT_FILE not present" + exit 1 + fi +} + +build_jar() { + runv lein clean + runv lein uberjar + mkdir -p "$(dirname $OUTPUT_FILE)" + runv cp target/materialize-driver-"$(plugin_version)"-standalone.jar "$OUTPUT_FILE" + echo "created $OUTPUT_FILE" +} + +plugin_version() { + grep -o 'version: .*' resources/metabase-plugin.yaml | sed 's/version: //' +} + +current_version() { + local version + local current_tag + local tag_no_v + version="$(plugin_version)" + current_tag="$(git tag --list --points-at HEAD)" + # strip the leading v from a tag, since it is never in the yaml file + tag_no_v="${current_tag#v}" + if [[ $version =~ $tag_no_v ]]; then + echo "$current_tag" + else + echo "$version" + fi +} + +runv() { + echo "🚀$ $*" + "$@" +} + +main "$@" diff --git a/project.clj b/project.clj index db6d8cd..d179da7 100644 --- a/project.clj +++ b/project.clj @@ -1,4 +1,4 @@ -(defproject metabase/materialize-driver "0.0.3-SNAPSHOT" +(defproject metabase/materialize-driver "0.0.5-SNAPSHOT" :description "Metabase Materialized Driver" :dependencies diff --git a/resources/metabase-plugin.yaml b/resources/metabase-plugin.yaml index 12845c2..6dda39f 100644 --- a/resources/metabase-plugin.yaml +++ b/resources/metabase-plugin.yaml @@ -2,7 +2,7 @@ info: name: Metabase Materialize Driver # Include JDBC driver version too? - version: 0.0.3-SNAPSHOT + version: 0.0.5-SNAPSHOT description: Allows Metabase to connect to Materialize. driver: # Name of the driver; corresponds to the keyword (e.g. :sqlite) used @@ -32,4 +32,4 @@ init: - step: load-namespace namespace: metabase.driver.materialize - step: register-jdbc-driver - class: io.materialize.Driver \ No newline at end of file + class: io.materialize.Driver diff --git a/src/metabase/driver/materialize.clj b/src/metabase/driver/materialize.clj index d6db64a..a9bd7c1 100644 --- a/src/metabase/driver/materialize.clj +++ b/src/metabase/driver/materialize.clj @@ -6,7 +6,8 @@ [metabase.driver :as driver] [metabase.driver.sql-jdbc [common :as sql-jdbc.common] - [connection :as sql-jdbc.conn]])) + [connection :as sql-jdbc.conn] + [sync :as sql-jdbc.sync]])) (driver/register! :materialize, :parent :postgres) @@ -28,6 +29,7 @@ :subname (make-subname host port db)} (dissoc opts :host :port :db))) +(defmethod driver/display-name :materialize [_] "Materialize") (defmethod sql-jdbc.conn/connection-details->spec :materialize [_ {ssl? :ssl, :as details-map}] (-> details-map @@ -41,3 +43,7 @@ (set/rename-keys {:dbname :db}) materialize (sql-jdbc.common/handle-additional-options details-map))) + +(defmethod driver/describe-table :materialize + [driver database table] + (sql-jdbc.sync/describe-table driver database table))