Remove alpha annotation for volume node affinity

This commit is contained in:
wackxu
2018-03-28 14:45:06 +08:00
parent 15489d09c5
commit 5ed705faf8
8 changed files with 2 additions and 548 deletions

View File

@@ -564,34 +564,4 @@ func PersistentVolumeClaimHasClass(claim *core.PersistentVolumeClaim) bool {
}
return false
}
// GetStorageNodeAffinityFromAnnotation gets the json serialized data from PersistentVolume.Annotations
// and converts it to the NodeAffinity type in core.
// TODO: update when storage node affinity graduates to beta
func GetStorageNodeAffinityFromAnnotation(annotations map[string]string) (*core.NodeAffinity, error) {
if len(annotations) > 0 && annotations[core.AlphaStorageNodeAffinityAnnotation] != "" {
var affinity core.NodeAffinity
err := json.Unmarshal([]byte(annotations[core.AlphaStorageNodeAffinityAnnotation]), &affinity)
if err != nil {
return nil, err
}
return &affinity, nil
}
return nil, nil
}
// Converts NodeAffinity type to Alpha annotation for use in PersistentVolumes
// TODO: update when storage node affinity graduates to beta
func StorageNodeAffinityToAlphaAnnotation(annotations map[string]string, affinity *core.NodeAffinity) error {
if affinity == nil {
return nil
}
json, err := json.Marshal(*affinity)
if err != nil {
return err
}
annotations[core.AlphaStorageNodeAffinityAnnotation] = string(json)
return nil
}
}

View File

@@ -286,93 +286,6 @@ func TestSysctlsFromPodAnnotation(t *testing.T) {
}
}
// TODO: remove when alpha support for topology constraints is removed
func TestGetNodeAffinityFromAnnotations(t *testing.T) {
testCases := []struct {
annotations map[string]string
expectErr bool
}{
{
annotations: nil,
expectErr: false,
},
{
annotations: map[string]string{},
expectErr: false,
},
{
annotations: map[string]string{
core.AlphaStorageNodeAffinityAnnotation: `{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
]}
}`,
},
expectErr: false,
},
{
annotations: map[string]string{
core.AlphaStorageNodeAffinityAnnotation: `[{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
]}
}]`,
},
expectErr: true,
},
{
annotations: map[string]string{
core.AlphaStorageNodeAffinityAnnotation: `{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms":
"matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
}
}`,
},
expectErr: true,
},
}
for i, tc := range testCases {
_, err := GetStorageNodeAffinityFromAnnotation(tc.annotations)
if err == nil && tc.expectErr {
t.Errorf("[%v]expected error but got none.", i)
}
if err != nil && !tc.expectErr {
t.Errorf("[%v]did not expect error but got: %v", i, err)
}
}
}
func TestIsHugePageResourceName(t *testing.T) {
testCases := []struct {
name core.ResourceName

View File

@@ -419,32 +419,3 @@ func GetPersistentVolumeClaimClass(claim *v1.PersistentVolumeClaim) string {
return ""
}
// GetStorageNodeAffinityFromAnnotation gets the json serialized data from PersistentVolume.Annotations
// and converts it to the NodeAffinity type in api.
// TODO: update when storage node affinity graduates to beta
func GetStorageNodeAffinityFromAnnotation(annotations map[string]string) (*v1.NodeAffinity, error) {
if len(annotations) > 0 && annotations[v1.AlphaStorageNodeAffinityAnnotation] != "" {
var affinity v1.NodeAffinity
err := json.Unmarshal([]byte(annotations[v1.AlphaStorageNodeAffinityAnnotation]), &affinity)
if err != nil {
return nil, err
}
return &affinity, nil
}
return nil, nil
}
// Converts NodeAffinity type to Alpha annotation for use in PersistentVolumes
// TODO: update when storage node affinity graduates to beta
func StorageNodeAffinityToAlphaAnnotation(annotations map[string]string, affinity *v1.NodeAffinity) error {
if affinity == nil {
return nil
}
json, err := json.Marshal(*affinity)
if err != nil {
return err
}
annotations[v1.AlphaStorageNodeAffinityAnnotation] = string(json)
return nil
}

View File

@@ -566,90 +566,3 @@ func TestSysctlsFromPodAnnotation(t *testing.T) {
}
}
}
// TODO: remove when alpha support for topology constraints is removed
func TestGetNodeAffinityFromAnnotations(t *testing.T) {
testCases := []struct {
annotations map[string]string
expectErr bool
}{
{
annotations: nil,
expectErr: false,
},
{
annotations: map[string]string{},
expectErr: false,
},
{
annotations: map[string]string{
v1.AlphaStorageNodeAffinityAnnotation: `{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
]}
}`,
},
expectErr: false,
},
{
annotations: map[string]string{
v1.AlphaStorageNodeAffinityAnnotation: `[{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [
{ "matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
]}
}]`,
},
expectErr: true,
},
{
annotations: map[string]string{
v1.AlphaStorageNodeAffinityAnnotation: `{
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms":
"matchExpressions": [
{ "key": "test-key1",
"operator": "In",
"values": ["test-value1", "test-value2"]
},
{ "key": "test-key2",
"operator": "In",
"values": ["test-value1", "test-value2"]
}
]}
}
}`,
},
expectErr: true,
},
}
for i, tc := range testCases {
_, err := GetStorageNodeAffinityFromAnnotation(tc.annotations)
if err == nil && tc.expectErr {
t.Errorf("[%v]expected error but got none.", i)
}
if err != nil && !tc.expectErr {
t.Errorf("[%v]did not expect error but got: %v", i, err)
}
}
}

