Skip to content

Commit 42b3712

Browse files
authored
Merge pull request #63 from fly-apps/restore-support
Add support for Fly Volume Restores
2 parents 99f2870 + fb0862a commit 42b3712

File tree

6 files changed

+302
-56
lines changed

6 files changed

+302
-56
lines changed

Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ RUN CGO_ENABLED=0 GOOS=linux go build -v -o /fly/bin/event_handler ./cmd/event_h
1111
RUN CGO_ENABLED=0 GOOS=linux go build -v -o /fly/bin/failover_validation ./cmd/failover_validation
1212
RUN CGO_ENABLED=0 GOOS=linux go build -v -o /fly/bin/standby_cleaner ./cmd/standby_cleaner
1313
RUN CGO_ENABLED=0 GOOS=linux go build -v -o /fly/bin/pg_unregister ./cmd/pg_unregister
14+
RUN CGO_ENABLED=0 GOOS=linux go build -v -o /fly/bin/start_admin_server ./cmd/admin_server
15+
1416
RUN CGO_ENABLED=0 GOOS=linux go build -v -o /fly/bin/start ./cmd/start
1517

1618
COPY ./bin/* /fly/bin/

cmd/admin_server/main.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package main
2+
3+
import (
4+
"github.com/fly-apps/postgres-flex/internal/api"
5+
"github.com/fly-apps/postgres-flex/internal/flypg"
6+
)
7+
8+
func main() {
9+
node, err := flypg.NewNode()
10+
if err != nil {
11+
panic(err)
12+
}
13+
14+
api.StartHttpServer(node)
15+
}

cmd/start/main.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,12 @@ func main() {
5454
svisor.AddProcess("repmgrd", fmt.Sprintf("gosu postgres repmgrd -f %s --daemonize=false", node.RepMgr.ConfigPath),
5555
supervisor.WithRestart(0, 5*time.Second),
5656
)
57-
svisor.AddProcess("standby_cleaner", "/usr/local/bin/standby_cleaner", supervisor.WithRestart(0, 5*time.Second))
57+
svisor.AddProcess("standby_cleaner", "/usr/local/bin/standby_cleaner",
58+
supervisor.WithRestart(0, 5*time.Second),
59+
)
60+
svisor.AddProcess("admin", "/usr/local/bin/start_admin_server",
61+
supervisor.WithRestart(0, 5*time.Second),
62+
)
5863

5964
exporterEnv := map[string]string{
6065
"DATA_SOURCE_URI": fmt.Sprintf("[%s]:%d/postgres?sslmode=disable", node.PrivateIP, node.Port),
@@ -63,11 +68,12 @@ func main() {
6368
"PG_EXPORTER_EXCLUDE_DATABASE": "template0,template1",
6469
"PG_EXPORTER_AUTO_DISCOVER_DATABASES": "true",
6570
}
66-
67-
svisor.AddProcess("exporter", "postgres_exporter", supervisor.WithEnv(exporterEnv), supervisor.WithRestart(0, 1*time.Second))
71+
svisor.AddProcess("exporter", "postgres_exporter",
72+
supervisor.WithEnv(exporterEnv),
73+
supervisor.WithRestart(0, 1*time.Second),
74+
)
6875

6976
svisor.StopOnSignal(syscall.SIGINT, syscall.SIGTERM)
70-
svisor.StartHttpListener(node)
7177

7278
if err := svisor.Run(); err != nil {
7379
fmt.Println(err)

internal/flypg/node.go

Lines changed: 55 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,26 @@ func NewNode() (*Node, error) {
123123
}
124124

125125
func (n *Node) Init(ctx context.Context) error {
126+
// Ensure directory and files have proper permissions
126127
if err := setDirOwnership(); err != nil {
127128
return err
128129
}
129130

131+
// Initiate a restore
132+
if os.Getenv("FLY_RESTORED_FROM") != "" {
133+
// Check to see if there's an active restore.
134+
active, err := isRestoreActive()
135+
if err != nil {
136+
return err
137+
}
138+
139+
if active {
140+
if err := Restore(ctx, n); err != nil {
141+
return fmt.Errorf("failed to issue restore: %s", err)
142+
}
143+
}
144+
}
145+
130146
if ZombieLockExists() {
131147
fmt.Println("Zombie lock detected!")
132148
primaryStr, err := readZombieLock()
@@ -188,7 +204,7 @@ func (n *Node) Init(ctx context.Context) error {
188204
}
189205
}
190206

191-
err := WriteSSHKey()
207+
err := writeSSHKey()
192208
if err != nil {
193209
return fmt.Errorf("failed initialize ssh. %v", err)
194210
}
@@ -211,12 +227,10 @@ func (n *Node) Init(ctx context.Context) error {
211227

212228
if !clusterInitialized {
213229
// Initialize ourselves as the primary.
214-
fmt.Println("Initializing postgres")
215230
if err := n.initializePG(); err != nil {
216231
return fmt.Errorf("failed to initialize postgres %s", err)
217232
}
218233

219-
fmt.Println("Setting default HBA")
220234
if err := n.setDefaultHBA(); err != nil {
221235
return fmt.Errorf("failed updating pg_hba.conf: %s", err)
222236
}
@@ -233,7 +247,6 @@ func (n *Node) Init(ctx context.Context) error {
233247
}
234248
}
235249

236-
fmt.Println("Initializing Postgres configuration")
237250
if err := n.configurePostgres(store); err != nil {
238251
return fmt.Errorf("failed to configure postgres: %s", err)
239252
}
@@ -245,44 +258,6 @@ func (n *Node) Init(ctx context.Context) error {
245258
return nil
246259
}
247260

248-
func WriteSSHKey() error {
249-
err := os.Mkdir("/data/.ssh", 0700)
250-
if err != nil && !os.IsExist(err) {
251-
return err
252-
}
253-
254-
key := os.Getenv("SSH_KEY")
255-
256-
keyFile, err := os.Create("/data/.ssh/id_rsa")
257-
if err != nil {
258-
return err
259-
}
260-
defer keyFile.Close()
261-
_, err = keyFile.Write([]byte(key))
262-
if err != nil {
263-
return err
264-
}
265-
266-
cert := os.Getenv("SSH_CERT")
267-
268-
certFile, err := os.Create("/data/.ssh/id_rsa-cert.pub")
269-
if err != nil {
270-
return err
271-
}
272-
defer certFile.Close()
273-
_, err = certFile.Write([]byte(cert))
274-
if err != nil {
275-
return err
276-
}
277-
278-
err = setSSHOwnership()
279-
if err != nil {
280-
return err
281-
}
282-
283-
return nil
284-
}
285-
286261
// PostInit are operations that should be executed against a running Postgres on boot.
287262
func (n *Node) PostInit(ctx context.Context) error {
288263
if ZombieLockExists() {
@@ -529,17 +504,14 @@ func (n *Node) isPGInitialized() bool {
529504
}
530505

531506
func (n *Node) configure(ctx context.Context, store *state.Store) error {
532-
fmt.Println("Initializing internal config")
533507
if err := n.configureInternal(store); err != nil {
534508
return fmt.Errorf("failed to set internal config: %s", err)
535509
}
536510

537-
fmt.Println("Initializing replication manager")
538511
if err := n.configureRepmgr(store); err != nil {
539512
return fmt.Errorf("failed to configure repmgr config: %s", err)
540513
}
541514

542-
fmt.Println("Initializing pgbouncer")
543515
if err := n.configurePGBouncer(store); err != nil {
544516
return fmt.Errorf("failed to configure pgbouncer: %s", err)
545517
}
@@ -553,6 +525,44 @@ func (n *Node) configure(ctx context.Context, store *state.Store) error {
553525
return nil
554526
}
555527

528+
func writeSSHKey() error {
529+
err := os.Mkdir("/data/.ssh", 0700)
530+
if err != nil && !os.IsExist(err) {
531+
return err
532+
}
533+
534+
key := os.Getenv("SSH_KEY")
535+
536+
keyFile, err := os.Create("/data/.ssh/id_rsa")
537+
if err != nil {
538+
return err
539+
}
540+
defer keyFile.Close()
541+
_, err = keyFile.Write([]byte(key))
542+
if err != nil {
543+
return err
544+
}
545+
546+
cert := os.Getenv("SSH_CERT")
547+
548+
certFile, err := os.Create("/data/.ssh/id_rsa-cert.pub")
549+
if err != nil {
550+
return err
551+
}
552+
defer certFile.Close()
553+
_, err = certFile.Write([]byte(cert))
554+
if err != nil {
555+
return err
556+
}
557+
558+
err = setSSHOwnership()
559+
if err != nil {
560+
return err
561+
}
562+
563+
return nil
564+
}
565+
556566
func (n *Node) configureInternal(store *state.Store) error {
557567
if err := n.InternalConfig.initialize(); err != nil {
558568
return fmt.Errorf("failed to initialize internal config: %s", err)

0 commit comments

Comments
 (0)