Vendor changes for v1.6.0-beta.3

pull/1314/head
Matt Rickard 2017-03-14 15:33:10 -07:00
parent b279d733ad
commit 73a0dfb487
46 changed files with 1940 additions and 1868 deletions

3141
Godeps/Godeps.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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).

View File

@ -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
}

View File

@ -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.

View File

@ -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"`
}

View File

@ -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"

View File

@ -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.

View File

@ -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",

View File

@ -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 {

View File

@ -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]
}

View File

@ -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"`
}

View File

@ -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 {

View File

@ -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

View File

@ -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
}

View File

@ -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")

View File

@ -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.

View File

@ -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)

View File

@ -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)

View File

@ -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{

View File

@ -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",

View File

@ -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
})

View File

@ -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{}

View File

@ -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()

View File

@ -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
}

View File

@ -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.

View File

@ -28,6 +28,7 @@ import (
// (kubecontainer) types.
const (
statusRunningPrefix = "Up"
statusCreatedPrefix = "Created"
statusExitedPrefix = "Exited"
)

View File

@ -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.

View File

@ -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)

View File

@ -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)
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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",

View File

@ -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 {

View File

@ -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",

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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"

View File

@ -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"],

View File

@ -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()

44
vendor/k8s.io/kubernetes/pkg/volume/validation/BUILD generated vendored Normal file
View File

@ -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"],
)

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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,