Skip to content

Commit

Permalink
feat: add support for postgresql
Browse files Browse the repository at this point in the history
This allows users to connect to a postgresql backend for our ent
library. The ent client creation was broken into it's own function so we
can use the enttest library to pass in the test client for unit testing
in the future.
  • Loading branch information
mikhailswift committed Sep 21, 2023
1 parent 658b3f6 commit c2001a4
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 34 deletions.
9 changes: 7 additions & 2 deletions cmd/archivista/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/testifysec/archivista"
"github.com/testifysec/archivista/internal/config"
"github.com/testifysec/archivista/internal/metadatastorage/mysqlstore"
"github.com/testifysec/archivista/internal/metadatastorage/sqlstore"
"github.com/testifysec/archivista/internal/objectstorage/blobstore"
"github.com/testifysec/archivista/internal/objectstorage/filestore"
"github.com/testifysec/archivista/internal/server"
Expand Down Expand Up @@ -86,7 +86,12 @@ func main() {
logrus.Fatalf("error initializing storage clients: %+v", err)
}

mysqlStore, mysqlStoreCh, err := mysqlstore.New(ctx, cfg.SQLStoreConnectionString)
entClient, err := sqlstore.NewEntClient(cfg.SQLBackend, cfg.SQLStoreConnectionString)
if err != nil {
logrus.Fatalf("could not create ent client: %+v", err)
}

mysqlStore, mysqlStoreCh, err := sqlstore.New(ctx, entClient)
if err != nil {
logrus.Fatalf("error initializing mysql client: %+v", err)
}
Expand Down
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Config struct {
SPIFFEAddress string `default:"unix:///tmp/spire-agent/public/api.sock" desc:"SPIFFE server address" split_words:"true"`
SPIFFETrustedServerId string `default:"" desc:"Trusted SPIFFE server ID; defaults to any" split_words:"true"`
SQLStoreConnectionString string `default:"root:example@tcp(db)/testify" desc:"SQL store connection string" split_words:"true"`
SQLBackend string `default:"MYSQL" desc:"SQL backend to use. Options are MYSQL, PSQL" split_words:"true"`

StorageBackend string `default:"" desc:"Backend to use for attestation storage. Options are FILE, BLOB, or empty string for disabled." split_words:"true"`
FileServeOn string `default:"" desc:"What address to serve files on. Only valid when using FILE storage backend." split_words:"true"`
Expand Down
70 changes: 70 additions & 0 deletions internal/metadatastorage/sqlstore/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2023 The Archivista Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sqlstore

import (
"fmt"
"strings"
"time"

"ariga.io/sqlcomment"
"entgo.io/ent/dialect"
"entgo.io/ent/dialect/sql"
"github.com/go-sql-driver/mysql"
"github.com/testifysec/archivista/ent"
)

// NewEntClient creates an ent client for use in the sqlmetadata store.
// Valid backends are MYSQL and PSQL.
func NewEntClient(sqlBackend string, connectionString string) (*ent.Client, error) {
var entDialect string
switch strings.ToUpper(sqlBackend) {
case "MYSQL":
dbConfig, err := mysql.ParseDSN(connectionString)
if err != nil {
return nil, fmt.Errorf("could not parse mysql connection string: %w", err)
}

// this tells the go-sql-driver to parse times from mysql to go's time.Time
// see https://github.com/go-sql-driver/mysql#timetime-support for details
dbConfig.ParseTime = true
entDialect = dialect.MySQL
connectionString = dbConfig.FormatDSN()
case "PSQL":
entDialect = dialect.Postgres
default:
return nil, fmt.Errorf("unknown sql backend: %s", sqlBackend)
}

drv, err := sql.Open(entDialect, connectionString)
if err != nil {
return nil, fmt.Errorf("could not open sql connection: %w", err)
}

db := drv.DB()
db.SetMaxIdleConns(10)
db.SetMaxOpenConns(100)
db.SetConnMaxLifetime(3 * time.Minute)
sqlcommentDrv := sqlcomment.NewDriver(drv,
sqlcomment.WithDriverVerTag(),
sqlcomment.WithTags(sqlcomment.Tags{
sqlcomment.KeyApplication: "archivista",
sqlcomment.KeyFramework: "net/http",
}),
)

client := ent.NewClient(ent.Driver(sqlcommentDrv))
return client, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package mysqlstore
package sqlstore

import (
"context"
Expand All @@ -22,10 +22,7 @@ import (
"fmt"
"time"

"ariga.io/sqlcomment"
"entgo.io/ent/dialect/sql"
"github.com/digitorus/timestamp"
"github.com/go-sql-driver/mysql"
"github.com/sirupsen/logrus"
"github.com/testifysec/archivista/ent"
"github.com/testifysec/archivista/internal/metadatastorage"
Expand All @@ -47,34 +44,7 @@ type Store struct {
client *ent.Client
}

func New(ctx context.Context, connectionstring string) (*Store, <-chan error, error) {
dbConfig, err := mysql.ParseDSN(connectionstring)
if err != nil {
return nil, nil, err
}

dbConfig.ParseTime = true
connectionstring = dbConfig.FormatDSN()
drv, err := sql.Open("mysql", connectionstring)
if err != nil {
return nil, nil, err
}
sqlcommentDrv := sqlcomment.NewDriver(drv,
sqlcomment.WithDriverVerTag(),
sqlcomment.WithTags(sqlcomment.Tags{
sqlcomment.KeyApplication: "archivista",
sqlcomment.KeyFramework: "net/http",
}),
)

// TODO make sure these take affect in sqlcommentDrv
db := drv.DB()
db.SetMaxIdleConns(10)
db.SetMaxOpenConns(100)
db.SetConnMaxLifetime(3 * time.Minute)

client := ent.NewClient(ent.Driver(sqlcommentDrv))

func New(ctx context.Context, client *ent.Client) (*Store, <-chan error, error) {
errCh := make(chan error)

go func() {
Expand Down

0 comments on commit c2001a4

Please sign in to comment.