-
Notifications
You must be signed in to change notification settings - Fork 41
/
utils.go
115 lines (98 loc) · 2.42 KB
/
utils.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
package cli
import (
"crypto/rand"
"fmt"
"math"
"math/big"
"regexp"
"strings"
"time"
"github.com/1Password/connect-sdk-go/onepassword"
)
type opArg interface {
format() string
}
type opFlag struct {
name string
value string
}
func (f opFlag) format() string {
return fmt.Sprintf("--%s=%s", f.name, f.value)
}
func f(name, value string) opArg {
return opFlag{name: name, value: value}
}
type opParam struct {
value string
}
func (p opParam) format() string {
return p.value
}
func p(value string) opArg {
return opParam{value: value}
}
var cliErrorRegex = regexp.MustCompile(`(?m)^\[ERROR] (\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}) (.+)$`)
func parseCliError(stderr []byte) error {
subMatches := cliErrorRegex.FindStringSubmatch(string(stderr))
if len(subMatches) != 3 {
return fmt.Errorf("unkown op error: %s", string(stderr))
}
return fmt.Errorf("op error: %s", subMatches[2])
}
func passwordField(item *onepassword.Item) *onepassword.ItemField {
for _, f := range item.Fields {
if f.Purpose == onepassword.FieldPurposePassword {
return f
}
}
return nil
}
func passwordRecipe(item *onepassword.Item) string {
if pf := passwordField(item); pf != nil {
return passwordRecipeToString(pf.Recipe)
}
return ""
}
func passwordRecipeToString(recipe *onepassword.GeneratorRecipe) string {
str := ""
if recipe != nil {
str += strings.Join(recipe.CharacterSets, ",")
if recipe.Length > 0 {
if str == "" {
str += fmt.Sprintf("%d", recipe.Length)
} else {
str += fmt.Sprintf(",%d", recipe.Length)
}
}
}
return str
}
// waitBeforeRetry waits some amount of time based on retryAttempt
// it implements 'exponential backoff with jitter' algorithm
func waitBeforeRetry(retryAttempts int) {
randInt, err := rand.Int(rand.Reader, big.NewInt(100))
if err != nil {
randInt = big.NewInt(0)
}
randPercentage := float64(randInt.Int64()) / 100
jitter := (1.0 + randPercentage) / 2
exp := math.Pow(2, float64(retryAttempts))
retryTimeMilliseconds := 100 + 500*exp*jitter
wait := time.Duration(retryTimeMilliseconds) * time.Millisecond
time.Sleep(wait)
}
func makeBuildVersion(version string) string {
parts := strings.Split(strings.ReplaceAll(version, "-beta", ""), ".")
buildVersion := parts[0]
for i := 1; i < len(parts); i++ {
if len(parts[i]) == 1 {
buildVersion += "0" + parts[i]
} else {
buildVersion += parts[i]
}
}
if len(parts) != 3 {
return buildVersion
}
return buildVersion + "01"
}