mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Clean up brace whitespace in **/validation_test.go
This was making my eyes bleed as I read over code.
I used the following in vim.  I made them up on the fly, but they seemed
to pass manual inspection.
:g/},\n\s*{$/s//}, {/
:w
:g/{$\n\s*{$/s//{{/
:w
:g/^\(\s*\)},\n\1},$/s//}},/
:w
:g/^\(\s*\)},$\n\1}$/s//}}/
:w
			
			
This commit is contained in:
		
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -28,96 +28,84 @@ func TestValidateServerStorageVersion(t *testing.T) {
 | 
				
			|||||||
	cases := []struct {
 | 
						cases := []struct {
 | 
				
			||||||
		ssv         apiserverinternal.ServerStorageVersion
 | 
							ssv         apiserverinternal.ServerStorageVersion
 | 
				
			||||||
		expectedErr string
 | 
							expectedErr string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ssv: apiserverinternal.ServerStorageVersion{
 | 
							ssv: apiserverinternal.ServerStorageVersion{
 | 
				
			||||||
			APIServerID:       "-fea",
 | 
								APIServerID:       "-fea",
 | 
				
			||||||
			EncodingVersion:   "v1alpha1",
 | 
								EncodingVersion:   "v1alpha1",
 | 
				
			||||||
			DecodableVersions: []string{"v1alpha1", "v1"},
 | 
								DecodableVersions: []string{"v1alpha1", "v1"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: "apiServerID: Invalid value",
 | 
							expectedErr: "apiServerID: Invalid value",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ssv: apiserverinternal.ServerStorageVersion{
 | 
							ssv: apiserverinternal.ServerStorageVersion{
 | 
				
			||||||
			APIServerID:       "fea",
 | 
								APIServerID:       "fea",
 | 
				
			||||||
			EncodingVersion:   "v1alpha1",
 | 
								EncodingVersion:   "v1alpha1",
 | 
				
			||||||
			DecodableVersions: []string{"v1beta1", "v1"},
 | 
								DecodableVersions: []string{"v1beta1", "v1"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: "decodableVersions must include encodingVersion",
 | 
							expectedErr: "decodableVersions must include encodingVersion",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ssv: apiserverinternal.ServerStorageVersion{
 | 
							ssv: apiserverinternal.ServerStorageVersion{
 | 
				
			||||||
			APIServerID:       "fea",
 | 
								APIServerID:       "fea",
 | 
				
			||||||
			EncodingVersion:   "v1alpha1",
 | 
								EncodingVersion:   "v1alpha1",
 | 
				
			||||||
			DecodableVersions: []string{"v1alpha1", "v1", "-fea"},
 | 
								DecodableVersions: []string{"v1alpha1", "v1", "-fea"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: "decodableVersions[2]: Invalid value",
 | 
							expectedErr: "decodableVersions[2]: Invalid value",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ssv: apiserverinternal.ServerStorageVersion{
 | 
							ssv: apiserverinternal.ServerStorageVersion{
 | 
				
			||||||
			APIServerID:       "fea",
 | 
								APIServerID:       "fea",
 | 
				
			||||||
			EncodingVersion:   "v1alpha1",
 | 
								EncodingVersion:   "v1alpha1",
 | 
				
			||||||
			DecodableVersions: []string{"v1alpha1", "v1"},
 | 
								DecodableVersions: []string{"v1alpha1", "v1"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: "",
 | 
							expectedErr: "",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ssv: apiserverinternal.ServerStorageVersion{
 | 
							ssv: apiserverinternal.ServerStorageVersion{
 | 
				
			||||||
			APIServerID:       "fea",
 | 
								APIServerID:       "fea",
 | 
				
			||||||
			EncodingVersion:   "mygroup.com/v2",
 | 
								EncodingVersion:   "mygroup.com/v2",
 | 
				
			||||||
			DecodableVersions: []string{"v1alpha1", "v1", "mygroup.com/v2"},
 | 
								DecodableVersions: []string{"v1alpha1", "v1", "mygroup.com/v2"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: "",
 | 
							expectedErr: "",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ssv: apiserverinternal.ServerStorageVersion{
 | 
							ssv: apiserverinternal.ServerStorageVersion{
 | 
				
			||||||
			APIServerID:       "fea",
 | 
								APIServerID:       "fea",
 | 
				
			||||||
			EncodingVersion:   "mygroup.com/v2",
 | 
								EncodingVersion:   "mygroup.com/v2",
 | 
				
			||||||
			DecodableVersions: []string{"mygroup.com/v2", "/v3"},
 | 
								DecodableVersions: []string{"mygroup.com/v2", "/v3"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: `[].decodableVersions[1]: Invalid value: "/v3": group part: must be non-empty`,
 | 
							expectedErr: `[].decodableVersions[1]: Invalid value: "/v3": group part: must be non-empty`,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ssv: apiserverinternal.ServerStorageVersion{
 | 
							ssv: apiserverinternal.ServerStorageVersion{
 | 
				
			||||||
			APIServerID:       "fea",
 | 
								APIServerID:       "fea",
 | 
				
			||||||
			EncodingVersion:   "mygroup.com/v2",
 | 
								EncodingVersion:   "mygroup.com/v2",
 | 
				
			||||||
			DecodableVersions: []string{"mygroup.com/v2", "mygroup.com/"},
 | 
								DecodableVersions: []string{"mygroup.com/v2", "mygroup.com/"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/": version part: must be non-empty`,
 | 
							expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/": version part: must be non-empty`,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ssv: apiserverinternal.ServerStorageVersion{
 | 
							ssv: apiserverinternal.ServerStorageVersion{
 | 
				
			||||||
			APIServerID:       "fea",
 | 
								APIServerID:       "fea",
 | 
				
			||||||
			EncodingVersion:   "/v3",
 | 
								EncodingVersion:   "/v3",
 | 
				
			||||||
			DecodableVersions: []string{"mygroup.com/v2", "/v3"},
 | 
								DecodableVersions: []string{"mygroup.com/v2", "/v3"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: `[].encodingVersion: Invalid value: "/v3": group part: must be non-empty`,
 | 
							expectedErr: `[].encodingVersion: Invalid value: "/v3": group part: must be non-empty`,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ssv: apiserverinternal.ServerStorageVersion{
 | 
							ssv: apiserverinternal.ServerStorageVersion{
 | 
				
			||||||
			APIServerID:       "fea",
 | 
								APIServerID:       "fea",
 | 
				
			||||||
			EncodingVersion:   "v1",
 | 
								EncodingVersion:   "v1",
 | 
				
			||||||
			DecodableVersions: []string{"v1", "mygroup_com/v2"},
 | 
								DecodableVersions: []string{"v1", "mygroup_com/v2"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup_com/v2": group part: a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`,
 | 
							expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup_com/v2": group part: a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ssv: apiserverinternal.ServerStorageVersion{
 | 
							ssv: apiserverinternal.ServerStorageVersion{
 | 
				
			||||||
			APIServerID:       "fea",
 | 
								APIServerID:       "fea",
 | 
				
			||||||
			EncodingVersion:   "v1",
 | 
								EncodingVersion:   "v1",
 | 
				
			||||||
			DecodableVersions: []string{"v1", "mygroup.com/v2_"},
 | 
								DecodableVersions: []string{"v1", "mygroup.com/v2_"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/v2_": version part: a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name',  or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?')`,
 | 
							expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/v2_": version part: a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name',  or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?')`,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ssv: apiserverinternal.ServerStorageVersion{
 | 
							ssv: apiserverinternal.ServerStorageVersion{
 | 
				
			||||||
			APIServerID:       "fea",
 | 
								APIServerID:       "fea",
 | 
				
			||||||
			EncodingVersion:   "v1",
 | 
								EncodingVersion:   "v1",
 | 
				
			||||||
			DecodableVersions: []string{"v1", "mygroup.com/v2/myresource"},
 | 
								DecodableVersions: []string{"v1", "mygroup.com/v2/myresource"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/v2/myresource": an apiVersion is a DNS-1035 label, which must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name',  or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?') with an optional DNS subdomain prefix and '/' (e.g. 'example.com/MyVersion')`,
 | 
							expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/v2/myresource": an apiVersion is a DNS-1035 label, which must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name',  or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?') with an optional DNS subdomain prefix and '/' (e.g. 'example.com/MyVersion')`,
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range cases {
 | 
						for _, tc := range cases {
 | 
				
			||||||
		err := validateServerStorageVersion(tc.ssv, field.NewPath("")).ToAggregate()
 | 
							err := validateServerStorageVersion(tc.ssv, field.NewPath("")).ToAggregate()
 | 
				
			||||||
@@ -142,91 +130,70 @@ func TestValidateCommonVersion(t *testing.T) {
 | 
				
			|||||||
	cases := []struct {
 | 
						cases := []struct {
 | 
				
			||||||
		status      apiserverinternal.StorageVersionStatus
 | 
							status      apiserverinternal.StorageVersionStatus
 | 
				
			||||||
		expectedErr string
 | 
							expectedErr string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		status: apiserverinternal.StorageVersionStatus{
 | 
							status: apiserverinternal.StorageVersionStatus{
 | 
				
			||||||
			StorageVersions:       []apiserverinternal.ServerStorageVersion{},
 | 
								StorageVersions:       []apiserverinternal.ServerStorageVersion{},
 | 
				
			||||||
			CommonEncodingVersion: func() *string { a := "v1alpha1"; return &a }(),
 | 
								CommonEncodingVersion: func() *string { a := "v1alpha1"; return &a }(),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: "should be nil if servers do not agree on the same encoding version, or if there is no server reporting the supported versions yet",
 | 
							expectedErr: "should be nil if servers do not agree on the same encoding version, or if there is no server reporting the supported versions yet",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		status: apiserverinternal.StorageVersionStatus{
 | 
							status: apiserverinternal.StorageVersionStatus{
 | 
				
			||||||
				StorageVersions: []apiserverinternal.ServerStorageVersion{
 | 
								StorageVersions: []apiserverinternal.ServerStorageVersion{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				APIServerID:     "1",
 | 
									APIServerID:     "1",
 | 
				
			||||||
				EncodingVersion: "v1alpha1",
 | 
									EncodingVersion: "v1alpha1",
 | 
				
			||||||
					},
 | 
								}, {
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				APIServerID:     "2",
 | 
									APIServerID:     "2",
 | 
				
			||||||
				EncodingVersion: "v1",
 | 
									EncodingVersion: "v1",
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			CommonEncodingVersion: func() *string { a := "v1alpha1"; return &a }(),
 | 
								CommonEncodingVersion: func() *string { a := "v1alpha1"; return &a }(),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: "should be nil if servers do not agree on the same encoding version, or if there is no server reporting the supported versions yet",
 | 
							expectedErr: "should be nil if servers do not agree on the same encoding version, or if there is no server reporting the supported versions yet",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		status: apiserverinternal.StorageVersionStatus{
 | 
							status: apiserverinternal.StorageVersionStatus{
 | 
				
			||||||
				StorageVersions: []apiserverinternal.ServerStorageVersion{
 | 
								StorageVersions: []apiserverinternal.ServerStorageVersion{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				APIServerID:     "1",
 | 
									APIServerID:     "1",
 | 
				
			||||||
				EncodingVersion: "v1alpha1",
 | 
									EncodingVersion: "v1alpha1",
 | 
				
			||||||
					},
 | 
								}, {
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				APIServerID:     "2",
 | 
									APIServerID:     "2",
 | 
				
			||||||
				EncodingVersion: "v1alpha1",
 | 
									EncodingVersion: "v1alpha1",
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			CommonEncodingVersion: nil,
 | 
								CommonEncodingVersion: nil,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: "Invalid value: \"null\": the common encoding version is v1alpha1",
 | 
							expectedErr: "Invalid value: \"null\": the common encoding version is v1alpha1",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		status: apiserverinternal.StorageVersionStatus{
 | 
							status: apiserverinternal.StorageVersionStatus{
 | 
				
			||||||
				StorageVersions: []apiserverinternal.ServerStorageVersion{
 | 
								StorageVersions: []apiserverinternal.ServerStorageVersion{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				APIServerID:     "1",
 | 
									APIServerID:     "1",
 | 
				
			||||||
				EncodingVersion: "v1alpha1",
 | 
									EncodingVersion: "v1alpha1",
 | 
				
			||||||
					},
 | 
								}, {
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				APIServerID:     "2",
 | 
									APIServerID:     "2",
 | 
				
			||||||
				EncodingVersion: "v1alpha1",
 | 
									EncodingVersion: "v1alpha1",
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			CommonEncodingVersion: func() *string { a := "v1"; return &a }(),
 | 
								CommonEncodingVersion: func() *string { a := "v1"; return &a }(),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: "Invalid value: \"v1\": the actual common encoding version is v1alpha1",
 | 
							expectedErr: "Invalid value: \"v1\": the actual common encoding version is v1alpha1",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		status: apiserverinternal.StorageVersionStatus{
 | 
							status: apiserverinternal.StorageVersionStatus{
 | 
				
			||||||
				StorageVersions: []apiserverinternal.ServerStorageVersion{
 | 
								StorageVersions: []apiserverinternal.ServerStorageVersion{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				APIServerID:     "1",
 | 
									APIServerID:     "1",
 | 
				
			||||||
				EncodingVersion: "v1alpha1",
 | 
									EncodingVersion: "v1alpha1",
 | 
				
			||||||
					},
 | 
								}, {
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				APIServerID:     "2",
 | 
									APIServerID:     "2",
 | 
				
			||||||
				EncodingVersion: "v1alpha1",
 | 
									EncodingVersion: "v1alpha1",
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			CommonEncodingVersion: func() *string { a := "v1alpha1"; return &a }(),
 | 
								CommonEncodingVersion: func() *string { a := "v1alpha1"; return &a }(),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: "",
 | 
							expectedErr: "",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		status: apiserverinternal.StorageVersionStatus{
 | 
							status: apiserverinternal.StorageVersionStatus{
 | 
				
			||||||
				StorageVersions: []apiserverinternal.ServerStorageVersion{
 | 
								StorageVersions: []apiserverinternal.ServerStorageVersion{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				APIServerID:     "1",
 | 
									APIServerID:     "1",
 | 
				
			||||||
				EncodingVersion: "v1alpha1",
 | 
									EncodingVersion: "v1alpha1",
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			CommonEncodingVersion: func() *string { a := "v1alpha1"; return &a }(),
 | 
								CommonEncodingVersion: func() *string { a := "v1alpha1"; return &a }(),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: "",
 | 
							expectedErr: "",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range cases {
 | 
						for _, tc := range cases {
 | 
				
			||||||
		err := validateCommonVersion(tc.status, field.NewPath(""))
 | 
							err := validateCommonVersion(tc.status, field.NewPath(""))
 | 
				
			||||||
		if err == nil && len(tc.expectedErr) == 0 {
 | 
							if err == nil && len(tc.expectedErr) == 0 {
 | 
				
			||||||
@@ -250,78 +217,58 @@ func TestValidateStorageVersionCondition(t *testing.T) {
 | 
				
			|||||||
	cases := []struct {
 | 
						cases := []struct {
 | 
				
			||||||
		conditions  []apiserverinternal.StorageVersionCondition
 | 
							conditions  []apiserverinternal.StorageVersionCondition
 | 
				
			||||||
		expectedErr string
 | 
							expectedErr string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
							conditions: []apiserverinternal.StorageVersionCondition{{
 | 
				
			||||||
			conditions: []apiserverinternal.StorageVersionCondition{
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Type:    "-fea",
 | 
								Type:    "-fea",
 | 
				
			||||||
			Status:  "True",
 | 
								Status:  "True",
 | 
				
			||||||
			Reason:  "unknown",
 | 
								Reason:  "unknown",
 | 
				
			||||||
			Message: "unknown",
 | 
								Message: "unknown",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		expectedErr: "type: Invalid value",
 | 
							expectedErr: "type: Invalid value",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
							conditions: []apiserverinternal.StorageVersionCondition{{
 | 
				
			||||||
			conditions: []apiserverinternal.StorageVersionCondition{
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Type:    "fea",
 | 
								Type:    "fea",
 | 
				
			||||||
			Status:  "-True",
 | 
								Status:  "-True",
 | 
				
			||||||
			Reason:  "unknown",
 | 
								Reason:  "unknown",
 | 
				
			||||||
			Message: "unknown",
 | 
								Message: "unknown",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		expectedErr: "status: Invalid value",
 | 
							expectedErr: "status: Invalid value",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
							conditions: []apiserverinternal.StorageVersionCondition{{
 | 
				
			||||||
			conditions: []apiserverinternal.StorageVersionCondition{
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Type:    "fea",
 | 
								Type:    "fea",
 | 
				
			||||||
			Status:  "True",
 | 
								Status:  "True",
 | 
				
			||||||
			Message: "unknown",
 | 
								Message: "unknown",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		expectedErr: "Required value: reason cannot be empty",
 | 
							expectedErr: "Required value: reason cannot be empty",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
							conditions: []apiserverinternal.StorageVersionCondition{{
 | 
				
			||||||
			conditions: []apiserverinternal.StorageVersionCondition{
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Type:   "fea",
 | 
								Type:   "fea",
 | 
				
			||||||
			Status: "True",
 | 
								Status: "True",
 | 
				
			||||||
			Reason: "unknown",
 | 
								Reason: "unknown",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		expectedErr: "Required value: message cannot be empty",
 | 
							expectedErr: "Required value: message cannot be empty",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
							conditions: []apiserverinternal.StorageVersionCondition{{
 | 
				
			||||||
			conditions: []apiserverinternal.StorageVersionCondition{
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Type:    "fea",
 | 
								Type:    "fea",
 | 
				
			||||||
			Status:  "True",
 | 
								Status:  "True",
 | 
				
			||||||
			Reason:  "unknown",
 | 
								Reason:  "unknown",
 | 
				
			||||||
			Message: "unknown",
 | 
								Message: "unknown",
 | 
				
			||||||
				},
 | 
							}, {
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Type:    "fea",
 | 
								Type:    "fea",
 | 
				
			||||||
			Status:  "True",
 | 
								Status:  "True",
 | 
				
			||||||
			Reason:  "unknown",
 | 
								Reason:  "unknown",
 | 
				
			||||||
			Message: "unknown",
 | 
								Message: "unknown",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		expectedErr: `"fea": the type of the condition is not unique, it also appears in conditions[0]`,
 | 
							expectedErr: `"fea": the type of the condition is not unique, it also appears in conditions[0]`,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
							conditions: []apiserverinternal.StorageVersionCondition{{
 | 
				
			||||||
			conditions: []apiserverinternal.StorageVersionCondition{
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Type:    "fea",
 | 
								Type:    "fea",
 | 
				
			||||||
			Status:  "True",
 | 
								Status:  "True",
 | 
				
			||||||
			Reason:  "unknown",
 | 
								Reason:  "unknown",
 | 
				
			||||||
			Message: "unknown",
 | 
								Message: "unknown",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		expectedErr: "",
 | 
							expectedErr: "",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range cases {
 | 
						for _, tc := range cases {
 | 
				
			||||||
		err := validateStorageVersionCondition(tc.conditions, field.NewPath("")).ToAggregate()
 | 
							err := validateStorageVersionCondition(tc.conditions, field.NewPath("")).ToAggregate()
 | 
				
			||||||
		if err == nil && len(tc.expectedErr) == 0 {
 | 
							if err == nil && len(tc.expectedErr) == 0 {
 | 
				
			||||||
@@ -345,40 +292,31 @@ func TestValidateStorageVersionName(t *testing.T) {
 | 
				
			|||||||
	cases := []struct {
 | 
						cases := []struct {
 | 
				
			||||||
		name        string
 | 
							name        string
 | 
				
			||||||
		expectedErr string
 | 
							expectedErr string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:        "",
 | 
							name:        "",
 | 
				
			||||||
		expectedErr: `name must be in the form of <group>.<resource>`,
 | 
							expectedErr: `name must be in the form of <group>.<resource>`,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:        "pods",
 | 
							name:        "pods",
 | 
				
			||||||
		expectedErr: `name must be in the form of <group>.<resource>`,
 | 
							expectedErr: `name must be in the form of <group>.<resource>`,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:        "core.pods",
 | 
							name:        "core.pods",
 | 
				
			||||||
		expectedErr: "",
 | 
							expectedErr: "",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:        "authentication.k8s.io.tokenreviews",
 | 
							name:        "authentication.k8s.io.tokenreviews",
 | 
				
			||||||
		expectedErr: "",
 | 
							expectedErr: "",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:        strings.Repeat("x", 253) + ".tokenreviews",
 | 
							name:        strings.Repeat("x", 253) + ".tokenreviews",
 | 
				
			||||||
		expectedErr: "",
 | 
							expectedErr: "",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:        strings.Repeat("x", 254) + ".tokenreviews",
 | 
							name:        strings.Repeat("x", 254) + ".tokenreviews",
 | 
				
			||||||
		expectedErr: `the group segment must be no more than 253 characters`,
 | 
							expectedErr: `the group segment must be no more than 253 characters`,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:        "authentication.k8s.io." + strings.Repeat("x", 63),
 | 
							name:        "authentication.k8s.io." + strings.Repeat("x", 63),
 | 
				
			||||||
		expectedErr: "",
 | 
							expectedErr: "",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:        "authentication.k8s.io." + strings.Repeat("x", 64),
 | 
							name:        "authentication.k8s.io." + strings.Repeat("x", 64),
 | 
				
			||||||
		expectedErr: `the resource segment must be no more than 63 characters`,
 | 
							expectedErr: `the resource segment must be no more than 63 characters`,
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range cases {
 | 
						for _, tc := range cases {
 | 
				
			||||||
		errs := ValidateStorageVersionName(tc.name, false)
 | 
							errs := ValidateStorageVersionName(tc.name, false)
 | 
				
			||||||
		if errs == nil && len(tc.expectedErr) == 0 {
 | 
							if errs == nil && len(tc.expectedErr) == 0 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -248,32 +248,26 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
		errs field.ErrorList
 | 
							errs field.ErrorList
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	successCases := []testCase{
 | 
						successCases := []testCase{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "alpha name",
 | 
							name: "alpha name",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakName("abc")),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakName("abc")),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "alphanumeric name",
 | 
							name: "alphanumeric name",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakName("abc-123")),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakName("abc-123")),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "parallel pod management",
 | 
							name: "parallel pod management",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy(apps.ParallelPodManagement)),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy(apps.ParallelPodManagement)),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "ordered ready pod management",
 | 
							name: "ordered ready pod management",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy(apps.OrderedReadyPodManagement)),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy(apps.OrderedReadyPodManagement)),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "update strategy",
 | 
							name: "update strategy",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakReplicas(3),
 | 
								tweakReplicas(3),
 | 
				
			||||||
			tweakUpdateStrategyType(apps.RollingUpdateStatefulSetStrategyType),
 | 
								tweakUpdateStrategyType(apps.RollingUpdateStatefulSetStrategyType),
 | 
				
			||||||
			tweakRollingUpdatePartition(2),
 | 
								tweakRollingUpdatePartition(2),
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "PVC policy " + enableStatefulSetAutoDeletePVC,
 | 
							name: "PVC policy " + enableStatefulSetAutoDeletePVC,
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakPVCPolicy(mkPVCPolicy(
 | 
								tweakPVCPolicy(mkPVCPolicy(
 | 
				
			||||||
@@ -281,8 +275,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
				tweakPVCScalePolicy(apps.RetainPersistentVolumeClaimRetentionPolicyType),
 | 
									tweakPVCScalePolicy(apps.RetainPersistentVolumeClaimRetentionPolicyType),
 | 
				
			||||||
			)),
 | 
								)),
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "maxUnavailable with parallel pod management",
 | 
							name: "maxUnavailable with parallel pod management",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakReplicas(3),
 | 
								tweakReplicas(3),
 | 
				
			||||||
@@ -290,8 +283,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
			tweakRollingUpdatePartition(2),
 | 
								tweakRollingUpdatePartition(2),
 | 
				
			||||||
			tweakMaxUnavailable(intstr.FromInt32(2)),
 | 
								tweakMaxUnavailable(intstr.FromInt32(2)),
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "ordinals.start positive value",
 | 
							name: "ordinals.start positive value",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakReplicas(3),
 | 
								tweakReplicas(3),
 | 
				
			||||||
@@ -300,58 +292,50 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	errorCases := []testCase{
 | 
						errorCases := []testCase{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "zero-length name",
 | 
							name: "zero-length name",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakName("")),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakName("")),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Required(field.NewPath("metadata", "name"), ""),
 | 
								field.Required(field.NewPath("metadata", "name"), ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "name-with-dots",
 | 
							name: "name-with-dots",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakName("abc.123")),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakName("abc.123")),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("metadata", "name"), "abc.123", ""),
 | 
								field.Invalid(field.NewPath("metadata", "name"), "abc.123", ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "long name",
 | 
							name: "long name",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakName(strings.Repeat("a", 64))),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakName(strings.Repeat("a", 64))),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("metadata", "name"), strings.Repeat("a", 64), ""),
 | 
								field.Invalid(field.NewPath("metadata", "name"), strings.Repeat("a", 64), ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "missing-namespace",
 | 
							name: "missing-namespace",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakNamespace("")),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakNamespace("")),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Required(field.NewPath("metadata", "namespace"), ""),
 | 
								field.Required(field.NewPath("metadata", "namespace"), ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "empty selector",
 | 
							name: "empty selector",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakSelectorLabels(nil)),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakSelectorLabels(nil)),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Required(field.NewPath("spec", "selector"), ""),
 | 
								field.Required(field.NewPath("spec", "selector"), ""),
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "template", "metadata", "labels"), nil, ""), // selector is empty, labels are not, so select doesn't match labels
 | 
								field.Invalid(field.NewPath("spec", "template", "metadata", "labels"), nil, ""), // selector is empty, labels are not, so select doesn't match labels
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "selector_doesnt_match",
 | 
							name: "selector_doesnt_match",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakSelectorLabels(map[string]string{"foo": "bar"})),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakSelectorLabels(map[string]string{"foo": "bar"})),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "template", "metadata", "labels"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "template", "metadata", "labels"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "negative_replicas",
 | 
							name: "negative_replicas",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakReplicas(-1)),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakReplicas(-1)),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "replicas"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "replicas"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid_label",
 | 
							name: "invalid_label",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakLabels("NoUppercaseOrSpecialCharsLike=Equals", "bar"),
 | 
								tweakLabels("NoUppercaseOrSpecialCharsLike=Equals", "bar"),
 | 
				
			||||||
@@ -359,8 +343,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("metadata", "labels"), nil, ""),
 | 
								field.Invalid(field.NewPath("metadata", "labels"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid_label 2",
 | 
							name: "invalid_label 2",
 | 
				
			||||||
		set: mkStatefulSet(&invalidPodTemplate,
 | 
							set: mkStatefulSet(&invalidPodTemplate,
 | 
				
			||||||
			tweakLabels("NoUppercaseOrSpecialCharsLike=Equals", "bar"),
 | 
								tweakLabels("NoUppercaseOrSpecialCharsLike=Equals", "bar"),
 | 
				
			||||||
@@ -371,8 +354,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
			field.Invalid(field.NewPath("spec", "selector"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "selector"), nil, ""),
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "selector", "matchLabels"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "selector", "matchLabels"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid_annotation",
 | 
							name: "invalid_annotation",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakAnnotations("NoUppercaseOrSpecialCharsLike=Equals", "bar"),
 | 
								tweakAnnotations("NoUppercaseOrSpecialCharsLike=Equals", "bar"),
 | 
				
			||||||
@@ -380,29 +362,25 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("metadata", "annotations"), nil, ""),
 | 
								field.Invalid(field.NewPath("metadata", "annotations"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid restart policy 1",
 | 
							name: "invalid restart policy 1",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy(api.RestartPolicyOnFailure)),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy(api.RestartPolicyOnFailure)),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.NotSupported(field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
 | 
								field.NotSupported(field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid restart policy 2",
 | 
							name: "invalid restart policy 2",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy(api.RestartPolicyNever)),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy(api.RestartPolicyNever)),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.NotSupported(field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
 | 
								field.NotSupported(field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "empty restart policy",
 | 
							name: "empty restart policy",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy("")),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakTemplateRestartPolicy("")),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.NotSupported(field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
 | 
								field.NotSupported(field.NewPath("spec", "template", "spec", "restartPolicy"), nil, nil),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid update strategy",
 | 
							name: "invalid update strategy",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakReplicas(3),
 | 
								tweakReplicas(3),
 | 
				
			||||||
@@ -411,8 +389,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "updateStrategy"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "updateStrategy"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "empty update strategy",
 | 
							name: "empty update strategy",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakReplicas(3),
 | 
								tweakReplicas(3),
 | 
				
			||||||
@@ -421,8 +398,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Required(field.NewPath("spec", "updateStrategy"), ""),
 | 
								field.Required(field.NewPath("spec", "updateStrategy"), ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid rolling update",
 | 
							name: "invalid rolling update",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakReplicas(3),
 | 
								tweakReplicas(3),
 | 
				
			||||||
@@ -432,8 +408,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "updateStrategy", "rollingUpdate"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "updateStrategy", "rollingUpdate"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "negative parition",
 | 
							name: "negative parition",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakReplicas(3),
 | 
								tweakReplicas(3),
 | 
				
			||||||
@@ -442,8 +417,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "updateStrategy", "rollingUpdate", "partition"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "updateStrategy", "rollingUpdate", "partition"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "empty pod management policy",
 | 
							name: "empty pod management policy",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakPodManagementPolicy(""),
 | 
								tweakPodManagementPolicy(""),
 | 
				
			||||||
@@ -452,22 +426,19 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Required(field.NewPath("spec", "podManagementPolicy"), ""),
 | 
								field.Required(field.NewPath("spec", "podManagementPolicy"), ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid pod management policy",
 | 
							name: "invalid pod management policy",
 | 
				
			||||||
		set:  mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy("foo")),
 | 
							set:  mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy("foo")),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "podManagementPolicy"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "podManagementPolicy"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "set active deadline seconds",
 | 
							name: "set active deadline seconds",
 | 
				
			||||||
		set:  mkStatefulSet(&invalidPodTemplate2, tweakReplicas(3)),
 | 
							set:  mkStatefulSet(&invalidPodTemplate2, tweakReplicas(3)),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Forbidden(field.NewPath("spec", "template", "spec", "activeDeadlineSeconds"), ""),
 | 
								field.Forbidden(field.NewPath("spec", "template", "spec", "activeDeadlineSeconds"), ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "empty PersistentVolumeClaimRetentionPolicy " + enableStatefulSetAutoDeletePVC,
 | 
							name: "empty PersistentVolumeClaimRetentionPolicy " + enableStatefulSetAutoDeletePVC,
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakPVCPolicy(mkPVCPolicy()),
 | 
								tweakPVCPolicy(mkPVCPolicy()),
 | 
				
			||||||
@@ -476,8 +447,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
			field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenDeleted"), nil, nil),
 | 
								field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenDeleted"), nil, nil),
 | 
				
			||||||
			field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenScaled"), nil, nil),
 | 
								field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenScaled"), nil, nil),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid PersistentVolumeClaimRetentionPolicy " + enableStatefulSetAutoDeletePVC,
 | 
							name: "invalid PersistentVolumeClaimRetentionPolicy " + enableStatefulSetAutoDeletePVC,
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakPVCPolicy(mkPVCPolicy(
 | 
								tweakPVCPolicy(mkPVCPolicy(
 | 
				
			||||||
@@ -489,8 +459,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
			field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenDeleted"), nil, nil),
 | 
								field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenDeleted"), nil, nil),
 | 
				
			||||||
			field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenScaled"), nil, nil),
 | 
								field.NotSupported(field.NewPath("spec", "persistentVolumeClaimRetentionPolicy", "whenScaled"), nil, nil),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "zero maxUnavailable",
 | 
							name: "zero maxUnavailable",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakReplicas(3),
 | 
								tweakReplicas(3),
 | 
				
			||||||
@@ -500,8 +469,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "updateStrategy", "rollingUpdate", "maxUnavailable"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "updateStrategy", "rollingUpdate", "maxUnavailable"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "zero percent maxUnavailable",
 | 
							name: "zero percent maxUnavailable",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakReplicas(3),
 | 
								tweakReplicas(3),
 | 
				
			||||||
@@ -511,8 +479,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "updateStrategy", "rollingUpdate", "maxUnavailable"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "updateStrategy", "rollingUpdate", "maxUnavailable"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "greater than 100 percent maxUnavailable",
 | 
							name: "greater than 100 percent maxUnavailable",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakReplicas(3),
 | 
								tweakReplicas(3),
 | 
				
			||||||
@@ -522,8 +489,7 @@ func TestValidateStatefulSet(t *testing.T) {
 | 
				
			|||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "updateStrategy", "rollingUpdate", "maxUnavailable"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "updateStrategy", "rollingUpdate", "maxUnavailable"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid ordinals.start",
 | 
							name: "invalid ordinals.start",
 | 
				
			||||||
		set: mkStatefulSet(&validPodTemplate,
 | 
							set: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakReplicas(3),
 | 
								tweakReplicas(3),
 | 
				
			||||||
@@ -635,48 +601,42 @@ func TestValidateStatefulSetStatus(t *testing.T) {
 | 
				
			|||||||
		observedGeneration *int64
 | 
							observedGeneration *int64
 | 
				
			||||||
		collisionCount     *int32
 | 
							collisionCount     *int32
 | 
				
			||||||
		expectedErr        bool
 | 
							expectedErr        bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:            "valid status",
 | 
							name:            "valid status",
 | 
				
			||||||
		replicas:        3,
 | 
							replicas:        3,
 | 
				
			||||||
		readyReplicas:   3,
 | 
							readyReplicas:   3,
 | 
				
			||||||
		currentReplicas: 2,
 | 
							currentReplicas: 2,
 | 
				
			||||||
		updatedReplicas: 1,
 | 
							updatedReplicas: 1,
 | 
				
			||||||
		expectedErr:     false,
 | 
							expectedErr:     false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:            "invalid replicas",
 | 
							name:            "invalid replicas",
 | 
				
			||||||
		replicas:        -1,
 | 
							replicas:        -1,
 | 
				
			||||||
		readyReplicas:   3,
 | 
							readyReplicas:   3,
 | 
				
			||||||
		currentReplicas: 2,
 | 
							currentReplicas: 2,
 | 
				
			||||||
		updatedReplicas: 1,
 | 
							updatedReplicas: 1,
 | 
				
			||||||
		expectedErr:     true,
 | 
							expectedErr:     true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:            "invalid readyReplicas",
 | 
							name:            "invalid readyReplicas",
 | 
				
			||||||
		replicas:        3,
 | 
							replicas:        3,
 | 
				
			||||||
		readyReplicas:   -1,
 | 
							readyReplicas:   -1,
 | 
				
			||||||
		currentReplicas: 2,
 | 
							currentReplicas: 2,
 | 
				
			||||||
		updatedReplicas: 1,
 | 
							updatedReplicas: 1,
 | 
				
			||||||
		expectedErr:     true,
 | 
							expectedErr:     true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:            "invalid currentReplicas",
 | 
							name:            "invalid currentReplicas",
 | 
				
			||||||
		replicas:        3,
 | 
							replicas:        3,
 | 
				
			||||||
		readyReplicas:   3,
 | 
							readyReplicas:   3,
 | 
				
			||||||
		currentReplicas: -1,
 | 
							currentReplicas: -1,
 | 
				
			||||||
		updatedReplicas: 1,
 | 
							updatedReplicas: 1,
 | 
				
			||||||
		expectedErr:     true,
 | 
							expectedErr:     true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:            "invalid updatedReplicas",
 | 
							name:            "invalid updatedReplicas",
 | 
				
			||||||
		replicas:        3,
 | 
							replicas:        3,
 | 
				
			||||||
		readyReplicas:   3,
 | 
							readyReplicas:   3,
 | 
				
			||||||
		currentReplicas: 2,
 | 
							currentReplicas: 2,
 | 
				
			||||||
		updatedReplicas: -1,
 | 
							updatedReplicas: -1,
 | 
				
			||||||
		expectedErr:     true,
 | 
							expectedErr:     true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "invalid observedGeneration",
 | 
							name:               "invalid observedGeneration",
 | 
				
			||||||
		replicas:           3,
 | 
							replicas:           3,
 | 
				
			||||||
		readyReplicas:      3,
 | 
							readyReplicas:      3,
 | 
				
			||||||
@@ -684,8 +644,7 @@ func TestValidateStatefulSetStatus(t *testing.T) {
 | 
				
			|||||||
		updatedReplicas:    1,
 | 
							updatedReplicas:    1,
 | 
				
			||||||
		observedGeneration: &observedGenerationMinusOne,
 | 
							observedGeneration: &observedGenerationMinusOne,
 | 
				
			||||||
		expectedErr:        true,
 | 
							expectedErr:        true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:            "invalid collisionCount",
 | 
							name:            "invalid collisionCount",
 | 
				
			||||||
		replicas:        3,
 | 
							replicas:        3,
 | 
				
			||||||
		readyReplicas:   3,
 | 
							readyReplicas:   3,
 | 
				
			||||||
@@ -693,48 +652,42 @@ func TestValidateStatefulSetStatus(t *testing.T) {
 | 
				
			|||||||
		updatedReplicas: 1,
 | 
							updatedReplicas: 1,
 | 
				
			||||||
		collisionCount:  &collisionCountMinusOne,
 | 
							collisionCount:  &collisionCountMinusOne,
 | 
				
			||||||
		expectedErr:     true,
 | 
							expectedErr:     true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:            "readyReplicas greater than replicas",
 | 
							name:            "readyReplicas greater than replicas",
 | 
				
			||||||
		replicas:        3,
 | 
							replicas:        3,
 | 
				
			||||||
		readyReplicas:   4,
 | 
							readyReplicas:   4,
 | 
				
			||||||
		currentReplicas: 2,
 | 
							currentReplicas: 2,
 | 
				
			||||||
		updatedReplicas: 1,
 | 
							updatedReplicas: 1,
 | 
				
			||||||
		expectedErr:     true,
 | 
							expectedErr:     true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:            "currentReplicas greater than replicas",
 | 
							name:            "currentReplicas greater than replicas",
 | 
				
			||||||
		replicas:        3,
 | 
							replicas:        3,
 | 
				
			||||||
		readyReplicas:   3,
 | 
							readyReplicas:   3,
 | 
				
			||||||
		currentReplicas: 4,
 | 
							currentReplicas: 4,
 | 
				
			||||||
		updatedReplicas: 1,
 | 
							updatedReplicas: 1,
 | 
				
			||||||
		expectedErr:     true,
 | 
							expectedErr:     true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:            "updatedReplicas greater than replicas",
 | 
							name:            "updatedReplicas greater than replicas",
 | 
				
			||||||
		replicas:        3,
 | 
							replicas:        3,
 | 
				
			||||||
		readyReplicas:   3,
 | 
							readyReplicas:   3,
 | 
				
			||||||
		currentReplicas: 2,
 | 
							currentReplicas: 2,
 | 
				
			||||||
		updatedReplicas: 4,
 | 
							updatedReplicas: 4,
 | 
				
			||||||
		expectedErr:     true,
 | 
							expectedErr:     true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:              "invalid: number of available replicas",
 | 
							name:              "invalid: number of available replicas",
 | 
				
			||||||
		replicas:          3,
 | 
							replicas:          3,
 | 
				
			||||||
		readyReplicas:     3,
 | 
							readyReplicas:     3,
 | 
				
			||||||
		currentReplicas:   2,
 | 
							currentReplicas:   2,
 | 
				
			||||||
		availableReplicas: int32(-1),
 | 
							availableReplicas: int32(-1),
 | 
				
			||||||
		expectedErr:       true,
 | 
							expectedErr:       true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:              "invalid: available replicas greater than replicas",
 | 
							name:              "invalid: available replicas greater than replicas",
 | 
				
			||||||
		replicas:          3,
 | 
							replicas:          3,
 | 
				
			||||||
		readyReplicas:     3,
 | 
							readyReplicas:     3,
 | 
				
			||||||
		currentReplicas:   2,
 | 
							currentReplicas:   2,
 | 
				
			||||||
		availableReplicas: int32(4),
 | 
							availableReplicas: int32(4),
 | 
				
			||||||
		expectedErr:       true,
 | 
							expectedErr:       true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:              "invalid: available replicas greater than ready replicas",
 | 
							name:              "invalid: available replicas greater than ready replicas",
 | 
				
			||||||
		replicas:          3,
 | 
							replicas:          3,
 | 
				
			||||||
		readyReplicas:     2,
 | 
							readyReplicas:     2,
 | 
				
			||||||
@@ -842,23 +795,19 @@ func TestValidateStatefulSetUpdate(t *testing.T) {
 | 
				
			|||||||
		errs   field.ErrorList
 | 
							errs   field.ErrorList
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	successCases := []testCase{
 | 
						successCases := []testCase{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update replica count",
 | 
							name:   "update replica count",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate),
 | 
							old:    mkStatefulSet(&validPodTemplate),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakReplicas(3)),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakReplicas(3)),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update containers 1",
 | 
							name:   "update containers 1",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate),
 | 
							old:    mkStatefulSet(&validPodTemplate),
 | 
				
			||||||
		update: mkStatefulSet(addContainersValidTemplate),
 | 
							update: mkStatefulSet(addContainersValidTemplate),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update containers 2",
 | 
							name:   "update containers 2",
 | 
				
			||||||
		old:    mkStatefulSet(addContainersValidTemplate),
 | 
							old:    mkStatefulSet(addContainersValidTemplate),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate),
 | 
							update: mkStatefulSet(&validPodTemplate),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "update containers and pvc retention policy 1",
 | 
							name: "update containers and pvc retention policy 1",
 | 
				
			||||||
		old:  mkStatefulSet(addContainersValidTemplate),
 | 
							old:  mkStatefulSet(addContainersValidTemplate),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate,
 | 
							update: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
@@ -867,8 +816,7 @@ func TestValidateStatefulSetUpdate(t *testing.T) {
 | 
				
			|||||||
				tweakPVCScalePolicy(apps.RetainPersistentVolumeClaimRetentionPolicyType),
 | 
									tweakPVCScalePolicy(apps.RetainPersistentVolumeClaimRetentionPolicyType),
 | 
				
			||||||
			)),
 | 
								)),
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "update containers and pvc retention policy 2",
 | 
							name: "update containers and pvc retention policy 2",
 | 
				
			||||||
		old: mkStatefulSet(&validPodTemplate,
 | 
							old: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakPVCPolicy(mkPVCPolicy(
 | 
								tweakPVCPolicy(mkPVCPolicy(
 | 
				
			||||||
@@ -876,54 +824,46 @@ func TestValidateStatefulSetUpdate(t *testing.T) {
 | 
				
			|||||||
			)),
 | 
								)),
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate),
 | 
							update: mkStatefulSet(&validPodTemplate),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "update update strategy",
 | 
							name: "update update strategy",
 | 
				
			||||||
		old:  mkStatefulSet(&validPodTemplate),
 | 
							old:  mkStatefulSet(&validPodTemplate),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate,
 | 
							update: mkStatefulSet(&validPodTemplate,
 | 
				
			||||||
			tweakUpdateStrategyType(apps.OnDeleteStatefulSetStrategyType),
 | 
								tweakUpdateStrategyType(apps.OnDeleteStatefulSetStrategyType),
 | 
				
			||||||
		),
 | 
							),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update min ready seconds 1",
 | 
							name:   "update min ready seconds 1",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate),
 | 
							old:    mkStatefulSet(&validPodTemplate),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakMinReadySeconds(10)),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakMinReadySeconds(10)),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update min ready seconds 2",
 | 
							name:   "update min ready seconds 2",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate, tweakMinReadySeconds(5)),
 | 
							old:    mkStatefulSet(&validPodTemplate, tweakMinReadySeconds(5)),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakMinReadySeconds(10)),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakMinReadySeconds(10)),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update existing instance with now-invalid name",
 | 
							name:   "update existing instance with now-invalid name",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate, tweakFinalizers("final")),
 | 
							old:    mkStatefulSet(&validPodTemplate, tweakFinalizers("final")),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakFinalizers()),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakFinalizers()),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update existing instance with .spec.ordinals.start",
 | 
							name:   "update existing instance with .spec.ordinals.start",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate),
 | 
							old:    mkStatefulSet(&validPodTemplate),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakOrdinalsStart(3)),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakOrdinalsStart(3)),
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	errorCases := []testCase{
 | 
						errorCases := []testCase{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update name",
 | 
							name:   "update name",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate, tweakName("abc")),
 | 
							old:    mkStatefulSet(&validPodTemplate, tweakName("abc")),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakName("abc2")),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakName("abc2")),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("metadata", "name"), nil, ""),
 | 
								field.Invalid(field.NewPath("metadata", "name"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update namespace",
 | 
							name:   "update namespace",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate, tweakNamespace(metav1.NamespaceDefault)),
 | 
							old:    mkStatefulSet(&validPodTemplate, tweakNamespace(metav1.NamespaceDefault)),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakNamespace(metav1.NamespaceDefault+"1")),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakNamespace(metav1.NamespaceDefault+"1")),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("metadata", "namespace"), nil, ""),
 | 
								field.Invalid(field.NewPath("metadata", "namespace"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "update selector",
 | 
							name: "update selector",
 | 
				
			||||||
		old:  mkStatefulSet(&validPodTemplate, tweakSelectorLabels(validLabels)),
 | 
							old:  mkStatefulSet(&validPodTemplate, tweakSelectorLabels(validLabels)),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate2,
 | 
							update: mkStatefulSet(&validPodTemplate2,
 | 
				
			||||||
@@ -932,48 +872,42 @@ func TestValidateStatefulSetUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Forbidden(field.NewPath("spec"), ""),
 | 
								field.Forbidden(field.NewPath("spec"), ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update pod management policy 1",
 | 
							name:   "update pod management policy 1",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy("")),
 | 
							old:    mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy("")),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy(apps.OrderedReadyPodManagement)),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy(apps.OrderedReadyPodManagement)),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Forbidden(field.NewPath("spec"), ""),
 | 
								field.Forbidden(field.NewPath("spec"), ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update pod management policy 2",
 | 
							name:   "update pod management policy 2",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy(apps.ParallelPodManagement)),
 | 
							old:    mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy(apps.ParallelPodManagement)),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy(apps.OrderedReadyPodManagement)),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakPodManagementPolicy(apps.OrderedReadyPodManagement)),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Forbidden(field.NewPath("spec"), ""),
 | 
								field.Forbidden(field.NewPath("spec"), ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update to negative replicas",
 | 
							name:   "update to negative replicas",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate),
 | 
							old:    mkStatefulSet(&validPodTemplate),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakReplicas(-1)),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakReplicas(-1)),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "replicas"), nil, ""),
 | 
								field.Invalid(field.NewPath("spec", "replicas"), nil, ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update pvc template size",
 | 
							name:   "update pvc template size",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplate)),
 | 
							old:    mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplate)),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplateChangedSize)),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplateChangedSize)),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Forbidden(field.NewPath("spec"), ""),
 | 
								field.Forbidden(field.NewPath("spec"), ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "update pvc template storage class",
 | 
							name:   "update pvc template storage class",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplate)),
 | 
							old:    mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplate)),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplateChangedClass)),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplateChangedClass)),
 | 
				
			||||||
		errs: field.ErrorList{
 | 
							errs: field.ErrorList{
 | 
				
			||||||
			field.Forbidden(field.NewPath("spec"), ""),
 | 
								field.Forbidden(field.NewPath("spec"), ""),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "add new pvc template",
 | 
							name:   "add new pvc template",
 | 
				
			||||||
		old:    mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplate)),
 | 
							old:    mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplate)),
 | 
				
			||||||
		update: mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplate, validPVCTemplate2)),
 | 
							update: mkStatefulSet(&validPodTemplate, tweakPVCTemplate(validPVCTemplate, validPVCTemplate2)),
 | 
				
			||||||
@@ -1112,26 +1046,22 @@ func TestValidateControllerRevisionUpdate(t *testing.T) {
 | 
				
			|||||||
		newHistory apps.ControllerRevision
 | 
							newHistory apps.ControllerRevision
 | 
				
			||||||
		oldHistory apps.ControllerRevision
 | 
							oldHistory apps.ControllerRevision
 | 
				
			||||||
		isValid    bool
 | 
							isValid    bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:       "valid",
 | 
							name:       "valid",
 | 
				
			||||||
		newHistory: valid,
 | 
							newHistory: valid,
 | 
				
			||||||
		oldHistory: valid,
 | 
							oldHistory: valid,
 | 
				
			||||||
		isValid:    true,
 | 
							isValid:    true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:       "invalid",
 | 
							name:       "invalid",
 | 
				
			||||||
		newHistory: noVersion,
 | 
							newHistory: noVersion,
 | 
				
			||||||
		oldHistory: valid,
 | 
							oldHistory: valid,
 | 
				
			||||||
		isValid:    false,
 | 
							isValid:    false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:       "changed data",
 | 
							name:       "changed data",
 | 
				
			||||||
		newHistory: changedData,
 | 
							newHistory: changedData,
 | 
				
			||||||
		oldHistory: valid,
 | 
							oldHistory: valid,
 | 
				
			||||||
		isValid:    false,
 | 
							isValid:    false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:       "changed revision",
 | 
							name:       "changed revision",
 | 
				
			||||||
		newHistory: changedRevision,
 | 
							newHistory: changedRevision,
 | 
				
			||||||
		oldHistory: valid,
 | 
							oldHistory: valid,
 | 
				
			||||||
@@ -1158,8 +1088,7 @@ func TestValidateDaemonSetStatusUpdate(t *testing.T) {
 | 
				
			|||||||
		update apps.DaemonSet
 | 
							update apps.DaemonSet
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	successCases := []dsUpdateTest{
 | 
						successCases := []dsUpdateTest{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		old: apps.DaemonSet{
 | 
							old: apps.DaemonSet{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
								ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
				
			||||||
			Status: apps.DaemonSetStatus{
 | 
								Status: apps.DaemonSetStatus{
 | 
				
			||||||
@@ -2071,8 +2000,7 @@ func TestValidateDaemonSet(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	successCases := []apps.DaemonSet{
 | 
						successCases := []apps.DaemonSet{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
							ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
				
			||||||
		Spec: apps.DaemonSetSpec{
 | 
							Spec: apps.DaemonSetSpec{
 | 
				
			||||||
			Selector: &metav1.LabelSelector{MatchLabels: validSelector},
 | 
								Selector: &metav1.LabelSelector{MatchLabels: validSelector},
 | 
				
			||||||
@@ -2081,8 +2009,7 @@ func TestValidateDaemonSet(t *testing.T) {
 | 
				
			|||||||
				Type: apps.OnDeleteDaemonSetStrategyType,
 | 
									Type: apps.OnDeleteDaemonSetStrategyType,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
 | 
							ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
 | 
				
			||||||
		Spec: apps.DaemonSetSpec{
 | 
							Spec: apps.DaemonSetSpec{
 | 
				
			||||||
			Selector: &metav1.LabelSelector{MatchLabels: validSelector},
 | 
								Selector: &metav1.LabelSelector{MatchLabels: validSelector},
 | 
				
			||||||
@@ -2290,14 +2217,12 @@ func validDeployment() *apps.Deployment {
 | 
				
			|||||||
				Spec: api.PodSpec{
 | 
									Spec: api.PodSpec{
 | 
				
			||||||
					RestartPolicy: api.RestartPolicyAlways,
 | 
										RestartPolicy: api.RestartPolicyAlways,
 | 
				
			||||||
					DNSPolicy:     api.DNSDefault,
 | 
										DNSPolicy:     api.DNSDefault,
 | 
				
			||||||
					Containers: []api.Container{
 | 
										Containers: []api.Container{{
 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
						Name:                     "nginx",
 | 
											Name:                     "nginx",
 | 
				
			||||||
						Image:                    "image",
 | 
											Image:                    "image",
 | 
				
			||||||
						ImagePullPolicy:          api.PullNever,
 | 
											ImagePullPolicy:          api.PullNever,
 | 
				
			||||||
						TerminationMessagePolicy: api.TerminationMessageReadFile,
 | 
											TerminationMessagePolicy: api.TerminationMessageReadFile,
 | 
				
			||||||
						},
 | 
										}},
 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			RollbackTo: &apps.RollbackConfig{
 | 
								RollbackTo: &apps.RollbackConfig{
 | 
				
			||||||
@@ -2427,8 +2352,7 @@ func TestValidateDeploymentStatus(t *testing.T) {
 | 
				
			|||||||
		collisionCount     *int32
 | 
							collisionCount     *int32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		expectedErr bool
 | 
							expectedErr bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "valid status",
 | 
							name:               "valid status",
 | 
				
			||||||
		replicas:           3,
 | 
							replicas:           3,
 | 
				
			||||||
		updatedReplicas:    3,
 | 
							updatedReplicas:    3,
 | 
				
			||||||
@@ -2436,8 +2360,7 @@ func TestValidateDeploymentStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:  1,
 | 
							availableReplicas:  1,
 | 
				
			||||||
		observedGeneration: 2,
 | 
							observedGeneration: 2,
 | 
				
			||||||
		expectedErr:        false,
 | 
							expectedErr:        false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "invalid replicas",
 | 
							name:               "invalid replicas",
 | 
				
			||||||
		replicas:           -1,
 | 
							replicas:           -1,
 | 
				
			||||||
		updatedReplicas:    2,
 | 
							updatedReplicas:    2,
 | 
				
			||||||
@@ -2445,8 +2368,7 @@ func TestValidateDeploymentStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:  1,
 | 
							availableReplicas:  1,
 | 
				
			||||||
		observedGeneration: 2,
 | 
							observedGeneration: 2,
 | 
				
			||||||
		expectedErr:        true,
 | 
							expectedErr:        true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "invalid updatedReplicas",
 | 
							name:               "invalid updatedReplicas",
 | 
				
			||||||
		replicas:           2,
 | 
							replicas:           2,
 | 
				
			||||||
		updatedReplicas:    -1,
 | 
							updatedReplicas:    -1,
 | 
				
			||||||
@@ -2454,32 +2376,28 @@ func TestValidateDeploymentStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:  1,
 | 
							availableReplicas:  1,
 | 
				
			||||||
		observedGeneration: 2,
 | 
							observedGeneration: 2,
 | 
				
			||||||
		expectedErr:        true,
 | 
							expectedErr:        true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "invalid readyReplicas",
 | 
							name:               "invalid readyReplicas",
 | 
				
			||||||
		replicas:           3,
 | 
							replicas:           3,
 | 
				
			||||||
		readyReplicas:      -1,
 | 
							readyReplicas:      -1,
 | 
				
			||||||
		availableReplicas:  1,
 | 
							availableReplicas:  1,
 | 
				
			||||||
		observedGeneration: 2,
 | 
							observedGeneration: 2,
 | 
				
			||||||
		expectedErr:        true,
 | 
							expectedErr:        true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "invalid availableReplicas",
 | 
							name:               "invalid availableReplicas",
 | 
				
			||||||
		replicas:           3,
 | 
							replicas:           3,
 | 
				
			||||||
		readyReplicas:      3,
 | 
							readyReplicas:      3,
 | 
				
			||||||
		availableReplicas:  -1,
 | 
							availableReplicas:  -1,
 | 
				
			||||||
		observedGeneration: 2,
 | 
							observedGeneration: 2,
 | 
				
			||||||
		expectedErr:        true,
 | 
							expectedErr:        true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "invalid observedGeneration",
 | 
							name:               "invalid observedGeneration",
 | 
				
			||||||
		replicas:           3,
 | 
							replicas:           3,
 | 
				
			||||||
		readyReplicas:      3,
 | 
							readyReplicas:      3,
 | 
				
			||||||
		availableReplicas:  3,
 | 
							availableReplicas:  3,
 | 
				
			||||||
		observedGeneration: -1,
 | 
							observedGeneration: -1,
 | 
				
			||||||
		expectedErr:        true,
 | 
							expectedErr:        true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "updatedReplicas greater than replicas",
 | 
							name:               "updatedReplicas greater than replicas",
 | 
				
			||||||
		replicas:           3,
 | 
							replicas:           3,
 | 
				
			||||||
		updatedReplicas:    4,
 | 
							updatedReplicas:    4,
 | 
				
			||||||
@@ -2487,32 +2405,28 @@ func TestValidateDeploymentStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:  3,
 | 
							availableReplicas:  3,
 | 
				
			||||||
		observedGeneration: 1,
 | 
							observedGeneration: 1,
 | 
				
			||||||
		expectedErr:        true,
 | 
							expectedErr:        true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "readyReplicas greater than replicas",
 | 
							name:               "readyReplicas greater than replicas",
 | 
				
			||||||
		replicas:           3,
 | 
							replicas:           3,
 | 
				
			||||||
		readyReplicas:      4,
 | 
							readyReplicas:      4,
 | 
				
			||||||
		availableReplicas:  3,
 | 
							availableReplicas:  3,
 | 
				
			||||||
		observedGeneration: 1,
 | 
							observedGeneration: 1,
 | 
				
			||||||
		expectedErr:        true,
 | 
							expectedErr:        true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "availableReplicas greater than replicas",
 | 
							name:               "availableReplicas greater than replicas",
 | 
				
			||||||
		replicas:           3,
 | 
							replicas:           3,
 | 
				
			||||||
		readyReplicas:      3,
 | 
							readyReplicas:      3,
 | 
				
			||||||
		availableReplicas:  4,
 | 
							availableReplicas:  4,
 | 
				
			||||||
		observedGeneration: 1,
 | 
							observedGeneration: 1,
 | 
				
			||||||
		expectedErr:        true,
 | 
							expectedErr:        true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "availableReplicas greater than readyReplicas",
 | 
							name:               "availableReplicas greater than readyReplicas",
 | 
				
			||||||
		replicas:           3,
 | 
							replicas:           3,
 | 
				
			||||||
		readyReplicas:      2,
 | 
							readyReplicas:      2,
 | 
				
			||||||
		availableReplicas:  3,
 | 
							availableReplicas:  3,
 | 
				
			||||||
		observedGeneration: 1,
 | 
							observedGeneration: 1,
 | 
				
			||||||
		expectedErr:        true,
 | 
							expectedErr:        true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:               "invalid collisionCount",
 | 
							name:               "invalid collisionCount",
 | 
				
			||||||
		replicas:           3,
 | 
							replicas:           3,
 | 
				
			||||||
		observedGeneration: 1,
 | 
							observedGeneration: 1,
 | 
				
			||||||
@@ -2548,8 +2462,7 @@ func TestValidateDeploymentStatusUpdate(t *testing.T) {
 | 
				
			|||||||
		from, to apps.DeploymentStatus
 | 
							from, to apps.DeploymentStatus
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		expectedErr bool
 | 
							expectedErr bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "increase: valid update",
 | 
							name: "increase: valid update",
 | 
				
			||||||
		from: apps.DeploymentStatus{
 | 
							from: apps.DeploymentStatus{
 | 
				
			||||||
			CollisionCount: nil,
 | 
								CollisionCount: nil,
 | 
				
			||||||
@@ -2558,8 +2471,7 @@ func TestValidateDeploymentStatusUpdate(t *testing.T) {
 | 
				
			|||||||
			CollisionCount: &collisionCount,
 | 
								CollisionCount: &collisionCount,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: false,
 | 
							expectedErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "stable: valid update",
 | 
							name: "stable: valid update",
 | 
				
			||||||
		from: apps.DeploymentStatus{
 | 
							from: apps.DeploymentStatus{
 | 
				
			||||||
			CollisionCount: &collisionCount,
 | 
								CollisionCount: &collisionCount,
 | 
				
			||||||
@@ -2568,8 +2480,7 @@ func TestValidateDeploymentStatusUpdate(t *testing.T) {
 | 
				
			|||||||
			CollisionCount: &collisionCount,
 | 
								CollisionCount: &collisionCount,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: false,
 | 
							expectedErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "unset: invalid update",
 | 
							name: "unset: invalid update",
 | 
				
			||||||
		from: apps.DeploymentStatus{
 | 
							from: apps.DeploymentStatus{
 | 
				
			||||||
			CollisionCount: &collisionCount,
 | 
								CollisionCount: &collisionCount,
 | 
				
			||||||
@@ -2578,8 +2489,7 @@ func TestValidateDeploymentStatusUpdate(t *testing.T) {
 | 
				
			|||||||
			CollisionCount: nil,
 | 
								CollisionCount: nil,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedErr: true,
 | 
							expectedErr: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "decrease: invalid update",
 | 
							name: "decrease: invalid update",
 | 
				
			||||||
		from: apps.DeploymentStatus{
 | 
							from: apps.DeploymentStatus{
 | 
				
			||||||
			CollisionCount: &otherCollisionCount,
 | 
								CollisionCount: &otherCollisionCount,
 | 
				
			||||||
@@ -2872,8 +2782,7 @@ func TestValidateReplicaSetStatus(t *testing.T) {
 | 
				
			|||||||
		observedGeneration   int64
 | 
							observedGeneration   int64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		expectedErr bool
 | 
							expectedErr bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:                 "valid status",
 | 
							name:                 "valid status",
 | 
				
			||||||
		replicas:             3,
 | 
							replicas:             3,
 | 
				
			||||||
		fullyLabeledReplicas: 3,
 | 
							fullyLabeledReplicas: 3,
 | 
				
			||||||
@@ -2881,8 +2790,7 @@ func TestValidateReplicaSetStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:    1,
 | 
							availableReplicas:    1,
 | 
				
			||||||
		observedGeneration:   2,
 | 
							observedGeneration:   2,
 | 
				
			||||||
		expectedErr:          false,
 | 
							expectedErr:          false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:                 "invalid replicas",
 | 
							name:                 "invalid replicas",
 | 
				
			||||||
		replicas:             -1,
 | 
							replicas:             -1,
 | 
				
			||||||
		fullyLabeledReplicas: 3,
 | 
							fullyLabeledReplicas: 3,
 | 
				
			||||||
@@ -2890,8 +2798,7 @@ func TestValidateReplicaSetStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:    1,
 | 
							availableReplicas:    1,
 | 
				
			||||||
		observedGeneration:   2,
 | 
							observedGeneration:   2,
 | 
				
			||||||
		expectedErr:          true,
 | 
							expectedErr:          true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:                 "invalid fullyLabeledReplicas",
 | 
							name:                 "invalid fullyLabeledReplicas",
 | 
				
			||||||
		replicas:             3,
 | 
							replicas:             3,
 | 
				
			||||||
		fullyLabeledReplicas: -1,
 | 
							fullyLabeledReplicas: -1,
 | 
				
			||||||
@@ -2899,8 +2806,7 @@ func TestValidateReplicaSetStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:    1,
 | 
							availableReplicas:    1,
 | 
				
			||||||
		observedGeneration:   2,
 | 
							observedGeneration:   2,
 | 
				
			||||||
		expectedErr:          true,
 | 
							expectedErr:          true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:                 "invalid readyReplicas",
 | 
							name:                 "invalid readyReplicas",
 | 
				
			||||||
		replicas:             3,
 | 
							replicas:             3,
 | 
				
			||||||
		fullyLabeledReplicas: 3,
 | 
							fullyLabeledReplicas: 3,
 | 
				
			||||||
@@ -2908,8 +2814,7 @@ func TestValidateReplicaSetStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:    1,
 | 
							availableReplicas:    1,
 | 
				
			||||||
		observedGeneration:   2,
 | 
							observedGeneration:   2,
 | 
				
			||||||
		expectedErr:          true,
 | 
							expectedErr:          true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:                 "invalid availableReplicas",
 | 
							name:                 "invalid availableReplicas",
 | 
				
			||||||
		replicas:             3,
 | 
							replicas:             3,
 | 
				
			||||||
		fullyLabeledReplicas: 3,
 | 
							fullyLabeledReplicas: 3,
 | 
				
			||||||
@@ -2917,8 +2822,7 @@ func TestValidateReplicaSetStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:    -1,
 | 
							availableReplicas:    -1,
 | 
				
			||||||
		observedGeneration:   2,
 | 
							observedGeneration:   2,
 | 
				
			||||||
		expectedErr:          true,
 | 
							expectedErr:          true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:                 "invalid observedGeneration",
 | 
							name:                 "invalid observedGeneration",
 | 
				
			||||||
		replicas:             3,
 | 
							replicas:             3,
 | 
				
			||||||
		fullyLabeledReplicas: 3,
 | 
							fullyLabeledReplicas: 3,
 | 
				
			||||||
@@ -2926,8 +2830,7 @@ func TestValidateReplicaSetStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:    3,
 | 
							availableReplicas:    3,
 | 
				
			||||||
		observedGeneration:   -1,
 | 
							observedGeneration:   -1,
 | 
				
			||||||
		expectedErr:          true,
 | 
							expectedErr:          true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:                 "fullyLabeledReplicas greater than replicas",
 | 
							name:                 "fullyLabeledReplicas greater than replicas",
 | 
				
			||||||
		replicas:             3,
 | 
							replicas:             3,
 | 
				
			||||||
		fullyLabeledReplicas: 4,
 | 
							fullyLabeledReplicas: 4,
 | 
				
			||||||
@@ -2935,8 +2838,7 @@ func TestValidateReplicaSetStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:    3,
 | 
							availableReplicas:    3,
 | 
				
			||||||
		observedGeneration:   1,
 | 
							observedGeneration:   1,
 | 
				
			||||||
		expectedErr:          true,
 | 
							expectedErr:          true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:                 "readyReplicas greater than replicas",
 | 
							name:                 "readyReplicas greater than replicas",
 | 
				
			||||||
		replicas:             3,
 | 
							replicas:             3,
 | 
				
			||||||
		fullyLabeledReplicas: 3,
 | 
							fullyLabeledReplicas: 3,
 | 
				
			||||||
@@ -2944,8 +2846,7 @@ func TestValidateReplicaSetStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:    3,
 | 
							availableReplicas:    3,
 | 
				
			||||||
		observedGeneration:   1,
 | 
							observedGeneration:   1,
 | 
				
			||||||
		expectedErr:          true,
 | 
							expectedErr:          true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:                 "availableReplicas greater than replicas",
 | 
							name:                 "availableReplicas greater than replicas",
 | 
				
			||||||
		replicas:             3,
 | 
							replicas:             3,
 | 
				
			||||||
		fullyLabeledReplicas: 3,
 | 
							fullyLabeledReplicas: 3,
 | 
				
			||||||
@@ -2953,8 +2854,7 @@ func TestValidateReplicaSetStatus(t *testing.T) {
 | 
				
			|||||||
		availableReplicas:    4,
 | 
							availableReplicas:    4,
 | 
				
			||||||
		observedGeneration:   1,
 | 
							observedGeneration:   1,
 | 
				
			||||||
		expectedErr:          true,
 | 
							expectedErr:          true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:                 "availableReplicas greater than readyReplicas",
 | 
							name:                 "availableReplicas greater than readyReplicas",
 | 
				
			||||||
		replicas:             3,
 | 
							replicas:             3,
 | 
				
			||||||
		fullyLabeledReplicas: 3,
 | 
							fullyLabeledReplicas: 3,
 | 
				
			||||||
@@ -2998,8 +2898,7 @@ func TestValidateReplicaSetStatusUpdate(t *testing.T) {
 | 
				
			|||||||
		old    apps.ReplicaSet
 | 
							old    apps.ReplicaSet
 | 
				
			||||||
		update apps.ReplicaSet
 | 
							update apps.ReplicaSet
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	successCases := []rcUpdateTest{
 | 
						successCases := []rcUpdateTest{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		old: apps.ReplicaSet{
 | 
							old: apps.ReplicaSet{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
								ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
				
			||||||
			Spec: apps.ReplicaSetSpec{
 | 
								Spec: apps.ReplicaSetSpec{
 | 
				
			||||||
@@ -3300,22 +3199,19 @@ func TestValidateReplicaSet(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	successCases := []apps.ReplicaSet{
 | 
						successCases := []apps.ReplicaSet{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
							ObjectMeta: metav1.ObjectMeta{Name: "abc", Namespace: metav1.NamespaceDefault},
 | 
				
			||||||
		Spec: apps.ReplicaSetSpec{
 | 
							Spec: apps.ReplicaSetSpec{
 | 
				
			||||||
			Selector: &metav1.LabelSelector{MatchLabels: validLabels},
 | 
								Selector: &metav1.LabelSelector{MatchLabels: validLabels},
 | 
				
			||||||
			Template: validPodTemplate.Template,
 | 
								Template: validPodTemplate.Template,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
 | 
							ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
 | 
				
			||||||
		Spec: apps.ReplicaSetSpec{
 | 
							Spec: apps.ReplicaSetSpec{
 | 
				
			||||||
			Selector: &metav1.LabelSelector{MatchLabels: validLabels},
 | 
								Selector: &metav1.LabelSelector{MatchLabels: validLabels},
 | 
				
			||||||
			Template: validPodTemplate.Template,
 | 
								Template: validPodTemplate.Template,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
 | 
							ObjectMeta: metav1.ObjectMeta{Name: "abc-123", Namespace: metav1.NamespaceDefault},
 | 
				
			||||||
		Spec: apps.ReplicaSetSpec{
 | 
							Spec: apps.ReplicaSetSpec{
 | 
				
			||||||
			Replicas: 1,
 | 
								Replicas: 1,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,13 +40,11 @@ func TestValidateSARSpec(t *testing.T) {
 | 
				
			|||||||
		name string
 | 
							name string
 | 
				
			||||||
		obj  authorizationapi.SubjectAccessReviewSpec
 | 
							obj  authorizationapi.SubjectAccessReviewSpec
 | 
				
			||||||
		msg  string
 | 
							msg  string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "neither request",
 | 
							name: "neither request",
 | 
				
			||||||
		obj:  authorizationapi.SubjectAccessReviewSpec{User: "me"},
 | 
							obj:  authorizationapi.SubjectAccessReviewSpec{User: "me"},
 | 
				
			||||||
		msg:  "exactly one of nonResourceAttributes or resourceAttributes must be specified",
 | 
							msg:  "exactly one of nonResourceAttributes or resourceAttributes must be specified",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "both requests",
 | 
							name: "both requests",
 | 
				
			||||||
		obj: authorizationapi.SubjectAccessReviewSpec{
 | 
							obj: authorizationapi.SubjectAccessReviewSpec{
 | 
				
			||||||
			ResourceAttributes:    &authorizationapi.ResourceAttributes{},
 | 
								ResourceAttributes:    &authorizationapi.ResourceAttributes{},
 | 
				
			||||||
@@ -54,15 +52,13 @@ func TestValidateSARSpec(t *testing.T) {
 | 
				
			|||||||
			User:                  "me",
 | 
								User:                  "me",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		msg: "cannot be specified in combination with resourceAttributes",
 | 
							msg: "cannot be specified in combination with resourceAttributes",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "no subject",
 | 
							name: "no subject",
 | 
				
			||||||
		obj: authorizationapi.SubjectAccessReviewSpec{
 | 
							obj: authorizationapi.SubjectAccessReviewSpec{
 | 
				
			||||||
			ResourceAttributes: &authorizationapi.ResourceAttributes{},
 | 
								ResourceAttributes: &authorizationapi.ResourceAttributes{},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		msg: `spec.user: Invalid value: "": at least one of user or group must be specified`,
 | 
							msg: `spec.user: Invalid value: "": at least one of user or group must be specified`,
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, c := range errorCases {
 | 
						for _, c := range errorCases {
 | 
				
			||||||
		errs := ValidateSubjectAccessReviewSpec(c.obj, field.NewPath("spec"))
 | 
							errs := ValidateSubjectAccessReviewSpec(c.obj, field.NewPath("spec"))
 | 
				
			||||||
@@ -102,21 +98,18 @@ func TestValidateSelfSAR(t *testing.T) {
 | 
				
			|||||||
		name string
 | 
							name string
 | 
				
			||||||
		obj  authorizationapi.SelfSubjectAccessReviewSpec
 | 
							obj  authorizationapi.SelfSubjectAccessReviewSpec
 | 
				
			||||||
		msg  string
 | 
							msg  string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "neither request",
 | 
							name: "neither request",
 | 
				
			||||||
		obj:  authorizationapi.SelfSubjectAccessReviewSpec{},
 | 
							obj:  authorizationapi.SelfSubjectAccessReviewSpec{},
 | 
				
			||||||
		msg:  "exactly one of nonResourceAttributes or resourceAttributes must be specified",
 | 
							msg:  "exactly one of nonResourceAttributes or resourceAttributes must be specified",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "both requests",
 | 
							name: "both requests",
 | 
				
			||||||
		obj: authorizationapi.SelfSubjectAccessReviewSpec{
 | 
							obj: authorizationapi.SelfSubjectAccessReviewSpec{
 | 
				
			||||||
			ResourceAttributes:    &authorizationapi.ResourceAttributes{},
 | 
								ResourceAttributes:    &authorizationapi.ResourceAttributes{},
 | 
				
			||||||
			NonResourceAttributes: &authorizationapi.NonResourceAttributes{},
 | 
								NonResourceAttributes: &authorizationapi.NonResourceAttributes{},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		msg: "cannot be specified in combination with resourceAttributes",
 | 
							msg: "cannot be specified in combination with resourceAttributes",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, c := range errorCases {
 | 
						for _, c := range errorCases {
 | 
				
			||||||
		errs := ValidateSelfSubjectAccessReviewSpec(c.obj, field.NewPath("spec"))
 | 
							errs := ValidateSelfSubjectAccessReviewSpec(c.obj, field.NewPath("spec"))
 | 
				
			||||||
@@ -136,14 +129,12 @@ func TestValidateSelfSAR(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestValidateLocalSAR(t *testing.T) {
 | 
					func TestValidateLocalSAR(t *testing.T) {
 | 
				
			||||||
	successCases := []authorizationapi.LocalSubjectAccessReview{
 | 
						successCases := []authorizationapi.LocalSubjectAccessReview{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Spec: authorizationapi.SubjectAccessReviewSpec{
 | 
							Spec: authorizationapi.SubjectAccessReviewSpec{
 | 
				
			||||||
			ResourceAttributes: &authorizationapi.ResourceAttributes{},
 | 
								ResourceAttributes: &authorizationapi.ResourceAttributes{},
 | 
				
			||||||
			User:               "user",
 | 
								User:               "user",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, successCase := range successCases {
 | 
						for _, successCase := range successCases {
 | 
				
			||||||
		if errs := ValidateLocalSubjectAccessReview(&successCase); len(errs) != 0 {
 | 
							if errs := ValidateLocalSubjectAccessReview(&successCase); len(errs) != 0 {
 | 
				
			||||||
			t.Errorf("expected success: %v", errs)
 | 
								t.Errorf("expected success: %v", errs)
 | 
				
			||||||
@@ -154,8 +145,7 @@ func TestValidateLocalSAR(t *testing.T) {
 | 
				
			|||||||
		name string
 | 
							name string
 | 
				
			||||||
		obj  *authorizationapi.LocalSubjectAccessReview
 | 
							obj  *authorizationapi.LocalSubjectAccessReview
 | 
				
			||||||
		msg  string
 | 
							msg  string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "name",
 | 
							name: "name",
 | 
				
			||||||
		obj: &authorizationapi.LocalSubjectAccessReview{
 | 
							obj: &authorizationapi.LocalSubjectAccessReview{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{Name: "a"},
 | 
								ObjectMeta: metav1.ObjectMeta{Name: "a"},
 | 
				
			||||||
@@ -165,8 +155,7 @@ func TestValidateLocalSAR(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		msg: "must be empty except for namespace",
 | 
							msg: "must be empty except for namespace",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "namespace conflict",
 | 
							name: "namespace conflict",
 | 
				
			||||||
		obj: &authorizationapi.LocalSubjectAccessReview{
 | 
							obj: &authorizationapi.LocalSubjectAccessReview{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{Namespace: "a"},
 | 
								ObjectMeta: metav1.ObjectMeta{Namespace: "a"},
 | 
				
			||||||
@@ -176,8 +165,7 @@ func TestValidateLocalSAR(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		msg: "must match metadata.namespace",
 | 
							msg: "must match metadata.namespace",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "nonresource",
 | 
							name: "nonresource",
 | 
				
			||||||
		obj: &authorizationapi.LocalSubjectAccessReview{
 | 
							obj: &authorizationapi.LocalSubjectAccessReview{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{Namespace: "a"},
 | 
								ObjectMeta: metav1.ObjectMeta{Namespace: "a"},
 | 
				
			||||||
@@ -187,8 +175,7 @@ func TestValidateLocalSAR(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		msg: "disallowed on this kind of request",
 | 
							msg: "disallowed on this kind of request",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, c := range errorCases {
 | 
						for _, c := range errorCases {
 | 
				
			||||||
		errs := ValidateLocalSubjectAccessReview(c.obj)
 | 
							errs := ValidateLocalSubjectAccessReview(c.obj)
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -112,49 +112,39 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionIgnore,
 | 
												Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
								OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{
 | 
												OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								Type:   api.DisruptionTarget,
 | 
													Type:   api.DisruptionTarget,
 | 
				
			||||||
								Status: api.ConditionTrue,
 | 
													Status: api.ConditionTrue,
 | 
				
			||||||
									},
 | 
												}},
 | 
				
			||||||
								},
 | 
											}, {
 | 
				
			||||||
							},
 | 
					 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
								OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{
 | 
												OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								Type:   api.PodConditionType("CustomConditionType"),
 | 
													Type:   api.PodConditionType("CustomConditionType"),
 | 
				
			||||||
								Status: api.ConditionFalse,
 | 
													Status: api.ConditionFalse,
 | 
				
			||||||
									},
 | 
												}},
 | 
				
			||||||
								},
 | 
											}, {
 | 
				
			||||||
							},
 | 
					 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionCount,
 | 
												Action: batch.PodFailurePolicyActionCount,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								ContainerName: pointer.String("abc"),
 | 
													ContainerName: pointer.String("abc"),
 | 
				
			||||||
								Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:        []int32{1, 2, 3},
 | 
													Values:        []int32{1, 2, 3},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}, {
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionIgnore,
 | 
												Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								ContainerName: pointer.String("def"),
 | 
													ContainerName: pointer.String("def"),
 | 
				
			||||||
								Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:        []int32{4},
 | 
													Values:        []int32{4},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}, {
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								Operator: batch.PodFailurePolicyOnExitCodesOpNotIn,
 | 
													Operator: batch.PodFailurePolicyOnExitCodesOpNotIn,
 | 
				
			||||||
								Values:   []int32{5, 6, 7},
 | 
													Values:   []int32{5, 6, 7},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -314,11 +304,9 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -331,15 +319,13 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:   []int32{11, 11},
 | 
													Values:   []int32{11, 11},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -352,8 +338,7 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
@@ -365,8 +350,7 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
									return tooManyValues
 | 
														return tooManyValues
 | 
				
			||||||
								}(),
 | 
													}(),
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -404,8 +388,7 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
							OnPodConditions: func() []batch.PodFailurePolicyOnPodConditionsPattern {
 | 
												OnPodConditions: func() []batch.PodFailurePolicyOnPodConditionsPattern {
 | 
				
			||||||
								tooManyPatterns := make([]batch.PodFailurePolicyOnPodConditionsPattern, maxPodFailurePolicyOnPodConditionsPatterns+1)
 | 
													tooManyPatterns := make([]batch.PodFailurePolicyOnPodConditionsPattern, maxPodFailurePolicyOnPodConditionsPatterns+1)
 | 
				
			||||||
@@ -417,8 +400,7 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
								}
 | 
													}
 | 
				
			||||||
								return tooManyPatterns
 | 
													return tooManyPatterns
 | 
				
			||||||
							}(),
 | 
												}(),
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -431,15 +413,13 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:   []int32{12, 13, 13, 13},
 | 
													Values:   []int32{12, 13, 13, 13},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -452,15 +432,13 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:   []int32{19, 11},
 | 
													Values:   []int32{19, 11},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -473,15 +451,13 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:   []int32{},
 | 
													Values:   []int32{},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -494,15 +470,13 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: "",
 | 
												Action: "",
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:   []int32{1, 2, 3},
 | 
													Values:   []int32{1, 2, 3},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -515,15 +489,13 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								Operator: "",
 | 
													Operator: "",
 | 
				
			||||||
								Values:   []int32{1, 2, 3},
 | 
													Values:   []int32{1, 2, 3},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -536,22 +508,18 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								ContainerName: pointer.String("abc"),
 | 
													ContainerName: pointer.String("abc"),
 | 
				
			||||||
								Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:        []int32{1, 2, 3},
 | 
													Values:        []int32{1, 2, 3},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
								OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{
 | 
												OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								Type:   api.DisruptionTarget,
 | 
													Type:   api.DisruptionTarget,
 | 
				
			||||||
								Status: api.ConditionTrue,
 | 
													Status: api.ConditionTrue,
 | 
				
			||||||
									},
 | 
												}},
 | 
				
			||||||
								},
 | 
											}},
 | 
				
			||||||
							},
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -564,15 +532,13 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionIgnore,
 | 
												Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator: batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:   []int32{1, 0, 2},
 | 
													Values:   []int32{1, 0, 2},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -585,24 +551,21 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionIgnore,
 | 
												Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								ContainerName: pointer.String("abc"),
 | 
													ContainerName: pointer.String("abc"),
 | 
				
			||||||
								Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:        []int32{1, 2, 3},
 | 
													Values:        []int32{1, 2, 3},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}, {
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionFailJob,
 | 
												Action: batch.PodFailurePolicyActionFailJob,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								ContainerName: pointer.String("xyz"),
 | 
													ContainerName: pointer.String("xyz"),
 | 
				
			||||||
								Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:        []int32{5, 6, 7},
 | 
													Values:        []int32{5, 6, 7},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -615,16 +578,14 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: "UnknownAction",
 | 
												Action: "UnknownAction",
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								ContainerName: pointer.String("abc"),
 | 
													ContainerName: pointer.String("abc"),
 | 
				
			||||||
								Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
													Operator:      batch.PodFailurePolicyOnExitCodesOpIn,
 | 
				
			||||||
								Values:        []int32{1, 2, 3},
 | 
													Values:        []int32{1, 2, 3},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -637,15 +598,13 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionIgnore,
 | 
												Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
							OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
												OnExitCodes: &batch.PodFailurePolicyOnExitCodesRequirement{
 | 
				
			||||||
								Operator: "UnknownOperator",
 | 
													Operator: "UnknownOperator",
 | 
				
			||||||
								Values:   []int32{1, 2, 3},
 | 
													Values:   []int32{1, 2, 3},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -658,16 +617,12 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionIgnore,
 | 
												Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
								OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{
 | 
												OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								Type: api.DisruptionTarget,
 | 
													Type: api.DisruptionTarget,
 | 
				
			||||||
									},
 | 
												}},
 | 
				
			||||||
								},
 | 
											}},
 | 
				
			||||||
							},
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -680,17 +635,13 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionIgnore,
 | 
												Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
								OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{
 | 
												OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								Type:   api.DisruptionTarget,
 | 
													Type:   api.DisruptionTarget,
 | 
				
			||||||
								Status: "UnknownStatus",
 | 
													Status: "UnknownStatus",
 | 
				
			||||||
									},
 | 
												}},
 | 
				
			||||||
								},
 | 
											}},
 | 
				
			||||||
							},
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -703,16 +654,12 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionIgnore,
 | 
												Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
								OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{
 | 
												OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								Status: api.ConditionTrue,
 | 
													Status: api.ConditionTrue,
 | 
				
			||||||
									},
 | 
												}},
 | 
				
			||||||
								},
 | 
											}},
 | 
				
			||||||
							},
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -725,17 +672,13 @@ func TestValidateJob(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionIgnore,
 | 
												Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
								OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{
 | 
												OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								Type:   api.PodConditionType("Invalid Condition Type"),
 | 
													Type:   api.PodConditionType("Invalid Condition Type"),
 | 
				
			||||||
								Status: api.ConditionTrue,
 | 
													Status: api.ConditionTrue,
 | 
				
			||||||
									},
 | 
												}},
 | 
				
			||||||
								},
 | 
											}},
 | 
				
			||||||
							},
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -1116,17 +1059,13 @@ func TestValidateJobUpdate(t *testing.T) {
 | 
				
			|||||||
	validNodeAffinity := &api.Affinity{
 | 
						validNodeAffinity := &api.Affinity{
 | 
				
			||||||
		NodeAffinity: &api.NodeAffinity{
 | 
							NodeAffinity: &api.NodeAffinity{
 | 
				
			||||||
			RequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{
 | 
								RequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{
 | 
				
			||||||
				NodeSelectorTerms: []api.NodeSelectorTerm{
 | 
									NodeSelectorTerms: []api.NodeSelectorTerm{{
 | 
				
			||||||
					{
 | 
										MatchExpressions: []api.NodeSelectorRequirement{{
 | 
				
			||||||
						MatchExpressions: []api.NodeSelectorRequirement{
 | 
					 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
						Key:      "foo",
 | 
											Key:      "foo",
 | 
				
			||||||
						Operator: api.NodeSelectorOpIn,
 | 
											Operator: api.NodeSelectorOpIn,
 | 
				
			||||||
						Values:   []string{"bar", "value2"},
 | 
											Values:   []string{"bar", "value2"},
 | 
				
			||||||
							},
 | 
										}},
 | 
				
			||||||
						},
 | 
									}},
 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1134,17 +1073,13 @@ func TestValidateJobUpdate(t *testing.T) {
 | 
				
			|||||||
	validPodTemplateWithAffinity.Spec.Affinity = &api.Affinity{
 | 
						validPodTemplateWithAffinity.Spec.Affinity = &api.Affinity{
 | 
				
			||||||
		NodeAffinity: &api.NodeAffinity{
 | 
							NodeAffinity: &api.NodeAffinity{
 | 
				
			||||||
			RequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{
 | 
								RequiredDuringSchedulingIgnoredDuringExecution: &api.NodeSelector{
 | 
				
			||||||
				NodeSelectorTerms: []api.NodeSelectorTerm{
 | 
									NodeSelectorTerms: []api.NodeSelectorTerm{{
 | 
				
			||||||
					{
 | 
										MatchExpressions: []api.NodeSelectorRequirement{{
 | 
				
			||||||
						MatchExpressions: []api.NodeSelectorRequirement{
 | 
					 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
						Key:      "foo",
 | 
											Key:      "foo",
 | 
				
			||||||
						Operator: api.NodeSelectorOpIn,
 | 
											Operator: api.NodeSelectorOpIn,
 | 
				
			||||||
						Values:   []string{"bar", "value"},
 | 
											Values:   []string{"bar", "value"},
 | 
				
			||||||
							},
 | 
										}},
 | 
				
			||||||
						},
 | 
									}},
 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1242,17 +1177,13 @@ func TestValidateJobUpdate(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			update: func(job *batch.Job) {
 | 
								update: func(job *batch.Job) {
 | 
				
			||||||
				job.Spec.PodFailurePolicy = &batch.PodFailurePolicy{
 | 
									job.Spec.PodFailurePolicy = &batch.PodFailurePolicy{
 | 
				
			||||||
					Rules: []batch.PodFailurePolicyRule{
 | 
										Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
						Action: batch.PodFailurePolicyActionIgnore,
 | 
											Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
							OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{
 | 
											OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{{
 | 
				
			||||||
								{
 | 
					 | 
				
			||||||
							Type:   api.DisruptionTarget,
 | 
												Type:   api.DisruptionTarget,
 | 
				
			||||||
							Status: api.ConditionTrue,
 | 
												Status: api.ConditionTrue,
 | 
				
			||||||
								},
 | 
											}},
 | 
				
			||||||
							},
 | 
										}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			err: &field.Error{
 | 
								err: &field.Error{
 | 
				
			||||||
@@ -1267,29 +1198,23 @@ func TestValidateJobUpdate(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionIgnore,
 | 
												Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
								OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{
 | 
												OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								Type:   api.DisruptionTarget,
 | 
													Type:   api.DisruptionTarget,
 | 
				
			||||||
								Status: api.ConditionTrue,
 | 
													Status: api.ConditionTrue,
 | 
				
			||||||
									},
 | 
												}},
 | 
				
			||||||
								},
 | 
											}},
 | 
				
			||||||
							},
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			update: func(job *batch.Job) {
 | 
								update: func(job *batch.Job) {
 | 
				
			||||||
				job.Spec.PodFailurePolicy.Rules = append(job.Spec.PodFailurePolicy.Rules, batch.PodFailurePolicyRule{
 | 
									job.Spec.PodFailurePolicy.Rules = append(job.Spec.PodFailurePolicy.Rules, batch.PodFailurePolicyRule{
 | 
				
			||||||
					Action: batch.PodFailurePolicyActionCount,
 | 
										Action: batch.PodFailurePolicyActionCount,
 | 
				
			||||||
					OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{
 | 
										OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{{
 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
						Type:   api.DisruptionTarget,
 | 
											Type:   api.DisruptionTarget,
 | 
				
			||||||
						Status: api.ConditionTrue,
 | 
											Status: api.ConditionTrue,
 | 
				
			||||||
						},
 | 
										}},
 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			err: &field.Error{
 | 
								err: &field.Error{
 | 
				
			||||||
@@ -1304,17 +1229,13 @@ func TestValidateJobUpdate(t *testing.T) {
 | 
				
			|||||||
					Selector: validGeneratedSelector,
 | 
										Selector: validGeneratedSelector,
 | 
				
			||||||
					Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
										Template: validPodTemplateSpecForGeneratedRestartPolicyNever,
 | 
				
			||||||
					PodFailurePolicy: &batch.PodFailurePolicy{
 | 
										PodFailurePolicy: &batch.PodFailurePolicy{
 | 
				
			||||||
						Rules: []batch.PodFailurePolicyRule{
 | 
											Rules: []batch.PodFailurePolicyRule{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Action: batch.PodFailurePolicyActionIgnore,
 | 
												Action: batch.PodFailurePolicyActionIgnore,
 | 
				
			||||||
								OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{
 | 
												OnPodConditions: []batch.PodFailurePolicyOnPodConditionsPattern{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								Type:   api.DisruptionTarget,
 | 
													Type:   api.DisruptionTarget,
 | 
				
			||||||
								Status: api.ConditionTrue,
 | 
													Status: api.ConditionTrue,
 | 
				
			||||||
									},
 | 
												}},
 | 
				
			||||||
								},
 | 
											}},
 | 
				
			||||||
							},
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -413,18 +413,15 @@ func Test_getValidationOptions(t *testing.T) {
 | 
				
			|||||||
		newCSR *capi.CertificateSigningRequest
 | 
							newCSR *capi.CertificateSigningRequest
 | 
				
			||||||
		oldCSR *capi.CertificateSigningRequest
 | 
							oldCSR *capi.CertificateSigningRequest
 | 
				
			||||||
		want   certificateValidationOptions
 | 
							want   certificateValidationOptions
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "strict create",
 | 
							name:   "strict create",
 | 
				
			||||||
		oldCSR: nil,
 | 
							oldCSR: nil,
 | 
				
			||||||
		want:   certificateValidationOptions{},
 | 
							want:   certificateValidationOptions{},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "strict update",
 | 
							name:   "strict update",
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{},
 | 
							oldCSR: &capi.CertificateSigningRequest{},
 | 
				
			||||||
		want:   certificateValidationOptions{},
 | 
							want:   certificateValidationOptions{},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "compatible update, approved+denied",
 | 
							name: "compatible update, approved+denied",
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved}, {Type: capi.CertificateDenied}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved}, {Type: capi.CertificateDenied}},
 | 
				
			||||||
@@ -432,15 +429,13 @@ func Test_getValidationOptions(t *testing.T) {
 | 
				
			|||||||
		want: certificateValidationOptions{
 | 
							want: certificateValidationOptions{
 | 
				
			||||||
			allowBothApprovedAndDenied: true,
 | 
								allowBothApprovedAndDenied: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "compatible update, legacy signerName",
 | 
							name:   "compatible update, legacy signerName",
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{Spec: capi.CertificateSigningRequestSpec{SignerName: capi.LegacyUnknownSignerName}},
 | 
							oldCSR: &capi.CertificateSigningRequest{Spec: capi.CertificateSigningRequestSpec{SignerName: capi.LegacyUnknownSignerName}},
 | 
				
			||||||
		want: certificateValidationOptions{
 | 
							want: certificateValidationOptions{
 | 
				
			||||||
			allowLegacySignerName: true,
 | 
								allowLegacySignerName: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "compatible update, duplicate condition types",
 | 
							name: "compatible update, duplicate condition types",
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved}, {Type: capi.CertificateApproved}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved}, {Type: capi.CertificateApproved}},
 | 
				
			||||||
@@ -448,8 +443,7 @@ func Test_getValidationOptions(t *testing.T) {
 | 
				
			|||||||
		want: certificateValidationOptions{
 | 
							want: certificateValidationOptions{
 | 
				
			||||||
			allowDuplicateConditionTypes: true,
 | 
								allowDuplicateConditionTypes: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "compatible update, empty condition types",
 | 
							name: "compatible update, empty condition types",
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{}},
 | 
				
			||||||
@@ -457,8 +451,7 @@ func Test_getValidationOptions(t *testing.T) {
 | 
				
			|||||||
		want: certificateValidationOptions{
 | 
							want: certificateValidationOptions{
 | 
				
			||||||
			allowEmptyConditionType: true,
 | 
								allowEmptyConditionType: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "compatible update, no diff to certificate",
 | 
							name: "compatible update, no diff to certificate",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Certificate: validCertificate,
 | 
								Certificate: validCertificate,
 | 
				
			||||||
@@ -469,8 +462,7 @@ func Test_getValidationOptions(t *testing.T) {
 | 
				
			|||||||
		want: certificateValidationOptions{
 | 
							want: certificateValidationOptions{
 | 
				
			||||||
			allowArbitraryCertificate: true,
 | 
								allowArbitraryCertificate: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "compatible update, existing invalid certificate",
 | 
							name: "compatible update, existing invalid certificate",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Certificate: []byte(`new - no PEM blocks`),
 | 
								Certificate: []byte(`new - no PEM blocks`),
 | 
				
			||||||
@@ -481,22 +473,19 @@ func Test_getValidationOptions(t *testing.T) {
 | 
				
			|||||||
		want: certificateValidationOptions{
 | 
							want: certificateValidationOptions{
 | 
				
			||||||
			allowArbitraryCertificate: true,
 | 
								allowArbitraryCertificate: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "compatible update, existing unknown usages",
 | 
							name:   "compatible update, existing unknown usages",
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{Spec: capi.CertificateSigningRequestSpec{Usages: []capi.KeyUsage{"unknown"}}},
 | 
							oldCSR: &capi.CertificateSigningRequest{Spec: capi.CertificateSigningRequestSpec{Usages: []capi.KeyUsage{"unknown"}}},
 | 
				
			||||||
		want: certificateValidationOptions{
 | 
							want: certificateValidationOptions{
 | 
				
			||||||
			allowUnknownUsages: true,
 | 
								allowUnknownUsages: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "compatible update, existing duplicate usages",
 | 
							name:   "compatible update, existing duplicate usages",
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{Spec: capi.CertificateSigningRequestSpec{Usages: []capi.KeyUsage{"any", "any"}}},
 | 
							oldCSR: &capi.CertificateSigningRequest{Spec: capi.CertificateSigningRequestSpec{Usages: []capi.KeyUsage{"any", "any"}}},
 | 
				
			||||||
		want: certificateValidationOptions{
 | 
							want: certificateValidationOptions{
 | 
				
			||||||
			allowDuplicateUsages: true,
 | 
								allowDuplicateUsages: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tt := range tests {
 | 
						for _, tt := range tests {
 | 
				
			||||||
		t.Run(tt.name, func(t *testing.T) {
 | 
							t.Run(tt.name, func(t *testing.T) {
 | 
				
			||||||
			if got := getValidationOptions(tt.newCSR, tt.oldCSR); !reflect.DeepEqual(got, tt.want) {
 | 
								if got := getValidationOptions(tt.newCSR, tt.oldCSR); !reflect.DeepEqual(got, tt.want) {
 | 
				
			||||||
@@ -524,18 +513,15 @@ func TestValidateCertificateSigningRequestUpdate(t *testing.T) {
 | 
				
			|||||||
		newCSR *capi.CertificateSigningRequest
 | 
							newCSR *capi.CertificateSigningRequest
 | 
				
			||||||
		oldCSR *capi.CertificateSigningRequest
 | 
							oldCSR *capi.CertificateSigningRequest
 | 
				
			||||||
		errs   []string
 | 
							errs   []string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "no-op",
 | 
							name:   "no-op",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "finalizer change with invalid status",
 | 
							name:   "finalizer change with invalid status",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "add Approved condition",
 | 
							name: "add Approved condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved, Status: core.ConditionTrue}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved, Status: core.ConditionTrue}},
 | 
				
			||||||
@@ -544,8 +530,7 @@ func TestValidateCertificateSigningRequestUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not add a condition of type "Approved"`,
 | 
								`status.conditions: Forbidden: updates may not add a condition of type "Approved"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "remove Approved condition",
 | 
							name:   "remove Approved condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -554,8 +539,7 @@ func TestValidateCertificateSigningRequestUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not remove a condition of type "Approved"`,
 | 
								`status.conditions: Forbidden: updates may not remove a condition of type "Approved"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "add Denied condition",
 | 
							name: "add Denied condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateDenied, Status: core.ConditionTrue}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateDenied, Status: core.ConditionTrue}},
 | 
				
			||||||
@@ -564,8 +548,7 @@ func TestValidateCertificateSigningRequestUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not add a condition of type "Denied"`,
 | 
								`status.conditions: Forbidden: updates may not add a condition of type "Denied"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "remove Denied condition",
 | 
							name:   "remove Denied condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -574,16 +557,14 @@ func TestValidateCertificateSigningRequestUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not remove a condition of type "Denied"`,
 | 
								`status.conditions: Forbidden: updates may not remove a condition of type "Denied"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "add Failed condition",
 | 
							name: "add Failed condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateFailed, Status: core.ConditionTrue}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateFailed, Status: core.ConditionTrue}},
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
				
			||||||
		errs:   []string{},
 | 
							errs:   []string{},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "remove Failed condition",
 | 
							name:   "remove Failed condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -592,8 +573,7 @@ func TestValidateCertificateSigningRequestUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not remove a condition of type "Failed"`,
 | 
								`status.conditions: Forbidden: updates may not remove a condition of type "Failed"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "set certificate",
 | 
							name: "set certificate",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Certificate: validCertificate,
 | 
								Certificate: validCertificate,
 | 
				
			||||||
@@ -602,8 +582,7 @@ func TestValidateCertificateSigningRequestUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.certificate: Forbidden: updates may not set certificate content`,
 | 
								`status.certificate: Forbidden: updates may not set certificate content`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tt := range tests {
 | 
						for _, tt := range tests {
 | 
				
			||||||
		t.Run(tt.name, func(t *testing.T) {
 | 
							t.Run(tt.name, func(t *testing.T) {
 | 
				
			||||||
@@ -640,18 +619,15 @@ func TestValidateCertificateSigningRequestStatusUpdate(t *testing.T) {
 | 
				
			|||||||
		newCSR *capi.CertificateSigningRequest
 | 
							newCSR *capi.CertificateSigningRequest
 | 
				
			||||||
		oldCSR *capi.CertificateSigningRequest
 | 
							oldCSR *capi.CertificateSigningRequest
 | 
				
			||||||
		errs   []string
 | 
							errs   []string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "no-op",
 | 
							name:   "no-op",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "finalizer change with invalid status",
 | 
							name:   "finalizer change with invalid status",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "finalizer change with duplicate and unknown usages",
 | 
							name: "finalizer change with duplicate and unknown usages",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: capi.CertificateSigningRequestSpec{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: capi.CertificateSigningRequestSpec{
 | 
				
			||||||
			Usages:     []capi.KeyUsage{"unknown", "unknown"},
 | 
								Usages:     []capi.KeyUsage{"unknown", "unknown"},
 | 
				
			||||||
@@ -663,8 +639,7 @@ func TestValidateCertificateSigningRequestStatusUpdate(t *testing.T) {
 | 
				
			|||||||
			Request:    newCSRPEM(t),
 | 
								Request:    newCSRPEM(t),
 | 
				
			||||||
			SignerName: validSignerName,
 | 
								SignerName: validSignerName,
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "add Approved condition",
 | 
							name: "add Approved condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved, Status: core.ConditionTrue}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved, Status: core.ConditionTrue}},
 | 
				
			||||||
@@ -673,8 +648,7 @@ func TestValidateCertificateSigningRequestStatusUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not add a condition of type "Approved"`,
 | 
								`status.conditions: Forbidden: updates may not add a condition of type "Approved"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "remove Approved condition",
 | 
							name:   "remove Approved condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -683,8 +657,7 @@ func TestValidateCertificateSigningRequestStatusUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not remove a condition of type "Approved"`,
 | 
								`status.conditions: Forbidden: updates may not remove a condition of type "Approved"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "add Denied condition",
 | 
							name: "add Denied condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateDenied, Status: core.ConditionTrue}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateDenied, Status: core.ConditionTrue}},
 | 
				
			||||||
@@ -693,8 +666,7 @@ func TestValidateCertificateSigningRequestStatusUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not add a condition of type "Denied"`,
 | 
								`status.conditions: Forbidden: updates may not add a condition of type "Denied"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "remove Denied condition",
 | 
							name:   "remove Denied condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -703,16 +675,14 @@ func TestValidateCertificateSigningRequestStatusUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not remove a condition of type "Denied"`,
 | 
								`status.conditions: Forbidden: updates may not remove a condition of type "Denied"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "add Failed condition",
 | 
							name: "add Failed condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateFailed, Status: core.ConditionTrue}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateFailed, Status: core.ConditionTrue}},
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
				
			||||||
		errs:   []string{},
 | 
							errs:   []string{},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "remove Failed condition",
 | 
							name:   "remove Failed condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -721,16 +691,14 @@ func TestValidateCertificateSigningRequestStatusUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not remove a condition of type "Failed"`,
 | 
								`status.conditions: Forbidden: updates may not remove a condition of type "Failed"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "set valid certificate",
 | 
							name: "set valid certificate",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Certificate: validCertificate,
 | 
								Certificate: validCertificate,
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
				
			||||||
		errs:   []string{},
 | 
							errs:   []string{},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "set invalid certificate",
 | 
							name: "set invalid certificate",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Certificate: invalidCertificateNoPEM,
 | 
								Certificate: invalidCertificateNoPEM,
 | 
				
			||||||
@@ -739,8 +707,7 @@ func TestValidateCertificateSigningRequestStatusUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.certificate: Invalid value: "<certificate data>": must contain at least one CERTIFICATE PEM block`,
 | 
								`status.certificate: Invalid value: "<certificate data>": must contain at least one CERTIFICATE PEM block`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "reset certificate",
 | 
							name: "reset certificate",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Certificate: invalidCertificateNonCertificatePEM,
 | 
								Certificate: invalidCertificateNonCertificatePEM,
 | 
				
			||||||
@@ -751,8 +718,7 @@ func TestValidateCertificateSigningRequestStatusUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.certificate: Forbidden: updates may not modify existing certificate content`,
 | 
								`status.certificate: Forbidden: updates may not modify existing certificate content`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tt := range tests {
 | 
						for _, tt := range tests {
 | 
				
			||||||
		t.Run(tt.name, func(t *testing.T) {
 | 
							t.Run(tt.name, func(t *testing.T) {
 | 
				
			||||||
@@ -789,25 +755,21 @@ func TestValidateCertificateSigningRequestApprovalUpdate(t *testing.T) {
 | 
				
			|||||||
		newCSR *capi.CertificateSigningRequest
 | 
							newCSR *capi.CertificateSigningRequest
 | 
				
			||||||
		oldCSR *capi.CertificateSigningRequest
 | 
							oldCSR *capi.CertificateSigningRequest
 | 
				
			||||||
		errs   []string
 | 
							errs   []string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "no-op",
 | 
							name:   "no-op",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "finalizer change with invalid certificate",
 | 
							name:   "finalizer change with invalid certificate",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{Certificate: invalidCertificateNoPEM}},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "add Approved condition",
 | 
							name: "add Approved condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved, Status: core.ConditionTrue}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved, Status: core.ConditionTrue}},
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "remove Approved condition",
 | 
							name:   "remove Approved condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -816,15 +778,13 @@ func TestValidateCertificateSigningRequestApprovalUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not remove a condition of type "Approved"`,
 | 
								`status.conditions: Forbidden: updates may not remove a condition of type "Approved"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "add Denied condition",
 | 
							name: "add Denied condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateDenied, Status: core.ConditionTrue}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateDenied, Status: core.ConditionTrue}},
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "remove Denied condition",
 | 
							name:   "remove Denied condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -833,16 +793,14 @@ func TestValidateCertificateSigningRequestApprovalUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not remove a condition of type "Denied"`,
 | 
								`status.conditions: Forbidden: updates may not remove a condition of type "Denied"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "add Failed condition",
 | 
							name: "add Failed condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateFailed, Status: core.ConditionTrue}},
 | 
								Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateFailed, Status: core.ConditionTrue}},
 | 
				
			||||||
		}},
 | 
							}},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec},
 | 
				
			||||||
		errs:   []string{},
 | 
							errs:   []string{},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:   "remove Failed condition",
 | 
							name:   "remove Failed condition",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec},
 | 
				
			||||||
		oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							oldCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMetaWithFinalizers, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -851,8 +809,7 @@ func TestValidateCertificateSigningRequestApprovalUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.conditions: Forbidden: updates may not remove a condition of type "Failed"`,
 | 
								`status.conditions: Forbidden: updates may not remove a condition of type "Failed"`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "set certificate",
 | 
							name: "set certificate",
 | 
				
			||||||
		newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
							newCSR: &capi.CertificateSigningRequest{ObjectMeta: validUpdateMeta, Spec: validSpec, Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
			Certificate: validCertificate,
 | 
								Certificate: validCertificate,
 | 
				
			||||||
@@ -861,8 +818,7 @@ func TestValidateCertificateSigningRequestApprovalUpdate(t *testing.T) {
 | 
				
			|||||||
		errs: []string{
 | 
							errs: []string{
 | 
				
			||||||
			`status.certificate: Forbidden: updates may not set certificate content`,
 | 
								`status.certificate: Forbidden: updates may not set certificate content`,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tt := range tests {
 | 
						for _, tt := range tests {
 | 
				
			||||||
		t.Run(tt.name, func(t *testing.T) {
 | 
							t.Run(tt.name, func(t *testing.T) {
 | 
				
			||||||
@@ -909,32 +865,28 @@ func Test_validateCertificateSigningRequestOptions(t *testing.T) {
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			name: "no status",
 | 
								name: "no status",
 | 
				
			||||||
			csr:  &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec},
 | 
								csr:  &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec},
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "approved condition",
 | 
								name: "approved condition",
 | 
				
			||||||
			csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
								csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
				
			||||||
				Status: capi.CertificateSigningRequestStatus{
 | 
									Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
					Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved, Status: core.ConditionTrue}},
 | 
										Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateApproved, Status: core.ConditionTrue}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "denied condition",
 | 
								name: "denied condition",
 | 
				
			||||||
			csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
								csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
				
			||||||
				Status: capi.CertificateSigningRequestStatus{
 | 
									Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
					Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateDenied, Status: core.ConditionTrue}},
 | 
										Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateDenied, Status: core.ConditionTrue}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "failed condition",
 | 
								name: "failed condition",
 | 
				
			||||||
			csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
								csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
				
			||||||
				Status: capi.CertificateSigningRequestStatus{
 | 
									Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
					Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateFailed, Status: core.ConditionTrue}},
 | 
										Conditions: []capi.CertificateSigningRequestCondition{{Type: capi.CertificateFailed, Status: core.ConditionTrue}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "approved+issued",
 | 
								name: "approved+issued",
 | 
				
			||||||
			csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
								csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
				
			||||||
				Status: capi.CertificateSigningRequestStatus{
 | 
									Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -969,8 +921,7 @@ func Test_validateCertificateSigningRequestOptions(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			lenientOpts: certificateValidationOptions{allowEmptyConditionType: true},
 | 
								lenientOpts: certificateValidationOptions{allowEmptyConditionType: true},
 | 
				
			||||||
			strictErrs:  []string{`status.conditions[0].type: Required value`},
 | 
								strictErrs:  []string{`status.conditions[0].type: Required value`},
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "approved and denied",
 | 
								name: "approved and denied",
 | 
				
			||||||
			csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
								csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
				
			||||||
				Status: capi.CertificateSigningRequestStatus{
 | 
									Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -979,8 +930,7 @@ func Test_validateCertificateSigningRequestOptions(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			lenientOpts: certificateValidationOptions{allowBothApprovedAndDenied: true},
 | 
								lenientOpts: certificateValidationOptions{allowBothApprovedAndDenied: true},
 | 
				
			||||||
			strictErrs:  []string{`status.conditions[1].type: Invalid value: "Denied": Approved and Denied conditions are mutually exclusive`},
 | 
								strictErrs:  []string{`status.conditions[1].type: Invalid value: "Denied": Approved and Denied conditions are mutually exclusive`},
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "duplicate condition",
 | 
								name: "duplicate condition",
 | 
				
			||||||
			csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
								csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
				
			||||||
				Status: capi.CertificateSigningRequestStatus{
 | 
									Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -1002,8 +952,7 @@ func Test_validateCertificateSigningRequestOptions(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			lenientOpts: certificateValidationOptions{allowArbitraryCertificate: true},
 | 
								lenientOpts: certificateValidationOptions{allowArbitraryCertificate: true},
 | 
				
			||||||
			strictErrs:  []string{`status.certificate: Invalid value: "<certificate data>": must contain at least one CERTIFICATE PEM block`},
 | 
								strictErrs:  []string{`status.certificate: Invalid value: "<certificate data>": must contain at least one CERTIFICATE PEM block`},
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "status.certificate, non-CERTIFICATE PEM",
 | 
								name: "status.certificate, non-CERTIFICATE PEM",
 | 
				
			||||||
			csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
								csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
				
			||||||
				Status: capi.CertificateSigningRequestStatus{
 | 
									Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -1013,8 +962,7 @@ func Test_validateCertificateSigningRequestOptions(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			lenientOpts: certificateValidationOptions{allowArbitraryCertificate: true},
 | 
								lenientOpts: certificateValidationOptions{allowArbitraryCertificate: true},
 | 
				
			||||||
			strictErrs:  []string{`status.certificate: Invalid value: "<certificate data>": only CERTIFICATE PEM blocks are allowed, found "CERTIFICATE1"`},
 | 
								strictErrs:  []string{`status.certificate: Invalid value: "<certificate data>": only CERTIFICATE PEM blocks are allowed, found "CERTIFICATE1"`},
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "status.certificate, PEM headers",
 | 
								name: "status.certificate, PEM headers",
 | 
				
			||||||
			csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
								csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
				
			||||||
				Status: capi.CertificateSigningRequestStatus{
 | 
									Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -1024,8 +972,7 @@ func Test_validateCertificateSigningRequestOptions(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			lenientOpts: certificateValidationOptions{allowArbitraryCertificate: true},
 | 
								lenientOpts: certificateValidationOptions{allowArbitraryCertificate: true},
 | 
				
			||||||
			strictErrs:  []string{`status.certificate: Invalid value: "<certificate data>": no PEM block headers are permitted`},
 | 
								strictErrs:  []string{`status.certificate: Invalid value: "<certificate data>": no PEM block headers are permitted`},
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "status.certificate, non-base64 PEM",
 | 
								name: "status.certificate, non-base64 PEM",
 | 
				
			||||||
			csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
								csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
				
			||||||
				Status: capi.CertificateSigningRequestStatus{
 | 
									Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -1035,8 +982,7 @@ func Test_validateCertificateSigningRequestOptions(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			lenientOpts: certificateValidationOptions{allowArbitraryCertificate: true},
 | 
								lenientOpts: certificateValidationOptions{allowArbitraryCertificate: true},
 | 
				
			||||||
			strictErrs:  []string{`status.certificate: Invalid value: "<certificate data>": must contain at least one CERTIFICATE PEM block`},
 | 
								strictErrs:  []string{`status.certificate: Invalid value: "<certificate data>": must contain at least one CERTIFICATE PEM block`},
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "status.certificate, empty PEM block",
 | 
								name: "status.certificate, empty PEM block",
 | 
				
			||||||
			csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
								csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
				
			||||||
				Status: capi.CertificateSigningRequestStatus{
 | 
									Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -1046,8 +992,7 @@ func Test_validateCertificateSigningRequestOptions(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			lenientOpts: certificateValidationOptions{allowArbitraryCertificate: true},
 | 
								lenientOpts: certificateValidationOptions{allowArbitraryCertificate: true},
 | 
				
			||||||
			strictErrs:  []string{`status.certificate: Invalid value: "<certificate data>": found CERTIFICATE PEM block containing 0 certificates`},
 | 
								strictErrs:  []string{`status.certificate: Invalid value: "<certificate data>": found CERTIFICATE PEM block containing 0 certificates`},
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "status.certificate, non-ASN1 data",
 | 
								name: "status.certificate, non-ASN1 data",
 | 
				
			||||||
			csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
								csr: &capi.CertificateSigningRequest{ObjectMeta: validObjectMeta, Spec: validSpec,
 | 
				
			||||||
				Status: capi.CertificateSigningRequestStatus{
 | 
									Status: capi.CertificateSigningRequestStatus{
 | 
				
			||||||
@@ -1164,8 +1109,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		bundle      *capi.ClusterTrustBundle
 | 
							bundle      *capi.ClusterTrustBundle
 | 
				
			||||||
		opts        ValidateClusterTrustBundleOptions
 | 
							opts        ValidateClusterTrustBundleOptions
 | 
				
			||||||
		wantErrors  field.ErrorList
 | 
							wantErrors  field.ErrorList
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "valid, no signer name",
 | 
							description: "valid, no signer name",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1175,8 +1119,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
				TrustBundle: goodCert1Block,
 | 
									TrustBundle: goodCert1Block,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, no signer name, invalid name",
 | 
							description: "invalid, no signer name, invalid name",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1189,8 +1132,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("metadata", "name"), "k8s.io:bar:foo", "ClusterTrustBundle without signer name must not have \":\" in its name"),
 | 
								field.Invalid(field.NewPath("metadata", "name"), "k8s.io:bar:foo", "ClusterTrustBundle without signer name must not have \":\" in its name"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "valid, with signer name",
 | 
							description: "valid, with signer name",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1201,8 +1143,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
				TrustBundle: goodCert1Block,
 | 
									TrustBundle: goodCert1Block,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, with signer name, missing name prefix",
 | 
							description: "invalid, with signer name, missing name prefix",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1216,8 +1157,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("metadata", "name"), "look-ma-no-prefix", "ClusterTrustBundle for signerName k8s.io/foo must be named with prefix k8s.io:foo:"),
 | 
								field.Invalid(field.NewPath("metadata", "name"), "look-ma-no-prefix", "ClusterTrustBundle for signerName k8s.io/foo must be named with prefix k8s.io:foo:"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, with signer name, empty name suffix",
 | 
							description: "invalid, with signer name, empty name suffix",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1231,8 +1171,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("metadata", "name"), "k8s.io:foo:", `a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`),
 | 
								field.Invalid(field.NewPath("metadata", "name"), "k8s.io:foo:", `a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, with signer name, bad name suffix",
 | 
							description: "invalid, with signer name, bad name suffix",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1246,8 +1185,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("metadata", "name"), "k8s.io:foo:123notvalidDNSSubdomain", `a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`),
 | 
								field.Invalid(field.NewPath("metadata", "name"), "k8s.io:foo:123notvalidDNSSubdomain", `a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "valid, with signer name, with inter-block garbage",
 | 
							description: "valid, with signer name, with inter-block garbage",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1258,8 +1196,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
				TrustBundle: "garbage\n" + goodCert1Block + "\ngarbage\n" + goodCert2Block,
 | 
									TrustBundle: "garbage\n" + goodCert1Block + "\ngarbage\n" + goodCert2Block,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, no signer name, no trust anchors",
 | 
							description: "invalid, no signer name, no trust anchors",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1270,8 +1207,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "at least one trust anchor must be provided"),
 | 
								field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "at least one trust anchor must be provided"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, no trust anchors",
 | 
							description: "invalid, no trust anchors",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1284,8 +1220,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "at least one trust anchor must be provided"),
 | 
								field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "at least one trust anchor must be provided"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, bad signer name",
 | 
							description: "invalid, bad signer name",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1299,8 +1234,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "signerName"), "invalid", "must be a fully qualified domain and path of the form 'example.com/signer-name'"),
 | 
								field.Invalid(field.NewPath("spec", "signerName"), "invalid", "must be a fully qualified domain and path of the form 'example.com/signer-name'"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, no blocks",
 | 
							description: "invalid, no blocks",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1313,8 +1247,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "at least one trust anchor must be provided"),
 | 
								field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "at least one trust anchor must be provided"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, bad block type",
 | 
							description: "invalid, bad block type",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1327,8 +1260,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "entry 1 has bad block type: NOTACERTIFICATE"),
 | 
								field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "entry 1 has bad block type: NOTACERTIFICATE"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, block with headers",
 | 
							description: "invalid, block with headers",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1341,8 +1273,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "entry 1 has PEM block headers"),
 | 
								field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "entry 1 has PEM block headers"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, cert is not a CA cert",
 | 
							description: "invalid, cert is not a CA cert",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1355,8 +1286,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "entry 0 does not have the CA bit set"),
 | 
								field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "entry 0 does not have the CA bit set"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, duplicated blocks",
 | 
							description: "invalid, duplicated blocks",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1369,8 +1299,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "duplicate trust anchor (indices [0 1])"),
 | 
								field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "duplicate trust anchor (indices [0 1])"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "invalid, non-certificate entry",
 | 
							description: "invalid, non-certificate entry",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1383,8 +1312,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "entry 1 does not parse as X.509"),
 | 
								field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "entry 1 does not parse as X.509"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "allow any old garbage in the PEM field if we suppress parsing",
 | 
							description: "allow any old garbage in the PEM field if we suppress parsing",
 | 
				
			||||||
		bundle: &capi.ClusterTrustBundle{
 | 
							bundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1397,8 +1325,7 @@ func TestValidateClusterTrustBundle(t *testing.T) {
 | 
				
			|||||||
		opts: ValidateClusterTrustBundleOptions{
 | 
							opts: ValidateClusterTrustBundleOptions{
 | 
				
			||||||
			SuppressBundleParsing: true,
 | 
								SuppressBundleParsing: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range testCases {
 | 
						for _, tc := range testCases {
 | 
				
			||||||
		t.Run(tc.description, func(t *testing.T) {
 | 
							t.Run(tc.description, func(t *testing.T) {
 | 
				
			||||||
			gotErrors := ValidateClusterTrustBundle(tc.bundle, tc.opts)
 | 
								gotErrors := ValidateClusterTrustBundle(tc.bundle, tc.opts)
 | 
				
			||||||
@@ -1454,8 +1381,7 @@ func TestValidateClusterTrustBundleUpdate(t *testing.T) {
 | 
				
			|||||||
		description          string
 | 
							description          string
 | 
				
			||||||
		oldBundle, newBundle *capi.ClusterTrustBundle
 | 
							oldBundle, newBundle *capi.ClusterTrustBundle
 | 
				
			||||||
		wantErrors           field.ErrorList
 | 
							wantErrors           field.ErrorList
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "changing signer name disallowed",
 | 
							description: "changing signer name disallowed",
 | 
				
			||||||
		oldBundle: &capi.ClusterTrustBundle{
 | 
							oldBundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1479,8 +1405,7 @@ func TestValidateClusterTrustBundleUpdate(t *testing.T) {
 | 
				
			|||||||
			field.Invalid(field.NewPath("metadata", "name"), "k8s.io:foo:bar", "ClusterTrustBundle for signerName k8s.io/bar must be named with prefix k8s.io:bar:"),
 | 
								field.Invalid(field.NewPath("metadata", "name"), "k8s.io:foo:bar", "ClusterTrustBundle for signerName k8s.io/bar must be named with prefix k8s.io:bar:"),
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "signerName"), "k8s.io/bar", "field is immutable"),
 | 
								field.Invalid(field.NewPath("spec", "signerName"), "k8s.io/bar", "field is immutable"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "adding certificate allowed",
 | 
							description: "adding certificate allowed",
 | 
				
			||||||
		oldBundle: &capi.ClusterTrustBundle{
 | 
							oldBundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1500,8 +1425,7 @@ func TestValidateClusterTrustBundleUpdate(t *testing.T) {
 | 
				
			|||||||
				TrustBundle: goodCert1Block + "\n" + goodCert2Block,
 | 
									TrustBundle: goodCert1Block + "\n" + goodCert2Block,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "emptying trustBundle disallowed",
 | 
							description: "emptying trustBundle disallowed",
 | 
				
			||||||
		oldBundle: &capi.ClusterTrustBundle{
 | 
							oldBundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1524,8 +1448,7 @@ func TestValidateClusterTrustBundleUpdate(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "at least one trust anchor must be provided"),
 | 
								field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "at least one trust anchor must be provided"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description: "emptying trustBundle (replace with non-block garbage) disallowed",
 | 
							description: "emptying trustBundle (replace with non-block garbage) disallowed",
 | 
				
			||||||
		oldBundle: &capi.ClusterTrustBundle{
 | 
							oldBundle: &capi.ClusterTrustBundle{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
@@ -1548,8 +1471,7 @@ func TestValidateClusterTrustBundleUpdate(t *testing.T) {
 | 
				
			|||||||
		wantErrors: field.ErrorList{
 | 
							wantErrors: field.ErrorList{
 | 
				
			||||||
			field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "at least one trust anchor must be provided"),
 | 
								field.Invalid(field.NewPath("spec", "trustBundle"), "<value omitted>", "at least one trust anchor must be provided"),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range testCases {
 | 
						for _, tc := range testCases {
 | 
				
			||||||
		t.Run(tc.description, func(t *testing.T) {
 | 
							t.Run(tc.description, func(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,8 +31,7 @@ func TestValidateResourceRequirements(t *testing.T) {
 | 
				
			|||||||
	successCase := []struct {
 | 
						successCase := []struct {
 | 
				
			||||||
		name         string
 | 
							name         string
 | 
				
			||||||
		requirements v1.ResourceRequirements
 | 
							requirements v1.ResourceRequirements
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Resources with Requests equal to Limits",
 | 
							name: "Resources with Requests equal to Limits",
 | 
				
			||||||
		requirements: v1.ResourceRequirements{
 | 
							requirements: v1.ResourceRequirements{
 | 
				
			||||||
			Requests: v1.ResourceList{
 | 
								Requests: v1.ResourceList{
 | 
				
			||||||
@@ -44,8 +43,7 @@ func TestValidateResourceRequirements(t *testing.T) {
 | 
				
			|||||||
				v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"),
 | 
									v1.ResourceName(v1.ResourceMemory): resource.MustParse("10G"),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Resources with only Limits",
 | 
							name: "Resources with only Limits",
 | 
				
			||||||
		requirements: v1.ResourceRequirements{
 | 
							requirements: v1.ResourceRequirements{
 | 
				
			||||||
			Limits: v1.ResourceList{
 | 
								Limits: v1.ResourceList{
 | 
				
			||||||
@@ -54,8 +52,7 @@ func TestValidateResourceRequirements(t *testing.T) {
 | 
				
			|||||||
				v1.ResourceName("my.org/resource"): resource.MustParse("10"),
 | 
									v1.ResourceName("my.org/resource"): resource.MustParse("10"),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Resources with only Requests",
 | 
							name: "Resources with only Requests",
 | 
				
			||||||
		requirements: v1.ResourceRequirements{
 | 
							requirements: v1.ResourceRequirements{
 | 
				
			||||||
			Requests: v1.ResourceList{
 | 
								Requests: v1.ResourceList{
 | 
				
			||||||
@@ -64,8 +61,7 @@ func TestValidateResourceRequirements(t *testing.T) {
 | 
				
			|||||||
				v1.ResourceName("my.org/resource"): resource.MustParse("10"),
 | 
									v1.ResourceName("my.org/resource"): resource.MustParse("10"),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Resources with Requests Less Than Limits",
 | 
							name: "Resources with Requests Less Than Limits",
 | 
				
			||||||
		requirements: v1.ResourceRequirements{
 | 
							requirements: v1.ResourceRequirements{
 | 
				
			||||||
			Requests: v1.ResourceList{
 | 
								Requests: v1.ResourceList{
 | 
				
			||||||
@@ -79,8 +75,7 @@ func TestValidateResourceRequirements(t *testing.T) {
 | 
				
			|||||||
				v1.ResourceName("my.org/resource"): resource.MustParse("9"),
 | 
									v1.ResourceName("my.org/resource"): resource.MustParse("9"),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range successCase {
 | 
						for _, tc := range successCase {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
			if errs := ValidateResourceRequirements(&tc.requirements, field.NewPath("resources")); len(errs) != 0 {
 | 
								if errs := ValidateResourceRequirements(&tc.requirements, field.NewPath("resources")); len(errs) != 0 {
 | 
				
			||||||
@@ -94,8 +89,7 @@ func TestValidateResourceRequirements(t *testing.T) {
 | 
				
			|||||||
		requirements          v1.ResourceRequirements
 | 
							requirements          v1.ResourceRequirements
 | 
				
			||||||
		skipLimitValueCheck   bool
 | 
							skipLimitValueCheck   bool
 | 
				
			||||||
		skipRequestValueCheck bool
 | 
							skipRequestValueCheck bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Resources with Requests Larger Than Limits",
 | 
							name: "Resources with Requests Larger Than Limits",
 | 
				
			||||||
		requirements: v1.ResourceRequirements{
 | 
							requirements: v1.ResourceRequirements{
 | 
				
			||||||
			Requests: v1.ResourceList{
 | 
								Requests: v1.ResourceList{
 | 
				
			||||||
@@ -109,8 +103,7 @@ func TestValidateResourceRequirements(t *testing.T) {
 | 
				
			|||||||
				v1.ResourceName("my.org/resource"): resource.MustParse("9m"),
 | 
									v1.ResourceName("my.org/resource"): resource.MustParse("9m"),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Invalid Resources with Requests",
 | 
							name: "Invalid Resources with Requests",
 | 
				
			||||||
		requirements: v1.ResourceRequirements{
 | 
							requirements: v1.ResourceRequirements{
 | 
				
			||||||
			Requests: v1.ResourceList{
 | 
								Requests: v1.ResourceList{
 | 
				
			||||||
@@ -118,8 +111,7 @@ func TestValidateResourceRequirements(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		skipRequestValueCheck: true,
 | 
							skipRequestValueCheck: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Invalid Resources with Limits",
 | 
							name: "Invalid Resources with Limits",
 | 
				
			||||||
		requirements: v1.ResourceRequirements{
 | 
							requirements: v1.ResourceRequirements{
 | 
				
			||||||
			Limits: v1.ResourceList{
 | 
								Limits: v1.ResourceList{
 | 
				
			||||||
@@ -127,8 +119,7 @@ func TestValidateResourceRequirements(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		skipLimitValueCheck: true,
 | 
							skipLimitValueCheck: true,
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range errorCase {
 | 
						for _, tc := range errorCase {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
			errs := ValidateResourceRequirements(&tc.requirements, field.NewPath("resources"))
 | 
								errs := ValidateResourceRequirements(&tc.requirements, field.NewPath("resources"))
 | 
				
			||||||
@@ -168,28 +159,22 @@ func TestValidateContainerResourceName(t *testing.T) {
 | 
				
			|||||||
	successCase := []struct {
 | 
						successCase := []struct {
 | 
				
			||||||
		name         string
 | 
							name         string
 | 
				
			||||||
		ResourceName string
 | 
							ResourceName string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "CPU resource",
 | 
							name:         "CPU resource",
 | 
				
			||||||
		ResourceName: "cpu",
 | 
							ResourceName: "cpu",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "Memory resource",
 | 
							name:         "Memory resource",
 | 
				
			||||||
		ResourceName: "memory",
 | 
							ResourceName: "memory",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "Hugepages resource",
 | 
							name:         "Hugepages resource",
 | 
				
			||||||
		ResourceName: "hugepages-2Mi",
 | 
							ResourceName: "hugepages-2Mi",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "Namespaced resource",
 | 
							name:         "Namespaced resource",
 | 
				
			||||||
		ResourceName: "kubernetes.io/resource-foo",
 | 
							ResourceName: "kubernetes.io/resource-foo",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "Extended Resource",
 | 
							name:         "Extended Resource",
 | 
				
			||||||
		ResourceName: "my.org/resource-bar",
 | 
							ResourceName: "my.org/resource-bar",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range successCase {
 | 
						for _, tc := range successCase {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
			if errs := ValidateContainerResourceName(tc.ResourceName, field.NewPath(tc.ResourceName)); len(errs) != 0 {
 | 
								if errs := ValidateContainerResourceName(tc.ResourceName, field.NewPath(tc.ResourceName)); len(errs) != 0 {
 | 
				
			||||||
@@ -201,20 +186,16 @@ func TestValidateContainerResourceName(t *testing.T) {
 | 
				
			|||||||
	errorCase := []struct {
 | 
						errorCase := []struct {
 | 
				
			||||||
		name         string
 | 
							name         string
 | 
				
			||||||
		ResourceName string
 | 
							ResourceName string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "Invalid standard resource",
 | 
							name:         "Invalid standard resource",
 | 
				
			||||||
		ResourceName: "cpu-core",
 | 
							ResourceName: "cpu-core",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "Invalid namespaced resource",
 | 
							name:         "Invalid namespaced resource",
 | 
				
			||||||
		ResourceName: "kubernetes.io/",
 | 
							ResourceName: "kubernetes.io/",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "Invalid extended resource",
 | 
							name:         "Invalid extended resource",
 | 
				
			||||||
		ResourceName: "my.org-foo-resource",
 | 
							ResourceName: "my.org-foo-resource",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range errorCase {
 | 
						for _, tc := range errorCase {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
			if errs := ValidateContainerResourceName(tc.ResourceName, field.NewPath(tc.ResourceName)); len(errs) == 0 {
 | 
								if errs := ValidateContainerResourceName(tc.ResourceName, field.NewPath(tc.ResourceName)); len(errs) == 0 {
 | 
				
			||||||
@@ -239,45 +220,38 @@ func TestValidatePodLogOptions(t *testing.T) {
 | 
				
			|||||||
	successCase := []struct {
 | 
						successCase := []struct {
 | 
				
			||||||
		name          string
 | 
							name          string
 | 
				
			||||||
		podLogOptions v1.PodLogOptions
 | 
							podLogOptions v1.PodLogOptions
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:          "Empty PodLogOptions",
 | 
							name:          "Empty PodLogOptions",
 | 
				
			||||||
		podLogOptions: v1.PodLogOptions{},
 | 
							podLogOptions: v1.PodLogOptions{},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "PodLogOptions with TailLines",
 | 
							name: "PodLogOptions with TailLines",
 | 
				
			||||||
		podLogOptions: v1.PodLogOptions{
 | 
							podLogOptions: v1.PodLogOptions{
 | 
				
			||||||
			TailLines: &positiveLine,
 | 
								TailLines: &positiveLine,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "PodLogOptions with LimitBytes",
 | 
							name: "PodLogOptions with LimitBytes",
 | 
				
			||||||
		podLogOptions: v1.PodLogOptions{
 | 
							podLogOptions: v1.PodLogOptions{
 | 
				
			||||||
			LimitBytes: &limitBytesGreaterThan1,
 | 
								LimitBytes: &limitBytesGreaterThan1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "PodLogOptions with only sinceSeconds",
 | 
							name: "PodLogOptions with only sinceSeconds",
 | 
				
			||||||
		podLogOptions: v1.PodLogOptions{
 | 
							podLogOptions: v1.PodLogOptions{
 | 
				
			||||||
			SinceSeconds: &sinceSecondsGreaterThan1,
 | 
								SinceSeconds: &sinceSecondsGreaterThan1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "PodLogOptions with LimitBytes with TailLines",
 | 
							name: "PodLogOptions with LimitBytes with TailLines",
 | 
				
			||||||
		podLogOptions: v1.PodLogOptions{
 | 
							podLogOptions: v1.PodLogOptions{
 | 
				
			||||||
			LimitBytes: &limitBytesGreaterThan1,
 | 
								LimitBytes: &limitBytesGreaterThan1,
 | 
				
			||||||
			TailLines:  &positiveLine,
 | 
								TailLines:  &positiveLine,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "PodLogOptions with LimitBytes with TailLines with SinceSeconds",
 | 
							name: "PodLogOptions with LimitBytes with TailLines with SinceSeconds",
 | 
				
			||||||
		podLogOptions: v1.PodLogOptions{
 | 
							podLogOptions: v1.PodLogOptions{
 | 
				
			||||||
			LimitBytes:   &limitBytesGreaterThan1,
 | 
								LimitBytes:   &limitBytesGreaterThan1,
 | 
				
			||||||
			TailLines:    &positiveLine,
 | 
								TailLines:    &positiveLine,
 | 
				
			||||||
			SinceSeconds: &sinceSecondsGreaterThan1,
 | 
								SinceSeconds: &sinceSecondsGreaterThan1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range successCase {
 | 
						for _, tc := range successCase {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
			if errs := ValidatePodLogOptions(&tc.podLogOptions); len(errs) != 0 {
 | 
								if errs := ValidatePodLogOptions(&tc.podLogOptions); len(errs) != 0 {
 | 
				
			||||||
@@ -289,24 +263,21 @@ func TestValidatePodLogOptions(t *testing.T) {
 | 
				
			|||||||
	errorCase := []struct {
 | 
						errorCase := []struct {
 | 
				
			||||||
		name          string
 | 
							name          string
 | 
				
			||||||
		podLogOptions v1.PodLogOptions
 | 
							podLogOptions v1.PodLogOptions
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Invalid podLogOptions with Negative TailLines",
 | 
							name: "Invalid podLogOptions with Negative TailLines",
 | 
				
			||||||
		podLogOptions: v1.PodLogOptions{
 | 
							podLogOptions: v1.PodLogOptions{
 | 
				
			||||||
			TailLines:    &negativeLine,
 | 
								TailLines:    &negativeLine,
 | 
				
			||||||
			LimitBytes:   &limitBytesGreaterThan1,
 | 
								LimitBytes:   &limitBytesGreaterThan1,
 | 
				
			||||||
			SinceSeconds: &sinceSecondsGreaterThan1,
 | 
								SinceSeconds: &sinceSecondsGreaterThan1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Invalid podLogOptions with zero or negative LimitBytes",
 | 
							name: "Invalid podLogOptions with zero or negative LimitBytes",
 | 
				
			||||||
		podLogOptions: v1.PodLogOptions{
 | 
							podLogOptions: v1.PodLogOptions{
 | 
				
			||||||
			TailLines:    &positiveLine,
 | 
								TailLines:    &positiveLine,
 | 
				
			||||||
			LimitBytes:   &limitBytesLessThan1,
 | 
								LimitBytes:   &limitBytesLessThan1,
 | 
				
			||||||
			SinceSeconds: &sinceSecondsGreaterThan1,
 | 
								SinceSeconds: &sinceSecondsGreaterThan1,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Invalid podLogOptions with zero or negative SinceSeconds",
 | 
							name: "Invalid podLogOptions with zero or negative SinceSeconds",
 | 
				
			||||||
		podLogOptions: v1.PodLogOptions{
 | 
							podLogOptions: v1.PodLogOptions{
 | 
				
			||||||
			TailLines:    &negativeLine,
 | 
								TailLines:    &negativeLine,
 | 
				
			||||||
@@ -321,8 +292,7 @@ func TestValidatePodLogOptions(t *testing.T) {
 | 
				
			|||||||
			SinceSeconds: &sinceSecondsGreaterThan1,
 | 
								SinceSeconds: &sinceSecondsGreaterThan1,
 | 
				
			||||||
			SinceTime:    ×tamp,
 | 
								SinceTime:    ×tamp,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range errorCase {
 | 
						for _, tc := range errorCase {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
			if errs := ValidatePodLogOptions(&tc.podLogOptions); len(errs) == 0 {
 | 
								if errs := ValidatePodLogOptions(&tc.podLogOptions); len(errs) == 0 {
 | 
				
			||||||
@@ -338,54 +308,37 @@ func TestAccumulateUniqueHostPorts(t *testing.T) {
 | 
				
			|||||||
		containers  []v1.Container
 | 
							containers  []v1.Container
 | 
				
			||||||
		accumulator *sets.String
 | 
							accumulator *sets.String
 | 
				
			||||||
		fldPath     *field.Path
 | 
							fldPath     *field.Path
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "HostPort is not allocated while containers use the same port with different protocol",
 | 
							name: "HostPort is not allocated while containers use the same port with different protocol",
 | 
				
			||||||
			containers: []v1.Container{
 | 
							containers: []v1.Container{{
 | 
				
			||||||
				{
 | 
								Ports: []v1.ContainerPort{{
 | 
				
			||||||
					Ports: []v1.ContainerPort{
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
				HostPort: 8080,
 | 
									HostPort: 8080,
 | 
				
			||||||
				Protocol: v1.ProtocolUDP,
 | 
									Protocol: v1.ProtocolUDP,
 | 
				
			||||||
						},
 | 
								}},
 | 
				
			||||||
					},
 | 
							}, {
 | 
				
			||||||
				},
 | 
								Ports: []v1.ContainerPort{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					Ports: []v1.ContainerPort{
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
				HostPort: 8080,
 | 
									HostPort: 8080,
 | 
				
			||||||
				Protocol: v1.ProtocolTCP,
 | 
									Protocol: v1.ProtocolTCP,
 | 
				
			||||||
						},
 | 
								}},
 | 
				
			||||||
					},
 | 
							}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		accumulator: &sets.String{},
 | 
							accumulator: &sets.String{},
 | 
				
			||||||
		fldPath:     field.NewPath("spec", "containers"),
 | 
							fldPath:     field.NewPath("spec", "containers"),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "HostPort is not allocated while containers use different ports",
 | 
							name: "HostPort is not allocated while containers use different ports",
 | 
				
			||||||
			containers: []v1.Container{
 | 
							containers: []v1.Container{{
 | 
				
			||||||
				{
 | 
								Ports: []v1.ContainerPort{{
 | 
				
			||||||
					Ports: []v1.ContainerPort{
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
				HostPort: 8080,
 | 
									HostPort: 8080,
 | 
				
			||||||
				Protocol: v1.ProtocolUDP,
 | 
									Protocol: v1.ProtocolUDP,
 | 
				
			||||||
						},
 | 
								}},
 | 
				
			||||||
					},
 | 
							}, {
 | 
				
			||||||
				},
 | 
								Ports: []v1.ContainerPort{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					Ports: []v1.ContainerPort{
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
				HostPort: 8081,
 | 
									HostPort: 8081,
 | 
				
			||||||
				Protocol: v1.ProtocolUDP,
 | 
									Protocol: v1.ProtocolUDP,
 | 
				
			||||||
						},
 | 
								}},
 | 
				
			||||||
					},
 | 
							}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		accumulator: &sets.String{},
 | 
							accumulator: &sets.String{},
 | 
				
			||||||
		fldPath:     field.NewPath("spec", "containers"),
 | 
							fldPath:     field.NewPath("spec", "containers"),
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range successCase {
 | 
						for _, tc := range successCase {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
			if errs := AccumulateUniqueHostPorts(tc.containers, tc.accumulator, tc.fldPath); len(errs) != 0 {
 | 
								if errs := AccumulateUniqueHostPorts(tc.containers, tc.accumulator, tc.fldPath); len(errs) != 0 {
 | 
				
			||||||
@@ -398,54 +351,37 @@ func TestAccumulateUniqueHostPorts(t *testing.T) {
 | 
				
			|||||||
		containers  []v1.Container
 | 
							containers  []v1.Container
 | 
				
			||||||
		accumulator *sets.String
 | 
							accumulator *sets.String
 | 
				
			||||||
		fldPath     *field.Path
 | 
							fldPath     *field.Path
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "HostPort is already allocated while containers use the same port with UDP",
 | 
							name: "HostPort is already allocated while containers use the same port with UDP",
 | 
				
			||||||
			containers: []v1.Container{
 | 
							containers: []v1.Container{{
 | 
				
			||||||
				{
 | 
								Ports: []v1.ContainerPort{{
 | 
				
			||||||
					Ports: []v1.ContainerPort{
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
				HostPort: 8080,
 | 
									HostPort: 8080,
 | 
				
			||||||
				Protocol: v1.ProtocolUDP,
 | 
									Protocol: v1.ProtocolUDP,
 | 
				
			||||||
						},
 | 
								}},
 | 
				
			||||||
					},
 | 
							}, {
 | 
				
			||||||
				},
 | 
								Ports: []v1.ContainerPort{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					Ports: []v1.ContainerPort{
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
				HostPort: 8080,
 | 
									HostPort: 8080,
 | 
				
			||||||
				Protocol: v1.ProtocolUDP,
 | 
									Protocol: v1.ProtocolUDP,
 | 
				
			||||||
						},
 | 
								}},
 | 
				
			||||||
					},
 | 
							}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		accumulator: &sets.String{},
 | 
							accumulator: &sets.String{},
 | 
				
			||||||
		fldPath:     field.NewPath("spec", "containers"),
 | 
							fldPath:     field.NewPath("spec", "containers"),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "HostPort is already allocated",
 | 
							name: "HostPort is already allocated",
 | 
				
			||||||
			containers: []v1.Container{
 | 
							containers: []v1.Container{{
 | 
				
			||||||
				{
 | 
								Ports: []v1.ContainerPort{{
 | 
				
			||||||
					Ports: []v1.ContainerPort{
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
				HostPort: 8080,
 | 
									HostPort: 8080,
 | 
				
			||||||
				Protocol: v1.ProtocolUDP,
 | 
									Protocol: v1.ProtocolUDP,
 | 
				
			||||||
						},
 | 
								}},
 | 
				
			||||||
					},
 | 
							}, {
 | 
				
			||||||
				},
 | 
								Ports: []v1.ContainerPort{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					Ports: []v1.ContainerPort{
 | 
					 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
				HostPort: 8081,
 | 
									HostPort: 8081,
 | 
				
			||||||
				Protocol: v1.ProtocolUDP,
 | 
									Protocol: v1.ProtocolUDP,
 | 
				
			||||||
						},
 | 
								}},
 | 
				
			||||||
					},
 | 
							}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		accumulator: &sets.String{"8080/UDP": sets.Empty{}},
 | 
							accumulator: &sets.String{"8080/UDP": sets.Empty{}},
 | 
				
			||||||
		fldPath:     field.NewPath("spec", "containers"),
 | 
							fldPath:     field.NewPath("spec", "containers"),
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range errorCase {
 | 
						for _, tc := range errorCase {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
			if errs := AccumulateUniqueHostPorts(tc.containers, tc.accumulator, tc.fldPath); len(errs) == 0 {
 | 
								if errs := AccumulateUniqueHostPorts(tc.containers, tc.accumulator, tc.fldPath); len(errs) == 0 {
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -477,22 +477,18 @@ func TestValidateIngress(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		Spec: networking.IngressSpec{
 | 
							Spec: networking.IngressSpec{
 | 
				
			||||||
			DefaultBackend: &defaultBackend,
 | 
								DefaultBackend: &defaultBackend,
 | 
				
			||||||
			Rules: []networking.IngressRule{
 | 
								Rules: []networking.IngressRule{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				Host: "foo.bar.com",
 | 
									Host: "foo.bar.com",
 | 
				
			||||||
				IngressRuleValue: networking.IngressRuleValue{
 | 
									IngressRuleValue: networking.IngressRuleValue{
 | 
				
			||||||
					HTTP: &networking.HTTPIngressRuleValue{
 | 
										HTTP: &networking.HTTPIngressRuleValue{
 | 
				
			||||||
							Paths: []networking.HTTPIngressPath{
 | 
											Paths: []networking.HTTPIngressPath{{
 | 
				
			||||||
								{
 | 
					 | 
				
			||||||
							Path:     "/foo",
 | 
												Path:     "/foo",
 | 
				
			||||||
							PathType: &pathTypeImplementationSpecific,
 | 
												PathType: &pathTypeImplementationSpecific,
 | 
				
			||||||
							Backend:  defaultBackend,
 | 
												Backend:  defaultBackend,
 | 
				
			||||||
 | 
											}},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
						},
 | 
								}},
 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		Status: networking.IngressStatus{
 | 
							Status: networking.IngressStatus{
 | 
				
			||||||
			LoadBalancer: networking.IngressLoadBalancerStatus{
 | 
								LoadBalancer: networking.IngressLoadBalancerStatus{
 | 
				
			||||||
@@ -595,8 +591,7 @@ func TestValidateIngress(t *testing.T) {
 | 
				
			|||||||
			tweakIngress: func(ing *networking.Ingress) {
 | 
								tweakIngress: func(ing *networking.Ingress) {
 | 
				
			||||||
				ing.Spec.Rules[0].IngressRuleValue = networking.IngressRuleValue{
 | 
									ing.Spec.Rules[0].IngressRuleValue = networking.IngressRuleValue{
 | 
				
			||||||
					HTTP: &networking.HTTPIngressRuleValue{
 | 
										HTTP: &networking.HTTPIngressRuleValue{
 | 
				
			||||||
						Paths: []networking.HTTPIngressPath{
 | 
											Paths: []networking.HTTPIngressPath{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Path:     "/foo",
 | 
												Path:     "/foo",
 | 
				
			||||||
							PathType: &pathTypeImplementationSpecific,
 | 
												PathType: &pathTypeImplementationSpecific,
 | 
				
			||||||
							Backend: networking.IngressBackend{
 | 
												Backend: networking.IngressBackend{
 | 
				
			||||||
@@ -607,8 +602,7 @@ func TestValidateIngress(t *testing.T) {
 | 
				
			|||||||
									Name:     "bar",
 | 
														Name:     "bar",
 | 
				
			||||||
								},
 | 
													},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -620,8 +614,7 @@ func TestValidateIngress(t *testing.T) {
 | 
				
			|||||||
			tweakIngress: func(ing *networking.Ingress) {
 | 
								tweakIngress: func(ing *networking.Ingress) {
 | 
				
			||||||
				ing.Spec.Rules[0].IngressRuleValue = networking.IngressRuleValue{
 | 
									ing.Spec.Rules[0].IngressRuleValue = networking.IngressRuleValue{
 | 
				
			||||||
					HTTP: &networking.HTTPIngressRuleValue{
 | 
										HTTP: &networking.HTTPIngressRuleValue{
 | 
				
			||||||
						Paths: []networking.HTTPIngressPath{
 | 
											Paths: []networking.HTTPIngressPath{{
 | 
				
			||||||
							{
 | 
					 | 
				
			||||||
							Path:     "/foo",
 | 
												Path:     "/foo",
 | 
				
			||||||
							PathType: &pathTypeImplementationSpecific,
 | 
												PathType: &pathTypeImplementationSpecific,
 | 
				
			||||||
							Backend: networking.IngressBackend{
 | 
												Backend: networking.IngressBackend{
 | 
				
			||||||
@@ -632,8 +625,7 @@ func TestValidateIngress(t *testing.T) {
 | 
				
			|||||||
									Name:     "bar",
 | 
														Name:     "bar",
 | 
				
			||||||
								},
 | 
													},
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							},
 | 
											}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -790,15 +782,13 @@ func TestValidateIngressRuleValue(t *testing.T) {
 | 
				
			|||||||
		t.Run(name, func(t *testing.T) {
 | 
							t.Run(name, func(t *testing.T) {
 | 
				
			||||||
			irv := &networking.IngressRuleValue{
 | 
								irv := &networking.IngressRuleValue{
 | 
				
			||||||
				HTTP: &networking.HTTPIngressRuleValue{
 | 
									HTTP: &networking.HTTPIngressRuleValue{
 | 
				
			||||||
					Paths: []networking.HTTPIngressPath{
 | 
										Paths: []networking.HTTPIngressPath{{
 | 
				
			||||||
						{
 | 
					 | 
				
			||||||
						Path:     testCase.path,
 | 
											Path:     testCase.path,
 | 
				
			||||||
						PathType: &testCase.pathType,
 | 
											PathType: &testCase.pathType,
 | 
				
			||||||
						Backend: networking.IngressBackend{
 | 
											Backend: networking.IngressBackend{
 | 
				
			||||||
							Service: &serviceBackend,
 | 
												Service: &serviceBackend,
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
						},
 | 
										}},
 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			errs := validateIngressRuleValue(irv, field.NewPath("testing"), IngressValidationOptions{})
 | 
								errs := validateIngressRuleValue(irv, field.NewPath("testing"), IngressValidationOptions{})
 | 
				
			||||||
@@ -1638,22 +1628,18 @@ func TestValidateIngressTLS(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			Spec: networking.IngressSpec{
 | 
								Spec: networking.IngressSpec{
 | 
				
			||||||
				DefaultBackend: &defaultBackend,
 | 
									DefaultBackend: &defaultBackend,
 | 
				
			||||||
				Rules: []networking.IngressRule{
 | 
									Rules: []networking.IngressRule{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
					Host: "foo.bar.com",
 | 
										Host: "foo.bar.com",
 | 
				
			||||||
					IngressRuleValue: networking.IngressRuleValue{
 | 
										IngressRuleValue: networking.IngressRuleValue{
 | 
				
			||||||
						HTTP: &networking.HTTPIngressRuleValue{
 | 
											HTTP: &networking.HTTPIngressRuleValue{
 | 
				
			||||||
								Paths: []networking.HTTPIngressPath{
 | 
												Paths: []networking.HTTPIngressPath{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								Path:     "/foo",
 | 
													Path:     "/foo",
 | 
				
			||||||
								PathType: &pathTypeImplementationSpecific,
 | 
													PathType: &pathTypeImplementationSpecific,
 | 
				
			||||||
								Backend:  defaultBackend,
 | 
													Backend:  defaultBackend,
 | 
				
			||||||
 | 
												}},
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
							},
 | 
									}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Status: networking.IngressStatus{
 | 
								Status: networking.IngressStatus{
 | 
				
			||||||
				LoadBalancer: networking.IngressLoadBalancerStatus{
 | 
									LoadBalancer: networking.IngressLoadBalancerStatus{
 | 
				
			||||||
@@ -1670,11 +1656,9 @@ func TestValidateIngressTLS(t *testing.T) {
 | 
				
			|||||||
	wildcardHost := "foo.*.bar.com"
 | 
						wildcardHost := "foo.*.bar.com"
 | 
				
			||||||
	badWildcardTLS := newValid()
 | 
						badWildcardTLS := newValid()
 | 
				
			||||||
	badWildcardTLS.Spec.Rules[0].Host = "*.foo.bar.com"
 | 
						badWildcardTLS.Spec.Rules[0].Host = "*.foo.bar.com"
 | 
				
			||||||
	badWildcardTLS.Spec.TLS = []networking.IngressTLS{
 | 
						badWildcardTLS.Spec.TLS = []networking.IngressTLS{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Hosts: []string{wildcardHost},
 | 
							Hosts: []string{wildcardHost},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	badWildcardTLSErr := fmt.Sprintf("spec.tls[0].hosts[0]: Invalid value: '%v'", wildcardHost)
 | 
						badWildcardTLSErr := fmt.Sprintf("spec.tls[0].hosts[0]: Invalid value: '%v'", wildcardHost)
 | 
				
			||||||
	errorCases[badWildcardTLSErr] = badWildcardTLS
 | 
						errorCases[badWildcardTLSErr] = badWildcardTLS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1696,11 +1680,9 @@ func TestValidateIngressTLS(t *testing.T) {
 | 
				
			|||||||
	wildHost := "*.bar.com"
 | 
						wildHost := "*.bar.com"
 | 
				
			||||||
	goodWildcardTLS := newValid()
 | 
						goodWildcardTLS := newValid()
 | 
				
			||||||
	goodWildcardTLS.Spec.Rules[0].Host = "*.bar.com"
 | 
						goodWildcardTLS.Spec.Rules[0].Host = "*.bar.com"
 | 
				
			||||||
	goodWildcardTLS.Spec.TLS = []networking.IngressTLS{
 | 
						goodWildcardTLS.Spec.TLS = []networking.IngressTLS{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Hosts: []string{wildHost},
 | 
							Hosts: []string{wildHost},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	validCases[fmt.Sprintf("spec.tls[0].hosts: Valid value: '%v'", wildHost)] = goodWildcardTLS
 | 
						validCases[fmt.Sprintf("spec.tls[0].hosts: Valid value: '%v'", wildHost)] = goodWildcardTLS
 | 
				
			||||||
	for k, v := range validCases {
 | 
						for k, v := range validCases {
 | 
				
			||||||
		errs := validateIngress(&v, IngressValidationOptions{})
 | 
							errs := validateIngress(&v, IngressValidationOptions{})
 | 
				
			||||||
@@ -1731,21 +1713,17 @@ func TestValidateEmptyIngressTLS(t *testing.T) {
 | 
				
			|||||||
				Namespace: metav1.NamespaceDefault,
 | 
									Namespace: metav1.NamespaceDefault,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Spec: networking.IngressSpec{
 | 
								Spec: networking.IngressSpec{
 | 
				
			||||||
				Rules: []networking.IngressRule{
 | 
									Rules: []networking.IngressRule{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
					Host: "foo.bar.com",
 | 
										Host: "foo.bar.com",
 | 
				
			||||||
					IngressRuleValue: networking.IngressRuleValue{
 | 
										IngressRuleValue: networking.IngressRuleValue{
 | 
				
			||||||
						HTTP: &networking.HTTPIngressRuleValue{
 | 
											HTTP: &networking.HTTPIngressRuleValue{
 | 
				
			||||||
								Paths: []networking.HTTPIngressPath{
 | 
												Paths: []networking.HTTPIngressPath{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								PathType: &pathTypeImplementationSpecific,
 | 
													PathType: &pathTypeImplementationSpecific,
 | 
				
			||||||
								Backend:  defaultBackend,
 | 
													Backend:  defaultBackend,
 | 
				
			||||||
 | 
												}},
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
							},
 | 
									}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -1757,11 +1735,9 @@ func TestValidateEmptyIngressTLS(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	validCases[fmt.Sprintf("spec.tls[0]: Valid value: %v", goodEmptyTLS.Spec.TLS[0])] = goodEmptyTLS
 | 
						validCases[fmt.Sprintf("spec.tls[0]: Valid value: %v", goodEmptyTLS.Spec.TLS[0])] = goodEmptyTLS
 | 
				
			||||||
	goodEmptyHosts := newValid()
 | 
						goodEmptyHosts := newValid()
 | 
				
			||||||
	goodEmptyHosts.Spec.TLS = []networking.IngressTLS{
 | 
						goodEmptyHosts.Spec.TLS = []networking.IngressTLS{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Hosts: []string{},
 | 
							Hosts: []string{},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	validCases[fmt.Sprintf("spec.tls[0]: Valid value: %v", goodEmptyHosts.Spec.TLS[0])] = goodEmptyHosts
 | 
						validCases[fmt.Sprintf("spec.tls[0]: Valid value: %v", goodEmptyHosts.Spec.TLS[0])] = goodEmptyHosts
 | 
				
			||||||
	for k, v := range validCases {
 | 
						for k, v := range validCases {
 | 
				
			||||||
		errs := validateIngress(&v, IngressValidationOptions{})
 | 
							errs := validateIngress(&v, IngressValidationOptions{})
 | 
				
			||||||
@@ -1791,21 +1767,17 @@ func TestValidateIngressStatusUpdate(t *testing.T) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			Spec: networking.IngressSpec{
 | 
								Spec: networking.IngressSpec{
 | 
				
			||||||
				DefaultBackend: &defaultBackend,
 | 
									DefaultBackend: &defaultBackend,
 | 
				
			||||||
				Rules: []networking.IngressRule{
 | 
									Rules: []networking.IngressRule{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
					Host: "foo.bar.com",
 | 
										Host: "foo.bar.com",
 | 
				
			||||||
					IngressRuleValue: networking.IngressRuleValue{
 | 
										IngressRuleValue: networking.IngressRuleValue{
 | 
				
			||||||
						HTTP: &networking.HTTPIngressRuleValue{
 | 
											HTTP: &networking.HTTPIngressRuleValue{
 | 
				
			||||||
								Paths: []networking.HTTPIngressPath{
 | 
												Paths: []networking.HTTPIngressPath{{
 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
								Path:    "/foo",
 | 
													Path:    "/foo",
 | 
				
			||||||
								Backend: defaultBackend,
 | 
													Backend: defaultBackend,
 | 
				
			||||||
 | 
												}},
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
							},
 | 
									}},
 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Status: networking.IngressStatus{
 | 
								Status: networking.IngressStatus{
 | 
				
			||||||
				LoadBalancer: networking.IngressLoadBalancerStatus{
 | 
									LoadBalancer: networking.IngressLoadBalancerStatus{
 | 
				
			||||||
@@ -1867,17 +1839,13 @@ func TestValidateIngressStatusUpdate(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func makeNodeSelector(key string, op api.NodeSelectorOperator, values []string) *api.NodeSelector {
 | 
					func makeNodeSelector(key string, op api.NodeSelectorOperator, values []string) *api.NodeSelector {
 | 
				
			||||||
	return &api.NodeSelector{
 | 
						return &api.NodeSelector{
 | 
				
			||||||
		NodeSelectorTerms: []api.NodeSelectorTerm{
 | 
							NodeSelectorTerms: []api.NodeSelectorTerm{{
 | 
				
			||||||
			{
 | 
								MatchExpressions: []api.NodeSelectorRequirement{{
 | 
				
			||||||
				MatchExpressions: []api.NodeSelectorRequirement{
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Key:      key,
 | 
									Key:      key,
 | 
				
			||||||
				Operator: op,
 | 
									Operator: op,
 | 
				
			||||||
				Values:   values,
 | 
									Values:   values,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1901,48 +1869,39 @@ func TestValidateClusterCIDR(t *testing.T) {
 | 
				
			|||||||
		name      string
 | 
							name      string
 | 
				
			||||||
		cc        *networking.ClusterCIDR
 | 
							cc        *networking.ClusterCIDR
 | 
				
			||||||
		expectErr bool
 | 
							expectErr bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "valid SingleStack IPv4 ClusterCIDR",
 | 
							name:      "valid SingleStack IPv4 ClusterCIDR",
 | 
				
			||||||
		cc:        makeClusterCIDR(8, "10.1.0.0/16", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(8, "10.1.0.0/16", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "valid SingleStack IPv4 ClusterCIDR, perNodeHostBits = maxPerNodeHostBits",
 | 
							name:      "valid SingleStack IPv4 ClusterCIDR, perNodeHostBits = maxPerNodeHostBits",
 | 
				
			||||||
		cc:        makeClusterCIDR(16, "10.1.0.0/16", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(16, "10.1.0.0/16", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "valid SingleStack IPv4 ClusterCIDR, perNodeHostBits > minPerNodeHostBits",
 | 
							name:      "valid SingleStack IPv4 ClusterCIDR, perNodeHostBits > minPerNodeHostBits",
 | 
				
			||||||
		cc:        makeClusterCIDR(4, "10.1.0.0/16", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(4, "10.1.0.0/16", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "valid SingleStack IPv6 ClusterCIDR",
 | 
							name:      "valid SingleStack IPv6 ClusterCIDR",
 | 
				
			||||||
		cc:        makeClusterCIDR(8, "", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(8, "", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "valid SingleStack IPv6 ClusterCIDR, perNodeHostBits = maxPerNodeHostBit",
 | 
							name:      "valid SingleStack IPv6 ClusterCIDR, perNodeHostBits = maxPerNodeHostBit",
 | 
				
			||||||
		cc:        makeClusterCIDR(64, "", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(64, "", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "valid SingleStack IPv6 ClusterCIDR, perNodeHostBits > minPerNodeHostBit",
 | 
							name:      "valid SingleStack IPv6 ClusterCIDR, perNodeHostBits > minPerNodeHostBit",
 | 
				
			||||||
		cc:        makeClusterCIDR(4, "", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(4, "", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "valid SingleStack IPv6 ClusterCIDR perNodeHostBits=100",
 | 
							name:      "valid SingleStack IPv6 ClusterCIDR perNodeHostBits=100",
 | 
				
			||||||
		cc:        makeClusterCIDR(100, "", "fd00:1:1::/16", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(100, "", "fd00:1:1::/16", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "valid DualStack ClusterCIDR",
 | 
							name:      "valid DualStack ClusterCIDR",
 | 
				
			||||||
		cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "valid DualStack ClusterCIDR, no NodeSelector",
 | 
							name:      "valid DualStack ClusterCIDR, no NodeSelector",
 | 
				
			||||||
		cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:1:1::/64", nil),
 | 
							cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:1:1::/64", nil),
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
@@ -1952,8 +1911,7 @@ func TestValidateClusterCIDR(t *testing.T) {
 | 
				
			|||||||
			name:      "invalid ClusterCIDR, no IPv4 or IPv6 CIDR",
 | 
								name:      "invalid ClusterCIDR, no IPv4 or IPv6 CIDR",
 | 
				
			||||||
			cc:        makeClusterCIDR(8, "", "", nil),
 | 
								cc:        makeClusterCIDR(8, "", "", nil),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:      "invalid ClusterCIDR, invalid nodeSelector",
 | 
								name:      "invalid ClusterCIDR, invalid nodeSelector",
 | 
				
			||||||
			cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("NoUppercaseOrSpecialCharsLike=Equals", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("NoUppercaseOrSpecialCharsLike=Equals", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
@@ -1963,13 +1921,11 @@ func TestValidateClusterCIDR(t *testing.T) {
 | 
				
			|||||||
			name:      "invalid SingleStack IPv4 ClusterCIDR, invalid spec.IPv4",
 | 
								name:      "invalid SingleStack IPv4 ClusterCIDR, invalid spec.IPv4",
 | 
				
			||||||
			cc:        makeClusterCIDR(8, "test", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(8, "test", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:      "invalid Singlestack IPv4 ClusterCIDR, perNodeHostBits > maxPerNodeHostBits",
 | 
								name:      "invalid Singlestack IPv4 ClusterCIDR, perNodeHostBits > maxPerNodeHostBits",
 | 
				
			||||||
			cc:        makeClusterCIDR(100, "10.1.0.0/16", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(100, "10.1.0.0/16", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:      "invalid SingleStack IPv4 ClusterCIDR, perNodeHostBits < minPerNodeHostBits",
 | 
								name:      "invalid SingleStack IPv4 ClusterCIDR, perNodeHostBits < minPerNodeHostBits",
 | 
				
			||||||
			cc:        makeClusterCIDR(2, "10.1.0.0/16", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(2, "10.1.0.0/16", "", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
@@ -1979,18 +1935,15 @@ func TestValidateClusterCIDR(t *testing.T) {
 | 
				
			|||||||
			name:      "invalid SingleStack IPv6 ClusterCIDR, invalid spec.IPv6",
 | 
								name:      "invalid SingleStack IPv6 ClusterCIDR, invalid spec.IPv6",
 | 
				
			||||||
			cc:        makeClusterCIDR(8, "", "testv6", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(8, "", "testv6", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:      "invalid SingleStack IPv6 ClusterCIDR, valid IPv4 CIDR in spec.IPv6",
 | 
								name:      "invalid SingleStack IPv6 ClusterCIDR, valid IPv4 CIDR in spec.IPv6",
 | 
				
			||||||
			cc:        makeClusterCIDR(8, "", "10.2.0.0/16", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(8, "", "10.2.0.0/16", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:      "invalid SingleStack IPv6 ClusterCIDR, invalid perNodeHostBits > maxPerNodeHostBits",
 | 
								name:      "invalid SingleStack IPv6 ClusterCIDR, invalid perNodeHostBits > maxPerNodeHostBits",
 | 
				
			||||||
			cc:        makeClusterCIDR(12, "", "fd00::/120", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(12, "", "fd00::/120", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:      "invalid SingleStack IPv6 ClusterCIDR, invalid perNodeHostBits < minPerNodeHostBits",
 | 
								name:      "invalid SingleStack IPv6 ClusterCIDR, invalid perNodeHostBits < minPerNodeHostBits",
 | 
				
			||||||
			cc:        makeClusterCIDR(3, "", "fd00::/120", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(3, "", "fd00::/120", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
@@ -2000,18 +1953,15 @@ func TestValidateClusterCIDR(t *testing.T) {
 | 
				
			|||||||
			name:      "invalid DualStack ClusterCIDR, valid spec.IPv4, invalid spec.IPv6",
 | 
								name:      "invalid DualStack ClusterCIDR, valid spec.IPv4, invalid spec.IPv6",
 | 
				
			||||||
			cc:        makeClusterCIDR(8, "10.1.0.0/16", "testv6", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(8, "10.1.0.0/16", "testv6", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:      "invalid DualStack ClusterCIDR, valid spec.IPv6, invalid spec.IPv4",
 | 
								name:      "invalid DualStack ClusterCIDR, valid spec.IPv6, invalid spec.IPv4",
 | 
				
			||||||
			cc:        makeClusterCIDR(8, "testv4", "fd00::/120", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(8, "testv4", "fd00::/120", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:      "invalid DualStack ClusterCIDR, invalid perNodeHostBits > maxPerNodeHostBits",
 | 
								name:      "invalid DualStack ClusterCIDR, invalid perNodeHostBits > maxPerNodeHostBits",
 | 
				
			||||||
			cc:        makeClusterCIDR(24, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(24, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name:      "invalid DualStack ClusterCIDR, valid IPv6 CIDR in spec.IPv4",
 | 
								name:      "invalid DualStack ClusterCIDR, valid IPv6 CIDR in spec.IPv4",
 | 
				
			||||||
			cc:        makeClusterCIDR(8, "fd00::/120", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
								cc:        makeClusterCIDR(8, "fd00::/120", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
			expectErr: true,
 | 
								expectErr: true,
 | 
				
			||||||
@@ -2038,33 +1988,27 @@ func TestValidateClusterConfigUpdate(t *testing.T) {
 | 
				
			|||||||
		name      string
 | 
							name      string
 | 
				
			||||||
		cc        *networking.ClusterCIDR
 | 
							cc        *networking.ClusterCIDR
 | 
				
			||||||
		expectErr bool
 | 
							expectErr bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "Successful update, no changes to ClusterCIDR.Spec",
 | 
							name:      "Successful update, no changes to ClusterCIDR.Spec",
 | 
				
			||||||
		cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "Failed update, update spec.PerNodeHostBits",
 | 
							name:      "Failed update, update spec.PerNodeHostBits",
 | 
				
			||||||
		cc:        makeClusterCIDR(12, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(12, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: true,
 | 
							expectErr: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "Failed update, update spec.IPv4",
 | 
							name:      "Failed update, update spec.IPv4",
 | 
				
			||||||
		cc:        makeClusterCIDR(8, "10.2.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(8, "10.2.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: true,
 | 
							expectErr: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "Failed update, update spec.IPv6",
 | 
							name:      "Failed update, update spec.IPv6",
 | 
				
			||||||
		cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:2:/112", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
							cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:2:/112", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar"})),
 | 
				
			||||||
		expectErr: true,
 | 
							expectErr: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:      "Failed update, update spec.NodeSelector",
 | 
							name:      "Failed update, update spec.NodeSelector",
 | 
				
			||||||
		cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar2"})),
 | 
							cc:        makeClusterCIDR(8, "10.1.0.0/16", "fd00:1:1::/64", makeNodeSelector("foo", api.NodeSelectorOpIn, []string{"bar2"})),
 | 
				
			||||||
		expectErr: true,
 | 
							expectErr: true,
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, testCase := range testCases {
 | 
						for _, testCase := range testCases {
 | 
				
			||||||
		t.Run(testCase.name, func(t *testing.T) {
 | 
							t.Run(testCase.name, func(t *testing.T) {
 | 
				
			||||||
			err := ValidateClusterCIDRUpdate(testCase.cc, oldCCC)
 | 
								err := ValidateClusterCIDRUpdate(testCase.cc, oldCCC)
 | 
				
			||||||
@@ -2244,8 +2188,7 @@ func TestValidateIPAddressUpdate(t *testing.T) {
 | 
				
			|||||||
		name      string
 | 
							name      string
 | 
				
			||||||
		new       func(svc *networking.IPAddress) *networking.IPAddress
 | 
							new       func(svc *networking.IPAddress) *networking.IPAddress
 | 
				
			||||||
		expectErr bool
 | 
							expectErr bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Successful update, no changes",
 | 
							name: "Successful update, no changes",
 | 
				
			||||||
		new: func(old *networking.IPAddress) *networking.IPAddress {
 | 
							new: func(old *networking.IPAddress) *networking.IPAddress {
 | 
				
			||||||
			out := old.DeepCopy()
 | 
								out := old.DeepCopy()
 | 
				
			||||||
@@ -2267,8 +2210,7 @@ func TestValidateIPAddressUpdate(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
				return out
 | 
									return out
 | 
				
			||||||
			}, expectErr: true,
 | 
								}, expectErr: true,
 | 
				
			||||||
		},
 | 
							}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "Failed update, delete spec.ParentRef",
 | 
								name: "Failed update, delete spec.ParentRef",
 | 
				
			||||||
			new: func(svc *networking.IPAddress) *networking.IPAddress {
 | 
								new: func(svc *networking.IPAddress) *networking.IPAddress {
 | 
				
			||||||
				out := svc.DeepCopy()
 | 
									out := svc.DeepCopy()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -134,8 +134,7 @@ func TestValidateOverhead(t *testing.T) {
 | 
				
			|||||||
	successCase := []struct {
 | 
						successCase := []struct {
 | 
				
			||||||
		Name     string
 | 
							Name     string
 | 
				
			||||||
		overhead *node.Overhead
 | 
							overhead *node.Overhead
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "Overhead with valid cpu and memory resources",
 | 
							Name: "Overhead with valid cpu and memory resources",
 | 
				
			||||||
		overhead: &node.Overhead{
 | 
							overhead: &node.Overhead{
 | 
				
			||||||
			PodFixed: core.ResourceList{
 | 
								PodFixed: core.ResourceList{
 | 
				
			||||||
@@ -143,8 +142,7 @@ func TestValidateOverhead(t *testing.T) {
 | 
				
			|||||||
				core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
 | 
									core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range successCase {
 | 
						for _, tc := range successCase {
 | 
				
			||||||
		rc := &node.RuntimeClass{
 | 
							rc := &node.RuntimeClass{
 | 
				
			||||||
@@ -160,16 +158,14 @@ func TestValidateOverhead(t *testing.T) {
 | 
				
			|||||||
	errorCase := []struct {
 | 
						errorCase := []struct {
 | 
				
			||||||
		Name     string
 | 
							Name     string
 | 
				
			||||||
		overhead *node.Overhead
 | 
							overhead *node.Overhead
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "Invalid Resources",
 | 
							Name: "Invalid Resources",
 | 
				
			||||||
		overhead: &node.Overhead{
 | 
							overhead: &node.Overhead{
 | 
				
			||||||
			PodFixed: core.ResourceList{
 | 
								PodFixed: core.ResourceList{
 | 
				
			||||||
				core.ResourceName("my.org"): resource.MustParse("10m"),
 | 
									core.ResourceName("my.org"): resource.MustParse("10m"),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range errorCase {
 | 
						for _, tc := range errorCase {
 | 
				
			||||||
		rc := &node.RuntimeClass{
 | 
							rc := &node.RuntimeClass{
 | 
				
			||||||
			ObjectMeta: metav1.ObjectMeta{Name: "foo"},
 | 
								ObjectMeta: metav1.ObjectMeta{Name: "foo"},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,40 +107,35 @@ func TestValidateUnhealthyPodEvictionPolicyDisruptionBudgetSpec(t *testing.T) {
 | 
				
			|||||||
		name      string
 | 
							name      string
 | 
				
			||||||
		pdbSpec   policy.PodDisruptionBudgetSpec
 | 
							pdbSpec   policy.PodDisruptionBudgetSpec
 | 
				
			||||||
		expectErr bool
 | 
							expectErr bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid nil UnhealthyPodEvictionPolicy",
 | 
							name: "valid nil UnhealthyPodEvictionPolicy",
 | 
				
			||||||
		pdbSpec: policy.PodDisruptionBudgetSpec{
 | 
							pdbSpec: policy.PodDisruptionBudgetSpec{
 | 
				
			||||||
			MinAvailable:               &c1,
 | 
								MinAvailable:               &c1,
 | 
				
			||||||
			UnhealthyPodEvictionPolicy: nil,
 | 
								UnhealthyPodEvictionPolicy: nil,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid UnhealthyPodEvictionPolicy",
 | 
							name: "valid UnhealthyPodEvictionPolicy",
 | 
				
			||||||
		pdbSpec: policy.PodDisruptionBudgetSpec{
 | 
							pdbSpec: policy.PodDisruptionBudgetSpec{
 | 
				
			||||||
			MinAvailable:               &c1,
 | 
								MinAvailable:               &c1,
 | 
				
			||||||
			UnhealthyPodEvictionPolicy: &alwaysAllowPolicy,
 | 
								UnhealthyPodEvictionPolicy: &alwaysAllowPolicy,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErr: false,
 | 
							expectErr: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "empty UnhealthyPodEvictionPolicy",
 | 
							name: "empty UnhealthyPodEvictionPolicy",
 | 
				
			||||||
		pdbSpec: policy.PodDisruptionBudgetSpec{
 | 
							pdbSpec: policy.PodDisruptionBudgetSpec{
 | 
				
			||||||
			MinAvailable:               &c1,
 | 
								MinAvailable:               &c1,
 | 
				
			||||||
			UnhealthyPodEvictionPolicy: new(policy.UnhealthyPodEvictionPolicyType),
 | 
								UnhealthyPodEvictionPolicy: new(policy.UnhealthyPodEvictionPolicyType),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErr: true,
 | 
							expectErr: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid UnhealthyPodEvictionPolicy",
 | 
							name: "invalid UnhealthyPodEvictionPolicy",
 | 
				
			||||||
		pdbSpec: policy.PodDisruptionBudgetSpec{
 | 
							pdbSpec: policy.PodDisruptionBudgetSpec{
 | 
				
			||||||
			MinAvailable:               &c1,
 | 
								MinAvailable:               &c1,
 | 
				
			||||||
			UnhealthyPodEvictionPolicy: &invalidPolicy,
 | 
								UnhealthyPodEvictionPolicy: &invalidPolicy,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErr: true,
 | 
							expectErr: true,
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range testCases {
 | 
						for _, tc := range testCases {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
@@ -162,8 +157,7 @@ func TestValidatePodDisruptionBudgetStatus(t *testing.T) {
 | 
				
			|||||||
		name                string
 | 
							name                string
 | 
				
			||||||
		pdbStatus           policy.PodDisruptionBudgetStatus
 | 
							pdbStatus           policy.PodDisruptionBudgetStatus
 | 
				
			||||||
		expectErrForVersion map[schema.GroupVersion]bool
 | 
							expectErrForVersion map[schema.GroupVersion]bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "DisruptionsAllowed: 10",
 | 
							name: "DisruptionsAllowed: 10",
 | 
				
			||||||
		pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
							pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
				
			||||||
			DisruptionsAllowed: 10,
 | 
								DisruptionsAllowed: 10,
 | 
				
			||||||
@@ -172,8 +166,7 @@ func TestValidatePodDisruptionBudgetStatus(t *testing.T) {
 | 
				
			|||||||
			policy.SchemeGroupVersion:        expectNoErrors,
 | 
								policy.SchemeGroupVersion:        expectNoErrors,
 | 
				
			||||||
			policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
								policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "CurrentHealthy: 5",
 | 
							name: "CurrentHealthy: 5",
 | 
				
			||||||
		pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
							pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
				
			||||||
			CurrentHealthy: 5,
 | 
								CurrentHealthy: 5,
 | 
				
			||||||
@@ -182,8 +175,7 @@ func TestValidatePodDisruptionBudgetStatus(t *testing.T) {
 | 
				
			|||||||
			policy.SchemeGroupVersion:        expectNoErrors,
 | 
								policy.SchemeGroupVersion:        expectNoErrors,
 | 
				
			||||||
			policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
								policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "DesiredHealthy: 3",
 | 
							name: "DesiredHealthy: 3",
 | 
				
			||||||
		pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
							pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
				
			||||||
			DesiredHealthy: 3,
 | 
								DesiredHealthy: 3,
 | 
				
			||||||
@@ -192,8 +184,7 @@ func TestValidatePodDisruptionBudgetStatus(t *testing.T) {
 | 
				
			|||||||
			policy.SchemeGroupVersion:        expectNoErrors,
 | 
								policy.SchemeGroupVersion:        expectNoErrors,
 | 
				
			||||||
			policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
								policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "ExpectedPods: 2",
 | 
							name: "ExpectedPods: 2",
 | 
				
			||||||
		pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
							pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
				
			||||||
			ExpectedPods: 2,
 | 
								ExpectedPods: 2,
 | 
				
			||||||
@@ -202,8 +193,7 @@ func TestValidatePodDisruptionBudgetStatus(t *testing.T) {
 | 
				
			|||||||
			policy.SchemeGroupVersion:        expectNoErrors,
 | 
								policy.SchemeGroupVersion:        expectNoErrors,
 | 
				
			||||||
			policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
								policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "DisruptionsAllowed: -10",
 | 
							name: "DisruptionsAllowed: -10",
 | 
				
			||||||
		pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
							pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
				
			||||||
			DisruptionsAllowed: -10,
 | 
								DisruptionsAllowed: -10,
 | 
				
			||||||
@@ -212,8 +202,7 @@ func TestValidatePodDisruptionBudgetStatus(t *testing.T) {
 | 
				
			|||||||
			policy.SchemeGroupVersion:        expectErrors,
 | 
								policy.SchemeGroupVersion:        expectErrors,
 | 
				
			||||||
			policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
								policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "CurrentHealthy: -5",
 | 
							name: "CurrentHealthy: -5",
 | 
				
			||||||
		pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
							pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
				
			||||||
			CurrentHealthy: -5,
 | 
								CurrentHealthy: -5,
 | 
				
			||||||
@@ -222,8 +211,7 @@ func TestValidatePodDisruptionBudgetStatus(t *testing.T) {
 | 
				
			|||||||
			policy.SchemeGroupVersion:        expectErrors,
 | 
								policy.SchemeGroupVersion:        expectErrors,
 | 
				
			||||||
			policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
								policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "DesiredHealthy: -3",
 | 
							name: "DesiredHealthy: -3",
 | 
				
			||||||
		pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
							pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
				
			||||||
			DesiredHealthy: -3,
 | 
								DesiredHealthy: -3,
 | 
				
			||||||
@@ -232,8 +220,7 @@ func TestValidatePodDisruptionBudgetStatus(t *testing.T) {
 | 
				
			|||||||
			policy.SchemeGroupVersion:        expectErrors,
 | 
								policy.SchemeGroupVersion:        expectErrors,
 | 
				
			||||||
			policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
								policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "ExpectedPods: -2",
 | 
							name: "ExpectedPods: -2",
 | 
				
			||||||
		pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
							pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
				
			||||||
			ExpectedPods: -2,
 | 
								ExpectedPods: -2,
 | 
				
			||||||
@@ -242,12 +229,10 @@ func TestValidatePodDisruptionBudgetStatus(t *testing.T) {
 | 
				
			|||||||
			policy.SchemeGroupVersion:        expectErrors,
 | 
								policy.SchemeGroupVersion:        expectErrors,
 | 
				
			||||||
			policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
								policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Conditions valid",
 | 
							name: "Conditions valid",
 | 
				
			||||||
		pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
							pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
				
			||||||
				Conditions: []metav1.Condition{
 | 
								Conditions: []metav1.Condition{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:   policyv1beta1.DisruptionAllowedCondition,
 | 
									Type:   policyv1beta1.DisruptionAllowedCondition,
 | 
				
			||||||
				Status: metav1.ConditionTrue,
 | 
									Status: metav1.ConditionTrue,
 | 
				
			||||||
				LastTransitionTime: metav1.Time{
 | 
									LastTransitionTime: metav1.Time{
 | 
				
			||||||
@@ -256,34 +241,28 @@ func TestValidatePodDisruptionBudgetStatus(t *testing.T) {
 | 
				
			|||||||
				Reason:             policyv1beta1.SufficientPodsReason,
 | 
									Reason:             policyv1beta1.SufficientPodsReason,
 | 
				
			||||||
				Message:            "message",
 | 
									Message:            "message",
 | 
				
			||||||
				ObservedGeneration: 3,
 | 
									ObservedGeneration: 3,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErrForVersion: map[schema.GroupVersion]bool{
 | 
							expectErrForVersion: map[schema.GroupVersion]bool{
 | 
				
			||||||
			policy.SchemeGroupVersion:        expectNoErrors,
 | 
								policy.SchemeGroupVersion:        expectNoErrors,
 | 
				
			||||||
			policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
								policyv1beta1.SchemeGroupVersion: expectNoErrors,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Conditions not valid",
 | 
							name: "Conditions not valid",
 | 
				
			||||||
		pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
							pdbStatus: policy.PodDisruptionBudgetStatus{
 | 
				
			||||||
				Conditions: []metav1.Condition{
 | 
								Conditions: []metav1.Condition{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:   policyv1beta1.DisruptionAllowedCondition,
 | 
									Type:   policyv1beta1.DisruptionAllowedCondition,
 | 
				
			||||||
				Status: metav1.ConditionTrue,
 | 
									Status: metav1.ConditionTrue,
 | 
				
			||||||
					},
 | 
								}, {
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:   policyv1beta1.DisruptionAllowedCondition,
 | 
									Type:   policyv1beta1.DisruptionAllowedCondition,
 | 
				
			||||||
				Status: metav1.ConditionFalse,
 | 
									Status: metav1.ConditionFalse,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErrForVersion: map[schema.GroupVersion]bool{
 | 
							expectErrForVersion: map[schema.GroupVersion]bool{
 | 
				
			||||||
			policy.SchemeGroupVersion:        expectErrors,
 | 
								policy.SchemeGroupVersion:        expectErrors,
 | 
				
			||||||
			policyv1beta1.SchemeGroupVersion: expectErrors,
 | 
								policyv1beta1.SchemeGroupVersion: expectErrors,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range testCases {
 | 
						for _, tc := range testCases {
 | 
				
			||||||
		for apiVersion, expectErrors := range tc.expectErrForVersion {
 | 
							for apiVersion, expectErrors := range tc.expectErrForVersion {
 | 
				
			||||||
@@ -1165,23 +1144,19 @@ func TestAllowEphemeralVolumeType(t *testing.T) {
 | 
				
			|||||||
		description      string
 | 
							description      string
 | 
				
			||||||
		hasGenericVolume bool
 | 
							hasGenericVolume bool
 | 
				
			||||||
		psp              func() *policy.PodSecurityPolicy
 | 
							psp              func() *policy.PodSecurityPolicy
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description:      "PodSecurityPolicySpec Without GenericVolume",
 | 
							description:      "PodSecurityPolicySpec Without GenericVolume",
 | 
				
			||||||
		hasGenericVolume: false,
 | 
							hasGenericVolume: false,
 | 
				
			||||||
		psp:              pspWithoutGenericVolume,
 | 
							psp:              pspWithoutGenericVolume,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description:      "PodSecurityPolicySpec With GenericVolume",
 | 
							description:      "PodSecurityPolicySpec With GenericVolume",
 | 
				
			||||||
		hasGenericVolume: true,
 | 
							hasGenericVolume: true,
 | 
				
			||||||
		psp:              pspWithGenericVolume,
 | 
							psp:              pspWithGenericVolume,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		description:      "is nil",
 | 
							description:      "is nil",
 | 
				
			||||||
		hasGenericVolume: false,
 | 
							hasGenericVolume: false,
 | 
				
			||||||
		psp:              pspNil,
 | 
							psp:              pspNil,
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, oldPSPInfo := range pspInfo {
 | 
						for _, oldPSPInfo := range pspInfo {
 | 
				
			||||||
		for _, newPSPInfo := range pspInfo {
 | 
							for _, newPSPInfo := range pspInfo {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -402,12 +402,10 @@ func TestValidateRoleNonResourceURL(t *testing.T) {
 | 
				
			|||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
				Name: "default",
 | 
									Name: "default",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Rules: []rbac.PolicyRule{
 | 
								Rules: []rbac.PolicyRule{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				Verbs:           []string{"get"},
 | 
									Verbs:           []string{"get"},
 | 
				
			||||||
				NonResourceURLs: []string{"/*"},
 | 
									NonResourceURLs: []string{"/*"},
 | 
				
			||||||
				},
 | 
								}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		wantErr: false,
 | 
							wantErr: false,
 | 
				
			||||||
	}.test(t)
 | 
						}.test(t)
 | 
				
			||||||
@@ -420,13 +418,11 @@ func TestValidateRoleNamespacedNonResourceURL(t *testing.T) {
 | 
				
			|||||||
				Namespace: "default",
 | 
									Namespace: "default",
 | 
				
			||||||
				Name:      "default",
 | 
									Name:      "default",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Rules: []rbac.PolicyRule{
 | 
								Rules: []rbac.PolicyRule{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				// non-resource URLs are invalid for namespaced rules
 | 
									// non-resource URLs are invalid for namespaced rules
 | 
				
			||||||
				Verbs:           []string{"get"},
 | 
									Verbs:           []string{"get"},
 | 
				
			||||||
				NonResourceURLs: []string{"/*"},
 | 
									NonResourceURLs: []string{"/*"},
 | 
				
			||||||
				},
 | 
								}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		wantErr: true,
 | 
							wantErr: true,
 | 
				
			||||||
		errType: field.ErrorTypeInvalid,
 | 
							errType: field.ErrorTypeInvalid,
 | 
				
			||||||
@@ -440,12 +436,10 @@ func TestValidateRoleNonResourceURLNoVerbs(t *testing.T) {
 | 
				
			|||||||
			ObjectMeta: metav1.ObjectMeta{
 | 
								ObjectMeta: metav1.ObjectMeta{
 | 
				
			||||||
				Name: "default",
 | 
									Name: "default",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Rules: []rbac.PolicyRule{
 | 
								Rules: []rbac.PolicyRule{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				Verbs:           []string{},
 | 
									Verbs:           []string{},
 | 
				
			||||||
				NonResourceURLs: []string{"/*"},
 | 
									NonResourceURLs: []string{"/*"},
 | 
				
			||||||
				},
 | 
								}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		wantErr: true,
 | 
							wantErr: true,
 | 
				
			||||||
		errType: field.ErrorTypeRequired,
 | 
							errType: field.ErrorTypeRequired,
 | 
				
			||||||
@@ -460,14 +454,12 @@ func TestValidateRoleMixedNonResourceAndResource(t *testing.T) {
 | 
				
			|||||||
				Name:      "default",
 | 
									Name:      "default",
 | 
				
			||||||
				Namespace: "default",
 | 
									Namespace: "default",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Rules: []rbac.PolicyRule{
 | 
								Rules: []rbac.PolicyRule{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				Verbs:           []string{"get"},
 | 
									Verbs:           []string{"get"},
 | 
				
			||||||
				NonResourceURLs: []string{"/*"},
 | 
									NonResourceURLs: []string{"/*"},
 | 
				
			||||||
				APIGroups:       []string{"v1"},
 | 
									APIGroups:       []string{"v1"},
 | 
				
			||||||
				Resources:       []string{"pods"},
 | 
									Resources:       []string{"pods"},
 | 
				
			||||||
				},
 | 
								}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		wantErr: true,
 | 
							wantErr: true,
 | 
				
			||||||
		errType: field.ErrorTypeInvalid,
 | 
							errType: field.ErrorTypeInvalid,
 | 
				
			||||||
@@ -482,13 +474,11 @@ func TestValidateRoleValidResource(t *testing.T) {
 | 
				
			|||||||
				Name:      "default",
 | 
									Name:      "default",
 | 
				
			||||||
				Namespace: "default",
 | 
									Namespace: "default",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Rules: []rbac.PolicyRule{
 | 
								Rules: []rbac.PolicyRule{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				Verbs:     []string{"get"},
 | 
									Verbs:     []string{"get"},
 | 
				
			||||||
				APIGroups: []string{"v1"},
 | 
									APIGroups: []string{"v1"},
 | 
				
			||||||
				Resources: []string{"pods"},
 | 
									Resources: []string{"pods"},
 | 
				
			||||||
				},
 | 
								}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		wantErr: false,
 | 
							wantErr: false,
 | 
				
			||||||
	}.test(t)
 | 
						}.test(t)
 | 
				
			||||||
@@ -501,12 +491,10 @@ func TestValidateRoleNoAPIGroup(t *testing.T) {
 | 
				
			|||||||
				Name:      "default",
 | 
									Name:      "default",
 | 
				
			||||||
				Namespace: "default",
 | 
									Namespace: "default",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Rules: []rbac.PolicyRule{
 | 
								Rules: []rbac.PolicyRule{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				Verbs:     []string{"get"},
 | 
									Verbs:     []string{"get"},
 | 
				
			||||||
				Resources: []string{"pods"},
 | 
									Resources: []string{"pods"},
 | 
				
			||||||
				},
 | 
								}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		wantErr: true,
 | 
							wantErr: true,
 | 
				
			||||||
		errType: field.ErrorTypeRequired,
 | 
							errType: field.ErrorTypeRequired,
 | 
				
			||||||
@@ -521,12 +509,10 @@ func TestValidateRoleNoResources(t *testing.T) {
 | 
				
			|||||||
				Name:      "default",
 | 
									Name:      "default",
 | 
				
			||||||
				Namespace: "default",
 | 
									Namespace: "default",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Rules: []rbac.PolicyRule{
 | 
								Rules: []rbac.PolicyRule{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
				Verbs:     []string{"get"},
 | 
									Verbs:     []string{"get"},
 | 
				
			||||||
				APIGroups: []string{"v1"},
 | 
									APIGroups: []string{"v1"},
 | 
				
			||||||
				},
 | 
								}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		wantErr: true,
 | 
							wantErr: true,
 | 
				
			||||||
		errType: field.ErrorTypeRequired,
 | 
							errType: field.ErrorTypeRequired,
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -86,22 +86,19 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
		name      string
 | 
							name      string
 | 
				
			||||||
		configure func(config *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration
 | 
							configure func(config *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration
 | 
				
			||||||
		errMsg    string
 | 
							errMsg    string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Success",
 | 
							name: "Success",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid NodeLeaseDurationSeconds",
 | 
							name: "invalid NodeLeaseDurationSeconds",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.NodeLeaseDurationSeconds = 0
 | 
								conf.NodeLeaseDurationSeconds = 0
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: nodeLeaseDurationSeconds must be greater than 0",
 | 
							errMsg: "invalid configuration: nodeLeaseDurationSeconds must be greater than 0",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify EnforceNodeAllocatable without enabling CgroupsPerQOS",
 | 
							name: "specify EnforceNodeAllocatable without enabling CgroupsPerQOS",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.CgroupsPerQOS = false
 | 
								conf.CgroupsPerQOS = false
 | 
				
			||||||
@@ -109,8 +106,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: enforceNodeAllocatable (--enforce-node-allocatable) is not supported unless cgroupsPerQOS (--cgroups-per-qos) is set to true",
 | 
							errMsg: "invalid configuration: enforceNodeAllocatable (--enforce-node-allocatable) is not supported unless cgroupsPerQOS (--cgroups-per-qos) is set to true",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify SystemCgroups without CgroupRoot",
 | 
							name: "specify SystemCgroups without CgroupRoot",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.SystemCgroups = "/"
 | 
								conf.SystemCgroups = "/"
 | 
				
			||||||
@@ -118,32 +114,28 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: systemCgroups (--system-cgroups) was specified and cgroupRoot (--cgroup-root) was not specified",
 | 
							errMsg: "invalid configuration: systemCgroups (--system-cgroups) was specified and cgroupRoot (--cgroup-root) was not specified",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid EventBurst",
 | 
							name: "invalid EventBurst",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.EventBurst = -1
 | 
								conf.EventBurst = -1
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: eventBurst (--event-burst) -1 must not be a negative number",
 | 
							errMsg: "invalid configuration: eventBurst (--event-burst) -1 must not be a negative number",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid EventRecordQPS",
 | 
							name: "invalid EventRecordQPS",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.EventRecordQPS = -1
 | 
								conf.EventRecordQPS = -1
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: eventRecordQPS (--event-qps) -1 must not be a negative number",
 | 
							errMsg: "invalid configuration: eventRecordQPS (--event-qps) -1 must not be a negative number",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid HealthzPort",
 | 
							name: "invalid HealthzPort",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.HealthzPort = 65536
 | 
								conf.HealthzPort = 65536
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: healthzPort (--healthz-port) 65536 must be between 1 and 65535, inclusive",
 | 
							errMsg: "invalid configuration: healthzPort (--healthz-port) 65536 must be between 1 and 65535, inclusive",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify CPUCFSQuotaPeriod without enabling CPUCFSQuotaPeriod",
 | 
							name: "specify CPUCFSQuotaPeriod without enabling CPUCFSQuotaPeriod",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"CustomCPUCFSQuotaPeriod": false}
 | 
								conf.FeatureGates = map[string]bool{"CustomCPUCFSQuotaPeriod": false}
 | 
				
			||||||
@@ -151,8 +143,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: cpuCFSQuotaPeriod (--cpu-cfs-quota-period) {200ms} requires feature gate CustomCPUCFSQuotaPeriod",
 | 
							errMsg: "invalid configuration: cpuCFSQuotaPeriod (--cpu-cfs-quota-period) {200ms} requires feature gate CustomCPUCFSQuotaPeriod",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid CPUCFSQuotaPeriod",
 | 
							name: "invalid CPUCFSQuotaPeriod",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"CustomCPUCFSQuotaPeriod": true}
 | 
								conf.FeatureGates = map[string]bool{"CustomCPUCFSQuotaPeriod": true}
 | 
				
			||||||
@@ -160,24 +151,21 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: cpuCFSQuotaPeriod (--cpu-cfs-quota-period) {2s} must be between 1ms and 1sec, inclusive",
 | 
							errMsg: "invalid configuration: cpuCFSQuotaPeriod (--cpu-cfs-quota-period) {2s} must be between 1ms and 1sec, inclusive",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid ImageGCHighThresholdPercent",
 | 
							name: "invalid ImageGCHighThresholdPercent",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.ImageGCHighThresholdPercent = 101
 | 
								conf.ImageGCHighThresholdPercent = 101
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: imageGCHighThresholdPercent (--image-gc-high-threshold) 101 must be between 0 and 100, inclusive",
 | 
							errMsg: "invalid configuration: imageGCHighThresholdPercent (--image-gc-high-threshold) 101 must be between 0 and 100, inclusive",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid ImageGCLowThresholdPercent",
 | 
							name: "invalid ImageGCLowThresholdPercent",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.ImageGCLowThresholdPercent = -1
 | 
								conf.ImageGCLowThresholdPercent = -1
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: imageGCLowThresholdPercent (--image-gc-low-threshold) -1 must be between 0 and 100, inclusive",
 | 
							errMsg: "invalid configuration: imageGCLowThresholdPercent (--image-gc-low-threshold) -1 must be between 0 and 100, inclusive",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "ImageGCLowThresholdPercent is equal to ImageGCHighThresholdPercent",
 | 
							name: "ImageGCLowThresholdPercent is equal to ImageGCHighThresholdPercent",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.ImageGCHighThresholdPercent = 0
 | 
								conf.ImageGCHighThresholdPercent = 0
 | 
				
			||||||
@@ -185,8 +173,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: imageGCLowThresholdPercent (--image-gc-low-threshold) 0 must be less than imageGCHighThresholdPercent (--image-gc-high-threshold) 0",
 | 
							errMsg: "invalid configuration: imageGCLowThresholdPercent (--image-gc-low-threshold) 0 must be less than imageGCHighThresholdPercent (--image-gc-high-threshold) 0",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "ImageGCLowThresholdPercent is greater than ImageGCHighThresholdPercent",
 | 
							name: "ImageGCLowThresholdPercent is greater than ImageGCHighThresholdPercent",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.ImageGCHighThresholdPercent = 0
 | 
								conf.ImageGCHighThresholdPercent = 0
 | 
				
			||||||
@@ -194,120 +181,105 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: imageGCLowThresholdPercent (--image-gc-low-threshold) 1 must be less than imageGCHighThresholdPercent (--image-gc-high-threshold) 0",
 | 
							errMsg: "invalid configuration: imageGCLowThresholdPercent (--image-gc-low-threshold) 1 must be less than imageGCHighThresholdPercent (--image-gc-high-threshold) 0",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid IPTablesDropBit",
 | 
							name: "invalid IPTablesDropBit",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.IPTablesDropBit = 32
 | 
								conf.IPTablesDropBit = 32
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: iptablesDropBit (--iptables-drop-bit) 32 must be between 0 and 31, inclusive",
 | 
							errMsg: "invalid configuration: iptablesDropBit (--iptables-drop-bit) 32 must be between 0 and 31, inclusive",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid IPTablesMasqueradeBit",
 | 
							name: "invalid IPTablesMasqueradeBit",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.IPTablesMasqueradeBit = 32
 | 
								conf.IPTablesMasqueradeBit = 32
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: iptablesMasqueradeBit (--iptables-masquerade-bit) 32 must be between 0 and 31, inclusive",
 | 
							errMsg: "invalid configuration: iptablesMasqueradeBit (--iptables-masquerade-bit) 32 must be between 0 and 31, inclusive",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid KubeAPIBurst",
 | 
							name: "invalid KubeAPIBurst",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.KubeAPIBurst = -1
 | 
								conf.KubeAPIBurst = -1
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: kubeAPIBurst (--kube-api-burst) -1 must not be a negative number",
 | 
							errMsg: "invalid configuration: kubeAPIBurst (--kube-api-burst) -1 must not be a negative number",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid KubeAPIQPS",
 | 
							name: "invalid KubeAPIQPS",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.KubeAPIQPS = -1
 | 
								conf.KubeAPIQPS = -1
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: kubeAPIQPS (--kube-api-qps) -1 must not be a negative number",
 | 
							errMsg: "invalid configuration: kubeAPIQPS (--kube-api-qps) -1 must not be a negative number",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid NodeStatusMaxImages",
 | 
							name: "invalid NodeStatusMaxImages",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.NodeStatusMaxImages = -2
 | 
								conf.NodeStatusMaxImages = -2
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: nodeStatusMaxImages (--node-status-max-images) -2 must be -1 or greater",
 | 
							errMsg: "invalid configuration: nodeStatusMaxImages (--node-status-max-images) -2 must be -1 or greater",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid MaxOpenFiles",
 | 
							name: "invalid MaxOpenFiles",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.MaxOpenFiles = -1
 | 
								conf.MaxOpenFiles = -1
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: maxOpenFiles (--max-open-files) -1 must not be a negative number",
 | 
							errMsg: "invalid configuration: maxOpenFiles (--max-open-files) -1 must not be a negative number",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid MaxPods",
 | 
							name: "invalid MaxPods",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.MaxPods = -1
 | 
								conf.MaxPods = -1
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: maxPods (--max-pods) -1 must not be a negative number",
 | 
							errMsg: "invalid configuration: maxPods (--max-pods) -1 must not be a negative number",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid OOMScoreAdj",
 | 
							name: "invalid OOMScoreAdj",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.OOMScoreAdj = 1001
 | 
								conf.OOMScoreAdj = 1001
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: oomScoreAdj (--oom-score-adj) 1001 must be between -1000 and 1000, inclusive",
 | 
							errMsg: "invalid configuration: oomScoreAdj (--oom-score-adj) 1001 must be between -1000 and 1000, inclusive",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid PodsPerCore",
 | 
							name: "invalid PodsPerCore",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.PodsPerCore = -1
 | 
								conf.PodsPerCore = -1
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: podsPerCore (--pods-per-core) -1 must not be a negative number",
 | 
							errMsg: "invalid configuration: podsPerCore (--pods-per-core) -1 must not be a negative number",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid Port",
 | 
							name: "invalid Port",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.Port = 65536
 | 
								conf.Port = 65536
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: port (--port) 65536 must be between 1 and 65535, inclusive",
 | 
							errMsg: "invalid configuration: port (--port) 65536 must be between 1 and 65535, inclusive",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid ReadOnlyPort",
 | 
							name: "invalid ReadOnlyPort",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.ReadOnlyPort = 65536
 | 
								conf.ReadOnlyPort = 65536
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: readOnlyPort (--read-only-port) 65536 must be between 0 and 65535, inclusive",
 | 
							errMsg: "invalid configuration: readOnlyPort (--read-only-port) 65536 must be between 0 and 65535, inclusive",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid RegistryBurst",
 | 
							name: "invalid RegistryBurst",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.RegistryBurst = -1
 | 
								conf.RegistryBurst = -1
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: registryBurst (--registry-burst) -1 must not be a negative number",
 | 
							errMsg: "invalid configuration: registryBurst (--registry-burst) -1 must not be a negative number",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid RegistryPullQPS",
 | 
							name: "invalid RegistryPullQPS",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.RegistryPullQPS = -1
 | 
								conf.RegistryPullQPS = -1
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: registryPullQPS (--registry-qps) -1 must not be a negative number",
 | 
							errMsg: "invalid configuration: registryPullQPS (--registry-qps) -1 must not be a negative number",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid MaxParallelImagePulls",
 | 
							name: "invalid MaxParallelImagePulls",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.MaxParallelImagePulls = utilpointer.Int32(0)
 | 
								conf.MaxParallelImagePulls = utilpointer.Int32(0)
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: maxParallelImagePulls 0 must be a positive number",
 | 
							errMsg: "invalid configuration: maxParallelImagePulls 0 must be a positive number",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid MaxParallelImagePulls and SerializeImagePulls combination",
 | 
							name: "invalid MaxParallelImagePulls and SerializeImagePulls combination",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.MaxParallelImagePulls = utilpointer.Int32(3)
 | 
								conf.MaxParallelImagePulls = utilpointer.Int32(3)
 | 
				
			||||||
@@ -315,16 +287,14 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: maxParallelImagePulls cannot be larger than 1 unless SerializeImagePulls (--serialize-image-pulls) is set to false",
 | 
							errMsg: "invalid configuration: maxParallelImagePulls cannot be larger than 1 unless SerializeImagePulls (--serialize-image-pulls) is set to false",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid MaxParallelImagePulls and SerializeImagePulls combination",
 | 
							name: "valid MaxParallelImagePulls and SerializeImagePulls combination",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.MaxParallelImagePulls = utilpointer.Int32(1)
 | 
								conf.MaxParallelImagePulls = utilpointer.Int32(1)
 | 
				
			||||||
			conf.SerializeImagePulls = true
 | 
								conf.SerializeImagePulls = true
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify ServerTLSBootstrap without enabling RotateKubeletServerCertificate",
 | 
							name: "specify ServerTLSBootstrap without enabling RotateKubeletServerCertificate",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"RotateKubeletServerCertificate": false}
 | 
								conf.FeatureGates = map[string]bool{"RotateKubeletServerCertificate": false}
 | 
				
			||||||
@@ -332,24 +302,21 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: serverTLSBootstrap true requires feature gate RotateKubeletServerCertificate",
 | 
							errMsg: "invalid configuration: serverTLSBootstrap true requires feature gate RotateKubeletServerCertificate",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid TopologyManagerPolicy",
 | 
							name: "invalid TopologyManagerPolicy",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.TopologyManagerPolicy = "invalid-policy"
 | 
								conf.TopologyManagerPolicy = "invalid-policy"
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: topologyManagerPolicy (--topology-manager-policy) \"invalid-policy\" must be one of: [\"none\" \"best-effort\" \"restricted\" \"single-numa-node\"]",
 | 
							errMsg: "invalid configuration: topologyManagerPolicy (--topology-manager-policy) \"invalid-policy\" must be one of: [\"none\" \"best-effort\" \"restricted\" \"single-numa-node\"]",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid TopologyManagerScope",
 | 
							name: "invalid TopologyManagerScope",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.TopologyManagerScope = "invalid-scope"
 | 
								conf.TopologyManagerScope = "invalid-scope"
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: topologyManagerScope (--topology-manager-scope) \"invalid-scope\" must be one of: \"container\", or \"pod\"",
 | 
							errMsg: "invalid configuration: topologyManagerScope (--topology-manager-scope) \"invalid-scope\" must be one of: \"container\", or \"pod\"",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "ShutdownGracePeriodCriticalPods is greater than ShutdownGracePeriod",
 | 
							name: "ShutdownGracePeriodCriticalPods is greater than ShutdownGracePeriod",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"GracefulNodeShutdown": true}
 | 
								conf.FeatureGates = map[string]bool{"GracefulNodeShutdown": true}
 | 
				
			||||||
@@ -358,8 +325,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: shutdownGracePeriodCriticalPods {2s} must be <= shutdownGracePeriod {1s}",
 | 
							errMsg: "invalid configuration: shutdownGracePeriodCriticalPods {2s} must be <= shutdownGracePeriod {1s}",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "ShutdownGracePeriod is less than 1 sec",
 | 
							name: "ShutdownGracePeriod is less than 1 sec",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"GracefulNodeShutdown": true}
 | 
								conf.FeatureGates = map[string]bool{"GracefulNodeShutdown": true}
 | 
				
			||||||
@@ -367,8 +333,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: shutdownGracePeriod {1ms} must be either zero or otherwise >= 1 sec",
 | 
							errMsg: "invalid configuration: shutdownGracePeriod {1ms} must be either zero or otherwise >= 1 sec",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "ShutdownGracePeriodCriticalPods is less than 1 sec",
 | 
							name: "ShutdownGracePeriodCriticalPods is less than 1 sec",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"GracefulNodeShutdown": true}
 | 
								conf.FeatureGates = map[string]bool{"GracefulNodeShutdown": true}
 | 
				
			||||||
@@ -376,8 +341,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: shutdownGracePeriodCriticalPods {1ms} must be either zero or otherwise >= 1 sec",
 | 
							errMsg: "invalid configuration: shutdownGracePeriodCriticalPods {1ms} must be either zero or otherwise >= 1 sec",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify ShutdownGracePeriod without enabling GracefulNodeShutdown",
 | 
							name: "specify ShutdownGracePeriod without enabling GracefulNodeShutdown",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"GracefulNodeShutdown": false}
 | 
								conf.FeatureGates = map[string]bool{"GracefulNodeShutdown": false}
 | 
				
			||||||
@@ -385,8 +349,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: specifying shutdownGracePeriod or shutdownGracePeriodCriticalPods requires feature gate GracefulNodeShutdown",
 | 
							errMsg: "invalid configuration: specifying shutdownGracePeriod or shutdownGracePeriodCriticalPods requires feature gate GracefulNodeShutdown",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify ShutdownGracePeriodCriticalPods without enabling GracefulNodeShutdown",
 | 
							name: "specify ShutdownGracePeriodCriticalPods without enabling GracefulNodeShutdown",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"GracefulNodeShutdown": false}
 | 
								conf.FeatureGates = map[string]bool{"GracefulNodeShutdown": false}
 | 
				
			||||||
@@ -394,8 +357,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: specifying shutdownGracePeriod or shutdownGracePeriodCriticalPods requires feature gate GracefulNodeShutdown",
 | 
							errMsg: "invalid configuration: specifying shutdownGracePeriod or shutdownGracePeriodCriticalPods requires feature gate GracefulNodeShutdown",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid MemorySwap.SwapBehavior",
 | 
							name: "invalid MemorySwap.SwapBehavior",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"NodeSwap": true}
 | 
								conf.FeatureGates = map[string]bool{"NodeSwap": true}
 | 
				
			||||||
@@ -403,8 +365,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: memorySwap.swapBehavior \"invalid-behavior\" must be one of: \"\", \"LimitedSwap\", or \"UnlimitedSwap\"",
 | 
							errMsg: "invalid configuration: memorySwap.swapBehavior \"invalid-behavior\" must be one of: \"\", \"LimitedSwap\", or \"UnlimitedSwap\"",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify MemorySwap.SwapBehavior without enabling NodeSwap",
 | 
							name: "specify MemorySwap.SwapBehavior without enabling NodeSwap",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"NodeSwap": false}
 | 
								conf.FeatureGates = map[string]bool{"NodeSwap": false}
 | 
				
			||||||
@@ -412,8 +373,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: memorySwap.swapBehavior cannot be set when NodeSwap feature flag is disabled",
 | 
							errMsg: "invalid configuration: memorySwap.swapBehavior cannot be set when NodeSwap feature flag is disabled",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify SystemReservedEnforcementKey without specifying SystemReservedCgroup",
 | 
							name: "specify SystemReservedEnforcementKey without specifying SystemReservedCgroup",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.EnforceNodeAllocatable = []string{kubetypes.SystemReservedEnforcementKey}
 | 
								conf.EnforceNodeAllocatable = []string{kubetypes.SystemReservedEnforcementKey}
 | 
				
			||||||
@@ -421,8 +381,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: systemReservedCgroup (--system-reserved-cgroup) must be specified when \"system-reserved\" contained in enforceNodeAllocatable (--enforce-node-allocatable)",
 | 
							errMsg: "invalid configuration: systemReservedCgroup (--system-reserved-cgroup) must be specified when \"system-reserved\" contained in enforceNodeAllocatable (--enforce-node-allocatable)",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify KubeReservedEnforcementKey without specifying KubeReservedCgroup",
 | 
							name: "specify KubeReservedEnforcementKey without specifying KubeReservedCgroup",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.EnforceNodeAllocatable = []string{kubetypes.KubeReservedEnforcementKey}
 | 
								conf.EnforceNodeAllocatable = []string{kubetypes.KubeReservedEnforcementKey}
 | 
				
			||||||
@@ -430,32 +389,28 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: kubeReservedCgroup (--kube-reserved-cgroup) must be specified when \"kube-reserved\" contained in enforceNodeAllocatable (--enforce-node-allocatable)",
 | 
							errMsg: "invalid configuration: kubeReservedCgroup (--kube-reserved-cgroup) must be specified when \"kube-reserved\" contained in enforceNodeAllocatable (--enforce-node-allocatable)",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify NodeAllocatableNoneKey with additional enforcements",
 | 
							name: "specify NodeAllocatableNoneKey with additional enforcements",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.EnforceNodeAllocatable = []string{kubetypes.NodeAllocatableNoneKey, kubetypes.KubeReservedEnforcementKey}
 | 
								conf.EnforceNodeAllocatable = []string{kubetypes.NodeAllocatableNoneKey, kubetypes.KubeReservedEnforcementKey}
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: enforceNodeAllocatable (--enforce-node-allocatable) may not contain additional enforcements when \"none\" is specified",
 | 
							errMsg: "invalid configuration: enforceNodeAllocatable (--enforce-node-allocatable) may not contain additional enforcements when \"none\" is specified",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid EnforceNodeAllocatable",
 | 
							name: "invalid EnforceNodeAllocatable",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.EnforceNodeAllocatable = []string{"invalid-enforce-node-allocatable"}
 | 
								conf.EnforceNodeAllocatable = []string{"invalid-enforce-node-allocatable"}
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: option \"invalid-enforce-node-allocatable\" specified for enforceNodeAllocatable (--enforce-node-allocatable). Valid options are \"pods\", \"system-reserved\", \"kube-reserved\", or \"none\"",
 | 
							errMsg: "invalid configuration: option \"invalid-enforce-node-allocatable\" specified for enforceNodeAllocatable (--enforce-node-allocatable). Valid options are \"pods\", \"system-reserved\", \"kube-reserved\", or \"none\"",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid HairpinMode",
 | 
							name: "invalid HairpinMode",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.HairpinMode = "invalid-hair-pin-mode"
 | 
								conf.HairpinMode = "invalid-hair-pin-mode"
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: option \"invalid-hair-pin-mode\" specified for hairpinMode (--hairpin-mode). Valid options are \"none\", \"hairpin-veth\" or \"promiscuous-bridge\"",
 | 
							errMsg: "invalid configuration: option \"invalid-hair-pin-mode\" specified for hairpinMode (--hairpin-mode). Valid options are \"none\", \"hairpin-veth\" or \"promiscuous-bridge\"",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify ReservedSystemCPUs with SystemReservedCgroup",
 | 
							name: "specify ReservedSystemCPUs with SystemReservedCgroup",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.ReservedSystemCPUs = "0-3"
 | 
								conf.ReservedSystemCPUs = "0-3"
 | 
				
			||||||
@@ -463,8 +418,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: can't use reservedSystemCPUs (--reserved-cpus) with systemReservedCgroup (--system-reserved-cgroup) or kubeReservedCgroup (--kube-reserved-cgroup)",
 | 
							errMsg: "invalid configuration: can't use reservedSystemCPUs (--reserved-cpus) with systemReservedCgroup (--system-reserved-cgroup) or kubeReservedCgroup (--kube-reserved-cgroup)",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify ReservedSystemCPUs with KubeReservedCgroup",
 | 
							name: "specify ReservedSystemCPUs with KubeReservedCgroup",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.ReservedSystemCPUs = "0-3"
 | 
								conf.ReservedSystemCPUs = "0-3"
 | 
				
			||||||
@@ -472,16 +426,14 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: can't use reservedSystemCPUs (--reserved-cpus) with systemReservedCgroup (--system-reserved-cgroup) or kubeReservedCgroup (--kube-reserved-cgroup)",
 | 
							errMsg: "invalid configuration: can't use reservedSystemCPUs (--reserved-cpus) with systemReservedCgroup (--system-reserved-cgroup) or kubeReservedCgroup (--kube-reserved-cgroup)",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid ReservedSystemCPUs",
 | 
							name: "invalid ReservedSystemCPUs",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.ReservedSystemCPUs = "invalid-reserved-system-cpus"
 | 
								conf.ReservedSystemCPUs = "invalid-reserved-system-cpus"
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: unable to parse reservedSystemCPUs (--reserved-cpus) invalid-reserved-system-cpus, error:",
 | 
							errMsg: "invalid configuration: unable to parse reservedSystemCPUs (--reserved-cpus) invalid-reserved-system-cpus, error:",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "enable MemoryQoS without specifying MemoryThrottlingFactor",
 | 
							name: "enable MemoryQoS without specifying MemoryThrottlingFactor",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"MemoryQoS": true}
 | 
								conf.FeatureGates = map[string]bool{"MemoryQoS": true}
 | 
				
			||||||
@@ -489,16 +441,14 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: memoryThrottlingFactor is required when MemoryQoS feature flag is enabled",
 | 
							errMsg: "invalid configuration: memoryThrottlingFactor is required when MemoryQoS feature flag is enabled",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid MemoryThrottlingFactor",
 | 
							name: "invalid MemoryThrottlingFactor",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.MemoryThrottlingFactor = utilpointer.Float64(1.1)
 | 
								conf.MemoryThrottlingFactor = utilpointer.Float64(1.1)
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: memoryThrottlingFactor 1.1 must be greater than 0 and less than or equal to 1.0",
 | 
							errMsg: "invalid configuration: memoryThrottlingFactor 1.1 must be greater than 0 and less than or equal to 1.0",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid Taint.TimeAdded",
 | 
							name: "invalid Taint.TimeAdded",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			now := metav1.Now()
 | 
								now := metav1.Now()
 | 
				
			||||||
@@ -506,8 +456,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: taint.TimeAdded is not nil",
 | 
							errMsg: "invalid configuration: taint.TimeAdded is not nil",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify tracing with KubeletTracing disabled",
 | 
							name: "specify tracing with KubeletTracing disabled",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			samplingRate := int32(99999)
 | 
								samplingRate := int32(99999)
 | 
				
			||||||
@@ -516,8 +465,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: tracing should not be configured if KubeletTracing feature flag is disabled.",
 | 
							errMsg: "invalid configuration: tracing should not be configured if KubeletTracing feature flag is disabled.",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify tracing invalid sampling rate",
 | 
							name: "specify tracing invalid sampling rate",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			samplingRate := int32(-1)
 | 
								samplingRate := int32(-1)
 | 
				
			||||||
@@ -526,8 +474,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "tracing.samplingRatePerMillion: Invalid value: -1: sampling rate must be positive",
 | 
							errMsg: "tracing.samplingRatePerMillion: Invalid value: -1: sampling rate must be positive",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "specify tracing invalid endpoint",
 | 
							name: "specify tracing invalid endpoint",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			ep := "dn%2s://localhost:4317"
 | 
								ep := "dn%2s://localhost:4317"
 | 
				
			||||||
@@ -536,42 +483,36 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "tracing.endpoint: Invalid value: \"dn%2s://localhost:4317\": parse \"dn%2s://localhost:4317\": first path segment in URL cannot contain colon",
 | 
							errMsg: "tracing.endpoint: Invalid value: \"dn%2s://localhost:4317\": parse \"dn%2s://localhost:4317\": first path segment in URL cannot contain colon",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid GracefulNodeShutdownBasedOnPodPriority",
 | 
							name: "invalid GracefulNodeShutdownBasedOnPodPriority",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"GracefulNodeShutdownBasedOnPodPriority": true}
 | 
								conf.FeatureGates = map[string]bool{"GracefulNodeShutdownBasedOnPodPriority": true}
 | 
				
			||||||
				conf.ShutdownGracePeriodByPodPriority = []kubeletconfig.ShutdownGracePeriodByPodPriority{
 | 
								conf.ShutdownGracePeriodByPodPriority = []kubeletconfig.ShutdownGracePeriodByPodPriority{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Priority:                   0,
 | 
									Priority:                   0,
 | 
				
			||||||
				ShutdownGracePeriodSeconds: 0,
 | 
									ShutdownGracePeriodSeconds: 0,
 | 
				
			||||||
			}}
 | 
								}}
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: Cannot specify both shutdownGracePeriodByPodPriority and shutdownGracePeriod at the same time",
 | 
							errMsg: "invalid configuration: Cannot specify both shutdownGracePeriodByPodPriority and shutdownGracePeriod at the same time",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Specifying shutdownGracePeriodByPodPriority without enable GracefulNodeShutdownBasedOnPodPriority",
 | 
							name: "Specifying shutdownGracePeriodByPodPriority without enable GracefulNodeShutdownBasedOnPodPriority",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"GracefulNodeShutdownBasedOnPodPriority": false}
 | 
								conf.FeatureGates = map[string]bool{"GracefulNodeShutdownBasedOnPodPriority": false}
 | 
				
			||||||
				conf.ShutdownGracePeriodByPodPriority = []kubeletconfig.ShutdownGracePeriodByPodPriority{
 | 
								conf.ShutdownGracePeriodByPodPriority = []kubeletconfig.ShutdownGracePeriodByPodPriority{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Priority:                   0,
 | 
									Priority:                   0,
 | 
				
			||||||
				ShutdownGracePeriodSeconds: 0,
 | 
									ShutdownGracePeriodSeconds: 0,
 | 
				
			||||||
			}}
 | 
								}}
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: Specifying shutdownGracePeriodByPodPriority requires feature gate GracefulNodeShutdownBasedOnPodPriority",
 | 
							errMsg: "invalid configuration: Specifying shutdownGracePeriodByPodPriority requires feature gate GracefulNodeShutdownBasedOnPodPriority",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "enableSystemLogQuery is enabled without NodeLogQuery feature gate",
 | 
							name: "enableSystemLogQuery is enabled without NodeLogQuery feature gate",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.EnableSystemLogQuery = true
 | 
								conf.EnableSystemLogQuery = true
 | 
				
			||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: NodeLogQuery feature gate is required for enableSystemLogHandler",
 | 
							errMsg: "invalid configuration: NodeLogQuery feature gate is required for enableSystemLogHandler",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "enableSystemLogQuery is enabled without enableSystemLogHandler",
 | 
							name: "enableSystemLogQuery is enabled without enableSystemLogHandler",
 | 
				
			||||||
		configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
							configure: func(conf *kubeletconfig.KubeletConfiguration) *kubeletconfig.KubeletConfiguration {
 | 
				
			||||||
			conf.FeatureGates = map[string]bool{"NodeLogQuery": true}
 | 
								conf.FeatureGates = map[string]bool{"NodeLogQuery": true}
 | 
				
			||||||
@@ -580,8 +521,7 @@ func TestValidateKubeletConfiguration(t *testing.T) {
 | 
				
			|||||||
			return conf
 | 
								return conf
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		errMsg: "invalid configuration: enableSystemLogHandler is required for enableSystemLogQuery",
 | 
							errMsg: "invalid configuration: enableSystemLogHandler is required for enableSystemLogQuery",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range cases {
 | 
						for _, tc := range cases {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,8 +36,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		proxyMode = kubeproxyconfig.ProxyModeIPVS
 | 
							proxyMode = kubeproxyconfig.ProxyModeIPVS
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	successCases := []kubeproxyconfig.KubeProxyConfiguration{
 | 
						successCases := []kubeproxyconfig.KubeProxyConfiguration{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		BindAddress:        "192.168.59.103",
 | 
							BindAddress:        "192.168.59.103",
 | 
				
			||||||
		HealthzBindAddress: "0.0.0.0:10256",
 | 
							HealthzBindAddress: "0.0.0.0:10256",
 | 
				
			||||||
		MetricsBindAddress: "127.0.0.1:10249",
 | 
							MetricsBindAddress: "127.0.0.1:10249",
 | 
				
			||||||
@@ -59,8 +58,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
			TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
			TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		BindAddress:        "192.168.59.103",
 | 
							BindAddress:        "192.168.59.103",
 | 
				
			||||||
		HealthzBindAddress: "0.0.0.0:10256",
 | 
							HealthzBindAddress: "0.0.0.0:10256",
 | 
				
			||||||
		MetricsBindAddress: "127.0.0.1:10249",
 | 
							MetricsBindAddress: "127.0.0.1:10249",
 | 
				
			||||||
@@ -77,8 +75,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
			TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
			TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		BindAddress:        "192.168.59.103",
 | 
							BindAddress:        "192.168.59.103",
 | 
				
			||||||
		HealthzBindAddress: "",
 | 
							HealthzBindAddress: "",
 | 
				
			||||||
		MetricsBindAddress: "127.0.0.1:10249",
 | 
							MetricsBindAddress: "127.0.0.1:10249",
 | 
				
			||||||
@@ -95,8 +92,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
			TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
			TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		BindAddress:        "fd00:192:168:59::103",
 | 
							BindAddress:        "fd00:192:168:59::103",
 | 
				
			||||||
		HealthzBindAddress: "",
 | 
							HealthzBindAddress: "",
 | 
				
			||||||
		MetricsBindAddress: "[::1]:10249",
 | 
							MetricsBindAddress: "[::1]:10249",
 | 
				
			||||||
@@ -113,8 +109,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
			TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
			TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		BindAddress:        "10.10.12.11",
 | 
							BindAddress:        "10.10.12.11",
 | 
				
			||||||
		HealthzBindAddress: "0.0.0.0:12345",
 | 
							HealthzBindAddress: "0.0.0.0:12345",
 | 
				
			||||||
		MetricsBindAddress: "127.0.0.1:10249",
 | 
							MetricsBindAddress: "127.0.0.1:10249",
 | 
				
			||||||
@@ -131,8 +126,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
			TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
			TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		BindAddress:        "10.10.12.11",
 | 
							BindAddress:        "10.10.12.11",
 | 
				
			||||||
		HealthzBindAddress: "0.0.0.0:12345",
 | 
							HealthzBindAddress: "0.0.0.0:12345",
 | 
				
			||||||
		MetricsBindAddress: "127.0.0.1:10249",
 | 
							MetricsBindAddress: "127.0.0.1:10249",
 | 
				
			||||||
@@ -149,8 +143,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
			TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
			TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		BindAddress:        "10.10.12.11",
 | 
							BindAddress:        "10.10.12.11",
 | 
				
			||||||
		HealthzBindAddress: "0.0.0.0:12345",
 | 
							HealthzBindAddress: "0.0.0.0:12345",
 | 
				
			||||||
		MetricsBindAddress: "127.0.0.1:10249",
 | 
							MetricsBindAddress: "127.0.0.1:10249",
 | 
				
			||||||
@@ -167,8 +160,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
			TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPEstablishedTimeout: &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
			TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
								TCPCloseWaitTimeout:   &metav1.Duration{Duration: 5 * time.Second},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		BindAddress:        "10.10.12.11",
 | 
							BindAddress:        "10.10.12.11",
 | 
				
			||||||
		HealthzBindAddress: "0.0.0.0:12345",
 | 
							HealthzBindAddress: "0.0.0.0:12345",
 | 
				
			||||||
		MetricsBindAddress: "127.0.0.1:10249",
 | 
							MetricsBindAddress: "127.0.0.1:10249",
 | 
				
			||||||
@@ -189,8 +181,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
		DetectLocal: kubeproxyconfig.DetectLocalConfiguration{
 | 
							DetectLocal: kubeproxyconfig.DetectLocalConfiguration{
 | 
				
			||||||
			InterfaceNamePrefix: "vethabcde",
 | 
								InterfaceNamePrefix: "vethabcde",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		BindAddress:        "10.10.12.11",
 | 
							BindAddress:        "10.10.12.11",
 | 
				
			||||||
		HealthzBindAddress: "0.0.0.0:12345",
 | 
							HealthzBindAddress: "0.0.0.0:12345",
 | 
				
			||||||
		MetricsBindAddress: "127.0.0.1:10249",
 | 
							MetricsBindAddress: "127.0.0.1:10249",
 | 
				
			||||||
@@ -211,8 +202,7 @@ func TestValidateKubeProxyConfiguration(t *testing.T) {
 | 
				
			|||||||
		DetectLocal: kubeproxyconfig.DetectLocalConfiguration{
 | 
							DetectLocal: kubeproxyconfig.DetectLocalConfiguration{
 | 
				
			||||||
			BridgeInterface: "avz",
 | 
								BridgeInterface: "avz",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, successCase := range successCases {
 | 
						for _, successCase := range successCases {
 | 
				
			||||||
		if errs := Validate(&successCase); len(errs) != 0 {
 | 
							if errs := Validate(&successCase); len(errs) != 0 {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,8 +57,7 @@ func TestValidateKubeSchedulerConfigurationV1beta2(t *testing.T) {
 | 
				
			|||||||
		PodInitialBackoffSeconds: podInitialBackoffSeconds,
 | 
							PodInitialBackoffSeconds: podInitialBackoffSeconds,
 | 
				
			||||||
		PodMaxBackoffSeconds:     podMaxBackoffSeconds,
 | 
							PodMaxBackoffSeconds:     podMaxBackoffSeconds,
 | 
				
			||||||
		PercentageOfNodesToScore: pointer.Int32(35),
 | 
							PercentageOfNodesToScore: pointer.Int32(35),
 | 
				
			||||||
		Profiles: []config.KubeSchedulerProfile{
 | 
							Profiles: []config.KubeSchedulerProfile{{
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			SchedulerName: "me",
 | 
								SchedulerName: "me",
 | 
				
			||||||
			Plugins: &config.Plugins{
 | 
								Plugins: &config.Plugins{
 | 
				
			||||||
				QueueSort: config.PluginSet{
 | 
									QueueSort: config.PluginSet{
 | 
				
			||||||
@@ -68,14 +67,11 @@ func TestValidateKubeSchedulerConfigurationV1beta2(t *testing.T) {
 | 
				
			|||||||
					Disabled: []config.Plugin{{Name: "*"}},
 | 
										Disabled: []config.Plugin{{Name: "*"}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
				PluginConfig: []config.PluginConfig{
 | 
								PluginConfig: []config.PluginConfig{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Name: "DefaultPreemption",
 | 
									Name: "DefaultPreemption",
 | 
				
			||||||
				Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 10, MinCandidateNodesAbsolute: 100},
 | 
									Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 10, MinCandidateNodesAbsolute: 100},
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
							}, {
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			SchedulerName: "other",
 | 
								SchedulerName: "other",
 | 
				
			||||||
			Plugins: &config.Plugins{
 | 
								Plugins: &config.Plugins{
 | 
				
			||||||
				QueueSort: config.PluginSet{
 | 
									QueueSort: config.PluginSet{
 | 
				
			||||||
@@ -85,14 +81,11 @@ func TestValidateKubeSchedulerConfigurationV1beta2(t *testing.T) {
 | 
				
			|||||||
					Enabled: []config.Plugin{{Name: "CustomBind"}},
 | 
										Enabled: []config.Plugin{{Name: "CustomBind"}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			},
 | 
							}},
 | 
				
			||||||
		},
 | 
							Extenders: []config.Extender{{
 | 
				
			||||||
		Extenders: []config.Extender{
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			PrioritizeVerb: "prioritize",
 | 
								PrioritizeVerb: "prioritize",
 | 
				
			||||||
			Weight:         1,
 | 
								Weight:         1,
 | 
				
			||||||
			},
 | 
							}},
 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	invalidParallelismValue := validConfig.DeepCopy()
 | 
						invalidParallelismValue := validConfig.DeepCopy()
 | 
				
			||||||
@@ -145,60 +138,46 @@ func TestValidateKubeSchedulerConfigurationV1beta2(t *testing.T) {
 | 
				
			|||||||
	extenderNegativeWeight.Extenders[0].Weight = -1
 | 
						extenderNegativeWeight.Extenders[0].Weight = -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	invalidNodePercentage := validConfig.DeepCopy()
 | 
						invalidNodePercentage := validConfig.DeepCopy()
 | 
				
			||||||
	invalidNodePercentage.Profiles[0].PluginConfig = []config.PluginConfig{
 | 
						invalidNodePercentage.Profiles[0].PluginConfig = []config.PluginConfig{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "DefaultPreemption",
 | 
							Name: "DefaultPreemption",
 | 
				
			||||||
		Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 200, MinCandidateNodesAbsolute: 100},
 | 
							Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 200, MinCandidateNodesAbsolute: 100},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	invalidPluginArgs := validConfig.DeepCopy()
 | 
						invalidPluginArgs := validConfig.DeepCopy()
 | 
				
			||||||
	invalidPluginArgs.Profiles[0].PluginConfig = []config.PluginConfig{
 | 
						invalidPluginArgs.Profiles[0].PluginConfig = []config.PluginConfig{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "DefaultPreemption",
 | 
							Name: "DefaultPreemption",
 | 
				
			||||||
		Args: &config.InterPodAffinityArgs{},
 | 
							Args: &config.InterPodAffinityArgs{},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	duplicatedPluginConfig := validConfig.DeepCopy()
 | 
						duplicatedPluginConfig := validConfig.DeepCopy()
 | 
				
			||||||
	duplicatedPluginConfig.Profiles[0].PluginConfig = []config.PluginConfig{
 | 
						duplicatedPluginConfig.Profiles[0].PluginConfig = []config.PluginConfig{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "config",
 | 
							Name: "config",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "config",
 | 
							Name: "config",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mismatchQueueSort := validConfig.DeepCopy()
 | 
						mismatchQueueSort := validConfig.DeepCopy()
 | 
				
			||||||
	mismatchQueueSort.Profiles = []config.KubeSchedulerProfile{
 | 
						mismatchQueueSort.Profiles = []config.KubeSchedulerProfile{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		SchedulerName: "me",
 | 
							SchedulerName: "me",
 | 
				
			||||||
		Plugins: &config.Plugins{
 | 
							Plugins: &config.Plugins{
 | 
				
			||||||
			QueueSort: config.PluginSet{
 | 
								QueueSort: config.PluginSet{
 | 
				
			||||||
				Enabled: []config.Plugin{{Name: "PrioritySort"}},
 | 
									Enabled: []config.Plugin{{Name: "PrioritySort"}},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
			PluginConfig: []config.PluginConfig{
 | 
							PluginConfig: []config.PluginConfig{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Name: "PrioritySort",
 | 
								Name: "PrioritySort",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
						}, {
 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		SchedulerName: "other",
 | 
							SchedulerName: "other",
 | 
				
			||||||
		Plugins: &config.Plugins{
 | 
							Plugins: &config.Plugins{
 | 
				
			||||||
			QueueSort: config.PluginSet{
 | 
								QueueSort: config.PluginSet{
 | 
				
			||||||
				Enabled: []config.Plugin{{Name: "CustomSort"}},
 | 
									Enabled: []config.Plugin{{Name: "CustomSort"}},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
			PluginConfig: []config.PluginConfig{
 | 
							PluginConfig: []config.PluginConfig{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Name: "CustomSort",
 | 
								Name: "CustomSort",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
						}}
 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	extenderDuplicateManagedResource := validConfig.DeepCopy()
 | 
						extenderDuplicateManagedResource := validConfig.DeepCopy()
 | 
				
			||||||
	extenderDuplicateManagedResource.Extenders[0].ManagedResources = []config.ExtenderManagedResource{
 | 
						extenderDuplicateManagedResource.Extenders[0].ManagedResources = []config.ExtenderManagedResource{
 | 
				
			||||||
@@ -455,8 +434,7 @@ func TestValidateKubeSchedulerConfigurationV1beta3(t *testing.T) {
 | 
				
			|||||||
		PodInitialBackoffSeconds: podInitialBackoffSeconds,
 | 
							PodInitialBackoffSeconds: podInitialBackoffSeconds,
 | 
				
			||||||
		PodMaxBackoffSeconds:     podMaxBackoffSeconds,
 | 
							PodMaxBackoffSeconds:     podMaxBackoffSeconds,
 | 
				
			||||||
		PercentageOfNodesToScore: pointer.Int32(35),
 | 
							PercentageOfNodesToScore: pointer.Int32(35),
 | 
				
			||||||
		Profiles: []config.KubeSchedulerProfile{
 | 
							Profiles: []config.KubeSchedulerProfile{{
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			SchedulerName: "me",
 | 
								SchedulerName: "me",
 | 
				
			||||||
			Plugins: &config.Plugins{
 | 
								Plugins: &config.Plugins{
 | 
				
			||||||
				QueueSort: config.PluginSet{
 | 
									QueueSort: config.PluginSet{
 | 
				
			||||||
@@ -466,14 +444,11 @@ func TestValidateKubeSchedulerConfigurationV1beta3(t *testing.T) {
 | 
				
			|||||||
					Disabled: []config.Plugin{{Name: "*"}},
 | 
										Disabled: []config.Plugin{{Name: "*"}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
				PluginConfig: []config.PluginConfig{
 | 
								PluginConfig: []config.PluginConfig{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Name: "DefaultPreemption",
 | 
									Name: "DefaultPreemption",
 | 
				
			||||||
				Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 10, MinCandidateNodesAbsolute: 100},
 | 
									Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 10, MinCandidateNodesAbsolute: 100},
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
							}, {
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			SchedulerName: "other",
 | 
								SchedulerName: "other",
 | 
				
			||||||
			Plugins: &config.Plugins{
 | 
								Plugins: &config.Plugins{
 | 
				
			||||||
				QueueSort: config.PluginSet{
 | 
									QueueSort: config.PluginSet{
 | 
				
			||||||
@@ -483,14 +458,11 @@ func TestValidateKubeSchedulerConfigurationV1beta3(t *testing.T) {
 | 
				
			|||||||
					Enabled: []config.Plugin{{Name: "CustomBind"}},
 | 
										Enabled: []config.Plugin{{Name: "CustomBind"}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			},
 | 
							}},
 | 
				
			||||||
		},
 | 
							Extenders: []config.Extender{{
 | 
				
			||||||
		Extenders: []config.Extender{
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			PrioritizeVerb: "prioritize",
 | 
								PrioritizeVerb: "prioritize",
 | 
				
			||||||
			Weight:         1,
 | 
								Weight:         1,
 | 
				
			||||||
			},
 | 
							}},
 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	invalidParallelismValue := validConfig.DeepCopy()
 | 
						invalidParallelismValue := validConfig.DeepCopy()
 | 
				
			||||||
@@ -543,20 +515,16 @@ func TestValidateKubeSchedulerConfigurationV1beta3(t *testing.T) {
 | 
				
			|||||||
	extenderNegativeWeight.Extenders[0].Weight = -1
 | 
						extenderNegativeWeight.Extenders[0].Weight = -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	invalidNodePercentage := validConfig.DeepCopy()
 | 
						invalidNodePercentage := validConfig.DeepCopy()
 | 
				
			||||||
	invalidNodePercentage.Profiles[0].PluginConfig = []config.PluginConfig{
 | 
						invalidNodePercentage.Profiles[0].PluginConfig = []config.PluginConfig{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "DefaultPreemption",
 | 
							Name: "DefaultPreemption",
 | 
				
			||||||
		Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 200, MinCandidateNodesAbsolute: 100},
 | 
							Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 200, MinCandidateNodesAbsolute: 100},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	invalidPluginArgs := validConfig.DeepCopy()
 | 
						invalidPluginArgs := validConfig.DeepCopy()
 | 
				
			||||||
	invalidPluginArgs.Profiles[0].PluginConfig = []config.PluginConfig{
 | 
						invalidPluginArgs.Profiles[0].PluginConfig = []config.PluginConfig{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "DefaultPreemption",
 | 
							Name: "DefaultPreemption",
 | 
				
			||||||
		Args: &config.InterPodAffinityArgs{},
 | 
							Args: &config.InterPodAffinityArgs{},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	duplicatedPlugins := validConfig.DeepCopy()
 | 
						duplicatedPlugins := validConfig.DeepCopy()
 | 
				
			||||||
	duplicatedPlugins.Profiles[0].Plugins.PreEnqueue.Enabled = []config.Plugin{
 | 
						duplicatedPlugins.Profiles[0].Plugins.PreEnqueue.Enabled = []config.Plugin{
 | 
				
			||||||
@@ -565,44 +533,34 @@ func TestValidateKubeSchedulerConfigurationV1beta3(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	duplicatedPluginConfig := validConfig.DeepCopy()
 | 
						duplicatedPluginConfig := validConfig.DeepCopy()
 | 
				
			||||||
	duplicatedPluginConfig.Profiles[0].PluginConfig = []config.PluginConfig{
 | 
						duplicatedPluginConfig.Profiles[0].PluginConfig = []config.PluginConfig{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "config",
 | 
							Name: "config",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "config",
 | 
							Name: "config",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mismatchQueueSort := validConfig.DeepCopy()
 | 
						mismatchQueueSort := validConfig.DeepCopy()
 | 
				
			||||||
	mismatchQueueSort.Profiles = []config.KubeSchedulerProfile{
 | 
						mismatchQueueSort.Profiles = []config.KubeSchedulerProfile{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		SchedulerName: "me",
 | 
							SchedulerName: "me",
 | 
				
			||||||
		Plugins: &config.Plugins{
 | 
							Plugins: &config.Plugins{
 | 
				
			||||||
			QueueSort: config.PluginSet{
 | 
								QueueSort: config.PluginSet{
 | 
				
			||||||
				Enabled: []config.Plugin{{Name: "PrioritySort"}},
 | 
									Enabled: []config.Plugin{{Name: "PrioritySort"}},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
			PluginConfig: []config.PluginConfig{
 | 
							PluginConfig: []config.PluginConfig{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Name: "PrioritySort",
 | 
								Name: "PrioritySort",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
						}, {
 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		SchedulerName: "other",
 | 
							SchedulerName: "other",
 | 
				
			||||||
		Plugins: &config.Plugins{
 | 
							Plugins: &config.Plugins{
 | 
				
			||||||
			QueueSort: config.PluginSet{
 | 
								QueueSort: config.PluginSet{
 | 
				
			||||||
				Enabled: []config.Plugin{{Name: "CustomSort"}},
 | 
									Enabled: []config.Plugin{{Name: "CustomSort"}},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
			PluginConfig: []config.PluginConfig{
 | 
							PluginConfig: []config.PluginConfig{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Name: "CustomSort",
 | 
								Name: "CustomSort",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
						}}
 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	extenderDuplicateManagedResource := validConfig.DeepCopy()
 | 
						extenderDuplicateManagedResource := validConfig.DeepCopy()
 | 
				
			||||||
	extenderDuplicateManagedResource.Extenders[0].ManagedResources = []config.ExtenderManagedResource{
 | 
						extenderDuplicateManagedResource.Extenders[0].ManagedResources = []config.ExtenderManagedResource{
 | 
				
			||||||
@@ -858,8 +816,7 @@ func TestValidateKubeSchedulerConfigurationV1(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		PodInitialBackoffSeconds: podInitialBackoffSeconds,
 | 
							PodInitialBackoffSeconds: podInitialBackoffSeconds,
 | 
				
			||||||
		PodMaxBackoffSeconds:     podMaxBackoffSeconds,
 | 
							PodMaxBackoffSeconds:     podMaxBackoffSeconds,
 | 
				
			||||||
		Profiles: []config.KubeSchedulerProfile{
 | 
							Profiles: []config.KubeSchedulerProfile{{
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			SchedulerName:            "me",
 | 
								SchedulerName:            "me",
 | 
				
			||||||
			PercentageOfNodesToScore: pointer.Int32(35),
 | 
								PercentageOfNodesToScore: pointer.Int32(35),
 | 
				
			||||||
			Plugins: &config.Plugins{
 | 
								Plugins: &config.Plugins{
 | 
				
			||||||
@@ -870,14 +827,11 @@ func TestValidateKubeSchedulerConfigurationV1(t *testing.T) {
 | 
				
			|||||||
					Disabled: []config.Plugin{{Name: "*"}},
 | 
										Disabled: []config.Plugin{{Name: "*"}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
				PluginConfig: []config.PluginConfig{
 | 
								PluginConfig: []config.PluginConfig{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Name: "DefaultPreemption",
 | 
									Name: "DefaultPreemption",
 | 
				
			||||||
				Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 10, MinCandidateNodesAbsolute: 100},
 | 
									Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 10, MinCandidateNodesAbsolute: 100},
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
							}, {
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			SchedulerName:            "other",
 | 
								SchedulerName:            "other",
 | 
				
			||||||
			PercentageOfNodesToScore: pointer.Int32(35),
 | 
								PercentageOfNodesToScore: pointer.Int32(35),
 | 
				
			||||||
			Plugins: &config.Plugins{
 | 
								Plugins: &config.Plugins{
 | 
				
			||||||
@@ -888,14 +842,11 @@ func TestValidateKubeSchedulerConfigurationV1(t *testing.T) {
 | 
				
			|||||||
					Enabled: []config.Plugin{{Name: "CustomBind"}},
 | 
										Enabled: []config.Plugin{{Name: "CustomBind"}},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			},
 | 
							}},
 | 
				
			||||||
		},
 | 
							Extenders: []config.Extender{{
 | 
				
			||||||
		Extenders: []config.Extender{
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			PrioritizeVerb: "prioritize",
 | 
								PrioritizeVerb: "prioritize",
 | 
				
			||||||
			Weight:         1,
 | 
								Weight:         1,
 | 
				
			||||||
			},
 | 
							}},
 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	invalidParallelismValue := validConfig.DeepCopy()
 | 
						invalidParallelismValue := validConfig.DeepCopy()
 | 
				
			||||||
@@ -948,60 +899,46 @@ func TestValidateKubeSchedulerConfigurationV1(t *testing.T) {
 | 
				
			|||||||
	extenderNegativeWeight.Extenders[0].Weight = -1
 | 
						extenderNegativeWeight.Extenders[0].Weight = -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	invalidNodePercentage := validConfig.DeepCopy()
 | 
						invalidNodePercentage := validConfig.DeepCopy()
 | 
				
			||||||
	invalidNodePercentage.Profiles[0].PluginConfig = []config.PluginConfig{
 | 
						invalidNodePercentage.Profiles[0].PluginConfig = []config.PluginConfig{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "DefaultPreemption",
 | 
							Name: "DefaultPreemption",
 | 
				
			||||||
		Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 200, MinCandidateNodesAbsolute: 100},
 | 
							Args: &config.DefaultPreemptionArgs{MinCandidateNodesPercentage: 200, MinCandidateNodesAbsolute: 100},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	invalidPluginArgs := validConfig.DeepCopy()
 | 
						invalidPluginArgs := validConfig.DeepCopy()
 | 
				
			||||||
	invalidPluginArgs.Profiles[0].PluginConfig = []config.PluginConfig{
 | 
						invalidPluginArgs.Profiles[0].PluginConfig = []config.PluginConfig{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "DefaultPreemption",
 | 
							Name: "DefaultPreemption",
 | 
				
			||||||
		Args: &config.InterPodAffinityArgs{},
 | 
							Args: &config.InterPodAffinityArgs{},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	duplicatedPluginConfig := validConfig.DeepCopy()
 | 
						duplicatedPluginConfig := validConfig.DeepCopy()
 | 
				
			||||||
	duplicatedPluginConfig.Profiles[0].PluginConfig = []config.PluginConfig{
 | 
						duplicatedPluginConfig.Profiles[0].PluginConfig = []config.PluginConfig{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "config",
 | 
							Name: "config",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Name: "config",
 | 
							Name: "config",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mismatchQueueSort := validConfig.DeepCopy()
 | 
						mismatchQueueSort := validConfig.DeepCopy()
 | 
				
			||||||
	mismatchQueueSort.Profiles = []config.KubeSchedulerProfile{
 | 
						mismatchQueueSort.Profiles = []config.KubeSchedulerProfile{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		SchedulerName: "me",
 | 
							SchedulerName: "me",
 | 
				
			||||||
		Plugins: &config.Plugins{
 | 
							Plugins: &config.Plugins{
 | 
				
			||||||
			QueueSort: config.PluginSet{
 | 
								QueueSort: config.PluginSet{
 | 
				
			||||||
				Enabled: []config.Plugin{{Name: "PrioritySort"}},
 | 
									Enabled: []config.Plugin{{Name: "PrioritySort"}},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
			PluginConfig: []config.PluginConfig{
 | 
							PluginConfig: []config.PluginConfig{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Name: "PrioritySort",
 | 
								Name: "PrioritySort",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
						}, {
 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		SchedulerName: "other",
 | 
							SchedulerName: "other",
 | 
				
			||||||
		Plugins: &config.Plugins{
 | 
							Plugins: &config.Plugins{
 | 
				
			||||||
			QueueSort: config.PluginSet{
 | 
								QueueSort: config.PluginSet{
 | 
				
			||||||
				Enabled: []config.Plugin{{Name: "CustomSort"}},
 | 
									Enabled: []config.Plugin{{Name: "CustomSort"}},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
			PluginConfig: []config.PluginConfig{
 | 
							PluginConfig: []config.PluginConfig{{
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Name: "CustomSort",
 | 
								Name: "CustomSort",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
						}}
 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	extenderDuplicateManagedResource := validConfig.DeepCopy()
 | 
						extenderDuplicateManagedResource := validConfig.DeepCopy()
 | 
				
			||||||
	extenderDuplicateManagedResource.Extenders[0].ManagedResources = []config.ExtenderManagedResource{
 | 
						extenderDuplicateManagedResource.Extenders[0].ManagedResources = []config.ExtenderManagedResource{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,158 +27,124 @@ func TestValidateConfiguration(t *testing.T) {
 | 
				
			|||||||
		name           string
 | 
							name           string
 | 
				
			||||||
		config         eventratelimitapi.Configuration
 | 
							config         eventratelimitapi.Configuration
 | 
				
			||||||
		expectedResult bool
 | 
							expectedResult bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid server",
 | 
							name: "valid server",
 | 
				
			||||||
		config: eventratelimitapi.Configuration{
 | 
							config: eventratelimitapi.Configuration{
 | 
				
			||||||
				Limits: []eventratelimitapi.Limit{
 | 
								Limits: []eventratelimitapi.Limit{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:  "Server",
 | 
									Type:  "Server",
 | 
				
			||||||
				Burst: 5,
 | 
									Burst: 5,
 | 
				
			||||||
				QPS:   1,
 | 
									QPS:   1,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedResult: true,
 | 
							expectedResult: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid namespace",
 | 
							name: "valid namespace",
 | 
				
			||||||
		config: eventratelimitapi.Configuration{
 | 
							config: eventratelimitapi.Configuration{
 | 
				
			||||||
				Limits: []eventratelimitapi.Limit{
 | 
								Limits: []eventratelimitapi.Limit{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:      "Namespace",
 | 
									Type:      "Namespace",
 | 
				
			||||||
				Burst:     10,
 | 
									Burst:     10,
 | 
				
			||||||
				QPS:       2,
 | 
									QPS:       2,
 | 
				
			||||||
				CacheSize: 100,
 | 
									CacheSize: 100,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedResult: true,
 | 
							expectedResult: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid user",
 | 
							name: "valid user",
 | 
				
			||||||
		config: eventratelimitapi.Configuration{
 | 
							config: eventratelimitapi.Configuration{
 | 
				
			||||||
				Limits: []eventratelimitapi.Limit{
 | 
								Limits: []eventratelimitapi.Limit{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:      "User",
 | 
									Type:      "User",
 | 
				
			||||||
				Burst:     10,
 | 
									Burst:     10,
 | 
				
			||||||
				QPS:       2,
 | 
									QPS:       2,
 | 
				
			||||||
				CacheSize: 100,
 | 
									CacheSize: 100,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedResult: true,
 | 
							expectedResult: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid source+object",
 | 
							name: "valid source+object",
 | 
				
			||||||
		config: eventratelimitapi.Configuration{
 | 
							config: eventratelimitapi.Configuration{
 | 
				
			||||||
				Limits: []eventratelimitapi.Limit{
 | 
								Limits: []eventratelimitapi.Limit{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:      "SourceAndObject",
 | 
									Type:      "SourceAndObject",
 | 
				
			||||||
				Burst:     5,
 | 
									Burst:     5,
 | 
				
			||||||
				QPS:       1,
 | 
									QPS:       1,
 | 
				
			||||||
				CacheSize: 1000,
 | 
									CacheSize: 1000,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedResult: true,
 | 
							expectedResult: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid multiple",
 | 
							name: "valid multiple",
 | 
				
			||||||
		config: eventratelimitapi.Configuration{
 | 
							config: eventratelimitapi.Configuration{
 | 
				
			||||||
				Limits: []eventratelimitapi.Limit{
 | 
								Limits: []eventratelimitapi.Limit{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:  "Server",
 | 
									Type:  "Server",
 | 
				
			||||||
				Burst: 5,
 | 
									Burst: 5,
 | 
				
			||||||
				QPS:   1,
 | 
									QPS:   1,
 | 
				
			||||||
					},
 | 
								}, {
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:      "Namespace",
 | 
									Type:      "Namespace",
 | 
				
			||||||
				Burst:     10,
 | 
									Burst:     10,
 | 
				
			||||||
				QPS:       2,
 | 
									QPS:       2,
 | 
				
			||||||
				CacheSize: 100,
 | 
									CacheSize: 100,
 | 
				
			||||||
					},
 | 
								}, {
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:      "SourceAndObject",
 | 
									Type:      "SourceAndObject",
 | 
				
			||||||
				Burst:     25,
 | 
									Burst:     25,
 | 
				
			||||||
				QPS:       10,
 | 
									QPS:       10,
 | 
				
			||||||
				CacheSize: 1000,
 | 
									CacheSize: 1000,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedResult: true,
 | 
							expectedResult: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:           "missing limits",
 | 
							name:           "missing limits",
 | 
				
			||||||
		config:         eventratelimitapi.Configuration{},
 | 
							config:         eventratelimitapi.Configuration{},
 | 
				
			||||||
		expectedResult: false,
 | 
							expectedResult: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "missing type",
 | 
							name: "missing type",
 | 
				
			||||||
		config: eventratelimitapi.Configuration{
 | 
							config: eventratelimitapi.Configuration{
 | 
				
			||||||
				Limits: []eventratelimitapi.Limit{
 | 
								Limits: []eventratelimitapi.Limit{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Burst:     25,
 | 
									Burst:     25,
 | 
				
			||||||
				QPS:       10,
 | 
									QPS:       10,
 | 
				
			||||||
				CacheSize: 1000,
 | 
									CacheSize: 1000,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedResult: false,
 | 
							expectedResult: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid type",
 | 
							name: "invalid type",
 | 
				
			||||||
		config: eventratelimitapi.Configuration{
 | 
							config: eventratelimitapi.Configuration{
 | 
				
			||||||
				Limits: []eventratelimitapi.Limit{
 | 
								Limits: []eventratelimitapi.Limit{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:      "unknown-type",
 | 
									Type:      "unknown-type",
 | 
				
			||||||
				Burst:     25,
 | 
									Burst:     25,
 | 
				
			||||||
				QPS:       10,
 | 
									QPS:       10,
 | 
				
			||||||
				CacheSize: 1000,
 | 
									CacheSize: 1000,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedResult: false,
 | 
							expectedResult: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "missing burst",
 | 
							name: "missing burst",
 | 
				
			||||||
		config: eventratelimitapi.Configuration{
 | 
							config: eventratelimitapi.Configuration{
 | 
				
			||||||
				Limits: []eventratelimitapi.Limit{
 | 
								Limits: []eventratelimitapi.Limit{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type: "Server",
 | 
									Type: "Server",
 | 
				
			||||||
				QPS:  1,
 | 
									QPS:  1,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedResult: false,
 | 
							expectedResult: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "missing qps",
 | 
							name: "missing qps",
 | 
				
			||||||
		config: eventratelimitapi.Configuration{
 | 
							config: eventratelimitapi.Configuration{
 | 
				
			||||||
				Limits: []eventratelimitapi.Limit{
 | 
								Limits: []eventratelimitapi.Limit{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:  "Server",
 | 
									Type:  "Server",
 | 
				
			||||||
				Burst: 5,
 | 
									Burst: 5,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedResult: false,
 | 
							expectedResult: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "negative cache size",
 | 
							name: "negative cache size",
 | 
				
			||||||
		config: eventratelimitapi.Configuration{
 | 
							config: eventratelimitapi.Configuration{
 | 
				
			||||||
				Limits: []eventratelimitapi.Limit{
 | 
								Limits: []eventratelimitapi.Limit{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Type:      "Namespace",
 | 
									Type:      "Namespace",
 | 
				
			||||||
				Burst:     10,
 | 
									Burst:     10,
 | 
				
			||||||
				QPS:       2,
 | 
									QPS:       2,
 | 
				
			||||||
				CacheSize: -1,
 | 
									CacheSize: -1,
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectedResult: false,
 | 
							expectedResult: false,
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range cases {
 | 
						for _, tc := range cases {
 | 
				
			||||||
		errs := ValidateConfiguration(&tc.config)
 | 
							errs := ValidateConfiguration(&tc.config)
 | 
				
			||||||
		if e, a := tc.expectedResult, len(errs) == 0; e != a {
 | 
							if e, a := tc.expectedResult, len(errs) == 0; e != a {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,9 +17,10 @@ limitations under the License.
 | 
				
			|||||||
package validation
 | 
					package validation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	api "k8s.io/kubernetes/pkg/apis/core"
 | 
						api "k8s.io/kubernetes/pkg/apis/core"
 | 
				
			||||||
	internalapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
 | 
						internalapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestValidateConfiguration(t *testing.T) {
 | 
					func TestValidateConfiguration(t *testing.T) {
 | 
				
			||||||
@@ -28,8 +29,7 @@ func TestValidateConfiguration(t *testing.T) {
 | 
				
			|||||||
		config     internalapi.Configuration
 | 
							config     internalapi.Configuration
 | 
				
			||||||
		testName   string
 | 
							testName   string
 | 
				
			||||||
		testStatus bool
 | 
							testStatus bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		config: internalapi.Configuration{
 | 
							config: internalapi.Configuration{
 | 
				
			||||||
			Default: []api.Toleration{
 | 
								Default: []api.Toleration{
 | 
				
			||||||
				{Key: "foo", Operator: "Exists", Value: "", Effect: "NoExecute", TolerationSeconds: &[]int64{60}[0]},
 | 
									{Key: "foo", Operator: "Exists", Value: "", Effect: "NoExecute", TolerationSeconds: &[]int64{60}[0]},
 | 
				
			||||||
@@ -44,22 +44,19 @@ func TestValidateConfiguration(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		testName:   "Valid cases",
 | 
							testName:   "Valid cases",
 | 
				
			||||||
		testStatus: true,
 | 
							testStatus: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		config: internalapi.Configuration{
 | 
							config: internalapi.Configuration{
 | 
				
			||||||
			Whitelist: []api.Toleration{{Key: "foo", Operator: "Exists", Value: "bar", Effect: "NoSchedule"}},
 | 
								Whitelist: []api.Toleration{{Key: "foo", Operator: "Exists", Value: "bar", Effect: "NoSchedule"}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		testName:   "Invalid case",
 | 
							testName:   "Invalid case",
 | 
				
			||||||
		testStatus: false,
 | 
							testStatus: false,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		config: internalapi.Configuration{
 | 
							config: internalapi.Configuration{
 | 
				
			||||||
			Default: []api.Toleration{{Operator: "Equal", Value: "bar", Effect: "NoSchedule"}},
 | 
								Default: []api.Toleration{{Operator: "Equal", Value: "bar", Effect: "NoSchedule"}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		testName:   "Invalid case",
 | 
							testName:   "Invalid case",
 | 
				
			||||||
		testStatus: false,
 | 
							testStatus: false,
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := range tests {
 | 
						for i := range tests {
 | 
				
			||||||
		errs := ValidateConfiguration(&tests[i].config)
 | 
							errs := ValidateConfiguration(&tests[i].config)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,9 +17,10 @@ limitations under the License.
 | 
				
			|||||||
package validation
 | 
					package validation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/apis/meta/internalversion"
 | 
						"k8s.io/apimachinery/pkg/apis/meta/internalversion"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestValidateListOptions(t *testing.T) {
 | 
					func TestValidateListOptions(t *testing.T) {
 | 
				
			||||||
@@ -32,55 +33,47 @@ func TestValidateListOptions(t *testing.T) {
 | 
				
			|||||||
		opts                    internalversion.ListOptions
 | 
							opts                    internalversion.ListOptions
 | 
				
			||||||
		watchListFeatureEnabled bool
 | 
							watchListFeatureEnabled bool
 | 
				
			||||||
		expectErrors            []string
 | 
							expectErrors            []string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid-default",
 | 
							name: "valid-default",
 | 
				
			||||||
		opts: internalversion.ListOptions{},
 | 
							opts: internalversion.ListOptions{},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid-resourceversionmatch-exact",
 | 
							name: "valid-resourceversionmatch-exact",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			ResourceVersion:      "1",
 | 
								ResourceVersion:      "1",
 | 
				
			||||||
			ResourceVersionMatch: metav1.ResourceVersionMatchExact,
 | 
								ResourceVersionMatch: metav1.ResourceVersionMatchExact,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid-resourceversionmatch-exact",
 | 
							name: "invalid-resourceversionmatch-exact",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			ResourceVersion:      "0",
 | 
								ResourceVersion:      "0",
 | 
				
			||||||
			ResourceVersionMatch: metav1.ResourceVersionMatchExact,
 | 
								ResourceVersionMatch: metav1.ResourceVersionMatchExact,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErrors: []string{"resourceVersionMatch: Forbidden: resourceVersionMatch \"exact\" is forbidden for resourceVersion \"0\""},
 | 
							expectErrors: []string{"resourceVersionMatch: Forbidden: resourceVersionMatch \"exact\" is forbidden for resourceVersion \"0\""},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid-resourceversionmatch-notolderthan",
 | 
							name: "valid-resourceversionmatch-notolderthan",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			ResourceVersion:      "0",
 | 
								ResourceVersion:      "0",
 | 
				
			||||||
			ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
 | 
								ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "invalid-resourceversionmatch",
 | 
							name: "invalid-resourceversionmatch",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			ResourceVersion:      "0",
 | 
								ResourceVersion:      "0",
 | 
				
			||||||
			ResourceVersionMatch: "foo",
 | 
								ResourceVersionMatch: "foo",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErrors: []string{"resourceVersionMatch: Unsupported value: \"foo\": supported values: \"Exact\", \"NotOlderThan\", \"\""},
 | 
							expectErrors: []string{"resourceVersionMatch: Unsupported value: \"foo\": supported values: \"Exact\", \"NotOlderThan\", \"\""},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "list-sendInitialEvents-forbidden",
 | 
							name: "list-sendInitialEvents-forbidden",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			SendInitialEvents: boolPtrFn(true),
 | 
								SendInitialEvents: boolPtrFn(true),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErrors: []string{"sendInitialEvents: Forbidden: sendInitialEvents is forbidden for list"},
 | 
							expectErrors: []string{"sendInitialEvents: Forbidden: sendInitialEvents is forbidden for list"},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid-watch-default",
 | 
							name: "valid-watch-default",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			Watch: true,
 | 
								Watch: true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid-watch-sendInitialEvents-on",
 | 
							name: "valid-watch-sendInitialEvents-on",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			Watch:                true,
 | 
								Watch:                true,
 | 
				
			||||||
@@ -89,8 +82,7 @@ func TestValidateListOptions(t *testing.T) {
 | 
				
			|||||||
			AllowWatchBookmarks:  true,
 | 
								AllowWatchBookmarks:  true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		watchListFeatureEnabled: true,
 | 
							watchListFeatureEnabled: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "valid-watch-sendInitialEvents-off",
 | 
							name: "valid-watch-sendInitialEvents-off",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			Watch:                true,
 | 
								Watch:                true,
 | 
				
			||||||
@@ -99,24 +91,21 @@ func TestValidateListOptions(t *testing.T) {
 | 
				
			|||||||
			AllowWatchBookmarks:  true,
 | 
								AllowWatchBookmarks:  true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		watchListFeatureEnabled: true,
 | 
							watchListFeatureEnabled: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "watch-resourceversionmatch-without-sendInitialEvents-forbidden",
 | 
							name: "watch-resourceversionmatch-without-sendInitialEvents-forbidden",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			Watch:                true,
 | 
								Watch:                true,
 | 
				
			||||||
			ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
 | 
								ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErrors: []string{"resourceVersionMatch: Forbidden: resourceVersionMatch is forbidden for watch unless sendInitialEvents is provided"},
 | 
							expectErrors: []string{"resourceVersionMatch: Forbidden: resourceVersionMatch is forbidden for watch unless sendInitialEvents is provided"},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "watch-sendInitialEvents-without-resourceversionmatch-forbidden",
 | 
							name: "watch-sendInitialEvents-without-resourceversionmatch-forbidden",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			Watch:             true,
 | 
								Watch:             true,
 | 
				
			||||||
			SendInitialEvents: boolPtrFn(true),
 | 
								SendInitialEvents: boolPtrFn(true),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErrors: []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
 | 
							expectErrors: []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "watch-sendInitialEvents-with-exact-resourceversionmatch-forbidden",
 | 
							name: "watch-sendInitialEvents-with-exact-resourceversionmatch-forbidden",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			Watch:                true,
 | 
								Watch:                true,
 | 
				
			||||||
@@ -126,8 +115,7 @@ func TestValidateListOptions(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		watchListFeatureEnabled: true,
 | 
							watchListFeatureEnabled: true,
 | 
				
			||||||
		expectErrors:            []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "resourceVersionMatch: Unsupported value: \"Exact\": supported values: \"NotOlderThan\""},
 | 
							expectErrors:            []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "resourceVersionMatch: Unsupported value: \"Exact\": supported values: \"NotOlderThan\""},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "watch-sendInitialEvents-on-with-empty-resourceversionmatch-forbidden",
 | 
							name: "watch-sendInitialEvents-on-with-empty-resourceversionmatch-forbidden",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			Watch:                true,
 | 
								Watch:                true,
 | 
				
			||||||
@@ -135,8 +123,7 @@ func TestValidateListOptions(t *testing.T) {
 | 
				
			|||||||
			ResourceVersionMatch: "",
 | 
								ResourceVersionMatch: "",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErrors: []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
 | 
							expectErrors: []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "watch-sendInitialEvents-off-with-empty-resourceversionmatch-forbidden",
 | 
							name: "watch-sendInitialEvents-off-with-empty-resourceversionmatch-forbidden",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			Watch:                true,
 | 
								Watch:                true,
 | 
				
			||||||
@@ -144,8 +131,7 @@ func TestValidateListOptions(t *testing.T) {
 | 
				
			|||||||
			ResourceVersionMatch: "",
 | 
								ResourceVersionMatch: "",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErrors: []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
 | 
							expectErrors: []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "watch-sendInitialEvents-with-incorrect-resourceversionmatch-forbidden",
 | 
							name: "watch-sendInitialEvents-with-incorrect-resourceversionmatch-forbidden",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			Watch:                true,
 | 
								Watch:                true,
 | 
				
			||||||
@@ -155,8 +141,7 @@ func TestValidateListOptions(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		watchListFeatureEnabled: true,
 | 
							watchListFeatureEnabled: true,
 | 
				
			||||||
		expectErrors:            []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "resourceVersionMatch: Unsupported value: \"incorrect\": supported values: \"NotOlderThan\""},
 | 
							expectErrors:            []string{"resourceVersionMatch: Forbidden: sendInitialEvents requires setting resourceVersionMatch to NotOlderThan", "resourceVersionMatch: Unsupported value: \"incorrect\": supported values: \"NotOlderThan\""},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		// note that validating allowWatchBookmarks would break backward compatibility
 | 
							// note that validating allowWatchBookmarks would break backward compatibility
 | 
				
			||||||
		// because it was possible to request initial events via resourceVersion=0 before this change
 | 
							// because it was possible to request initial events via resourceVersion=0 before this change
 | 
				
			||||||
		name: "watch-sendInitialEvents-no-allowWatchBookmark",
 | 
							name: "watch-sendInitialEvents-no-allowWatchBookmark",
 | 
				
			||||||
@@ -166,8 +151,7 @@ func TestValidateListOptions(t *testing.T) {
 | 
				
			|||||||
			ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
 | 
								ResourceVersionMatch: metav1.ResourceVersionMatchNotOlderThan,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		watchListFeatureEnabled: true,
 | 
							watchListFeatureEnabled: true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "watch-sendInitialEvents-no-watchlist-fg-disabled",
 | 
							name: "watch-sendInitialEvents-no-watchlist-fg-disabled",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			Watch:                true,
 | 
								Watch:                true,
 | 
				
			||||||
@@ -176,8 +160,7 @@ func TestValidateListOptions(t *testing.T) {
 | 
				
			|||||||
			AllowWatchBookmarks:  true,
 | 
								AllowWatchBookmarks:  true,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		expectErrors: []string{"sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
 | 
							expectErrors: []string{"sendInitialEvents: Forbidden: sendInitialEvents is forbidden for watch unless the WatchList feature gate is enabled"},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "watch-sendInitialEvents-no-watchlist-fg-disabled",
 | 
							name: "watch-sendInitialEvents-no-watchlist-fg-disabled",
 | 
				
			||||||
		opts: internalversion.ListOptions{
 | 
							opts: internalversion.ListOptions{
 | 
				
			||||||
			Watch:                true,
 | 
								Watch:                true,
 | 
				
			||||||
@@ -188,8 +171,7 @@ func TestValidateListOptions(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		watchListFeatureEnabled: true,
 | 
							watchListFeatureEnabled: true,
 | 
				
			||||||
		expectErrors:            []string{"resourceVersionMatch: Forbidden: resourceVersionMatch is forbidden when continue is provided"},
 | 
							expectErrors:            []string{"resourceVersionMatch: Forbidden: resourceVersionMatch is forbidden when continue is provided"},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range cases {
 | 
						for _, tc := range cases {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -136,31 +136,26 @@ func TestValidPatchOptions(t *testing.T) {
 | 
				
			|||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		opts      metav1.PatchOptions
 | 
							opts      metav1.PatchOptions
 | 
				
			||||||
		patchType types.PatchType
 | 
							patchType types.PatchType
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		opts: metav1.PatchOptions{
 | 
							opts: metav1.PatchOptions{
 | 
				
			||||||
			Force:        boolPtr(true),
 | 
								Force:        boolPtr(true),
 | 
				
			||||||
			FieldManager: "kubectl",
 | 
								FieldManager: "kubectl",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		patchType: types.ApplyPatchType,
 | 
							patchType: types.ApplyPatchType,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		opts: metav1.PatchOptions{
 | 
							opts: metav1.PatchOptions{
 | 
				
			||||||
			FieldManager: "kubectl",
 | 
								FieldManager: "kubectl",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		patchType: types.ApplyPatchType,
 | 
							patchType: types.ApplyPatchType,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		opts:      metav1.PatchOptions{},
 | 
							opts:      metav1.PatchOptions{},
 | 
				
			||||||
		patchType: types.MergePatchType,
 | 
							patchType: types.MergePatchType,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		opts: metav1.PatchOptions{
 | 
							opts: metav1.PatchOptions{
 | 
				
			||||||
			FieldManager: "patcher",
 | 
								FieldManager: "patcher",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		patchType: types.MergePatchType,
 | 
							patchType: types.MergePatchType,
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, test := range tests {
 | 
						for _, test := range tests {
 | 
				
			||||||
		t.Run(fmt.Sprintf("%v", test.opts), func(t *testing.T) {
 | 
							t.Run(fmt.Sprintf("%v", test.opts), func(t *testing.T) {
 | 
				
			||||||
@@ -243,36 +238,30 @@ func TestValidateFieldManagerInvalid(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestValidateManagedFieldsInvalid(t *testing.T) {
 | 
					func TestValidateManagedFieldsInvalid(t *testing.T) {
 | 
				
			||||||
	tests := []metav1.ManagedFieldsEntry{
 | 
						tests := []metav1.ManagedFieldsEntry{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Operation:  metav1.ManagedFieldsOperationUpdate,
 | 
							Operation:  metav1.ManagedFieldsOperationUpdate,
 | 
				
			||||||
		FieldsType: "RandomVersion",
 | 
							FieldsType: "RandomVersion",
 | 
				
			||||||
		APIVersion: "v1",
 | 
							APIVersion: "v1",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Operation:  "RandomOperation",
 | 
							Operation:  "RandomOperation",
 | 
				
			||||||
		FieldsType: "FieldsV1",
 | 
							FieldsType: "FieldsV1",
 | 
				
			||||||
		APIVersion: "v1",
 | 
							APIVersion: "v1",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		// Operation is missing
 | 
							// Operation is missing
 | 
				
			||||||
		FieldsType: "FieldsV1",
 | 
							FieldsType: "FieldsV1",
 | 
				
			||||||
		APIVersion: "v1",
 | 
							APIVersion: "v1",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Operation:  metav1.ManagedFieldsOperationUpdate,
 | 
							Operation:  metav1.ManagedFieldsOperationUpdate,
 | 
				
			||||||
		FieldsType: "FieldsV1",
 | 
							FieldsType: "FieldsV1",
 | 
				
			||||||
		// Invalid fieldManager
 | 
							// Invalid fieldManager
 | 
				
			||||||
		Manager:    "field\nmanager",
 | 
							Manager:    "field\nmanager",
 | 
				
			||||||
		APIVersion: "v1",
 | 
							APIVersion: "v1",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Operation:   metav1.ManagedFieldsOperationApply,
 | 
							Operation:   metav1.ManagedFieldsOperationApply,
 | 
				
			||||||
		FieldsType:  "FieldsV1",
 | 
							FieldsType:  "FieldsV1",
 | 
				
			||||||
		APIVersion:  "v1",
 | 
							APIVersion:  "v1",
 | 
				
			||||||
		Subresource: "TooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLong",
 | 
							Subresource: "TooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLongTooLong",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, test := range tests {
 | 
						for _, test := range tests {
 | 
				
			||||||
		t.Run(fmt.Sprintf("%#v", test), func(t *testing.T) {
 | 
							t.Run(fmt.Sprintf("%#v", test), func(t *testing.T) {
 | 
				
			||||||
@@ -285,30 +274,25 @@ func TestValidateManagedFieldsInvalid(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestValidateMangedFieldsValid(t *testing.T) {
 | 
					func TestValidateMangedFieldsValid(t *testing.T) {
 | 
				
			||||||
	tests := []metav1.ManagedFieldsEntry{
 | 
						tests := []metav1.ManagedFieldsEntry{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Operation:  metav1.ManagedFieldsOperationUpdate,
 | 
							Operation:  metav1.ManagedFieldsOperationUpdate,
 | 
				
			||||||
		APIVersion: "v1",
 | 
							APIVersion: "v1",
 | 
				
			||||||
		// FieldsType is missing
 | 
							// FieldsType is missing
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Operation:  metav1.ManagedFieldsOperationUpdate,
 | 
							Operation:  metav1.ManagedFieldsOperationUpdate,
 | 
				
			||||||
		FieldsType: "FieldsV1",
 | 
							FieldsType: "FieldsV1",
 | 
				
			||||||
		APIVersion: "v1",
 | 
							APIVersion: "v1",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Operation:   metav1.ManagedFieldsOperationApply,
 | 
							Operation:   metav1.ManagedFieldsOperationApply,
 | 
				
			||||||
		FieldsType:  "FieldsV1",
 | 
							FieldsType:  "FieldsV1",
 | 
				
			||||||
		APIVersion:  "v1",
 | 
							APIVersion:  "v1",
 | 
				
			||||||
		Subresource: "scale",
 | 
							Subresource: "scale",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		Operation:  metav1.ManagedFieldsOperationApply,
 | 
							Operation:  metav1.ManagedFieldsOperationApply,
 | 
				
			||||||
		FieldsType: "FieldsV1",
 | 
							FieldsType: "FieldsV1",
 | 
				
			||||||
		APIVersion: "v1",
 | 
							APIVersion: "v1",
 | 
				
			||||||
		Manager:    "🍔",
 | 
							Manager:    "🍔",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, test := range tests {
 | 
						for _, test := range tests {
 | 
				
			||||||
		t.Run(fmt.Sprintf("%#v", test), func(t *testing.T) {
 | 
							t.Run(fmt.Sprintf("%#v", test), func(t *testing.T) {
 | 
				
			||||||
@@ -325,8 +309,7 @@ func TestValidateConditions(t *testing.T) {
 | 
				
			|||||||
		name         string
 | 
							name         string
 | 
				
			||||||
		conditions   []metav1.Condition
 | 
							conditions   []metav1.Condition
 | 
				
			||||||
		validateErrs func(t *testing.T, errs field.ErrorList)
 | 
							validateErrs func(t *testing.T, errs field.ErrorList)
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "bunch-of-invalid-fields",
 | 
							name: "bunch-of-invalid-fields",
 | 
				
			||||||
		conditions: []metav1.Condition{{
 | 
							conditions: []metav1.Condition{{
 | 
				
			||||||
			Type:               ":invalid",
 | 
								Type:               ":invalid",
 | 
				
			||||||
@@ -358,27 +341,22 @@ func TestValidateConditions(t *testing.T) {
 | 
				
			|||||||
				t.Errorf("missing %q in\n%v", needle, errorsAsString(errs))
 | 
									t.Errorf("missing %q in\n%v", needle, errorsAsString(errs))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "duplicates",
 | 
							name: "duplicates",
 | 
				
			||||||
		conditions: []metav1.Condition{{
 | 
							conditions: []metav1.Condition{{
 | 
				
			||||||
			Type: "First",
 | 
								Type: "First",
 | 
				
			||||||
			},
 | 
							}, {
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Type: "Second",
 | 
								Type: "Second",
 | 
				
			||||||
				},
 | 
							}, {
 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Type: "First",
 | 
								Type: "First",
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
		validateErrs: func(t *testing.T, errs field.ErrorList) {
 | 
							validateErrs: func(t *testing.T, errs field.ErrorList) {
 | 
				
			||||||
			needle := `status.conditions[2].type: Duplicate value: "First"`
 | 
								needle := `status.conditions[2].type: Duplicate value: "First"`
 | 
				
			||||||
			if !hasError(errs, needle) {
 | 
								if !hasError(errs, needle) {
 | 
				
			||||||
				t.Errorf("missing %q in\n%v", needle, errorsAsString(errs))
 | 
									t.Errorf("missing %q in\n%v", needle, errorsAsString(errs))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "colon-allowed-in-reason",
 | 
							name: "colon-allowed-in-reason",
 | 
				
			||||||
		conditions: []metav1.Condition{{
 | 
							conditions: []metav1.Condition{{
 | 
				
			||||||
			Type:   "First",
 | 
								Type:   "First",
 | 
				
			||||||
@@ -390,8 +368,7 @@ func TestValidateConditions(t *testing.T) {
 | 
				
			|||||||
				t.Errorf("has %q in\n%v", needle, errorsAsString(errs))
 | 
									t.Errorf("has %q in\n%v", needle, errorsAsString(errs))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "comma-allowed-in-reason",
 | 
							name: "comma-allowed-in-reason",
 | 
				
			||||||
		conditions: []metav1.Condition{{
 | 
							conditions: []metav1.Condition{{
 | 
				
			||||||
			Type:   "First",
 | 
								Type:   "First",
 | 
				
			||||||
@@ -403,8 +380,7 @@ func TestValidateConditions(t *testing.T) {
 | 
				
			|||||||
				t.Errorf("has %q in\n%v", needle, errorsAsString(errs))
 | 
									t.Errorf("has %q in\n%v", needle, errorsAsString(errs))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "reason-does-not-end-in-delimiter",
 | 
							name: "reason-does-not-end-in-delimiter",
 | 
				
			||||||
		conditions: []metav1.Condition{{
 | 
							conditions: []metav1.Condition{{
 | 
				
			||||||
			Type:   "First",
 | 
								Type:   "First",
 | 
				
			||||||
@@ -416,8 +392,7 @@ func TestValidateConditions(t *testing.T) {
 | 
				
			|||||||
				t.Errorf("missing %q in\n%v", needle, errorsAsString(errs))
 | 
									t.Errorf("missing %q in\n%v", needle, errorsAsString(errs))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, test := range tests {
 | 
						for _, test := range tests {
 | 
				
			||||||
		t.Run(test.name, func(t *testing.T) {
 | 
							t.Run(test.name, func(t *testing.T) {
 | 
				
			||||||
@@ -433,31 +408,25 @@ func TestLabelSelectorMatchExpression(t *testing.T) {
 | 
				
			|||||||
		labelSelector   *metav1.LabelSelector
 | 
							labelSelector   *metav1.LabelSelector
 | 
				
			||||||
		wantErrorNumber int
 | 
							wantErrorNumber int
 | 
				
			||||||
		validateErrs    func(t *testing.T, errs field.ErrorList)
 | 
							validateErrs    func(t *testing.T, errs field.ErrorList)
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "Valid LabelSelector",
 | 
							name: "Valid LabelSelector",
 | 
				
			||||||
		labelSelector: &metav1.LabelSelector{
 | 
							labelSelector: &metav1.LabelSelector{
 | 
				
			||||||
				MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
								MatchExpressions: []metav1.LabelSelectorRequirement{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Key:      "key",
 | 
									Key:      "key",
 | 
				
			||||||
				Operator: metav1.LabelSelectorOpIn,
 | 
									Operator: metav1.LabelSelectorOpIn,
 | 
				
			||||||
				Values:   []string{"value"},
 | 
									Values:   []string{"value"},
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		wantErrorNumber: 0,
 | 
							wantErrorNumber: 0,
 | 
				
			||||||
		validateErrs:    nil,
 | 
							validateErrs:    nil,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "MatchExpression's key name isn't valid",
 | 
							name: "MatchExpression's key name isn't valid",
 | 
				
			||||||
		labelSelector: &metav1.LabelSelector{
 | 
							labelSelector: &metav1.LabelSelector{
 | 
				
			||||||
				MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
								MatchExpressions: []metav1.LabelSelectorRequirement{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Key:      "-key",
 | 
									Key:      "-key",
 | 
				
			||||||
				Operator: metav1.LabelSelectorOpIn,
 | 
									Operator: metav1.LabelSelectorOpIn,
 | 
				
			||||||
				Values:   []string{"value"},
 | 
									Values:   []string{"value"},
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		wantErrorNumber: 1,
 | 
							wantErrorNumber: 1,
 | 
				
			||||||
		validateErrs: func(t *testing.T, errs field.ErrorList) {
 | 
							validateErrs: func(t *testing.T, errs field.ErrorList) {
 | 
				
			||||||
@@ -466,17 +435,14 @@ func TestLabelSelectorMatchExpression(t *testing.T) {
 | 
				
			|||||||
				t.Errorf("missing %q in\n%v", errMessage, errorsAsString(errs))
 | 
									t.Errorf("missing %q in\n%v", errMessage, errorsAsString(errs))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "MatchExpression's operator isn't valid",
 | 
							name: "MatchExpression's operator isn't valid",
 | 
				
			||||||
		labelSelector: &metav1.LabelSelector{
 | 
							labelSelector: &metav1.LabelSelector{
 | 
				
			||||||
				MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
								MatchExpressions: []metav1.LabelSelectorRequirement{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Key:      "key",
 | 
									Key:      "key",
 | 
				
			||||||
				Operator: "abc",
 | 
									Operator: "abc",
 | 
				
			||||||
				Values:   []string{"value"},
 | 
									Values:   []string{"value"},
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		wantErrorNumber: 1,
 | 
							wantErrorNumber: 1,
 | 
				
			||||||
		validateErrs: func(t *testing.T, errs field.ErrorList) {
 | 
							validateErrs: func(t *testing.T, errs field.ErrorList) {
 | 
				
			||||||
@@ -485,17 +451,14 @@ func TestLabelSelectorMatchExpression(t *testing.T) {
 | 
				
			|||||||
				t.Errorf("missing %q in\n%v", errMessage, errorsAsString(errs))
 | 
									t.Errorf("missing %q in\n%v", errMessage, errorsAsString(errs))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name: "MatchExpression's value name isn't valid",
 | 
							name: "MatchExpression's value name isn't valid",
 | 
				
			||||||
		labelSelector: &metav1.LabelSelector{
 | 
							labelSelector: &metav1.LabelSelector{
 | 
				
			||||||
				MatchExpressions: []metav1.LabelSelectorRequirement{
 | 
								MatchExpressions: []metav1.LabelSelectorRequirement{{
 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
				Key:      "key",
 | 
									Key:      "key",
 | 
				
			||||||
				Operator: metav1.LabelSelectorOpIn,
 | 
									Operator: metav1.LabelSelectorOpIn,
 | 
				
			||||||
				Values:   []string{"-value"},
 | 
									Values:   []string{"-value"},
 | 
				
			||||||
					},
 | 
								}},
 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		wantErrorNumber: 1,
 | 
							wantErrorNumber: 1,
 | 
				
			||||||
		validateErrs: func(t *testing.T, errs field.ErrorList) {
 | 
							validateErrs: func(t *testing.T, errs field.ErrorList) {
 | 
				
			||||||
@@ -504,8 +467,7 @@ func TestLabelSelectorMatchExpression(t *testing.T) {
 | 
				
			|||||||
				t.Errorf("missing %q in\n%v", errMessage, errorsAsString(errs))
 | 
									t.Errorf("missing %q in\n%v", errMessage, errorsAsString(errs))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for index, testCase := range testCases {
 | 
						for index, testCase := range testCases {
 | 
				
			||||||
		t.Run(testCase.name, func(t *testing.T) {
 | 
							t.Run(testCase.name, func(t *testing.T) {
 | 
				
			||||||
			allErrs := ValidateLabelSelector(testCase.labelSelector, LabelSelectorValidationOptions{false}, field.NewPath("labelSelector"))
 | 
								allErrs := ValidateLabelSelector(testCase.labelSelector, LabelSelectorValidationOptions{false}, field.NewPath("labelSelector"))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -630,33 +630,27 @@ func TestIsFullyQualifiedName(t *testing.T) {
 | 
				
			|||||||
		name       string
 | 
							name       string
 | 
				
			||||||
		targetName string
 | 
							targetName string
 | 
				
			||||||
		err        string
 | 
							err        string
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:       "name needs to be fully qualified, i.e., contains at least 2 dots",
 | 
							name:       "name needs to be fully qualified, i.e., contains at least 2 dots",
 | 
				
			||||||
		targetName: "k8s.io",
 | 
							targetName: "k8s.io",
 | 
				
			||||||
		err:        "should be a domain with at least three segments separated by dots",
 | 
							err:        "should be a domain with at least three segments separated by dots",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:       "name should not include scheme",
 | 
							name:       "name should not include scheme",
 | 
				
			||||||
		targetName: "http://foo.k8s.io",
 | 
							targetName: "http://foo.k8s.io",
 | 
				
			||||||
		err:        "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters",
 | 
							err:        "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:       "email should be invalid",
 | 
							name:       "email should be invalid",
 | 
				
			||||||
		targetName: "example@foo.k8s.io",
 | 
							targetName: "example@foo.k8s.io",
 | 
				
			||||||
		err:        "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters",
 | 
							err:        "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:       "name cannot be empty",
 | 
							name:       "name cannot be empty",
 | 
				
			||||||
		targetName: "",
 | 
							targetName: "",
 | 
				
			||||||
		err:        "Required value",
 | 
							err:        "Required value",
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:       "name must conform to RFC 1123",
 | 
							name:       "name must conform to RFC 1123",
 | 
				
			||||||
		targetName: "A.B.C",
 | 
							targetName: "A.B.C",
 | 
				
			||||||
		err:        "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters",
 | 
							err:        "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters",
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for _, tc := range messageTests {
 | 
						for _, tc := range messageTests {
 | 
				
			||||||
		err := IsFullyQualifiedName(field.NewPath(""), tc.targetName).ToAggregate()
 | 
							err := IsFullyQualifiedName(field.NewPath(""), tc.targetName).ToAggregate()
 | 
				
			||||||
		switch {
 | 
							switch {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,22 +23,16 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestValidateConfiguration(t *testing.T) {
 | 
					func TestValidateConfiguration(t *testing.T) {
 | 
				
			||||||
	successCases := []resourcequotaapi.Configuration{
 | 
						successCases := []resourcequotaapi.Configuration{{
 | 
				
			||||||
		{
 | 
							LimitedResources: []resourcequotaapi.LimitedResource{{
 | 
				
			||||||
			LimitedResources: []resourcequotaapi.LimitedResource{
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Resource:      "pods",
 | 
								Resource:      "pods",
 | 
				
			||||||
			MatchContains: []string{"requests.cpu"},
 | 
								MatchContains: []string{"requests.cpu"},
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
						}, {
 | 
				
			||||||
		},
 | 
							LimitedResources: []resourcequotaapi.LimitedResource{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			LimitedResources: []resourcequotaapi.LimitedResource{
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
			Resource:      "persistentvolumeclaims",
 | 
								Resource:      "persistentvolumeclaims",
 | 
				
			||||||
			MatchContains: []string{"requests.storage"},
 | 
								MatchContains: []string{"requests.storage"},
 | 
				
			||||||
				},
 | 
							}},
 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for i := range successCases {
 | 
						for i := range successCases {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -134,11 +134,9 @@ func TestValidatePolicy(t *testing.T) {
 | 
				
			|||||||
	policy := audit.Policy{OmitStages: []audit.Stage{
 | 
						policy := audit.Policy{OmitStages: []audit.Stage{
 | 
				
			||||||
		audit.Stage("foo"),
 | 
							audit.Stage("foo"),
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
		Rules: []audit.PolicyRule{
 | 
							Rules: []audit.PolicyRule{{
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
			Level: audit.LevelMetadata,
 | 
								Level: audit.LevelMetadata,
 | 
				
			||||||
			},
 | 
							}},
 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	errorCases = append(errorCases, policy)
 | 
						errorCases = append(errorCases, policy)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -748,37 +748,31 @@ func TestErrConfigurationInvalidWithErrorsIs(t *testing.T) {
 | 
				
			|||||||
		err          error
 | 
							err          error
 | 
				
			||||||
		matchAgainst error
 | 
							matchAgainst error
 | 
				
			||||||
		expectMatch  bool
 | 
							expectMatch  bool
 | 
				
			||||||
	}{
 | 
						}{{
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "no match",
 | 
							name:         "no match",
 | 
				
			||||||
		err:          errConfigurationInvalid{errors.New("my-error"), errors.New("my-other-error")},
 | 
							err:          errConfigurationInvalid{errors.New("my-error"), errors.New("my-other-error")},
 | 
				
			||||||
		matchAgainst: fmt.Errorf("no entry %s", "here"),
 | 
							matchAgainst: fmt.Errorf("no entry %s", "here"),
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "match via .Is()",
 | 
							name:         "match via .Is()",
 | 
				
			||||||
		err:          errConfigurationInvalid{errors.New("forbidden"), alwaysMatchingError{}},
 | 
							err:          errConfigurationInvalid{errors.New("forbidden"), alwaysMatchingError{}},
 | 
				
			||||||
		matchAgainst: errors.New("unauthorized"),
 | 
							matchAgainst: errors.New("unauthorized"),
 | 
				
			||||||
		expectMatch:  true,
 | 
							expectMatch:  true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "match via equality",
 | 
							name:         "match via equality",
 | 
				
			||||||
		err:          errConfigurationInvalid{errors.New("err"), someError{}},
 | 
							err:          errConfigurationInvalid{errors.New("err"), someError{}},
 | 
				
			||||||
		matchAgainst: someError{},
 | 
							matchAgainst: someError{},
 | 
				
			||||||
		expectMatch:  true,
 | 
							expectMatch:  true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "match via nested aggregate",
 | 
							name:         "match via nested aggregate",
 | 
				
			||||||
		err:          errConfigurationInvalid{errors.New("closed today"), errConfigurationInvalid{errConfigurationInvalid{someError{}}}},
 | 
							err:          errConfigurationInvalid{errors.New("closed today"), errConfigurationInvalid{errConfigurationInvalid{someError{}}}},
 | 
				
			||||||
		matchAgainst: someError{},
 | 
							matchAgainst: someError{},
 | 
				
			||||||
		expectMatch:  true,
 | 
							expectMatch:  true,
 | 
				
			||||||
		},
 | 
						}, {
 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
		name:         "match via wrapped aggregate",
 | 
							name:         "match via wrapped aggregate",
 | 
				
			||||||
		err:          fmt.Errorf("wrap: %w", errConfigurationInvalid{errors.New("err"), someError{}}),
 | 
							err:          fmt.Errorf("wrap: %w", errConfigurationInvalid{errors.New("err"), someError{}}),
 | 
				
			||||||
		matchAgainst: someError{},
 | 
							matchAgainst: someError{},
 | 
				
			||||||
		expectMatch:  true,
 | 
							expectMatch:  true,
 | 
				
			||||||
		},
 | 
						}}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, tc := range testCases {
 | 
						for _, tc := range testCases {
 | 
				
			||||||
		t.Run(tc.name, func(t *testing.T) {
 | 
							t.Run(tc.name, func(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user