View File

@@ -1536,18 +1536,9 @@ func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList {
}
}
nodeAffinitySpecified, errs := validateStorageNodeAffinityAnnotation(pv.ObjectMeta.Annotations, metaPath.Child("annotations"))
nodeAffinitySpecified, errs := validateVolumeNodeAffinity(pv.Spec.NodeAffinity, specPath.Child("nodeAffinity"))
allErrs = append(allErrs, errs...)
volumeNodeAffinitySpecified, errs := validateVolumeNodeAffinity(pv.Spec.NodeAffinity, specPath.Child("nodeAffinity"))
allErrs = append(allErrs, errs...)
if nodeAffinitySpecified && volumeNodeAffinitySpecified {
allErrs = append(allErrs, field.Forbidden(specPath.Child("nodeAffinity"), "may not specify both alpha nodeAffinity annotation and nodeAffinity field"))
}
nodeAffinitySpecified = nodeAffinitySpecified || volumeNodeAffinitySpecified
numVolumes := 0
if pv.Spec.HostPath != nil {
if numVolumes > 0 {
@@ -5009,35 +5000,6 @@ func sysctlIntersection(a []core.Sysctl, b []core.Sysctl) []string {
return result
}
// validateStorageNodeAffinityAnnotation tests that the serialized TopologyConstraints in PersistentVolume.Annotations has valid data
func validateStorageNodeAffinityAnnotation(annotations map[string]string, fldPath *field.Path) (bool, field.ErrorList) {
allErrs := field.ErrorList{}
na, err := helper.GetStorageNodeAffinityFromAnnotation(annotations)
if err != nil {
allErrs = append(allErrs, field.Invalid(fldPath, core.AlphaStorageNodeAffinityAnnotation, err.Error()))
return false, allErrs
}
if na == nil {
return false, allErrs
}
if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
allErrs = append(allErrs, field.Forbidden(fldPath, "Storage node affinity is disabled by feature-gate"))
}
policySpecified := false
if na.RequiredDuringSchedulingIgnoredDuringExecution != nil {
allErrs = append(allErrs, ValidateNodeSelector(na.RequiredDuringSchedulingIgnoredDuringExecution, fldPath.Child("requiredDuringSchedulingIgnoredDuringExecution"))...)
policySpecified = true
}
if len(na.PreferredDuringSchedulingIgnoredDuringExecution) > 0 {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("preferredDuringSchedulingIgnoredDuringExection"), "Storage node affinity does not support preferredDuringSchedulingIgnoredDuringExecution"))
}
return policySpecified, allErrs
}
// validateVolumeNodeAffinity tests that the PersistentVolume.NodeAffinity has valid data
// returns:
// - true if volumeNodeAffinity is set

View File

