From 3cd32ba904b5b77d4eac791a49973b595e855f25 Mon Sep 17 00:00:00 2001 From: roger2hk Date: Tue, 30 Jul 2024 19:32:02 +0000 Subject: [PATCH 1/5] Add docker compose files in example-mysql --- cmd/example-mysql/docker/Dockerfile | 17 +++++++++++ cmd/example-mysql/docker/compose.yaml | 37 +++++++++++++++++++++++ cmd/example-mysql/docker/testdata/key | 1 + cmd/example-mysql/docker/testdata/key.pub | 1 + cmd/example-mysql/main.go | 22 ++++++++++++++ 5 files changed, 78 insertions(+) create mode 100644 cmd/example-mysql/docker/Dockerfile create mode 100644 cmd/example-mysql/docker/compose.yaml create mode 100644 cmd/example-mysql/docker/testdata/key create mode 100644 cmd/example-mysql/docker/testdata/key.pub diff --git a/cmd/example-mysql/docker/Dockerfile b/cmd/example-mysql/docker/Dockerfile new file mode 100644 index 00000000..3f5d629e --- /dev/null +++ b/cmd/example-mysql/docker/Dockerfile @@ -0,0 +1,17 @@ +FROM golang:1.22.5-bookworm@sha256:af9b40f2b1851be993763b85288f8434af87b5678af04355b1e33ff530b5765f as build + +WORKDIR /build + +# pre-copy/cache go.mod for pre-downloading dependencies and only redownloading them in subsequent builds if they change +COPY go.mod go.sum ./ +RUN go mod download && go mod verify + +COPY . . +RUN go build ./cmd/example-mysql + +FROM gcr.io/distroless/base-debian12@sha256:1aae189e3baecbb4044c648d356ddb75025b2ba8d14cdc9c2a19ba784c90bfb9 + +COPY --from=build /build/example-mysql / +COPY --from=build /build/cmd/example-mysql/docker/testdata/key /build/cmd/example-mysql/docker/testdata/key.pub /build/storage/mysql/schema.sql / + +ENTRYPOINT ["/example-mysql"] diff --git a/cmd/example-mysql/docker/compose.yaml b/cmd/example-mysql/docker/compose.yaml new file mode 100644 index 00000000..f9618509 --- /dev/null +++ b/cmd/example-mysql/docker/compose.yaml @@ -0,0 +1,37 @@ +services: + + tessera-example-mysql-db: + container_name: tessera-mysql-db + image: "mysql:8.4" + ports: + - "3306:3306" + environment: + - MYSQL_ROOT_PASSWORD=tessera + - MYSQL_DATABASE=tessera + - MYSQL_USER=tessera + - MYSQL_PASSWORD=tessera + restart: always + healthcheck: + test: mysql --user=$$MYSQL_USER --password=$$MYSQL_PASSWORD --silent --execute "SHOW DATABASES;" + interval: 5s + timeout: 5s + retries: 10 + + tessera-example-mysql: + container_name: tessera-example-mysql + build: + context: ../../../ + dockerfile: ./cmd/example-mysql/docker/Dockerfile + ports: + - "2024:2024" + command: [ + "--mysql_uri=tessera:tessera@tcp(tessera-example-mysql-db:3306)/tessera", + "--init_schema_path=/schema.sql", + "--private_key_path=/key", + "--public_key_path=/key.pub", + "--alsologtostderr", + ] + restart: always + depends_on: + tessera-example-mysql-db: + condition: service_healthy diff --git a/cmd/example-mysql/docker/testdata/key b/cmd/example-mysql/docker/testdata/key new file mode 100644 index 00000000..1b687879 --- /dev/null +++ b/cmd/example-mysql/docker/testdata/key @@ -0,0 +1 @@ +PRIVATE+KEY+Test-Betty+df84580a+Afge8kCzBXU7jb3cV2Q363oNXCufJ6u9mjOY1BGRY9E2 \ No newline at end of file diff --git a/cmd/example-mysql/docker/testdata/key.pub b/cmd/example-mysql/docker/testdata/key.pub new file mode 100644 index 00000000..6794e261 --- /dev/null +++ b/cmd/example-mysql/docker/testdata/key.pub @@ -0,0 +1 @@ +Test-Betty+df84580a+AQQASqPUZoIHcJAF5mBOryctwFdTV1E0GRY4kEAtTzwB \ No newline at end of file diff --git a/cmd/example-mysql/main.go b/cmd/example-mysql/main.go index 4ba5461f..b9b83da5 100644 --- a/cmd/example-mysql/main.go +++ b/cmd/example-mysql/main.go @@ -38,6 +38,7 @@ var ( dbConnMaxLifetime = flag.Duration("db_conn_max_lifetime", 3*time.Minute, "") dbMaxOpenConns = flag.Int("db_max_open_conns", 64, "") dbMaxIdleConns = flag.Int("db_max_idle_conns", 64, "") + initSchemaPath = flag.String("init_schema_path", "", "Location of the schema file if database initialization is needed") listen = flag.String("listen", ":2024", "Address:port to listen on") privateKeyPath = flag.String("private_key_path", "", "Location of private key file") publicKeyPath = flag.String("public_key_path", "", "Location of public key file") @@ -56,6 +57,8 @@ func main() { db.SetMaxOpenConns(*dbMaxOpenConns) db.SetMaxIdleConns(*dbMaxIdleConns) + initDatabaseSchema(ctx, db) + rawPrivateKey, err := os.ReadFile(*privateKeyPath) if err != nil { klog.Exitf("Failed to read private key file %q: %v", *privateKeyPath, err) @@ -242,3 +245,22 @@ func parseTileIndexWidth(index string) (uint64, uint64, error) { return i, w, nil } + +func initDatabaseSchema(ctx context.Context, db *sql.DB) { + if db != nil && *initSchemaPath != "" { + rawSchema, err := os.ReadFile(*initSchemaPath) + if err != nil { + klog.Exitf("Failed to read init schema file %q: %v", *initSchemaPath, err) + } + + queries := strings.SplitAfter(strings.TrimSpace(string(rawSchema)), ";") + + for _, query := range queries { + if len(query) > 0 { + if _, err := db.ExecContext(ctx, query); err != nil { + klog.Exitf("Failed to execute init database schema: %v", err) + } + } + } + } +} From c35f0931069bda4729dd9879bdfbebec6e37f1b0 Mon Sep 17 00:00:00 2001 From: roger2hk Date: Wed, 31 Jul 2024 09:38:39 +0000 Subject: [PATCH 2/5] Update the example-mysql Docker image to `alpine` --- cmd/example-mysql/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/example-mysql/docker/Dockerfile b/cmd/example-mysql/docker/Dockerfile index 3f5d629e..a34934c3 100644 --- a/cmd/example-mysql/docker/Dockerfile +++ b/cmd/example-mysql/docker/Dockerfile @@ -9,7 +9,7 @@ RUN go mod download && go mod verify COPY . . RUN go build ./cmd/example-mysql -FROM gcr.io/distroless/base-debian12@sha256:1aae189e3baecbb4044c648d356ddb75025b2ba8d14cdc9c2a19ba784c90bfb9 +FROM alpine:3.20@sha256:0a4eaa0eecf5f8c050e5bba433f58c052be7587ee8af3e8b3910ef9ab5fbe9f5 COPY --from=build /build/example-mysql / COPY --from=build /build/cmd/example-mysql/docker/testdata/key /build/cmd/example-mysql/docker/testdata/key.pub /build/storage/mysql/schema.sql / From 1a9be8a0e1a20573133938d2a31604288f9af8bc Mon Sep 17 00:00:00 2001 From: roger2hk Date: Wed, 31 Jul 2024 09:39:27 +0000 Subject: [PATCH 3/5] Initialize database schema with `multiStatements=true` --- cmd/example-mysql/main.go | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/cmd/example-mysql/main.go b/cmd/example-mysql/main.go index b9b83da5..f3eeca1a 100644 --- a/cmd/example-mysql/main.go +++ b/cmd/example-mysql/main.go @@ -57,7 +57,7 @@ func main() { db.SetMaxOpenConns(*dbMaxOpenConns) db.SetMaxIdleConns(*dbMaxIdleConns) - initDatabaseSchema(ctx, db) + initDatabaseSchema(ctx) rawPrivateKey, err := os.ReadFile(*privateKeyPath) if err != nil { @@ -246,21 +246,26 @@ func parseTileIndexWidth(index string) (uint64, uint64, error) { return i, w, nil } -func initDatabaseSchema(ctx context.Context, db *sql.DB) { - if db != nil && *initSchemaPath != "" { +func initDatabaseSchema(ctx context.Context) { + if *initSchemaPath != "" { + db, err := sql.Open("mysql", *mysqlURI+"?multiStatements=true") + if err != nil { + klog.Exitf("Failed to connect to DB: %v", err) + } + defer db.Close() + rawSchema, err := os.ReadFile(*initSchemaPath) if err != nil { klog.Exitf("Failed to read init schema file %q: %v", *initSchemaPath, err) } + if _, err := db.ExecContext(ctx, string(rawSchema)); err != nil { + klog.Exitf("Failed to execute init database schema: %v", err) + } - queries := strings.SplitAfter(strings.TrimSpace(string(rawSchema)), ";") - - for _, query := range queries { - if len(query) > 0 { - if _, err := db.ExecContext(ctx, query); err != nil { - klog.Exitf("Failed to execute init database schema: %v", err) - } + defer func() { + if err := db.Close(); err != nil { + klog.Warningf("Failed to close db: %v", err) } - } + }() } } From 8e20b22802526739a26efc13aa96e50eaff06180 Mon Sep 17 00:00:00 2001 From: roger2hk Date: Wed, 31 Jul 2024 09:59:04 +0000 Subject: [PATCH 4/5] Add `CGO_ENABLED=0` when building example-mysql --- cmd/example-mysql/docker/Dockerfile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/example-mysql/docker/Dockerfile b/cmd/example-mysql/docker/Dockerfile index a34934c3..0857cfe6 100644 --- a/cmd/example-mysql/docker/Dockerfile +++ b/cmd/example-mysql/docker/Dockerfile @@ -7,11 +7,10 @@ COPY go.mod go.sum ./ RUN go mod download && go mod verify COPY . . -RUN go build ./cmd/example-mysql +RUN CGO_ENABLED=0 go build -v ./cmd/example-mysql FROM alpine:3.20@sha256:0a4eaa0eecf5f8c050e5bba433f58c052be7587ee8af3e8b3910ef9ab5fbe9f5 -COPY --from=build /build/example-mysql / -COPY --from=build /build/cmd/example-mysql/docker/testdata/key /build/cmd/example-mysql/docker/testdata/key.pub /build/storage/mysql/schema.sql / +COPY --from=build /build/example-mysql /build/cmd/example-mysql/docker/testdata/key /build/cmd/example-mysql/docker/testdata/key.pub /build/storage/mysql/schema.sql / ENTRYPOINT ["/example-mysql"] From 1b4de10e9cbfc0bb492efcd6dcef3a3163fcbac1 Mon Sep 17 00:00:00 2001 From: roger2hk Date: Wed, 31 Jul 2024 10:01:00 +0000 Subject: [PATCH 5/5] Add logs to `initDatabaseSchema` --- cmd/example-mysql/main.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cmd/example-mysql/main.go b/cmd/example-mysql/main.go index f3eeca1a..7ed6a1cc 100644 --- a/cmd/example-mysql/main.go +++ b/cmd/example-mysql/main.go @@ -248,11 +248,17 @@ func parseTileIndexWidth(index string) (uint64, uint64, error) { func initDatabaseSchema(ctx context.Context) { if *initSchemaPath != "" { + klog.Infof("Initializing database schema") + db, err := sql.Open("mysql", *mysqlURI+"?multiStatements=true") if err != nil { klog.Exitf("Failed to connect to DB: %v", err) } - defer db.Close() + defer func() { + if err := db.Close(); err != nil { + klog.Warningf("Failed to close db: %v", err) + } + }() rawSchema, err := os.ReadFile(*initSchemaPath) if err != nil { @@ -262,10 +268,6 @@ func initDatabaseSchema(ctx context.Context) { klog.Exitf("Failed to execute init database schema: %v", err) } - defer func() { - if err := db.Close(); err != nil { - klog.Warningf("Failed to close db: %v", err) - } - }() + klog.Infof("Database schema initialized") } }