170 lines
3.7 KiB
Go
170 lines
3.7 KiB
Go
|
package integrations
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/jmoiron/sqlx"
|
||
|
"go.signoz.io/signoz/pkg/query-service/model"
|
||
|
)
|
||
|
|
||
|
func InitSqliteDBIfNeeded(db *sqlx.DB) error {
|
||
|
if db == nil {
|
||
|
return fmt.Errorf("db is required")
|
||
|
}
|
||
|
|
||
|
createTablesStatements := `
|
||
|
CREATE TABLE IF NOT EXISTS integrations_installed(
|
||
|
integration_id TEXT PRIMARY KEY,
|
||
|
config_json TEXT,
|
||
|
installed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
|
)
|
||
|
`
|
||
|
_, err := db.Exec(createTablesStatements)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf(
|
||
|
"could not ensure integrations schema in sqlite DB: %w", err,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
type InstalledIntegrationsSqliteRepo struct {
|
||
|
db *sqlx.DB
|
||
|
}
|
||
|
|
||
|
func NewInstalledIntegrationsSqliteRepo(db *sqlx.DB) (
|
||
|
*InstalledIntegrationsSqliteRepo, error,
|
||
|
) {
|
||
|
err := InitSqliteDBIfNeeded(db)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf(
|
||
|
"couldn't ensure sqlite schema for installed integrations: %w", err,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
return &InstalledIntegrationsSqliteRepo{
|
||
|
db: db,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (r *InstalledIntegrationsSqliteRepo) list(
|
||
|
ctx context.Context,
|
||
|
) ([]InstalledIntegration, *model.ApiError) {
|
||
|
integrations := []InstalledIntegration{}
|
||
|
|
||
|
err := r.db.SelectContext(
|
||
|
ctx, &integrations, `
|
||
|
select
|
||
|
integration_id,
|
||
|
config_json,
|
||
|
installed_at
|
||
|
from integrations_installed
|
||
|
order by installed_at
|
||
|
`,
|
||
|
)
|
||
|
if err != nil {
|
||
|
return nil, model.InternalError(fmt.Errorf(
|
||
|
"could not query installed integrations: %w", err,
|
||
|
))
|
||
|
}
|
||
|
return integrations, nil
|
||
|
}
|
||
|
|
||
|
func (r *InstalledIntegrationsSqliteRepo) get(
|
||
|
ctx context.Context, integrationIds []string,
|
||
|
) (map[string]InstalledIntegration, *model.ApiError) {
|
||
|
integrations := []InstalledIntegration{}
|
||
|
|
||
|
idPlaceholders := []string{}
|
||
|
idValues := []interface{}{}
|
||
|
for _, id := range integrationIds {
|
||
|
idPlaceholders = append(idPlaceholders, "?")
|
||
|
idValues = append(idValues, id)
|
||
|
}
|
||
|
|
||
|
err := r.db.SelectContext(
|
||
|
ctx, &integrations, fmt.Sprintf(`
|
||
|
select
|
||
|
integration_id,
|
||
|
config_json,
|
||
|
installed_at
|
||
|
from integrations_installed
|
||
|
where integration_id in (%s)`,
|
||
|
strings.Join(idPlaceholders, ", "),
|
||
|
),
|
||
|
idValues...,
|
||
|
)
|
||
|
if err != nil {
|
||
|
return nil, model.InternalError(fmt.Errorf(
|
||
|
"could not query installed integrations: %w", err,
|
||
|
))
|
||
|
}
|
||
|
|
||
|
result := map[string]InstalledIntegration{}
|
||
|
for _, ii := range integrations {
|
||
|
result[ii.IntegrationId] = ii
|
||
|
}
|
||
|
|
||
|
return result, nil
|
||
|
}
|
||
|
|
||
|
func (r *InstalledIntegrationsSqliteRepo) upsert(
|
||
|
ctx context.Context,
|
||
|
integrationId string,
|
||
|
config InstalledIntegrationConfig,
|
||
|
) (*InstalledIntegration, *model.ApiError) {
|
||
|
serializedConfig, err := config.Value()
|
||
|
if err != nil {
|
||
|
return nil, model.BadRequest(fmt.Errorf(
|
||
|
"could not serialize integration config: %w", err,
|
||
|
))
|
||
|
}
|
||
|
|
||
|
_, dbErr := r.db.ExecContext(
|
||
|
ctx, `
|
||
|
INSERT INTO integrations_installed (
|
||
|
integration_id,
|
||
|
config_json
|
||
|
) values ($1, $2)
|
||
|
on conflict(integration_id) do update
|
||
|
set config_json=excluded.config_json
|
||
|
`, integrationId, serializedConfig,
|
||
|
)
|
||
|
if dbErr != nil {
|
||
|
return nil, model.InternalError(fmt.Errorf(
|
||
|
"could not insert record for integration installation: %w", dbErr,
|
||
|
))
|
||
|
}
|
||
|
|
||
|
res, apiErr := r.get(ctx, []string{integrationId})
|
||
|
if apiErr != nil || len(res) < 1 {
|
||
|
return nil, model.WrapApiError(
|
||
|
apiErr, "could not fetch installed integration",
|
||
|
)
|
||
|
}
|
||
|
|
||
|
installed := res[integrationId]
|
||
|
|
||
|
return &installed, nil
|
||
|
}
|
||
|
|
||
|
func (r *InstalledIntegrationsSqliteRepo) delete(
|
||
|
ctx context.Context, integrationId string,
|
||
|
) *model.ApiError {
|
||
|
_, dbErr := r.db.ExecContext(ctx, `
|
||
|
DELETE FROM integrations_installed where integration_id = ?
|
||
|
`, integrationId)
|
||
|
|
||
|
if dbErr != nil {
|
||
|
return model.InternalError(fmt.Errorf(
|
||
|
"could not delete installed integration record for %s: %w",
|
||
|
integrationId, dbErr,
|
||
|
))
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|