mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
test/e2e: check both beta and zone label for getting cluster zone
Signed-off-by: Andrew Sy Kim <kiman@vmware.com>
This commit is contained in:
parent
07229d6c51
commit
349749644f
@ -35,7 +35,6 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
@ -520,7 +519,7 @@ func (c *awsElasticBlockStoreProvisioner) Provision(selectedNode *v1.Node, allow
|
|||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: c.options.PVName,
|
Name: c.options.PVName,
|
||||||
Labels: labels,
|
Labels: map[string]string{},
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
util.VolumeDynamicallyCreatedByKey: "aws-ebs-dynamic-provisioner",
|
util.VolumeDynamicallyCreatedByKey: "aws-ebs-dynamic-provisioner",
|
||||||
},
|
},
|
||||||
@ -548,9 +547,21 @@ func (c *awsElasticBlockStoreProvisioner) Provision(selectedNode *v1.Node, allow
|
|||||||
pv.Spec.AccessModes = c.plugin.GetAccessModes()
|
pv.Spec.AccessModes = c.plugin.GetAccessModes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requirements := make([]v1.NodeSelectorRequirement, 0)
|
||||||
|
if len(labels) != 0 {
|
||||||
|
if pv.Labels == nil {
|
||||||
|
pv.Labels = make(map[string]string)
|
||||||
|
}
|
||||||
|
for k, v := range labels {
|
||||||
|
pv.Labels[k] = v
|
||||||
|
requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
||||||
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
||||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = volumehelpers.TranslateZoneRegionLabelsToNodeSelectorTerms(labels)
|
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1)
|
||||||
|
pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements
|
||||||
|
|
||||||
return pv, nil
|
return pv, nil
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ func TestPlugin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n := len(persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms)
|
n := len(persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms)
|
||||||
if n != 2 {
|
if n != 1 {
|
||||||
t.Errorf("Provision() returned unexpected number of NodeSelectorTerms %d. Expected %d", n, 1)
|
t.Errorf("Provision() returned unexpected number of NodeSelectorTerms %d. Expected %d", n, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,25 +228,6 @@ func TestPlugin(t *testing.T) {
|
|||||||
if len(req.Values) != 1 || req.Values[0] != "yes" {
|
if len(req.Values) != 1 || req.Values[0] != "yes" {
|
||||||
t.Errorf("Provision() returned unexpected requirement value in NodeAffinity %v", req.Values)
|
t.Errorf("Provision() returned unexpected requirement value in NodeAffinity %v", req.Values)
|
||||||
}
|
}
|
||||||
|
|
||||||
n = len(persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms[1].MatchExpressions)
|
|
||||||
if n != 1 {
|
|
||||||
t.Errorf("Provision() returned unexpected number of MatchExpressions %d. Expected %d", n, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
req = persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms[1].MatchExpressions[0]
|
|
||||||
if req.Key != "fakepdmanager" {
|
|
||||||
t.Errorf("Provision() returned unexpected requirement key in NodeAffinity %v", req.Key)
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.Operator != v1.NodeSelectorOpIn {
|
|
||||||
t.Errorf("Provision() returned unexpected requirement operator in NodeAffinity %v", req.Operator)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(req.Values) != 1 || req.Values[0] != "yes" {
|
|
||||||
t.Errorf("Provision() returned unexpected requirement value in NodeAffinity %v", req.Values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test Deleter
|
// Test Deleter
|
||||||
volSpec := &volume.Spec{
|
volSpec := &volume.Spec{
|
||||||
PersistentVolume: persistentSpec,
|
PersistentVolume: persistentSpec,
|
||||||
|
@ -322,16 +322,22 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
|
|||||||
if zoned {
|
if zoned {
|
||||||
// Set node affinity labels based on availability zone labels.
|
// Set node affinity labels based on availability zone labels.
|
||||||
if len(labels) > 0 {
|
if len(labels) > 0 {
|
||||||
nodeSelectorTerms = volumehelpers.TranslateZoneRegionLabelsToNodeSelectorTerms(labels)
|
requirements := make([]v1.NodeSelectorRequirement, 0)
|
||||||
}
|
for k, v := range labels {
|
||||||
|
requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
||||||
|
MatchExpressions: requirements,
|
||||||
|
})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Set node affinity labels based on fault domains.
|
// Set node affinity labels based on fault domains.
|
||||||
// This is required because unzoned AzureDisk can't be attached to zoned nodes.
|
// This is required because unzoned AzureDisk can't be attached to zoned nodes.
|
||||||
// There are at most 3 fault domains available in each region.
|
// There are at most 3 fault domains available in each region.
|
||||||
// Refer https://docs.microsoft.com/en-us/azure/virtual-machines/windows/manage-availability.
|
// Refer https://docs.microsoft.com/en-us/azure/virtual-machines/windows/manage-availability.
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
deprecatedTopologyReqs := []v1.NodeSelectorRequirement{
|
requirements := []v1.NodeSelectorRequirement{
|
||||||
{
|
{
|
||||||
Key: v1.LabelZoneRegion,
|
Key: v1.LabelZoneRegion,
|
||||||
Operator: v1.NodeSelectorOpIn,
|
Operator: v1.NodeSelectorOpIn,
|
||||||
@ -343,25 +349,8 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
|
|||||||
Values: []string{strconv.Itoa(i)},
|
Values: []string{strconv.Itoa(i)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
topologyReqs := []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegionStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{diskController.GetLocation()},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{strconv.Itoa(i)},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
||||||
MatchExpressions: deprecatedTopologyReqs,
|
MatchExpressions: requirements,
|
||||||
})
|
|
||||||
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
|
||||||
MatchExpressions: topologyReqs,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/pkg/util/mount"
|
"k8s.io/kubernetes/pkg/util/mount"
|
||||||
@ -619,9 +618,18 @@ func (c *cinderVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopolo
|
|||||||
pv.Spec.AccessModes = c.plugin.GetAccessModes()
|
pv.Spec.AccessModes = c.plugin.GetAccessModes()
|
||||||
}
|
}
|
||||||
|
|
||||||
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
requirements := make([]v1.NodeSelectorRequirement, 0)
|
||||||
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
for k, v := range labels {
|
||||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = volumehelpers.TranslateZoneRegionLabelsToNodeSelectorTerms(labels)
|
if v != "" {
|
||||||
|
requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(requirements) > 0 {
|
||||||
|
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
||||||
|
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
||||||
|
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1)
|
||||||
|
pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements
|
||||||
|
}
|
||||||
|
|
||||||
return pv, nil
|
return pv, nil
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,6 @@ func (fake *fakePDManager) DetachDisk(c *cinderVolumeUnmounter) error {
|
|||||||
func (fake *fakePDManager) CreateVolume(c *cinderVolumeProvisioner, node *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (volumeID string, volumeSizeGB int, labels map[string]string, fstype string, err error) {
|
func (fake *fakePDManager) CreateVolume(c *cinderVolumeProvisioner, node *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (volumeID string, volumeSizeGB int, labels map[string]string, fstype string, err error) {
|
||||||
labels = make(map[string]string)
|
labels = make(map[string]string)
|
||||||
labels[v1.LabelZoneFailureDomain] = "nova"
|
labels[v1.LabelZoneFailureDomain] = "nova"
|
||||||
labels[v1.LabelZoneFailureDomainStable] = "nova"
|
|
||||||
return "test-volume-name", 1, labels, "", nil
|
return "test-volume-name", 1, labels, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,7 +229,7 @@ func TestPlugin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n := len(persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms)
|
n := len(persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms)
|
||||||
if n != 2 {
|
if n != 1 {
|
||||||
t.Errorf("Provision() returned unexpected number of NodeSelectorTerms %d. Expected %d", n, 1)
|
t.Errorf("Provision() returned unexpected number of NodeSelectorTerms %d. Expected %d", n, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,25 +252,6 @@ func TestPlugin(t *testing.T) {
|
|||||||
t.Errorf("Provision() returned unexpected requirement value in NodeAffinity %v", req.Values)
|
t.Errorf("Provision() returned unexpected requirement value in NodeAffinity %v", req.Values)
|
||||||
}
|
}
|
||||||
|
|
||||||
n = len(persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms[1].MatchExpressions)
|
|
||||||
if n != 1 {
|
|
||||||
t.Errorf("Provision() returned unexpected number of MatchExpressions %d. Expected %d", n, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
req = persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms[1].MatchExpressions[0]
|
|
||||||
|
|
||||||
if req.Key != v1.LabelZoneFailureDomainStable {
|
|
||||||
t.Errorf("Provision() returned unexpected requirement key in NodeAffinity %v", req.Key)
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.Operator != v1.NodeSelectorOpIn {
|
|
||||||
t.Errorf("Provision() returned unexpected requirement operator in NodeAffinity %v", req.Operator)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(req.Values) != 1 || req.Values[0] != "nova" {
|
|
||||||
t.Errorf("Provision() returned unexpected requirement value in NodeAffinity %v", req.Values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test Deleter
|
// Test Deleter
|
||||||
volSpec := &volume.Spec{
|
volSpec := &volume.Spec{
|
||||||
PersistentVolume: persistentSpec,
|
PersistentVolume: persistentSpec,
|
||||||
|
@ -157,12 +157,6 @@ func getZonesFromNodes(kubeClient clientset.Interface) (sets.String, error) {
|
|||||||
for _, node := range nodes.Items {
|
for _, node := range nodes.Items {
|
||||||
if zone, ok := node.Labels[v1.LabelZoneFailureDomain]; ok {
|
if zone, ok := node.Labels[v1.LabelZoneFailureDomain]; ok {
|
||||||
zones.Insert(zone)
|
zones.Insert(zone)
|
||||||
// don't need to check GA label if beta label already exists
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if zone, ok := node.Labels[v1.LabelZoneFailureDomainStable]; ok {
|
|
||||||
zones.Insert(zone)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
klog.V(4).Infof("zones found: %v", zones)
|
klog.V(4).Infof("zones found: %v", zones)
|
||||||
@ -235,12 +229,9 @@ func (util *DiskUtil) CreateVolume(c *cinderVolumeProvisioner, node *v1.Node, al
|
|||||||
if IgnoreVolumeAZ == false {
|
if IgnoreVolumeAZ == false {
|
||||||
if volumeAZ != "" {
|
if volumeAZ != "" {
|
||||||
volumeLabels[v1.LabelZoneFailureDomain] = volumeAZ
|
volumeLabels[v1.LabelZoneFailureDomain] = volumeAZ
|
||||||
volumeLabels[v1.LabelZoneFailureDomainStable] = volumeAZ
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if volumeRegion != "" {
|
if volumeRegion != "" {
|
||||||
volumeLabels[v1.LabelZoneRegion] = volumeRegion
|
volumeLabels[v1.LabelZoneRegion] = volumeRegion
|
||||||
volumeLabels[v1.LabelZoneRegionStable] = volumeRegion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return volumeID, volSizeGiB, volumeLabels, fstype, nil
|
return volumeID, volSizeGiB, volumeLabels, fstype, nil
|
||||||
|
@ -457,8 +457,7 @@ func createPVSpec(name string, readOnly bool, zones []string) *volume.Spec {
|
|||||||
if zones != nil {
|
if zones != nil {
|
||||||
zonesLabel := strings.Join(zones, cloudvolume.LabelMultiZoneDelimiter)
|
zonesLabel := strings.Join(zones, cloudvolume.LabelMultiZoneDelimiter)
|
||||||
spec.PersistentVolume.ObjectMeta.Labels = map[string]string{
|
spec.PersistentVolume.ObjectMeta.Labels = map[string]string{
|
||||||
v1.LabelZoneFailureDomain: zonesLabel,
|
v1.LabelZoneFailureDomain: zonesLabel,
|
||||||
v1.LabelZoneFailureDomainStable: zonesLabel,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +515,7 @@ func (c *gcePersistentDiskProvisioner) Provision(selectedNode *v1.Node, allowedT
|
|||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: c.options.PVName,
|
Name: c.options.PVName,
|
||||||
Labels: labels,
|
Labels: map[string]string{},
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
util.VolumeDynamicallyCreatedByKey: "gce-pd-dynamic-provisioner",
|
util.VolumeDynamicallyCreatedByKey: "gce-pd-dynamic-provisioner",
|
||||||
},
|
},
|
||||||
@ -542,15 +542,32 @@ func (c *gcePersistentDiskProvisioner) Provision(selectedNode *v1.Node, allowedT
|
|||||||
pv.Spec.AccessModes = c.plugin.GetAccessModes()
|
pv.Spec.AccessModes = c.plugin.GetAccessModes()
|
||||||
}
|
}
|
||||||
|
|
||||||
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
requirements := make([]v1.NodeSelectorRequirement, 0)
|
||||||
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
if len(labels) != 0 {
|
||||||
|
if pv.Labels == nil {
|
||||||
nodeSelectorTerms, err := volumehelpers.TranslateZoneLabelsToNodeSelectorTerms(labels)
|
pv.Labels = make(map[string]string)
|
||||||
if err != nil {
|
}
|
||||||
return nil, err
|
for k, v := range labels {
|
||||||
|
pv.Labels[k] = v
|
||||||
|
var values []string
|
||||||
|
if k == v1.LabelZoneFailureDomain {
|
||||||
|
values, err = volumehelpers.LabelZonesToList(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to convert label string for Zone: %s to a List: %v", v, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
values = []string{v}
|
||||||
|
}
|
||||||
|
requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: values})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = nodeSelectorTerms
|
if len(requirements) > 0 {
|
||||||
|
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
||||||
|
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
||||||
|
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1)
|
||||||
|
pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements
|
||||||
|
}
|
||||||
|
|
||||||
return pv, nil
|
return pv, nil
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,6 @@ func (fake *fakePDManager) CreateVolume(c *gcePersistentDiskProvisioner, node *v
|
|||||||
labels = make(map[string]string)
|
labels = make(map[string]string)
|
||||||
labels["fakepdmanager"] = "yes"
|
labels["fakepdmanager"] = "yes"
|
||||||
labels[v1.LabelZoneFailureDomain] = "zone1__zone2"
|
labels[v1.LabelZoneFailureDomain] = "zone1__zone2"
|
||||||
labels[v1.LabelZoneFailureDomainStable] = "zone1__zone2"
|
|
||||||
return "test-gce-volume-name", 100, labels, "", nil
|
return "test-gce-volume-name", 100, labels, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,14 +203,10 @@ func TestPlugin(t *testing.T) {
|
|||||||
t.Errorf("Provision() returned unexpected value for %s: %v", v1.LabelZoneFailureDomain, persistentSpec.Labels[v1.LabelZoneFailureDomain])
|
t.Errorf("Provision() returned unexpected value for %s: %v", v1.LabelZoneFailureDomain, persistentSpec.Labels[v1.LabelZoneFailureDomain])
|
||||||
}
|
}
|
||||||
|
|
||||||
if persistentSpec.Labels[v1.LabelZoneFailureDomainStable] != "zone1__zone2" {
|
|
||||||
t.Errorf("Provision() returned unexpected value for %s: %v", v1.LabelZoneFailureDomainStable, persistentSpec.Labels[v1.LabelZoneFailureDomainStable])
|
|
||||||
}
|
|
||||||
|
|
||||||
if persistentSpec.Spec.NodeAffinity == nil {
|
if persistentSpec.Spec.NodeAffinity == nil {
|
||||||
t.Errorf("Unexpected nil NodeAffinity found")
|
t.Errorf("Unexpected nil NodeAffinity found")
|
||||||
}
|
}
|
||||||
if len(persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms) != 2 {
|
if len(persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms) != 1 {
|
||||||
t.Errorf("Unexpected number of NodeSelectorTerms")
|
t.Errorf("Unexpected number of NodeSelectorTerms")
|
||||||
}
|
}
|
||||||
term := persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms[0]
|
term := persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms[0]
|
||||||
@ -232,24 +227,6 @@ func TestPlugin(t *testing.T) {
|
|||||||
t.Errorf("ZoneFailureDomain elements %v does not match zone labels %v", r.Values, zones)
|
t.Errorf("ZoneFailureDomain elements %v does not match zone labels %v", r.Values, zones)
|
||||||
}
|
}
|
||||||
|
|
||||||
term = persistentSpec.Spec.NodeAffinity.Required.NodeSelectorTerms[1]
|
|
||||||
if len(term.MatchExpressions) != 2 {
|
|
||||||
t.Errorf("Unexpected number of NodeSelectorRequirements in volume NodeAffinity: %d", len(term.MatchExpressions))
|
|
||||||
}
|
|
||||||
r, _ = getNodeSelectorRequirementWithKey("fakepdmanager", term)
|
|
||||||
if r == nil || r.Values[0] != "yes" || r.Operator != v1.NodeSelectorOpIn {
|
|
||||||
t.Errorf("NodeSelectorRequirement fakepdmanager-in-yes not found in volume NodeAffinity")
|
|
||||||
}
|
|
||||||
zones, _ = volumehelpers.ZonesToSet("zone1,zone2")
|
|
||||||
r, _ = getNodeSelectorRequirementWithKey(v1.LabelZoneFailureDomainStable, term)
|
|
||||||
if r == nil {
|
|
||||||
t.Errorf("NodeSelectorRequirement %s-in-%v not found in volume NodeAffinity", v1.LabelZoneFailureDomainStable, zones)
|
|
||||||
}
|
|
||||||
sort.Strings(r.Values)
|
|
||||||
if !reflect.DeepEqual(r.Values, zones.List()) {
|
|
||||||
t.Errorf("ZoneFailureDomain elements %v does not match zone labels %v", r.Values, zones)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test Deleter
|
// Test Deleter
|
||||||
volSpec := &volume.Spec{
|
volSpec := &volume.Spec{
|
||||||
PersistentVolume: persistentSpec,
|
PersistentVolume: persistentSpec,
|
||||||
|
@ -349,11 +349,7 @@ func udevadmChangeToDrive(drivePath string) error {
|
|||||||
// Checks whether the given GCE PD volume spec is associated with a regional PD.
|
// Checks whether the given GCE PD volume spec is associated with a regional PD.
|
||||||
func isRegionalPD(spec *volume.Spec) bool {
|
func isRegionalPD(spec *volume.Spec) bool {
|
||||||
if spec.PersistentVolume != nil {
|
if spec.PersistentVolume != nil {
|
||||||
zonesLabel, ok := spec.PersistentVolume.Labels[v1.LabelZoneFailureDomain]
|
zonesLabel := spec.PersistentVolume.Labels[v1.LabelZoneFailureDomain]
|
||||||
if !ok {
|
|
||||||
zonesLabel = spec.PersistentVolume.Labels[v1.LabelZoneFailureDomainStable]
|
|
||||||
}
|
|
||||||
|
|
||||||
zones := strings.Split(zonesLabel, cloudvolume.LabelMultiZoneDelimiter)
|
zones := strings.Split(zonesLabel, cloudvolume.LabelMultiZoneDelimiter)
|
||||||
return len(zones) > 1
|
return len(zones) > 1
|
||||||
}
|
}
|
||||||
|
@ -223,231 +223,6 @@ func TestCheckVolumeNodeAffinity(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_CheckNodeAffinityWithTopology(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
pv *v1.PersistentVolume
|
|
||||||
nodeLabels map[string]string
|
|
||||||
expectSuccess bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "PV has only beta label, node has beta/GA label -- zone only",
|
|
||||||
pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
|
|
||||||
Required: &v1.NodeSelector{
|
|
||||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
nodeLabels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone",
|
|
||||||
v1.LabelZoneFailureDomainStable: "zone",
|
|
||||||
},
|
|
||||||
expectSuccess: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "PV has only beta label, node has beta/GA label -- zone and region",
|
|
||||||
pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
|
|
||||||
Required: &v1.NodeSelector{
|
|
||||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegion,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
nodeLabels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone",
|
|
||||||
v1.LabelZoneFailureDomainStable: "zone",
|
|
||||||
v1.LabelZoneRegion: "region",
|
|
||||||
v1.LabelZoneRegionStable: "region",
|
|
||||||
},
|
|
||||||
expectSuccess: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "PV has both beta/GA label, node has only beta -- zone only",
|
|
||||||
pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
|
|
||||||
Required: &v1.NodeSelector{
|
|
||||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
nodeLabels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone",
|
|
||||||
},
|
|
||||||
expectSuccess: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "PV has both beta/GA label, node has only beta -- zone and region",
|
|
||||||
pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
|
|
||||||
Required: &v1.NodeSelector{
|
|
||||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegion,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegionStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
nodeLabels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone",
|
|
||||||
v1.LabelZoneRegion: "region",
|
|
||||||
},
|
|
||||||
expectSuccess: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "PV has both beta/GA label, node has both beta/GA label -- zone only",
|
|
||||||
pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
|
|
||||||
Required: &v1.NodeSelector{
|
|
||||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
nodeLabels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone",
|
|
||||||
v1.LabelZoneFailureDomainStable: "zone",
|
|
||||||
},
|
|
||||||
expectSuccess: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "PV has both beta/GA label, node has both beta/GA label -- zone and region",
|
|
||||||
pv: testVolumeWithNodeAffinity(t, &v1.VolumeNodeAffinity{
|
|
||||||
Required: &v1.NodeSelector{
|
|
||||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegion,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegionStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
nodeLabels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone",
|
|
||||||
v1.LabelZoneRegion: "region",
|
|
||||||
v1.LabelZoneFailureDomainStable: "zone",
|
|
||||||
v1.LabelZoneRegionStable: "region",
|
|
||||||
},
|
|
||||||
expectSuccess: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
err := CheckNodeAffinity(test.pv, test.nodeLabels)
|
|
||||||
|
|
||||||
if err != nil && test.expectSuccess {
|
|
||||||
t.Errorf("CheckTopology returned error: %v", err)
|
|
||||||
}
|
|
||||||
if err == nil && !test.expectSuccess {
|
|
||||||
t.Error("CheckTopology returned success, expected error")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testVolumeWithNodeAffinity(t *testing.T, affinity *v1.VolumeNodeAffinity) *v1.PersistentVolume {
|
func testVolumeWithNodeAffinity(t *testing.T, affinity *v1.VolumeNodeAffinity) *v1.PersistentVolume {
|
||||||
objMeta := metav1.ObjectMeta{Name: "test-constraints"}
|
objMeta := metav1.ObjectMeta{Name: "test-constraints"}
|
||||||
return &v1.PersistentVolume{
|
return &v1.PersistentVolume{
|
||||||
|
@ -403,7 +403,7 @@ func (v *vsphereVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopol
|
|||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: v.options.PVName,
|
Name: v.options.PVName,
|
||||||
Labels: volSpec.Labels,
|
Labels: map[string]string{},
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
util.VolumeDynamicallyCreatedByKey: "vsphere-volume-dynamic-provisioner",
|
util.VolumeDynamicallyCreatedByKey: "vsphere-volume-dynamic-provisioner",
|
||||||
},
|
},
|
||||||
@ -430,15 +430,33 @@ func (v *vsphereVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopol
|
|||||||
pv.Spec.AccessModes = v.plugin.GetAccessModes()
|
pv.Spec.AccessModes = v.plugin.GetAccessModes()
|
||||||
}
|
}
|
||||||
|
|
||||||
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
labels := volSpec.Labels
|
||||||
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
requirements := make([]v1.NodeSelectorRequirement, 0)
|
||||||
|
if len(labels) != 0 {
|
||||||
nodeSelectorTerms, err := volumehelpers.TranslateZoneLabelsToNodeSelectorTerms(volSpec.Labels)
|
if pv.Labels == nil {
|
||||||
if err != nil {
|
pv.Labels = make(map[string]string)
|
||||||
return nil, err
|
}
|
||||||
|
for k, v := range labels {
|
||||||
|
pv.Labels[k] = v
|
||||||
|
var values []string
|
||||||
|
if k == v1.LabelZoneFailureDomain {
|
||||||
|
values, err = volumehelpers.LabelZonesToList(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to convert label string for Zone: %s to a List: %v", v, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
values = []string{v}
|
||||||
|
}
|
||||||
|
requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: values})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = nodeSelectorTerms
|
if len(requirements) > 0 {
|
||||||
|
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
||||||
|
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
||||||
|
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1)
|
||||||
|
pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements
|
||||||
|
}
|
||||||
|
|
||||||
return pv, nil
|
return pv, nil
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
@ -118,13 +117,11 @@ func (l *persistentVolumeLabel) Admit(ctx context.Context, a admission.Attribute
|
|||||||
return admission.NewForbidden(a, err)
|
return admission.NewForbidden(a, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requirements := make([]api.NodeSelectorRequirement, 0)
|
||||||
if len(volumeLabels) != 0 {
|
if len(volumeLabels) != 0 {
|
||||||
if volume.Labels == nil {
|
if volume.Labels == nil {
|
||||||
volume.Labels = make(map[string]string)
|
volume.Labels = make(map[string]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecatedTopologyReqs := make([]api.NodeSelectorRequirement, 0)
|
|
||||||
topologyReqs := make([]api.NodeSelectorRequirement, 0)
|
|
||||||
for k, v := range volumeLabels {
|
for k, v := range volumeLabels {
|
||||||
// We (silently) replace labels if they are provided.
|
// We (silently) replace labels if they are provided.
|
||||||
// This should be OK because they are in the kubernetes.io namespace
|
// This should be OK because they are in the kubernetes.io namespace
|
||||||
@ -132,11 +129,8 @@ func (l *persistentVolumeLabel) Admit(ctx context.Context, a admission.Attribute
|
|||||||
volume.Labels[k] = v
|
volume.Labels[k] = v
|
||||||
|
|
||||||
// Set NodeSelectorRequirements based on the labels
|
// Set NodeSelectorRequirements based on the labels
|
||||||
//
|
|
||||||
// we currently set both beta (failure-domain.beta.kubernetes.io/zone) and
|
|
||||||
// GA (topology.kubernetes.io/zone) topology labels for volumes
|
|
||||||
var values []string
|
var values []string
|
||||||
if k == v1.LabelZoneFailureDomain || k == v1.LabelZoneFailureDomainStable {
|
if k == v1.LabelZoneFailureDomain {
|
||||||
zones, err := volumehelpers.LabelZonesToSet(v)
|
zones, err := volumehelpers.LabelZonesToSet(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return admission.NewForbidden(a, fmt.Errorf("failed to convert label string for Zone: %s to a Set", v))
|
return admission.NewForbidden(a, fmt.Errorf("failed to convert label string for Zone: %s to a Set", v))
|
||||||
@ -146,17 +140,7 @@ func (l *persistentVolumeLabel) Admit(ctx context.Context, a admission.Attribute
|
|||||||
} else {
|
} else {
|
||||||
values = []string{v}
|
values = []string{v}
|
||||||
}
|
}
|
||||||
|
requirements = append(requirements, api.NodeSelectorRequirement{Key: k, Operator: api.NodeSelectorOpIn, Values: values})
|
||||||
// separate topology requirements based on deprecated vs stable zone/region labels
|
|
||||||
// all other labels apply to both requirements
|
|
||||||
if k == v1.LabelZoneFailureDomain || k == v1.LabelZoneRegion {
|
|
||||||
deprecatedTopologyReqs = append(deprecatedTopologyReqs, api.NodeSelectorRequirement{Key: k, Operator: api.NodeSelectorOpIn, Values: values})
|
|
||||||
} else if k == v1.LabelZoneFailureDomainStable || k == v1.LabelZoneRegionStable {
|
|
||||||
topologyReqs = append(topologyReqs, api.NodeSelectorRequirement{Key: k, Operator: api.NodeSelectorOpIn, Values: values})
|
|
||||||
} else {
|
|
||||||
deprecatedTopologyReqs = append(deprecatedTopologyReqs, api.NodeSelectorRequirement{Key: k, Operator: api.NodeSelectorOpIn, Values: values})
|
|
||||||
topologyReqs = append(topologyReqs, api.NodeSelectorRequirement{Key: k, Operator: api.NodeSelectorOpIn, Values: values})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if volume.Spec.NodeAffinity == nil {
|
if volume.Spec.NodeAffinity == nil {
|
||||||
@ -169,44 +153,16 @@ func (l *persistentVolumeLabel) Admit(ctx context.Context, a admission.Attribute
|
|||||||
// Need at least one term pre-allocated whose MatchExpressions can be appended to
|
// Need at least one term pre-allocated whose MatchExpressions can be appended to
|
||||||
volume.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]api.NodeSelectorTerm, 1)
|
volume.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]api.NodeSelectorTerm, 1)
|
||||||
}
|
}
|
||||||
|
if nodeSelectorRequirementKeysExistInNodeSelectorTerms(requirements, volume.Spec.NodeAffinity.Required.NodeSelectorTerms) {
|
||||||
deprecatedNodeTerms := volume.DeepCopy().Spec.NodeAffinity.Required.NodeSelectorTerms
|
klog.V(4).Infof("NodeSelectorRequirements for cloud labels %v conflict with existing NodeAffinity %v. Skipping addition of NodeSelectorRequirements for cloud labels.",
|
||||||
stableNodeTerms := volume.DeepCopy().Spec.NodeAffinity.Required.NodeSelectorTerms
|
requirements, volume.Spec.NodeAffinity)
|
||||||
|
} else {
|
||||||
// only attempt to rewrite beta/stable topology labels if there are no conflicting labels on the PV at all
|
for _, req := range requirements {
|
||||||
if nodeSelectorRequirementKeysExistInNodeSelectorTerms(deprecatedTopologyReqs, volume.Spec.NodeAffinity.Required.NodeSelectorTerms) ||
|
for i := range volume.Spec.NodeAffinity.Required.NodeSelectorTerms {
|
||||||
nodeSelectorRequirementKeysExistInNodeSelectorTerms(topologyReqs, volume.Spec.NodeAffinity.Required.NodeSelectorTerms) {
|
volume.Spec.NodeAffinity.Required.NodeSelectorTerms[i].MatchExpressions = append(volume.Spec.NodeAffinity.Required.NodeSelectorTerms[i].MatchExpressions, req)
|
||||||
klog.V(4).Infof("NodeSelectorRequirements for cloud labels %v conflict with existing NodeAffinity %v or %v. Skipping addition of NodeSelectorRequirements for cloud labels.",
|
}
|
||||||
deprecatedTopologyReqs, topologyReqs, volume.Spec.NodeAffinity)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, req := range deprecatedTopologyReqs {
|
|
||||||
for i := range deprecatedNodeTerms {
|
|
||||||
deprecatedNodeTerms[i].MatchExpressions = append(deprecatedNodeTerms[i].MatchExpressions, req)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, req := range topologyReqs {
|
|
||||||
for i := range stableNodeTerms {
|
|
||||||
stableNodeTerms[i].MatchExpressions = append(stableNodeTerms[i].MatchExpressions, req)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated and stable node selector terms are the same, i.e. the cloud provider
|
|
||||||
// didn't specify eithr zone/region labels. In the case set either one without
|
|
||||||
// expanding the set of selector terms
|
|
||||||
if reflect.DeepEqual(deprecatedTopologyReqs, topologyReqs) {
|
|
||||||
volume.Spec.NodeAffinity.Required.NodeSelectorTerms = stableNodeTerms
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// for deprecated topology labels, we overwrite existing terms directly with the deprecated topology reqs appended
|
|
||||||
volume.Spec.NodeAffinity.Required.NodeSelectorTerms = deprecatedNodeTerms
|
|
||||||
|
|
||||||
// for new stable topology labels, we expand node selector requirements by copying existing selector terms but using stable topology labels
|
|
||||||
volume.Spec.NodeAffinity.Required.NodeSelectorTerms = append(volume.Spec.NodeAffinity.Required.NodeSelectorTerms, stableNodeTerms...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -215,17 +171,15 @@ func (l *persistentVolumeLabel) Admit(ctx context.Context, a admission.Attribute
|
|||||||
func (l *persistentVolumeLabel) findVolumeLabels(volume *api.PersistentVolume) (map[string]string, error) {
|
func (l *persistentVolumeLabel) findVolumeLabels(volume *api.PersistentVolume) (map[string]string, error) {
|
||||||
existingLabels := volume.Labels
|
existingLabels := volume.Labels
|
||||||
|
|
||||||
// deprecated zone/region labels are still the source of truth
|
// All cloud providers set only these two labels.
|
||||||
domain, domainOK := existingLabels[v1.LabelZoneFailureDomain]
|
domain, domainOK := existingLabels[v1.LabelZoneFailureDomain]
|
||||||
region, regionOK := existingLabels[v1.LabelZoneRegion]
|
region, regionOK := existingLabels[v1.LabelZoneRegion]
|
||||||
isDynamicallyProvisioned := metav1.HasAnnotation(volume.ObjectMeta, persistentvolume.AnnDynamicallyProvisioned)
|
isDynamicallyProvisioned := metav1.HasAnnotation(volume.ObjectMeta, persistentvolume.AnnDynamicallyProvisioned)
|
||||||
if isDynamicallyProvisioned && domainOK && regionOK {
|
if isDynamicallyProvisioned && domainOK && regionOK {
|
||||||
// PV already has all the labels and we can trust the dynamic provisioning that it provided correct values.
|
// PV already has all the labels and we can trust the dynamic provisioning that it provided correct values.
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
v1.LabelZoneFailureDomain: domain,
|
v1.LabelZoneFailureDomain: domain,
|
||||||
v1.LabelZoneRegion: region,
|
v1.LabelZoneRegion: region,
|
||||||
v1.LabelZoneFailureDomainStable: domain,
|
|
||||||
v1.LabelZoneRegionStable: region,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,10 +66,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
name: "non-cloud PV ignored",
|
name: "non-cloud PV ignored",
|
||||||
handler: newPersistentVolumeLabel(),
|
handler: newPersistentVolumeLabel(),
|
||||||
pvlabeler: mockVolumeLabels(map[string]string{
|
pvlabeler: mockVolumeLabels(map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
}),
|
}),
|
||||||
preAdmissionPV: &api.PersistentVolume{
|
preAdmissionPV: &api.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "noncloud", Namespace: "myns"},
|
ObjectMeta: metav1.ObjectMeta{Name: "noncloud", Namespace: "myns"},
|
||||||
@ -175,10 +174,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
name: "AWS EBS PV labeled correctly",
|
name: "AWS EBS PV labeled correctly",
|
||||||
handler: newPersistentVolumeLabel(),
|
handler: newPersistentVolumeLabel(),
|
||||||
pvlabeler: mockVolumeLabels(map[string]string{
|
pvlabeler: mockVolumeLabels(map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
}),
|
}),
|
||||||
preAdmissionPV: &api.PersistentVolume{
|
preAdmissionPV: &api.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "awsebs", Namespace: "myns"},
|
ObjectMeta: metav1.ObjectMeta{Name: "awsebs", Namespace: "myns"},
|
||||||
@ -195,10 +193,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
Name: "awsebs",
|
Name: "awsebs",
|
||||||
Namespace: "myns",
|
Namespace: "myns",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: api.PersistentVolumeSpec{
|
Spec: api.PersistentVolumeSpec{
|
||||||
@ -229,25 +226,6 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MatchExpressions: []api.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: "a",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "b",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"2"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1", "2", "3"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -259,19 +237,15 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
name: "existing labels from dynamic provisioning are not changed",
|
name: "existing labels from dynamic provisioning are not changed",
|
||||||
handler: newPersistentVolumeLabel(),
|
handler: newPersistentVolumeLabel(),
|
||||||
pvlabeler: mockVolumeLabels(map[string]string{
|
pvlabeler: mockVolumeLabels(map[string]string{
|
||||||
v1.LabelZoneFailureDomain: "domain1",
|
v1.LabelZoneFailureDomain: "domain1",
|
||||||
v1.LabelZoneRegion: "region1",
|
v1.LabelZoneRegion: "region1",
|
||||||
v1.LabelZoneFailureDomainStable: "domain1",
|
|
||||||
v1.LabelZoneRegionStable: "region1",
|
|
||||||
}),
|
}),
|
||||||
preAdmissionPV: &api.PersistentVolume{
|
preAdmissionPV: &api.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "awsebs", Namespace: "myns",
|
Name: "awsebs", Namespace: "myns",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
v1.LabelZoneFailureDomain: "existingDomain",
|
v1.LabelZoneFailureDomain: "existingDomain",
|
||||||
v1.LabelZoneRegion: "existingRegion",
|
v1.LabelZoneRegion: "existingRegion",
|
||||||
v1.LabelZoneFailureDomainStable: "existingDomain",
|
|
||||||
v1.LabelZoneRegionStable: "existingRegion",
|
|
||||||
},
|
},
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
persistentvolume.AnnDynamicallyProvisioned: "kubernetes.io/aws-ebs",
|
persistentvolume.AnnDynamicallyProvisioned: "kubernetes.io/aws-ebs",
|
||||||
@ -290,10 +264,8 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
Name: "awsebs",
|
Name: "awsebs",
|
||||||
Namespace: "myns",
|
Namespace: "myns",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
v1.LabelZoneFailureDomain: "existingDomain",
|
v1.LabelZoneFailureDomain: "existingDomain",
|
||||||
v1.LabelZoneRegion: "existingRegion",
|
v1.LabelZoneRegion: "existingRegion",
|
||||||
v1.LabelZoneFailureDomainStable: "existingDomain",
|
|
||||||
v1.LabelZoneRegionStable: "existingRegion",
|
|
||||||
},
|
},
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
persistentvolume.AnnDynamicallyProvisioned: "kubernetes.io/aws-ebs",
|
persistentvolume.AnnDynamicallyProvisioned: "kubernetes.io/aws-ebs",
|
||||||
@ -322,20 +294,6 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MatchExpressions: []api.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegionStable,
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"existingRegion"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"existingDomain"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -347,10 +305,8 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
name: "existing labels from user are changed",
|
name: "existing labels from user are changed",
|
||||||
handler: newPersistentVolumeLabel(),
|
handler: newPersistentVolumeLabel(),
|
||||||
pvlabeler: mockVolumeLabels(map[string]string{
|
pvlabeler: mockVolumeLabels(map[string]string{
|
||||||
v1.LabelZoneFailureDomain: "domain1",
|
v1.LabelZoneFailureDomain: "domain1",
|
||||||
v1.LabelZoneRegion: "region1",
|
v1.LabelZoneRegion: "region1",
|
||||||
v1.LabelZoneFailureDomainStable: "domain1",
|
|
||||||
v1.LabelZoneRegionStable: "region1",
|
|
||||||
}),
|
}),
|
||||||
preAdmissionPV: &api.PersistentVolume{
|
preAdmissionPV: &api.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -373,10 +329,8 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
Name: "awsebs",
|
Name: "awsebs",
|
||||||
Namespace: "myns",
|
Namespace: "myns",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
v1.LabelZoneFailureDomain: "domain1",
|
v1.LabelZoneFailureDomain: "domain1",
|
||||||
v1.LabelZoneRegion: "region1",
|
v1.LabelZoneRegion: "region1",
|
||||||
v1.LabelZoneFailureDomainStable: "domain1",
|
|
||||||
v1.LabelZoneRegionStable: "region1",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: api.PersistentVolumeSpec{
|
Spec: api.PersistentVolumeSpec{
|
||||||
@ -402,20 +356,6 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MatchExpressions: []api.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegionStable,
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"domain1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -427,10 +367,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
name: "GCE PD PV labeled correctly",
|
name: "GCE PD PV labeled correctly",
|
||||||
handler: newPersistentVolumeLabel(),
|
handler: newPersistentVolumeLabel(),
|
||||||
pvlabeler: mockVolumeLabels(map[string]string{
|
pvlabeler: mockVolumeLabels(map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
}),
|
}),
|
||||||
preAdmissionPV: &api.PersistentVolume{
|
preAdmissionPV: &api.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "gcepd", Namespace: "myns"},
|
ObjectMeta: metav1.ObjectMeta{Name: "gcepd", Namespace: "myns"},
|
||||||
@ -447,10 +386,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
Name: "gcepd",
|
Name: "gcepd",
|
||||||
Namespace: "myns",
|
Namespace: "myns",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: api.PersistentVolumeSpec{
|
Spec: api.PersistentVolumeSpec{
|
||||||
@ -481,25 +419,6 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MatchExpressions: []api.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: "a",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "b",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"2"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1", "2", "3"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -511,10 +430,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
name: "Azure Disk PV labeled correctly",
|
name: "Azure Disk PV labeled correctly",
|
||||||
handler: newPersistentVolumeLabel(),
|
handler: newPersistentVolumeLabel(),
|
||||||
pvlabeler: mockVolumeLabels(map[string]string{
|
pvlabeler: mockVolumeLabels(map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
}),
|
}),
|
||||||
preAdmissionPV: &api.PersistentVolume{
|
preAdmissionPV: &api.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -534,10 +452,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
Name: "azurepd",
|
Name: "azurepd",
|
||||||
Namespace: "myns",
|
Namespace: "myns",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: api.PersistentVolumeSpec{
|
Spec: api.PersistentVolumeSpec{
|
||||||
@ -568,25 +485,6 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MatchExpressions: []api.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: "a",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "b",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"2"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1", "2", "3"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -598,10 +496,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
name: "Cinder Disk PV labeled correctly",
|
name: "Cinder Disk PV labeled correctly",
|
||||||
handler: newPersistentVolumeLabel(),
|
handler: newPersistentVolumeLabel(),
|
||||||
pvlabeler: mockVolumeLabels(map[string]string{
|
pvlabeler: mockVolumeLabels(map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
}),
|
}),
|
||||||
preAdmissionPV: &api.PersistentVolume{
|
preAdmissionPV: &api.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -621,10 +518,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
Name: "azurepd",
|
Name: "azurepd",
|
||||||
Namespace: "myns",
|
Namespace: "myns",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: api.PersistentVolumeSpec{
|
Spec: api.PersistentVolumeSpec{
|
||||||
@ -655,25 +551,6 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MatchExpressions: []api.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: "a",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "b",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"2"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1", "2", "3"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -685,10 +562,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
name: "AWS EBS PV overrides user applied labels",
|
name: "AWS EBS PV overrides user applied labels",
|
||||||
handler: newPersistentVolumeLabel(),
|
handler: newPersistentVolumeLabel(),
|
||||||
pvlabeler: mockVolumeLabels(map[string]string{
|
pvlabeler: mockVolumeLabels(map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
}),
|
}),
|
||||||
preAdmissionPV: &api.PersistentVolume{
|
preAdmissionPV: &api.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -711,10 +587,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
Name: "awsebs",
|
Name: "awsebs",
|
||||||
Namespace: "myns",
|
Namespace: "myns",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: api.PersistentVolumeSpec{
|
Spec: api.PersistentVolumeSpec{
|
||||||
@ -745,25 +620,6 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MatchExpressions: []api.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: "a",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "b",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"2"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1", "2", "3"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -963,10 +819,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
name: "vSphere PV labeled correctly",
|
name: "vSphere PV labeled correctly",
|
||||||
handler: newPersistentVolumeLabel(),
|
handler: newPersistentVolumeLabel(),
|
||||||
pvlabeler: mockVolumeLabels(map[string]string{
|
pvlabeler: mockVolumeLabels(map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
}),
|
}),
|
||||||
preAdmissionPV: &api.PersistentVolume{
|
preAdmissionPV: &api.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -986,10 +841,9 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
Name: "vSpherePV",
|
Name: "vSpherePV",
|
||||||
Namespace: "myns",
|
Namespace: "myns",
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"a": "1",
|
"a": "1",
|
||||||
"b": "2",
|
"b": "2",
|
||||||
v1.LabelZoneFailureDomain: "1__2__3",
|
v1.LabelZoneFailureDomain: "1__2__3",
|
||||||
v1.LabelZoneFailureDomainStable: "1__2__3",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: api.PersistentVolumeSpec{
|
Spec: api.PersistentVolumeSpec{
|
||||||
@ -1020,25 +874,6 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MatchExpressions: []api.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: "a",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "b",
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"2"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: api.NodeSelectorOpIn,
|
|
||||||
Values: []string{"1", "2", "3"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1065,8 +900,6 @@ func Test_PVLAdmission(t *testing.T) {
|
|||||||
if !reflect.DeepEqual(testcase.preAdmissionPV, testcase.postAdmissionPV) {
|
if !reflect.DeepEqual(testcase.preAdmissionPV, testcase.postAdmissionPV) {
|
||||||
t.Logf("expected PV: %+v", testcase.postAdmissionPV)
|
t.Logf("expected PV: %+v", testcase.postAdmissionPV)
|
||||||
t.Logf("actual PV: %+v", testcase.preAdmissionPV)
|
t.Logf("actual PV: %+v", testcase.preAdmissionPV)
|
||||||
t.Logf("expected PV node affinity: %+v", testcase.postAdmissionPV.Spec.NodeAffinity.Required)
|
|
||||||
t.Logf("actual PV node affinity: %+v", testcase.preAdmissionPV.Spec.NodeAffinity.Required)
|
|
||||||
t.Error("unexpected PV")
|
t.Error("unexpected PV")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1094,12 +927,10 @@ func sortMatchExpressions(pv *api.PersistentVolume) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for t := range pv.Spec.NodeAffinity.Required.NodeSelectorTerms {
|
match := pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions
|
||||||
match := pv.Spec.NodeAffinity.Required.NodeSelectorTerms[t].MatchExpressions
|
sort.Slice(match, func(i, j int) bool {
|
||||||
sort.Slice(match, func(i, j int) bool {
|
return match[i].Key < match[j].Key
|
||||||
return match[i].Key < match[j].Key
|
})
|
||||||
})
|
|
||||||
|
|
||||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms[t].MatchExpressions = match
|
pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = match
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -120,11 +120,7 @@ func SelectZonesForVolume(zoneParameterPresent, zonesParameterPresent bool, zone
|
|||||||
var ok bool
|
var ok bool
|
||||||
zoneFromNode, ok = node.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
|
zoneFromNode, ok = node.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
|
||||||
if !ok {
|
if !ok {
|
||||||
zoneFromNode, ok = node.ObjectMeta.Labels[v1.LabelZoneFailureDomainStable]
|
return nil, fmt.Errorf("%s Label for node missing", v1.LabelZoneFailureDomain)
|
||||||
}
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("Label %q or %q for node is missing", v1.LabelZoneFailureDomain, v1.LabelZoneFailureDomainStable)
|
|
||||||
}
|
}
|
||||||
// if single replica volume and node with zone found, return immediately
|
// if single replica volume and node with zone found, return immediately
|
||||||
if numReplicas == 1 {
|
if numReplicas == 1 {
|
||||||
@ -139,8 +135,7 @@ func SelectZonesForVolume(zoneParameterPresent, zonesParameterPresent bool, zone
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (len(allowedTopologies) > 0) && (allowedZones.Len() == 0) {
|
if (len(allowedTopologies) > 0) && (allowedZones.Len() == 0) {
|
||||||
return nil, fmt.Errorf("no matchLabelExpressions with keys %q,%q found in allowedTopologies. Please specify matchLabelExpressions with keys: %q,%q",
|
return nil, fmt.Errorf("no matchLabelExpressions with %s key found in allowedTopologies. Please specify matchLabelExpressions with %s key", v1.LabelZoneFailureDomain, v1.LabelZoneFailureDomain)
|
||||||
v1.LabelZoneFailureDomain, v1.LabelZoneFailureDomainStable, v1.LabelZoneFailureDomain, v1.LabelZoneFailureDomainStable)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if allowedZones.Len() > 0 {
|
if allowedZones.Len() > 0 {
|
||||||
@ -190,7 +185,7 @@ func ZonesFromAllowedTopologies(allowedTopologies []v1.TopologySelectorTerm) (se
|
|||||||
zones := make(sets.String)
|
zones := make(sets.String)
|
||||||
for _, term := range allowedTopologies {
|
for _, term := range allowedTopologies {
|
||||||
for _, exp := range term.MatchLabelExpressions {
|
for _, exp := range term.MatchLabelExpressions {
|
||||||
if exp.Key == v1.LabelZoneFailureDomain || exp.Key == v1.LabelZoneFailureDomainStable {
|
if exp.Key == v1.LabelZoneFailureDomain {
|
||||||
for _, value := range exp.Values {
|
for _, value := range exp.Values {
|
||||||
zones.Insert(value)
|
zones.Insert(value)
|
||||||
}
|
}
|
||||||
@ -313,103 +308,3 @@ func getPVCNameHashAndIndexOffset(pvcName string) (hash uint32, index uint32) {
|
|||||||
|
|
||||||
return hash, index
|
return hash, index
|
||||||
}
|
}
|
||||||
|
|
||||||
// TranslateZoneRegionLabelsToNodeSelectorTerms translates the set of provided labels as []v1.NodeSelectorTerms.
|
|
||||||
// For zone/region topologies, a node can have either only the beta label (failure-domain.beta.kubernetes.io/{zone,region})
|
|
||||||
// or both the beta and GA label (topology.kubernetes.io/{zone,region}). We have to put each topology label into
|
|
||||||
// separate node selector terms so PVs can be scheduled on nodes with either one or both labels
|
|
||||||
func TranslateZoneRegionLabelsToNodeSelectorTerms(labels map[string]string) []v1.NodeSelectorTerm {
|
|
||||||
nodeSelectorTerms := make([]v1.NodeSelectorTerm, 0)
|
|
||||||
deprecatedTopologyReqs := make([]v1.NodeSelectorRequirement, 0)
|
|
||||||
topologyReqs := make([]v1.NodeSelectorRequirement, 0)
|
|
||||||
|
|
||||||
if len(labels) == 0 {
|
|
||||||
return nodeSelectorTerms
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range labels {
|
|
||||||
if k == v1.LabelZoneFailureDomain || k == v1.LabelZoneRegion {
|
|
||||||
deprecatedTopologyReqs = append(deprecatedTopologyReqs, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if k == v1.LabelZoneFailureDomainStable || k == v1.LabelZoneRegionStable {
|
|
||||||
topologyReqs = append(topologyReqs, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// remaining labels outside known topology labels get added to both beta and GA node selectors
|
|
||||||
deprecatedTopologyReqs = append(deprecatedTopologyReqs, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
|
|
||||||
topologyReqs = append(topologyReqs, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(deprecatedTopologyReqs) > 0 {
|
|
||||||
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
|
||||||
MatchExpressions: deprecatedTopologyReqs,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(topologyReqs) > 0 {
|
|
||||||
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
|
||||||
MatchExpressions: topologyReqs,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodeSelectorTerms
|
|
||||||
}
|
|
||||||
|
|
||||||
// TranslateZoneLabelsToNodeSelectorTerms translates the set of provided labels as []v1.NodeSelectorTerms.
|
|
||||||
// For zone topologies, a node can have either only the beta label (failure-domain.beta.kubernetes.io/zone)
|
|
||||||
// or both the beta and GA label (topology.kubernetes.io/zone). We have to put each topology label into
|
|
||||||
// separate node selector terms so PVs can be scheduled on nodes with either one or both labels
|
|
||||||
func TranslateZoneLabelsToNodeSelectorTerms(labels map[string]string) ([]v1.NodeSelectorTerm, error) {
|
|
||||||
nodeSelectorTerms := make([]v1.NodeSelectorTerm, 0)
|
|
||||||
deprecatedTopologyReqs := make([]v1.NodeSelectorRequirement, 0)
|
|
||||||
topologyReqs := make([]v1.NodeSelectorRequirement, 0)
|
|
||||||
|
|
||||||
if len(labels) == 0 {
|
|
||||||
return nodeSelectorTerms, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range labels {
|
|
||||||
var values []string
|
|
||||||
if k == v1.LabelZoneFailureDomain {
|
|
||||||
values, err := LabelZonesToList(v)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to convert label string for Zone: %s to a List: %v", v, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
deprecatedTopologyReqs = append(deprecatedTopologyReqs, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: values})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if k == v1.LabelZoneFailureDomainStable {
|
|
||||||
values, err := LabelZonesToList(v)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to convert label string for Zone: %s to a List: %v", v, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
topologyReqs = append(topologyReqs, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: values})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// remaining labels outside known topology labels get added to both beta and GA node selectors
|
|
||||||
values = []string{v}
|
|
||||||
deprecatedTopologyReqs = append(deprecatedTopologyReqs, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: values})
|
|
||||||
topologyReqs = append(topologyReqs, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: values})
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(deprecatedTopologyReqs) > 0 {
|
|
||||||
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
|
||||||
MatchExpressions: deprecatedTopologyReqs,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(topologyReqs) > 0 {
|
|
||||||
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
|
||||||
MatchExpressions: topologyReqs,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodeSelectorTerms, nil
|
|
||||||
}
|
|
||||||
|
@ -17,10 +17,7 @@ limitations under the License.
|
|||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
"reflect"
|
|
||||||
"sort"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
@ -420,7 +417,7 @@ func TestChooseZonesForVolume(t *testing.T) {
|
|||||||
func TestSelectZoneForVolume(t *testing.T) {
|
func TestSelectZoneForVolume(t *testing.T) {
|
||||||
|
|
||||||
nodeWithZoneLabels := &v1.Node{}
|
nodeWithZoneLabels := &v1.Node{}
|
||||||
nodeWithZoneLabels.Labels = map[string]string{v1.LabelZoneFailureDomain: "zoneX", v1.LabelZoneFailureDomainStable: "zoneX"}
|
nodeWithZoneLabels.Labels = map[string]string{v1.LabelZoneFailureDomain: "zoneX"}
|
||||||
|
|
||||||
nodeWithNoLabels := &v1.Node{}
|
nodeWithNoLabels := &v1.Node{}
|
||||||
|
|
||||||
@ -661,10 +658,6 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||||||
Key: v1.LabelZoneFailureDomain,
|
Key: v1.LabelZoneFailureDomain,
|
||||||
Values: []string{"zoneX", "zoneY"},
|
Values: []string{"zoneX", "zoneY"},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Values: []string{"zoneX", "zoneY"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -696,22 +689,6 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Values: []string{"zoneX"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Values: []string{"zoneY"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Reject: false,
|
Reject: false,
|
||||||
ExpectedZones: "zoneX,zoneY",
|
ExpectedZones: "zoneX,zoneY",
|
||||||
@ -1133,7 +1110,7 @@ func TestSelectZonesForVolume(t *testing.T) {
|
|||||||
// Select zones from node label and AllowedTopologies [Pass]
|
// Select zones from node label and AllowedTopologies [Pass]
|
||||||
// [1] Node with zone labels
|
// [1] Node with zone labels
|
||||||
// [2] no Zone/Zones parameters
|
// [2] no Zone/Zones parameters
|
||||||
// [3] AllowedTopologies with single term with multiple values specified, both beta and GA zone labels
|
// [3] AllowedTopologies with single term with multiple values specified
|
||||||
// [4] ReplicaCount specified
|
// [4] ReplicaCount specified
|
||||||
// [5] ZonesWithNodes irrelevant
|
// [5] ZonesWithNodes irrelevant
|
||||||
// Note: the test Name suffix is used as the pvcname and it's suffix is important to influence ChooseZonesForVolume
|
// Note: the test Name suffix is used as the pvcname and it's suffix is important to influence ChooseZonesForVolume
|
||||||
@ -1149,10 +1126,6 @@ func TestSelectZonesForVolume(t *testing.T) {
|
|||||||
Key: v1.LabelZoneFailureDomain,
|
Key: v1.LabelZoneFailureDomain,
|
||||||
Values: []string{"zoneV", "zoneW", "zoneX", "zoneY", "zoneZ"},
|
Values: []string{"zoneV", "zoneW", "zoneX", "zoneY", "zoneZ"},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Values: []string{"zoneV", "zoneW", "zoneX", "zoneY", "zoneZ"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1165,35 +1138,7 @@ func TestSelectZonesForVolume(t *testing.T) {
|
|||||||
// Select zones from node label and AllowedTopologies [Pass]
|
// Select zones from node label and AllowedTopologies [Pass]
|
||||||
// [1] Node with zone labels
|
// [1] Node with zone labels
|
||||||
// [2] no Zone/Zones parameters
|
// [2] no Zone/Zones parameters
|
||||||
// [3] AllowedTopologies with single term with multiple values specified, only GA zone labels
|
// [3] AllowedTopologies with single term with multiple values specified
|
||||||
// [4] ReplicaCount specified
|
|
||||||
// [5] ZonesWithNodes irrelevant
|
|
||||||
// Note: the test Name suffix is used as the pvcname and it's suffix is important to influence ChooseZonesForVolume
|
|
||||||
// to NOT pick zoneX from AllowedTopologies if zoneFromNode is incorrectly set or not set at all.
|
|
||||||
{
|
|
||||||
Name: "Node_with_Zone_labels_and_Multiple_Allowed_Topology_values_Superset-1",
|
|
||||||
Node: nodeWithZoneLabels,
|
|
||||||
ReplicaCount: 2,
|
|
||||||
AllowedTopologies: []v1.TopologySelectorTerm{
|
|
||||||
{
|
|
||||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Values: []string{"zoneV", "zoneW", "zoneX", "zoneY", "zoneZ"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Reject: false,
|
|
||||||
ExpectSpecificZone: true,
|
|
||||||
ExpectedZone: "zoneX",
|
|
||||||
ExpectedZones: "zoneV,zoneW,zoneX,zoneY,zoneZ",
|
|
||||||
},
|
|
||||||
|
|
||||||
// Select zones from node label and AllowedTopologies [Pass]
|
|
||||||
// [1] Node with zone labels
|
|
||||||
// [2] no Zone/Zones parameters
|
|
||||||
// [3] AllowedTopologies with single term with multiple values specified, has both beta/GA zone labels
|
|
||||||
// [4] ReplicaCount specified
|
// [4] ReplicaCount specified
|
||||||
// [5] ZonesWithNodes irrelevant
|
// [5] ZonesWithNodes irrelevant
|
||||||
{
|
{
|
||||||
@ -1207,10 +1152,6 @@ func TestSelectZonesForVolume(t *testing.T) {
|
|||||||
Key: v1.LabelZoneFailureDomain,
|
Key: v1.LabelZoneFailureDomain,
|
||||||
Values: []string{"zoneX", "zoneY"},
|
Values: []string{"zoneX", "zoneY"},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Values: []string{"zoneX", "zoneY"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1334,7 +1275,7 @@ func TestSelectZonesForVolume(t *testing.T) {
|
|||||||
// Select zones from node label and AllowedTopologies [Pass]
|
// Select zones from node label and AllowedTopologies [Pass]
|
||||||
// [1] Node with zone labels
|
// [1] Node with zone labels
|
||||||
// [2] no Zone/Zones parametes specified
|
// [2] no Zone/Zones parametes specified
|
||||||
// [3] AllowedTopologies with multiple terms specified, has both beta/GA zone labels
|
// [3] AllowedTopologies with multiple terms specified
|
||||||
// [4] ReplicaCount specified
|
// [4] ReplicaCount specified
|
||||||
// [5] ZonesWithNodes irrelevant
|
// [5] ZonesWithNodes irrelevant
|
||||||
{
|
{
|
||||||
@ -1358,22 +1299,6 @@ func TestSelectZonesForVolume(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Values: []string{"zoneX"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Values: []string{"zoneY"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Reject: false,
|
Reject: false,
|
||||||
ExpectSpecificZone: true,
|
ExpectSpecificZone: true,
|
||||||
@ -1712,396 +1637,3 @@ func checkFnv32(t *testing.T, s string, expected uint32) {
|
|||||||
t.Fatalf("hash of %q was %v, expected %v", s, h.Sum32(), expected)
|
t.Fatalf("hash of %q was %v, expected %v", s, h.Sum32(), expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_TranslateZoneRegionLabelsToNodeSelectorTerms(t *testing.T) {
|
|
||||||
testcases := []struct {
|
|
||||||
name string
|
|
||||||
labels map[string]string
|
|
||||||
nodeSelectorTerm []v1.NodeSelectorTerm
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "empty label set",
|
|
||||||
labels: map[string]string{},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "nil label set",
|
|
||||||
labels: nil,
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with beta zone labels",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1",
|
|
||||||
},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with beta and stable zone labels",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1",
|
|
||||||
v1.LabelZoneFailureDomainStable: "zone1",
|
|
||||||
},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with beta zone and region labels",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1",
|
|
||||||
v1.LabelZoneRegion: "region1",
|
|
||||||
},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegion,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with stable zone and region labels",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1",
|
|
||||||
v1.LabelZoneRegion: "region1",
|
|
||||||
},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegion,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with beta/stable and zone/region labels",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1",
|
|
||||||
v1.LabelZoneFailureDomainStable: "zone1",
|
|
||||||
v1.LabelZoneRegion: "region1",
|
|
||||||
v1.LabelZoneRegionStable: "region1",
|
|
||||||
},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegion,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegionStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with beta/stable and zone/region and other labels",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1",
|
|
||||||
v1.LabelZoneFailureDomainStable: "zone1",
|
|
||||||
v1.LabelZoneRegion: "region1",
|
|
||||||
v1.LabelZoneRegionStable: "region1",
|
|
||||||
"hello": "world",
|
|
||||||
},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegion,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "hello",
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"world"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneRegionStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"region1"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "hello",
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"world"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testcase := range testcases {
|
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
|
||||||
nodeSelectorTerm := TranslateZoneRegionLabelsToNodeSelectorTerms(testcase.labels)
|
|
||||||
sortNodeSelectorTerm(nodeSelectorTerm)
|
|
||||||
sortNodeSelectorTerm(testcase.nodeSelectorTerm)
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(nodeSelectorTerm, testcase.nodeSelectorTerm) {
|
|
||||||
t.Logf("actual node selector term: %v", nodeSelectorTerm)
|
|
||||||
t.Logf("expected node selector term: %v", testcase.nodeSelectorTerm)
|
|
||||||
t.Error("unexpected node selector term")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_TranslateZoneLabelsToNodeSelectorTerms(t *testing.T) {
|
|
||||||
testcases := []struct {
|
|
||||||
name string
|
|
||||||
labels map[string]string
|
|
||||||
nodeSelectorTerm []v1.NodeSelectorTerm
|
|
||||||
expectedErr error
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "empty label set",
|
|
||||||
labels: map[string]string{},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "nil label set",
|
|
||||||
labels: nil,
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with beta zone labels",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1",
|
|
||||||
},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with beta multi-zone labels",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1__zone2",
|
|
||||||
},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1", "zone2"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with beta and stable zone labels",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1",
|
|
||||||
v1.LabelZoneFailureDomainStable: "zone1",
|
|
||||||
},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with beta and stable multi-zone labels",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1__zone2",
|
|
||||||
v1.LabelZoneFailureDomainStable: "zone1__zone2",
|
|
||||||
},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1", "zone2"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1", "zone2"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with beta/stable zones and others",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1__zone2",
|
|
||||||
v1.LabelZoneFailureDomainStable: "zone1__zone2",
|
|
||||||
"hello": "world",
|
|
||||||
},
|
|
||||||
nodeSelectorTerm: []v1.NodeSelectorTerm{
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomain,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1", "zone2"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "hello",
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"world"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
|
||||||
{
|
|
||||||
Key: v1.LabelZoneFailureDomainStable,
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"zone1", "zone2"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Key: "hello",
|
|
||||||
Operator: v1.NodeSelectorOpIn,
|
|
||||||
Values: []string{"world"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "with invalid zone value",
|
|
||||||
labels: map[string]string{
|
|
||||||
v1.LabelZoneFailureDomain: "zone1__",
|
|
||||||
},
|
|
||||||
expectedErr: fmt.Errorf("failed to convert label string for Zone: zone1__ to a List: %q separated list (%q) must not contain an empty string", "__", "zone1__"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testcase := range testcases {
|
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
|
||||||
nodeSelectorTerm, err := TranslateZoneLabelsToNodeSelectorTerms(testcase.labels)
|
|
||||||
if !reflect.DeepEqual(err, testcase.expectedErr) {
|
|
||||||
t.Logf("actual err: %v", err)
|
|
||||||
t.Logf("expected err: %v", testcase.expectedErr)
|
|
||||||
t.Fatal("unexpected error")
|
|
||||||
}
|
|
||||||
|
|
||||||
sortNodeSelectorTerm(nodeSelectorTerm)
|
|
||||||
sortNodeSelectorTerm(testcase.nodeSelectorTerm)
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(nodeSelectorTerm, testcase.nodeSelectorTerm) {
|
|
||||||
t.Logf("actual node selector term: %v", nodeSelectorTerm)
|
|
||||||
t.Logf("expected node selector term: %v", testcase.nodeSelectorTerm)
|
|
||||||
t.Error("unexpected node selector term")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func sortNodeSelectorTerm(nodeSelectorTerms []v1.NodeSelectorTerm) {
|
|
||||||
for _, nodeSelectorTerm := range nodeSelectorTerms {
|
|
||||||
sort.Slice(nodeSelectorTerm.MatchExpressions, func(i, j int) bool {
|
|
||||||
return nodeSelectorTerm.MatchExpressions[i].Key < nodeSelectorTerm.MatchExpressions[j].Key
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -73,16 +73,13 @@ func translateAllowedTopologies(terms []v1.TopologySelectorTerm) ([]v1.TopologyS
|
|||||||
newTopologies := []v1.TopologySelectorTerm{}
|
newTopologies := []v1.TopologySelectorTerm{}
|
||||||
for _, term := range terms {
|
for _, term := range terms {
|
||||||
newTerm := v1.TopologySelectorTerm{}
|
newTerm := v1.TopologySelectorTerm{}
|
||||||
zoneFound := false
|
|
||||||
for _, exp := range term.MatchLabelExpressions {
|
for _, exp := range term.MatchLabelExpressions {
|
||||||
var newExp v1.TopologySelectorLabelRequirement
|
var newExp v1.TopologySelectorLabelRequirement
|
||||||
if !zoneFound && (exp.Key == v1.LabelZoneFailureDomain || exp.Key == v1.LabelZoneFailureDomainStable) {
|
if exp.Key == v1.LabelZoneFailureDomain {
|
||||||
newExp = v1.TopologySelectorLabelRequirement{
|
newExp = v1.TopologySelectorLabelRequirement{
|
||||||
Key: GCEPDTopologyKey,
|
Key: GCEPDTopologyKey,
|
||||||
Values: exp.Values,
|
Values: exp.Values,
|
||||||
}
|
}
|
||||||
|
|
||||||
zoneFound = true
|
|
||||||
} else if exp.Key == GCEPDTopologyKey {
|
} else if exp.Key == GCEPDTopologyKey {
|
||||||
newExp = exp
|
newExp = exp
|
||||||
} else {
|
} else {
|
||||||
@ -243,11 +240,7 @@ func (g *gcePersistentDiskCSITranslator) TranslateInTreePVToCSI(pv *v1.Persisten
|
|||||||
return nil, fmt.Errorf("pv is nil or GCE Persistent Disk source not defined on pv")
|
return nil, fmt.Errorf("pv is nil or GCE Persistent Disk source not defined on pv")
|
||||||
}
|
}
|
||||||
|
|
||||||
zonesLabel, ok := pv.Labels[v1.LabelZoneFailureDomain]
|
zonesLabel := pv.Labels[v1.LabelZoneFailureDomain]
|
||||||
if !ok {
|
|
||||||
zonesLabel = pv.Labels[v1.LabelZoneFailureDomainStable]
|
|
||||||
}
|
|
||||||
|
|
||||||
zones := strings.Split(zonesLabel, cloudvolume.LabelMultiZoneDelimiter)
|
zones := strings.Split(zonesLabel, cloudvolume.LabelMultiZoneDelimiter)
|
||||||
if len(zones) == 1 && len(zones[0]) != 0 {
|
if len(zones) == 1 && len(zones[0]) != 0 {
|
||||||
// Zonal
|
// Zonal
|
||||||
|
@ -71,14 +71,9 @@ func TestTranslatePDInTreeStorageClassToCSI(t *testing.T) {
|
|||||||
options: NewStorageClass(map[string]string{}, generateToplogySelectors(GCEPDTopologyKey, []string{"foo"})),
|
options: NewStorageClass(map[string]string{}, generateToplogySelectors(GCEPDTopologyKey, []string{"foo"})),
|
||||||
expOptions: NewStorageClass(map[string]string{}, generateToplogySelectors(GCEPDTopologyKey, []string{"foo"})),
|
expOptions: NewStorageClass(map[string]string{}, generateToplogySelectors(GCEPDTopologyKey, []string{"foo"})),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "some translated topology using deprecated zone label",
|
|
||||||
options: NewStorageClass(map[string]string{}, generateToplogySelectors(v1.LabelZoneFailureDomain, []string{"foo"})),
|
|
||||||
expOptions: NewStorageClass(map[string]string{}, generateToplogySelectors(GCEPDTopologyKey, []string{"foo"})),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "some translated topology",
|
name: "some translated topology",
|
||||||
options: NewStorageClass(map[string]string{}, generateToplogySelectors(v1.LabelZoneFailureDomainStable, []string{"foo"})),
|
options: NewStorageClass(map[string]string{}, generateToplogySelectors(v1.LabelZoneFailureDomain, []string{"foo"})),
|
||||||
expOptions: NewStorageClass(map[string]string{}, generateToplogySelectors(GCEPDTopologyKey, []string{"foo"})),
|
expOptions: NewStorageClass(map[string]string{}, generateToplogySelectors(GCEPDTopologyKey, []string{"foo"})),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2639,15 +2639,11 @@ func (c *Cloud) GetVolumeLabels(volumeName KubernetesVolumeID) (map[string]strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
labels[v1.LabelZoneFailureDomain] = az
|
labels[v1.LabelZoneFailureDomain] = az
|
||||||
labels[v1.LabelZoneFailureDomainStable] = az
|
|
||||||
|
|
||||||
region, err := azToRegion(az)
|
region, err := azToRegion(az)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
labels[v1.LabelZoneRegion] = region
|
labels[v1.LabelZoneRegion] = region
|
||||||
labels[v1.LabelZoneRegionStable] = region
|
|
||||||
|
|
||||||
return labels, nil
|
return labels, nil
|
||||||
}
|
}
|
||||||
|
@ -1262,11 +1262,8 @@ func TestGetVolumeLabels(t *testing.T) {
|
|||||||
|
|
||||||
assert.Nil(t, err, "Error creating Volume %v", err)
|
assert.Nil(t, err, "Error creating Volume %v", err)
|
||||||
assert.Equal(t, map[string]string{
|
assert.Equal(t, map[string]string{
|
||||||
v1.LabelZoneFailureDomain: "us-east-1a",
|
v1.LabelZoneFailureDomain: "us-east-1a",
|
||||||
v1.LabelZoneRegion: "us-east-1",
|
v1.LabelZoneRegion: "us-east-1"}, labels)
|
||||||
v1.LabelZoneFailureDomainStable: "us-east-1a",
|
|
||||||
v1.LabelZoneRegionStable: "us-east-1",
|
|
||||||
}, labels)
|
|
||||||
awsServices.ec2.(*MockedFakeEC2).AssertExpectations(t)
|
awsServices.ec2.(*MockedFakeEC2).AssertExpectations(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1339,10 +1336,8 @@ func TestGetLabelsForVolume(t *testing.T) {
|
|||||||
AvailabilityZone: aws.String("us-east-1a"),
|
AvailabilityZone: aws.String("us-east-1a"),
|
||||||
}},
|
}},
|
||||||
map[string]string{
|
map[string]string{
|
||||||
v1.LabelZoneFailureDomain: "us-east-1a",
|
v1.LabelZoneFailureDomain: "us-east-1a",
|
||||||
v1.LabelZoneRegion: "us-east-1",
|
v1.LabelZoneRegion: "us-east-1",
|
||||||
v1.LabelZoneFailureDomainStable: "us-east-1a",
|
|
||||||
v1.LabelZoneRegionStable: "us-east-1",
|
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
@ -636,9 +636,7 @@ func (az *Cloud) SetInformers(informerFactory informers.SharedInformerFactory) {
|
|||||||
prevNode := prev.(*v1.Node)
|
prevNode := prev.(*v1.Node)
|
||||||
newNode := obj.(*v1.Node)
|
newNode := obj.(*v1.Node)
|
||||||
if newNode.Labels[v1.LabelZoneFailureDomain] ==
|
if newNode.Labels[v1.LabelZoneFailureDomain] ==
|
||||||
prevNode.Labels[v1.LabelZoneFailureDomain] &&
|
prevNode.Labels[v1.LabelZoneFailureDomain] {
|
||||||
newNode.Labels[v1.LabelZoneFailureDomainStable] ==
|
|
||||||
prevNode.Labels[v1.LabelZoneFailureDomainStable] {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
az.updateNodeCaches(prevNode, newNode)
|
az.updateNodeCaches(prevNode, newNode)
|
||||||
@ -673,10 +671,6 @@ func (az *Cloud) updateNodeCaches(prevNode, newNode *v1.Node) {
|
|||||||
if prevNode != nil {
|
if prevNode != nil {
|
||||||
// Remove from nodeZones cache.
|
// Remove from nodeZones cache.
|
||||||
prevZone, ok := prevNode.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
|
prevZone, ok := prevNode.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
|
||||||
if !ok {
|
|
||||||
prevZone, ok = prevNode.ObjectMeta.Labels[v1.LabelZoneFailureDomainStable]
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok && az.isAvailabilityZone(prevZone) {
|
if ok && az.isAvailabilityZone(prevZone) {
|
||||||
az.nodeZones[prevZone].Delete(prevNode.ObjectMeta.Name)
|
az.nodeZones[prevZone].Delete(prevNode.ObjectMeta.Name)
|
||||||
if az.nodeZones[prevZone].Len() == 0 {
|
if az.nodeZones[prevZone].Len() == 0 {
|
||||||
@ -700,10 +694,6 @@ func (az *Cloud) updateNodeCaches(prevNode, newNode *v1.Node) {
|
|||||||
if newNode != nil {
|
if newNode != nil {
|
||||||
// Add to nodeZones cache.
|
// Add to nodeZones cache.
|
||||||
newZone, ok := newNode.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
|
newZone, ok := newNode.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
|
||||||
if !ok {
|
|
||||||
newZone, ok = newNode.ObjectMeta.Labels[v1.LabelZoneFailureDomainStable]
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok && az.isAvailabilityZone(newZone) {
|
if ok && az.isAvailabilityZone(newZone) {
|
||||||
if az.nodeZones[newZone] == nil {
|
if az.nodeZones[newZone] == nil {
|
||||||
az.nodeZones[newZone] = sets.NewString()
|
az.nodeZones[newZone] = sets.NewString()
|
||||||
|
@ -333,10 +333,8 @@ func (c *Cloud) GetAzureDiskLabels(diskURI string) (map[string]string, error) {
|
|||||||
zone := c.makeZone(c.Location, zoneID)
|
zone := c.makeZone(c.Location, zoneID)
|
||||||
klog.V(4).Infof("Got zone %q for Azure disk %q", zone, diskName)
|
klog.V(4).Infof("Got zone %q for Azure disk %q", zone, diskName)
|
||||||
labels := map[string]string{
|
labels := map[string]string{
|
||||||
v1.LabelZoneRegion: c.Location,
|
v1.LabelZoneRegion: c.Location,
|
||||||
v1.LabelZoneFailureDomain: zone,
|
v1.LabelZoneFailureDomain: zone,
|
||||||
v1.LabelZoneRegionStable: c.Location,
|
|
||||||
v1.LabelZoneFailureDomainStable: zone,
|
|
||||||
}
|
}
|
||||||
return labels, nil
|
return labels, nil
|
||||||
}
|
}
|
||||||
|
@ -694,9 +694,7 @@ func (g *Cloud) SetInformers(informerFactory informers.SharedInformerFactory) {
|
|||||||
prevNode := prev.(*v1.Node)
|
prevNode := prev.(*v1.Node)
|
||||||
newNode := obj.(*v1.Node)
|
newNode := obj.(*v1.Node)
|
||||||
if newNode.Labels[v1.LabelZoneFailureDomain] ==
|
if newNode.Labels[v1.LabelZoneFailureDomain] ==
|
||||||
prevNode.Labels[v1.LabelZoneFailureDomain] &&
|
prevNode.Labels[v1.LabelZoneFailureDomain] {
|
||||||
newNode.Labels[v1.LabelZoneFailureDomainStable] ==
|
|
||||||
prevNode.Labels[v1.LabelZoneFailureDomainStable] {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.updateNodeZones(prevNode, newNode)
|
g.updateNodeZones(prevNode, newNode)
|
||||||
@ -728,10 +726,6 @@ func (g *Cloud) updateNodeZones(prevNode, newNode *v1.Node) {
|
|||||||
defer g.nodeZonesLock.Unlock()
|
defer g.nodeZonesLock.Unlock()
|
||||||
if prevNode != nil {
|
if prevNode != nil {
|
||||||
prevZone, ok := prevNode.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
|
prevZone, ok := prevNode.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
|
||||||
if !ok {
|
|
||||||
prevZone, ok = prevNode.ObjectMeta.Labels[v1.LabelZoneFailureDomainStable]
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
g.nodeZones[prevZone].Delete(prevNode.ObjectMeta.Name)
|
g.nodeZones[prevZone].Delete(prevNode.ObjectMeta.Name)
|
||||||
if g.nodeZones[prevZone].Len() == 0 {
|
if g.nodeZones[prevZone].Len() == 0 {
|
||||||
@ -741,10 +735,6 @@ func (g *Cloud) updateNodeZones(prevNode, newNode *v1.Node) {
|
|||||||
}
|
}
|
||||||
if newNode != nil {
|
if newNode != nil {
|
||||||
newZone, ok := newNode.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
|
newZone, ok := newNode.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
|
||||||
if !ok {
|
|
||||||
newZone, ok = newNode.ObjectMeta.Labels[v1.LabelZoneFailureDomainStable]
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
if g.nodeZones[newZone] == nil {
|
if g.nodeZones[newZone] == nil {
|
||||||
g.nodeZones[newZone] = sets.NewString()
|
g.nodeZones[newZone] = sets.NewString()
|
||||||
|
@ -499,10 +499,7 @@ func (g *Cloud) GetLabelsForVolume(ctx context.Context, pv *v1.PersistentVolume)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the zone is already labeled, honor the hint
|
// If the zone is already labeled, honor the hint
|
||||||
zone, ok := pv.Labels[v1.LabelZoneFailureDomain]
|
zone := pv.Labels[v1.LabelZoneFailureDomain]
|
||||||
if !ok {
|
|
||||||
zone = pv.Labels[v1.LabelZoneFailureDomainStable]
|
|
||||||
}
|
|
||||||
|
|
||||||
labels, err := g.GetAutoLabelsForPD(pv.Spec.GCEPersistentDisk.PDName, zone)
|
labels, err := g.GetAutoLabelsForPD(pv.Spec.GCEPersistentDisk.PDName, zone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -859,8 +856,6 @@ func (g *Cloud) GetAutoLabelsForPD(name string, zone string) (map[string]string,
|
|||||||
}
|
}
|
||||||
labels[v1.LabelZoneFailureDomain] = zoneInfo.zone
|
labels[v1.LabelZoneFailureDomain] = zoneInfo.zone
|
||||||
labels[v1.LabelZoneRegion] = disk.Region
|
labels[v1.LabelZoneRegion] = disk.Region
|
||||||
labels[v1.LabelZoneFailureDomainStable] = zoneInfo.zone
|
|
||||||
labels[v1.LabelZoneRegionStable] = disk.Region
|
|
||||||
case multiZone:
|
case multiZone:
|
||||||
if zoneInfo.replicaZones == nil || zoneInfo.replicaZones.Len() <= 0 {
|
if zoneInfo.replicaZones == nil || zoneInfo.replicaZones.Len() <= 0 {
|
||||||
// Unexpected, but sanity-check
|
// Unexpected, but sanity-check
|
||||||
@ -869,9 +864,6 @@ func (g *Cloud) GetAutoLabelsForPD(name string, zone string) (map[string]string,
|
|||||||
labels[v1.LabelZoneFailureDomain] =
|
labels[v1.LabelZoneFailureDomain] =
|
||||||
volumehelpers.ZonesSetToLabelValue(zoneInfo.replicaZones)
|
volumehelpers.ZonesSetToLabelValue(zoneInfo.replicaZones)
|
||||||
labels[v1.LabelZoneRegion] = disk.Region
|
labels[v1.LabelZoneRegion] = disk.Region
|
||||||
labels[v1.LabelZoneFailureDomainStable] =
|
|
||||||
volumehelpers.ZonesSetToLabelValue(zoneInfo.replicaZones)
|
|
||||||
labels[v1.LabelZoneRegionStable] = disk.Region
|
|
||||||
case nil:
|
case nil:
|
||||||
// Unexpected, but sanity-check
|
// Unexpected, but sanity-check
|
||||||
return nil, fmt.Errorf("PD did not have ZoneInfo: %v", disk)
|
return nil, fmt.Errorf("PD did not have ZoneInfo: %v", disk)
|
||||||
|
@ -465,23 +465,13 @@ func TestGetAutoLabelsForPD_Basic(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if labels[v1.LabelZoneFailureDomain] != zone {
|
if labels[v1.LabelZoneFailureDomain] != zone {
|
||||||
t.Errorf("Failure domain is '%v', but zone is '%v'",
|
t.Errorf("Failure domain is '%v', but zone is '%v'",
|
||||||
labels[v1.LabelZoneFailureDomain], zone)
|
labels[v1.LabelZoneFailureDomain], zone)
|
||||||
}
|
}
|
||||||
|
|
||||||
if labels[v1.LabelZoneRegion] != gceRegion {
|
if labels[v1.LabelZoneRegion] != gceRegion {
|
||||||
t.Errorf("Region is '%v', but region is 'us-central1'", labels[v1.LabelZoneRegion])
|
t.Errorf("Region is '%v', but region is 'us-central1'", labels[v1.LabelZoneRegion])
|
||||||
}
|
}
|
||||||
|
|
||||||
if labels[v1.LabelZoneFailureDomainStable] != zone {
|
|
||||||
t.Errorf("Failure domain is '%v', but zone is '%v'",
|
|
||||||
labels[v1.LabelZoneFailureDomainStable], zone)
|
|
||||||
}
|
|
||||||
if labels[v1.LabelZoneRegionStable] != gceRegion {
|
|
||||||
t.Errorf("Region is '%v', but region is 'us-central1'", labels[v1.LabelZoneRegionStable])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAutoLabelsForPD_NoZone(t *testing.T) {
|
func TestGetAutoLabelsForPD_NoZone(t *testing.T) {
|
||||||
@ -518,14 +508,6 @@ func TestGetAutoLabelsForPD_NoZone(t *testing.T) {
|
|||||||
if labels[v1.LabelZoneRegion] != gceRegion {
|
if labels[v1.LabelZoneRegion] != gceRegion {
|
||||||
t.Errorf("Region is '%v', but region is 'europe-west1'", labels[v1.LabelZoneRegion])
|
t.Errorf("Region is '%v', but region is 'europe-west1'", labels[v1.LabelZoneRegion])
|
||||||
}
|
}
|
||||||
|
|
||||||
if labels[v1.LabelZoneFailureDomainStable] != zone {
|
|
||||||
t.Errorf("Failure domain is '%v', but zone is '%v'",
|
|
||||||
labels[v1.LabelZoneFailureDomainStable], zone)
|
|
||||||
}
|
|
||||||
if labels[v1.LabelZoneRegionStable] != gceRegion {
|
|
||||||
t.Errorf("Region is '%v', but region is 'europe-west1'", labels[v1.LabelZoneRegionStable])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAutoLabelsForPD_DiskNotFound(t *testing.T) {
|
func TestGetAutoLabelsForPD_DiskNotFound(t *testing.T) {
|
||||||
@ -612,14 +594,6 @@ func TestGetAutoLabelsForPD_DupDisk(t *testing.T) {
|
|||||||
if labels[v1.LabelZoneRegion] != gceRegion {
|
if labels[v1.LabelZoneRegion] != gceRegion {
|
||||||
t.Errorf("Region is '%v', but region is 'us-west1'", labels[v1.LabelZoneRegion])
|
t.Errorf("Region is '%v', but region is 'us-west1'", labels[v1.LabelZoneRegion])
|
||||||
}
|
}
|
||||||
|
|
||||||
if labels[v1.LabelZoneFailureDomainStable] != zone {
|
|
||||||
t.Errorf("Failure domain is '%v', but zone is '%v'",
|
|
||||||
labels[v1.LabelZoneFailureDomainStable], zone)
|
|
||||||
}
|
|
||||||
if labels[v1.LabelZoneRegionStable] != gceRegion {
|
|
||||||
t.Errorf("Region is '%v', but region is 'us-west1'", labels[v1.LabelZoneRegionStable])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAutoLabelsForPD_DupDiskNoZone(t *testing.T) {
|
func TestGetAutoLabelsForPD_DupDiskNoZone(t *testing.T) {
|
||||||
|
@ -60,20 +60,12 @@ func splitNodesByZone(nodes []*v1.Node) map[string][]*v1.Node {
|
|||||||
return zones
|
return zones
|
||||||
}
|
}
|
||||||
|
|
||||||
// getZone checks the deprecated beta zone label first and falls back to GA label if the beta label does not exist
|
|
||||||
// if both don't exist, returns the default zone which is ""
|
|
||||||
func getZone(n *v1.Node) string {
|
func getZone(n *v1.Node) string {
|
||||||
zone, ok := n.Labels[v1.LabelZoneFailureDomain]
|
zone, ok := n.Labels[v1.LabelZoneFailureDomain]
|
||||||
if ok {
|
if !ok {
|
||||||
return zone
|
return defaultZone
|
||||||
}
|
}
|
||||||
|
return zone
|
||||||
zone, ok = n.Labels[v1.LabelZoneFailureDomainStable]
|
|
||||||
if ok {
|
|
||||||
return zone
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultZone
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeHostURL(projectsAPIEndpoint, projectID, zone, host string) string {
|
func makeHostURL(projectsAPIEndpoint, projectID, zone, host string) string {
|
||||||
|
@ -736,8 +736,6 @@ func (os *OpenStack) GetLabelsForVolume(ctx context.Context, pv *v1.PersistentVo
|
|||||||
labels := make(map[string]string)
|
labels := make(map[string]string)
|
||||||
labels[v1.LabelZoneFailureDomain] = volume.AvailabilityZone
|
labels[v1.LabelZoneFailureDomain] = volume.AvailabilityZone
|
||||||
labels[v1.LabelZoneRegion] = os.region
|
labels[v1.LabelZoneRegion] = os.region
|
||||||
labels[v1.LabelZoneFailureDomainStable] = volume.AvailabilityZone
|
|
||||||
labels[v1.LabelZoneRegionStable] = os.region
|
|
||||||
klog.V(4).Infof("The Volume %s has labels %v", pv.Spec.Cinder.VolumeID, labels)
|
klog.V(4).Infof("The Volume %s has labels %v", pv.Spec.Cinder.VolumeID, labels)
|
||||||
|
|
||||||
return labels, nil
|
return labels, nil
|
||||||
|
@ -203,8 +203,8 @@ func (nm *NodeManager) DiscoverNode(node *v1.Node) error {
|
|||||||
node.Name, vm, res.vc, res.datacenter.Name())
|
node.Name, vm, res.vc, res.datacenter.Name())
|
||||||
|
|
||||||
// Get the node zone information
|
// Get the node zone information
|
||||||
nodeFd := getNodeZoneFailureDomain(node)
|
nodeFd := node.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
|
||||||
nodeRegion := getNodeRegion(node)
|
nodeRegion := node.ObjectMeta.Labels[v1.LabelZoneRegion]
|
||||||
nodeZone := &cloudprovider.Zone{FailureDomain: nodeFd, Region: nodeRegion}
|
nodeZone := &cloudprovider.Zone{FailureDomain: nodeFd, Region: nodeRegion}
|
||||||
nodeInfo := &NodeInfo{dataCenter: res.datacenter, vm: vm, vcServer: res.vc, vmUUID: nodeUUID, zone: nodeZone}
|
nodeInfo := &NodeInfo{dataCenter: res.datacenter, vm: vm, vcServer: res.vc, vmUUID: nodeUUID, zone: nodeZone}
|
||||||
nm.addNodeInfo(node.ObjectMeta.Name, nodeInfo)
|
nm.addNodeInfo(node.ObjectMeta.Name, nodeInfo)
|
||||||
@ -230,34 +230,6 @@ func (nm *NodeManager) DiscoverNode(node *v1.Node) error {
|
|||||||
return vclib.ErrNoVMFound
|
return vclib.ErrNoVMFound
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNodeZoneFailureDomain(node *v1.Node) string {
|
|
||||||
zone, ok := node.Labels[v1.LabelZoneFailureDomain]
|
|
||||||
if ok {
|
|
||||||
return zone
|
|
||||||
}
|
|
||||||
|
|
||||||
zone, ok = node.Labels[v1.LabelZoneFailureDomainStable]
|
|
||||||
if ok {
|
|
||||||
return zone
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNodeRegion(node *v1.Node) string {
|
|
||||||
region, ok := node.Labels[v1.LabelZoneRegion]
|
|
||||||
if ok {
|
|
||||||
return region
|
|
||||||
}
|
|
||||||
|
|
||||||
region, ok = node.Labels[v1.LabelZoneRegionStable]
|
|
||||||
if ok {
|
|
||||||
return region
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (nm *NodeManager) RegisterNode(node *v1.Node) error {
|
func (nm *NodeManager) RegisterNode(node *v1.Node) error {
|
||||||
nm.addNode(node)
|
nm.addNode(node)
|
||||||
return nm.DiscoverNode(node)
|
return nm.DiscoverNode(node)
|
||||||
|
@ -1649,8 +1649,6 @@ func (vs *VSphere) GetVolumeLabels(volumePath string) (map[string]string, error)
|
|||||||
if len(dsZones) > 0 {
|
if len(dsZones) > 0 {
|
||||||
labels[v1.LabelZoneRegion] = dsZones[0].Region
|
labels[v1.LabelZoneRegion] = dsZones[0].Region
|
||||||
labels[v1.LabelZoneFailureDomain] = dsZones[0].FailureDomain
|
labels[v1.LabelZoneFailureDomain] = dsZones[0].FailureDomain
|
||||||
labels[v1.LabelZoneRegionStable] = dsZones[0].Region
|
|
||||||
labels[v1.LabelZoneFailureDomainStable] = dsZones[0].FailureDomain
|
|
||||||
}
|
}
|
||||||
return labels, nil
|
return labels, nil
|
||||||
}
|
}
|
||||||
|
@ -34,11 +34,19 @@ func RecreateNodes(c clientset.Interface, nodes []v1.Node) error {
|
|||||||
nodeNamesByZone := make(map[string][]string)
|
nodeNamesByZone := make(map[string][]string)
|
||||||
for i := range nodes {
|
for i := range nodes {
|
||||||
node := &nodes[i]
|
node := &nodes[i]
|
||||||
zone := framework.TestContext.CloudConfig.Zone
|
|
||||||
if z, ok := node.Labels[v1.LabelZoneFailureDomain]; ok {
|
if zone, ok := node.Labels[v1.LabelZoneFailureDomain]; ok {
|
||||||
zone = z
|
nodeNamesByZone[zone] = append(nodeNamesByZone[zone], node.Name)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
nodeNamesByZone[zone] = append(nodeNamesByZone[zone], node.Name)
|
|
||||||
|
if zone, ok := node.Labels[v1.LabelZoneFailureDomainStable]; ok {
|
||||||
|
nodeNamesByZone[zone] = append(nodeNamesByZone[zone], node.Name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultZone := framework.TestContext.CloudConfig.Zone
|
||||||
|
nodeNamesByZone[defaultZone] = append(nodeNamesByZone[defaultZone], node.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the sole managed instance group name
|
// Find the sole managed instance group name
|
||||||
|
@ -2587,6 +2587,10 @@ func GetClusterZones(c clientset.Interface) (sets.String, error) {
|
|||||||
if zone, found := node.Labels[v1.LabelZoneFailureDomain]; found {
|
if zone, found := node.Labels[v1.LabelZoneFailureDomain]; found {
|
||||||
zones.Insert(zone)
|
zones.Insert(zone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if zone, found := node.Labels[v1.LabelZoneFailureDomainStable]; found {
|
||||||
|
zones.Insert(zone)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return zones, nil
|
return zones, nil
|
||||||
}
|
}
|
||||||
|
@ -497,7 +497,7 @@ func verifyPVZoneLabels(client clientset.Interface, namespace string, scParamete
|
|||||||
ginkgo.By("Verify zone information is present in the volume labels")
|
ginkgo.By("Verify zone information is present in the volume labels")
|
||||||
for _, pv := range persistentvolumes {
|
for _, pv := range persistentvolumes {
|
||||||
// Multiple zones are separated with "__"
|
// Multiple zones are separated with "__"
|
||||||
pvZoneLabels := strings.Split(pv.ObjectMeta.Labels[v1.LabelZoneFailureDomain], "__")
|
pvZoneLabels := strings.Split(pv.ObjectMeta.Labels["failure-domain.beta.kubernetes.io/zone"], "__")
|
||||||
for _, zone := range zones {
|
for _, zone := range zones {
|
||||||
gomega.Expect(pvZoneLabels).Should(gomega.ContainElement(zone), "Incorrect or missing zone labels in pv.")
|
gomega.Expect(pvZoneLabels).Should(gomega.ContainElement(zone), "Incorrect or missing zone labels in pv.")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user