/
watchdog.go
146 lines (120 loc) · 3.4 KB
/
watchdog.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package watchdog
import (
"errors"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"github.com/buildpacks/libbuildpack/v2/layers"
"github.com/buildpacks/libbuildpack/v2/logger"
)
const (
executableName = "watchdog"
)
type metadata struct {
Version string
}
type HttpClient interface {
Get(url string) (*http.Response, error)
}
type Contributor struct {
log logger.Logger
httpClient HttpClient
}
func NewContributor(log logger.Logger, httpClient HttpClient) *Contributor {
return &Contributor{
log: log,
httpClient: httpClient,
}
}
func (l *Contributor) Contribute(lyrs layers.Layers, conf Config) (*layers.Layer, error) {
watchdogLayer := lyrs.Layer(executableName)
if err := l.installBinaries(watchdogLayer, conf.Version); err != nil {
return nil, err
}
if err := l.configureApp(lyrs, watchdogLayer, conf.ProcessType); err != nil {
return nil, err
}
return &watchdogLayer, nil
}
func (l *Contributor) installBinaries(watchdogLayer layers.Layer, version string) error {
wdMD := &metadata{}
if err := watchdogLayer.ReadMetadata(wdMD); err != nil {
return errors.New("read metadata: " + err.Error())
}
switch {
case wdMD.Version == version:
l.log.Debug("using cache")
case wdMD.Version != "":
if err := watchdogLayer.RemoveMetadata(); err != nil {
return errors.New("removing old metadata: " + err.Error())
}
fallthrough
default:
if err := l.downloadWatchdog(version, watchdogLayer.Root); err != nil {
return errors.New("downloading binary: " + err.Error())
}
}
wdMD.Version = version
if err := watchdogLayer.WriteMetadata(&wdMD, layers.Cache, layers.Launch); err != nil {
return errors.New("writing metadata: " + err.Error())
}
return nil
}
// configureApp configures the application
func (l *Contributor) configureApp(lyrs layers.Layers, watchdogLayer layers.Layer, processType string) error {
err := watchdogLayer.DefaultLaunchEnv("function_process", fmt.Sprintf("/cnb/lifecycle/launcher %s", processType))
if err != nil {
return errors.New("writing function_process env var: " + err.Error())
}
err = lyrs.WriteApplicationMetadata(layers.Metadata{
Processes: []layers.Process{{
Type: "faas",
Command: filepath.Join(watchdogLayer.Root, executableName),
Args: nil,
Direct: false,
}},
Slices: nil,
})
if err != nil {
return errors.New("writing app metadata file: " + err.Error())
}
return nil
}
func (l *Contributor) downloadWatchdog(version string, layerDir string) error {
downloadUrl := fmt.Sprintf(
"https://github.com/openfaas-incubator/of-watchdog/releases/download/%s/of-watchdog",
version,
)
l.log.Debug("downloading from: %s", downloadUrl)
resp, err := l.httpClient.Get(downloadUrl)
if err != nil {
return err
}
defer func() {
_ = resp.Body.Close()
}()
if resp.StatusCode != 200 {
return fmt.Errorf("downloading from '%s' returned status code '%d'", downloadUrl, resp.StatusCode)
}
err = os.MkdirAll(layerDir, os.ModePerm)
if err != nil {
return errors.New("creating layer dir: " + err.Error())
}
watchdogBin, err := os.Create(filepath.Join(layerDir, executableName))
if err != nil {
return errors.New("creating binary: " + err.Error())
}
defer func() {
_ = watchdogBin.Close()
}()
_, err = io.Copy(watchdogBin, resp.Body)
if err != nil {
return errors.New("downloading watchdog: " + err.Error())
}
if err := os.Chmod(watchdogBin.Name(), os.ModePerm); err != nil {
return err
}
return nil
}