This repository has been archived by the owner on Apr 26, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
postgres.go
75 lines (66 loc) · 2.53 KB
/
postgres.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package main
import (
"encoding/json"
"time"
"github.com/flynn/flynn-discovery/Godeps/_workspace/src/github.com/jackc/pgx"
)
func NewPostgresBackend(db *pgx.ConnPool) StorageBackend {
return &PostgresBackend{db: db}
}
type PostgresBackend struct {
db *pgx.ConnPool
}
func (b *PostgresBackend) CreateCluster(cluster *Cluster) error {
return b.db.QueryRow("INSERT INTO clusters (creator_ip, creator_user_agent) VALUES ($1, $2) RETURNING cluster_id, created_at",
cluster.CreatorIP, cluster.CreatorUserAgent).Scan(&cluster.ID, &cluster.CreatedAt)
}
func (b *PostgresBackend) CreateInstance(inst *Instance) error {
if inst.SSHPublicKeys == nil {
inst.SSHPublicKeys = []SSHPublicKey{}
}
// pgx doesn't like unmarshalling into **time.Time
inst.CreatedAt = &time.Time{}
sshKeys, _ := json.Marshal(inst.SSHPublicKeys)
err := b.db.QueryRow("INSERT INTO instances (cluster_id, flynn_version, ssh_public_keys, url, name, creator_ip) VALUES ($1, $2, $3, $4, $5, $6) RETURNING instance_id, created_at",
inst.ClusterID, inst.FlynnVersion, string(sshKeys), inst.URL, inst.Name, inst.CreatorIP).Scan(&inst.ID, inst.CreatedAt)
if pgErr, ok := err.(pgx.PgError); ok && pgErr.Code == "23505" /*duplicate key violates unique constraint*/ && pgErr.ConstraintName == "instances_cluster_id_url_key" {
row := b.db.QueryRow("SELECT instance_id, flynn_version, ssh_public_keys, url, name, creator_ip, created_at FROM instances WHERE cluster_id = $1 AND url = $2", inst.ClusterID, inst.URL)
if err := scanInstance(row, inst); err != nil {
return err
}
return ErrExists
}
return err
}
type pgxScanner interface {
Scan(...interface{}) error
}
func scanInstance(row pgxScanner, inst *Instance) error {
if inst.CreatedAt == nil {
inst.CreatedAt = &time.Time{}
}
var sshKeys string
if err := row.Scan(&inst.ID, &inst.FlynnVersion, &sshKeys, &inst.URL, &inst.Name, &inst.CreatorIP, inst.CreatedAt); err != nil {
return err
}
if err := json.Unmarshal([]byte(sshKeys), &inst.SSHPublicKeys); err != nil {
return err
}
return nil
}
func (b *PostgresBackend) GetClusterInstances(clusterID string) ([]*Instance, error) {
rows, err := b.db.Query("SELECT instance_id, flynn_version, ssh_public_keys, url, name, creator_ip, created_at FROM instances WHERE cluster_id = $1", clusterID)
if err != nil {
return nil, err
}
var instances []*Instance
for rows.Next() {
inst := &Instance{ClusterID: clusterID}
if err := scanInstance(rows, inst); err != nil {
rows.Close()
return nil, err
}
instances = append(instances, inst)
}
return instances, rows.Err()
}