This repository has been archived by the owner on Oct 24, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
syscfg.go
129 lines (110 loc) · 2.53 KB
/
syscfg.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
// Package syscfg is the base module for this subsystem.
package syscfg
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io/fs"
"os"
"path"
"sync/atomic"
"time"
errw "github.com/pkg/errors"
)
var (
// versions embedded at build time.
Version = ""
GitRevision = ""
)
// GetVersion returns the version embedded at build time.
func GetVersion() string {
if Version == "" {
return "custom"
}
return Version
}
// GetRevision returns the git revision embedded at build time.
func GetRevision() string {
if GitRevision == "" {
return "unknown"
}
return GitRevision
}
type Config struct {
Logging LogConfig `json:"logging"`
Upgrades UpgradesConfig `json:"upgrades"`
}
func LoadConfig(path string) (*Config, error) {
//nolint:gosec
jsonBytes, err := os.ReadFile(path)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return &Config{}, nil
}
return &Config{}, err
}
newConfig := &Config{}
if err = json.Unmarshal(jsonBytes, newConfig); err != nil {
return &Config{}, err
}
return newConfig, nil
}
func writeFileIfNew(outPath string, data []byte) (bool, error) {
//nolint:gosec
curFileBytes, err := os.ReadFile(outPath)
if err != nil {
if !errw.Is(err, fs.ErrNotExist) {
return false, errw.Wrapf(err, "opening %s for reading", outPath)
}
} else if bytes.Equal(curFileBytes, data) {
return false, nil
}
//nolint:gosec
if err := os.MkdirAll(path.Dir(outPath), 0o755); err != nil {
return true, errw.Wrapf(err, "creating directory for %s", outPath)
}
//nolint:gosec
if err := os.WriteFile(outPath, data, 0o644); err != nil {
return true, errw.Wrapf(err, "writing %s", outPath)
}
return true, nil
}
type ContextKey string
const HCReqKey = ContextKey("healthcheck")
// HealthySleep allows a process to sleep while stil responding to context cancellation AND healthchecks. Returns false if cancelled.
func HealthySleep(ctx context.Context, timeout time.Duration) bool {
hc, ok := ctx.Value(HCReqKey).(*atomic.Bool)
if !ok {
// this should never happen, so avoiding having to pass a logger by just printing
//nolint:forbidigo
fmt.Println("context passed to HealthySleep without healthcheck value")
}
stop := &atomic.Bool{}
defer stop.Store(true)
go func() {
for {
if hc.Swap(false) {
//nolint:forbidigo
fmt.Println("HEALTHY")
}
if stop.Load() {
return
}
select {
case <-ctx.Done():
return
case <-time.After(time.Second):
}
}
}()
for {
select {
case <-ctx.Done():
return false
case <-time.After(timeout):
return true
}
}
}