forked from fergusstrange/embedded-postgres
-
Notifications
You must be signed in to change notification settings - Fork 0
/
remote_fetch.go
96 lines (86 loc) · 2.54 KB
/
remote_fetch.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package embeddedpostgres
import (
"archive/zip"
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/mholt/archiver/v3"
)
// RemoteFetchStrategy provides a strategy to fetch a Postgres binary so that it is available for use.
type RemoteFetchStrategy func() error
func defaultRemoteFetchStrategy(remoteFetchHost string, versionStrategy VersionStrategy, cacheLocator CacheLocator) RemoteFetchStrategy {
return func() error {
operatingSystem, architecture, version := versionStrategy()
downloadURL := fmt.Sprintf("%s/maven2/io/zonky/test/postgres/embedded-postgres-binaries-%s-%s/%s/embedded-postgres-binaries-%s-%s-%s.jar",
remoteFetchHost,
operatingSystem,
architecture,
version,
operatingSystem,
architecture,
version)
resp, err := http.Get(downloadURL)
if err != nil {
return fmt.Errorf("unable to connect to %s", remoteFetchHost)
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("no version found matching %s", version)
}
defer func() {
if err := resp.Body.Close(); err != nil {
log.Fatal(err)
}
}()
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return errorFetchingPostgres(err)
}
zipFile := archiver.NewZip()
if err := zipFile.Open(bytes.NewReader(bodyBytes), resp.ContentLength); err != nil {
return errorFetchingPostgres(err)
}
defer func() {
if err := zipFile.Close(); err != nil {
log.Fatal(err)
}
}()
for {
downloadedArchive, err := zipFile.Read()
if err != nil {
return errorExtractingBinary(downloadURL)
}
if header, ok := downloadedArchive.Header.(zip.FileHeader); !ok || !strings.HasSuffix(header.Name, ".txz") {
continue
}
downloadedArchiveBytes, err := ioutil.ReadAll(downloadedArchive)
if err == nil {
cacheLocation, _ := cacheLocator()
if err := createArchiveFile(cacheLocation, downloadedArchiveBytes); err != nil {
return fmt.Errorf("unable to extract postgres archive to %s", cacheLocation)
}
break
}
}
return nil
}
}
func errorExtractingBinary(downloadURL string) error {
return fmt.Errorf("error fetching postgres: cannot find binary in archive retrieved from %s", downloadURL)
}
func errorFetchingPostgres(err error) error {
return fmt.Errorf("error fetching postgres: %s", err)
}
func createArchiveFile(archiveLocation string, archiveBytes []byte) error {
if err := os.MkdirAll(filepath.Dir(archiveLocation), 0755); err != nil {
return err
}
if err := ioutil.WriteFile(archiveLocation, archiveBytes, 0666); err != nil {
return err
}
return nil
}