runable
This commit is contained in:
@@ -60,13 +60,13 @@ func run() error {
|
||||
}
|
||||
defer redisClient.Close()
|
||||
|
||||
chMain, err := repo.NewClickHouse(ctx, cfg.ClickHouseAddr, cfg.ClickHouseDB, cfg.ClickHouseUser, cfg.ClickHousePassword)
|
||||
chMain, err := repo.NewClickHouse(ctx, cfg.ClickHouseAddr, cfg.ClickHouseDB, cfg.ClickHouseUser, cfg.ClickHousePassword, cfg.ClickHouseSecure)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = chMain.Close() }()
|
||||
|
||||
chRO, err := repo.NewClickHouseReadOnly(ctx, cfg.ClickHouseAddr, cfg.ClickHouseDB, cfg.ClickHouseSQLUser, cfg.ClickHouseSQLPassword)
|
||||
chRO, err := repo.NewClickHouseReadOnly(ctx, cfg.ClickHouseAddr, cfg.ClickHouseDB, cfg.ClickHouseSQLUser, cfg.ClickHouseSQLPassword, cfg.ClickHouseSecure)
|
||||
if err != nil {
|
||||
// Read-only user might not be provisioned in dev. Log + fall back to
|
||||
// the main connection so /query/sql still works locally; production
|
||||
|
||||
@@ -36,6 +36,7 @@ type Config struct {
|
||||
ClickHouseDB string `env:"CLICKHOUSE_DB" envDefault:"cdp"`
|
||||
ClickHouseUser string `env:"CLICKHOUSE_USER" envDefault:"default"`
|
||||
ClickHousePassword string `env:"CLICKHOUSE_PASSWORD"`
|
||||
ClickHouseSecure bool `env:"CLICKHOUSE_SECURE" envDefault:"false"`
|
||||
}
|
||||
|
||||
func Load() (*Config, error) {
|
||||
|
||||
@@ -2,17 +2,20 @@ package repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
|
||||
"github.com/ClickHouse/clickhouse-go/v2"
|
||||
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
|
||||
)
|
||||
|
||||
// NewClickHouse opens a native-protocol ClickHouse connection. The returned
|
||||
// driver.Conn is safe for concurrent use. Caller owns Close().
|
||||
func NewClickHouse(ctx context.Context, addr, db, user, password string) (driver.Conn, error) {
|
||||
conn, err := clickhouse.Open(&clickhouse.Options{
|
||||
Addr: []string{addr},
|
||||
// NewClickHouse opens a ClickHouse connection. `secure` enables TLS. The
|
||||
// wire protocol is auto-selected from the port: 8123/8443 (HTTP interface)
|
||||
// use HTTP, the native default otherwise.
|
||||
func NewClickHouse(ctx context.Context, addr, db, user, password string, secure bool) (driver.Conn, error) {
|
||||
opts := &clickhouse.Options{
|
||||
Addr: []string{addr},
|
||||
Protocol: protocolFromAddr(addr),
|
||||
Auth: clickhouse.Auth{
|
||||
Database: db,
|
||||
Username: user,
|
||||
@@ -21,7 +24,11 @@ func NewClickHouse(ctx context.Context, addr, db, user, password string) (driver
|
||||
Settings: clickhouse.Settings{
|
||||
"readonly": 0, // analytics queries; per-user read-only enforced for /query/sql separately
|
||||
},
|
||||
})
|
||||
}
|
||||
if secure {
|
||||
opts.TLS = &tls.Config{MinVersion: tls.VersionTLS12}
|
||||
}
|
||||
conn, err := clickhouse.Open(opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open clickhouse: %w", err)
|
||||
}
|
||||
@@ -35,9 +42,10 @@ func NewClickHouse(ctx context.Context, addr, db, user, password string) (driver
|
||||
// NewClickHouseReadOnly opens a ClickHouse connection using a SELECT-only
|
||||
// account. Used to back the /query/sql sandbox: DDL/DML are rejected at the DB
|
||||
// level even if the app-level keyword guard is bypassed.
|
||||
func NewClickHouseReadOnly(ctx context.Context, addr, db, user, password string) (driver.Conn, error) {
|
||||
conn, err := clickhouse.Open(&clickhouse.Options{
|
||||
Addr: []string{addr},
|
||||
func NewClickHouseReadOnly(ctx context.Context, addr, db, user, password string, secure bool) (driver.Conn, error) {
|
||||
opts := &clickhouse.Options{
|
||||
Addr: []string{addr},
|
||||
Protocol: protocolFromAddr(addr),
|
||||
Auth: clickhouse.Auth{
|
||||
Database: db,
|
||||
Username: user,
|
||||
@@ -46,7 +54,11 @@ func NewClickHouseReadOnly(ctx context.Context, addr, db, user, password string)
|
||||
Settings: clickhouse.Settings{
|
||||
"readonly": 2, // belt-and-braces: server-side enforce read-only
|
||||
},
|
||||
})
|
||||
}
|
||||
if secure {
|
||||
opts.TLS = &tls.Config{MinVersion: tls.VersionTLS12}
|
||||
}
|
||||
conn, err := clickhouse.Open(opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open clickhouse (ro): %w", err)
|
||||
}
|
||||
@@ -56,3 +68,24 @@ func NewClickHouseReadOnly(ctx context.Context, addr, db, user, password string)
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// protocolFromAddr selects HTTP for the well-known ClickHouse HTTP-interface
|
||||
// ports (8123/8443) and Native otherwise. Lets CLICKHOUSE_ADDR target either
|
||||
// kind of endpoint without an extra env var.
|
||||
func protocolFromAddr(addr string) clickhouse.Protocol {
|
||||
switch port := portOf(addr); port {
|
||||
case "8123", "8443":
|
||||
return clickhouse.HTTP
|
||||
default:
|
||||
return clickhouse.Native
|
||||
}
|
||||
}
|
||||
|
||||
func portOf(addr string) string {
|
||||
for i := len(addr) - 1; i >= 0; i-- {
|
||||
if addr[i] == ':' {
|
||||
return addr[i+1:]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user