Vendor changes for v1.6.0-beta.3
parent
b279d733ad
commit
73a0dfb487
File diff suppressed because it is too large
Load Diff
|
@ -31,7 +31,7 @@ minikube start
|
|||
--iso-url string Location of the minikube iso (default "https://storage.googleapis.com/minikube/iso/minikube-v1.0.7.iso")
|
||||
--keep-context This will keep the existing kubectl context and will create a minikube context.
|
||||
--kubernetes-version string The kubernetes version that the minikube VM will use (ex: v1.2.3)
|
||||
OR a URI which contains a localkube binary (ex: https://storage.googleapis.com/minikube/k8sReleases/v1.3.0/localkube-linux-amd64) (default "v1.6.0-beta.2")
|
||||
OR a URI which contains a localkube binary (ex: https://storage.googleapis.com/minikube/k8sReleases/v1.3.0/localkube-linux-amd64) (default "v1.6.0-beta.3")
|
||||
--kvm-network string The KVM network name. (only supported with KVM driver) (default "default")
|
||||
--memory int Amount of RAM allocated to the minikube VM (default 2048)
|
||||
--network-plugin string The name of the network plugin
|
||||
|
|
|
@ -34,12 +34,12 @@ const (
|
|||
// fluentd in not running as a manifest pod with LabelFluentdDsReady.
|
||||
LabelFluentdDsReady = "alpha.kubernetes.io/fluentd-ds-ready"
|
||||
|
||||
// When the --use-taint-based-evictions flag is enabled,
|
||||
// When feature-gate for TaintBasedEvictions=true flag is enabled,
|
||||
// TaintNodeNotReady would be automatically added by node controller
|
||||
// when node is not ready, and removed when node becomes ready.
|
||||
TaintNodeNotReady = "node.alpha.kubernetes.io/notReady"
|
||||
|
||||
// When the --use-taint-based-evictions flag is enabled,
|
||||
// When feature-gate for TaintBasedEvictions=true flag is enabled,
|
||||
// TaintNodeUnreachable would be automatically added by node controller
|
||||
// when node becomes unreachable (corresponding to NodeReady status ConditionUnknown)
|
||||
// and removed when node becomes reachable (NodeReady status ConditionTrue).
|
||||
|
|
|
@ -190,18 +190,43 @@ func (s *GenericAPIServer) PrepareRun() preparedGenericAPIServer {
|
|||
// Run spawns the http servers (secure and insecure). It only returns if stopCh is closed
|
||||
// or one of the ports cannot be listened on initially.
|
||||
func (s preparedGenericAPIServer) Run(stopCh <-chan struct{}) error {
|
||||
err := s.NonBlockingRun(stopCh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
<-stopCh
|
||||
return nil
|
||||
}
|
||||
|
||||
// NonBlockingRun spawns the http servers (secure and insecure). An error is
|
||||
// returned if either of the ports cannot be listened on.
|
||||
func (s preparedGenericAPIServer) NonBlockingRun(stopCh <-chan struct{}) error {
|
||||
// Use an internal stop channel to allow cleanup of the listeners on error.
|
||||
internalStopCh := make(chan struct{})
|
||||
|
||||
if s.SecureServingInfo != nil && s.Handler != nil {
|
||||
if err := s.serveSecurely(stopCh); err != nil {
|
||||
if err := s.serveSecurely(internalStopCh); err != nil {
|
||||
close(internalStopCh)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if s.InsecureServingInfo != nil && s.InsecureHandler != nil {
|
||||
if err := s.serveInsecurely(stopCh); err != nil {
|
||||
if err := s.serveInsecurely(internalStopCh); err != nil {
|
||||
close(internalStopCh)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Now that both listeners have bound successfully, it is the
|
||||
// responsibility of the caller to close the provided channel to
|
||||
// ensure cleanup.
|
||||
go func() {
|
||||
<-stopCh
|
||||
close(internalStopCh)
|
||||
}()
|
||||
|
||||
s.RunPostStartHooks()
|
||||
|
||||
// err == systemd.SdNotifyNoSocket when not running on a systemd system
|
||||
|
@ -209,7 +234,6 @@ func (s preparedGenericAPIServer) Run(stopCh <-chan struct{}) error {
|
|||
glog.Errorf("Unable to send systemd daemon successful start message: %v\n", err)
|
||||
}
|
||||
|
||||
<-stopCh
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -327,7 +327,7 @@ type VolumeSource struct {
|
|||
// PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine
|
||||
PhotonPersistentDisk *PhotonPersistentDiskVolumeSource `json:"photonPersistentDisk,omitempty" protobuf:"bytes,23,opt,name=photonPersistentDisk"`
|
||||
// Items for all in one resources secrets, configmaps, and downward API
|
||||
Projected *ProjectedVolumeSource `json:"projected,omitempty"`
|
||||
Projected *ProjectedVolumeSource `json:"projected,omitempty" protobuf:"bytes,26,opt,name=projected"`
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,24,opt,name=portworxVolume"`
|
||||
|
@ -492,7 +492,7 @@ type PersistentVolumeSpec struct {
|
|||
// Name of StorageClass to which this persistent volume belongs. Empty value
|
||||
// means that this volume does not belong to any StorageClass.
|
||||
// +optional
|
||||
StorageClassName string `json:"storageClassName,omitempty"`
|
||||
StorageClassName string `json:"storageClassName,omitempty" protobuf:"bytes,6,opt,name=storageClassName"`
|
||||
}
|
||||
|
||||
// PersistentVolumeReclaimPolicy describes a policy for end-of-life maintenance of persistent volumes.
|
||||
|
@ -591,7 +591,7 @@ type PersistentVolumeClaimSpec struct {
|
|||
// Name of the StorageClass required by the claim.
|
||||
// More info: http://kubernetes.io/docs/user-guide/persistent-volumes#class-1
|
||||
// +optional
|
||||
StorageClassName *string `json:"storageClassName,omitempty"`
|
||||
StorageClassName *string `json:"storageClassName,omitempty" protobuf:"bytes,5,opt,name=storageClassName"`
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimStatus is the current status of a persistent volume claim.
|
||||
|
@ -1238,14 +1238,14 @@ type ConfigMapProjection struct {
|
|||
// Represents a projected volume source
|
||||
type ProjectedVolumeSource struct {
|
||||
// list of volume projections
|
||||
Sources []VolumeProjection `json:"sources"`
|
||||
Sources []VolumeProjection `json:"sources" protobuf:"bytes,1,rep,name=sources"`
|
||||
// Mode bits to use on created files by default. Must be a value between
|
||||
// 0 and 0777.
|
||||
// Directories within the path are not affected by this setting.
|
||||
// This might be in conflict with other options that affect the file
|
||||
// mode, like fsGroup, and the result can be other mode bits set.
|
||||
// +optional
|
||||
DefaultMode *int32 `json:"defaultMode,omitempty"`
|
||||
DefaultMode *int32 `json:"defaultMode,omitempty" protobuf:"varint,2,opt,name=defaultMode"`
|
||||
}
|
||||
|
||||
// Projection that may be projected along with other supported volume types
|
||||
|
@ -1253,11 +1253,11 @@ type VolumeProjection struct {
|
|||
// all types below are the supported types for projection into the same volume
|
||||
|
||||
// information about the secret data to project
|
||||
Secret *SecretProjection `json:"secret,omitempty"`
|
||||
Secret *SecretProjection `json:"secret,omitempty" protobuf:"bytes,1,opt,name=secret"`
|
||||
// information about the downwardAPI data to project
|
||||
DownwardAPI *DownwardAPIProjection `json:"downwardAPI,omitempty"`
|
||||
DownwardAPI *DownwardAPIProjection `json:"downwardAPI,omitempty" protobuf:"bytes,2,opt,name=downwardAPI"`
|
||||
// information about the configMap data to project
|
||||
ConfigMap *ConfigMapProjection `json:"configMap,omitempty"`
|
||||
ConfigMap *ConfigMapProjection `json:"configMap,omitempty" protobuf:"bytes,3,opt,name=configMap"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -3113,7 +3113,7 @@ type NodeSpec struct {
|
|||
Unschedulable bool `json:"unschedulable,omitempty" protobuf:"varint,4,opt,name=unschedulable"`
|
||||
// If specified, the node's taints.
|
||||
// +optional
|
||||
Taints []Taint `json:"taints,omitempty" protobuf:"bytes,5,opt,name=taints"`
|
||||
Taints []Taint `json:"taints,omitempty" protobuf:"bytes,5,opt,name=taints"`
|
||||
}
|
||||
|
||||
// DaemonEndpoint contains information about a single Daemon endpoint.
|
||||
|
@ -3533,7 +3533,7 @@ type DeleteOptions struct {
|
|||
// Defaults to Default.
|
||||
// Either this field or OrphanDependents may be set, but not both.
|
||||
// +optional
|
||||
PropagationPolicy *DeletionPropagation
|
||||
PropagationPolicy *DeletionPropagation `protobuf:"bytes,4,opt,name=propagationPolicy,casttype=DeletionPropagation"`
|
||||
}
|
||||
|
||||
// ListOptions is the query options to a standard REST list call.
|
||||
|
|
|
@ -33,15 +33,15 @@ type StorageClass struct {
|
|||
// Standard object's metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
// +optional
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// Provisioner indicates the type of the provisioner.
|
||||
Provisioner string `json:"provisioner"`
|
||||
Provisioner string `json:"provisioner" protobuf:"bytes,2,opt,name=provisioner"`
|
||||
|
||||
// Parameters holds the parameters for the provisioner that should
|
||||
// create volumes of this storage class.
|
||||
// +optional
|
||||
Parameters map[string]string `json:"parameters,omitempty"`
|
||||
Parameters map[string]string `json:"parameters,omitempty" protobuf:"bytes,3,rep,name=parameters"`
|
||||
}
|
||||
|
||||
// StorageClassList is a collection of storage classes.
|
||||
|
@ -50,8 +50,8 @@ type StorageClassList struct {
|
|||
// Standard list metadata
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
// +optional
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// Items is the list of StorageClasses
|
||||
Items []StorageClass `json:"items"`
|
||||
Items []StorageClass `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ var (
|
|||
// semantic version is a git hash, but the version itself is no
|
||||
// longer the direct output of "git describe", but a slight
|
||||
// translation to be semver compliant.
|
||||
gitVersion string = "v1.6.0-beta.1+$Format:%h$"
|
||||
gitVersion string = "v1.6.0-beta.2+$Format:%h$"
|
||||
gitCommit string = "$Format:%H$" // sha1 from git, output of $(git rev-parse HEAD)
|
||||
gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"
|
||||
|
||||
|
|
|
@ -327,7 +327,7 @@ type VolumeSource struct {
|
|||
// PhotonPersistentDisk represents a PhotonController persistent disk attached and mounted on kubelets host machine
|
||||
PhotonPersistentDisk *PhotonPersistentDiskVolumeSource `json:"photonPersistentDisk,omitempty" protobuf:"bytes,23,opt,name=photonPersistentDisk"`
|
||||
// Items for all in one resources secrets, configmaps, and downward API
|
||||
Projected *ProjectedVolumeSource `json:"projected,omitempty"`
|
||||
Projected *ProjectedVolumeSource `json:"projected,omitempty" protobuf:"bytes,26,opt,name=projected"`
|
||||
// PortworxVolume represents a portworx volume attached and mounted on kubelets host machine
|
||||
// +optional
|
||||
PortworxVolume *PortworxVolumeSource `json:"portworxVolume,omitempty" protobuf:"bytes,24,opt,name=portworxVolume"`
|
||||
|
@ -492,7 +492,7 @@ type PersistentVolumeSpec struct {
|
|||
// Name of StorageClass to which this persistent volume belongs. Empty value
|
||||
// means that this volume does not belong to any StorageClass.
|
||||
// +optional
|
||||
StorageClassName string `json:"storageClassName,omitempty"`
|
||||
StorageClassName string `json:"storageClassName,omitempty" protobuf:"bytes,6,opt,name=storageClassName"`
|
||||
}
|
||||
|
||||
// PersistentVolumeReclaimPolicy describes a policy for end-of-life maintenance of persistent volumes.
|
||||
|
@ -591,7 +591,7 @@ type PersistentVolumeClaimSpec struct {
|
|||
// Name of the StorageClass required by the claim.
|
||||
// More info: http://kubernetes.io/docs/user-guide/persistent-volumes#class-1
|
||||
// +optional
|
||||
StorageClassName *string `json:"storageClassName,omitempty"`
|
||||
StorageClassName *string `json:"storageClassName,omitempty" protobuf:"bytes,5,opt,name=storageClassName"`
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimStatus is the current status of a persistent volume claim.
|
||||
|
@ -1238,14 +1238,14 @@ type ConfigMapProjection struct {
|
|||
// Represents a projected volume source
|
||||
type ProjectedVolumeSource struct {
|
||||
// list of volume projections
|
||||
Sources []VolumeProjection `json:"sources"`
|
||||
Sources []VolumeProjection `json:"sources" protobuf:"bytes,1,rep,name=sources"`
|
||||
// Mode bits to use on created files by default. Must be a value between
|
||||
// 0 and 0777.
|
||||
// Directories within the path are not affected by this setting.
|
||||
// This might be in conflict with other options that affect the file
|
||||
// mode, like fsGroup, and the result can be other mode bits set.
|
||||
// +optional
|
||||
DefaultMode *int32 `json:"defaultMode,omitempty"`
|
||||
DefaultMode *int32 `json:"defaultMode,omitempty" protobuf:"varint,2,opt,name=defaultMode"`
|
||||
}
|
||||
|
||||
// Projection that may be projected along with other supported volume types
|
||||
|
@ -1253,11 +1253,11 @@ type VolumeProjection struct {
|
|||
// all types below are the supported types for projection into the same volume
|
||||
|
||||
// information about the secret data to project
|
||||
Secret *SecretProjection `json:"secret,omitempty"`
|
||||
Secret *SecretProjection `json:"secret,omitempty" protobuf:"bytes,1,opt,name=secret"`
|
||||
// information about the downwardAPI data to project
|
||||
DownwardAPI *DownwardAPIProjection `json:"downwardAPI,omitempty"`
|
||||
DownwardAPI *DownwardAPIProjection `json:"downwardAPI,omitempty" protobuf:"bytes,2,opt,name=downwardAPI"`
|
||||
// information about the configMap data to project
|
||||
ConfigMap *ConfigMapProjection `json:"configMap,omitempty"`
|
||||
ConfigMap *ConfigMapProjection `json:"configMap,omitempty" protobuf:"bytes,3,opt,name=configMap"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -3113,7 +3113,7 @@ type NodeSpec struct {
|
|||
Unschedulable bool `json:"unschedulable,omitempty" protobuf:"varint,4,opt,name=unschedulable"`
|
||||
// If specified, the node's taints.
|
||||
// +optional
|
||||
Taints []Taint `json:"taints,omitempty" protobuf:"bytes,5,opt,name=taints"`
|
||||
Taints []Taint `json:"taints,omitempty" protobuf:"bytes,5,opt,name=taints"`
|
||||
}
|
||||
|
||||
// DaemonEndpoint contains information about a single Daemon endpoint.
|
||||
|
@ -3533,7 +3533,7 @@ type DeleteOptions struct {
|
|||
// Defaults to Default.
|
||||
// Either this field or OrphanDependents may be set, but not both.
|
||||
// +optional
|
||||
PropagationPolicy *DeletionPropagation
|
||||
PropagationPolicy *DeletionPropagation `protobuf:"bytes,4,opt,name=propagationPolicy,casttype=DeletionPropagation"`
|
||||
}
|
||||
|
||||
// ListOptions is the query options to a standard REST list call.
|
||||
|
|
|
@ -15,7 +15,6 @@ go_library(
|
|||
"events.go",
|
||||
"schema.go",
|
||||
"validation.go",
|
||||
"volume_plugins.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
|
@ -27,30 +26,6 @@ go_library(
|
|||
"//pkg/capabilities:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/security/apparmor:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/aws_ebs:go_default_library",
|
||||
"//pkg/volume/azure_dd:go_default_library",
|
||||
"//pkg/volume/azure_file:go_default_library",
|
||||
"//pkg/volume/cephfs:go_default_library",
|
||||
"//pkg/volume/cinder:go_default_library",
|
||||
"//pkg/volume/configmap:go_default_library",
|
||||
"//pkg/volume/downwardapi:go_default_library",
|
||||
"//pkg/volume/empty_dir:go_default_library",
|
||||
"//pkg/volume/fc:go_default_library",
|
||||
"//pkg/volume/flexvolume:go_default_library",
|
||||
"//pkg/volume/flocker:go_default_library",
|
||||
"//pkg/volume/gce_pd:go_default_library",
|
||||
"//pkg/volume/git_repo:go_default_library",
|
||||
"//pkg/volume/glusterfs:go_default_library",
|
||||
"//pkg/volume/host_path:go_default_library",
|
||||
"//pkg/volume/iscsi:go_default_library",
|
||||
"//pkg/volume/nfs:go_default_library",
|
||||
"//pkg/volume/photon_pd:go_default_library",
|
||||
"//pkg/volume/projected:go_default_library",
|
||||
"//pkg/volume/quobyte:go_default_library",
|
||||
"//pkg/volume/rbd:go_default_library",
|
||||
"//pkg/volume/secret:go_default_library",
|
||||
"//pkg/volume/vsphere_volume:go_default_library",
|
||||
"//vendor:github.com/emicklei/go-restful/swagger",
|
||||
"//vendor:github.com/exponent-io/jsonpath",
|
||||
"//vendor:github.com/golang/glog",
|
||||
|
@ -100,7 +75,6 @@ go_test(
|
|||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||
"//pkg/capabilities:go_default_library",
|
||||
"//pkg/security/apparmor:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//vendor:github.com/ghodss/yaml",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/testing",
|
||||
|
|
|
@ -47,7 +47,6 @@ import (
|
|||
"k8s.io/kubernetes/pkg/capabilities"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/security/apparmor"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
)
|
||||
|
||||
// TODO: delete this global variable when we enable the validation of common
|
||||
|
@ -64,11 +63,6 @@ var volumeModeErrorMsg string = "must be a number between 0 and 0777 (octal), bo
|
|||
|
||||
// BannedOwners is a black list of object that are not allowed to be owners.
|
||||
var BannedOwners = genericvalidation.BannedOwners
|
||||
var volumePlugins []volume.VolumePlugin
|
||||
|
||||
func init() {
|
||||
volumePlugins = probeVolumePlugins()
|
||||
}
|
||||
|
||||
// ValidateHasLabel requires that metav1.ObjectMeta has a Label with key and expectedValue
|
||||
func ValidateHasLabel(meta metav1.ObjectMeta, fldPath *field.Path, key, expectedValue string) field.ErrorList {
|
||||
|
@ -1064,20 +1058,6 @@ func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
|
|||
}
|
||||
}
|
||||
|
||||
volumePlugin := findPluginBySpec(volumePlugins, pv)
|
||||
mountOptions := volume.MountOptionFromApiPV(pv)
|
||||
|
||||
metaField := field.NewPath("metadata")
|
||||
if volumePlugin == nil && len(mountOptions) > 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(metaField.Child("annotations", volume.MountOptionAnnotation), "may not specify mount options for this volume type"))
|
||||
}
|
||||
|
||||
if volumePlugin != nil {
|
||||
if !volumePlugin.SupportsMountOption() && len(mountOptions) > 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(metaField.Child("annotations", volume.MountOptionAnnotation), "may not specify mount options for this volume type"))
|
||||
}
|
||||
}
|
||||
|
||||
numVolumes := 0
|
||||
if pv.Spec.HostPath != nil {
|
||||
if numVolumes > 0 {
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/aws_ebs"
|
||||
"k8s.io/kubernetes/pkg/volume/azure_dd"
|
||||
"k8s.io/kubernetes/pkg/volume/azure_file"
|
||||
"k8s.io/kubernetes/pkg/volume/cephfs"
|
||||
"k8s.io/kubernetes/pkg/volume/cinder"
|
||||
"k8s.io/kubernetes/pkg/volume/configmap"
|
||||
"k8s.io/kubernetes/pkg/volume/downwardapi"
|
||||
"k8s.io/kubernetes/pkg/volume/empty_dir"
|
||||
"k8s.io/kubernetes/pkg/volume/fc"
|
||||
"k8s.io/kubernetes/pkg/volume/flexvolume"
|
||||
"k8s.io/kubernetes/pkg/volume/flocker"
|
||||
"k8s.io/kubernetes/pkg/volume/gce_pd"
|
||||
"k8s.io/kubernetes/pkg/volume/git_repo"
|
||||
"k8s.io/kubernetes/pkg/volume/glusterfs"
|
||||
"k8s.io/kubernetes/pkg/volume/host_path"
|
||||
"k8s.io/kubernetes/pkg/volume/iscsi"
|
||||
"k8s.io/kubernetes/pkg/volume/nfs"
|
||||
"k8s.io/kubernetes/pkg/volume/photon_pd"
|
||||
"k8s.io/kubernetes/pkg/volume/projected"
|
||||
"k8s.io/kubernetes/pkg/volume/quobyte"
|
||||
"k8s.io/kubernetes/pkg/volume/rbd"
|
||||
"k8s.io/kubernetes/pkg/volume/secret"
|
||||
"k8s.io/kubernetes/pkg/volume/vsphere_volume"
|
||||
)
|
||||
|
||||
func probeVolumePlugins() []volume.VolumePlugin {
|
||||
allPlugins := []volume.VolumePlugin{}
|
||||
|
||||
// list of volume plugins to probe for
|
||||
allPlugins = append(allPlugins, aws_ebs.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, empty_dir.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, gce_pd.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, git_repo.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, host_path.ProbeVolumePlugins(volume.VolumeConfig{})...)
|
||||
allPlugins = append(allPlugins, nfs.ProbeVolumePlugins(volume.VolumeConfig{})...)
|
||||
allPlugins = append(allPlugins, secret.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, iscsi.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, glusterfs.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, rbd.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, cinder.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, quobyte.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, cephfs.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, downwardapi.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, flocker.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, flexvolume.ProbeVolumePlugins("")...)
|
||||
allPlugins = append(allPlugins, azure_file.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, configmap.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, vsphere_volume.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, azure_dd.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, photon_pd.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, projected.ProbeVolumePlugins()...)
|
||||
return allPlugins
|
||||
}
|
||||
|
||||
func findPluginBySpec(volumePlugins []volume.VolumePlugin, pv *api.PersistentVolume) volume.VolumePlugin {
|
||||
matches := []volume.VolumePlugin{}
|
||||
v1Pv := &v1.PersistentVolume{}
|
||||
err := v1.Convert_api_PersistentVolume_To_v1_PersistentVolume(pv, v1Pv, nil)
|
||||
if err != nil {
|
||||
glog.Errorf("Error converting to v1.PersistentVolume: %v", err)
|
||||
return nil
|
||||
}
|
||||
volumeSpec := &volume.Spec{PersistentVolume: v1Pv}
|
||||
for _, plugin := range volumePlugins {
|
||||
if plugin.CanSupport(volumeSpec) {
|
||||
matches = append(matches, plugin)
|
||||
}
|
||||
}
|
||||
|
||||
if len(matches) == 0 {
|
||||
glog.V(5).Infof("No matching plugin found for : %s", pv.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(matches) > 1 {
|
||||
glog.V(3).Infof("multiple volume plugins matched for : %s ", pv.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
return matches[0]
|
||||
}
|
|
@ -33,15 +33,15 @@ type StorageClass struct {
|
|||
// Standard object's metadata.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
// +optional
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// Provisioner indicates the type of the provisioner.
|
||||
Provisioner string `json:"provisioner"`
|
||||
Provisioner string `json:"provisioner" protobuf:"bytes,2,opt,name=provisioner"`
|
||||
|
||||
// Parameters holds the parameters for the provisioner that should
|
||||
// create volumes of this storage class.
|
||||
// +optional
|
||||
Parameters map[string]string `json:"parameters,omitempty"`
|
||||
Parameters map[string]string `json:"parameters,omitempty" protobuf:"bytes,3,rep,name=parameters"`
|
||||
}
|
||||
|
||||
// StorageClassList is a collection of storage classes.
|
||||
|
@ -50,8 +50,8 @@ type StorageClassList struct {
|
|||
// Standard list metadata
|
||||
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
|
||||
// +optional
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// Items is the list of StorageClasses
|
||||
Items []StorageClass `json:"items"`
|
||||
Items []StorageClass `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
|
|
@ -152,7 +152,10 @@ type Routes interface {
|
|||
DeleteRoute(clusterName string, route *Route) error
|
||||
}
|
||||
|
||||
var InstanceNotFound = errors.New("instance not found")
|
||||
var (
|
||||
InstanceNotFound = errors.New("instance not found")
|
||||
DiskNotFound = errors.New("disk is not found")
|
||||
)
|
||||
|
||||
// Zone represents the location of a particular machine.
|
||||
type Zone struct {
|
||||
|
|
|
@ -2511,6 +2511,10 @@ func (gce *GCECloud) DeleteDisk(diskToDelete string) error {
|
|||
if isGCEError(err, "resourceInUseByAnotherResource") {
|
||||
return volume.NewDeletedVolumeInUseError(err.Error())
|
||||
}
|
||||
|
||||
if err == cloudprovider.DiskNotFound {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -2712,6 +2716,7 @@ func (gce *GCECloud) getDiskByName(diskName string, zone string) (*gceDisk, erro
|
|||
|
||||
// Scans all managed zones to return the GCE PD
|
||||
// Prefer getDiskByName, if the zone can be established
|
||||
// Return cloudprovider.DiskNotFound if the given disk cannot be found in any zone
|
||||
func (gce *GCECloud) getDiskByNameUnknownZone(diskName string) (*gceDisk, error) {
|
||||
// Note: this is the gotcha right now with GCE PD support:
|
||||
// disk names are not unique per-region.
|
||||
|
@ -2742,7 +2747,8 @@ func (gce *GCECloud) getDiskByNameUnknownZone(diskName string) (*gceDisk, error)
|
|||
if found != nil {
|
||||
return found, nil
|
||||
}
|
||||
return nil, fmt.Errorf("GCE persistent disk %q not found in managed zones (%s)", diskName, strings.Join(gce.managedZones, ","))
|
||||
glog.Warningf("GCE persistent disk %q not found in managed zones (%s)", diskName, strings.Join(gce.managedZones, ","))
|
||||
return nil, cloudprovider.DiskNotFound
|
||||
}
|
||||
|
||||
// GetGCERegion returns region of the gce zone. Zone names
|
||||
|
|
|
@ -273,6 +273,9 @@ func newVSphere(cfg VSphereConfig) (*VSphere, error) {
|
|||
if cfg.Global.RoundTripperCount == 0 {
|
||||
cfg.Global.RoundTripperCount = RoundTripperDefaultCount
|
||||
}
|
||||
if cfg.Global.VCenterPort != "" {
|
||||
glog.Warningf("port is a deprecated field in vsphere.conf and will be removed in future release.")
|
||||
}
|
||||
|
||||
c, err := newClient(context.TODO(), &cfg)
|
||||
if err != nil {
|
||||
|
@ -310,7 +313,7 @@ func logout(vs *VSphere) {
|
|||
|
||||
func newClient(ctx context.Context, cfg *VSphereConfig) (*govmomi.Client, error) {
|
||||
// Parse URL from string
|
||||
u, err := url.Parse(fmt.Sprintf("https://%s:%s/sdk", cfg.Global.VCenterIP, cfg.Global.VCenterPort))
|
||||
u, err := url.Parse(fmt.Sprintf("https://%s/sdk", cfg.Global.VCenterIP))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ func GetVSphere() (*VSphere, error) {
|
|||
func getVSphereConfig() *VSphereConfig {
|
||||
var cfg VSphereConfig
|
||||
cfg.Global.VCenterIP = os.Getenv("VSPHERE_VCENTER")
|
||||
cfg.Global.VCenterPort = os.Getenv("VSPHERE_VCENTER_PORT")
|
||||
cfg.Global.User = os.Getenv("VSPHERE_USER")
|
||||
cfg.Global.Password = os.Getenv("VSPHERE_PASSWORD")
|
||||
cfg.Global.Datacenter = os.Getenv("VSPHERE_DATACENTER")
|
||||
|
|
|
@ -578,7 +578,7 @@ func (dsc *DaemonSetsController) manage(ds *extensions.DaemonSet) error {
|
|||
return utilerrors.NewAggregate(errors)
|
||||
}
|
||||
|
||||
// syncNodes deletes given pods and creates new daemon set pods on the given node
|
||||
// syncNodes deletes given pods and creates new daemon set pods on the given nodes
|
||||
// returns slice with erros if any
|
||||
func (dsc *DaemonSetsController) syncNodes(ds *extensions.DaemonSet, podsToDelete, nodesNeedingDaemonPods []string) []error {
|
||||
// We need to set expectations before creating/deleting pods to avoid race conditions.
|
||||
|
|
|
@ -44,8 +44,6 @@ func GetInternalPodTemplateSpecHash(template api.PodTemplateSpec) uint32 {
|
|||
return podTemplateSpecHasher.Sum32()
|
||||
}
|
||||
|
||||
// TODO: move it to a better place. It's also used by DaemonSets
|
||||
// Maybe to pkg/api/v1/resource_helpers.go
|
||||
func GetPodTemplateSpecHashFnv(template v1.PodTemplateSpec) uint32 {
|
||||
podTemplateSpecHasher := fnv.New32a()
|
||||
hashutil.DeepHashObject(podTemplateSpecHasher, template)
|
||||
|
|
|
@ -143,6 +143,12 @@ func (gc *GarbageCollector) attemptToDeleteWorker() bool {
|
|||
}
|
||||
err := gc.attemptToDeleteItem(n)
|
||||
if err != nil {
|
||||
// TODO: remove this block when gc starts using dynamic RESTMapper.
|
||||
if restMappingError, ok := err.(*restMappingError); ok {
|
||||
utilruntime.HandleError(fmt.Errorf("Ignore syncing item %#v: %s", n, restMappingError.Message()))
|
||||
// The RESTMapper is static, so no need to retry, otherwise we'll get the same error.
|
||||
return true
|
||||
}
|
||||
utilruntime.HandleError(fmt.Errorf("Error syncing item %#v: %v", n, err))
|
||||
// retry if garbage collection of an object failed.
|
||||
gc.attemptToDelete.AddRateLimited(item)
|
||||
|
|
|
@ -30,13 +30,36 @@ import (
|
|||
"k8s.io/kubernetes/pkg/client/retry"
|
||||
)
|
||||
|
||||
type restMappingError struct {
|
||||
kind string
|
||||
version string
|
||||
}
|
||||
|
||||
func (r *restMappingError) Error() string {
|
||||
versionKind := fmt.Sprintf("%s/%s", r.version, r.kind)
|
||||
return fmt.Sprintf("unable to get REST mapping for %s.", versionKind)
|
||||
}
|
||||
|
||||
// Message prints more details
|
||||
func (r *restMappingError) Message() string {
|
||||
versionKind := fmt.Sprintf("%s/%s", r.version, r.kind)
|
||||
errMsg := fmt.Sprintf("unable to get REST mapping for %s.", versionKind)
|
||||
errMsg += fmt.Sprintf(" If %s is a thirdparty resource (tpr), please note that the garbage collector doesn't support tpr yet. Once tpr is supported, object with ownerReferences referring non-existing tpr objects will be deleted by the garbage collector.", versionKind)
|
||||
errMsg += fmt.Sprintf(" If %s is not a tpr, then you should remove ownerReferences that refer %s objects manually.", versionKind, versionKind)
|
||||
return errMsg
|
||||
}
|
||||
|
||||
func newRESTMappingError(kind, version string) *restMappingError {
|
||||
return &restMappingError{kind: kind, version: version}
|
||||
}
|
||||
|
||||
// apiResource consults the REST mapper to translate an <apiVersion, kind,
|
||||
// namespace> tuple to a unversioned.APIResource struct.
|
||||
func (gc *GarbageCollector) apiResource(apiVersion, kind string, namespaced bool) (*metav1.APIResource, error) {
|
||||
fqKind := schema.FromAPIVersionAndKind(apiVersion, kind)
|
||||
mapping, err := gc.restMapper.RESTMapping(fqKind.GroupKind(), apiVersion)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get REST mapping for kind: %s, version: %s", kind, apiVersion)
|
||||
return nil, newRESTMappingError(kind, apiVersion)
|
||||
}
|
||||
glog.V(5).Infof("map kind %s, version %s to resource %s", kind, apiVersion, mapping.Resource)
|
||||
resource := metav1.APIResource{
|
||||
|
|
|
@ -71,7 +71,6 @@ go_test(
|
|||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/extensions/v1beta1:go_default_library",
|
||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||
|
|
|
@ -485,6 +485,7 @@ func (nc *NodeController) Run() {
|
|||
oppositeTaint = *NotReadyTaintTemplate
|
||||
} else {
|
||||
// It seems that the Node is ready again, so there's no need to taint it.
|
||||
glog.V(4).Infof("Node %v was in a taint queue, but it's ready now. Ignoring taint request.", value.Value)
|
||||
return true, 0
|
||||
}
|
||||
|
||||
|
@ -498,6 +499,8 @@ func (nc *NodeController) Run() {
|
|||
value.Value,
|
||||
err))
|
||||
return false, 0
|
||||
} else {
|
||||
glog.V(4).Info("Added %v Taint to Node %v", taintToAdd, value.Value)
|
||||
}
|
||||
err = controller.RemoveTaintOffNode(nc.kubeClient, value.Value, &oppositeTaint, node)
|
||||
if err != nil {
|
||||
|
@ -508,6 +511,8 @@ func (nc *NodeController) Run() {
|
|||
value.Value,
|
||||
err))
|
||||
return false, 0
|
||||
} else {
|
||||
glog.V(4).Info("Made sure that Node %v has no %v Taint", value.Value, oppositeTaint)
|
||||
}
|
||||
return true, 0
|
||||
})
|
||||
|
|
|
@ -44,41 +44,6 @@ const (
|
|||
retries = 5
|
||||
)
|
||||
|
||||
func computeTaintDifference(left []v1.Taint, right []v1.Taint) []v1.Taint {
|
||||
result := []v1.Taint{}
|
||||
for i := range left {
|
||||
found := false
|
||||
for j := range right {
|
||||
if left[i] == right[j] {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
result = append(result, left[i])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// copy of 'computeTaintDifference' - long live lack of generics...
|
||||
func computeTolerationDifference(left []v1.Toleration, right []v1.Toleration) []v1.Toleration {
|
||||
result := []v1.Toleration{}
|
||||
for i := range left {
|
||||
found := false
|
||||
for j := range right {
|
||||
if left[i] == right[j] {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
result = append(result, left[i])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Needed to make workqueue work
|
||||
type updateItemInterface interface{}
|
||||
|
||||
|
|
|
@ -121,12 +121,12 @@ func (q *TimedWorkerQueue) AddWork(args *WorkArgs, createdAt time.Time, fireAt t
|
|||
|
||||
// CancelWork removes scheduled function execution from the queue. Returns true if work was cancelled.
|
||||
func (q *TimedWorkerQueue) CancelWork(key string) bool {
|
||||
glog.V(4).Infof("Cancelling TimedWorkerQueue item %v at %v", key, time.Now())
|
||||
q.Lock()
|
||||
defer q.Unlock()
|
||||
worker, found := q.workers[key]
|
||||
result := false
|
||||
if found {
|
||||
glog.V(4).Infof("Cancelling TimedWorkerQueue item %v at %v", key, time.Now())
|
||||
if worker != nil {
|
||||
result = true
|
||||
worker.Cancel()
|
||||
|
|
|
@ -32,6 +32,10 @@ import (
|
|||
"k8s.io/kubernetes/pkg/kubelet/dockertools"
|
||||
)
|
||||
|
||||
const (
|
||||
dockerDefaultLoggingDriver = "json-file"
|
||||
)
|
||||
|
||||
// ListContainers lists all containers matching the filter.
|
||||
func (ds *dockerService) ListContainers(filter *runtimeapi.ContainerFilter) ([]*runtimeapi.Container, error) {
|
||||
opts := dockertypes.ContainerListOptions{All: true}
|
||||
|
@ -217,13 +221,35 @@ func (ds *dockerService) createContainerLogSymlink(containerID string) error {
|
|||
if err != nil {
|
||||
return fmt.Errorf("failed to get container %q log path: %v", containerID, err)
|
||||
}
|
||||
if path != "" && realPath != "" {
|
||||
// Only create the symlink when container log path is specified.
|
||||
|
||||
if path == "" {
|
||||
glog.V(5).Infof("Container %s log path isn't specified, will not create the symlink", containerID)
|
||||
return nil
|
||||
}
|
||||
|
||||
if realPath != "" {
|
||||
// Only create the symlink when container log path is specified and log file exists.
|
||||
if err = ds.os.Symlink(realPath, path); err != nil {
|
||||
return fmt.Errorf("failed to create symbolic link %q to the container log file %q for container %q: %v",
|
||||
path, realPath, containerID, err)
|
||||
}
|
||||
} else {
|
||||
dockerLoggingDriver := ""
|
||||
dockerInfo, err := ds.client.Info()
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to execute Info() call to the Docker client: %v", err)
|
||||
} else {
|
||||
dockerLoggingDriver = dockerInfo.LoggingDriver
|
||||
glog.V(10).Infof("Docker logging driver is %s", dockerLoggingDriver)
|
||||
}
|
||||
|
||||
if dockerLoggingDriver == dockerDefaultLoggingDriver {
|
||||
glog.Errorf("Cannot create symbolic link because container log file doesn't exist!")
|
||||
} else {
|
||||
glog.V(5).Infof("Unsupported logging driver: %s", dockerLoggingDriver)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,12 @@ func (ds *dockerService) RunPodSandbox(config *runtimeapi.PodSandboxConfig) (str
|
|||
// recognized by the CNI standard yet.
|
||||
cID := kubecontainer.BuildContainerID(runtimeName, createResp.ID)
|
||||
err = ds.network.SetUpPod(config.GetMetadata().Namespace, config.GetMetadata().Name, cID, config.Annotations)
|
||||
// TODO: Do we need to teardown on failure or can we rely on a StopPodSandbox call with the given ID?
|
||||
if err != nil {
|
||||
// TODO(random-liu): Do we need to teardown network here?
|
||||
if err := ds.client.StopContainer(createResp.ID, defaultSandboxGracePeriod); err != nil {
|
||||
glog.Warningf("Failed to stop sandbox container %q for pod %q: %v", createResp.ID, config.Metadata.Name, err)
|
||||
}
|
||||
}
|
||||
return createResp.ID, err
|
||||
}
|
||||
|
||||
|
@ -341,6 +346,18 @@ func (ds *dockerService) ListPodSandbox(filter *runtimeapi.PodSandboxFilter) ([]
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we get the list of checkpoints first so that we don't include
|
||||
// new PodSandboxes that are being created right now.
|
||||
var err error
|
||||
checkpoints := []string{}
|
||||
if filter == nil {
|
||||
checkpoints, err = ds.checkpointHandler.ListCheckpoints()
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to list checkpoints: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
containers, err := ds.client.ListContainers(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -367,27 +384,21 @@ func (ds *dockerService) ListPodSandbox(filter *runtimeapi.PodSandboxFilter) ([]
|
|||
// Include sandbox that could only be found with its checkpoint if no filter is applied
|
||||
// These PodSandbox will only include PodSandboxID, Name, Namespace.
|
||||
// These PodSandbox will be in PodSandboxState_SANDBOX_NOTREADY state.
|
||||
if filter == nil {
|
||||
checkpoints, err := ds.checkpointHandler.ListCheckpoints()
|
||||
for _, id := range checkpoints {
|
||||
if _, ok := sandboxIDs[id]; ok {
|
||||
continue
|
||||
}
|
||||
checkpoint, err := ds.checkpointHandler.GetCheckpoint(id)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to list checkpoints: %v", err)
|
||||
}
|
||||
for _, id := range checkpoints {
|
||||
if _, ok := sandboxIDs[id]; ok {
|
||||
continue
|
||||
}
|
||||
checkpoint, err := ds.checkpointHandler.GetCheckpoint(id)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to retrieve checkpoint for sandbox %q: %v", id, err)
|
||||
glog.Errorf("Failed to retrieve checkpoint for sandbox %q: %v", id, err)
|
||||
|
||||
if err == errors.CorruptCheckpointError {
|
||||
glog.V(2).Info("Removing corrupted checkpoint %q: %+v", id, *checkpoint)
|
||||
ds.checkpointHandler.RemoveCheckpoint(id)
|
||||
}
|
||||
continue
|
||||
if err == errors.CorruptCheckpointError {
|
||||
glog.V(2).Info("Removing corrupted checkpoint %q: %+v", id, *checkpoint)
|
||||
ds.checkpointHandler.RemoveCheckpoint(id)
|
||||
}
|
||||
result = append(result, checkpointToRuntimeAPISandbox(id, checkpoint))
|
||||
continue
|
||||
}
|
||||
result = append(result, checkpointToRuntimeAPISandbox(id, checkpoint))
|
||||
}
|
||||
|
||||
// Include legacy sandboxes if there are still legacy sandboxes not cleaned up yet.
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
// (kubecontainer) types.
|
||||
const (
|
||||
statusRunningPrefix = "Up"
|
||||
statusCreatedPrefix = "Created"
|
||||
statusExitedPrefix = "Exited"
|
||||
)
|
||||
|
||||
|
|
|
@ -78,11 +78,12 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
DockerType = "docker"
|
||||
DockerType = "docker"
|
||||
dockerDefaultLoggingDriver = "json-file"
|
||||
|
||||
// https://docs.docker.com/engine/reference/api/docker_remote_api/
|
||||
// docker version should be at least 1.9.x
|
||||
minimumDockerAPIVersion = "1.21"
|
||||
// docker version should be at least 1.10.x
|
||||
minimumDockerAPIVersion = "1.22"
|
||||
|
||||
// Remote API version for docker daemon versions
|
||||
// https://docs.docker.com/engine/reference/api/docker_remote_api/
|
||||
|
@ -1793,14 +1794,31 @@ func (dm *DockerManager) runContainerInPod(pod *v1.Pod, container *v1.Container,
|
|||
return kubecontainer.ContainerID{}, fmt.Errorf("InspectContainer: %v", err)
|
||||
}
|
||||
|
||||
// Create a symbolic link to the Docker container log file using a name which captures the
|
||||
// full pod name, the container name and the Docker container ID. Cluster level logging will
|
||||
// capture these symbolic filenames which can be used for search terms in Elasticsearch or for
|
||||
// labels for Cloud Logging.
|
||||
containerLogFile := containerInfo.LogPath
|
||||
symlinkFile := LogSymlink(dm.containerLogsDir, kubecontainer.GetPodFullName(pod), container.Name, id.ID)
|
||||
if err = dm.os.Symlink(containerLogFile, symlinkFile); err != nil {
|
||||
glog.Errorf("Failed to create symbolic link to the log file of pod %q container %q: %v", format.Pod(pod), container.Name, err)
|
||||
if containerLogFile != "" {
|
||||
// Create a symbolic link to the Docker container log file using a name which captures the
|
||||
// full pod name, the container name and the Docker container ID. Cluster level logging will
|
||||
// capture these symbolic filenames which can be used for search terms in Elasticsearch or for
|
||||
// labels for Cloud Logging.
|
||||
symlinkFile := LogSymlink(dm.containerLogsDir, kubecontainer.GetPodFullName(pod), container.Name, id.ID)
|
||||
if err = dm.os.Symlink(containerLogFile, symlinkFile); err != nil {
|
||||
glog.Errorf("Failed to create symbolic link to the log file of pod %q container %q: %v", format.Pod(pod), container.Name, err)
|
||||
}
|
||||
} else {
|
||||
dockerLoggingDriver := ""
|
||||
dockerInfo, err := dm.client.Info()
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to execute Info() call to the Docker client: %v", err)
|
||||
} else {
|
||||
dockerLoggingDriver = dockerInfo.LoggingDriver
|
||||
glog.V(10).Infof("Docker logging driver is %s", dockerLoggingDriver)
|
||||
}
|
||||
|
||||
if dockerLoggingDriver == dockerDefaultLoggingDriver {
|
||||
glog.Errorf("Cannot create symbolic link because container log file doesn't exist!")
|
||||
} else {
|
||||
glog.V(5).Infof("Unsupported logging driver: %s", dockerLoggingDriver)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if current docker version is higher than 1.10. Otherwise, we have to apply OOMScoreAdj instead of using docker API.
|
||||
|
|
|
@ -516,12 +516,13 @@ func (f *FakeDockerClient) CreateContainer(c dockertypes.ContainerCreateConfig)
|
|||
name := "/" + c.Name
|
||||
id := GetFakeContainerID(name)
|
||||
f.appendContainerTrace("Created", id)
|
||||
timestamp := f.Clock.Now()
|
||||
// The newest container should be in front, because we assume so in GetPodStatus()
|
||||
f.RunningContainerList = append([]dockertypes.Container{
|
||||
{ID: id, Names: []string{name}, Image: c.Config.Image, Labels: c.Config.Labels},
|
||||
{ID: id, Names: []string{name}, Image: c.Config.Image, Created: timestamp.Unix(), State: statusCreatedPrefix, Labels: c.Config.Labels},
|
||||
}, f.RunningContainerList...)
|
||||
f.ContainerMap[id] = convertFakeContainer(&FakeContainer{
|
||||
ID: id, Name: name, Config: c.Config, HostConfig: c.HostConfig, CreatedAt: f.Clock.Now()})
|
||||
ID: id, Name: name, Config: c.Config, HostConfig: c.HostConfig, CreatedAt: timestamp})
|
||||
|
||||
f.normalSleep(100, 25, 25)
|
||||
|
||||
|
@ -539,12 +540,13 @@ func (f *FakeDockerClient) StartContainer(id string) error {
|
|||
}
|
||||
f.appendContainerTrace("Started", id)
|
||||
container, ok := f.ContainerMap[id]
|
||||
timestamp := f.Clock.Now()
|
||||
if !ok {
|
||||
container = convertFakeContainer(&FakeContainer{ID: id, Name: id})
|
||||
container = convertFakeContainer(&FakeContainer{ID: id, Name: id, CreatedAt: timestamp})
|
||||
}
|
||||
container.State.Running = true
|
||||
container.State.Pid = os.Getpid()
|
||||
container.State.StartedAt = dockerTimestampToString(f.Clock.Now())
|
||||
container.State.StartedAt = dockerTimestampToString(timestamp)
|
||||
container.NetworkSettings.IPAddress = "2.3.4.5"
|
||||
f.ContainerMap[id] = container
|
||||
f.updateContainerStatus(id, statusRunningPrefix)
|
||||
|
|
|
@ -278,7 +278,7 @@ func (cgc *containerGC) evictSandboxes(minAge time.Duration) error {
|
|||
if createdAt.After(newestGCTime) {
|
||||
continue
|
||||
}
|
||||
|
||||
glog.V(4).Infof("PodSandbox %q is eligible for garbage collection since it was created before %v: %+v", sandboxID, newestGCTime, sandbox)
|
||||
evictSandboxes = append(evictSandboxes, sandboxID)
|
||||
}
|
||||
|
||||
|
|
|
@ -619,6 +619,7 @@ func (m *kubeGenericRuntimeManager) SyncPod(pod *v1.Pod, _ v1.PodStatus, podStat
|
|||
glog.Errorf("createPodSandbox for pod %q failed: %v", format.Pod(pod), err)
|
||||
return
|
||||
}
|
||||
glog.V(4).Infof("Created PodSandbox %q for pod %q", podSandboxID, format.Pod(pod))
|
||||
|
||||
podSandboxStatus, err := m.runtimeService.PodSandboxStatus(podSandboxID)
|
||||
if err != nil {
|
||||
|
|
|
@ -393,7 +393,7 @@ func (m *manager) syncBatch() {
|
|||
}
|
||||
syncedUID = mirrorUID
|
||||
}
|
||||
if m.needsUpdate(syncedUID, status) || m.couldBeDeleted(uid, status.status) {
|
||||
if m.needsUpdate(syncedUID, status) {
|
||||
updatedStatuses = append(updatedStatuses, podStatusSyncRequest{uid, status})
|
||||
} else if m.needsReconcile(uid, status.status) {
|
||||
// Delete the apiStatusVersions here to force an update on the pod status
|
||||
|
@ -469,7 +469,7 @@ func (m *manager) syncPod(uid types.UID, status versionedPodStatus) {
|
|||
// This method is not thread safe, and most only be accessed by the sync thread.
|
||||
func (m *manager) needsUpdate(uid types.UID, status versionedPodStatus) bool {
|
||||
latest, ok := m.apiStatusVersions[uid]
|
||||
return !ok || latest < status.version
|
||||
return !ok || latest < status.version || m.couldBeDeleted(uid, status.status)
|
||||
}
|
||||
|
||||
func (m *manager) couldBeDeleted(uid types.UID, status v1.PodStatus) bool {
|
||||
|
|
|
@ -18,6 +18,7 @@ go_library(
|
|||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/validation:go_default_library",
|
||||
"//pkg/volume/validation:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/fields",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
"k8s.io/apiserver/pkg/storage/names"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/validation"
|
||||
volumevalidation "k8s.io/kubernetes/pkg/volume/validation"
|
||||
)
|
||||
|
||||
// persistentvolumeStrategy implements behavior for PersistentVolume objects
|
||||
|
@ -53,7 +54,8 @@ func (persistentvolumeStrategy) PrepareForCreate(ctx genericapirequest.Context,
|
|||
|
||||
func (persistentvolumeStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
|
||||
persistentvolume := obj.(*api.PersistentVolume)
|
||||
return validation.ValidatePersistentVolume(persistentvolume)
|
||||
errorList := validation.ValidatePersistentVolume(persistentvolume)
|
||||
return append(errorList, volumevalidation.ValidatePersistentVolume(persistentvolume)...)
|
||||
}
|
||||
|
||||
// Canonicalize normalizes the object after validation.
|
||||
|
@ -72,8 +74,10 @@ func (persistentvolumeStrategy) PrepareForUpdate(ctx genericapirequest.Context,
|
|||
}
|
||||
|
||||
func (persistentvolumeStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
|
||||
errorList := validation.ValidatePersistentVolume(obj.(*api.PersistentVolume))
|
||||
return append(errorList, validation.ValidatePersistentVolumeUpdate(obj.(*api.PersistentVolume), old.(*api.PersistentVolume))...)
|
||||
newPv := obj.(*api.PersistentVolume)
|
||||
errorList := validation.ValidatePersistentVolume(newPv)
|
||||
errorList = append(errorList, volumevalidation.ValidatePersistentVolume(newPv)...)
|
||||
return append(errorList, validation.ValidatePersistentVolumeUpdate(newPv, old.(*api.PersistentVolume))...)
|
||||
}
|
||||
|
||||
func (persistentvolumeStrategy) AllowUnconditionalUpdate() bool {
|
||||
|
|
1
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/BUILD
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/BUILD
generated
vendored
|
@ -16,6 +16,7 @@ go_library(
|
|||
"//pkg/registry/rbac:go_default_library",
|
||||
"//pkg/registry/rbac/validation:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/endpoints/request",
|
||||
|
|
9
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/storage.go
generated
vendored
9
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/storage.go
generated
vendored
|
@ -19,6 +19,7 @@ package policybased
|
|||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
|
@ -48,11 +49,11 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run
|
|||
}
|
||||
|
||||
clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
|
||||
if rbacregistry.BindingAuthorized(ctx, clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace, s.authorizer) {
|
||||
if rbacregistry.BindingAuthorized(ctx, clusterRoleBinding.RoleRef, metav1.NamespaceNone, s.authorizer) {
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace)
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, metav1.NamespaceNone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -71,12 +72,12 @@ func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.Up
|
|||
clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
|
||||
|
||||
// if we're explicitly authorized to bind this clusterrole, return
|
||||
if rbacregistry.BindingAuthorized(ctx, clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace, s.authorizer) {
|
||||
if rbacregistry.BindingAuthorized(ctx, clusterRoleBinding.RoleRef, metav1.NamespaceNone, s.authorizer) {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
// Otherwise, see if we already have all the permissions contained in the referenced clusterrole
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace)
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, metav1.NamespaceNone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ func BindingAuthorized(ctx genericapirequest.Context, roleRef rbac.RoleRef, bind
|
|||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf(
|
||||
"error authorizing user %#v to bind %#v in namespace %s: %v",
|
||||
roleRef, bindingNamespace, user, err,
|
||||
user, roleRef, bindingNamespace, err,
|
||||
))
|
||||
}
|
||||
return ok
|
||||
|
|
|
@ -47,12 +47,19 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run
|
|||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
// Get the namespace from the context (populated from the URL).
|
||||
// The namespace in the object can be empty until StandardStorage.Create()->BeforeCreate() populates it from the context.
|
||||
namespace, ok := genericapirequest.NamespaceFrom(ctx)
|
||||
if !ok {
|
||||
return nil, errors.NewBadRequest("namespace is required")
|
||||
}
|
||||
|
||||
roleBinding := obj.(*rbac.RoleBinding)
|
||||
if rbacregistry.BindingAuthorized(ctx, roleBinding.RoleRef, roleBinding.Namespace, s.authorizer) {
|
||||
if rbacregistry.BindingAuthorized(ctx, roleBinding.RoleRef, namespace, s.authorizer) {
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, roleBinding.Namespace)
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -68,15 +75,22 @@ func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.Up
|
|||
}
|
||||
|
||||
nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx genericapirequest.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
|
||||
// Get the namespace from the context (populated from the URL).
|
||||
// The namespace in the object can be empty until StandardStorage.Update()->BeforeUpdate() populates it from the context.
|
||||
namespace, ok := genericapirequest.NamespaceFrom(ctx)
|
||||
if !ok {
|
||||
return nil, errors.NewBadRequest("namespace is required")
|
||||
}
|
||||
|
||||
roleBinding := obj.(*rbac.RoleBinding)
|
||||
|
||||
// if we're explicitly authorized to bind this role, return
|
||||
if rbacregistry.BindingAuthorized(ctx, roleBinding.RoleRef, roleBinding.Namespace, s.authorizer) {
|
||||
if rbacregistry.BindingAuthorized(ctx, roleBinding.RoleRef, namespace, s.authorizer) {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
// Otherwise, see if we already have all the permissions contained in the referenced role
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, roleBinding.Namespace)
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ var (
|
|||
// semantic version is a git hash, but the version itself is no
|
||||
// longer the direct output of "git describe", but a slight
|
||||
// translation to be semver compliant.
|
||||
gitVersion string = "v1.6.0-beta.2+$Format:%h$"
|
||||
gitVersion string = "v1.6.0-beta.3+$Format:%h$"
|
||||
gitCommit string = "$Format:%H$" // sha1 from git, output of $(git rev-parse HEAD)
|
||||
gitTreeState string = "not a git tree" // state of git tree, either "clean" or "dirty"
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ go_library(
|
|||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/client/clientset_generated/clientset:go_default_library",
|
||||
"//pkg/cloudprovider:go_default_library",
|
||||
|
@ -119,6 +118,7 @@ filegroup(
|
|||
"//pkg/volume/secret:all-srcs",
|
||||
"//pkg/volume/testing:all-srcs",
|
||||
"//pkg/volume/util:all-srcs",
|
||||
"//pkg/volume/validation:all-srcs",
|
||||
"//pkg/volume/vsphere_volume:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
|
|
|
@ -23,7 +23,6 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
|
||||
|
||||
|
@ -388,16 +387,6 @@ func MountOptionFromSpec(spec *Spec, options ...string) []string {
|
|||
return options
|
||||
}
|
||||
|
||||
// MountOptionFromApiPV extracts mount options from api.PersistentVolume
|
||||
func MountOptionFromApiPV(pv *api.PersistentVolume) []string {
|
||||
mountOptions := []string{}
|
||||
if mo, ok := pv.Annotations[MountOptionAnnotation]; ok {
|
||||
moList := strings.Split(mo, ",")
|
||||
return JoinMountOptions(moList, mountOptions)
|
||||
}
|
||||
return mountOptions
|
||||
}
|
||||
|
||||
// JoinMountOptions joins mount options eliminating duplicates
|
||||
func JoinMountOptions(userOptions []string, systemOptions []string) []string {
|
||||
allMountOptions := sets.NewString()
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["pv_validation_test.go"],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["pv_validation.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
// MountOptionAnnotation defines mount option annotation used in PVs
|
||||
const MountOptionAnnotation = "volume.beta.kubernetes.io/mount-options"
|
||||
|
||||
// ValidatePersistentVolume validates PV object for plugin specific validation
|
||||
// We can put here validations which are specific to volume types.
|
||||
func ValidatePersistentVolume(pv *api.PersistentVolume) field.ErrorList {
|
||||
return checkMountOption(pv)
|
||||
}
|
||||
|
||||
func checkMountOption(pv *api.PersistentVolume) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
// if PV is of these types we don't return errors
|
||||
// since mount options is supported
|
||||
if pv.Spec.GCEPersistentDisk != nil ||
|
||||
pv.Spec.AWSElasticBlockStore != nil ||
|
||||
pv.Spec.Glusterfs != nil ||
|
||||
pv.Spec.NFS != nil ||
|
||||
pv.Spec.RBD != nil ||
|
||||
pv.Spec.Quobyte != nil ||
|
||||
pv.Spec.ISCSI != nil ||
|
||||
pv.Spec.Cinder != nil ||
|
||||
pv.Spec.CephFS != nil ||
|
||||
pv.Spec.AzureFile != nil ||
|
||||
pv.Spec.VsphereVolume != nil ||
|
||||
pv.Spec.AzureDisk != nil ||
|
||||
pv.Spec.PhotonPersistentDisk != nil {
|
||||
return allErrs
|
||||
}
|
||||
// any other type if mount option is present lets return error
|
||||
if _, ok := pv.Annotations[MountOptionAnnotation]; ok {
|
||||
metaField := field.NewPath("metadata")
|
||||
allErrs = append(allErrs, field.Forbidden(metaField.Child("annotations", MountOptionAnnotation), "may not specify mount options for this volume type"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
|
@ -304,7 +304,10 @@ func authorizedForPolicy(info user.Info, policy *extensions.PodSecurityPolicy, a
|
|||
return true
|
||||
}
|
||||
attr := buildAttributes(info, policy)
|
||||
allowed, _, _ := authz.Authorize(attr)
|
||||
allowed, reason, err := authz.Authorize(attr)
|
||||
if err != nil {
|
||||
glog.V(5).Infof("cannot authorized for policy: %v,%v", reason, err)
|
||||
}
|
||||
return allowed
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import (
|
|||
)
|
||||
|
||||
// The maximum priority value to give to a node
|
||||
// Prioritiy values range from 0-maxPriority
|
||||
// Priority values range from 0-maxPriority
|
||||
const maxPriority float32 = 10
|
||||
|
||||
// When zone information is present, give 2/3 of the weighting to zone spreading, 1/3 to node spreading
|
||||
|
|
|
@ -82,6 +82,19 @@ func (r *Resource) ResourceList() v1.ResourceList {
|
|||
return result
|
||||
}
|
||||
|
||||
func (r *Resource) Clone() *Resource {
|
||||
res := &Resource{
|
||||
MilliCPU: r.MilliCPU,
|
||||
Memory: r.Memory,
|
||||
NvidiaGPU: r.NvidiaGPU,
|
||||
}
|
||||
res.OpaqueIntResources = make(map[v1.ResourceName]int64)
|
||||
for k, v := range r.OpaqueIntResources {
|
||||
res.OpaqueIntResources[k] = v
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (r *Resource) AddOpaque(name v1.ResourceName, quantity int64) {
|
||||
r.SetOpaque(name, r.OpaqueIntResources[name]+quantity)
|
||||
}
|
||||
|
@ -190,9 +203,9 @@ func (n *NodeInfo) AllocatableResource() Resource {
|
|||
func (n *NodeInfo) Clone() *NodeInfo {
|
||||
clone := &NodeInfo{
|
||||
node: n.node,
|
||||
requestedResource: &(*n.requestedResource),
|
||||
nonzeroRequest: &(*n.nonzeroRequest),
|
||||
allocatableResource: &(*n.allocatableResource),
|
||||
requestedResource: n.requestedResource.Clone(),
|
||||
nonzeroRequest: n.nonzeroRequest.Clone(),
|
||||
allocatableResource: n.allocatableResource.Clone(),
|
||||
allowedPodNumber: n.allowedPodNumber,
|
||||
taintsErr: n.taintsErr,
|
||||
memoryPressureCondition: n.memoryPressureCondition,
|
||||
|
|
Loading…
Reference in New Issue