This repository has been archived by the owner on Jan 19, 2022. It is now read-only.
/
names.go
173 lines (148 loc) · 4.83 KB
/
names.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Package names has helpers for naming resources and generating strings
package names
import (
"crypto/md5"
"crypto/rand"
"encoding/hex"
"fmt"
"hash/fnv"
"regexp"
"strconv"
"strings"
"github.com/pkg/errors"
)
const (
// ConfigMap is used in log messages
ConfigMap = "configmap"
// Secret is used in log messages
Secret = "secret"
)
var allowedDNSLabelChars = regexp.MustCompile("[^-a-z0-9]*")
// DNSLabelSafe filters invalid characters and returns a string that is safe to use as a DNS label.
// It does not enforce the required string length, see `Sanitize`.
//
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names
func DNSLabelSafe(name string) string {
name = strings.Replace(name, "_", "-", -1)
name = strings.ToLower(name)
name = allowedDNSLabelChars.ReplaceAllLiteralString(name, "")
name = strings.TrimLeft(name, "-")
name = strings.TrimRight(name, "-")
return name
}
// Sanitize produces valid k8s names, i.e. for containers: [a-z0-9]([-a-z0-9]*[a-z0-9])?
// The result is DNS label compatible and usable as a path segment name.
//
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names
func Sanitize(name string) string {
name = DNSLabelSafe(name)
return TruncateMD5(name, 63)
}
var allowedDNSSubdomainChars = regexp.MustCompile("[^-.a-z0-9]*")
// SanitizeSubdomain allows more than Sanitize, cannot be used for DNS or path segments.
//
// https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-subdomain-names
func SanitizeSubdomain(name string) string {
name = strings.Replace(name, "_", "-", -1)
name = strings.ToLower(name)
name = allowedDNSSubdomainChars.ReplaceAllLiteralString(name, "")
name = strings.TrimPrefix(name, "-")
name = strings.TrimSuffix(name, "-")
name = strings.TrimPrefix(name, ".")
name = strings.TrimSuffix(name, ".")
name = TruncateMD5(name, 253)
return name
}
// GetStatefulSetName gets statefulset name from podName
func GetStatefulSetName(name string) string {
nameSplit := strings.Split(name, "-")
nameSplit = nameSplit[0 : len(nameSplit)-1]
statefulSetName := strings.Join(nameSplit, "-")
return statefulSetName
}
// JobName returns a unique, short name for a given eJob k8s allows 63 chars,
// but the job's pod will have -\d{6} (=7 chars) appended. So we return max 56
// chars: name39-suffix16
func JobName(eJobName string) (string, error) {
name := truncate(eJobName, 39)
hashID, err := randSuffix(name)
if err != nil {
return "", errors.Wrapf(err, "could not randomize job suffix for name %s", name)
}
return fmt.Sprintf("%s-%s", name, hashID), nil
}
// VolumeName generate volume name based on secret name
func VolumeName(secretName string) string {
nameSlices := strings.Split(secretName, ".")
volName := ""
if len(nameSlices) > 1 {
volName = nameSlices[1]
} else {
volName = nameSlices[0]
}
return Sanitize(volName)
}
var podOrdinalRegex = regexp.MustCompile(`(.*)-([0-9]+)$`)
// OrdinalFromPodName returns ordinal from pod name
func OrdinalFromPodName(name string) int {
podOrdinal := -1
match := podOrdinalRegex.FindStringSubmatch(name)
if len(match) < 3 {
return podOrdinal
}
if i, err := strconv.ParseInt(match[2], 10, 32); err == nil {
podOrdinal = int(i)
}
return podOrdinal
}
// CSRName returns a CertificateSigningRequest name for a given QuarksJob
func CSRName(namespace, quarksSecretName string) string {
return fmt.Sprintf("%s-%s", truncate(namespace, 19), Sanitize(truncate(quarksSecretName, 19)))
}
// CsrPrivateKeySecretName returns a Secret name for a given CertificateSigningRequest private key
func CsrPrivateKeySecretName(csrName string) string {
return csrName + "-csr-private-key"
}
func randSuffix(str string) (string, error) {
randBytes := make([]byte, 16)
_, err := rand.Read(randBytes)
if err != nil {
return "", errors.Wrap(err, "could not read rand bytes")
}
a := fnv.New64()
_, err = a.Write([]byte(str + string(randBytes)))
if err != nil {
return "", errors.Wrapf(err, "could not write hash for str %s", str)
}
return hex.EncodeToString(a.Sum(nil)), nil
}
func truncate(name string, max int) string {
if len(name) > max {
return name[0:max]
}
return name
}
// TruncateMD5 truncates the string to n chars and adds a hex encoded md5
// sum. Producing a uniq representation of the original string, if maxLen >= 32.
// Example: names are limited to 63 characters so we recalculate the name as
// <name trimmed to 30 characters>-<md5 hash of name>
func TruncateMD5(s string, maxLen int) string {
if len(s) <= maxLen {
return s
}
sumHex := md5.Sum([]byte(s))
sum := hex.EncodeToString(sumHex[:]) // 32 chars
suffix := "-" + sum
suffixLen := 33
// enough space for suffix?
if maxLen < suffixLen {
return sum[:maxLen]
}
if maxLen == suffixLen {
return sum
}
// s > maxLen now
// maxLen > 33 now
last := maxLen - suffixLen
return s[:last] + suffix
}