-
Notifications
You must be signed in to change notification settings - Fork 4.9k
/
Copy pathutils.go
165 lines (146 loc) · 4.71 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
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
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package util
import (
"fmt"
"os"
"os/user"
"path/filepath"
"regexp"
"strconv"
"strings"
"github.com/blang/semver/v4"
units "github.com/docker/go-units"
"github.com/pkg/errors"
)
const (
downloadURL = "https://storage.googleapis.com/minikube/releases/%s/minikube-%s-%s%s"
)
// CalculateSizeInMB returns the number of MB in the human readable string
func CalculateSizeInMB(humanReadableSize string) (int, error) {
_, err := strconv.ParseInt(humanReadableSize, 10, 64)
if err == nil {
humanReadableSize += "mb"
}
// parse the size suffix binary instead of decimal so that 1G -> 1024MB instead of 1000MB
size, err := units.RAMInBytes(humanReadableSize)
if err != nil {
return 0, fmt.Errorf("FromHumanSize: %v", err)
}
return int(size / units.MiB), nil
}
// ConvertMBToBytes converts MB to bytes
func ConvertMBToBytes(mbSize int) int64 {
return int64(mbSize) * units.MiB
}
// ConvertBytesToMB converts bytes to MB
func ConvertBytesToMB(byteSize int64) int {
return int(ConvertUnsignedBytesToMB(uint64(byteSize)))
}
// ConvertUnsignedBytesToMB converts bytes to MB
func ConvertUnsignedBytesToMB(byteSize uint64) int64 {
return int64(byteSize / units.MiB)
}
// GetBinaryDownloadURL returns a suitable URL for the platform and arch
func GetBinaryDownloadURL(version, platform, arch string) string {
switch platform {
case "windows":
return fmt.Sprintf(downloadURL, version, platform, arch, ".exe")
default:
return fmt.Sprintf(downloadURL, version, platform, arch, "")
}
}
// ChownR does a recursive os.Chown
func ChownR(path string, uid, gid int) error {
return filepath.Walk(path, func(name string, _ os.FileInfo, err error) error {
if err == nil {
err = os.Chown(name, uid, gid)
}
return err
})
}
// MaybeChownDirRecursiveToMinikubeUser changes ownership of a dir, if requested
func MaybeChownDirRecursiveToMinikubeUser(dir string) error {
if os.Getenv("CHANGE_MINIKUBE_NONE_USER") != "" && os.Getenv("SUDO_USER") != "" {
username := os.Getenv("SUDO_USER")
usr, err := user.Lookup(username)
if err != nil {
return errors.Wrap(err, "Error looking up user")
}
uid, err := strconv.Atoi(usr.Uid)
if err != nil {
return errors.Wrapf(err, "Error parsing uid for user: %s", username)
}
gid, err := strconv.Atoi(usr.Gid)
if err != nil {
return errors.Wrapf(err, "Error parsing gid for user: %s", username)
}
if err := ChownR(dir, uid, gid); err != nil {
return errors.Wrapf(err, "Error changing ownership for: %s", dir)
}
}
return nil
}
// ParseKubernetesVersion parses the Kubernetes version
func ParseKubernetesVersion(version string) (semver.Version, error) {
return semver.Make(version[1:])
}
// RemoveDuplicateStrings takes a string slice and returns a slice without duplicates
func RemoveDuplicateStrings(initial []string) []string {
var result []string
m := make(map[string]bool, len(initial))
for _, v := range initial {
if _, ok := m[v]; ok {
continue
}
m[v] = true
result = append(result, v)
}
return result
}
// MaskProxyPassword masks the password in a proxy URL
func MaskProxyPassword(proxyURL string) string {
// Proxy variable values SHOULD have a value like
// https(s)://<whatever>
parts := strings.Split(proxyURL, "://")
if len(parts) == 2 {
proxyAddress := parts[1]
// Let's store the username, the URL and an optional port address
pattern := `([^:]+):.+(@[\w\.]+)(:\d+)?`
re := regexp.MustCompile(pattern)
matches := re.FindStringSubmatch(proxyAddress)
mask := "*****"
switch len(matches) {
case 4:
return fmt.Sprintf("%s://%s:%s%s%s", parts[0], matches[1], mask, matches[2], matches[3])
case 3:
return fmt.Sprintf("%s//%s:%s@%s", parts[0], matches[1], mask, matches[2])
}
}
return proxyURL
}
// MaskProxyPasswordWithKey masks the password in a proxy URL specified by a key-value pair
func MaskProxyPasswordWithKey(v string) string {
parts := strings.Split(v, "=")
// Is it an attribution variable?
if len(parts) == 2 {
key := strings.ToUpper(parts[0])
// Is it a proxy setting?
if key == "HTTP_PROXY" || key == "HTTPS_PROXY" {
proxyValue := parts[1]
maskedProxyValue := MaskProxyPassword(proxyValue)
return key + "=" + maskedProxyValue
}
}
return v
}