git subrepo clone (merge) https://github.com/kubernetes-incubator/metrics-server.git metrics-server
subrepo:
subdir: "metrics-server"
merged: "92d8412"
upstream:
origin: "https://github.com/kubernetes-incubator/metrics-server.git"
branch: "master"
commit: "92d8412"
git-subrepo:
version: "0.4.0"
origin: "???"
commit: "???"
diff --git a/metrics-server/vendor/k8s.io/client-go/util/buffer/ring_growing.go b/metrics-server/vendor/k8s.io/client-go/util/buffer/ring_growing.go
new file mode 100644
index 0000000..86965a5
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/buffer/ring_growing.go
@@ -0,0 +1,72 @@
+/*
+Copyright 2017 The Kubernetes Authors.
+
+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 buffer
+
+// RingGrowing is a growing ring buffer.
+// Not thread safe.
+type RingGrowing struct {
+ data []interface{}
+ n int // Size of Data
+ beg int // First available element
+ readable int // Number of data items available
+}
+
+// NewRingGrowing constructs a new RingGrowing instance with provided parameters.
+func NewRingGrowing(initialSize int) *RingGrowing {
+ return &RingGrowing{
+ data: make([]interface{}, initialSize),
+ n: initialSize,
+ }
+}
+
+// ReadOne reads (consumes) first item from the buffer if it is available, otherwise returns false.
+func (r *RingGrowing) ReadOne() (data interface{}, ok bool) {
+ if r.readable == 0 {
+ return nil, false
+ }
+ r.readable--
+ element := r.data[r.beg]
+ r.data[r.beg] = nil // Remove reference to the object to help GC
+ if r.beg == r.n-1 {
+ // Was the last element
+ r.beg = 0
+ } else {
+ r.beg++
+ }
+ return element, true
+}
+
+// WriteOne adds an item to the end of the buffer, growing it if it is full.
+func (r *RingGrowing) WriteOne(data interface{}) {
+ if r.readable == r.n {
+ // Time to grow
+ newN := r.n * 2
+ newData := make([]interface{}, newN)
+ to := r.beg + r.readable
+ if to <= r.n {
+ copy(newData, r.data[r.beg:to])
+ } else {
+ copied := copy(newData, r.data[r.beg:])
+ copy(newData[copied:], r.data[:(to%r.n)])
+ }
+ r.beg = 0
+ r.data = newData
+ r.n = newN
+ }
+ r.data[(r.readable+r.beg)%r.n] = data
+ r.readable++
+}
diff --git a/metrics-server/vendor/k8s.io/client-go/util/cert/cert.go b/metrics-server/vendor/k8s.io/client-go/util/cert/cert.go
new file mode 100644
index 0000000..fb7f5fa
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/cert/cert.go
@@ -0,0 +1,245 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+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 cert
+
+import (
+ "bytes"
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ cryptorand "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "math"
+ "math/big"
+ "net"
+ "time"
+)
+
+const (
+ rsaKeySize = 2048
+ duration365d = time.Hour * 24 * 365
+)
+
+// Config contains the basic fields required for creating a certificate
+type Config struct {
+ CommonName string
+ Organization []string
+ AltNames AltNames
+ Usages []x509.ExtKeyUsage
+}
+
+// AltNames contains the domain names and IP addresses that will be added
+// to the API Server's x509 certificate SubAltNames field. The values will
+// be passed directly to the x509.Certificate object.
+type AltNames struct {
+ DNSNames []string
+ IPs []net.IP
+}
+
+// NewPrivateKey creates an RSA private key
+func NewPrivateKey() (*rsa.PrivateKey, error) {
+ return rsa.GenerateKey(cryptorand.Reader, rsaKeySize)
+}
+
+// NewSelfSignedCACert creates a CA certificate
+func NewSelfSignedCACert(cfg Config, key *rsa.PrivateKey) (*x509.Certificate, error) {
+ now := time.Now()
+ tmpl := x509.Certificate{
+ SerialNumber: new(big.Int).SetInt64(0),
+ Subject: pkix.Name{
+ CommonName: cfg.CommonName,
+ Organization: cfg.Organization,
+ },
+ NotBefore: now.UTC(),
+ NotAfter: now.Add(duration365d * 10).UTC(),
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+ BasicConstraintsValid: true,
+ IsCA: true,
+ }
+
+ certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &tmpl, &tmpl, key.Public(), key)
+ if err != nil {
+ return nil, err
+ }
+ return x509.ParseCertificate(certDERBytes)
+}
+
+// NewSignedCert creates a signed certificate using the given CA certificate and key
+func NewSignedCert(cfg Config, key *rsa.PrivateKey, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, error) {
+ serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64))
+ if err != nil {
+ return nil, err
+ }
+ if len(cfg.CommonName) == 0 {
+ return nil, errors.New("must specify a CommonName")
+ }
+ if len(cfg.Usages) == 0 {
+ return nil, errors.New("must specify at least one ExtKeyUsage")
+ }
+
+ certTmpl := x509.Certificate{
+ Subject: pkix.Name{
+ CommonName: cfg.CommonName,
+ Organization: cfg.Organization,
+ },
+ DNSNames: cfg.AltNames.DNSNames,
+ IPAddresses: cfg.AltNames.IPs,
+ SerialNumber: serial,
+ NotBefore: caCert.NotBefore,
+ NotAfter: time.Now().Add(duration365d).UTC(),
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: cfg.Usages,
+ }
+ certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &certTmpl, caCert, key.Public(), caKey)
+ if err != nil {
+ return nil, err
+ }
+ return x509.ParseCertificate(certDERBytes)
+}
+
+// MakeEllipticPrivateKeyPEM creates an ECDSA private key
+func MakeEllipticPrivateKeyPEM() ([]byte, error) {
+ privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader)
+ if err != nil {
+ return nil, err
+ }
+
+ derBytes, err := x509.MarshalECPrivateKey(privateKey)
+ if err != nil {
+ return nil, err
+ }
+
+ privateKeyPemBlock := &pem.Block{
+ Type: ECPrivateKeyBlockType,
+ Bytes: derBytes,
+ }
+ return pem.EncodeToMemory(privateKeyPemBlock), nil
+}
+
+// GenerateSelfSignedCertKey creates a self-signed certificate and key for the given host.
+// Host may be an IP or a DNS name
+// You may also specify additional subject alt names (either ip or dns names) for the certificate
+func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS []string) ([]byte, []byte, error) {
+ caKey, err := rsa.GenerateKey(cryptorand.Reader, 2048)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ caTemplate := x509.Certificate{
+ SerialNumber: big.NewInt(1),
+ Subject: pkix.Name{
+ CommonName: fmt.Sprintf("%s-ca@%d", host, time.Now().Unix()),
+ },
+ NotBefore: time.Now(),
+ NotAfter: time.Now().Add(time.Hour * 24 * 365),
+
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
+ BasicConstraintsValid: true,
+ IsCA: true,
+ }
+
+ caDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &caTemplate, &caTemplate, &caKey.PublicKey, caKey)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ caCertificate, err := x509.ParseCertificate(caDERBytes)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ priv, err := rsa.GenerateKey(cryptorand.Reader, 2048)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ template := x509.Certificate{
+ SerialNumber: big.NewInt(2),
+ Subject: pkix.Name{
+ CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()),
+ },
+ NotBefore: time.Now(),
+ NotAfter: time.Now().Add(time.Hour * 24 * 365),
+
+ KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+ BasicConstraintsValid: true,
+ }
+
+ if ip := net.ParseIP(host); ip != nil {
+ template.IPAddresses = append(template.IPAddresses, ip)
+ } else {
+ template.DNSNames = append(template.DNSNames, host)
+ }
+
+ template.IPAddresses = append(template.IPAddresses, alternateIPs...)
+ template.DNSNames = append(template.DNSNames, alternateDNS...)
+
+ derBytes, err := x509.CreateCertificate(cryptorand.Reader, &template, caCertificate, &priv.PublicKey, caKey)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // Generate cert, followed by ca
+ certBuffer := bytes.Buffer{}
+ if err := pem.Encode(&certBuffer, &pem.Block{Type: CertificateBlockType, Bytes: derBytes}); err != nil {
+ return nil, nil, err
+ }
+ if err := pem.Encode(&certBuffer, &pem.Block{Type: CertificateBlockType, Bytes: caDERBytes}); err != nil {
+ return nil, nil, err
+ }
+
+ // Generate key
+ keyBuffer := bytes.Buffer{}
+ if err := pem.Encode(&keyBuffer, &pem.Block{Type: RSAPrivateKeyBlockType, Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
+ return nil, nil, err
+ }
+
+ return certBuffer.Bytes(), keyBuffer.Bytes(), nil
+}
+
+// FormatBytesCert receives byte array certificate and formats in human-readable format
+func FormatBytesCert(cert []byte) (string, error) {
+ block, _ := pem.Decode(cert)
+ c, err := x509.ParseCertificate(block.Bytes)
+ if err != nil {
+ return "", fmt.Errorf("failed to parse certificate [%v]", err)
+ }
+ return FormatCert(c), nil
+}
+
+// FormatCert receives certificate and formats in human-readable format
+func FormatCert(c *x509.Certificate) string {
+ var ips []string
+ for _, ip := range c.IPAddresses {
+ ips = append(ips, ip.String())
+ }
+ altNames := append(ips, c.DNSNames...)
+ res := fmt.Sprintf(
+ "Issuer: CN=%s | Subject: CN=%s | CA: %t\n",
+ c.Issuer.CommonName, c.Subject.CommonName, c.IsCA,
+ )
+ res += fmt.Sprintf("Not before: %s Not After: %s", c.NotBefore, c.NotAfter)
+ if len(altNames) > 0 {
+ res += fmt.Sprintf("\nAlternate Names: %v", altNames)
+ }
+ return res
+}
diff --git a/metrics-server/vendor/k8s.io/client-go/util/cert/csr.go b/metrics-server/vendor/k8s.io/client-go/util/cert/csr.go
new file mode 100644
index 0000000..39a6751
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/cert/csr.go
@@ -0,0 +1,75 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+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 cert
+
+import (
+ cryptorand "crypto/rand"
+ "crypto/rsa"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "net"
+)
+
+// MakeCSR generates a PEM-encoded CSR using the supplied private key, subject, and SANs.
+// All key types that are implemented via crypto.Signer are supported (This includes *rsa.PrivateKey and *ecdsa.PrivateKey.)
+func MakeCSR(privateKey interface{}, subject *pkix.Name, dnsSANs []string, ipSANs []net.IP) (csr []byte, err error) {
+ template := &x509.CertificateRequest{
+ Subject: *subject,
+ DNSNames: dnsSANs,
+ IPAddresses: ipSANs,
+ }
+
+ return MakeCSRFromTemplate(privateKey, template)
+}
+
+// MakeCSRFromTemplate generates a PEM-encoded CSR using the supplied private
+// key and certificate request as a template. All key types that are
+// implemented via crypto.Signer are supported (This includes *rsa.PrivateKey
+// and *ecdsa.PrivateKey.)
+func MakeCSRFromTemplate(privateKey interface{}, template *x509.CertificateRequest) ([]byte, error) {
+ t := *template
+ t.SignatureAlgorithm = sigType(privateKey)
+
+ csrDER, err := x509.CreateCertificateRequest(cryptorand.Reader, &t, privateKey)
+ if err != nil {
+ return nil, err
+ }
+
+ csrPemBlock := &pem.Block{
+ Type: CertificateRequestBlockType,
+ Bytes: csrDER,
+ }
+
+ return pem.EncodeToMemory(csrPemBlock), nil
+}
+
+func sigType(privateKey interface{}) x509.SignatureAlgorithm {
+ // Customize the signature for RSA keys, depending on the key size
+ if privateKey, ok := privateKey.(*rsa.PrivateKey); ok {
+ keySize := privateKey.N.BitLen()
+ switch {
+ case keySize >= 4096:
+ return x509.SHA512WithRSA
+ case keySize >= 3072:
+ return x509.SHA384WithRSA
+ default:
+ return x509.SHA256WithRSA
+ }
+ }
+ return x509.UnknownSignatureAlgorithm
+}
diff --git a/metrics-server/vendor/k8s.io/client-go/util/cert/io.go b/metrics-server/vendor/k8s.io/client-go/util/cert/io.go
new file mode 100644
index 0000000..a57bf09
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/cert/io.go
@@ -0,0 +1,193 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+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 cert
+
+import (
+ "crypto"
+ "crypto/ecdsa"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+// CanReadCertAndKey returns true if the certificate and key files already exists,
+// otherwise returns false. If lost one of cert and key, returns error.
+func CanReadCertAndKey(certPath, keyPath string) (bool, error) {
+ certReadable := canReadFile(certPath)
+ keyReadable := canReadFile(keyPath)
+
+ if certReadable == false && keyReadable == false {
+ return false, nil
+ }
+
+ if certReadable == false {
+ return false, fmt.Errorf("error reading %s, certificate and key must be supplied as a pair", certPath)
+ }
+
+ if keyReadable == false {
+ return false, fmt.Errorf("error reading %s, certificate and key must be supplied as a pair", keyPath)
+ }
+
+ return true, nil
+}
+
+// If the file represented by path exists and
+// readable, returns true otherwise returns false.
+func canReadFile(path string) bool {
+ f, err := os.Open(path)
+ if err != nil {
+ return false
+ }
+
+ defer f.Close()
+
+ return true
+}
+
+// WriteCert writes the pem-encoded certificate data to certPath.
+// The certificate file will be created with file mode 0644.
+// If the certificate file already exists, it will be overwritten.
+// The parent directory of the certPath will be created as needed with file mode 0755.
+func WriteCert(certPath string, data []byte) error {
+ if err := os.MkdirAll(filepath.Dir(certPath), os.FileMode(0755)); err != nil {
+ return err
+ }
+ return ioutil.WriteFile(certPath, data, os.FileMode(0644))
+}
+
+// WriteKey writes the pem-encoded key data to keyPath.
+// The key file will be created with file mode 0600.
+// If the key file already exists, it will be overwritten.
+// The parent directory of the keyPath will be created as needed with file mode 0755.
+func WriteKey(keyPath string, data []byte) error {
+ if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil {
+ return err
+ }
+ return ioutil.WriteFile(keyPath, data, os.FileMode(0600))
+}
+
+// LoadOrGenerateKeyFile looks for a key in the file at the given path. If it
+// can't find one, it will generate a new key and store it there.
+func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err error) {
+ loadedData, err := ioutil.ReadFile(keyPath)
+ // Call verifyKeyData to ensure the file wasn't empty/corrupt.
+ if err == nil && verifyKeyData(loadedData) {
+ return loadedData, false, err
+ }
+ if !os.IsNotExist(err) {
+ return nil, false, fmt.Errorf("error loading key from %s: %v", keyPath, err)
+ }
+
+ generatedData, err := MakeEllipticPrivateKeyPEM()
+ if err != nil {
+ return nil, false, fmt.Errorf("error generating key: %v", err)
+ }
+ if err := WriteKey(keyPath, generatedData); err != nil {
+ return nil, false, fmt.Errorf("error writing key to %s: %v", keyPath, err)
+ }
+ return generatedData, true, nil
+}
+
+// MarshalPrivateKeyToPEM converts a known private key type of RSA or ECDSA to
+// a PEM encoded block or returns an error.
+func MarshalPrivateKeyToPEM(privateKey crypto.PrivateKey) ([]byte, error) {
+ switch t := privateKey.(type) {
+ case *ecdsa.PrivateKey:
+ derBytes, err := x509.MarshalECPrivateKey(t)
+ if err != nil {
+ return nil, err
+ }
+ privateKeyPemBlock := &pem.Block{
+ Type: ECPrivateKeyBlockType,
+ Bytes: derBytes,
+ }
+ return pem.EncodeToMemory(privateKeyPemBlock), nil
+ case *rsa.PrivateKey:
+ return EncodePrivateKeyPEM(t), nil
+ default:
+ return nil, fmt.Errorf("private key is not a recognized type: %T", privateKey)
+ }
+}
+
+// NewPool returns an x509.CertPool containing the certificates in the given PEM-encoded file.
+// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
+func NewPool(filename string) (*x509.CertPool, error) {
+ certs, err := CertsFromFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ pool := x509.NewCertPool()
+ for _, cert := range certs {
+ pool.AddCert(cert)
+ }
+ return pool, nil
+}
+
+// CertsFromFile returns the x509.Certificates contained in the given PEM-encoded file.
+// Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates
+func CertsFromFile(file string) ([]*x509.Certificate, error) {
+ pemBlock, err := ioutil.ReadFile(file)
+ if err != nil {
+ return nil, err
+ }
+ certs, err := ParseCertsPEM(pemBlock)
+ if err != nil {
+ return nil, fmt.Errorf("error reading %s: %s", file, err)
+ }
+ return certs, nil
+}
+
+// PrivateKeyFromFile returns the private key in rsa.PrivateKey or ecdsa.PrivateKey format from a given PEM-encoded file.
+// Returns an error if the file could not be read or if the private key could not be parsed.
+func PrivateKeyFromFile(file string) (interface{}, error) {
+ data, err := ioutil.ReadFile(file)
+ if err != nil {
+ return nil, err
+ }
+ key, err := ParsePrivateKeyPEM(data)
+ if err != nil {
+ return nil, fmt.Errorf("error reading private key file %s: %v", file, err)
+ }
+ return key, nil
+}
+
+// PublicKeysFromFile returns the public keys in rsa.PublicKey or ecdsa.PublicKey format from a given PEM-encoded file.
+// Reads public keys from both public and private key files.
+func PublicKeysFromFile(file string) ([]interface{}, error) {
+ data, err := ioutil.ReadFile(file)
+ if err != nil {
+ return nil, err
+ }
+ keys, err := ParsePublicKeysPEM(data)
+ if err != nil {
+ return nil, fmt.Errorf("error reading public key file %s: %v", file, err)
+ }
+ return keys, nil
+}
+
+// verifyKeyData returns true if the provided data appears to be a valid private key.
+func verifyKeyData(data []byte) bool {
+ if len(data) == 0 {
+ return false
+ }
+ _, err := ParsePrivateKeyPEM(data)
+ return err == nil
+}
diff --git a/metrics-server/vendor/k8s.io/client-go/util/cert/pem.go b/metrics-server/vendor/k8s.io/client-go/util/cert/pem.go
new file mode 100644
index 0000000..b99e366
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/cert/pem.go
@@ -0,0 +1,269 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+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 cert
+
+import (
+ "crypto/ecdsa"
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "errors"
+ "fmt"
+)
+
+const (
+ // ECPrivateKeyBlockType is a possible value for pem.Block.Type.
+ ECPrivateKeyBlockType = "EC PRIVATE KEY"
+ // RSAPrivateKeyBlockType is a possible value for pem.Block.Type.
+ RSAPrivateKeyBlockType = "RSA PRIVATE KEY"
+ // PrivateKeyBlockType is a possible value for pem.Block.Type.
+ PrivateKeyBlockType = "PRIVATE KEY"
+ // PublicKeyBlockType is a possible value for pem.Block.Type.
+ PublicKeyBlockType = "PUBLIC KEY"
+ // CertificateBlockType is a possible value for pem.Block.Type.
+ CertificateBlockType = "CERTIFICATE"
+ // CertificateRequestBlockType is a possible value for pem.Block.Type.
+ CertificateRequestBlockType = "CERTIFICATE REQUEST"
+)
+
+// EncodePublicKeyPEM returns PEM-encoded public data
+func EncodePublicKeyPEM(key *rsa.PublicKey) ([]byte, error) {
+ der, err := x509.MarshalPKIXPublicKey(key)
+ if err != nil {
+ return []byte{}, err
+ }
+ block := pem.Block{
+ Type: PublicKeyBlockType,
+ Bytes: der,
+ }
+ return pem.EncodeToMemory(&block), nil
+}
+
+// EncodePrivateKeyPEM returns PEM-encoded private key data
+func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte {
+ block := pem.Block{
+ Type: RSAPrivateKeyBlockType,
+ Bytes: x509.MarshalPKCS1PrivateKey(key),
+ }
+ return pem.EncodeToMemory(&block)
+}
+
+// EncodeCertPEM returns PEM-endcoded certificate data
+func EncodeCertPEM(cert *x509.Certificate) []byte {
+ block := pem.Block{
+ Type: CertificateBlockType,
+ Bytes: cert.Raw,
+ }
+ return pem.EncodeToMemory(&block)
+}
+
+// ParsePrivateKeyPEM returns a private key parsed from a PEM block in the supplied data.
+// Recognizes PEM blocks for "EC PRIVATE KEY", "RSA PRIVATE KEY", or "PRIVATE KEY"
+func ParsePrivateKeyPEM(keyData []byte) (interface{}, error) {
+ var privateKeyPemBlock *pem.Block
+ for {
+ privateKeyPemBlock, keyData = pem.Decode(keyData)
+ if privateKeyPemBlock == nil {
+ break
+ }
+
+ switch privateKeyPemBlock.Type {
+ case ECPrivateKeyBlockType:
+ // ECDSA Private Key in ASN.1 format
+ if key, err := x509.ParseECPrivateKey(privateKeyPemBlock.Bytes); err == nil {
+ return key, nil
+ }
+ case RSAPrivateKeyBlockType:
+ // RSA Private Key in PKCS#1 format
+ if key, err := x509.ParsePKCS1PrivateKey(privateKeyPemBlock.Bytes); err == nil {
+ return key, nil
+ }
+ case PrivateKeyBlockType:
+ // RSA or ECDSA Private Key in unencrypted PKCS#8 format
+ if key, err := x509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes); err == nil {
+ return key, nil
+ }
+ }
+
+ // tolerate non-key PEM blocks for compatibility with things like "EC PARAMETERS" blocks
+ // originally, only the first PEM block was parsed and expected to be a key block
+ }
+
+ // we read all the PEM blocks and didn't recognize one
+ return nil, fmt.Errorf("data does not contain a valid RSA or ECDSA private key")
+}
+
+// ParsePublicKeysPEM is a helper function for reading an array of rsa.PublicKey or ecdsa.PublicKey from a PEM-encoded byte array.
+// Reads public keys from both public and private key files.
+func ParsePublicKeysPEM(keyData []byte) ([]interface{}, error) {
+ var block *pem.Block
+ keys := []interface{}{}
+ for {
+ // read the next block
+ block, keyData = pem.Decode(keyData)
+ if block == nil {
+ break
+ }
+
+ // test block against parsing functions
+ if privateKey, err := parseRSAPrivateKey(block.Bytes); err == nil {
+ keys = append(keys, &privateKey.PublicKey)
+ continue
+ }
+ if publicKey, err := parseRSAPublicKey(block.Bytes); err == nil {
+ keys = append(keys, publicKey)
+ continue
+ }
+ if privateKey, err := parseECPrivateKey(block.Bytes); err == nil {
+ keys = append(keys, &privateKey.PublicKey)
+ continue
+ }
+ if publicKey, err := parseECPublicKey(block.Bytes); err == nil {
+ keys = append(keys, publicKey)
+ continue
+ }
+
+ // tolerate non-key PEM blocks for backwards compatibility
+ // originally, only the first PEM block was parsed and expected to be a key block
+ }
+
+ if len(keys) == 0 {
+ return nil, fmt.Errorf("data does not contain any valid RSA or ECDSA public keys")
+ }
+ return keys, nil
+}
+
+// ParseCertsPEM returns the x509.Certificates contained in the given PEM-encoded byte array
+// Returns an error if a certificate could not be parsed, or if the data does not contain any certificates
+func ParseCertsPEM(pemCerts []byte) ([]*x509.Certificate, error) {
+ ok := false
+ certs := []*x509.Certificate{}
+ for len(pemCerts) > 0 {
+ var block *pem.Block
+ block, pemCerts = pem.Decode(pemCerts)
+ if block == nil {
+ break
+ }
+ // Only use PEM "CERTIFICATE" blocks without extra headers
+ if block.Type != CertificateBlockType || len(block.Headers) != 0 {
+ continue
+ }
+
+ cert, err := x509.ParseCertificate(block.Bytes)
+ if err != nil {
+ return certs, err
+ }
+
+ certs = append(certs, cert)
+ ok = true
+ }
+
+ if !ok {
+ return certs, errors.New("data does not contain any valid RSA or ECDSA certificates")
+ }
+ return certs, nil
+}
+
+// parseRSAPublicKey parses a single RSA public key from the provided data
+func parseRSAPublicKey(data []byte) (*rsa.PublicKey, error) {
+ var err error
+
+ // Parse the key
+ var parsedKey interface{}
+ if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil {
+ if cert, err := x509.ParseCertificate(data); err == nil {
+ parsedKey = cert.PublicKey
+ } else {
+ return nil, err
+ }
+ }
+
+ // Test if parsed key is an RSA Public Key
+ var pubKey *rsa.PublicKey
+ var ok bool
+ if pubKey, ok = parsedKey.(*rsa.PublicKey); !ok {
+ return nil, fmt.Errorf("data doesn't contain valid RSA Public Key")
+ }
+
+ return pubKey, nil
+}
+
+// parseRSAPrivateKey parses a single RSA private key from the provided data
+func parseRSAPrivateKey(data []byte) (*rsa.PrivateKey, error) {
+ var err error
+
+ // Parse the key
+ var parsedKey interface{}
+ if parsedKey, err = x509.ParsePKCS1PrivateKey(data); err != nil {
+ if parsedKey, err = x509.ParsePKCS8PrivateKey(data); err != nil {
+ return nil, err
+ }
+ }
+
+ // Test if parsed key is an RSA Private Key
+ var privKey *rsa.PrivateKey
+ var ok bool
+ if privKey, ok = parsedKey.(*rsa.PrivateKey); !ok {
+ return nil, fmt.Errorf("data doesn't contain valid RSA Private Key")
+ }
+
+ return privKey, nil
+}
+
+// parseECPublicKey parses a single ECDSA public key from the provided data
+func parseECPublicKey(data []byte) (*ecdsa.PublicKey, error) {
+ var err error
+
+ // Parse the key
+ var parsedKey interface{}
+ if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil {
+ if cert, err := x509.ParseCertificate(data); err == nil {
+ parsedKey = cert.PublicKey
+ } else {
+ return nil, err
+ }
+ }
+
+ // Test if parsed key is an ECDSA Public Key
+ var pubKey *ecdsa.PublicKey
+ var ok bool
+ if pubKey, ok = parsedKey.(*ecdsa.PublicKey); !ok {
+ return nil, fmt.Errorf("data doesn't contain valid ECDSA Public Key")
+ }
+
+ return pubKey, nil
+}
+
+// parseECPrivateKey parses a single ECDSA private key from the provided data
+func parseECPrivateKey(data []byte) (*ecdsa.PrivateKey, error) {
+ var err error
+
+ // Parse the key
+ var parsedKey interface{}
+ if parsedKey, err = x509.ParseECPrivateKey(data); err != nil {
+ return nil, err
+ }
+
+ // Test if parsed key is an ECDSA Private Key
+ var privKey *ecdsa.PrivateKey
+ var ok bool
+ if privKey, ok = parsedKey.(*ecdsa.PrivateKey); !ok {
+ return nil, fmt.Errorf("data doesn't contain valid ECDSA Private Key")
+ }
+
+ return privKey, nil
+}
diff --git a/metrics-server/vendor/k8s.io/client-go/util/connrotation/connrotation.go b/metrics-server/vendor/k8s.io/client-go/util/connrotation/connrotation.go
new file mode 100644
index 0000000..235a9e0
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/connrotation/connrotation.go
@@ -0,0 +1,105 @@
+/*
+Copyright 2018 The Kubernetes Authors.
+
+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 connrotation implements a connection dialer that tracks and can close
+// all created connections.
+//
+// This is used for credential rotation of long-lived connections, when there's
+// no way to re-authenticate on a live connection.
+package connrotation
+
+import (
+ "context"
+ "net"
+ "sync"
+)
+
+// DialFunc is a shorthand for signature of net.DialContext.
+type DialFunc func(ctx context.Context, network, address string) (net.Conn, error)
+
+// Dialer opens connections through Dial and tracks them.
+type Dialer struct {
+ dial DialFunc
+
+ mu sync.Mutex
+ conns map[*closableConn]struct{}
+}
+
+// NewDialer creates a new Dialer instance.
+//
+// If dial is not nil, it will be used to create new underlying connections.
+// Otherwise net.DialContext is used.
+func NewDialer(dial DialFunc) *Dialer {
+ return &Dialer{
+ dial: dial,
+ conns: make(map[*closableConn]struct{}),
+ }
+}
+
+// CloseAll forcibly closes all tracked connections.
+//
+// Note: new connections may get created before CloseAll returns.
+func (d *Dialer) CloseAll() {
+ d.mu.Lock()
+ conns := d.conns
+ d.conns = make(map[*closableConn]struct{})
+ d.mu.Unlock()
+
+ for conn := range conns {
+ conn.Close()
+ }
+}
+
+// Dial creates a new tracked connection.
+func (d *Dialer) Dial(network, address string) (net.Conn, error) {
+ return d.DialContext(context.Background(), network, address)
+}
+
+// DialContext creates a new tracked connection.
+func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
+ conn, err := d.dial(ctx, network, address)
+ if err != nil {
+ return nil, err
+ }
+
+ closable := &closableConn{Conn: conn}
+
+ // Start tracking the connection
+ d.mu.Lock()
+ d.conns[closable] = struct{}{}
+ d.mu.Unlock()
+
+ // When the connection is closed, remove it from the map. This will
+ // be no-op if the connection isn't in the map, e.g. if CloseAll()
+ // is called.
+ closable.onClose = func() {
+ d.mu.Lock()
+ delete(d.conns, closable)
+ d.mu.Unlock()
+ }
+
+ return closable, nil
+}
+
+type closableConn struct {
+ onClose func()
+ net.Conn
+}
+
+func (c *closableConn) Close() error {
+ go c.onClose()
+ return c.Conn.Close()
+}
diff --git a/metrics-server/vendor/k8s.io/client-go/util/flowcontrol/backoff.go b/metrics-server/vendor/k8s.io/client-go/util/flowcontrol/backoff.go
new file mode 100644
index 0000000..71d442a
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/flowcontrol/backoff.go
@@ -0,0 +1,149 @@
+/*
+Copyright 2015 The Kubernetes Authors.
+
+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 flowcontrol
+
+import (
+ "sync"
+ "time"
+
+ "k8s.io/apimachinery/pkg/util/clock"
+ "k8s.io/client-go/util/integer"
+)
+
+type backoffEntry struct {
+ backoff time.Duration
+ lastUpdate time.Time
+}
+
+type Backoff struct {
+ sync.Mutex
+ Clock clock.Clock
+ defaultDuration time.Duration
+ maxDuration time.Duration
+ perItemBackoff map[string]*backoffEntry
+}
+
+func NewFakeBackOff(initial, max time.Duration, tc *clock.FakeClock) *Backoff {
+ return &Backoff{
+ perItemBackoff: map[string]*backoffEntry{},
+ Clock: tc,
+ defaultDuration: initial,
+ maxDuration: max,
+ }
+}
+
+func NewBackOff(initial, max time.Duration) *Backoff {
+ return &Backoff{
+ perItemBackoff: map[string]*backoffEntry{},
+ Clock: clock.RealClock{},
+ defaultDuration: initial,
+ maxDuration: max,
+ }
+}
+
+// Get the current backoff Duration
+func (p *Backoff) Get(id string) time.Duration {
+ p.Lock()
+ defer p.Unlock()
+ var delay time.Duration
+ entry, ok := p.perItemBackoff[id]
+ if ok {
+ delay = entry.backoff
+ }
+ return delay
+}
+
+// move backoff to the next mark, capping at maxDuration
+func (p *Backoff) Next(id string, eventTime time.Time) {
+ p.Lock()
+ defer p.Unlock()
+ entry, ok := p.perItemBackoff[id]
+ if !ok || hasExpired(eventTime, entry.lastUpdate, p.maxDuration) {
+ entry = p.initEntryUnsafe(id)
+ } else {
+ delay := entry.backoff * 2 // exponential
+ entry.backoff = time.Duration(integer.Int64Min(int64(delay), int64(p.maxDuration)))
+ }
+ entry.lastUpdate = p.Clock.Now()
+}
+
+// Reset forces clearing of all backoff data for a given key.
+func (p *Backoff) Reset(id string) {
+ p.Lock()
+ defer p.Unlock()
+ delete(p.perItemBackoff, id)
+}
+
+// Returns True if the elapsed time since eventTime is smaller than the current backoff window
+func (p *Backoff) IsInBackOffSince(id string, eventTime time.Time) bool {
+ p.Lock()
+ defer p.Unlock()
+ entry, ok := p.perItemBackoff[id]
+ if !ok {
+ return false
+ }
+ if hasExpired(eventTime, entry.lastUpdate, p.maxDuration) {
+ return false
+ }
+ return p.Clock.Now().Sub(eventTime) < entry.backoff
+}
+
+// Returns True if time since lastupdate is less than the current backoff window.
+func (p *Backoff) IsInBackOffSinceUpdate(id string, eventTime time.Time) bool {
+ p.Lock()
+ defer p.Unlock()
+ entry, ok := p.perItemBackoff[id]
+ if !ok {
+ return false
+ }
+ if hasExpired(eventTime, entry.lastUpdate, p.maxDuration) {
+ return false
+ }
+ return eventTime.Sub(entry.lastUpdate) < entry.backoff
+}
+
+// Garbage collect records that have aged past maxDuration. Backoff users are expected
+// to invoke this periodically.
+func (p *Backoff) GC() {
+ p.Lock()
+ defer p.Unlock()
+ now := p.Clock.Now()
+ for id, entry := range p.perItemBackoff {
+ if now.Sub(entry.lastUpdate) > p.maxDuration*2 {
+ // GC when entry has not been updated for 2*maxDuration
+ delete(p.perItemBackoff, id)
+ }
+ }
+}
+
+func (p *Backoff) DeleteEntry(id string) {
+ p.Lock()
+ defer p.Unlock()
+ delete(p.perItemBackoff, id)
+}
+
+// Take a lock on *Backoff, before calling initEntryUnsafe
+func (p *Backoff) initEntryUnsafe(id string) *backoffEntry {
+ entry := &backoffEntry{backoff: p.defaultDuration}
+ p.perItemBackoff[id] = entry
+ return entry
+}
+
+// After 2*maxDuration we restart the backoff factor to the beginning
+func hasExpired(eventTime time.Time, lastUpdate time.Time, maxDuration time.Duration) bool {
+ return eventTime.Sub(lastUpdate) > maxDuration*2 // consider stable if it's ok for twice the maxDuration
+}
diff --git a/metrics-server/vendor/k8s.io/client-go/util/flowcontrol/throttle.go b/metrics-server/vendor/k8s.io/client-go/util/flowcontrol/throttle.go
new file mode 100644
index 0000000..e671c04
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/flowcontrol/throttle.go
@@ -0,0 +1,143 @@
+/*
+Copyright 2014 The Kubernetes Authors.
+
+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 flowcontrol
+
+import (
+ "sync"
+ "time"
+
+ "golang.org/x/time/rate"
+)
+
+type RateLimiter interface {
+ // TryAccept returns true if a token is taken immediately. Otherwise,
+ // it returns false.
+ TryAccept() bool
+ // Accept returns once a token becomes available.
+ Accept()
+ // Stop stops the rate limiter, subsequent calls to CanAccept will return false
+ Stop()
+ // QPS returns QPS of this rate limiter
+ QPS() float32
+}
+
+type tokenBucketRateLimiter struct {
+ limiter *rate.Limiter
+ clock Clock
+ qps float32
+}
+
+// NewTokenBucketRateLimiter creates a rate limiter which implements a token bucket approach.
+// The rate limiter allows bursts of up to 'burst' to exceed the QPS, while still maintaining a
+// smoothed qps rate of 'qps'.
+// The bucket is initially filled with 'burst' tokens, and refills at a rate of 'qps'.
+// The maximum number of tokens in the bucket is capped at 'burst'.
+func NewTokenBucketRateLimiter(qps float32, burst int) RateLimiter {
+ limiter := rate.NewLimiter(rate.Limit(qps), burst)
+ return newTokenBucketRateLimiter(limiter, realClock{}, qps)
+}
+
+// An injectable, mockable clock interface.
+type Clock interface {
+ Now() time.Time
+ Sleep(time.Duration)
+}
+
+type realClock struct{}
+
+func (realClock) Now() time.Time {
+ return time.Now()
+}
+func (realClock) Sleep(d time.Duration) {
+ time.Sleep(d)
+}
+
+// NewTokenBucketRateLimiterWithClock is identical to NewTokenBucketRateLimiter
+// but allows an injectable clock, for testing.
+func NewTokenBucketRateLimiterWithClock(qps float32, burst int, c Clock) RateLimiter {
+ limiter := rate.NewLimiter(rate.Limit(qps), burst)
+ return newTokenBucketRateLimiter(limiter, c, qps)
+}
+
+func newTokenBucketRateLimiter(limiter *rate.Limiter, c Clock, qps float32) RateLimiter {
+ return &tokenBucketRateLimiter{
+ limiter: limiter,
+ clock: c,
+ qps: qps,
+ }
+}
+
+func (t *tokenBucketRateLimiter) TryAccept() bool {
+ return t.limiter.AllowN(t.clock.Now(), 1)
+}
+
+// Accept will block until a token becomes available
+func (t *tokenBucketRateLimiter) Accept() {
+ now := t.clock.Now()
+ t.clock.Sleep(t.limiter.ReserveN(now, 1).DelayFrom(now))
+}
+
+func (t *tokenBucketRateLimiter) Stop() {
+}
+
+func (t *tokenBucketRateLimiter) QPS() float32 {
+ return t.qps
+}
+
+type fakeAlwaysRateLimiter struct{}
+
+func NewFakeAlwaysRateLimiter() RateLimiter {
+ return &fakeAlwaysRateLimiter{}
+}
+
+func (t *fakeAlwaysRateLimiter) TryAccept() bool {
+ return true
+}
+
+func (t *fakeAlwaysRateLimiter) Stop() {}
+
+func (t *fakeAlwaysRateLimiter) Accept() {}
+
+func (t *fakeAlwaysRateLimiter) QPS() float32 {
+ return 1
+}
+
+type fakeNeverRateLimiter struct {
+ wg sync.WaitGroup
+}
+
+func NewFakeNeverRateLimiter() RateLimiter {
+ rl := fakeNeverRateLimiter{}
+ rl.wg.Add(1)
+ return &rl
+}
+
+func (t *fakeNeverRateLimiter) TryAccept() bool {
+ return false
+}
+
+func (t *fakeNeverRateLimiter) Stop() {
+ t.wg.Done()
+}
+
+func (t *fakeNeverRateLimiter) Accept() {
+ t.wg.Wait()
+}
+
+func (t *fakeNeverRateLimiter) QPS() float32 {
+ return 1
+}
diff --git a/metrics-server/vendor/k8s.io/client-go/util/homedir/homedir.go b/metrics-server/vendor/k8s.io/client-go/util/homedir/homedir.go
new file mode 100644
index 0000000..816db57
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/homedir/homedir.go
@@ -0,0 +1,47 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+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 homedir
+
+import (
+ "os"
+ "runtime"
+)
+
+// HomeDir returns the home directory for the current user
+func HomeDir() string {
+ if runtime.GOOS == "windows" {
+
+ // First prefer the HOME environmental variable
+ if home := os.Getenv("HOME"); len(home) > 0 {
+ if _, err := os.Stat(home); err == nil {
+ return home
+ }
+ }
+ if homeDrive, homePath := os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH"); len(homeDrive) > 0 && len(homePath) > 0 {
+ homeDir := homeDrive + homePath
+ if _, err := os.Stat(homeDir); err == nil {
+ return homeDir
+ }
+ }
+ if userProfile := os.Getenv("USERPROFILE"); len(userProfile) > 0 {
+ if _, err := os.Stat(userProfile); err == nil {
+ return userProfile
+ }
+ }
+ }
+ return os.Getenv("HOME")
+}
diff --git a/metrics-server/vendor/k8s.io/client-go/util/integer/integer.go b/metrics-server/vendor/k8s.io/client-go/util/integer/integer.go
new file mode 100644
index 0000000..c6ea106
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/integer/integer.go
@@ -0,0 +1,67 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+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 integer
+
+func IntMax(a, b int) int {
+ if b > a {
+ return b
+ }
+ return a
+}
+
+func IntMin(a, b int) int {
+ if b < a {
+ return b
+ }
+ return a
+}
+
+func Int32Max(a, b int32) int32 {
+ if b > a {
+ return b
+ }
+ return a
+}
+
+func Int32Min(a, b int32) int32 {
+ if b < a {
+ return b
+ }
+ return a
+}
+
+func Int64Max(a, b int64) int64 {
+ if b > a {
+ return b
+ }
+ return a
+}
+
+func Int64Min(a, b int64) int64 {
+ if b < a {
+ return b
+ }
+ return a
+}
+
+// RoundToInt32 rounds floats into integer numbers.
+func RoundToInt32(a float64) int32 {
+ if a < 0 {
+ return int32(a - 0.5)
+ }
+ return int32(a + 0.5)
+}
diff --git a/metrics-server/vendor/k8s.io/client-go/util/retry/OWNERS b/metrics-server/vendor/k8s.io/client-go/util/retry/OWNERS
new file mode 100755
index 0000000..a4c1c2d
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/retry/OWNERS
@@ -0,0 +1,2 @@
+reviewers:
+- caesarxuchao
diff --git a/metrics-server/vendor/k8s.io/client-go/util/retry/util.go b/metrics-server/vendor/k8s.io/client-go/util/retry/util.go
new file mode 100644
index 0000000..3ac0840
--- /dev/null
+++ b/metrics-server/vendor/k8s.io/client-go/util/retry/util.go
@@ -0,0 +1,79 @@
+/*
+Copyright 2016 The Kubernetes Authors.
+
+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 retry
+
+import (
+ "time"
+
+ "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/util/wait"
+)
+
+// DefaultRetry is the recommended retry for a conflict where multiple clients
+// are making changes to the same resource.
+var DefaultRetry = wait.Backoff{
+ Steps: 5,
+ Duration: 10 * time.Millisecond,
+ Factor: 1.0,
+ Jitter: 0.1,
+}
+
+// DefaultBackoff is the recommended backoff for a conflict where a client
+// may be attempting to make an unrelated modification to a resource under
+// active management by one or more controllers.
+var DefaultBackoff = wait.Backoff{
+ Steps: 4,
+ Duration: 10 * time.Millisecond,
+ Factor: 5.0,
+ Jitter: 0.1,
+}
+
+// RetryConflict executes the provided function repeatedly, retrying if the server returns a conflicting
+// write. Callers should preserve previous executions if they wish to retry changes. It performs an
+// exponential backoff.
+//
+// var pod *api.Pod
+// err := RetryOnConflict(DefaultBackoff, func() (err error) {
+// pod, err = c.Pods("mynamespace").UpdateStatus(podStatus)
+// return
+// })
+// if err != nil {
+// // may be conflict if max retries were hit
+// return err
+// }
+// ...
+//
+// TODO: Make Backoff an interface?
+func RetryOnConflict(backoff wait.Backoff, fn func() error) error {
+ var lastConflictErr error
+ err := wait.ExponentialBackoff(backoff, func() (bool, error) {
+ err := fn()
+ switch {
+ case err == nil:
+ return true, nil
+ case errors.IsConflict(err):
+ lastConflictErr = err
+ return false, nil
+ default:
+ return false, err
+ }
+ })
+ if err == wait.ErrWaitTimeout {
+ err = lastConflictErr
+ }
+ return err
+}