@@ -35,7 +35,6 @@ import (
"k8s.io/kubernetes/pkg/api/legacyscheme"
_ "k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/helper"
"k8s.io/kubernetes/pkg/capabilities"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/security/apparmor"
@@ -65,24 +64,6 @@ func testVolume(name string, namespace string, spec core.PersistentVolumeSpec) *
}
}
func testVolumeWithAlphaNodeAffinity(t *testing.T, name string, namespace string, affinity *core.NodeAffinity, spec core.PersistentVolumeSpec) *core.PersistentVolume {
objMeta := metav1.ObjectMeta{Name: name}
if namespace != "" {
objMeta.Namespace = namespace
}
objMeta.Annotations = map[string]string{}
err := helper.StorageNodeAffinityToAlphaAnnotation(objMeta.Annotations, affinity)
if err != nil {
t.Fatalf("Failed to get node affinity annotation: %v", err)
}
return &core.PersistentVolume{
ObjectMeta: objMeta,
Spec: spec,
}
}
func TestValidatePersistentVolumes(t *testing.T) {
validMode := core.PersistentVolumeFilesystem
scenarios := map[string]struct {
@@ -512,29 +493,6 @@ func TestValidateLocalVolumes(t *testing.T) {
isExpectedFailure bool
volume *core.PersistentVolume
}{
"alpha valid local volume": {
isExpectedFailure: false,
volume: testVolumeWithAlphaNodeAffinity(
t,
"valid-local-volume",
"",
&core.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{
NodeSelectorTerms: []core.NodeSelectorTerm{
{
MatchExpressions: []core.NodeSelectorRequirement{
{
Key: "test-label-key",
Operator: core.NodeSelectorOpIn,
Values: []string{"test-label-value"},
},
},
},
},
},
},
testLocalVolume("/foo", nil)),
},
"alpha invalid local volume nil annotations": {
isExpectedFailure: true,
volume: testVolume(
@@ -542,75 +500,6 @@ func TestValidateLocalVolumes(t *testing.T) {
"",
testLocalVolume("/foo", nil)),
},
"alpha invalid local volume empty affinity": {
isExpectedFailure: true,
volume: testVolumeWithAlphaNodeAffinity(
t,
"invalid-local-volume-empty-affinity",
"",
&core.NodeAffinity{},
testLocalVolume("/foo", nil)),
},
"alpha invalid local volume preferred affinity": {
isExpectedFailure: true,
volume: testVolumeWithAlphaNodeAffinity(
t,
"invalid-local-volume-preferred-affinity",
"",
&core.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{
NodeSelectorTerms: []core.NodeSelectorTerm{
{
MatchExpressions: []core.NodeSelectorRequirement{
{
Key: "test-label-key",
Operator: core.NodeSelectorOpIn,
Values: []string{"test-label-value"},
},
},
},
},
},
PreferredDuringSchedulingIgnoredDuringExecution: []core.PreferredSchedulingTerm{
{
Weight: 10,
Preference: core.NodeSelectorTerm{
MatchExpressions: []core.NodeSelectorRequirement{
{
Key: "test-label-key",
Operator: core.NodeSelectorOpIn,
Values: []string{"test-label-value"},
},
},
},
},
},
},
testLocalVolume("/foo", nil)),
},
"alpha and beta local volume": {
isExpectedFailure: true,
volume: testVolumeWithAlphaNodeAffinity(
t,
"invalid-alpha-beta-local-volume",
"",
&core.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{
NodeSelectorTerms: []core.NodeSelectorTerm{
{
MatchExpressions: []core.NodeSelectorRequirement{
{
Key: "test-label-key",
Operator: core.NodeSelectorOpIn,
Values: []string{"test-label-value"},
},
},
},
},
},
},
testLocalVolume("/foo", simpleVolumeNodeAffinity("foo", "bar"))),
},
"valid local volume": {
isExpectedFailure: false,
volume: testVolume("valid-local-volume", "",
@@ -654,29 +543,6 @@ func TestValidateLocalVolumesDisabled(t *testing.T) {
isExpectedFailure bool
volume *core.PersistentVolume
}{
"alpha disabled valid local volume": {
isExpectedFailure: true,
volume: testVolumeWithAlphaNodeAffinity(
t,
"valid-local-volume",
"",
&core.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &core.NodeSelector{
NodeSelectorTerms: []core.NodeSelectorTerm{
{
MatchExpressions: []core.NodeSelectorRequirement{
{
Key: "test-label-key",
Operator: core.NodeSelectorOpIn,
Values: []string{"test-label-value"},
},
},
},
},
},
},
testLocalVolume("/foo", nil)),
},
"feature disabled valid local volume": {
isExpectedFailure: true,
volume: testVolume("valid-local-volume", "",