mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
Migrate from snapClient.VolumesnapshotV1alpha1Client to
snapClient.SnapshotV1alpha1Client and also update kube dependency Signed-off-by: Humble Chirammal <hchiramm@redhat.com>
This commit is contained in:
committed by
mergify[bot]
parent
3bc6771df8
commit
22ff5c0911
4
vendor/k8s.io/kubernetes/pkg/kubelet/apis/config/types.go
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/kubelet/apis/config/types.go
generated
vendored
@ -291,12 +291,12 @@ type KubeletConfiguration struct {
|
||||
|
||||
/* the following fields are meant for Node Allocatable */
|
||||
|
||||
// A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=150G,pids=100) pairs
|
||||
// A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=150G,pid=100) pairs
|
||||
// that describe resources reserved for non-kubernetes components.
|
||||
// Currently only cpu and memory are supported.
|
||||
// See http://kubernetes.io/docs/user-guide/compute-resources for more detail.
|
||||
SystemReserved map[string]string
|
||||
// A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=150G,pids=100) pairs
|
||||
// A set of ResourceName=ResourceQuantity (e.g. cpu=200m,memory=150G,pid=100) pairs
|
||||
// that describe resources reserved for kubernetes system components.
|
||||
// Currently cpu, memory and local ephemeral storage for root file system are supported.
|
||||
// See http://kubernetes.io/docs/user-guide/compute-resources for more detail.
|
||||
|
27259
vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/api.pb.go
generated
vendored
27259
vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/api.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
55
vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/constants.go
generated
vendored
55
vendor/k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2/constants.go
generated
vendored
@ -1,55 +0,0 @@
|
||||
/*
|
||||
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 v1alpha2
|
||||
|
||||
// This file contains all constants defined in CRI.
|
||||
|
||||
// Required runtime condition type.
|
||||
const (
|
||||
// RuntimeReady means the runtime is up and ready to accept basic containers.
|
||||
RuntimeReady = "RuntimeReady"
|
||||
// NetworkReady means the runtime network is up and ready to accept containers which require network.
|
||||
NetworkReady = "NetworkReady"
|
||||
)
|
||||
|
||||
// LogStreamType is the type of the stream in CRI container log.
|
||||
type LogStreamType string
|
||||
|
||||
const (
|
||||
// Stdout is the stream type for stdout.
|
||||
Stdout LogStreamType = "stdout"
|
||||
// Stderr is the stream type for stderr.
|
||||
Stderr LogStreamType = "stderr"
|
||||
)
|
||||
|
||||
// LogTag is the tag of a log line in CRI container log.
|
||||
// Currently defined log tags:
|
||||
// * First tag: Partial/Full - P/F.
|
||||
// The field in the container log format can be extended to include multiple
|
||||
// tags by using a delimiter, but changes should be rare. If it becomes clear
|
||||
// that better extensibility is desired, a more extensible format (e.g., json)
|
||||
// should be adopted as a replacement and/or addition.
|
||||
type LogTag string
|
||||
|
||||
const (
|
||||
// LogTagPartial means the line is part of multiple lines.
|
||||
LogTagPartial LogTag = "P"
|
||||
// LogTagFull means the line is a single full line or the end of multiple lines.
|
||||
LogTagFull LogTag = "F"
|
||||
// LogTagDelimiter is the delimiter for different log tags.
|
||||
LogTagDelimiter = ":"
|
||||
)
|
1
vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_annotations.go
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_annotations.go
generated
vendored
@ -17,6 +17,7 @@ limitations under the License.
|
||||
package apis
|
||||
|
||||
const (
|
||||
// AnnotationProvidedIPAddr is a node IP annotation set by the "external" cloud provider.
|
||||
// When kubelet is started with the "external" cloud provider, then
|
||||
// it sets this annotation on the node to denote an ip address set from the
|
||||
// cmd line flag (--node-ip). This ip is verified with the cloudprovider as valid by
|
||||
|
6
vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_annotations_windows.go
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_annotations_windows.go
generated
vendored
@ -24,10 +24,12 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// HypervIsolationAnnotationKey and HypervIsolationValue are used to run windows containers with hyperv isolation.
|
||||
// HypervIsolationAnnotationKey is used to run windows containers with hyperv isolation.
|
||||
// Refer https://aka.ms/hyperv-container.
|
||||
HypervIsolationAnnotationKey = "experimental.windows.kubernetes.io/isolation-type"
|
||||
HypervIsolationValue = "hyperv"
|
||||
// HypervIsolationValue is used to run windows containers with hyperv isolation.
|
||||
// Refer https://aka.ms/hyperv-container.
|
||||
HypervIsolationValue = "hyperv"
|
||||
)
|
||||
|
||||
// ShouldIsolatedByHyperV returns true if a windows container should be run with hyperv isolation.
|
||||
|
11
vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_labels.go
generated
vendored
11
vendor/k8s.io/kubernetes/pkg/kubelet/apis/well_known_labels.go
generated
vendored
@ -24,10 +24,15 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// The OS/Arch labels are promoted to GA in 1.14. kubelet applies both beta
|
||||
// LabelOS is a label to indicate the operating system of the node.
|
||||
// The OS labels are promoted to GA in 1.14. kubelet applies both beta
|
||||
// and GA labels to ensure backward compatibility.
|
||||
// TODO: stop applying the beta OS/Arch labels in Kubernetes 1.18.
|
||||
LabelOS = "beta.kubernetes.io/os"
|
||||
// TODO: stop applying the beta OS labels in Kubernetes 1.18.
|
||||
LabelOS = "beta.kubernetes.io/os"
|
||||
// LabelArch is a label to indicate the architecture of the node.
|
||||
// The Arch labels are promoted to GA in 1.14. kubelet applies both beta
|
||||
// and GA labels to ensure backward compatibility.
|
||||
// TODO: stop applying the beta Arch labels in Kubernetes 1.18.
|
||||
LabelArch = "beta.kubernetes.io/arch"
|
||||
|
||||
// GA versions of the legacy beta labels.
|
||||
|
130
vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/checkpoint.go
generated
vendored
Normal file
130
vendor/k8s.io/kubernetes/pkg/kubelet/checkpoint/checkpoint.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
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 checkpoint
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/klog"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager"
|
||||
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum"
|
||||
)
|
||||
|
||||
const (
|
||||
// Delimiter used on checkpoints written to disk
|
||||
delimiter = "_"
|
||||
podPrefix = "Pod"
|
||||
)
|
||||
|
||||
// PodCheckpoint defines the operations to retrieve pod
|
||||
type PodCheckpoint interface {
|
||||
checkpointmanager.Checkpoint
|
||||
GetPod() *v1.Pod
|
||||
}
|
||||
|
||||
// Data to be stored as checkpoint
|
||||
type Data struct {
|
||||
Pod *v1.Pod
|
||||
Checksum checksum.Checksum
|
||||
}
|
||||
|
||||
// NewPodCheckpoint returns new pod checkpoint
|
||||
func NewPodCheckpoint(pod *v1.Pod) PodCheckpoint {
|
||||
return &Data{Pod: pod}
|
||||
}
|
||||
|
||||
// MarshalCheckpoint returns marshalled data
|
||||
func (cp *Data) MarshalCheckpoint() ([]byte, error) {
|
||||
cp.Checksum = checksum.New(*cp.Pod)
|
||||
return json.Marshal(*cp)
|
||||
}
|
||||
|
||||
// UnmarshalCheckpoint returns unmarshalled data
|
||||
func (cp *Data) UnmarshalCheckpoint(blob []byte) error {
|
||||
return json.Unmarshal(blob, cp)
|
||||
}
|
||||
|
||||
// VerifyChecksum verifies that passed checksum is same as calculated checksum
|
||||
func (cp *Data) VerifyChecksum() error {
|
||||
return cp.Checksum.Verify(*cp.Pod)
|
||||
}
|
||||
|
||||
// GetPod retrieves the pod from the checkpoint
|
||||
func (cp *Data) GetPod() *v1.Pod {
|
||||
return cp.Pod
|
||||
}
|
||||
|
||||
// checkAnnotations will validate the checkpoint annotations exist on the Pod
|
||||
func checkAnnotations(pod *v1.Pod) bool {
|
||||
if podAnnotations := pod.GetAnnotations(); podAnnotations != nil {
|
||||
if podAnnotations[core.BootstrapCheckpointAnnotationKey] == "true" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//getPodKey returns the full qualified path for the pod checkpoint
|
||||
func getPodKey(pod *v1.Pod) string {
|
||||
return fmt.Sprintf("%s%s%v.yaml", podPrefix, delimiter, pod.GetUID())
|
||||
}
|
||||
|
||||
// LoadPods Loads All Checkpoints from disk
|
||||
func LoadPods(cpm checkpointmanager.CheckpointManager) ([]*v1.Pod, error) {
|
||||
pods := make([]*v1.Pod, 0)
|
||||
|
||||
var err error
|
||||
checkpointKeys := []string{}
|
||||
checkpointKeys, err = cpm.ListCheckpoints()
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to list checkpoints: %v", err)
|
||||
}
|
||||
|
||||
for _, key := range checkpointKeys {
|
||||
checkpoint := NewPodCheckpoint(nil)
|
||||
err := cpm.GetCheckpoint(key, checkpoint)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to retrieve checkpoint for pod %q: %v", key, err)
|
||||
continue
|
||||
}
|
||||
pods = append(pods, checkpoint.GetPod())
|
||||
}
|
||||
return pods, nil
|
||||
}
|
||||
|
||||
// WritePod a checkpoint to a file on disk if annotation is present
|
||||
func WritePod(cpm checkpointmanager.CheckpointManager, pod *v1.Pod) error {
|
||||
var err error
|
||||
if checkAnnotations(pod) {
|
||||
data := NewPodCheckpoint(pod)
|
||||
err = cpm.CreateCheckpoint(getPodKey(pod), data)
|
||||
} else {
|
||||
// This is to handle an edge where a pod update could remove
|
||||
// an annotation and the checkpoint should then be removed.
|
||||
err = cpm.RemoveCheckpoint(getPodKey(pod))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// DeletePod deletes a checkpoint from disk if present
|
||||
func DeletePod(cpm checkpointmanager.CheckpointManager, pod *v1.Pod) error {
|
||||
return cpm.RemoveCheckpoint(getPodKey(pod))
|
||||
}
|
110
vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checkpoint_manager.go
generated
vendored
Normal file
110
vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checkpoint_manager.go
generated
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
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 checkpointmanager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors"
|
||||
utilstore "k8s.io/kubernetes/pkg/kubelet/util/store"
|
||||
utilfs "k8s.io/kubernetes/pkg/util/filesystem"
|
||||
)
|
||||
|
||||
// Checkpoint provides the process checkpoint data
|
||||
type Checkpoint interface {
|
||||
MarshalCheckpoint() ([]byte, error)
|
||||
UnmarshalCheckpoint(blob []byte) error
|
||||
VerifyChecksum() error
|
||||
}
|
||||
|
||||
// CheckpointManager provides the interface to manage checkpoint
|
||||
type CheckpointManager interface {
|
||||
// CreateCheckpoint persists checkpoint in CheckpointStore. checkpointKey is the key for utilstore to locate checkpoint.
|
||||
// For file backed utilstore, checkpointKey is the file name to write the checkpoint data.
|
||||
CreateCheckpoint(checkpointKey string, checkpoint Checkpoint) error
|
||||
// GetCheckpoint retrieves checkpoint from CheckpointStore.
|
||||
GetCheckpoint(checkpointKey string, checkpoint Checkpoint) error
|
||||
// WARNING: RemoveCheckpoint will not return error if checkpoint does not exist.
|
||||
RemoveCheckpoint(checkpointKey string) error
|
||||
// ListCheckpoint returns the list of existing checkpoints.
|
||||
ListCheckpoints() ([]string, error)
|
||||
}
|
||||
|
||||
// impl is an implementation of CheckpointManager. It persists checkpoint in CheckpointStore
|
||||
type impl struct {
|
||||
path string
|
||||
store utilstore.Store
|
||||
mutex sync.Mutex
|
||||
}
|
||||
|
||||
// NewCheckpointManager returns a new instance of a checkpoint manager
|
||||
func NewCheckpointManager(checkpointDir string) (CheckpointManager, error) {
|
||||
fstore, err := utilstore.NewFileStore(checkpointDir, utilfs.DefaultFs{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &impl{path: checkpointDir, store: fstore}, nil
|
||||
}
|
||||
|
||||
// CreateCheckpoint persists checkpoint in CheckpointStore.
|
||||
func (manager *impl) CreateCheckpoint(checkpointKey string, checkpoint Checkpoint) error {
|
||||
manager.mutex.Lock()
|
||||
defer manager.mutex.Unlock()
|
||||
blob, err := checkpoint.MarshalCheckpoint()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return manager.store.Write(checkpointKey, blob)
|
||||
}
|
||||
|
||||
// GetCheckpoint retrieves checkpoint from CheckpointStore.
|
||||
func (manager *impl) GetCheckpoint(checkpointKey string, checkpoint Checkpoint) error {
|
||||
manager.mutex.Lock()
|
||||
defer manager.mutex.Unlock()
|
||||
blob, err := manager.store.Read(checkpointKey)
|
||||
if err != nil {
|
||||
if err == utilstore.ErrKeyNotFound {
|
||||
return errors.ErrCheckpointNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
err = checkpoint.UnmarshalCheckpoint(blob)
|
||||
if err == nil {
|
||||
err = checkpoint.VerifyChecksum()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveCheckpoint will not return error if checkpoint does not exist.
|
||||
func (manager *impl) RemoveCheckpoint(checkpointKey string) error {
|
||||
manager.mutex.Lock()
|
||||
defer manager.mutex.Unlock()
|
||||
return manager.store.Delete(checkpointKey)
|
||||
}
|
||||
|
||||
// ListCheckpoints returns the list of existing checkpoints.
|
||||
func (manager *impl) ListCheckpoints() ([]string, error) {
|
||||
manager.mutex.Lock()
|
||||
defer manager.mutex.Unlock()
|
||||
keys, err := manager.store.List()
|
||||
if err != nil {
|
||||
return []string{}, fmt.Errorf("failed to list checkpoint store: %v", err)
|
||||
}
|
||||
return keys, nil
|
||||
}
|
47
vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum/checksum.go
generated
vendored
Normal file
47
vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum/checksum.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
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 checksum
|
||||
|
||||
import (
|
||||
"hash/fnv"
|
||||
|
||||
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors"
|
||||
hashutil "k8s.io/kubernetes/pkg/util/hash"
|
||||
)
|
||||
|
||||
// Checksum is the data to be stored as checkpoint
|
||||
type Checksum uint64
|
||||
|
||||
// Verify verifies that passed checksum is same as calculated checksum
|
||||
func (cs Checksum) Verify(data interface{}) error {
|
||||
if cs != New(data) {
|
||||
return errors.ErrCorruptCheckpoint
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// New returns the Checksum of checkpoint data
|
||||
func New(data interface{}) Checksum {
|
||||
return Checksum(getChecksum(data))
|
||||
}
|
||||
|
||||
// Get returns calculated checksum of checkpoint data
|
||||
func getChecksum(data interface{}) uint64 {
|
||||
hash := fnv.New32a()
|
||||
hashutil.DeepHashObject(hash, data)
|
||||
return uint64(hash.Sum32())
|
||||
}
|
25
vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors/errors.go
generated
vendored
Normal file
25
vendor/k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors/errors.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
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 errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ErrCorruptCheckpoint error is reported when checksum does not match
|
||||
var ErrCorruptCheckpoint = fmt.Errorf("checkpoint is corrupted")
|
||||
|
||||
// ErrCheckpointNotFound is reported when checkpoint is not found for a given key
|
||||
var ErrCheckpointNotFound = fmt.Errorf("checkpoint is not found")
|
149
vendor/k8s.io/kubernetes/pkg/kubelet/configmap/configmap_manager.go
generated
vendored
Normal file
149
vendor/k8s.io/kubernetes/pkg/kubelet/configmap/configmap_manager.go
generated
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
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 configmap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/manager"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
// Get configmap by configmap namespace and name.
|
||||
GetConfigMap(namespace, name string) (*v1.ConfigMap, error)
|
||||
|
||||
// WARNING: Register/UnregisterPod functions should be efficient,
|
||||
// i.e. should not block on network operations.
|
||||
|
||||
// RegisterPod registers all configmaps from a given pod.
|
||||
RegisterPod(pod *v1.Pod)
|
||||
|
||||
// UnregisterPod unregisters configmaps from a given pod that are not
|
||||
// used by any other registered pod.
|
||||
UnregisterPod(pod *v1.Pod)
|
||||
}
|
||||
|
||||
// simpleConfigMapManager implements ConfigMap Manager interface with
|
||||
// simple operations to apiserver.
|
||||
type simpleConfigMapManager struct {
|
||||
kubeClient clientset.Interface
|
||||
}
|
||||
|
||||
func NewSimpleConfigMapManager(kubeClient clientset.Interface) Manager {
|
||||
return &simpleConfigMapManager{kubeClient: kubeClient}
|
||||
}
|
||||
|
||||
func (s *simpleConfigMapManager) GetConfigMap(namespace, name string) (*v1.ConfigMap, error) {
|
||||
return s.kubeClient.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
func (s *simpleConfigMapManager) RegisterPod(pod *v1.Pod) {
|
||||
}
|
||||
|
||||
func (s *simpleConfigMapManager) UnregisterPod(pod *v1.Pod) {
|
||||
}
|
||||
|
||||
// configMapManager keeps a cache of all configmaps necessary
|
||||
// for registered pods. Different implementation of the store
|
||||
// may result in different semantics for freshness of configmaps
|
||||
// (e.g. ttl-based implementation vs watch-based implementation).
|
||||
type configMapManager struct {
|
||||
manager manager.Manager
|
||||
}
|
||||
|
||||
func (c *configMapManager) GetConfigMap(namespace, name string) (*v1.ConfigMap, error) {
|
||||
object, err := c.manager.GetObject(namespace, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if configmap, ok := object.(*v1.ConfigMap); ok {
|
||||
return configmap, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected object type: %v", object)
|
||||
}
|
||||
|
||||
func (c *configMapManager) RegisterPod(pod *v1.Pod) {
|
||||
c.manager.RegisterPod(pod)
|
||||
}
|
||||
|
||||
func (c *configMapManager) UnregisterPod(pod *v1.Pod) {
|
||||
c.manager.UnregisterPod(pod)
|
||||
}
|
||||
|
||||
func getConfigMapNames(pod *v1.Pod) sets.String {
|
||||
result := sets.NewString()
|
||||
podutil.VisitPodConfigmapNames(pod, func(name string) bool {
|
||||
result.Insert(name)
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
const (
|
||||
defaultTTL = time.Minute
|
||||
)
|
||||
|
||||
// NewCachingConfigMapManager creates a manager that keeps a cache of all configmaps
|
||||
// necessary for registered pods.
|
||||
// It implement the following logic:
|
||||
// - whenever a pod is create or updated, the cached versions of all configmaps
|
||||
// are invalidated
|
||||
// - every GetObject() call tries to fetch the value from local cache; if it is
|
||||
// not there, invalidated or too old, we fetch it from apiserver and refresh the
|
||||
// value in cache; otherwise it is just fetched from cache
|
||||
func NewCachingConfigMapManager(kubeClient clientset.Interface, getTTL manager.GetObjectTTLFunc) Manager {
|
||||
getConfigMap := func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) {
|
||||
return kubeClient.CoreV1().ConfigMaps(namespace).Get(name, opts)
|
||||
}
|
||||
configMapStore := manager.NewObjectStore(getConfigMap, clock.RealClock{}, getTTL, defaultTTL)
|
||||
return &configMapManager{
|
||||
manager: manager.NewCacheBasedManager(configMapStore, getConfigMapNames),
|
||||
}
|
||||
}
|
||||
|
||||
// NewWatchingConfigMapManager creates a manager that keeps a cache of all configmaps
|
||||
// necessary for registered pods.
|
||||
// It implements the following logic:
|
||||
// - whenever a pod is created or updated, we start inidvidual watches for all
|
||||
// referenced objects that aren't referenced from other registered pods
|
||||
// - every GetObject() returns a value from local cache propagated via watches
|
||||
func NewWatchingConfigMapManager(kubeClient clientset.Interface) Manager {
|
||||
listConfigMap := func(namespace string, opts metav1.ListOptions) (runtime.Object, error) {
|
||||
return kubeClient.CoreV1().ConfigMaps(namespace).List(opts)
|
||||
}
|
||||
watchConfigMap := func(namespace string, opts metav1.ListOptions) (watch.Interface, error) {
|
||||
return kubeClient.CoreV1().ConfigMaps(namespace).Watch(opts)
|
||||
}
|
||||
newConfigMap := func() runtime.Object {
|
||||
return &v1.ConfigMap{}
|
||||
}
|
||||
gr := corev1.Resource("configmap")
|
||||
return &configMapManager{
|
||||
manager: manager.NewWatchBasedManager(listConfigMap, watchConfigMap, newConfigMap, gr, getConfigMapNames),
|
||||
}
|
||||
}
|
40
vendor/k8s.io/kubernetes/pkg/kubelet/configmap/fake_manager.go
generated
vendored
Normal file
40
vendor/k8s.io/kubernetes/pkg/kubelet/configmap/fake_manager.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
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 configmap
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// fakeManager implements Manager interface for testing purposes.
|
||||
// simple operations to apiserver.
|
||||
type fakeManager struct {
|
||||
}
|
||||
|
||||
func NewFakeManager() Manager {
|
||||
return &fakeManager{}
|
||||
}
|
||||
|
||||
func (s *fakeManager) GetConfigMap(namespace, name string) (*v1.ConfigMap, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *fakeManager) RegisterPod(pod *v1.Pod) {
|
||||
}
|
||||
|
||||
func (s *fakeManager) UnregisterPod(pod *v1.Pod) {
|
||||
}
|
2
vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers.go
generated
vendored
@ -29,7 +29,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/tools/record"
|
||||
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/format"
|
||||
hashutil "k8s.io/kubernetes/pkg/util/hash"
|
||||
"k8s.io/kubernetes/third_party/forked/golang/expansion"
|
||||
|
8
vendor/k8s.io/kubernetes/pkg/kubelet/container/ref.go
generated
vendored
8
vendor/k8s.io/kubernetes/pkg/kubelet/container/ref.go
generated
vendored
@ -54,9 +54,8 @@ func fieldPath(pod *v1.Pod, container *v1.Container) (string, error) {
|
||||
if here.Name == container.Name {
|
||||
if here.Name == "" {
|
||||
return fmt.Sprintf("spec.containers[%d]", i), nil
|
||||
} else {
|
||||
return fmt.Sprintf("spec.containers{%s}", here.Name), nil
|
||||
}
|
||||
return fmt.Sprintf("spec.containers{%s}", here.Name), nil
|
||||
}
|
||||
}
|
||||
for i := range pod.Spec.InitContainers {
|
||||
@ -64,10 +63,9 @@ func fieldPath(pod *v1.Pod, container *v1.Container) (string, error) {
|
||||
if here.Name == container.Name {
|
||||
if here.Name == "" {
|
||||
return fmt.Sprintf("spec.initContainers[%d]", i), nil
|
||||
} else {
|
||||
return fmt.Sprintf("spec.initContainers{%s}", here.Name), nil
|
||||
}
|
||||
return fmt.Sprintf("spec.initContainers{%s}", here.Name), nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("container %#v not found in pod %#v", container, pod)
|
||||
return "", fmt.Errorf("container %q not found in pod %s/%s", container.Name, pod.Namespace, pod.Name)
|
||||
}
|
||||
|
2
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime.go
generated
vendored
@ -29,8 +29,8 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
"k8s.io/client-go/util/flowcontrol"
|
||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||
"k8s.io/klog"
|
||||
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
)
|
||||
|
||||
|
13
vendor/k8s.io/kubernetes/pkg/kubelet/events/event.go
generated
vendored
13
vendor/k8s.io/kubernetes/pkg/kubelet/events/event.go
generated
vendored
@ -49,22 +49,15 @@ const (
|
||||
StartingKubelet = "Starting"
|
||||
KubeletSetupFailed = "KubeletSetupFailed"
|
||||
FailedAttachVolume = "FailedAttachVolume"
|
||||
FailedDetachVolume = "FailedDetachVolume"
|
||||
FailedMountVolume = "FailedMount"
|
||||
VolumeResizeFailed = "VolumeResizeFailed"
|
||||
VolumeResizeSuccess = "VolumeResizeSuccessful"
|
||||
FileSystemResizeFailed = "FileSystemResizeFailed"
|
||||
FileSystemResizeSuccess = "FileSystemResizeSuccessful"
|
||||
FailedUnMountVolume = "FailedUnMount"
|
||||
FailedMapVolume = "FailedMapVolume"
|
||||
FailedUnmapDevice = "FailedUnmapDevice"
|
||||
WarnAlreadyMountedVolume = "AlreadyMountedVolume"
|
||||
SuccessfulDetachVolume = "SuccessfulDetachVolume"
|
||||
SuccessfulAttachVolume = "SuccessfulAttachVolume"
|
||||
SuccessfulMountVolume = "SuccessfulMountVolume"
|
||||
SuccessfulUnMountVolume = "SuccessfulUnMountVolume"
|
||||
HostPortConflict = "HostPortConflict"
|
||||
NodeSelectorMismatching = "NodeSelectorMismatching"
|
||||
InsufficientFreeCPU = "InsufficientFreeCPU"
|
||||
InsufficientFreeMemory = "InsufficientFreeMemory"
|
||||
NodeRebooted = "Rebooted"
|
||||
@ -72,7 +65,6 @@ const (
|
||||
ImageGCFailed = "ImageGCFailed"
|
||||
FailedNodeAllocatableEnforcement = "FailedNodeAllocatableEnforcement"
|
||||
SuccessfulNodeAllocatableEnforcement = "NodeAllocatableEnforced"
|
||||
UnsupportedMountOption = "UnsupportedMountOption"
|
||||
SandboxChanged = "SandboxChanged"
|
||||
FailedCreatePodSandBox = "FailedCreatePodSandBox"
|
||||
FailedStatusPodSandBox = "FailedPodSandBoxStatus"
|
||||
@ -92,7 +84,6 @@ const (
|
||||
FailedValidation = "FailedValidation"
|
||||
|
||||
// Lifecycle hooks
|
||||
FailedPostStartHook = "FailedPostStartHook"
|
||||
FailedPreStopHook = "FailedPreStopHook"
|
||||
UnfinishedPreStopHook = "UnfinishedPreStopHook"
|
||||
FailedPostStartHook = "FailedPostStartHook"
|
||||
FailedPreStopHook = "FailedPreStopHook"
|
||||
)
|
||||
|
113
vendor/k8s.io/kubernetes/pkg/kubelet/pod/mirror_client.go
generated
vendored
Normal file
113
vendor/k8s.io/kubernetes/pkg/kubelet/pod/mirror_client.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
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 pod
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog"
|
||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
|
||||
)
|
||||
|
||||
// MirrorClient knows how to create/delete a mirror pod in the API server.
|
||||
type MirrorClient interface {
|
||||
// CreateMirrorPod creates a mirror pod in the API server for the given
|
||||
// pod or returns an error. The mirror pod will have the same annotations
|
||||
// as the given pod as well as an extra annotation containing the hash of
|
||||
// the static pod.
|
||||
CreateMirrorPod(pod *v1.Pod) error
|
||||
// DeleteMirrorPod deletes the mirror pod with the given full name from
|
||||
// the API server or returns an error.
|
||||
DeleteMirrorPod(podFullName string) error
|
||||
}
|
||||
|
||||
// basicMirrorClient is a functional MirrorClient. Mirror pods are stored in
|
||||
// the kubelet directly because they need to be in sync with the internal
|
||||
// pods.
|
||||
type basicMirrorClient struct {
|
||||
apiserverClient clientset.Interface
|
||||
}
|
||||
|
||||
// NewBasicMirrorClient returns a new MirrorClient.
|
||||
func NewBasicMirrorClient(apiserverClient clientset.Interface) MirrorClient {
|
||||
return &basicMirrorClient{apiserverClient: apiserverClient}
|
||||
}
|
||||
|
||||
func (mc *basicMirrorClient) CreateMirrorPod(pod *v1.Pod) error {
|
||||
if mc.apiserverClient == nil {
|
||||
return nil
|
||||
}
|
||||
// Make a copy of the pod.
|
||||
copyPod := *pod
|
||||
copyPod.Annotations = make(map[string]string)
|
||||
|
||||
for k, v := range pod.Annotations {
|
||||
copyPod.Annotations[k] = v
|
||||
}
|
||||
hash := getPodHash(pod)
|
||||
copyPod.Annotations[kubetypes.ConfigMirrorAnnotationKey] = hash
|
||||
apiPod, err := mc.apiserverClient.CoreV1().Pods(copyPod.Namespace).Create(©Pod)
|
||||
if err != nil && errors.IsAlreadyExists(err) {
|
||||
// Check if the existing pod is the same as the pod we want to create.
|
||||
if h, ok := apiPod.Annotations[kubetypes.ConfigMirrorAnnotationKey]; ok && h == hash {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (mc *basicMirrorClient) DeleteMirrorPod(podFullName string) error {
|
||||
if mc.apiserverClient == nil {
|
||||
return nil
|
||||
}
|
||||
name, namespace, err := kubecontainer.ParsePodFullName(podFullName)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to parse a pod full name %q", podFullName)
|
||||
return err
|
||||
}
|
||||
klog.V(2).Infof("Deleting a mirror pod %q", podFullName)
|
||||
// TODO(random-liu): Delete the mirror pod with uid precondition in mirror pod manager
|
||||
if err := mc.apiserverClient.CoreV1().Pods(namespace).Delete(name, metav1.NewDeleteOptions(0)); err != nil && !errors.IsNotFound(err) {
|
||||
klog.Errorf("Failed deleting a mirror pod %q: %v", podFullName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsStaticPod returns true if the pod is a static pod.
|
||||
func IsStaticPod(pod *v1.Pod) bool {
|
||||
source, err := kubetypes.GetPodSource(pod)
|
||||
return err == nil && source != kubetypes.ApiserverSource
|
||||
}
|
||||
|
||||
// IsMirrorPod returns true if the pod is a mirror pod.
|
||||
func IsMirrorPod(pod *v1.Pod) bool {
|
||||
_, ok := pod.Annotations[kubetypes.ConfigMirrorAnnotationKey]
|
||||
return ok
|
||||
}
|
||||
|
||||
func getHashFromMirrorPod(pod *v1.Pod) (string, bool) {
|
||||
hash, ok := pod.Annotations[kubetypes.ConfigMirrorAnnotationKey]
|
||||
return hash, ok
|
||||
}
|
||||
|
||||
func getPodHash(pod *v1.Pod) string {
|
||||
// The annotation exists for all static pods.
|
||||
return pod.Annotations[kubetypes.ConfigHashAnnotationKey]
|
||||
}
|
385
vendor/k8s.io/kubernetes/pkg/kubelet/pod/pod_manager.go
generated
vendored
Normal file
385
vendor/k8s.io/kubernetes/pkg/kubelet/pod/pod_manager.go
generated
vendored
Normal file
@ -0,0 +1,385 @@
|
||||
/*
|
||||
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 pod
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"k8s.io/klog"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/kubelet/checkpoint"
|
||||
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager"
|
||||
"k8s.io/kubernetes/pkg/kubelet/configmap"
|
||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
"k8s.io/kubernetes/pkg/kubelet/secret"
|
||||
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
|
||||
)
|
||||
|
||||
// Manager stores and manages access to pods, maintaining the mappings
|
||||
// between static pods and mirror pods.
|
||||
//
|
||||
// The kubelet discovers pod updates from 3 sources: file, http, and
|
||||
// apiserver. Pods from non-apiserver sources are called static pods, and API
|
||||
// server is not aware of the existence of static pods. In order to monitor
|
||||
// the status of such pods, the kubelet creates a mirror pod for each static
|
||||
// pod via the API server.
|
||||
//
|
||||
// A mirror pod has the same pod full name (name and namespace) as its static
|
||||
// counterpart (albeit different metadata such as UID, etc). By leveraging the
|
||||
// fact that the kubelet reports the pod status using the pod full name, the
|
||||
// status of the mirror pod always reflects the actual status of the static
|
||||
// pod. When a static pod gets deleted, the associated orphaned mirror pod
|
||||
// will also be removed.
|
||||
type Manager interface {
|
||||
// GetPods returns the regular pods bound to the kubelet and their spec.
|
||||
GetPods() []*v1.Pod
|
||||
// GetPodByFullName returns the (non-mirror) pod that matches full name, as well as
|
||||
// whether the pod was found.
|
||||
GetPodByFullName(podFullName string) (*v1.Pod, bool)
|
||||
// GetPodByName provides the (non-mirror) pod that matches namespace and
|
||||
// name, as well as whether the pod was found.
|
||||
GetPodByName(namespace, name string) (*v1.Pod, bool)
|
||||
// GetPodByUID provides the (non-mirror) pod that matches pod UID, as well as
|
||||
// whether the pod is found.
|
||||
GetPodByUID(types.UID) (*v1.Pod, bool)
|
||||
// GetPodByMirrorPod returns the static pod for the given mirror pod and
|
||||
// whether it was known to the pod manger.
|
||||
GetPodByMirrorPod(*v1.Pod) (*v1.Pod, bool)
|
||||
// GetMirrorPodByPod returns the mirror pod for the given static pod and
|
||||
// whether it was known to the pod manager.
|
||||
GetMirrorPodByPod(*v1.Pod) (*v1.Pod, bool)
|
||||
// GetPodsAndMirrorPods returns the both regular and mirror pods.
|
||||
GetPodsAndMirrorPods() ([]*v1.Pod, []*v1.Pod)
|
||||
// SetPods replaces the internal pods with the new pods.
|
||||
// It is currently only used for testing.
|
||||
SetPods(pods []*v1.Pod)
|
||||
// AddPod adds the given pod to the manager.
|
||||
AddPod(pod *v1.Pod)
|
||||
// UpdatePod updates the given pod in the manager.
|
||||
UpdatePod(pod *v1.Pod)
|
||||
// DeletePod deletes the given pod from the manager. For mirror pods,
|
||||
// this means deleting the mappings related to mirror pods. For non-
|
||||
// mirror pods, this means deleting from indexes for all non-mirror pods.
|
||||
DeletePod(pod *v1.Pod)
|
||||
// DeleteOrphanedMirrorPods deletes all mirror pods which do not have
|
||||
// associated static pods. This method sends deletion requests to the API
|
||||
// server, but does NOT modify the internal pod storage in basicManager.
|
||||
DeleteOrphanedMirrorPods()
|
||||
// TranslatePodUID returns the actual UID of a pod. If the UID belongs to
|
||||
// a mirror pod, returns the UID of its static pod. Otherwise, returns the
|
||||
// original UID.
|
||||
//
|
||||
// All public-facing functions should perform this translation for UIDs
|
||||
// because user may provide a mirror pod UID, which is not recognized by
|
||||
// internal Kubelet functions.
|
||||
TranslatePodUID(uid types.UID) kubetypes.ResolvedPodUID
|
||||
// GetUIDTranslations returns the mappings of static pod UIDs to mirror pod
|
||||
// UIDs and mirror pod UIDs to static pod UIDs.
|
||||
GetUIDTranslations() (podToMirror map[kubetypes.ResolvedPodUID]kubetypes.MirrorPodUID, mirrorToPod map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID)
|
||||
// IsMirrorPodOf returns true if mirrorPod is a correct representation of
|
||||
// pod; false otherwise.
|
||||
IsMirrorPodOf(mirrorPod, pod *v1.Pod) bool
|
||||
|
||||
MirrorClient
|
||||
}
|
||||
|
||||
// basicManager is a functional Manager.
|
||||
//
|
||||
// All fields in basicManager are read-only and are updated calling SetPods,
|
||||
// AddPod, UpdatePod, or DeletePod.
|
||||
type basicManager struct {
|
||||
// Protects all internal maps.
|
||||
lock sync.RWMutex
|
||||
|
||||
// Regular pods indexed by UID.
|
||||
podByUID map[kubetypes.ResolvedPodUID]*v1.Pod
|
||||
// Mirror pods indexed by UID.
|
||||
mirrorPodByUID map[kubetypes.MirrorPodUID]*v1.Pod
|
||||
|
||||
// Pods indexed by full name for easy access.
|
||||
podByFullName map[string]*v1.Pod
|
||||
mirrorPodByFullName map[string]*v1.Pod
|
||||
|
||||
// Mirror pod UID to pod UID map.
|
||||
translationByUID map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID
|
||||
|
||||
// basicManager is keeping secretManager and configMapManager up-to-date.
|
||||
secretManager secret.Manager
|
||||
configMapManager configmap.Manager
|
||||
checkpointManager checkpointmanager.CheckpointManager
|
||||
|
||||
// A mirror pod client to create/delete mirror pods.
|
||||
MirrorClient
|
||||
}
|
||||
|
||||
// NewBasicPodManager returns a functional Manager.
|
||||
func NewBasicPodManager(client MirrorClient, secretManager secret.Manager, configMapManager configmap.Manager, cpm checkpointmanager.CheckpointManager) Manager {
|
||||
pm := &basicManager{}
|
||||
pm.secretManager = secretManager
|
||||
pm.configMapManager = configMapManager
|
||||
pm.checkpointManager = cpm
|
||||
pm.MirrorClient = client
|
||||
pm.SetPods(nil)
|
||||
return pm
|
||||
}
|
||||
|
||||
// Set the internal pods based on the new pods.
|
||||
func (pm *basicManager) SetPods(newPods []*v1.Pod) {
|
||||
pm.lock.Lock()
|
||||
defer pm.lock.Unlock()
|
||||
|
||||
pm.podByUID = make(map[kubetypes.ResolvedPodUID]*v1.Pod)
|
||||
pm.podByFullName = make(map[string]*v1.Pod)
|
||||
pm.mirrorPodByUID = make(map[kubetypes.MirrorPodUID]*v1.Pod)
|
||||
pm.mirrorPodByFullName = make(map[string]*v1.Pod)
|
||||
pm.translationByUID = make(map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID)
|
||||
|
||||
pm.updatePodsInternal(newPods...)
|
||||
}
|
||||
|
||||
func (pm *basicManager) AddPod(pod *v1.Pod) {
|
||||
pm.UpdatePod(pod)
|
||||
}
|
||||
|
||||
func (pm *basicManager) UpdatePod(pod *v1.Pod) {
|
||||
pm.lock.Lock()
|
||||
defer pm.lock.Unlock()
|
||||
pm.updatePodsInternal(pod)
|
||||
if pm.checkpointManager != nil {
|
||||
if err := checkpoint.WritePod(pm.checkpointManager, pod); err != nil {
|
||||
klog.Errorf("Error writing checkpoint for pod: %v", pod.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isPodInTerminatedState(pod *v1.Pod) bool {
|
||||
return pod.Status.Phase == v1.PodFailed || pod.Status.Phase == v1.PodSucceeded
|
||||
}
|
||||
|
||||
// updatePodsInternal replaces the given pods in the current state of the
|
||||
// manager, updating the various indices. The caller is assumed to hold the
|
||||
// lock.
|
||||
func (pm *basicManager) updatePodsInternal(pods ...*v1.Pod) {
|
||||
for _, pod := range pods {
|
||||
if pm.secretManager != nil {
|
||||
if isPodInTerminatedState(pod) {
|
||||
// Pods that are in terminated state and no longer running can be
|
||||
// ignored as they no longer require access to secrets.
|
||||
// It is especially important in watch-based manager, to avoid
|
||||
// unnecessary watches for terminated pods waiting for GC.
|
||||
pm.secretManager.UnregisterPod(pod)
|
||||
} else {
|
||||
// TODO: Consider detecting only status update and in such case do
|
||||
// not register pod, as it doesn't really matter.
|
||||
pm.secretManager.RegisterPod(pod)
|
||||
}
|
||||
}
|
||||
if pm.configMapManager != nil {
|
||||
if isPodInTerminatedState(pod) {
|
||||
// Pods that are in terminated state and no longer running can be
|
||||
// ignored as they no longer require access to configmaps.
|
||||
// It is especially important in watch-based manager, to avoid
|
||||
// unnecessary watches for terminated pods waiting for GC.
|
||||
pm.configMapManager.UnregisterPod(pod)
|
||||
} else {
|
||||
// TODO: Consider detecting only status update and in such case do
|
||||
// not register pod, as it doesn't really matter.
|
||||
pm.configMapManager.RegisterPod(pod)
|
||||
}
|
||||
}
|
||||
podFullName := kubecontainer.GetPodFullName(pod)
|
||||
// This logic relies on a static pod and its mirror to have the same name.
|
||||
// It is safe to type convert here due to the IsMirrorPod guard.
|
||||
if IsMirrorPod(pod) {
|
||||
mirrorPodUID := kubetypes.MirrorPodUID(pod.UID)
|
||||
pm.mirrorPodByUID[mirrorPodUID] = pod
|
||||
pm.mirrorPodByFullName[podFullName] = pod
|
||||
if p, ok := pm.podByFullName[podFullName]; ok {
|
||||
pm.translationByUID[mirrorPodUID] = kubetypes.ResolvedPodUID(p.UID)
|
||||
}
|
||||
} else {
|
||||
resolvedPodUID := kubetypes.ResolvedPodUID(pod.UID)
|
||||
pm.podByUID[resolvedPodUID] = pod
|
||||
pm.podByFullName[podFullName] = pod
|
||||
if mirror, ok := pm.mirrorPodByFullName[podFullName]; ok {
|
||||
pm.translationByUID[kubetypes.MirrorPodUID(mirror.UID)] = resolvedPodUID
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pm *basicManager) DeletePod(pod *v1.Pod) {
|
||||
pm.lock.Lock()
|
||||
defer pm.lock.Unlock()
|
||||
if pm.secretManager != nil {
|
||||
pm.secretManager.UnregisterPod(pod)
|
||||
}
|
||||
if pm.configMapManager != nil {
|
||||
pm.configMapManager.UnregisterPod(pod)
|
||||
}
|
||||
podFullName := kubecontainer.GetPodFullName(pod)
|
||||
// It is safe to type convert here due to the IsMirrorPod guard.
|
||||
if IsMirrorPod(pod) {
|
||||
mirrorPodUID := kubetypes.MirrorPodUID(pod.UID)
|
||||
delete(pm.mirrorPodByUID, mirrorPodUID)
|
||||
delete(pm.mirrorPodByFullName, podFullName)
|
||||
delete(pm.translationByUID, mirrorPodUID)
|
||||
} else {
|
||||
delete(pm.podByUID, kubetypes.ResolvedPodUID(pod.UID))
|
||||
delete(pm.podByFullName, podFullName)
|
||||
}
|
||||
if pm.checkpointManager != nil {
|
||||
if err := checkpoint.DeletePod(pm.checkpointManager, pod); err != nil {
|
||||
klog.Errorf("Error deleting checkpoint for pod: %v", pod.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pm *basicManager) GetPods() []*v1.Pod {
|
||||
pm.lock.RLock()
|
||||
defer pm.lock.RUnlock()
|
||||
return podsMapToPods(pm.podByUID)
|
||||
}
|
||||
|
||||
func (pm *basicManager) GetPodsAndMirrorPods() ([]*v1.Pod, []*v1.Pod) {
|
||||
pm.lock.RLock()
|
||||
defer pm.lock.RUnlock()
|
||||
pods := podsMapToPods(pm.podByUID)
|
||||
mirrorPods := mirrorPodsMapToMirrorPods(pm.mirrorPodByUID)
|
||||
return pods, mirrorPods
|
||||
}
|
||||
|
||||
func (pm *basicManager) GetPodByUID(uid types.UID) (*v1.Pod, bool) {
|
||||
pm.lock.RLock()
|
||||
defer pm.lock.RUnlock()
|
||||
pod, ok := pm.podByUID[kubetypes.ResolvedPodUID(uid)] // Safe conversion, map only holds non-mirrors.
|
||||
return pod, ok
|
||||
}
|
||||
|
||||
func (pm *basicManager) GetPodByName(namespace, name string) (*v1.Pod, bool) {
|
||||
podFullName := kubecontainer.BuildPodFullName(name, namespace)
|
||||
return pm.GetPodByFullName(podFullName)
|
||||
}
|
||||
|
||||
func (pm *basicManager) GetPodByFullName(podFullName string) (*v1.Pod, bool) {
|
||||
pm.lock.RLock()
|
||||
defer pm.lock.RUnlock()
|
||||
pod, ok := pm.podByFullName[podFullName]
|
||||
return pod, ok
|
||||
}
|
||||
|
||||
func (pm *basicManager) TranslatePodUID(uid types.UID) kubetypes.ResolvedPodUID {
|
||||
// It is safe to type convert to a resolved UID because type conversion is idempotent.
|
||||
if uid == "" {
|
||||
return kubetypes.ResolvedPodUID(uid)
|
||||
}
|
||||
|
||||
pm.lock.RLock()
|
||||
defer pm.lock.RUnlock()
|
||||
if translated, ok := pm.translationByUID[kubetypes.MirrorPodUID(uid)]; ok {
|
||||
return translated
|
||||
}
|
||||
return kubetypes.ResolvedPodUID(uid)
|
||||
}
|
||||
|
||||
func (pm *basicManager) GetUIDTranslations() (podToMirror map[kubetypes.ResolvedPodUID]kubetypes.MirrorPodUID,
|
||||
mirrorToPod map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID) {
|
||||
pm.lock.RLock()
|
||||
defer pm.lock.RUnlock()
|
||||
|
||||
podToMirror = make(map[kubetypes.ResolvedPodUID]kubetypes.MirrorPodUID, len(pm.translationByUID))
|
||||
mirrorToPod = make(map[kubetypes.MirrorPodUID]kubetypes.ResolvedPodUID, len(pm.translationByUID))
|
||||
// Insert empty translation mapping for all static pods.
|
||||
for uid, pod := range pm.podByUID {
|
||||
if !IsStaticPod(pod) {
|
||||
continue
|
||||
}
|
||||
podToMirror[uid] = ""
|
||||
}
|
||||
// Fill in translations. Notice that if there is no mirror pod for a
|
||||
// static pod, its uid will be translated into empty string "". This
|
||||
// is WAI, from the caller side we can know that the static pod doesn't
|
||||
// have a corresponding mirror pod instead of using static pod uid directly.
|
||||
for k, v := range pm.translationByUID {
|
||||
mirrorToPod[k] = v
|
||||
podToMirror[v] = k
|
||||
}
|
||||
return podToMirror, mirrorToPod
|
||||
}
|
||||
|
||||
func (pm *basicManager) getOrphanedMirrorPodNames() []string {
|
||||
pm.lock.RLock()
|
||||
defer pm.lock.RUnlock()
|
||||
var podFullNames []string
|
||||
for podFullName := range pm.mirrorPodByFullName {
|
||||
if _, ok := pm.podByFullName[podFullName]; !ok {
|
||||
podFullNames = append(podFullNames, podFullName)
|
||||
}
|
||||
}
|
||||
return podFullNames
|
||||
}
|
||||
|
||||
func (pm *basicManager) DeleteOrphanedMirrorPods() {
|
||||
podFullNames := pm.getOrphanedMirrorPodNames()
|
||||
for _, podFullName := range podFullNames {
|
||||
pm.MirrorClient.DeleteMirrorPod(podFullName)
|
||||
}
|
||||
}
|
||||
|
||||
func (pm *basicManager) IsMirrorPodOf(mirrorPod, pod *v1.Pod) bool {
|
||||
// Check name and namespace first.
|
||||
if pod.Name != mirrorPod.Name || pod.Namespace != mirrorPod.Namespace {
|
||||
return false
|
||||
}
|
||||
hash, ok := getHashFromMirrorPod(mirrorPod)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return hash == getPodHash(pod)
|
||||
}
|
||||
|
||||
func podsMapToPods(UIDMap map[kubetypes.ResolvedPodUID]*v1.Pod) []*v1.Pod {
|
||||
pods := make([]*v1.Pod, 0, len(UIDMap))
|
||||
for _, pod := range UIDMap {
|
||||
pods = append(pods, pod)
|
||||
}
|
||||
return pods
|
||||
}
|
||||
|
||||
func mirrorPodsMapToMirrorPods(UIDMap map[kubetypes.MirrorPodUID]*v1.Pod) []*v1.Pod {
|
||||
pods := make([]*v1.Pod, 0, len(UIDMap))
|
||||
for _, pod := range UIDMap {
|
||||
pods = append(pods, pod)
|
||||
}
|
||||
return pods
|
||||
}
|
||||
|
||||
func (pm *basicManager) GetMirrorPodByPod(pod *v1.Pod) (*v1.Pod, bool) {
|
||||
pm.lock.RLock()
|
||||
defer pm.lock.RUnlock()
|
||||
mirrorPod, ok := pm.mirrorPodByFullName[kubecontainer.GetPodFullName(pod)]
|
||||
return mirrorPod, ok
|
||||
}
|
||||
|
||||
func (pm *basicManager) GetPodByMirrorPod(mirrorPod *v1.Pod) (*v1.Pod, bool) {
|
||||
pm.lock.RLock()
|
||||
defer pm.lock.RUnlock()
|
||||
pod, ok := pm.podByFullName[kubecontainer.GetPodFullName(mirrorPod)]
|
||||
return pod, ok
|
||||
}
|
40
vendor/k8s.io/kubernetes/pkg/kubelet/secret/fake_manager.go
generated
vendored
Normal file
40
vendor/k8s.io/kubernetes/pkg/kubelet/secret/fake_manager.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
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 secret
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// fakeManager implements Manager interface for testing purposes.
|
||||
// simple operations to apiserver.
|
||||
type fakeManager struct {
|
||||
}
|
||||
|
||||
func NewFakeManager() Manager {
|
||||
return &fakeManager{}
|
||||
}
|
||||
|
||||
func (s *fakeManager) GetSecret(namespace, name string) (*v1.Secret, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *fakeManager) RegisterPod(pod *v1.Pod) {
|
||||
}
|
||||
|
||||
func (s *fakeManager) UnregisterPod(pod *v1.Pod) {
|
||||
}
|
149
vendor/k8s.io/kubernetes/pkg/kubelet/secret/secret_manager.go
generated
vendored
Normal file
149
vendor/k8s.io/kubernetes/pkg/kubelet/secret/secret_manager.go
generated
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
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 secret
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/manager"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
)
|
||||
|
||||
type Manager interface {
|
||||
// Get secret by secret namespace and name.
|
||||
GetSecret(namespace, name string) (*v1.Secret, error)
|
||||
|
||||
// WARNING: Register/UnregisterPod functions should be efficient,
|
||||
// i.e. should not block on network operations.
|
||||
|
||||
// RegisterPod registers all secrets from a given pod.
|
||||
RegisterPod(pod *v1.Pod)
|
||||
|
||||
// UnregisterPod unregisters secrets from a given pod that are not
|
||||
// used by any other registered pod.
|
||||
UnregisterPod(pod *v1.Pod)
|
||||
}
|
||||
|
||||
// simpleSecretManager implements SecretManager interfaces with
|
||||
// simple operations to apiserver.
|
||||
type simpleSecretManager struct {
|
||||
kubeClient clientset.Interface
|
||||
}
|
||||
|
||||
func NewSimpleSecretManager(kubeClient clientset.Interface) Manager {
|
||||
return &simpleSecretManager{kubeClient: kubeClient}
|
||||
}
|
||||
|
||||
func (s *simpleSecretManager) GetSecret(namespace, name string) (*v1.Secret, error) {
|
||||
return s.kubeClient.CoreV1().Secrets(namespace).Get(name, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
func (s *simpleSecretManager) RegisterPod(pod *v1.Pod) {
|
||||
}
|
||||
|
||||
func (s *simpleSecretManager) UnregisterPod(pod *v1.Pod) {
|
||||
}
|
||||
|
||||
// secretManager keeps a store with secrets necessary
|
||||
// for registered pods. Different implementations of the store
|
||||
// may result in different semantics for freshness of secrets
|
||||
// (e.g. ttl-based implementation vs watch-based implementation).
|
||||
type secretManager struct {
|
||||
manager manager.Manager
|
||||
}
|
||||
|
||||
func (s *secretManager) GetSecret(namespace, name string) (*v1.Secret, error) {
|
||||
object, err := s.manager.GetObject(namespace, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret, ok := object.(*v1.Secret); ok {
|
||||
return secret, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected object type: %v", object)
|
||||
}
|
||||
|
||||
func (s *secretManager) RegisterPod(pod *v1.Pod) {
|
||||
s.manager.RegisterPod(pod)
|
||||
}
|
||||
|
||||
func (s *secretManager) UnregisterPod(pod *v1.Pod) {
|
||||
s.manager.UnregisterPod(pod)
|
||||
}
|
||||
|
||||
func getSecretNames(pod *v1.Pod) sets.String {
|
||||
result := sets.NewString()
|
||||
podutil.VisitPodSecretNames(pod, func(name string) bool {
|
||||
result.Insert(name)
|
||||
return true
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
const (
|
||||
defaultTTL = time.Minute
|
||||
)
|
||||
|
||||
// NewCachingSecretManager creates a manager that keeps a cache of all secrets
|
||||
// necessary for registered pods.
|
||||
// It implements the following logic:
|
||||
// - whenever a pod is created or updated, the cached versions of all secrets
|
||||
// are invalidated
|
||||
// - every GetObject() call tries to fetch the value from local cache; if it is
|
||||
// not there, invalidated or too old, we fetch it from apiserver and refresh the
|
||||
// value in cache; otherwise it is just fetched from cache
|
||||
func NewCachingSecretManager(kubeClient clientset.Interface, getTTL manager.GetObjectTTLFunc) Manager {
|
||||
getSecret := func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) {
|
||||
return kubeClient.CoreV1().Secrets(namespace).Get(name, opts)
|
||||
}
|
||||
secretStore := manager.NewObjectStore(getSecret, clock.RealClock{}, getTTL, defaultTTL)
|
||||
return &secretManager{
|
||||
manager: manager.NewCacheBasedManager(secretStore, getSecretNames),
|
||||
}
|
||||
}
|
||||
|
||||
// NewWatchingSecretManager creates a manager that keeps a cache of all secrets
|
||||
// necessary for registered pods.
|
||||
// It implements the following logic:
|
||||
// - whenever a pod is created or updated, we start individual watches for all
|
||||
// referenced objects that aren't referenced from other registered pods
|
||||
// - every GetObject() returns a value from local cache propagated via watches
|
||||
func NewWatchingSecretManager(kubeClient clientset.Interface) Manager {
|
||||
listSecret := func(namespace string, opts metav1.ListOptions) (runtime.Object, error) {
|
||||
return kubeClient.CoreV1().Secrets(namespace).List(opts)
|
||||
}
|
||||
watchSecret := func(namespace string, opts metav1.ListOptions) (watch.Interface, error) {
|
||||
return kubeClient.CoreV1().Secrets(namespace).Watch(opts)
|
||||
}
|
||||
newSecret := func() runtime.Object {
|
||||
return &v1.Secret{}
|
||||
}
|
||||
gr := corev1.Resource("secret")
|
||||
return &secretManager{
|
||||
manager: manager.NewWatchBasedManager(listSecret, watchSecret, newSecret, gr, getSecretNames),
|
||||
}
|
||||
}
|
44
vendor/k8s.io/kubernetes/pkg/kubelet/util/boottime_util_darwin.go
generated
vendored
Normal file
44
vendor/k8s.io/kubernetes/pkg/kubelet/util/boottime_util_darwin.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
// +build darwin
|
||||
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// GetBootTime returns the time at which the machine was started, truncated to the nearest second
|
||||
func GetBootTime() (time.Time, error) {
|
||||
output, err := unix.SysctlRaw("kern.boottime")
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
var timeval syscall.Timeval
|
||||
if len(output) != int(unsafe.Sizeof(timeval)) {
|
||||
return time.Time{}, fmt.Errorf("unexpected output when calling syscall kern.bootime. Expected len(output) to be %v, but got %v",
|
||||
int(unsafe.Sizeof(timeval)), len(output))
|
||||
}
|
||||
timeval = *(*syscall.Timeval)(unsafe.Pointer(&output[0]))
|
||||
sec, nsec := timeval.Unix()
|
||||
return time.Unix(sec, nsec).Truncate(time.Second), nil
|
||||
}
|
36
vendor/k8s.io/kubernetes/pkg/kubelet/util/boottime_util_linux.go
generated
vendored
Normal file
36
vendor/k8s.io/kubernetes/pkg/kubelet/util/boottime_util_linux.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
// +build freebsd linux
|
||||
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// GetBootTime returns the time at which the machine was started, truncated to the nearest second
|
||||
func GetBootTime() (time.Time, error) {
|
||||
currentTime := time.Now()
|
||||
var info unix.Sysinfo_t
|
||||
if err := unix.Sysinfo(&info); err != nil {
|
||||
return time.Time{}, fmt.Errorf("error getting system uptime: %s", err)
|
||||
}
|
||||
return currentTime.Add(-time.Duration(info.Uptime) * time.Second).Truncate(time.Second), nil
|
||||
}
|
18
vendor/k8s.io/kubernetes/pkg/kubelet/util/doc.go
generated
vendored
Normal file
18
vendor/k8s.io/kubernetes/pkg/kubelet/util/doc.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
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 util holds utility functions.
|
||||
package util // import "k8s.io/kubernetes/pkg/kubelet/util"
|
272
vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/cache_based_manager.go
generated
vendored
Normal file
272
vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/cache_based_manager.go
generated
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
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 manager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
storageetcd "k8s.io/apiserver/pkg/storage/etcd"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
// GetObjectTTLFunc defines a function to get value of TTL.
|
||||
type GetObjectTTLFunc func() (time.Duration, bool)
|
||||
|
||||
// GetObjectFunc defines a function to get object with a given namespace and name.
|
||||
type GetObjectFunc func(string, string, metav1.GetOptions) (runtime.Object, error)
|
||||
|
||||
type objectKey struct {
|
||||
namespace string
|
||||
name string
|
||||
}
|
||||
|
||||
// objectStoreItems is a single item stored in objectStore.
|
||||
type objectStoreItem struct {
|
||||
refCount int
|
||||
data *objectData
|
||||
}
|
||||
|
||||
type objectData struct {
|
||||
sync.Mutex
|
||||
|
||||
object runtime.Object
|
||||
err error
|
||||
lastUpdateTime time.Time
|
||||
}
|
||||
|
||||
// objectStore is a local cache of objects.
|
||||
type objectStore struct {
|
||||
getObject GetObjectFunc
|
||||
clock clock.Clock
|
||||
|
||||
lock sync.Mutex
|
||||
items map[objectKey]*objectStoreItem
|
||||
|
||||
defaultTTL time.Duration
|
||||
getTTL GetObjectTTLFunc
|
||||
}
|
||||
|
||||
// NewObjectStore returns a new ttl-based instance of Store interface.
|
||||
func NewObjectStore(getObject GetObjectFunc, clock clock.Clock, getTTL GetObjectTTLFunc, ttl time.Duration) Store {
|
||||
return &objectStore{
|
||||
getObject: getObject,
|
||||
clock: clock,
|
||||
items: make(map[objectKey]*objectStoreItem),
|
||||
defaultTTL: ttl,
|
||||
getTTL: getTTL,
|
||||
}
|
||||
}
|
||||
|
||||
func isObjectOlder(newObject, oldObject runtime.Object) bool {
|
||||
if newObject == nil || oldObject == nil {
|
||||
return false
|
||||
}
|
||||
newVersion, _ := storageetcd.Versioner.ObjectResourceVersion(newObject)
|
||||
oldVersion, _ := storageetcd.Versioner.ObjectResourceVersion(oldObject)
|
||||
return newVersion < oldVersion
|
||||
}
|
||||
|
||||
func (s *objectStore) AddReference(namespace, name string) {
|
||||
key := objectKey{namespace: namespace, name: name}
|
||||
|
||||
// AddReference is called from RegisterPod, thus it needs to be efficient.
|
||||
// Thus Add() is only increasing refCount and generation of a given object.
|
||||
// Then Get() is responsible for fetching if needed.
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
item, exists := s.items[key]
|
||||
if !exists {
|
||||
item = &objectStoreItem{
|
||||
refCount: 0,
|
||||
data: &objectData{},
|
||||
}
|
||||
s.items[key] = item
|
||||
}
|
||||
|
||||
item.refCount++
|
||||
// This will trigger fetch on the next Get() operation.
|
||||
item.data = nil
|
||||
}
|
||||
|
||||
func (s *objectStore) DeleteReference(namespace, name string) {
|
||||
key := objectKey{namespace: namespace, name: name}
|
||||
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
if item, ok := s.items[key]; ok {
|
||||
item.refCount--
|
||||
if item.refCount == 0 {
|
||||
delete(s.items, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetObjectTTLFromNodeFunc returns a function that returns TTL value
|
||||
// from a given Node object.
|
||||
func GetObjectTTLFromNodeFunc(getNode func() (*v1.Node, error)) GetObjectTTLFunc {
|
||||
return func() (time.Duration, bool) {
|
||||
node, err := getNode()
|
||||
if err != nil {
|
||||
return time.Duration(0), false
|
||||
}
|
||||
if node != nil && node.Annotations != nil {
|
||||
if value, ok := node.Annotations[v1.ObjectTTLAnnotationKey]; ok {
|
||||
if intValue, err := strconv.Atoi(value); err == nil {
|
||||
return time.Duration(intValue) * time.Second, true
|
||||
}
|
||||
}
|
||||
}
|
||||
return time.Duration(0), false
|
||||
}
|
||||
}
|
||||
|
||||
func (s *objectStore) isObjectFresh(data *objectData) bool {
|
||||
objectTTL := s.defaultTTL
|
||||
if ttl, ok := s.getTTL(); ok {
|
||||
objectTTL = ttl
|
||||
}
|
||||
return s.clock.Now().Before(data.lastUpdateTime.Add(objectTTL))
|
||||
}
|
||||
|
||||
func (s *objectStore) Get(namespace, name string) (runtime.Object, error) {
|
||||
key := objectKey{namespace: namespace, name: name}
|
||||
|
||||
data := func() *objectData {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
item, exists := s.items[key]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
if item.data == nil {
|
||||
item.data = &objectData{}
|
||||
}
|
||||
return item.data
|
||||
}()
|
||||
if data == nil {
|
||||
return nil, fmt.Errorf("object %q/%q not registered", namespace, name)
|
||||
}
|
||||
|
||||
// After updating data in objectStore, lock the data, fetch object if
|
||||
// needed and return data.
|
||||
data.Lock()
|
||||
defer data.Unlock()
|
||||
if data.err != nil || !s.isObjectFresh(data) {
|
||||
opts := metav1.GetOptions{}
|
||||
if data.object != nil && data.err == nil {
|
||||
// This is just a periodic refresh of an object we successfully fetched previously.
|
||||
// In this case, server data from apiserver cache to reduce the load on both
|
||||
// etcd and apiserver (the cache is eventually consistent).
|
||||
util.FromApiserverCache(&opts)
|
||||
}
|
||||
|
||||
object, err := s.getObject(namespace, name, opts)
|
||||
if err != nil && !apierrors.IsNotFound(err) && data.object == nil && data.err == nil {
|
||||
// Couldn't fetch the latest object, but there is no cached data to return.
|
||||
// Return the fetch result instead.
|
||||
return object, err
|
||||
}
|
||||
if (err == nil && !isObjectOlder(object, data.object)) || apierrors.IsNotFound(err) {
|
||||
// If the fetch succeeded with a newer version of the object, or if the
|
||||
// object could not be found in the apiserver, update the cached data to
|
||||
// reflect the current status.
|
||||
data.object = object
|
||||
data.err = err
|
||||
data.lastUpdateTime = s.clock.Now()
|
||||
}
|
||||
}
|
||||
return data.object, data.err
|
||||
}
|
||||
|
||||
// cacheBasedManager keeps a store with objects necessary
|
||||
// for registered pods. Different implementations of the store
|
||||
// may result in different semantics for freshness of objects
|
||||
// (e.g. ttl-based implementation vs watch-based implementation).
|
||||
type cacheBasedManager struct {
|
||||
objectStore Store
|
||||
getReferencedObjects func(*v1.Pod) sets.String
|
||||
|
||||
lock sync.Mutex
|
||||
registeredPods map[objectKey]*v1.Pod
|
||||
}
|
||||
|
||||
func (c *cacheBasedManager) GetObject(namespace, name string) (runtime.Object, error) {
|
||||
return c.objectStore.Get(namespace, name)
|
||||
}
|
||||
|
||||
func (c *cacheBasedManager) RegisterPod(pod *v1.Pod) {
|
||||
names := c.getReferencedObjects(pod)
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
for name := range names {
|
||||
c.objectStore.AddReference(pod.Namespace, name)
|
||||
}
|
||||
var prev *v1.Pod
|
||||
key := objectKey{namespace: pod.Namespace, name: pod.Name}
|
||||
prev = c.registeredPods[key]
|
||||
c.registeredPods[key] = pod
|
||||
if prev != nil {
|
||||
for name := range c.getReferencedObjects(prev) {
|
||||
// On an update, the .Add() call above will have re-incremented the
|
||||
// ref count of any existing object, so any objects that are in both
|
||||
// names and prev need to have their ref counts decremented. Any that
|
||||
// are only in prev need to be completely removed. This unconditional
|
||||
// call takes care of both cases.
|
||||
c.objectStore.DeleteReference(prev.Namespace, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cacheBasedManager) UnregisterPod(pod *v1.Pod) {
|
||||
var prev *v1.Pod
|
||||
key := objectKey{namespace: pod.Namespace, name: pod.Name}
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
prev = c.registeredPods[key]
|
||||
delete(c.registeredPods, key)
|
||||
if prev != nil {
|
||||
for name := range c.getReferencedObjects(prev) {
|
||||
c.objectStore.DeleteReference(prev.Namespace, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewCacheBasedManager creates a manager that keeps a cache of all objects
|
||||
// necessary for registered pods.
|
||||
// It implements the following logic:
|
||||
// - whenever a pod is created or updated, the cached versions of all objects
|
||||
// is referencing are invalidated
|
||||
// - every GetObject() call tries to fetch the value from local cache; if it is
|
||||
// not there, invalidated or too old, we fetch it from apiserver and refresh the
|
||||
// value in cache; otherwise it is just fetched from cache
|
||||
func NewCacheBasedManager(objectStore Store, getReferencedObjects func(*v1.Pod) sets.String) Manager {
|
||||
return &cacheBasedManager{
|
||||
objectStore: objectStore,
|
||||
getReferencedObjects: getReferencedObjects,
|
||||
registeredPods: make(map[objectKey]*v1.Pod),
|
||||
}
|
||||
}
|
60
vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/manager.go
generated
vendored
Normal file
60
vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/manager.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
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 manager
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// Manager is the interface for registering and unregistering
|
||||
// objects referenced by pods in the underlying cache and
|
||||
// extracting those from that cache if needed.
|
||||
type Manager interface {
|
||||
// Get object by its namespace and name.
|
||||
GetObject(namespace, name string) (runtime.Object, error)
|
||||
|
||||
// WARNING: Register/UnregisterPod functions should be efficient,
|
||||
// i.e. should not block on network operations.
|
||||
|
||||
// RegisterPod registers all objects referenced from a given pod.
|
||||
//
|
||||
// NOTE: All implementations of RegisterPod should be idempotent.
|
||||
RegisterPod(pod *v1.Pod)
|
||||
|
||||
// UnregisterPod unregisters objects referenced from a given pod that are not
|
||||
// used by any other registered pod.
|
||||
//
|
||||
// NOTE: All implementations of UnregisterPod should be idempotent.
|
||||
UnregisterPod(pod *v1.Pod)
|
||||
}
|
||||
|
||||
// Store is the interface for a object cache that
|
||||
// can be used by cacheBasedManager.
|
||||
type Store interface {
|
||||
// AddReference adds a reference to the object to the store.
|
||||
// Note that multiple additions to the store has to be allowed
|
||||
// in the implementations and effectively treated as refcounted.
|
||||
AddReference(namespace, name string)
|
||||
// DeleteReference deletes reference to the object from the store.
|
||||
// Note that object should be deleted only when there was a
|
||||
// corresponding Delete call for each of Add calls (effectively
|
||||
// when refcount was reduced to zero).
|
||||
DeleteReference(namespace, name string)
|
||||
// Get an object from a store.
|
||||
Get(namespace, name string) (runtime.Object, error)
|
||||
}
|
194
vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/watch_based_manager.go
generated
vendored
Normal file
194
vendor/k8s.io/kubernetes/pkg/kubelet/util/manager/watch_based_manager.go
generated
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// TODO: We did some scalability tests and using watchBasedManager
|
||||
// seems to help with apiserver performance at scale visibly.
|
||||
// No issues we also observed at the scale of ~200k watchers with a
|
||||
// single apiserver.
|
||||
// However, we need to perform more extensive testing before we
|
||||
// enable this in production setups.
|
||||
|
||||
package manager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
)
|
||||
|
||||
type listObjectFunc func(string, metav1.ListOptions) (runtime.Object, error)
|
||||
type watchObjectFunc func(string, metav1.ListOptions) (watch.Interface, error)
|
||||
type newObjectFunc func() runtime.Object
|
||||
|
||||
// objectCacheItem is a single item stored in objectCache.
|
||||
type objectCacheItem struct {
|
||||
refCount int
|
||||
store cache.Store
|
||||
hasSynced func() (bool, error)
|
||||
stopCh chan struct{}
|
||||
}
|
||||
|
||||
// objectCache is a local cache of objects propagated via
|
||||
// individual watches.
|
||||
type objectCache struct {
|
||||
listObject listObjectFunc
|
||||
watchObject watchObjectFunc
|
||||
newObject newObjectFunc
|
||||
groupResource schema.GroupResource
|
||||
|
||||
lock sync.Mutex
|
||||
items map[objectKey]*objectCacheItem
|
||||
}
|
||||
|
||||
// NewObjectCache returns a new watch-based instance of Store interface.
|
||||
func NewObjectCache(listObject listObjectFunc, watchObject watchObjectFunc, newObject newObjectFunc, groupResource schema.GroupResource) Store {
|
||||
return &objectCache{
|
||||
listObject: listObject,
|
||||
watchObject: watchObject,
|
||||
newObject: newObject,
|
||||
groupResource: groupResource,
|
||||
items: make(map[objectKey]*objectCacheItem),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *objectCache) newStore() cache.Store {
|
||||
// TODO: We may consider created a dedicated store keeping just a single
|
||||
// item, instead of using a generic store implementation for this purpose.
|
||||
// However, simple benchmarks show that memory overhead in that case is
|
||||
// decrease from ~600B to ~300B per object. So we are not optimizing it
|
||||
// until we will see a good reason for that.
|
||||
return cache.NewStore(cache.MetaNamespaceKeyFunc)
|
||||
}
|
||||
|
||||
func (c *objectCache) newReflector(namespace, name string) *objectCacheItem {
|
||||
fieldSelector := fields.Set{"metadata.name": name}.AsSelector().String()
|
||||
listFunc := func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
options.FieldSelector = fieldSelector
|
||||
return c.listObject(namespace, options)
|
||||
}
|
||||
watchFunc := func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
options.FieldSelector = fieldSelector
|
||||
return c.watchObject(namespace, options)
|
||||
}
|
||||
store := c.newStore()
|
||||
reflector := cache.NewNamedReflector(
|
||||
fmt.Sprintf("object-%q/%q", namespace, name),
|
||||
&cache.ListWatch{ListFunc: listFunc, WatchFunc: watchFunc},
|
||||
c.newObject(),
|
||||
store,
|
||||
0,
|
||||
)
|
||||
stopCh := make(chan struct{})
|
||||
go reflector.Run(stopCh)
|
||||
return &objectCacheItem{
|
||||
refCount: 0,
|
||||
store: store,
|
||||
hasSynced: func() (bool, error) { return reflector.LastSyncResourceVersion() != "", nil },
|
||||
stopCh: stopCh,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *objectCache) AddReference(namespace, name string) {
|
||||
key := objectKey{namespace: namespace, name: name}
|
||||
|
||||
// AddReference is called from RegisterPod thus it needs to be efficient.
|
||||
// Thus, it is only increaisng refCount and in case of first registration
|
||||
// of a given object it starts corresponding reflector.
|
||||
// It's responsibility of the first Get operation to wait until the
|
||||
// reflector propagated the store.
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
item, exists := c.items[key]
|
||||
if !exists {
|
||||
item = c.newReflector(namespace, name)
|
||||
c.items[key] = item
|
||||
}
|
||||
item.refCount++
|
||||
}
|
||||
|
||||
func (c *objectCache) DeleteReference(namespace, name string) {
|
||||
key := objectKey{namespace: namespace, name: name}
|
||||
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
if item, ok := c.items[key]; ok {
|
||||
item.refCount--
|
||||
if item.refCount == 0 {
|
||||
// Stop the underlying reflector.
|
||||
close(item.stopCh)
|
||||
delete(c.items, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// key returns key of an object with a given name and namespace.
|
||||
// This has to be in-sync with cache.MetaNamespaceKeyFunc.
|
||||
func (c *objectCache) key(namespace, name string) string {
|
||||
if len(namespace) > 0 {
|
||||
return namespace + "/" + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func (c *objectCache) Get(namespace, name string) (runtime.Object, error) {
|
||||
key := objectKey{namespace: namespace, name: name}
|
||||
|
||||
c.lock.Lock()
|
||||
item, exists := c.items[key]
|
||||
c.lock.Unlock()
|
||||
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("object %q/%q not registered", namespace, name)
|
||||
}
|
||||
if err := wait.PollImmediate(10*time.Millisecond, time.Second, item.hasSynced); err != nil {
|
||||
return nil, fmt.Errorf("couldn't propagate object cache: %v", err)
|
||||
}
|
||||
|
||||
obj, exists, err := item.store.GetByKey(c.key(namespace, name))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, apierrors.NewNotFound(c.groupResource, name)
|
||||
}
|
||||
if object, ok := obj.(runtime.Object); ok {
|
||||
return object, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected object type: %v", obj)
|
||||
}
|
||||
|
||||
// NewWatchBasedManager creates a manager that keeps a cache of all objects
|
||||
// necessary for registered pods.
|
||||
// It implements the following logic:
|
||||
// - whenever a pod is created or updated, we start individual watches for all
|
||||
// referenced objects that aren't referenced from other registered pods
|
||||
// - every GetObject() returns a value from local cache propagated via watches
|
||||
func NewWatchBasedManager(listObject listObjectFunc, watchObject watchObjectFunc, newObject newObjectFunc, groupResource schema.GroupResource, getReferencedObjects func(*v1.Pod) sets.String) Manager {
|
||||
objectStore := NewObjectCache(listObject, watchObject, newObject, groupResource)
|
||||
return NewCacheBasedManager(objectStore, getReferencedObjects)
|
||||
}
|
18
vendor/k8s.io/kubernetes/pkg/kubelet/util/store/doc.go
generated
vendored
Normal file
18
vendor/k8s.io/kubernetes/pkg/kubelet/util/store/doc.go
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
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 store hosts a Store interface and its implementations.
|
||||
package store // import "k8s.io/kubernetes/pkg/kubelet/util/store"
|
167
vendor/k8s.io/kubernetes/pkg/kubelet/util/store/filestore.go
generated
vendored
Normal file
167
vendor/k8s.io/kubernetes/pkg/kubelet/util/store/filestore.go
generated
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
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 store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
utilfs "k8s.io/kubernetes/pkg/util/filesystem"
|
||||
)
|
||||
|
||||
const (
|
||||
// Name prefix for the temporary files.
|
||||
tmpPrefix = "."
|
||||
)
|
||||
|
||||
// FileStore is an implementation of the Store interface which stores data in files.
|
||||
type FileStore struct {
|
||||
// Absolute path to the base directory for storing data files.
|
||||
directoryPath string
|
||||
|
||||
// filesystem to use.
|
||||
filesystem utilfs.Filesystem
|
||||
}
|
||||
|
||||
// NewFileStore returns an instance of FileStore.
|
||||
func NewFileStore(path string, fs utilfs.Filesystem) (Store, error) {
|
||||
if err := ensureDirectory(fs, path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &FileStore{directoryPath: path, filesystem: fs}, nil
|
||||
}
|
||||
|
||||
// Write writes the given data to a file named key.
|
||||
func (f *FileStore) Write(key string, data []byte) error {
|
||||
if err := ValidateKey(key); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ensureDirectory(f.filesystem, f.directoryPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeFile(f.filesystem, f.getPathByKey(key), data)
|
||||
}
|
||||
|
||||
// Read reads the data from the file named key.
|
||||
func (f *FileStore) Read(key string) ([]byte, error) {
|
||||
if err := ValidateKey(key); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bytes, err := f.filesystem.ReadFile(f.getPathByKey(key))
|
||||
if os.IsNotExist(err) {
|
||||
return bytes, ErrKeyNotFound
|
||||
}
|
||||
return bytes, err
|
||||
}
|
||||
|
||||
// Delete deletes the key file.
|
||||
func (f *FileStore) Delete(key string) error {
|
||||
if err := ValidateKey(key); err != nil {
|
||||
return err
|
||||
}
|
||||
return removePath(f.filesystem, f.getPathByKey(key))
|
||||
}
|
||||
|
||||
// List returns all keys in the store.
|
||||
func (f *FileStore) List() ([]string, error) {
|
||||
keys := make([]string, 0)
|
||||
files, err := f.filesystem.ReadDir(f.directoryPath)
|
||||
if err != nil {
|
||||
return keys, err
|
||||
}
|
||||
for _, f := range files {
|
||||
if !strings.HasPrefix(f.Name(), tmpPrefix) {
|
||||
keys = append(keys, f.Name())
|
||||
}
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
// getPathByKey returns the full path of the file for the key.
|
||||
func (f *FileStore) getPathByKey(key string) string {
|
||||
return filepath.Join(f.directoryPath, key)
|
||||
}
|
||||
|
||||
// ensureDirectory creates the directory if it does not exist.
|
||||
func ensureDirectory(fs utilfs.Filesystem, path string) error {
|
||||
if _, err := fs.Stat(path); err != nil {
|
||||
// MkdirAll returns nil if directory already exists.
|
||||
return fs.MkdirAll(path, 0755)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// writeFile writes data to path in a single transaction.
|
||||
func writeFile(fs utilfs.Filesystem, path string, data []byte) (retErr error) {
|
||||
// Create a temporary file in the base directory of `path` with a prefix.
|
||||
tmpFile, err := fs.TempFile(filepath.Dir(path), tmpPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tmpPath := tmpFile.Name()
|
||||
shouldClose := true
|
||||
|
||||
defer func() {
|
||||
// Close the file.
|
||||
if shouldClose {
|
||||
if err := tmpFile.Close(); err != nil {
|
||||
if retErr == nil {
|
||||
retErr = fmt.Errorf("close error: %v", err)
|
||||
} else {
|
||||
retErr = fmt.Errorf("failed to close temp file after error %v; close error: %v", retErr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up the temp file on error.
|
||||
if retErr != nil && tmpPath != "" {
|
||||
if err := removePath(fs, tmpPath); err != nil {
|
||||
retErr = fmt.Errorf("failed to remove the temporary file (%q) after error %v; remove error: %v", tmpPath, retErr, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Write data.
|
||||
if _, err := tmpFile.Write(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sync file.
|
||||
if err := tmpFile.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Closing the file before renaming.
|
||||
err = tmpFile.Close()
|
||||
shouldClose = false
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fs.Rename(tmpPath, path)
|
||||
}
|
||||
|
||||
func removePath(fs utilfs.Filesystem, path string) error {
|
||||
if err := fs.Remove(path); err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
64
vendor/k8s.io/kubernetes/pkg/kubelet/util/store/store.go
generated
vendored
Normal file
64
vendor/k8s.io/kubernetes/pkg/kubelet/util/store/store.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
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 store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
const (
|
||||
keyMaxLength = 250
|
||||
|
||||
keyCharFmt string = "[A-Za-z0-9]"
|
||||
keyExtCharFmt string = "[-A-Za-z0-9_.]"
|
||||
qualifiedKeyFmt string = "(" + keyCharFmt + keyExtCharFmt + "*)?" + keyCharFmt
|
||||
)
|
||||
|
||||
var (
|
||||
// Key must consist of alphanumeric characters, '-', '_' or '.', and must start
|
||||
// and end with an alphanumeric character.
|
||||
keyRegex = regexp.MustCompile("^" + qualifiedKeyFmt + "$")
|
||||
|
||||
// ErrKeyNotFound is the error returned if key is not found in Store.
|
||||
ErrKeyNotFound = fmt.Errorf("key is not found")
|
||||
)
|
||||
|
||||
// Store provides the interface for storing keyed data.
|
||||
// Store must be thread-safe
|
||||
type Store interface {
|
||||
// key must contain one or more characters in [A-Za-z0-9]
|
||||
// Write writes data with key.
|
||||
Write(key string, data []byte) error
|
||||
// Read retrieves data with key
|
||||
// Read must return ErrKeyNotFound if key is not found.
|
||||
Read(key string) ([]byte, error)
|
||||
// Delete deletes data by key
|
||||
// Delete must not return error if key does not exist
|
||||
Delete(key string) error
|
||||
// List lists all existing keys.
|
||||
List() ([]string, error)
|
||||
}
|
||||
|
||||
// ValidateKey returns an error if the given key does not meet the requirement
|
||||
// of the key format and length.
|
||||
func ValidateKey(key string) error {
|
||||
if len(key) <= keyMaxLength && keyRegex.MatchString(key) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid key: %q", key)
|
||||
}
|
27
vendor/k8s.io/kubernetes/pkg/kubelet/util/util.go
generated
vendored
Normal file
27
vendor/k8s.io/kubernetes/pkg/kubelet/util/util.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// FromApiserverCache modifies <opts> so that the GET request will
|
||||
// be served from apiserver cache instead of from etcd.
|
||||
func FromApiserverCache(opts *metav1.GetOptions) {
|
||||
opts.ResourceVersion = "0"
|
||||
}
|
137
vendor/k8s.io/kubernetes/pkg/kubelet/util/util_unix.go
generated
vendored
Normal file
137
vendor/k8s.io/kubernetes/pkg/kubelet/util/util_unix.go
generated
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
// +build freebsd linux darwin
|
||||
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
const (
|
||||
// unixProtocol is the network protocol of unix socket.
|
||||
unixProtocol = "unix"
|
||||
)
|
||||
|
||||
// CreateListener creates a listener on the specified endpoint.
|
||||
func CreateListener(endpoint string) (net.Listener, error) {
|
||||
protocol, addr, err := parseEndpointWithFallbackProtocol(endpoint, unixProtocol)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if protocol != unixProtocol {
|
||||
return nil, fmt.Errorf("only support unix socket endpoint")
|
||||
}
|
||||
|
||||
// Unlink to cleanup the previous socket file.
|
||||
err = unix.Unlink(addr)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("failed to unlink socket file %q: %v", addr, err)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Dir(addr), 0750); err != nil {
|
||||
return nil, fmt.Errorf("error creating socket directory %q: %v", filepath.Dir(addr), err)
|
||||
}
|
||||
|
||||
// Create the socket on a tempfile and move it to the destination socket to handle improprer cleanup
|
||||
file, err := ioutil.TempFile(filepath.Dir(addr), "")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create temporary file: %v", err)
|
||||
}
|
||||
|
||||
if err := os.Remove(file.Name()); err != nil {
|
||||
return nil, fmt.Errorf("failed to remove temporary file: %v", err)
|
||||
}
|
||||
|
||||
l, err := net.Listen(protocol, file.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = os.Rename(file.Name(), addr); err != nil {
|
||||
return nil, fmt.Errorf("failed to move temporary file to addr %q: %v", addr, err)
|
||||
}
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// GetAddressAndDialer returns the address parsed from the given endpoint and a dialer.
|
||||
func GetAddressAndDialer(endpoint string) (string, func(addr string, timeout time.Duration) (net.Conn, error), error) {
|
||||
protocol, addr, err := parseEndpointWithFallbackProtocol(endpoint, unixProtocol)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
if protocol != unixProtocol {
|
||||
return "", nil, fmt.Errorf("only support unix socket endpoint")
|
||||
}
|
||||
|
||||
return addr, dial, nil
|
||||
}
|
||||
|
||||
func dial(addr string, timeout time.Duration) (net.Conn, error) {
|
||||
return net.DialTimeout(unixProtocol, addr, timeout)
|
||||
}
|
||||
|
||||
func parseEndpointWithFallbackProtocol(endpoint string, fallbackProtocol string) (protocol string, addr string, err error) {
|
||||
if protocol, addr, err = parseEndpoint(endpoint); err != nil && protocol == "" {
|
||||
fallbackEndpoint := fallbackProtocol + "://" + endpoint
|
||||
protocol, addr, err = parseEndpoint(fallbackEndpoint)
|
||||
if err == nil {
|
||||
klog.Warningf("Using %q as endpoint is deprecated, please consider using full url format %q.", endpoint, fallbackEndpoint)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseEndpoint(endpoint string) (string, string, error) {
|
||||
u, err := url.Parse(endpoint)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
switch u.Scheme {
|
||||
case "tcp":
|
||||
return "tcp", u.Host, nil
|
||||
|
||||
case "unix":
|
||||
return "unix", u.Path, nil
|
||||
|
||||
case "":
|
||||
return "", "", fmt.Errorf("Using %q as endpoint is deprecated, please consider using full url format", endpoint)
|
||||
|
||||
default:
|
||||
return u.Scheme, "", fmt.Errorf("protocol %q not supported", u.Scheme)
|
||||
}
|
||||
}
|
||||
|
||||
// LocalEndpoint returns the full path to a unix socket at the given endpoint
|
||||
func LocalEndpoint(path, file string) (string, error) {
|
||||
u := url.URL{
|
||||
Scheme: unixProtocol,
|
||||
Path: path,
|
||||
}
|
||||
return filepath.Join(u.String(), file+".sock"), nil
|
||||
}
|
54
vendor/k8s.io/kubernetes/pkg/kubelet/util/util_unsupported.go
generated
vendored
Normal file
54
vendor/k8s.io/kubernetes/pkg/kubelet/util/util_unsupported.go
generated
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
// +build !freebsd,!linux,!windows,!darwin
|
||||
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// CreateListener creates a listener on the specified endpoint.
|
||||
func CreateListener(endpoint string) (net.Listener, error) {
|
||||
return nil, fmt.Errorf("CreateListener is unsupported in this build")
|
||||
}
|
||||
|
||||
// GetAddressAndDialer returns the address parsed from the given endpoint and a dialer.
|
||||
func GetAddressAndDialer(endpoint string) (string, func(addr string, timeout time.Duration) (net.Conn, error), error) {
|
||||
return "", nil, fmt.Errorf("GetAddressAndDialer is unsupported in this build")
|
||||
}
|
||||
|
||||
// LockAndCheckSubPath empty implementation
|
||||
func LockAndCheckSubPath(volumePath, subPath string) ([]uintptr, error) {
|
||||
return []uintptr{}, nil
|
||||
}
|
||||
|
||||
// UnlockPath empty implementation
|
||||
func UnlockPath(fileHandles []uintptr) {
|
||||
}
|
||||
|
||||
// LocalEndpoint empty implementation
|
||||
func LocalEndpoint(path, file string) (string, error) {
|
||||
return "", fmt.Errorf("LocalEndpoints are unsupported in this build")
|
||||
}
|
||||
|
||||
// GetBootTime empty implementation
|
||||
func GetBootTime() (time.Time, error) {
|
||||
return time.Time{}, fmt.Errorf("GetBootTime is unsupported in this build")
|
||||
}
|
125
vendor/k8s.io/kubernetes/pkg/kubelet/util/util_windows.go
generated
vendored
Normal file
125
vendor/k8s.io/kubernetes/pkg/kubelet/util/util_windows.go
generated
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
// +build windows
|
||||
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
)
|
||||
|
||||
const (
|
||||
tcpProtocol = "tcp"
|
||||
npipeProtocol = "npipe"
|
||||
)
|
||||
|
||||
// CreateListener creates a listener on the specified endpoint.
|
||||
func CreateListener(endpoint string) (net.Listener, error) {
|
||||
protocol, addr, err := parseEndpoint(endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch protocol {
|
||||
case tcpProtocol:
|
||||
return net.Listen(tcpProtocol, addr)
|
||||
|
||||
case npipeProtocol:
|
||||
return winio.ListenPipe(addr, nil)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("only support tcp and npipe endpoint")
|
||||
}
|
||||
}
|
||||
|
||||
// GetAddressAndDialer returns the address parsed from the given endpoint and a dialer.
|
||||
func GetAddressAndDialer(endpoint string) (string, func(addr string, timeout time.Duration) (net.Conn, error), error) {
|
||||
protocol, addr, err := parseEndpoint(endpoint)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if protocol == tcpProtocol {
|
||||
return addr, tcpDial, nil
|
||||
}
|
||||
|
||||
if protocol == npipeProtocol {
|
||||
return addr, npipeDial, nil
|
||||
}
|
||||
|
||||
return "", nil, fmt.Errorf("only support tcp and npipe endpoint")
|
||||
}
|
||||
|
||||
func tcpDial(addr string, timeout time.Duration) (net.Conn, error) {
|
||||
return net.DialTimeout(tcpProtocol, addr, timeout)
|
||||
}
|
||||
|
||||
func npipeDial(addr string, timeout time.Duration) (net.Conn, error) {
|
||||
return winio.DialPipe(addr, &timeout)
|
||||
}
|
||||
|
||||
func parseEndpoint(endpoint string) (string, string, error) {
|
||||
// url.Parse doesn't recognize \, so replace with / first.
|
||||
endpoint = strings.Replace(endpoint, "\\", "/", -1)
|
||||
u, err := url.Parse(endpoint)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if u.Scheme == "tcp" {
|
||||
return "tcp", u.Host, nil
|
||||
} else if u.Scheme == "npipe" {
|
||||
if strings.HasPrefix(u.Path, "//./pipe") {
|
||||
return "npipe", u.Path, nil
|
||||
}
|
||||
|
||||
// fallback host if not provided.
|
||||
host := u.Host
|
||||
if host == "" {
|
||||
host = "."
|
||||
}
|
||||
return "npipe", fmt.Sprintf("//%s%s", host, u.Path), nil
|
||||
} else if u.Scheme == "" {
|
||||
return "", "", fmt.Errorf("Using %q as endpoint is deprecated, please consider using full url format", endpoint)
|
||||
} else {
|
||||
return u.Scheme, "", fmt.Errorf("protocol %q not supported", u.Scheme)
|
||||
}
|
||||
}
|
||||
|
||||
// LocalEndpoint empty implementation
|
||||
func LocalEndpoint(path, file string) (string, error) {
|
||||
return "", fmt.Errorf("LocalEndpoints are unsupported in this build")
|
||||
}
|
||||
|
||||
var tickCount = syscall.NewLazyDLL("kernel32.dll").NewProc("GetTickCount64")
|
||||
|
||||
// GetBootTime returns the time at which the machine was started, truncated to the nearest second
|
||||
func GetBootTime() (time.Time, error) {
|
||||
currentTime := time.Now()
|
||||
output, _, err := tickCount.Call()
|
||||
if errno, ok := err.(syscall.Errno); !ok || errno != 0 {
|
||||
return time.Time{}, err
|
||||
}
|
||||
return currentTime.Add(-time.Duration(output) * time.Millisecond).Truncate(time.Second), nil
|
||||
}
|
Reference in New Issue
Block a user