mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 02:43:36 +00:00
Fresh dep ensure
This commit is contained in:
1
vendor/k8s.io/kubernetes/plugin/pkg/admission/OWNERS
generated
vendored
1
vendor/k8s.io/kubernetes/plugin/pkg/admission/OWNERS
generated
vendored
@ -4,3 +4,4 @@ approvers:
|
||||
reviewers:
|
||||
- derekwaynecarr
|
||||
- deads2k
|
||||
- yue9944882
|
||||
|
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/admit/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/admit/BUILD
generated
vendored
@ -11,8 +11,8 @@ go_library(
|
||||
srcs = ["admission.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/admit",
|
||||
deps = [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -22,7 +22,7 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/admit/admission.go
generated
vendored
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/admit/admission.go
generated
vendored
@ -19,8 +19,8 @@ package admit
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
@ -58,7 +58,7 @@ func (alwaysAdmit) Handles(operation admission.Operation) bool {
|
||||
// NewAlwaysAdmit creates a new always admit admission handler
|
||||
func NewAlwaysAdmit() admission.Interface {
|
||||
// DEPRECATED: AlwaysAdmit admit all admission request, it is no use.
|
||||
glog.Warningf("%s admission controller is deprecated. "+
|
||||
klog.Warningf("%s admission controller is deprecated. "+
|
||||
"Please remove this controller from your configuration files and scripts.", PluginName)
|
||||
return new(alwaysAdmit)
|
||||
}
|
||||
|
2
vendor/k8s.io/kubernetes/plugin/pkg/admission/admit/admission_test.go
generated
vendored
2
vendor/k8s.io/kubernetes/plugin/pkg/admission/admit/admission_test.go
generated
vendored
@ -25,7 +25,7 @@ import (
|
||||
|
||||
func TestAdmissionNonNilAttribute(t *testing.T) {
|
||||
handler := NewAlwaysAdmit()
|
||||
err := handler.(*alwaysAdmit).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, nil))
|
||||
err := handler.(*alwaysAdmit).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned from admission handler")
|
||||
}
|
||||
|
12
vendor/k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages/BUILD
generated
vendored
12
vendor/k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages/BUILD
generated
vendored
@ -12,9 +12,9 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -24,9 +24,9 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages/admission_test.go
generated
vendored
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages/admission_test.go
generated
vendored
@ -47,7 +47,7 @@ func TestAdmission(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
err := handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||
err := handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned from admission handler")
|
||||
}
|
||||
@ -84,7 +84,7 @@ func TestValidate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
expectedError := `pods "123" is forbidden: spec.initContainers[0].imagePullPolicy: Unsupported value: "": supported values: "Always"`
|
||||
err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||
err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err == nil {
|
||||
t.Fatal("missing expected error")
|
||||
}
|
||||
@ -139,7 +139,7 @@ func TestOtherResources(t *testing.T) {
|
||||
for _, tc := range tests {
|
||||
handler := &AlwaysPullImages{}
|
||||
|
||||
err := handler.Admit(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, nil))
|
||||
err := handler.Admit(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, false, nil))
|
||||
|
||||
if tc.expectError {
|
||||
if err == nil {
|
||||
|
10
vendor/k8s.io/kubernetes/plugin/pkg/admission/antiaffinity/BUILD
generated
vendored
10
vendor/k8s.io/kubernetes/plugin/pkg/admission/antiaffinity/BUILD
generated
vendored
@ -16,8 +16,8 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -28,9 +28,9 @@ go_test(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/antiaffinity/admission_test.go
generated
vendored
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/antiaffinity/admission_test.go
generated
vendored
@ -199,7 +199,7 @@ func TestInterPodAffinityAdmission(t *testing.T) {
|
||||
}
|
||||
for _, test := range tests {
|
||||
pod.Spec.Affinity = test.affinity
|
||||
err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil))
|
||||
err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
|
||||
|
||||
if test.errorExpected && err == nil {
|
||||
t.Errorf("Expected error for Anti Affinity %+v but did not get an error", test.affinity)
|
||||
@ -267,7 +267,7 @@ func TestOtherResources(t *testing.T) {
|
||||
for _, tc := range tests {
|
||||
handler := &Plugin{}
|
||||
|
||||
err := handler.Validate(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, nil))
|
||||
err := handler.Validate(admission.NewAttributesRecord(tc.object, nil, api.Kind(tc.kind).WithVersion("version"), namespace, name, api.Resource(tc.resource).WithVersion("version"), tc.subresource, admission.Create, false, nil))
|
||||
|
||||
if tc.expectError {
|
||||
if err == nil {
|
||||
|
10
vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/BUILD
generated
vendored
10
vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/BUILD
generated
vendored
@ -13,8 +13,8 @@ go_test(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/core/helper:go_default_library",
|
||||
"//pkg/scheduler/algorithm:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//pkg/scheduler/api:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -24,9 +24,9 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/scheduler/algorithm:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//pkg/scheduler/api:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
10
vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/admission.go
generated
vendored
10
vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/admission.go
generated
vendored
@ -24,7 +24,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
@ -40,14 +40,14 @@ var (
|
||||
" that is added by default to every pod that does not already have such a toleration.")
|
||||
|
||||
notReadyToleration = api.Toleration{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: defaultNotReadyTolerationSeconds,
|
||||
}
|
||||
|
||||
unreachableToleration = api.Toleration{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: defaultUnreachableTolerationSeconds,
|
||||
@ -101,12 +101,12 @@ func (p *Plugin) Admit(attributes admission.Attributes) (err error) {
|
||||
toleratesNodeNotReady := false
|
||||
toleratesNodeUnreachable := false
|
||||
for _, toleration := range tolerations {
|
||||
if (toleration.Key == algorithm.TaintNodeNotReady || len(toleration.Key) == 0) &&
|
||||
if (toleration.Key == schedulerapi.TaintNodeNotReady || len(toleration.Key) == 0) &&
|
||||
(toleration.Effect == api.TaintEffectNoExecute || len(toleration.Effect) == 0) {
|
||||
toleratesNodeNotReady = true
|
||||
}
|
||||
|
||||
if (toleration.Key == algorithm.TaintNodeUnreachable || len(toleration.Key) == 0) &&
|
||||
if (toleration.Key == schedulerapi.TaintNodeUnreachable || len(toleration.Key) == 0) &&
|
||||
(toleration.Effect == api.TaintEffectNoExecute || len(toleration.Effect) == 0) {
|
||||
toleratesNodeUnreachable = true
|
||||
}
|
||||
|
66
vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/admission_test.go
generated
vendored
66
vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/admission_test.go
generated
vendored
@ -22,7 +22,7 @@ import (
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
|
||||
)
|
||||
|
||||
func TestForgivenessAdmission(t *testing.T) {
|
||||
@ -48,13 +48,13 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
@ -70,13 +70,13 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.DeprecatedTaintNodeNotReady,
|
||||
Key: schedulerapi.DeprecatedTaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
},
|
||||
{
|
||||
Key: algorithm.DeprecatedTaintNodeUnreachable,
|
||||
Key: schedulerapi.DeprecatedTaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
@ -88,25 +88,25 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.DeprecatedTaintNodeNotReady,
|
||||
Key: schedulerapi.DeprecatedTaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
},
|
||||
{
|
||||
Key: algorithm.DeprecatedTaintNodeUnreachable,
|
||||
Key: schedulerapi.DeprecatedTaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
@ -122,7 +122,7 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.DeprecatedTaintNodeNotReady,
|
||||
Key: schedulerapi.DeprecatedTaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
@ -134,19 +134,19 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.DeprecatedTaintNodeNotReady,
|
||||
Key: schedulerapi.DeprecatedTaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
@ -162,7 +162,7 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.DeprecatedTaintNodeUnreachable,
|
||||
Key: schedulerapi.DeprecatedTaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
@ -174,19 +174,19 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.DeprecatedTaintNodeUnreachable,
|
||||
Key: schedulerapi.DeprecatedTaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
@ -221,13 +221,13 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
TolerationSeconds: genTolerationSeconds(700),
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
@ -242,7 +242,7 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: genTolerationSeconds(700),
|
||||
@ -254,13 +254,13 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: genTolerationSeconds(700),
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
@ -275,7 +275,7 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: genTolerationSeconds(700),
|
||||
@ -287,13 +287,13 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: genTolerationSeconds(700),
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: &defaultTolerationSeconds,
|
||||
@ -308,13 +308,13 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: genTolerationSeconds(700),
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: genTolerationSeconds(700),
|
||||
@ -326,13 +326,13 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: genTolerationSeconds(700),
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: genTolerationSeconds(700),
|
||||
@ -347,7 +347,7 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
TolerationSeconds: genTolerationSeconds(700),
|
||||
},
|
||||
@ -358,12 +358,12 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Tolerations: []api.Toleration{
|
||||
{
|
||||
Key: algorithm.TaintNodeUnreachable,
|
||||
Key: schedulerapi.TaintNodeUnreachable,
|
||||
Operator: api.TolerationOpExists,
|
||||
TolerationSeconds: genTolerationSeconds(700),
|
||||
},
|
||||
{
|
||||
Key: algorithm.TaintNodeNotReady,
|
||||
Key: schedulerapi.TaintNodeNotReady,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoExecute,
|
||||
TolerationSeconds: genTolerationSeconds(300),
|
||||
@ -395,7 +395,7 @@ func TestForgivenessAdmission(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
err := handler.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil))
|
||||
err := handler.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("[%s]: unexpected error %v for pod %+v", test.description, err, test.requestedPod)
|
||||
}
|
||||
|
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/deny/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/deny/BUILD
generated
vendored
@ -11,8 +11,8 @@ go_library(
|
||||
srcs = ["admission.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/deny",
|
||||
deps = [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -22,7 +22,7 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/deny/admission.go
generated
vendored
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/deny/admission.go
generated
vendored
@ -20,7 +20,7 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
)
|
||||
@ -60,7 +60,7 @@ func (alwaysDeny) Handles(operation admission.Operation) bool {
|
||||
// NewAlwaysDeny creates an always deny admission handler
|
||||
func NewAlwaysDeny() admission.Interface {
|
||||
// DEPRECATED: AlwaysDeny denys all admission request, it is no use.
|
||||
glog.Warningf("%s admission controller is deprecated. "+
|
||||
klog.Warningf("%s admission controller is deprecated. "+
|
||||
"Please remove this controller from your configuration files and scripts.", PluginName)
|
||||
return new(alwaysDeny)
|
||||
}
|
||||
|
2
vendor/k8s.io/kubernetes/plugin/pkg/admission/deny/admission_test.go
generated
vendored
2
vendor/k8s.io/kubernetes/plugin/pkg/admission/deny/admission_test.go
generated
vendored
@ -25,7 +25,7 @@ import (
|
||||
|
||||
func TestAdmission(t *testing.T) {
|
||||
handler := NewAlwaysDeny()
|
||||
err := handler.(*alwaysDeny).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, nil))
|
||||
err := handler.(*alwaysDeny).Admit(admission.NewAttributesRecord(nil, nil, api.Kind("kind").WithVersion("version"), "namespace", "name", api.Resource("resource").WithVersion("version"), "subresource", admission.Create, false, nil))
|
||||
if err == nil {
|
||||
t.Error("Expected error returned from admission handler")
|
||||
}
|
||||
|
23
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/BUILD
generated
vendored
23
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/BUILD
generated
vendored
@ -16,13 +16,13 @@ go_test(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//plugin/pkg/admission/eventratelimit/apis/eventratelimit:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library",
|
||||
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/clock:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -43,12 +43,13 @@ go_library(
|
||||
"//plugin/pkg/admission/eventratelimit/apis/eventratelimit/install:go_default_library",
|
||||
"//plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1:go_default_library",
|
||||
"//plugin/pkg/admission/eventratelimit/apis/eventratelimit/validation:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library",
|
||||
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
19
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/admission.go
generated
vendored
19
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/admission.go
generated
vendored
@ -19,6 +19,8 @@ package eventratelimit
|
||||
import (
|
||||
"io"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/client-go/util/flowcontrol"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
@ -85,13 +87,24 @@ func (a *Plugin) Validate(attr admission.Attributes) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var rejectionError error
|
||||
// ignore all requests that specify dry-run
|
||||
// because they don't correspond to any calls to etcd,
|
||||
// they should not be affected by the ratelimit
|
||||
if attr.IsDryRun() {
|
||||
return nil
|
||||
}
|
||||
|
||||
var errors []error
|
||||
// give each limit enforcer a chance to reject the event
|
||||
for _, enforcer := range a.limitEnforcers {
|
||||
if err := enforcer.accept(attr); err != nil {
|
||||
rejectionError = err
|
||||
errors = append(errors, err)
|
||||
}
|
||||
}
|
||||
|
||||
return rejectionError
|
||||
if aggregatedErr := utilerrors.NewAggregate(errors); aggregatedErr != nil {
|
||||
return apierrors.NewTooManyRequestsError(aggregatedErr.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
22
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/admission_test.go
generated
vendored
22
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/admission_test.go
generated
vendored
@ -46,6 +46,7 @@ func attributesForRequest(rq request) admission.Attributes {
|
||||
api.Resource("resource").WithVersion("version"),
|
||||
"",
|
||||
admission.Create,
|
||||
rq.dryRun,
|
||||
&user.DefaultInfo{Name: rq.username})
|
||||
}
|
||||
|
||||
@ -56,6 +57,7 @@ type request struct {
|
||||
event *api.Event
|
||||
delay time.Duration
|
||||
accepted bool
|
||||
dryRun bool
|
||||
}
|
||||
|
||||
func newRequest(kind string) request {
|
||||
@ -91,6 +93,11 @@ func (r request) withEventComponent(component string) request {
|
||||
})
|
||||
}
|
||||
|
||||
func (r request) withDryRun(dryRun bool) request {
|
||||
r.dryRun = dryRun
|
||||
return r
|
||||
}
|
||||
|
||||
func (r request) withUser(name string) request {
|
||||
r.username = name
|
||||
return r
|
||||
@ -153,6 +160,21 @@ func TestEventRateLimiting(t *testing.T) {
|
||||
newEventRequest().blocked(),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "event not blocked by dry-run requests",
|
||||
serverBurst: 3,
|
||||
requests: []request{
|
||||
newEventRequest(),
|
||||
newEventRequest(),
|
||||
newEventRequest().withDryRun(true),
|
||||
newEventRequest().withDryRun(true),
|
||||
newEventRequest().withDryRun(true),
|
||||
newEventRequest().withDryRun(true),
|
||||
newEventRequest(),
|
||||
newEventRequest().blocked(),
|
||||
newEventRequest().withDryRun(true),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "non-event not blocked after tokens exhausted",
|
||||
serverBurst: 3,
|
||||
|
@ -15,9 +15,9 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit",
|
||||
deps = [
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -12,8 +12,8 @@ go_library(
|
||||
deps = [
|
||||
"//plugin/pkg/admission/eventratelimit/apis/eventratelimit:go_default_library",
|
||||
"//plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -19,10 +19,10 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1",
|
||||
deps = [
|
||||
"//plugin/pkg/admission/eventratelimit/apis/eventratelimit:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=eventratelimit.admission.k8s.io
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the API.
|
||||
// +groupName=eventratelimit.admission.k8s.io
|
||||
package v1alpha1 // import "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/v1alpha1"
|
||||
|
@ -34,13 +34,28 @@ func init() {
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(scheme *runtime.Scheme) error {
|
||||
return scheme.AddGeneratedConversionFuncs(
|
||||
Convert_v1alpha1_Configuration_To_eventratelimit_Configuration,
|
||||
Convert_eventratelimit_Configuration_To_v1alpha1_Configuration,
|
||||
Convert_v1alpha1_Limit_To_eventratelimit_Limit,
|
||||
Convert_eventratelimit_Limit_To_v1alpha1_Limit,
|
||||
)
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*Configuration)(nil), (*eventratelimit.Configuration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_Configuration_To_eventratelimit_Configuration(a.(*Configuration), b.(*eventratelimit.Configuration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*eventratelimit.Configuration)(nil), (*Configuration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_eventratelimit_Configuration_To_v1alpha1_Configuration(a.(*eventratelimit.Configuration), b.(*Configuration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*Limit)(nil), (*eventratelimit.Limit)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_Limit_To_eventratelimit_Limit(a.(*Limit), b.(*eventratelimit.Limit), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*eventratelimit.Limit)(nil), (*Limit)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_eventratelimit_Limit_To_v1alpha1_Limit(a.(*eventratelimit.Limit), b.(*Limit), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_Configuration_To_eventratelimit_Configuration(in *Configuration, out *eventratelimit.Configuration, s conversion.Scope) error {
|
||||
|
@ -12,7 +12,7 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/validation",
|
||||
deps = [
|
||||
"//plugin/pkg/admission/eventratelimit/apis/eventratelimit:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/limitenforcer.go
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/limitenforcer.go
generated
vendored
@ -22,7 +22,6 @@ import (
|
||||
|
||||
"github.com/hashicorp/golang-lru"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/client-go/util/flowcontrol"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
@ -99,7 +98,7 @@ func (enforcer *limitEnforcer) accept(attr admission.Attributes) error {
|
||||
allow := rateLimiter.TryAccept()
|
||||
|
||||
if !allow {
|
||||
return apierrors.NewTooManyRequestsError(fmt.Sprintf("limit reached on type %v for key %v", enforcer.limitType, key))
|
||||
return fmt.Errorf("limit reached on type %v for key %v", enforcer.limitType, key)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
24
vendor/k8s.io/kubernetes/plugin/pkg/admission/exec/BUILD
generated
vendored
24
vendor/k8s.io/kubernetes/plugin/pkg/admission/exec/BUILD
generated
vendored
@ -11,13 +11,11 @@ go_library(
|
||||
srcs = ["admission.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/exec",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -27,12 +25,12 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
||||
"//vendor/k8s.io/client-go/testing:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
94
vendor/k8s.io/kubernetes/plugin/pkg/admission/exec/admission.go
generated
vendored
94
vendor/k8s.io/kubernetes/plugin/pkg/admission/exec/admission.go
generated
vendored
@ -20,13 +20,11 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -54,7 +52,7 @@ func Register(plugins *admission.Plugins) {
|
||||
// a pod using host based configurations.
|
||||
type DenyExec struct {
|
||||
*admission.Handler
|
||||
client internalclientset.Interface
|
||||
client kubernetes.Interface
|
||||
|
||||
// these flags control which items will be checked to deny exec/attach
|
||||
hostNetwork bool
|
||||
@ -64,20 +62,7 @@ type DenyExec struct {
|
||||
}
|
||||
|
||||
var _ admission.ValidationInterface = &DenyExec{}
|
||||
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&DenyExec{})
|
||||
|
||||
// NewDenyEscalatingExec creates a new admission controller that denies an exec operation on a pod
|
||||
// using host based configurations.
|
||||
func NewDenyEscalatingExec() *DenyExec {
|
||||
return &DenyExec{
|
||||
Handler: admission.NewHandler(admission.Connect),
|
||||
hostNetwork: true,
|
||||
hostIPC: true,
|
||||
hostPID: true,
|
||||
privileged: true,
|
||||
}
|
||||
}
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeClientSet(&DenyExec{})
|
||||
|
||||
// NewDenyExecOnPrivileged creates a new admission controller that is only checking the privileged
|
||||
// option. This is for legacy support of the DenyExecOnPrivileged admission controller.
|
||||
@ -92,34 +77,56 @@ func NewDenyExecOnPrivileged() *DenyExec {
|
||||
}
|
||||
}
|
||||
|
||||
// NewDenyEscalatingExec creates a new admission controller that denies an exec operation on a pod
|
||||
// using host based configurations.
|
||||
func NewDenyEscalatingExec() *DenyExec {
|
||||
return &DenyExec{
|
||||
Handler: admission.NewHandler(admission.Connect),
|
||||
hostNetwork: true,
|
||||
hostIPC: true,
|
||||
hostPID: true,
|
||||
privileged: true,
|
||||
}
|
||||
}
|
||||
|
||||
// SetExternalKubeClientSet implements the WantsInternalKubeClientSet interface.
|
||||
func (d *DenyExec) SetExternalKubeClientSet(client kubernetes.Interface) {
|
||||
d.client = client
|
||||
}
|
||||
|
||||
// ValidateInitialization implements the InitializationValidator interface.
|
||||
func (d *DenyExec) ValidateInitialization() error {
|
||||
if d.client == nil {
|
||||
return fmt.Errorf("missing client")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate makes an admission decision based on the request attributes
|
||||
func (d *DenyExec) Validate(a admission.Attributes) (err error) {
|
||||
connectRequest, ok := a.GetObject().(*rest.ConnectRequest)
|
||||
if !ok {
|
||||
return errors.NewBadRequest("a connect request was received, but could not convert the request object.")
|
||||
path := a.GetResource().Resource
|
||||
if subresource := a.GetSubresource(); subresource != "" {
|
||||
path = path + "/" + subresource
|
||||
}
|
||||
// Only handle exec or attach requests on pods
|
||||
if connectRequest.ResourcePath != "pods/exec" && connectRequest.ResourcePath != "pods/attach" {
|
||||
if path != "pods/exec" && path != "pods/attach" {
|
||||
return nil
|
||||
}
|
||||
pod, err := d.client.Core().Pods(a.GetNamespace()).Get(connectRequest.Name, metav1.GetOptions{})
|
||||
pod, err := d.client.CoreV1().Pods(a.GetNamespace()).Get(a.GetName(), metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return admission.NewForbidden(a, err)
|
||||
}
|
||||
|
||||
if pod.Spec.SecurityContext != nil {
|
||||
securityContext := pod.Spec.SecurityContext
|
||||
if d.hostNetwork && securityContext.HostNetwork {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot exec into or attach to a container using host network"))
|
||||
}
|
||||
if d.hostNetwork && pod.Spec.HostNetwork {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot exec into or attach to a container using host network"))
|
||||
}
|
||||
|
||||
if d.hostPID && securityContext.HostPID {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot exec into or attach to a container using host pid"))
|
||||
}
|
||||
if d.hostPID && pod.Spec.HostPID {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot exec into or attach to a container using host pid"))
|
||||
}
|
||||
|
||||
if d.hostIPC && securityContext.HostIPC {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot exec into or attach to a container using host ipc"))
|
||||
}
|
||||
if d.hostIPC && pod.Spec.HostIPC {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot exec into or attach to a container using host ipc"))
|
||||
}
|
||||
|
||||
if d.privileged && isPrivileged(pod) {
|
||||
@ -130,7 +137,7 @@ func (d *DenyExec) Validate(a admission.Attributes) (err error) {
|
||||
}
|
||||
|
||||
// isPrivileged will return true a pod has any privileged containers
|
||||
func isPrivileged(pod *api.Pod) bool {
|
||||
func isPrivileged(pod *corev1.Pod) bool {
|
||||
for _, c := range pod.Spec.InitContainers {
|
||||
if c.SecurityContext == nil || c.SecurityContext.Privileged == nil {
|
||||
continue
|
||||
@ -149,16 +156,3 @@ func isPrivileged(pod *api.Pod) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// SetInternalKubeClientSet implements the WantsInternalKubeClientSet interface.
|
||||
func (d *DenyExec) SetInternalKubeClientSet(client internalclientset.Interface) {
|
||||
d.client = client
|
||||
}
|
||||
|
||||
// ValidateInitialization implements the InitializationValidator interface.
|
||||
func (d *DenyExec) ValidateInitialization() error {
|
||||
if d.client == nil {
|
||||
return fmt.Errorf("missing client")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
42
vendor/k8s.io/kubernetes/plugin/pkg/admission/exec/admission_test.go
generated
vendored
42
vendor/k8s.io/kubernetes/plugin/pkg/admission/exec/admission_test.go
generated
vendored
@ -19,13 +19,13 @@ package exec
|
||||
import (
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
)
|
||||
|
||||
// newAllowEscalatingExec returns `admission.Interface` that allows execution on
|
||||
@ -42,20 +42,18 @@ func newAllowEscalatingExec() *DenyExec {
|
||||
func TestAdmission(t *testing.T) {
|
||||
privPod := validPod("privileged")
|
||||
priv := true
|
||||
privPod.Spec.Containers[0].SecurityContext = &api.SecurityContext{
|
||||
privPod.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{
|
||||
Privileged: &priv,
|
||||
}
|
||||
|
||||
hostPIDPod := validPod("hostPID")
|
||||
hostPIDPod.Spec.SecurityContext = &api.PodSecurityContext{}
|
||||
hostPIDPod.Spec.SecurityContext.HostPID = true
|
||||
hostPIDPod.Spec.HostPID = true
|
||||
|
||||
hostIPCPod := validPod("hostIPC")
|
||||
hostIPCPod.Spec.SecurityContext = &api.PodSecurityContext{}
|
||||
hostIPCPod.Spec.SecurityContext.HostIPC = true
|
||||
hostIPCPod.Spec.HostIPC = true
|
||||
|
||||
testCases := map[string]struct {
|
||||
pod *api.Pod
|
||||
pod *corev1.Pod
|
||||
shouldAccept bool
|
||||
}{
|
||||
"priv": {
|
||||
@ -107,7 +105,7 @@ func TestAdmission(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept bool) {
|
||||
func testAdmission(t *testing.T, pod *corev1.Pod, handler *DenyExec, shouldAccept bool) {
|
||||
mockClient := &fake.Clientset{}
|
||||
mockClient.AddReactor("get", "pods", func(action core.Action) (bool, runtime.Object, error) {
|
||||
if action.(core.GetAction).GetName() == pod.Name {
|
||||
@ -117,13 +115,12 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b
|
||||
return true, nil, nil
|
||||
})
|
||||
|
||||
handler.SetInternalKubeClientSet(mockClient)
|
||||
handler.SetExternalKubeClientSet(mockClient)
|
||||
admission.ValidateInitialization(handler)
|
||||
|
||||
// pods/exec
|
||||
{
|
||||
req := &rest.ConnectRequest{Name: pod.Name, ResourcePath: "pods/exec"}
|
||||
err := handler.Validate(admission.NewAttributesRecord(req, nil, api.Kind("Pod").WithVersion("version"), "test", "name", api.Resource("pods").WithVersion("version"), "exec", admission.Connect, nil))
|
||||
err := handler.Validate(admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), "test", pod.Name, api.Resource("pods").WithVersion("version"), "exec", admission.Connect, false, nil))
|
||||
if shouldAccept && err != nil {
|
||||
t.Errorf("Unexpected error returned from admission handler: %v", err)
|
||||
}
|
||||
@ -134,8 +131,7 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b
|
||||
|
||||
// pods/attach
|
||||
{
|
||||
req := &rest.ConnectRequest{Name: pod.Name, ResourcePath: "pods/attach"}
|
||||
err := handler.Validate(admission.NewAttributesRecord(req, nil, api.Kind("Pod").WithVersion("version"), "test", "name", api.Resource("pods").WithVersion("version"), "attach", admission.Connect, nil))
|
||||
err := handler.Validate(admission.NewAttributesRecord(nil, nil, api.Kind("Pod").WithVersion("version"), "test", pod.Name, api.Resource("pods").WithVersion("version"), "attach", admission.Connect, false, nil))
|
||||
if shouldAccept && err != nil {
|
||||
t.Errorf("Unexpected error returned from admission handler: %v", err)
|
||||
}
|
||||
@ -149,20 +145,18 @@ func testAdmission(t *testing.T, pod *api.Pod, handler *DenyExec, shouldAccept b
|
||||
func TestDenyExecOnPrivileged(t *testing.T) {
|
||||
privPod := validPod("privileged")
|
||||
priv := true
|
||||
privPod.Spec.Containers[0].SecurityContext = &api.SecurityContext{
|
||||
privPod.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{
|
||||
Privileged: &priv,
|
||||
}
|
||||
|
||||
hostPIDPod := validPod("hostPID")
|
||||
hostPIDPod.Spec.SecurityContext = &api.PodSecurityContext{}
|
||||
hostPIDPod.Spec.SecurityContext.HostPID = true
|
||||
hostPIDPod.Spec.HostPID = true
|
||||
|
||||
hostIPCPod := validPod("hostIPC")
|
||||
hostIPCPod.Spec.SecurityContext = &api.PodSecurityContext{}
|
||||
hostIPCPod.Spec.SecurityContext.HostIPC = true
|
||||
hostIPCPod.Spec.HostIPC = true
|
||||
|
||||
testCases := map[string]struct {
|
||||
pod *api.Pod
|
||||
pod *corev1.Pod
|
||||
shouldAccept bool
|
||||
}{
|
||||
"priv": {
|
||||
@ -198,11 +192,11 @@ func TestDenyExecOnPrivileged(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func validPod(name string) *api.Pod {
|
||||
return &api.Pod{
|
||||
func validPod(name string) *corev1.Pod {
|
||||
return &corev1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: "test"},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{Name: "ctr1", Image: "image"},
|
||||
{Name: "ctr2", Image: "image2"},
|
||||
},
|
||||
|
10
vendor/k8s.io/kubernetes/plugin/pkg/admission/extendedresourcetoleration/BUILD
generated
vendored
10
vendor/k8s.io/kubernetes/plugin/pkg/admission/extendedresourcetoleration/BUILD
generated
vendored
@ -8,9 +8,9 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/core/helper:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -21,8 +21,8 @@ go_test(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/core/helper:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -354,7 +354,7 @@ func TestAdmit(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for i, test := range tests {
|
||||
err := plugin.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, core.Kind("Pod").WithVersion("version"), "foo", "name", core.Resource("pods").WithVersion("version"), "", "ignored", nil))
|
||||
err := plugin.Admit(admission.NewAttributesRecord(&test.requestedPod, nil, core.Kind("Pod").WithVersion("version"), "foo", "name", core.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("[%d: %s] unexpected error %v for pod %+v", i, test.description, err, test.requestedPod)
|
||||
}
|
||||
|
37
vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/BUILD
generated
vendored
37
vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/BUILD
generated
vendored
@ -11,14 +11,14 @@ go_library(
|
||||
srcs = ["gc_admission.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/gc",
|
||||
deps = [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -27,17 +27,20 @@ go_test(
|
||||
srcs = ["gc_admission_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/api/extensions/v1beta1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/discovery/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/restmapper:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
15
vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission.go
generated
vendored
15
vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission.go
generated
vendored
@ -186,11 +186,9 @@ func (a *gcPermissionsEnforcement) ownerRefToDeleteAttributeRecords(ref metav1.O
|
||||
return ret, err
|
||||
}
|
||||
for _, mapping := range mappings {
|
||||
ret = append(ret, authorizer.AttributesRecord{
|
||||
User: attributes.GetUserInfo(),
|
||||
Verb: "update",
|
||||
// ownerReference can only refer to an object in the same namespace, so attributes.GetNamespace() equals to the owner's namespace
|
||||
Namespace: attributes.GetNamespace(),
|
||||
ar := authorizer.AttributesRecord{
|
||||
User: attributes.GetUserInfo(),
|
||||
Verb: "update",
|
||||
APIGroup: mapping.Resource.Group,
|
||||
APIVersion: mapping.Resource.Version,
|
||||
Resource: mapping.Resource.Resource,
|
||||
@ -198,7 +196,12 @@ func (a *gcPermissionsEnforcement) ownerRefToDeleteAttributeRecords(ref metav1.O
|
||||
Name: ref.Name,
|
||||
ResourceRequest: true,
|
||||
Path: "",
|
||||
})
|
||||
}
|
||||
if mapping.Scope.Name() == meta.RESTScopeNameNamespace {
|
||||
// if the owner is namespaced, it must be in the same namespace as the dependent is.
|
||||
ar.Namespace = attributes.GetNamespace()
|
||||
}
|
||||
ret = append(ret, ar)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
113
vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission_test.go
generated
vendored
113
vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission_test.go
generated
vendored
@ -17,10 +17,12 @@ limitations under the License.
|
||||
package gc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
extensionv1beta1 "k8s.io/api/extensions/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
@ -28,7 +30,9 @@ import (
|
||||
"k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
"k8s.io/client-go/restmapper"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
)
|
||||
@ -68,6 +72,15 @@ func (fakeAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, s
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
}
|
||||
|
||||
if username == "non-node-deleter" {
|
||||
if a.GetVerb() == "delete" && a.GetResource() == "nodes" {
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
if a.GetVerb() == "update" && a.GetResource() == "nodes" && a.GetSubresource() == "finalizers" {
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
}
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
}
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
}
|
||||
|
||||
@ -88,7 +101,30 @@ func newGCPermissionsEnforcement() (*gcPermissionsEnforcement, error) {
|
||||
}
|
||||
|
||||
genericPluginInitializer := initializer.New(nil, nil, fakeAuthorizer{}, nil)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(nil, nil, nil, testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Scheme), nil)
|
||||
fakeDiscoveryClient := &fakediscovery.FakeDiscovery{Fake: &coretesting.Fake{}}
|
||||
fakeDiscoveryClient.Resources = []*metav1.APIResourceList{
|
||||
{
|
||||
GroupVersion: corev1.SchemeGroupVersion.String(),
|
||||
APIResources: []metav1.APIResource{
|
||||
{Name: "nodes", Namespaced: false, Kind: "Node"},
|
||||
{Name: "pods", Namespaced: true, Kind: "Pod"},
|
||||
{Name: "replicationcontrollers", Namespaced: true, Kind: "ReplicationController"},
|
||||
},
|
||||
},
|
||||
{
|
||||
GroupVersion: extensionv1beta1.SchemeGroupVersion.String(),
|
||||
APIResources: []metav1.APIResource{
|
||||
{Name: "daemonsets", Namespaced: true, Kind: "DaemonSet"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
restMapperRes, err := restmapper.GetAPIGroupResources(fakeDiscoveryClient)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unexpected error while constructing resource list from fake discovery client: %v", err)
|
||||
}
|
||||
restMapper := restmapper.NewDiscoveryRESTMapper(restMapperRes)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(nil, restMapper, nil)
|
||||
initializersChain := admission.PluginInitializers{}
|
||||
initializersChain = append(initializersChain, genericPluginInitializer)
|
||||
initializersChain = append(initializersChain, pluginInitializer)
|
||||
@ -270,7 +306,7 @@ func TestGCAdmission(t *testing.T) {
|
||||
operation = admission.Update
|
||||
}
|
||||
user := &user.DefaultInfo{Name: tc.username}
|
||||
attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, user)
|
||||
attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, false, user)
|
||||
|
||||
err = gcAdmit.Validate(attributes)
|
||||
if !tc.checkError(err) {
|
||||
@ -347,6 +383,23 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) {
|
||||
Name: "ds1",
|
||||
BlockOwnerDeletion: getFalseVar(),
|
||||
}
|
||||
blockNode := metav1.OwnerReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Node",
|
||||
Name: "node1",
|
||||
BlockOwnerDeletion: getTrueVar(),
|
||||
}
|
||||
notBlockNode := metav1.OwnerReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Node",
|
||||
Name: "node",
|
||||
BlockOwnerDeletion: getFalseVar(),
|
||||
}
|
||||
nilBlockNode := metav1.OwnerReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Node",
|
||||
Name: "node",
|
||||
}
|
||||
|
||||
expectNoError := func(err error) bool {
|
||||
return err == nil
|
||||
@ -386,7 +439,7 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) {
|
||||
name: "super-user, create, some ownerReferences have blockOwnerDeletion=true",
|
||||
username: "super",
|
||||
resource: api.SchemeGroupVersion.WithResource("pods"),
|
||||
newObj: podWithOwnerRefs(blockRC1, blockRC2),
|
||||
newObj: podWithOwnerRefs(blockRC1, blockRC2, blockNode),
|
||||
checkError: expectNoError,
|
||||
},
|
||||
{
|
||||
@ -403,6 +456,13 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) {
|
||||
newObj: podWithOwnerRefs(notBlockRC1, nilBlockRC2),
|
||||
checkError: expectNoError,
|
||||
},
|
||||
{
|
||||
name: "non-node-deleter, create, all ownerReferences have blockOwnerDeletion=false",
|
||||
username: "non-node-deleter",
|
||||
resource: api.SchemeGroupVersion.WithResource("pods"),
|
||||
newObj: podWithOwnerRefs(notBlockNode),
|
||||
checkError: expectNoError,
|
||||
},
|
||||
{
|
||||
name: "non-rc-deleter, create, some ownerReferences have blockOwnerDeletion=true",
|
||||
username: "non-rc-deleter",
|
||||
@ -417,21 +477,28 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) {
|
||||
newObj: podWithOwnerRefs(blockDS1),
|
||||
checkError: expectNoError,
|
||||
},
|
||||
{
|
||||
name: "non-node-deleter, create, some ownerReferences have blockOwnerDeletion=true",
|
||||
username: "non-node-deleter",
|
||||
resource: api.SchemeGroupVersion.WithResource("pods"),
|
||||
newObj: podWithOwnerRefs(blockNode),
|
||||
checkError: expectCantSetBlockOwnerDeletionError,
|
||||
},
|
||||
// cases are for update
|
||||
{
|
||||
name: "super-user, update, no ownerReferences change blockOwnerDeletion",
|
||||
username: "super",
|
||||
resource: api.SchemeGroupVersion.WithResource("pods"),
|
||||
oldObj: podWithOwnerRefs(nilBlockRC1),
|
||||
newObj: podWithOwnerRefs(notBlockRC1),
|
||||
oldObj: podWithOwnerRefs(nilBlockRC1, nilBlockNode),
|
||||
newObj: podWithOwnerRefs(notBlockRC1, notBlockNode),
|
||||
checkError: expectNoError,
|
||||
},
|
||||
{
|
||||
name: "super-user, update, some ownerReferences change to blockOwnerDeletion=true",
|
||||
username: "super",
|
||||
resource: api.SchemeGroupVersion.WithResource("pods"),
|
||||
oldObj: podWithOwnerRefs(notBlockRC1),
|
||||
newObj: podWithOwnerRefs(blockRC1),
|
||||
oldObj: podWithOwnerRefs(notBlockRC1, notBlockNode),
|
||||
newObj: podWithOwnerRefs(blockRC1, blockNode),
|
||||
checkError: expectNoError,
|
||||
},
|
||||
{
|
||||
@ -439,7 +506,7 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) {
|
||||
username: "super",
|
||||
resource: api.SchemeGroupVersion.WithResource("pods"),
|
||||
oldObj: podWithOwnerRefs(),
|
||||
newObj: podWithOwnerRefs(blockRC1),
|
||||
newObj: podWithOwnerRefs(blockRC1, blockNode),
|
||||
checkError: expectNoError,
|
||||
},
|
||||
{
|
||||
@ -466,6 +533,14 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) {
|
||||
newObj: podWithOwnerRefs(blockRC1),
|
||||
checkError: expectCantSetBlockOwnerDeletionError,
|
||||
},
|
||||
{
|
||||
name: "non-node-deleter, update, some ownerReferences change from blockOwnerDeletion=nil to true",
|
||||
username: "non-node-deleter",
|
||||
resource: api.SchemeGroupVersion.WithResource("pods"),
|
||||
oldObj: podWithOwnerRefs(nilBlockNode),
|
||||
newObj: podWithOwnerRefs(blockNode),
|
||||
checkError: expectCantSetBlockOwnerDeletionError,
|
||||
},
|
||||
{
|
||||
name: "non-rc-deleter, update, some ownerReferences change from blockOwnerDeletion=true to false",
|
||||
username: "non-rc-deleter",
|
||||
@ -474,6 +549,14 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) {
|
||||
newObj: podWithOwnerRefs(notBlockRC1),
|
||||
checkError: expectNoError,
|
||||
},
|
||||
{
|
||||
name: "non-node-deleter, update, some ownerReferences change from blockOwnerDeletion=true to false",
|
||||
username: "non-node-deleter",
|
||||
resource: api.SchemeGroupVersion.WithResource("pods"),
|
||||
oldObj: podWithOwnerRefs(blockNode),
|
||||
newObj: podWithOwnerRefs(notBlockNode),
|
||||
checkError: expectNoError,
|
||||
},
|
||||
{
|
||||
name: "non-rc-deleter, update, some ownerReferences change blockOwnerDeletion, but all such references are to daemonset",
|
||||
username: "non-rc-deleter",
|
||||
@ -506,6 +589,14 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) {
|
||||
newObj: podWithOwnerRefs(blockDS1),
|
||||
checkError: expectNoError,
|
||||
},
|
||||
{
|
||||
name: "non-node-deleter, update, add ownerReferences with blockOwnerDeletion=true",
|
||||
username: "non-node-deleter",
|
||||
resource: api.SchemeGroupVersion.WithResource("pods"),
|
||||
oldObj: podWithOwnerRefs(),
|
||||
newObj: podWithOwnerRefs(blockNode),
|
||||
checkError: expectCantSetBlockOwnerDeletionError,
|
||||
},
|
||||
}
|
||||
gcAdmit, err := newGCPermissionsEnforcement()
|
||||
if err != nil {
|
||||
@ -518,7 +609,7 @@ func TestBlockOwnerDeletionAdmission(t *testing.T) {
|
||||
operation = admission.Update
|
||||
}
|
||||
user := &user.DefaultInfo{Name: tc.username}
|
||||
attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, user)
|
||||
attributes := admission.NewAttributesRecord(tc.newObj, tc.oldObj, schema.GroupVersionKind{}, metav1.NamespaceDefault, "foo", tc.resource, tc.subresource, operation, false, user)
|
||||
|
||||
err := gcAdmit.Validate(attributes)
|
||||
if !tc.checkError(err) {
|
||||
|
26
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/BUILD
generated
vendored
26
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/BUILD
generated
vendored
@ -18,15 +18,15 @@ go_library(
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/imagepolicy/install:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/imagepolicy/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/cache:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/webhook:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
"//staging/src/k8s.io/api/imagepolicy/v1alpha1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/cache:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/webhook:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/rest:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -41,10 +41,10 @@ go_test(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/imagepolicy/install:go_default_library",
|
||||
"//vendor/k8s.io/api/imagepolicy/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api/v1:go_default_library",
|
||||
"//staging/src/k8s.io/api/imagepolicy/v1alpha1:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/clientcmd/api/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
32
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/admission.go
generated
vendored
32
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/admission.go
generated
vendored
@ -26,7 +26,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
|
||||
"k8s.io/api/imagepolicy/v1alpha1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@ -46,6 +46,21 @@ import (
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "ImagePolicyWebhook"
|
||||
|
||||
// AuditKeyPrefix is used as the prefix for all audit keys handled by this
|
||||
// pluggin. Some well known suffixes are listed below.
|
||||
var AuditKeyPrefix = strings.ToLower(PluginName) + ".image-policy.k8s.io/"
|
||||
|
||||
const (
|
||||
// ImagePolicyFailedOpenKeySuffix in an annotation indicates the image
|
||||
// review failed open when the image policy webhook backend connection
|
||||
// failed.
|
||||
ImagePolicyFailedOpenKeySuffix string = "failed-open"
|
||||
|
||||
// ImagePolicyAuditRequiredKeySuffix in an annotation indicates the pod
|
||||
// should be audited.
|
||||
ImagePolicyAuditRequiredKeySuffix string = "audit-required"
|
||||
)
|
||||
|
||||
var (
|
||||
groupVersions = []schema.GroupVersion{v1alpha1.SchemeGroupVersion}
|
||||
)
|
||||
@ -95,18 +110,21 @@ func (a *Plugin) filterAnnotations(allAnnotations map[string]string) map[string]
|
||||
// Function to call on webhook failure; behavior determined by defaultAllow flag
|
||||
func (a *Plugin) webhookError(pod *api.Pod, attributes admission.Attributes, err error) error {
|
||||
if err != nil {
|
||||
glog.V(2).Infof("error contacting webhook backend: %s", err)
|
||||
klog.V(2).Infof("error contacting webhook backend: %s", err)
|
||||
if a.defaultAllow {
|
||||
attributes.AddAnnotation(AuditKeyPrefix+ImagePolicyFailedOpenKeySuffix, "true")
|
||||
// TODO(wteiken): Remove the annotation code for the 1.13 release
|
||||
annotations := pod.GetAnnotations()
|
||||
if annotations == nil {
|
||||
annotations = make(map[string]string)
|
||||
}
|
||||
annotations[api.ImagePolicyFailedOpenKey] = "true"
|
||||
pod.ObjectMeta.SetAnnotations(annotations)
|
||||
glog.V(2).Infof("resource allowed in spite of webhook backend failure")
|
||||
|
||||
klog.V(2).Infof("resource allowed in spite of webhook backend failure")
|
||||
return nil
|
||||
}
|
||||
glog.V(2).Infof("resource not allowed due to webhook backend failure ")
|
||||
klog.V(2).Infof("resource not allowed due to webhook backend failure ")
|
||||
return admission.NewForbidden(attributes, err)
|
||||
}
|
||||
return nil
|
||||
@ -174,13 +192,17 @@ func (a *Plugin) admitPod(pod *api.Pod, attributes admission.Attributes, review
|
||||
a.responseCache.Add(string(cacheKey), review.Status, a.statusTTL(review.Status))
|
||||
}
|
||||
|
||||
for k, v := range review.Status.AuditAnnotations {
|
||||
if err := attributes.AddAnnotation(AuditKeyPrefix+k, v); err != nil {
|
||||
klog.Warningf("failed to set admission audit annotation %s to %s: %v", AuditKeyPrefix+k, v, err)
|
||||
}
|
||||
}
|
||||
if !review.Status.Allowed {
|
||||
if len(review.Status.Reason) > 0 {
|
||||
return fmt.Errorf("image policy webhook backend denied one or more images: %s", review.Status.Reason)
|
||||
}
|
||||
return errors.New("one or more images rejected by webhook backend")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
291
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/admission_test.go
generated
vendored
291
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/admission_test.go
generated
vendored
@ -192,66 +192,68 @@ current-context: default
|
||||
|
||||
for _, tt := range tests {
|
||||
// Use a closure so defer statements trigger between loop iterations.
|
||||
err := func() error {
|
||||
tempfile, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
t.Run(tt.msg, func(t *testing.T) {
|
||||
err := func() error {
|
||||
tempfile, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p := tempfile.Name()
|
||||
defer os.Remove(p)
|
||||
|
||||
tmpl, err := template.New("test").Parse(tt.kubeConfigTmpl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse test template: %v", err)
|
||||
}
|
||||
if err := tmpl.Execute(tempfile, data); err != nil {
|
||||
return fmt.Errorf("failed to execute test template: %v", err)
|
||||
}
|
||||
|
||||
tempconfigfile, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pc := tempconfigfile.Name()
|
||||
defer os.Remove(pc)
|
||||
|
||||
configTmpl, err := template.New("testconfig").Parse(defaultConfigTmplJSON)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse test template: %v", err)
|
||||
}
|
||||
dataConfig := struct {
|
||||
KubeConfig string
|
||||
AllowTTL int
|
||||
DenyTTL int
|
||||
RetryBackoff int
|
||||
DefaultAllow bool
|
||||
}{
|
||||
KubeConfig: p,
|
||||
AllowTTL: 500,
|
||||
DenyTTL: 500,
|
||||
RetryBackoff: 500,
|
||||
DefaultAllow: true,
|
||||
}
|
||||
if err := configTmpl.Execute(tempconfigfile, dataConfig); err != nil {
|
||||
return fmt.Errorf("failed to execute test template: %v", err)
|
||||
}
|
||||
|
||||
// Create a new admission controller
|
||||
configFile, err := os.Open(pc)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read test config: %v", err)
|
||||
}
|
||||
defer configFile.Close()
|
||||
|
||||
_, err = NewImagePolicyWebhook(configFile)
|
||||
return err
|
||||
}()
|
||||
if err != nil && !tt.wantErr {
|
||||
t.Errorf("failed to load plugin from config %q: %v", tt.msg, err)
|
||||
}
|
||||
p := tempfile.Name()
|
||||
defer os.Remove(p)
|
||||
|
||||
tmpl, err := template.New("test").Parse(tt.kubeConfigTmpl)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse test template: %v", err)
|
||||
if err == nil && tt.wantErr {
|
||||
t.Errorf("wanted an error when loading config, did not get one: %q", tt.msg)
|
||||
}
|
||||
if err := tmpl.Execute(tempfile, data); err != nil {
|
||||
return fmt.Errorf("failed to execute test template: %v", err)
|
||||
}
|
||||
|
||||
tempconfigfile, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pc := tempconfigfile.Name()
|
||||
defer os.Remove(pc)
|
||||
|
||||
configTmpl, err := template.New("testconfig").Parse(defaultConfigTmplJSON)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse test template: %v", err)
|
||||
}
|
||||
dataConfig := struct {
|
||||
KubeConfig string
|
||||
AllowTTL int
|
||||
DenyTTL int
|
||||
RetryBackoff int
|
||||
DefaultAllow bool
|
||||
}{
|
||||
KubeConfig: p,
|
||||
AllowTTL: 500,
|
||||
DenyTTL: 500,
|
||||
RetryBackoff: 500,
|
||||
DefaultAllow: true,
|
||||
}
|
||||
if err := configTmpl.Execute(tempconfigfile, dataConfig); err != nil {
|
||||
return fmt.Errorf("failed to execute test template: %v", err)
|
||||
}
|
||||
|
||||
// Create a new admission controller
|
||||
configFile, err := os.Open(pc)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read test config: %v", err)
|
||||
}
|
||||
defer configFile.Close()
|
||||
|
||||
_, err = NewImagePolicyWebhook(configFile)
|
||||
return err
|
||||
}()
|
||||
if err != nil && !tt.wantErr {
|
||||
t.Errorf("failed to load plugin from config %q: %v", tt.msg, err)
|
||||
}
|
||||
if err == nil && tt.wantErr {
|
||||
t.Errorf("wanted an error when loading config, did not get one: %q", tt.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,8 +296,9 @@ func NewTestServer(s Service, cert, key, caCert []byte) (*httptest.Server, error
|
||||
}
|
||||
s.Review(&review)
|
||||
type status struct {
|
||||
Allowed bool `json:"allowed"`
|
||||
Reason string `json:"reason"`
|
||||
Allowed bool `json:"allowed"`
|
||||
Reason string `json:"reason"`
|
||||
AuditAnnotations map[string]string `json:"auditAnnotations"`
|
||||
}
|
||||
resp := struct {
|
||||
APIVersion string `json:"apiVersion"`
|
||||
@ -304,7 +307,11 @@ func NewTestServer(s Service, cert, key, caCert []byte) (*httptest.Server, error
|
||||
}{
|
||||
APIVersion: v1alpha1.SchemeGroupVersion.String(),
|
||||
Kind: "ImageReview",
|
||||
Status: status{review.Status.Allowed, review.Status.Reason},
|
||||
Status: status{
|
||||
review.Status.Allowed,
|
||||
review.Status.Reason,
|
||||
review.Status.AuditAnnotations,
|
||||
},
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
@ -318,8 +325,9 @@ func NewTestServer(s Service, cert, key, caCert []byte) (*httptest.Server, error
|
||||
|
||||
// A service that can be set to allow all or deny all authorization requests.
|
||||
type mockService struct {
|
||||
allow bool
|
||||
statusCode int
|
||||
allow bool
|
||||
statusCode int
|
||||
outAnnotations map[string]string
|
||||
}
|
||||
|
||||
func (m *mockService) Review(r *v1alpha1.ImageReview) {
|
||||
@ -339,6 +347,8 @@ func (m *mockService) Review(r *v1alpha1.ImageReview) {
|
||||
if !r.Status.Allowed {
|
||||
r.Status.Reason = "not allowed"
|
||||
}
|
||||
|
||||
r.Status.AuditAnnotations = m.outAnnotations
|
||||
}
|
||||
func (m *mockService) Allow() { m.allow = true }
|
||||
func (m *mockService) Deny() { m.allow = false }
|
||||
@ -455,7 +465,7 @@ func TestTLSConfig(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
// Use a closure so defer statements trigger between loop iterations.
|
||||
func() {
|
||||
t.Run(tt.test, func(t *testing.T) {
|
||||
service := new(mockService)
|
||||
service.statusCode = 200
|
||||
|
||||
@ -472,7 +482,7 @@ func TestTLSConfig(t *testing.T) {
|
||||
return
|
||||
}
|
||||
pod := goodPod(strconv.Itoa(rand.Intn(1000)))
|
||||
attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{})
|
||||
attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
|
||||
|
||||
// Allow all and see if we get an error.
|
||||
service.Allow()
|
||||
@ -502,7 +512,7 @@ func TestTLSConfig(t *testing.T) {
|
||||
if err := wh.Validate(attr); err == nil {
|
||||
t.Errorf("%s: incorrectly admitted with DenyAll policy", tt.test)
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -561,7 +571,7 @@ func TestWebhookCache(t *testing.T) {
|
||||
{statusCode: 500, expectedErr: false, expectedAuthorized: true, expectedCached: true},
|
||||
}
|
||||
|
||||
attr := admission.NewAttributesRecord(goodPod("test"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{})
|
||||
attr := admission.NewAttributesRecord(goodPod("test"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
|
||||
|
||||
serv.allow = true
|
||||
|
||||
@ -573,7 +583,7 @@ func TestWebhookCache(t *testing.T) {
|
||||
{statusCode: 200, expectedErr: false, expectedAuthorized: true, expectedCached: false},
|
||||
{statusCode: 500, expectedErr: false, expectedAuthorized: true, expectedCached: true},
|
||||
}
|
||||
attr = admission.NewAttributesRecord(goodPod("test2"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{})
|
||||
attr = admission.NewAttributesRecord(goodPod("test2"), nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
|
||||
|
||||
testWebhookCacheCases(t, serv, wh, attr, tests)
|
||||
}
|
||||
@ -730,7 +740,7 @@ func TestContainerCombinations(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
// Use a closure so defer statements trigger between loop iterations.
|
||||
func() {
|
||||
t.Run(tt.test, func(t *testing.T) {
|
||||
service := new(mockService)
|
||||
service.statusCode = 200
|
||||
|
||||
@ -747,7 +757,7 @@ func TestContainerCombinations(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{})
|
||||
attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
|
||||
|
||||
err = wh.Validate(attr)
|
||||
if tt.wantAllowed {
|
||||
@ -769,27 +779,41 @@ func TestContainerCombinations(t *testing.T) {
|
||||
t.Errorf("%s: failed to admit: %v", tt.test, err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// fakeAttributes decorate kadmission.Attributes. It's used to trace the added annotations.
|
||||
type fakeAttributes struct {
|
||||
admission.Attributes
|
||||
annotations map[string]string
|
||||
}
|
||||
|
||||
func (f fakeAttributes) AddAnnotation(k, v string) error {
|
||||
f.annotations[k] = v
|
||||
return f.Attributes.AddAnnotation(k, v)
|
||||
}
|
||||
|
||||
func TestDefaultAllow(t *testing.T) {
|
||||
tests := []struct {
|
||||
test string
|
||||
pod *api.Pod
|
||||
wantAllowed, wantErr, defaultAllow bool
|
||||
defaultAllow bool
|
||||
wantAllowed, wantErr, wantFailOpen bool
|
||||
}{
|
||||
{
|
||||
test: "DefaultAllow = true, backend unreachable, bad image",
|
||||
pod: goodPod("bad"),
|
||||
defaultAllow: true,
|
||||
wantAllowed: true,
|
||||
wantFailOpen: true,
|
||||
},
|
||||
{
|
||||
test: "DefaultAllow = true, backend unreachable, good image",
|
||||
pod: goodPod("good"),
|
||||
defaultAllow: true,
|
||||
wantAllowed: true,
|
||||
wantFailOpen: true,
|
||||
},
|
||||
{
|
||||
test: "DefaultAllow = false, backend unreachable, good image",
|
||||
@ -797,6 +821,7 @@ func TestDefaultAllow(t *testing.T) {
|
||||
defaultAllow: false,
|
||||
wantAllowed: false,
|
||||
wantErr: true,
|
||||
wantFailOpen: false,
|
||||
},
|
||||
{
|
||||
test: "DefaultAllow = false, backend unreachable, bad image",
|
||||
@ -804,11 +829,12 @@ func TestDefaultAllow(t *testing.T) {
|
||||
defaultAllow: false,
|
||||
wantAllowed: false,
|
||||
wantErr: true,
|
||||
wantFailOpen: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
// Use a closure so defer statements trigger between loop iterations.
|
||||
func() {
|
||||
t.Run(tt.test, func(t *testing.T) {
|
||||
service := new(mockService)
|
||||
service.statusCode = 500
|
||||
|
||||
@ -825,7 +851,9 @@ func TestDefaultAllow(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{})
|
||||
attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
|
||||
annotations := make(map[string]string)
|
||||
attr = &fakeAttributes{attr, annotations}
|
||||
|
||||
err = wh.Validate(attr)
|
||||
if tt.wantAllowed {
|
||||
@ -847,7 +875,23 @@ func TestDefaultAllow(t *testing.T) {
|
||||
t.Errorf("%s: failed to admit: %v", tt.test, err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
podAnnotations := tt.pod.GetAnnotations()
|
||||
if tt.wantFailOpen {
|
||||
if podAnnotations == nil || podAnnotations[api.ImagePolicyFailedOpenKey] != "true" {
|
||||
t.Errorf("missing expected fail open pod annotation")
|
||||
}
|
||||
if annotations[AuditKeyPrefix+ImagePolicyFailedOpenKeySuffix] != "true" {
|
||||
t.Errorf("missing expected fail open attributes annotation")
|
||||
}
|
||||
} else {
|
||||
if podAnnotations != nil && podAnnotations[api.ImagePolicyFailedOpenKey] == "true" {
|
||||
t.Errorf("found unexpected fail open pod annotation")
|
||||
}
|
||||
if annotations[AuditKeyPrefix+ImagePolicyFailedOpenKeySuffix] == "true" {
|
||||
t.Errorf("found unexpected fail open attributes annotation")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -886,9 +930,9 @@ func TestAnnotationFiltering(t *testing.T) {
|
||||
annotations: map[string]string{
|
||||
"my.image-policy.k8s.io/test": "test",
|
||||
"other.image-policy.k8s.io/test2": "annotation",
|
||||
"test": "test",
|
||||
"another": "another",
|
||||
"": "",
|
||||
"test": "test",
|
||||
"another": "another",
|
||||
"": "",
|
||||
},
|
||||
outAnnotations: map[string]string{
|
||||
"my.image-policy.k8s.io/test": "test",
|
||||
@ -898,7 +942,7 @@ func TestAnnotationFiltering(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
// Use a closure so defer statements trigger between loop iterations.
|
||||
func() {
|
||||
t.Run(tt.test, func(t *testing.T) {
|
||||
service := new(annotationService)
|
||||
|
||||
server, err := NewTestServer(service, serverCert, serverKey, caCert)
|
||||
@ -917,7 +961,7 @@ func TestAnnotationFiltering(t *testing.T) {
|
||||
pod := goodPod("test")
|
||||
pod.Annotations = tt.annotations
|
||||
|
||||
attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &user.DefaultInfo{})
|
||||
attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
|
||||
|
||||
err = wh.Validate(attr)
|
||||
if err != nil {
|
||||
@ -928,7 +972,94 @@ func TestAnnotationFiltering(t *testing.T) {
|
||||
t.Errorf("expected annotations sent to webhook: %v to match expected: %v", service.Annotations(), tt.outAnnotations)
|
||||
}
|
||||
|
||||
}()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReturnedAnnotationAdd(t *testing.T) {
|
||||
tests := []struct {
|
||||
test string
|
||||
pod *api.Pod
|
||||
verifierAnnotations map[string]string
|
||||
expectedAnnotations map[string]string
|
||||
}{
|
||||
{
|
||||
test: "Add valid response annotations",
|
||||
pod: goodPod("good"),
|
||||
verifierAnnotations: map[string]string{
|
||||
"foo-test": "true",
|
||||
"bar-test": "false",
|
||||
},
|
||||
expectedAnnotations: map[string]string{
|
||||
"imagepolicywebhook.image-policy.k8s.io/foo-test": "true",
|
||||
"imagepolicywebhook.image-policy.k8s.io/bar-test": "false",
|
||||
},
|
||||
},
|
||||
{
|
||||
test: "No returned annotations are ignored",
|
||||
pod: goodPod("good"),
|
||||
verifierAnnotations: map[string]string{},
|
||||
expectedAnnotations: map[string]string{},
|
||||
},
|
||||
{
|
||||
test: "Handles nil annotations",
|
||||
pod: goodPod("good"),
|
||||
verifierAnnotations: nil,
|
||||
expectedAnnotations: map[string]string{},
|
||||
},
|
||||
{
|
||||
test: "Adds annotations for bad request",
|
||||
pod: &api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
ServiceAccountName: "default",
|
||||
SecurityContext: &api.PodSecurityContext{},
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Image: "bad",
|
||||
SecurityContext: &api.SecurityContext{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
verifierAnnotations: map[string]string{
|
||||
"foo-test": "false",
|
||||
},
|
||||
expectedAnnotations: map[string]string{
|
||||
"imagepolicywebhook.image-policy.k8s.io/foo-test": "false",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
// Use a closure so defer statements trigger between loop iterations.
|
||||
t.Run(tt.test, func(t *testing.T) {
|
||||
service := new(mockService)
|
||||
service.statusCode = 200
|
||||
service.outAnnotations = tt.verifierAnnotations
|
||||
|
||||
server, err := NewTestServer(service, serverCert, serverKey, caCert)
|
||||
if err != nil {
|
||||
t.Errorf("%s: failed to create server: %v", tt.test, err)
|
||||
return
|
||||
}
|
||||
defer server.Close()
|
||||
|
||||
wh, err := newImagePolicyWebhook(server.URL, clientCert, clientKey, caCert, 0, true)
|
||||
if err != nil {
|
||||
t.Errorf("%s: failed to create client: %v", tt.test, err)
|
||||
return
|
||||
}
|
||||
|
||||
pod := tt.pod
|
||||
|
||||
attr := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, false, &user.DefaultInfo{})
|
||||
annotations := make(map[string]string)
|
||||
attr = &fakeAttributes{attr, annotations}
|
||||
|
||||
err = wh.Validate(attr)
|
||||
if !reflect.DeepEqual(annotations, tt.expectedAnnotations) {
|
||||
t.Errorf("got audit annotations: %v; want: %v", annotations, tt.expectedAnnotations)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/config.go
generated
vendored
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/config.go
generated
vendored
@ -22,7 +22,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -72,13 +72,13 @@ func normalizeWebhookConfig(config *imagePolicyWebhookConfig) (err error) {
|
||||
func normalizeConfigDuration(name string, scale, value, min, max, defaultValue time.Duration) (time.Duration, error) {
|
||||
// disable with -1 sentinel
|
||||
if value == disableTTL {
|
||||
glog.V(2).Infof("image policy webhook %s disabled", name)
|
||||
klog.V(2).Infof("image policy webhook %s disabled", name)
|
||||
return time.Duration(0), nil
|
||||
}
|
||||
|
||||
// use default with 0 sentinel
|
||||
if value == useDefault {
|
||||
glog.V(2).Infof("image policy webhook %s using default value", name)
|
||||
klog.V(2).Infof("image policy webhook %s using default value", name)
|
||||
return defaultValue, nil
|
||||
}
|
||||
|
||||
|
47
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/BUILD
generated
vendored
47
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/BUILD
generated
vendored
@ -15,18 +15,19 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/limitranger",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/core/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -36,17 +37,19 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/client-go/testing:go_default_library",
|
||||
"//pkg/apis/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
128
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/admission.go
generated
vendored
128
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/admission.go
generated
vendored
@ -23,8 +23,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/hashicorp/golang-lru"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -32,11 +33,11 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitailizer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -55,9 +56,9 @@ func Register(plugins *admission.Plugins) {
|
||||
// LimitRanger enforces usage limits on a per resource basis in the namespace
|
||||
type LimitRanger struct {
|
||||
*admission.Handler
|
||||
client internalclientset.Interface
|
||||
client kubernetes.Interface
|
||||
actions LimitRangerActions
|
||||
lister corelisters.LimitRangeLister
|
||||
lister corev1listers.LimitRangeLister
|
||||
|
||||
// liveLookups holds the last few live lookups we've done to help ammortize cost on repeated lookup failures.
|
||||
// This let's us handle the case of latent caches, by looking up actual results for a namespace on cache miss/no results.
|
||||
@ -68,19 +69,25 @@ type LimitRanger struct {
|
||||
|
||||
var _ admission.MutationInterface = &LimitRanger{}
|
||||
var _ admission.ValidationInterface = &LimitRanger{}
|
||||
var _ kubeapiserveradmission.WantsInternalKubeInformerFactory = &LimitRanger{}
|
||||
|
||||
var _ genericadmissioninitailizer.WantsExternalKubeInformerFactory = &LimitRanger{}
|
||||
var _ genericadmissioninitailizer.WantsExternalKubeClientSet = &LimitRanger{}
|
||||
|
||||
type liveLookupEntry struct {
|
||||
expiry time.Time
|
||||
items []*api.LimitRange
|
||||
items []*corev1.LimitRange
|
||||
}
|
||||
|
||||
func (l *LimitRanger) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
limitRangeInformer := f.Core().InternalVersion().LimitRanges()
|
||||
func (l *LimitRanger) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
limitRangeInformer := f.Core().V1().LimitRanges()
|
||||
l.SetReadyFunc(limitRangeInformer.Informer().HasSynced)
|
||||
l.lister = limitRangeInformer.Lister()
|
||||
}
|
||||
|
||||
func (a *LimitRanger) SetExternalKubeClientSet(client kubernetes.Interface) {
|
||||
a.client = client
|
||||
}
|
||||
|
||||
func (l *LimitRanger) ValidateInitialization() error {
|
||||
if l.lister == nil {
|
||||
return fmt.Errorf("missing limitRange lister")
|
||||
@ -101,20 +108,11 @@ func (l *LimitRanger) Validate(a admission.Attributes) (err error) {
|
||||
return l.runLimitFunc(a, l.actions.ValidateLimit)
|
||||
}
|
||||
|
||||
func (l *LimitRanger) runLimitFunc(a admission.Attributes, limitFn func(limitRange *api.LimitRange, kind string, obj runtime.Object) error) (err error) {
|
||||
func (l *LimitRanger) runLimitFunc(a admission.Attributes, limitFn func(limitRange *corev1.LimitRange, kind string, obj runtime.Object) error) (err error) {
|
||||
if !l.actions.SupportsAttributes(a) {
|
||||
return nil
|
||||
}
|
||||
|
||||
obj := a.GetObject()
|
||||
name := "Unknown"
|
||||
if obj != nil {
|
||||
name, _ = meta.NewAccessor().Name(obj)
|
||||
if len(name) == 0 {
|
||||
name, _ = meta.NewAccessor().GenerateName(obj)
|
||||
}
|
||||
}
|
||||
|
||||
// ignore all objects marked for deletion
|
||||
oldObj := a.GetOldObject()
|
||||
if oldObj != nil {
|
||||
@ -148,7 +146,7 @@ func (l *LimitRanger) runLimitFunc(a admission.Attributes, limitFn func(limitRan
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LimitRanger) GetLimitRanges(a admission.Attributes) ([]*api.LimitRange, error) {
|
||||
func (l *LimitRanger) GetLimitRanges(a admission.Attributes) ([]*corev1.LimitRange, error) {
|
||||
items, err := l.lister.LimitRanges(a.GetNamespace()).List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, admission.NewForbidden(a, fmt.Errorf("unable to %s %v at this time because there was an error enforcing limit ranges", a.GetOperation(), a.GetResource()))
|
||||
@ -163,7 +161,7 @@ func (l *LimitRanger) GetLimitRanges(a admission.Attributes) ([]*api.LimitRange,
|
||||
// If there is already in-flight List() for a given namespace, we should wait until
|
||||
// it is finished and cache is updated instead of doing the same, also to avoid
|
||||
// throttling - see #22422 for details.
|
||||
liveList, err := l.client.Core().LimitRanges(a.GetNamespace()).List(metav1.ListOptions{})
|
||||
liveList, err := l.client.CoreV1().LimitRanges(a.GetNamespace()).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, admission.NewForbidden(a, err)
|
||||
}
|
||||
@ -204,31 +202,24 @@ func NewLimitRanger(actions LimitRangerActions) (*LimitRanger, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&LimitRanger{})
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&LimitRanger{})
|
||||
|
||||
func (a *LimitRanger) SetInternalKubeClientSet(client internalclientset.Interface) {
|
||||
a.client = client
|
||||
}
|
||||
|
||||
// defaultContainerResourceRequirements returns the default requirements for a container
|
||||
// the requirement.Limits are taken from the LimitRange defaults (if specified)
|
||||
// the requirement.Requests are taken from the LimitRange default request (if specified)
|
||||
func defaultContainerResourceRequirements(limitRange *api.LimitRange) api.ResourceRequirements {
|
||||
func defaultContainerResourceRequirements(limitRange *corev1.LimitRange) api.ResourceRequirements {
|
||||
requirements := api.ResourceRequirements{}
|
||||
requirements.Requests = api.ResourceList{}
|
||||
requirements.Limits = api.ResourceList{}
|
||||
|
||||
for i := range limitRange.Spec.Limits {
|
||||
limit := limitRange.Spec.Limits[i]
|
||||
if limit.Type == api.LimitTypeContainer {
|
||||
if limit.Type == corev1.LimitTypeContainer {
|
||||
for k, v := range limit.DefaultRequest {
|
||||
value := v.Copy()
|
||||
requirements.Requests[k] = *value
|
||||
requirements.Requests[api.ResourceName(k)] = *value
|
||||
}
|
||||
for k, v := range limit.Default {
|
||||
value := v.Copy()
|
||||
requirements.Limits[k] = *value
|
||||
requirements.Limits[api.ResourceName(k)] = *value
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -309,9 +300,9 @@ func requestLimitEnforcedValues(requestQuantity, limitQuantity, enforcedQuantity
|
||||
}
|
||||
|
||||
// minConstraint enforces the min constraint over the specified resource
|
||||
func minConstraint(limitType api.LimitType, resourceName api.ResourceName, enforced resource.Quantity, request api.ResourceList, limit api.ResourceList) error {
|
||||
req, reqExists := request[resourceName]
|
||||
lim, limExists := limit[resourceName]
|
||||
func minConstraint(limitType string, resourceName string, enforced resource.Quantity, request api.ResourceList, limit api.ResourceList) error {
|
||||
req, reqExists := request[api.ResourceName(resourceName)]
|
||||
lim, limExists := limit[api.ResourceName(resourceName)]
|
||||
observedReqValue, observedLimValue, enforcedValue := requestLimitEnforcedValues(req, lim, enforced)
|
||||
|
||||
if !reqExists {
|
||||
@ -328,8 +319,8 @@ func minConstraint(limitType api.LimitType, resourceName api.ResourceName, enfor
|
||||
|
||||
// maxRequestConstraint enforces the max constraint over the specified resource
|
||||
// use when specify LimitType resource doesn't recognize limit values
|
||||
func maxRequestConstraint(limitType api.LimitType, resourceName api.ResourceName, enforced resource.Quantity, request api.ResourceList) error {
|
||||
req, reqExists := request[resourceName]
|
||||
func maxRequestConstraint(limitType string, resourceName string, enforced resource.Quantity, request api.ResourceList) error {
|
||||
req, reqExists := request[api.ResourceName(resourceName)]
|
||||
observedReqValue, _, enforcedValue := requestLimitEnforcedValues(req, resource.Quantity{}, enforced)
|
||||
|
||||
if !reqExists {
|
||||
@ -342,9 +333,9 @@ func maxRequestConstraint(limitType api.LimitType, resourceName api.ResourceName
|
||||
}
|
||||
|
||||
// maxConstraint enforces the max constraint over the specified resource
|
||||
func maxConstraint(limitType api.LimitType, resourceName api.ResourceName, enforced resource.Quantity, request api.ResourceList, limit api.ResourceList) error {
|
||||
req, reqExists := request[resourceName]
|
||||
lim, limExists := limit[resourceName]
|
||||
func maxConstraint(limitType string, resourceName string, enforced resource.Quantity, request api.ResourceList, limit api.ResourceList) error {
|
||||
req, reqExists := request[api.ResourceName(resourceName)]
|
||||
lim, limExists := limit[api.ResourceName(resourceName)]
|
||||
observedReqValue, observedLimValue, enforcedValue := requestLimitEnforcedValues(req, lim, enforced)
|
||||
|
||||
if !limExists {
|
||||
@ -360,9 +351,9 @@ func maxConstraint(limitType api.LimitType, resourceName api.ResourceName, enfor
|
||||
}
|
||||
|
||||
// limitRequestRatioConstraint enforces the limit to request ratio over the specified resource
|
||||
func limitRequestRatioConstraint(limitType api.LimitType, resourceName api.ResourceName, enforced resource.Quantity, request api.ResourceList, limit api.ResourceList) error {
|
||||
req, reqExists := request[resourceName]
|
||||
lim, limExists := limit[resourceName]
|
||||
func limitRequestRatioConstraint(limitType string, resourceName string, enforced resource.Quantity, request api.ResourceList, limit api.ResourceList) error {
|
||||
req, reqExists := request[api.ResourceName(resourceName)]
|
||||
lim, limExists := limit[api.ResourceName(resourceName)]
|
||||
observedReqValue, observedLimValue, _ := requestLimitEnforcedValues(req, lim, enforced)
|
||||
|
||||
if !reqExists || (observedReqValue == int64(0)) {
|
||||
@ -435,7 +426,7 @@ var _ LimitRangerActions = &DefaultLimitRangerActions{}
|
||||
// Limit enforces resource requirements of incoming resources against enumerated constraints
|
||||
// on the LimitRange. It may modify the incoming object to apply default resource requirements
|
||||
// if not specified, and enumerated on the LimitRange
|
||||
func (d *DefaultLimitRangerActions) MutateLimit(limitRange *api.LimitRange, resourceName string, obj runtime.Object) error {
|
||||
func (d *DefaultLimitRangerActions) MutateLimit(limitRange *corev1.LimitRange, resourceName string, obj runtime.Object) error {
|
||||
switch resourceName {
|
||||
case "pods":
|
||||
return PodMutateLimitFunc(limitRange, obj.(*api.Pod))
|
||||
@ -446,7 +437,7 @@ func (d *DefaultLimitRangerActions) MutateLimit(limitRange *api.LimitRange, reso
|
||||
// Limit enforces resource requirements of incoming resources against enumerated constraints
|
||||
// on the LimitRange. It may modify the incoming object to apply default resource requirements
|
||||
// if not specified, and enumerated on the LimitRange
|
||||
func (d *DefaultLimitRangerActions) ValidateLimit(limitRange *api.LimitRange, resourceName string, obj runtime.Object) error {
|
||||
func (d *DefaultLimitRangerActions) ValidateLimit(limitRange *corev1.LimitRange, resourceName string, obj runtime.Object) error {
|
||||
switch resourceName {
|
||||
case "pods":
|
||||
return PodValidateLimitFunc(limitRange, obj.(*api.Pod))
|
||||
@ -463,11 +454,18 @@ func (d *DefaultLimitRangerActions) SupportsAttributes(a admission.Attributes) b
|
||||
return false
|
||||
}
|
||||
|
||||
// Since containers and initContainers cannot currently be added, removed, or updated, it is unnecessary
|
||||
// to mutate and validate limitrange on pod updates. Trying to mutate containers or initContainers on a pod
|
||||
// update request will always fail pod validation because those fields are immutable once the object is created.
|
||||
if a.GetKind().GroupKind() == api.Kind("Pod") && a.GetOperation() == admission.Update {
|
||||
return false
|
||||
}
|
||||
|
||||
return a.GetKind().GroupKind() == api.Kind("Pod") || a.GetKind().GroupKind() == api.Kind("PersistentVolumeClaim")
|
||||
}
|
||||
|
||||
// SupportsLimit always returns true.
|
||||
func (d *DefaultLimitRangerActions) SupportsLimit(limitRange *api.LimitRange) bool {
|
||||
func (d *DefaultLimitRangerActions) SupportsLimit(limitRange *corev1.LimitRange) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@ -475,22 +473,22 @@ func (d *DefaultLimitRangerActions) SupportsLimit(limitRange *api.LimitRange) bo
|
||||
// Users request storage via pvc.Spec.Resources.Requests. Min/Max is enforced by an admin with LimitRange.
|
||||
// Claims will not be modified with default values because storage is a required part of pvc.Spec.
|
||||
// All storage enforced values *only* apply to pvc.Spec.Resources.Requests.
|
||||
func PersistentVolumeClaimValidateLimitFunc(limitRange *api.LimitRange, pvc *api.PersistentVolumeClaim) error {
|
||||
func PersistentVolumeClaimValidateLimitFunc(limitRange *corev1.LimitRange, pvc *api.PersistentVolumeClaim) error {
|
||||
var errs []error
|
||||
for i := range limitRange.Spec.Limits {
|
||||
limit := limitRange.Spec.Limits[i]
|
||||
limitType := limit.Type
|
||||
if limitType == api.LimitTypePersistentVolumeClaim {
|
||||
if limitType == corev1.LimitTypePersistentVolumeClaim {
|
||||
for k, v := range limit.Min {
|
||||
// normal usage of minConstraint. pvc.Spec.Resources.Limits is not recognized as user input
|
||||
if err := minConstraint(limitType, k, v, pvc.Spec.Resources.Requests, api.ResourceList{}); err != nil {
|
||||
if err := minConstraint(string(limitType), string(k), v, pvc.Spec.Resources.Requests, api.ResourceList{}); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
for k, v := range limit.Max {
|
||||
// We want to enforce the max of the LimitRange against what
|
||||
// the user requested.
|
||||
if err := maxRequestConstraint(limitType, k, v, pvc.Spec.Resources.Requests); err != nil {
|
||||
if err := maxRequestConstraint(string(limitType), string(k), v, pvc.Spec.Resources.Requests); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
@ -502,7 +500,7 @@ func PersistentVolumeClaimValidateLimitFunc(limitRange *api.LimitRange, pvc *api
|
||||
// PodMutateLimitFunc sets resource requirements enumerated by the pod against
|
||||
// the specified LimitRange. The pod may be modified to apply default resource
|
||||
// requirements if not specified, and enumerated on the LimitRange
|
||||
func PodMutateLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {
|
||||
func PodMutateLimitFunc(limitRange *corev1.LimitRange, pod *api.Pod) error {
|
||||
defaultResources := defaultContainerResourceRequirements(limitRange)
|
||||
mergePodResourceRequirements(pod, &defaultResources)
|
||||
return nil
|
||||
@ -510,28 +508,28 @@ func PodMutateLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {
|
||||
|
||||
// PodValidateLimitFunc enforces resource requirements enumerated by the pod against
|
||||
// the specified LimitRange.
|
||||
func PodValidateLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {
|
||||
func PodValidateLimitFunc(limitRange *corev1.LimitRange, pod *api.Pod) error {
|
||||
var errs []error
|
||||
|
||||
for i := range limitRange.Spec.Limits {
|
||||
limit := limitRange.Spec.Limits[i]
|
||||
limitType := limit.Type
|
||||
// enforce container limits
|
||||
if limitType == api.LimitTypeContainer {
|
||||
if limitType == corev1.LimitTypeContainer {
|
||||
for j := range pod.Spec.Containers {
|
||||
container := &pod.Spec.Containers[j]
|
||||
for k, v := range limit.Min {
|
||||
if err := minConstraint(limitType, k, v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
if err := minConstraint(string(limitType), string(k), v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
for k, v := range limit.Max {
|
||||
if err := maxConstraint(limitType, k, v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
if err := maxConstraint(string(limitType), string(k), v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
for k, v := range limit.MaxLimitRequestRatio {
|
||||
if err := limitRequestRatioConstraint(limitType, k, v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
if err := limitRequestRatioConstraint(string(limitType), string(k), v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
@ -539,17 +537,17 @@ func PodValidateLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {
|
||||
for j := range pod.Spec.InitContainers {
|
||||
container := &pod.Spec.InitContainers[j]
|
||||
for k, v := range limit.Min {
|
||||
if err := minConstraint(limitType, k, v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
if err := minConstraint(string(limitType), string(k), v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
for k, v := range limit.Max {
|
||||
if err := maxConstraint(limitType, k, v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
if err := maxConstraint(string(limitType), string(k), v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
for k, v := range limit.MaxLimitRequestRatio {
|
||||
if err := limitRequestRatioConstraint(limitType, k, v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
if err := limitRequestRatioConstraint(string(limitType), string(k), v, container.Resources.Requests, container.Resources.Limits); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
@ -557,7 +555,7 @@ func PodValidateLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {
|
||||
}
|
||||
|
||||
// enforce pod limits on init containers
|
||||
if limitType == api.LimitTypePod {
|
||||
if limitType == corev1.LimitTypePod {
|
||||
containerRequests, containerLimits := []api.ResourceList{}, []api.ResourceList{}
|
||||
for j := range pod.Spec.Containers {
|
||||
container := &pod.Spec.Containers[j]
|
||||
@ -589,17 +587,17 @@ func PodValidateLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {
|
||||
}
|
||||
}
|
||||
for k, v := range limit.Min {
|
||||
if err := minConstraint(limitType, k, v, podRequests, podLimits); err != nil {
|
||||
if err := minConstraint(string(limitType), string(k), v, podRequests, podLimits); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
for k, v := range limit.Max {
|
||||
if err := maxConstraint(limitType, k, v, podRequests, podLimits); err != nil {
|
||||
if err := maxConstraint(string(limitType), string(k), v, podRequests, podLimits); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
for k, v := range limit.MaxLimitRequestRatio {
|
||||
if err := limitRequestRatioConstraint(limitType, k, v, podRequests, podLimits); err != nil {
|
||||
if err := limitRequestRatioConstraint(string(limitType), string(k), v, podRequests, podLimits); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
71
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/admission_test.go
generated
vendored
71
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/admission_test.go
generated
vendored
@ -22,18 +22,20 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/client-go/informers"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
"k8s.io/kubernetes/pkg/apis/core/v1"
|
||||
)
|
||||
|
||||
func getComputeResourceList(cpu, memory string) api.ResourceList {
|
||||
@ -63,8 +65,8 @@ func getResourceRequirements(requests, limits api.ResourceList) api.ResourceRequ
|
||||
}
|
||||
|
||||
// createLimitRange creates a limit range with the specified data
|
||||
func createLimitRange(limitType api.LimitType, min, max, defaultLimit, defaultRequest, maxLimitRequestRatio api.ResourceList) api.LimitRange {
|
||||
return api.LimitRange{
|
||||
func createLimitRange(limitType api.LimitType, min, max, defaultLimit, defaultRequest, maxLimitRequestRatio api.ResourceList) corev1.LimitRange {
|
||||
internalLimitRage := api.LimitRange{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "abc",
|
||||
Namespace: "test",
|
||||
@ -82,10 +84,13 @@ func createLimitRange(limitType api.LimitType, min, max, defaultLimit, defaultRe
|
||||
},
|
||||
},
|
||||
}
|
||||
externalLimitRange := corev1.LimitRange{}
|
||||
v1.Convert_core_LimitRange_To_v1_LimitRange(&internalLimitRage, &externalLimitRange, nil)
|
||||
return externalLimitRange
|
||||
}
|
||||
|
||||
func validLimitRange() api.LimitRange {
|
||||
return api.LimitRange{
|
||||
func validLimitRange() corev1.LimitRange {
|
||||
internalLimitRange := api.LimitRange{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "abc",
|
||||
Namespace: "test",
|
||||
@ -107,10 +112,13 @@ func validLimitRange() api.LimitRange {
|
||||
},
|
||||
},
|
||||
}
|
||||
externalLimitRange := corev1.LimitRange{}
|
||||
v1.Convert_core_LimitRange_To_v1_LimitRange(&internalLimitRange, &externalLimitRange, nil)
|
||||
return externalLimitRange
|
||||
}
|
||||
|
||||
func validLimitRangeNoDefaults() api.LimitRange {
|
||||
return api.LimitRange{
|
||||
func validLimitRangeNoDefaults() corev1.LimitRange {
|
||||
internalLimitRange := api.LimitRange{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "abc",
|
||||
Namespace: "test",
|
||||
@ -130,6 +138,9 @@ func validLimitRangeNoDefaults() api.LimitRange {
|
||||
},
|
||||
},
|
||||
}
|
||||
externalLimitRange := corev1.LimitRange{}
|
||||
v1.Convert_core_LimitRange_To_v1_LimitRange(&internalLimitRange, &externalLimitRange, nil)
|
||||
return externalLimitRange
|
||||
}
|
||||
|
||||
func validPod(name string, numContainers int, resources api.ResourceRequirements) api.Pod {
|
||||
@ -255,7 +266,7 @@ func TestMergePodResourceRequirements(t *testing.T) {
|
||||
func TestPodLimitFunc(t *testing.T) {
|
||||
type testCase struct {
|
||||
pod api.Pod
|
||||
limitRange api.LimitRange
|
||||
limitRange corev1.LimitRange
|
||||
}
|
||||
|
||||
successCases := []testCase{
|
||||
@ -686,7 +697,7 @@ func TestPodLimitFuncApplyDefault(t *testing.T) {
|
||||
|
||||
func TestLimitRangerIgnoresSubresource(t *testing.T) {
|
||||
limitRange := validLimitRangeNoDefaults()
|
||||
mockClient := newMockClientForTest([]api.LimitRange{limitRange})
|
||||
mockClient := newMockClientForTest([]corev1.LimitRange{limitRange})
|
||||
handler, informerFactory, err := newHandlerForTest(mockClient)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error initializing handler: %v", err)
|
||||
@ -694,16 +705,20 @@ func TestLimitRangerIgnoresSubresource(t *testing.T) {
|
||||
informerFactory.Start(wait.NeverStop)
|
||||
|
||||
testPod := validPod("testPod", 1, api.ResourceRequirements{})
|
||||
err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, nil))
|
||||
err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, nil))
|
||||
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err == nil {
|
||||
t.Errorf("Expected an error since the pod did not specify resource limits in its update call")
|
||||
t.Errorf("Expected an error since the pod did not specify resource limits in its create call")
|
||||
}
|
||||
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("Expected not to call limitranger actions on pod updates")
|
||||
}
|
||||
|
||||
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, nil))
|
||||
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("Should have ignored calls to any subresource of pod %v", err)
|
||||
}
|
||||
@ -712,7 +727,7 @@ func TestLimitRangerIgnoresSubresource(t *testing.T) {
|
||||
|
||||
func TestLimitRangerAdmitPod(t *testing.T) {
|
||||
limitRange := validLimitRangeNoDefaults()
|
||||
mockClient := newMockClientForTest([]api.LimitRange{limitRange})
|
||||
mockClient := newMockClientForTest([]corev1.LimitRange{limitRange})
|
||||
handler, informerFactory, err := newHandlerForTest(mockClient)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error initializing handler: %v", err)
|
||||
@ -720,16 +735,20 @@ func TestLimitRangerAdmitPod(t *testing.T) {
|
||||
informerFactory.Start(wait.NeverStop)
|
||||
|
||||
testPod := validPod("testPod", 1, api.ResourceRequirements{})
|
||||
err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, nil))
|
||||
err = handler.Admit(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, nil))
|
||||
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err == nil {
|
||||
t.Errorf("Expected an error since the pod did not specify resource limits in its update call")
|
||||
t.Errorf("Expected an error since the pod did not specify resource limits in its create call")
|
||||
}
|
||||
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("Expected not to call limitranger actions on pod updates")
|
||||
}
|
||||
|
||||
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, nil))
|
||||
err = handler.Validate(admission.NewAttributesRecord(&testPod, nil, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "testPod", api.Resource("pods").WithVersion("version"), "status", admission.Update, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("Should have ignored calls to any subresource of pod %v", err)
|
||||
}
|
||||
@ -738,17 +757,17 @@ func TestLimitRangerAdmitPod(t *testing.T) {
|
||||
terminatingPod := validPod("terminatingPod", 1, api.ResourceRequirements{})
|
||||
now := metav1.Now()
|
||||
terminatingPod.DeletionTimestamp = &now
|
||||
err = handler.Validate(admission.NewAttributesRecord(&terminatingPod, &terminatingPod, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "terminatingPod", api.Resource("pods").WithVersion("version"), "", admission.Update, nil))
|
||||
err = handler.Validate(admission.NewAttributesRecord(&terminatingPod, &terminatingPod, api.Kind("Pod").WithVersion("version"), limitRange.Namespace, "terminatingPod", api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("LimitRange should ignore a pod marked for termination")
|
||||
}
|
||||
}
|
||||
|
||||
// newMockClientForTest creates a mock client that returns a client configured for the specified list of limit ranges
|
||||
func newMockClientForTest(limitRanges []api.LimitRange) *fake.Clientset {
|
||||
func newMockClientForTest(limitRanges []corev1.LimitRange) *fake.Clientset {
|
||||
mockClient := &fake.Clientset{}
|
||||
mockClient.AddReactor("list", "limitranges", func(action core.Action) (bool, runtime.Object, error) {
|
||||
limitRangeList := &api.LimitRangeList{
|
||||
limitRangeList := &corev1.LimitRangeList{
|
||||
ListMeta: metav1.ListMeta{
|
||||
ResourceVersion: fmt.Sprintf("%d", len(limitRanges)),
|
||||
},
|
||||
@ -769,7 +788,7 @@ func newHandlerForTest(c clientset.Interface) (*LimitRanger, informers.SharedInf
|
||||
if err != nil {
|
||||
return nil, f, err
|
||||
}
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
|
||||
pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil)
|
||||
pluginInitializer.Initialize(handler)
|
||||
err = admission.ValidateInitialization(handler)
|
||||
return handler, f, err
|
||||
@ -788,7 +807,7 @@ func validPersistentVolumeClaim(name string, resources api.ResourceRequirements)
|
||||
func TestPersistentVolumeClaimLimitFunc(t *testing.T) {
|
||||
type testCase struct {
|
||||
pvc api.PersistentVolumeClaim
|
||||
limitRange api.LimitRange
|
||||
limitRange corev1.LimitRange
|
||||
}
|
||||
|
||||
successCases := []testCase{
|
||||
|
8
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/interfaces.go
generated
vendored
8
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/interfaces.go
generated
vendored
@ -17,20 +17,20 @@ limitations under the License.
|
||||
package limitranger
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
type LimitRangerActions interface {
|
||||
// MutateLimit is a pluggable function to set limits on the object.
|
||||
MutateLimit(limitRange *api.LimitRange, kind string, obj runtime.Object) error
|
||||
MutateLimit(limitRange *corev1.LimitRange, kind string, obj runtime.Object) error
|
||||
// ValidateLimits is a pluggable function to enforce limits on the object.
|
||||
ValidateLimit(limitRange *api.LimitRange, kind string, obj runtime.Object) error
|
||||
ValidateLimit(limitRange *corev1.LimitRange, kind string, obj runtime.Object) error
|
||||
// SupportsAttributes is a pluggable function to allow overridding what resources the limitranger
|
||||
// supports.
|
||||
SupportsAttributes(attr admission.Attributes) bool
|
||||
// SupportsLimit is a pluggable function to allow ignoring limits that should not be applied
|
||||
// for any reason.
|
||||
SupportsLimit(limitRange *api.LimitRange) bool
|
||||
SupportsLimit(limitRange *corev1.LimitRange) bool
|
||||
}
|
||||
|
36
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision/BUILD
generated
vendored
36
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision/BUILD
generated
vendored
@ -12,13 +12,14 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/core/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -28,16 +29,17 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/client-go/testing:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
36
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision/admission.go
generated
vendored
36
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision/admission.go
generated
vendored
@ -20,14 +20,15 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
@ -45,16 +46,21 @@ func Register(plugins *admission.Plugins) {
|
||||
// It is useful in deployments that do not want to restrict creation of a namespace prior to its usage.
|
||||
type Provision struct {
|
||||
*admission.Handler
|
||||
client internalclientset.Interface
|
||||
namespaceLister corelisters.NamespaceLister
|
||||
client kubernetes.Interface
|
||||
namespaceLister corev1listers.NamespaceLister
|
||||
}
|
||||
|
||||
var _ admission.MutationInterface = &Provision{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&Provision{})
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&Provision{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&Provision{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeClientSet(&Provision{})
|
||||
|
||||
// Admit makes an admission decision based on the request attributes
|
||||
func (p *Provision) Admit(a admission.Attributes) error {
|
||||
// Don't create a namespace if the request is for a dry-run.
|
||||
if a.IsDryRun() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// if we're here, then we've already passed authentication, so we're allowed to do what we're trying to do
|
||||
// if we're here, then the API server has found a route, which means that if we have a non-empty namespace
|
||||
// its a namespaced resource.
|
||||
@ -75,12 +81,12 @@ func (p *Provision) Admit(a admission.Attributes) error {
|
||||
return admission.NewForbidden(a, err)
|
||||
}
|
||||
|
||||
namespace := &api.Namespace{
|
||||
namespace := &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: a.GetNamespace(),
|
||||
Namespace: "",
|
||||
},
|
||||
Status: api.NamespaceStatus{},
|
||||
Status: corev1.NamespaceStatus{},
|
||||
}
|
||||
|
||||
_, err = p.client.Core().Namespaces().Create(namespace)
|
||||
@ -98,14 +104,14 @@ func NewProvision() *Provision {
|
||||
}
|
||||
}
|
||||
|
||||
// SetInternalKubeClientSet implements the WantsInternalKubeClientSet interface.
|
||||
func (p *Provision) SetInternalKubeClientSet(client internalclientset.Interface) {
|
||||
// SetExternalKubeClientSet implements the WantsExternalKubeClientSet interface.
|
||||
func (p *Provision) SetExternalKubeClientSet(client kubernetes.Interface) {
|
||||
p.client = client
|
||||
}
|
||||
|
||||
// SetInternalKubeInformerFactory implements the WantsInternalKubeInformerFactory interface.
|
||||
func (p *Provision) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
namespaceInformer := f.Core().InternalVersion().Namespaces()
|
||||
// SetExternalKubeInformerFactory implements the WantsExternalKubeInformerFactory interface.
|
||||
func (p *Provision) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
namespaceInformer := f.Core().V1().Namespaces()
|
||||
p.namespaceLister = namespaceInformer.Lister()
|
||||
p.SetReadyFunc(namespaceInformer.Informer().HasSynced)
|
||||
}
|
||||
|
43
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision/admission_test.go
generated
vendored
43
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision/admission_test.go
generated
vendored
@ -21,24 +21,25 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/client-go/informers"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
)
|
||||
|
||||
// newHandlerForTest returns the admission controller configured for testing.
|
||||
func newHandlerForTest(c clientset.Interface) (admission.MutationInterface, informers.SharedInformerFactory, error) {
|
||||
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
||||
handler := NewProvision()
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
|
||||
pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil)
|
||||
pluginInitializer.Initialize(handler)
|
||||
err := admission.ValidateInitialization(handler)
|
||||
return handler, f, err
|
||||
@ -48,13 +49,13 @@ func newHandlerForTest(c clientset.Interface) (admission.MutationInterface, info
|
||||
func newMockClientForTest(namespaces []string) *fake.Clientset {
|
||||
mockClient := &fake.Clientset{}
|
||||
mockClient.AddReactor("list", "namespaces", func(action core.Action) (bool, runtime.Object, error) {
|
||||
namespaceList := &api.NamespaceList{
|
||||
namespaceList := &corev1.NamespaceList{
|
||||
ListMeta: metav1.ListMeta{
|
||||
ResourceVersion: fmt.Sprintf("%d", len(namespaces)),
|
||||
},
|
||||
}
|
||||
for i, ns := range namespaces {
|
||||
namespaceList.Items = append(namespaceList.Items, api.Namespace{
|
||||
namespaceList.Items = append(namespaceList.Items, corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ns,
|
||||
ResourceVersion: fmt.Sprintf("%d", i),
|
||||
@ -98,7 +99,7 @@ func TestAdmission(t *testing.T) {
|
||||
informerFactory.Start(wait.NeverStop)
|
||||
|
||||
pod := newPod(namespace)
|
||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error returned from admission handler")
|
||||
}
|
||||
@ -118,7 +119,27 @@ func TestAdmissionNamespaceExists(t *testing.T) {
|
||||
informerFactory.Start(wait.NeverStop)
|
||||
|
||||
pod := newPod(namespace)
|
||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error returned from admission handler")
|
||||
}
|
||||
if hasCreateNamespaceAction(mockClient) {
|
||||
t.Errorf("unexpected create namespace action")
|
||||
}
|
||||
}
|
||||
|
||||
// TestAdmissionDryRun verifies that no client call is made on a dry run request
|
||||
func TestAdmissionDryRun(t *testing.T) {
|
||||
namespace := "test"
|
||||
mockClient := newMockClientForTest([]string{})
|
||||
handler, informerFactory, err := newHandlerForTest(mockClient)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error initializing handler: %v", err)
|
||||
}
|
||||
informerFactory.Start(wait.NeverStop)
|
||||
|
||||
pod := newPod(namespace)
|
||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, true, nil))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error returned from admission handler")
|
||||
}
|
||||
@ -139,7 +160,7 @@ func TestIgnoreAdmission(t *testing.T) {
|
||||
chainHandler := admission.NewChainHandler(handler)
|
||||
|
||||
pod := newPod(namespace)
|
||||
err = chainHandler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, nil))
|
||||
err = chainHandler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error returned from admission handler")
|
||||
}
|
||||
@ -161,7 +182,7 @@ func TestAdmissionWithLatentCache(t *testing.T) {
|
||||
informerFactory.Start(wait.NeverStop)
|
||||
|
||||
pod := newPod(namespace)
|
||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||
err = handler.Admit(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error returned from admission handler")
|
||||
}
|
||||
|
33
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/exists/BUILD
generated
vendored
33
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/exists/BUILD
generated
vendored
@ -12,13 +12,13 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/namespace/exists",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/core/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -28,15 +28,16 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/client-go/testing:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
26
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/exists/admission.go
generated
vendored
26
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/exists/admission.go
generated
vendored
@ -23,11 +23,11 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
informers "k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
@ -45,13 +45,13 @@ func Register(plugins *admission.Plugins) {
|
||||
// It is useful in deployments that want to enforce pre-declaration of a Namespace resource.
|
||||
type Exists struct {
|
||||
*admission.Handler
|
||||
client internalclientset.Interface
|
||||
namespaceLister corelisters.NamespaceLister
|
||||
client kubernetes.Interface
|
||||
namespaceLister corev1listers.NamespaceLister
|
||||
}
|
||||
|
||||
var _ admission.ValidationInterface = &Exists{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&Exists{})
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&Exists{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&Exists{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeClientSet(&Exists{})
|
||||
|
||||
// Validate makes an admission decision based on the request attributes
|
||||
func (e *Exists) Validate(a admission.Attributes) error {
|
||||
@ -93,14 +93,14 @@ func NewExists() *Exists {
|
||||
}
|
||||
}
|
||||
|
||||
// SetInternalKubeClientSet implements the WantsInternalKubeClientSet interface.
|
||||
func (e *Exists) SetInternalKubeClientSet(client internalclientset.Interface) {
|
||||
// SetExternalKubeClientSet implements the WantsExternalKubeClientSet interface.
|
||||
func (e *Exists) SetExternalKubeClientSet(client kubernetes.Interface) {
|
||||
e.client = client
|
||||
}
|
||||
|
||||
// SetInternalKubeInformerFactory implements the WantsInternalKubeInformerFactory interface.
|
||||
func (e *Exists) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
namespaceInformer := f.Core().InternalVersion().Namespaces()
|
||||
// SetExternalKubeInformerFactory implements the WantsExternalKubeInformerFactory interface.
|
||||
func (e *Exists) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
namespaceInformer := f.Core().V1().Namespaces()
|
||||
e.namespaceLister = namespaceInformer.Lister()
|
||||
e.SetReadyFunc(namespaceInformer.Informer().HasSynced)
|
||||
}
|
||||
|
21
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/exists/admission_test.go
generated
vendored
21
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/exists/admission_test.go
generated
vendored
@ -21,23 +21,24 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
informers "k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
)
|
||||
|
||||
// newHandlerForTest returns the admission controller configured for testing.
|
||||
func newHandlerForTest(c clientset.Interface) (admission.ValidationInterface, informers.SharedInformerFactory, error) {
|
||||
func newHandlerForTest(c kubernetes.Interface) (admission.ValidationInterface, informers.SharedInformerFactory, error) {
|
||||
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
||||
handler := NewExists()
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
|
||||
pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil)
|
||||
pluginInitializer.Initialize(handler)
|
||||
err := admission.ValidateInitialization(handler)
|
||||
return handler, f, err
|
||||
@ -47,13 +48,13 @@ func newHandlerForTest(c clientset.Interface) (admission.ValidationInterface, in
|
||||
func newMockClientForTest(namespaces []string) *fake.Clientset {
|
||||
mockClient := &fake.Clientset{}
|
||||
mockClient.AddReactor("list", "namespaces", func(action core.Action) (bool, runtime.Object, error) {
|
||||
namespaceList := &api.NamespaceList{
|
||||
namespaceList := &corev1.NamespaceList{
|
||||
ListMeta: metav1.ListMeta{
|
||||
ResourceVersion: fmt.Sprintf("%d", len(namespaces)),
|
||||
},
|
||||
}
|
||||
for i, ns := range namespaces {
|
||||
namespaceList.Items = append(namespaceList.Items, api.Namespace{
|
||||
namespaceList.Items = append(namespaceList.Items, corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: ns,
|
||||
ResourceVersion: fmt.Sprintf("%d", i),
|
||||
@ -87,7 +88,7 @@ func TestAdmissionNamespaceExists(t *testing.T) {
|
||||
informerFactory.Start(wait.NeverStop)
|
||||
|
||||
pod := newPod(namespace)
|
||||
err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||
err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error returned from admission handler")
|
||||
}
|
||||
@ -107,7 +108,7 @@ func TestAdmissionNamespaceDoesNotExist(t *testing.T) {
|
||||
informerFactory.Start(wait.NeverStop)
|
||||
|
||||
pod := newPod(namespace)
|
||||
err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||
err = handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err == nil {
|
||||
actions := ""
|
||||
for _, action := range mockClient.Actions() {
|
||||
|
43
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/BUILD
generated
vendored
43
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/BUILD
generated
vendored
@ -13,18 +13,24 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/api/pod:go_default_library",
|
||||
"//pkg/apis/authentication:go_default_library",
|
||||
"//pkg/apis/coordination:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/policy:go_default_library",
|
||||
"//pkg/auth/nodeidentifier:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/core/internalversion:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -34,17 +40,24 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/authentication:go_default_library",
|
||||
"//pkg/apis/coordination:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/policy:go_default_library",
|
||||
"//pkg/auth/nodeidentifier:go_default_library",
|
||||
"//pkg/client/listers/core/internalversion:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
|
||||
"//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/utils/pointer:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
13
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/OWNERS
generated
vendored
13
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/OWNERS
generated
vendored
@ -1,10 +1,7 @@
|
||||
approvers:
|
||||
- deads2k
|
||||
- liggitt
|
||||
- tallclair
|
||||
- mikedanese
|
||||
- sig-auth-node-isolation-approvers
|
||||
reviewers:
|
||||
- deads2k
|
||||
- liggitt
|
||||
- tallclair
|
||||
- mikedanese
|
||||
- sig-auth-node-isolation-reviewers
|
||||
labels:
|
||||
- sig/auth
|
||||
|
||||
|
185
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission.go
generated
vendored
185
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission.go
generated
vendored
@ -19,21 +19,28 @@ package noderestriction
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
apiserveradmission "k8s.io/apiserver/pkg/admission/initializer"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/informers"
|
||||
corev1lister "k8s.io/client-go/listers/core/v1"
|
||||
csiv1alpha1 "k8s.io/csi-api/pkg/apis/csi/v1alpha1"
|
||||
"k8s.io/klog"
|
||||
podutil "k8s.io/kubernetes/pkg/api/pod"
|
||||
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
|
||||
coordapi "k8s.io/kubernetes/pkg/apis/coordination"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
internalversion "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -61,18 +68,18 @@ func NewPlugin(nodeIdentifier nodeidentifier.NodeIdentifier) *nodePlugin {
|
||||
type nodePlugin struct {
|
||||
*admission.Handler
|
||||
nodeIdentifier nodeidentifier.NodeIdentifier
|
||||
podsGetter internalversion.PodLister
|
||||
podsGetter corev1lister.PodLister
|
||||
// allows overriding for testing
|
||||
features utilfeature.FeatureGate
|
||||
}
|
||||
|
||||
var (
|
||||
_ = admission.Interface(&nodePlugin{})
|
||||
_ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&nodePlugin{})
|
||||
_ = apiserveradmission.WantsExternalKubeInformerFactory(&nodePlugin{})
|
||||
)
|
||||
|
||||
func (p *nodePlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
p.podsGetter = f.Core().InternalVersion().Pods().Lister()
|
||||
func (p *nodePlugin) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
p.podsGetter = f.Core().V1().Pods().Lister()
|
||||
}
|
||||
|
||||
func (p *nodePlugin) ValidateInitialization() error {
|
||||
@ -86,10 +93,12 @@ func (p *nodePlugin) ValidateInitialization() error {
|
||||
}
|
||||
|
||||
var (
|
||||
podResource = api.Resource("pods")
|
||||
nodeResource = api.Resource("nodes")
|
||||
pvcResource = api.Resource("persistentvolumeclaims")
|
||||
svcacctResource = api.Resource("serviceaccounts")
|
||||
podResource = api.Resource("pods")
|
||||
nodeResource = api.Resource("nodes")
|
||||
pvcResource = api.Resource("persistentvolumeclaims")
|
||||
svcacctResource = api.Resource("serviceaccounts")
|
||||
leaseResource = coordapi.Resource("leases")
|
||||
csiNodeInfoResource = csiv1alpha1.Resource("csinodeinfos")
|
||||
)
|
||||
|
||||
func (c *nodePlugin) Admit(a admission.Attributes) error {
|
||||
@ -135,6 +144,18 @@ func (c *nodePlugin) Admit(a admission.Attributes) error {
|
||||
}
|
||||
return nil
|
||||
|
||||
case leaseResource:
|
||||
if c.features.Enabled(features.NodeLease) {
|
||||
return c.admitLease(nodeName, a)
|
||||
}
|
||||
return admission.NewForbidden(a, fmt.Errorf("disabled by feature gate %s", features.NodeLease))
|
||||
|
||||
case csiNodeInfoResource:
|
||||
if c.features.Enabled(features.KubeletPluginsWatcher) && c.features.Enabled(features.CSINodeInfo) {
|
||||
return c.admitCSINodeInfo(nodeName, a)
|
||||
}
|
||||
return admission.NewForbidden(a, fmt.Errorf("disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo))
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@ -313,6 +334,18 @@ func (c *nodePlugin) admitNode(nodeName string, a admission.Attributes) error {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot create with non-nil configSource"))
|
||||
}
|
||||
|
||||
// Don't allow a node to register with labels outside the allowed set.
|
||||
// This would allow a node to add or modify its labels in a way that would let it steer privileged workloads to itself.
|
||||
modifiedLabels := getModifiedLabels(node.Labels, nil)
|
||||
if forbiddenLabels := c.getForbiddenCreateLabels(modifiedLabels); len(forbiddenLabels) > 0 {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot set labels: %s", strings.Join(forbiddenLabels.List(), ", ")))
|
||||
}
|
||||
// check and warn if nodes set labels on create that would have been forbidden on update
|
||||
// TODO(liggitt): in 1.17, expand getForbiddenCreateLabels to match getForbiddenUpdateLabels and drop this
|
||||
if forbiddenUpdateLabels := c.getForbiddenUpdateLabels(modifiedLabels); len(forbiddenUpdateLabels) > 0 {
|
||||
klog.Warningf("node %q added disallowed labels on node creation: %s", nodeName, strings.Join(forbiddenUpdateLabels.List(), ", "))
|
||||
}
|
||||
|
||||
// On create, get name from new object if unset in admission
|
||||
if len(requestedName) == 0 {
|
||||
requestedName = node.Name
|
||||
@ -336,19 +369,100 @@ func (c *nodePlugin) admitNode(nodeName string, a admission.Attributes) error {
|
||||
// We scope node access to things listed in the Node.Spec, so allowing this would allow a view escalation.
|
||||
// We only do the check if the new node's configSource is non-nil; old kubelets might drop the field during a status update.
|
||||
if node.Spec.ConfigSource != nil && !apiequality.Semantic.DeepEqual(node.Spec.ConfigSource, oldNode.Spec.ConfigSource) {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot update configSource to a new non-nil configSource"))
|
||||
return admission.NewForbidden(a, fmt.Errorf("node %q cannot update configSource to a new non-nil configSource", nodeName))
|
||||
}
|
||||
|
||||
// Don't allow a node to update its own taints. This would allow a node to remove or modify its
|
||||
// taints in a way that would let it steer disallowed workloads to itself.
|
||||
if !apiequality.Semantic.DeepEqual(node.Spec.Taints, oldNode.Spec.Taints) {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot modify taints"))
|
||||
return admission.NewForbidden(a, fmt.Errorf("node %q cannot modify taints", nodeName))
|
||||
}
|
||||
|
||||
// Don't allow a node to update labels outside the allowed set.
|
||||
// This would allow a node to add or modify its labels in a way that would let it steer privileged workloads to itself.
|
||||
modifiedLabels := getModifiedLabels(node.Labels, oldNode.Labels)
|
||||
if forbiddenUpdateLabels := c.getForbiddenUpdateLabels(modifiedLabels); len(forbiddenUpdateLabels) > 0 {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot modify labels: %s", strings.Join(forbiddenUpdateLabels.List(), ", ")))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getModifiedLabels returns the set of label keys that are different between the two maps
|
||||
func getModifiedLabels(a, b map[string]string) sets.String {
|
||||
modified := sets.NewString()
|
||||
for k, v1 := range a {
|
||||
if v2, ok := b[k]; !ok || v1 != v2 {
|
||||
modified.Insert(k)
|
||||
}
|
||||
}
|
||||
for k, v1 := range b {
|
||||
if v2, ok := a[k]; !ok || v1 != v2 {
|
||||
modified.Insert(k)
|
||||
}
|
||||
}
|
||||
return modified
|
||||
}
|
||||
|
||||
func isKubernetesLabel(key string) bool {
|
||||
namespace := getLabelNamespace(key)
|
||||
if namespace == "kubernetes.io" || strings.HasSuffix(namespace, ".kubernetes.io") {
|
||||
return true
|
||||
}
|
||||
if namespace == "k8s.io" || strings.HasSuffix(namespace, ".k8s.io") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func getLabelNamespace(key string) string {
|
||||
if parts := strings.SplitN(key, "/", 2); len(parts) == 2 {
|
||||
return parts[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// getForbiddenCreateLabels returns the set of labels that may not be set by the node.
|
||||
// TODO(liggitt): in 1.17, expand to match getForbiddenUpdateLabels()
|
||||
func (c *nodePlugin) getForbiddenCreateLabels(modifiedLabels sets.String) sets.String {
|
||||
if len(modifiedLabels) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
forbiddenLabels := sets.NewString()
|
||||
for label := range modifiedLabels {
|
||||
namespace := getLabelNamespace(label)
|
||||
// forbid kubelets from setting node-restriction labels
|
||||
if namespace == kubeletapis.LabelNamespaceNodeRestriction || strings.HasSuffix(namespace, "."+kubeletapis.LabelNamespaceNodeRestriction) {
|
||||
forbiddenLabels.Insert(label)
|
||||
}
|
||||
}
|
||||
return forbiddenLabels
|
||||
}
|
||||
|
||||
// getForbiddenLabels returns the set of labels that may not be set by the node on update.
|
||||
func (c *nodePlugin) getForbiddenUpdateLabels(modifiedLabels sets.String) sets.String {
|
||||
if len(modifiedLabels) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
forbiddenLabels := sets.NewString()
|
||||
for label := range modifiedLabels {
|
||||
namespace := getLabelNamespace(label)
|
||||
// forbid kubelets from setting node-restriction labels
|
||||
if namespace == kubeletapis.LabelNamespaceNodeRestriction || strings.HasSuffix(namespace, "."+kubeletapis.LabelNamespaceNodeRestriction) {
|
||||
forbiddenLabels.Insert(label)
|
||||
}
|
||||
// forbid kubelets from setting unknown kubernetes.io and k8s.io labels on update
|
||||
if isKubernetesLabel(label) && !kubeletapis.IsKubeletLabel(label) {
|
||||
// TODO: defer to label policy once available
|
||||
forbiddenLabels.Insert(label)
|
||||
}
|
||||
}
|
||||
return forbiddenLabels
|
||||
}
|
||||
|
||||
func (c *nodePlugin) admitServiceAccount(nodeName string, a admission.Attributes) error {
|
||||
if a.GetOperation() != admission.Create {
|
||||
return nil
|
||||
@ -389,3 +503,48 @@ func (c *nodePlugin) admitServiceAccount(nodeName string, a admission.Attributes
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *nodePlugin) admitLease(nodeName string, a admission.Attributes) error {
|
||||
// the request must be against the system namespace reserved for node leases
|
||||
if a.GetNamespace() != api.NamespaceNodeLease {
|
||||
return admission.NewForbidden(a, fmt.Errorf("can only access leases in the %q system namespace", api.NamespaceNodeLease))
|
||||
}
|
||||
|
||||
// the request must come from a node with the same name as the lease
|
||||
if a.GetOperation() == admission.Create {
|
||||
// a.GetName() won't return the name on create, so we drill down to the proposed object
|
||||
lease, ok := a.GetObject().(*coordapi.Lease)
|
||||
if !ok {
|
||||
return admission.NewForbidden(a, fmt.Errorf("unexpected type %T", a.GetObject()))
|
||||
}
|
||||
if lease.Name != nodeName {
|
||||
return admission.NewForbidden(a, fmt.Errorf("can only access node lease with the same name as the requesting node"))
|
||||
}
|
||||
} else {
|
||||
if a.GetName() != nodeName {
|
||||
return admission.NewForbidden(a, fmt.Errorf("can only access node lease with the same name as the requesting node"))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *nodePlugin) admitCSINodeInfo(nodeName string, a admission.Attributes) error {
|
||||
// the request must come from a node with the same name as the CSINodeInfo object
|
||||
if a.GetOperation() == admission.Create {
|
||||
// a.GetName() won't return the name on create, so we drill down to the proposed object
|
||||
accessor, err := meta.Accessor(a.GetObject())
|
||||
if err != nil {
|
||||
return admission.NewForbidden(a, fmt.Errorf("unable to access the object name"))
|
||||
}
|
||||
if accessor.GetName() != nodeName {
|
||||
return admission.NewForbidden(a, fmt.Errorf("can only access CSINodeInfo with the same name as the requesting node"))
|
||||
}
|
||||
} else {
|
||||
if a.GetName() != nodeName {
|
||||
return admission.NewForbidden(a, fmt.Errorf("can only access CSINodeInfo with the same name as the requesting node"))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
738
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission_test.go
generated
vendored
738
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission_test.go
generated
vendored
File diff suppressed because it is too large
Load Diff
36
vendor/k8s.io/kubernetes/plugin/pkg/admission/podnodeselector/BUILD
generated
vendored
36
vendor/k8s.io/kubernetes/plugin/pkg/admission/podnodeselector/BUILD
generated
vendored
@ -12,17 +12,18 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/podnodeselector",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/core/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//pkg/kubeapiserver/admission/util:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -32,13 +33,14 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
33
vendor/k8s.io/kubernetes/plugin/pkg/admission/podnodeselector/admission.go
generated
vendored
33
vendor/k8s.io/kubernetes/plugin/pkg/admission/podnodeselector/admission.go
generated
vendored
@ -21,18 +21,19 @@ import (
|
||||
"io"
|
||||
"reflect"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util"
|
||||
)
|
||||
|
||||
@ -55,16 +56,14 @@ func Register(plugins *admission.Plugins) {
|
||||
// podNodeSelector is an implementation of admission.Interface.
|
||||
type podNodeSelector struct {
|
||||
*admission.Handler
|
||||
client internalclientset.Interface
|
||||
namespaceLister corelisters.NamespaceLister
|
||||
client kubernetes.Interface
|
||||
namespaceLister corev1listers.NamespaceLister
|
||||
// global default node selector and namespace whitelists in a cluster.
|
||||
clusterNodeSelectors map[string]string
|
||||
}
|
||||
|
||||
var _ admission.MutationInterface = &podNodeSelector{}
|
||||
var _ admission.ValidationInterface = &podNodeSelector{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&podNodeSelector{})
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&podNodeSelector{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeClientSet(&podNodeSelector{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&podNodeSelector{})
|
||||
|
||||
type pluginConfig struct {
|
||||
PodNodeSelectorPluginConfig map[string]string
|
||||
@ -191,7 +190,7 @@ func shouldIgnore(a admission.Attributes) bool {
|
||||
|
||||
_, ok := a.GetObject().(*api.Pod)
|
||||
if !ok {
|
||||
glog.Errorf("expected pod but got %s", a.GetKind().Kind)
|
||||
klog.Errorf("expected pod but got %s", a.GetKind().Kind)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -205,12 +204,12 @@ func NewPodNodeSelector(clusterNodeSelectors map[string]string) *podNodeSelector
|
||||
}
|
||||
}
|
||||
|
||||
func (a *podNodeSelector) SetInternalKubeClientSet(client internalclientset.Interface) {
|
||||
func (a *podNodeSelector) SetExternalKubeClientSet(client kubernetes.Interface) {
|
||||
a.client = client
|
||||
}
|
||||
|
||||
func (p *podNodeSelector) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
namespaceInformer := f.Core().InternalVersion().Namespaces()
|
||||
func (p *podNodeSelector) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
namespaceInformer := f.Core().V1().Namespaces()
|
||||
p.namespaceLister = namespaceInformer.Lister()
|
||||
p.SetReadyFunc(namespaceInformer.Informer().HasSynced)
|
||||
}
|
||||
@ -225,7 +224,7 @@ func (p *podNodeSelector) ValidateInitialization() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *podNodeSelector) defaultGetNamespace(name string) (*api.Namespace, error) {
|
||||
func (p *podNodeSelector) defaultGetNamespace(name string) (*corev1.Namespace, error) {
|
||||
namespace, err := p.client.Core().Namespaces().Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("namespace %s does not exist", name)
|
||||
@ -233,7 +232,7 @@ func (p *podNodeSelector) defaultGetNamespace(name string) (*api.Namespace, erro
|
||||
return namespace, nil
|
||||
}
|
||||
|
||||
func (p *podNodeSelector) getNodeSelectorMap(namespace *api.Namespace) (labels.Set, error) {
|
||||
func (p *podNodeSelector) getNodeSelectorMap(namespace *corev1.Namespace) (labels.Set, error) {
|
||||
selector := labels.Set{}
|
||||
labelsMap := labels.Set{}
|
||||
var err error
|
||||
|
57
vendor/k8s.io/kubernetes/plugin/pkg/admission/podnodeselector/admission_test.go
generated
vendored
57
vendor/k8s.io/kubernetes/plugin/pkg/admission/podnodeselector/admission_test.go
generated
vendored
@ -20,26 +20,27 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
)
|
||||
|
||||
// TestPodAdmission verifies various scenarios involving pod/namespace/global node label selectors
|
||||
func TestPodAdmission(t *testing.T) {
|
||||
namespace := &api.Namespace{
|
||||
namespace := &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "testNamespace",
|
||||
Namespace: "",
|
||||
},
|
||||
}
|
||||
|
||||
mockClient := &fake.Clientset{}
|
||||
mockClient := fake.NewSimpleClientset(namespace)
|
||||
handler, informerFactory, err := newHandlerForTest(mockClient)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error initializing handler: %v", err)
|
||||
@ -73,16 +74,16 @@ func TestPodAdmission(t *testing.T) {
|
||||
podNodeSelector: map[string]string{},
|
||||
mergedNodeSelector: labels.Set{},
|
||||
ignoreTestNamespaceNodeSelector: true,
|
||||
admit: true,
|
||||
testName: "No node selectors",
|
||||
admit: true,
|
||||
testName: "No node selectors",
|
||||
},
|
||||
{
|
||||
defaultNodeSelector: "infra = false",
|
||||
podNodeSelector: map[string]string{},
|
||||
mergedNodeSelector: labels.Set{"infra": "false"},
|
||||
ignoreTestNamespaceNodeSelector: true,
|
||||
admit: true,
|
||||
testName: "Default node selector and no conflicts",
|
||||
admit: true,
|
||||
testName: "Default node selector and no conflicts",
|
||||
},
|
||||
{
|
||||
defaultNodeSelector: "",
|
||||
@ -159,14 +160,14 @@ func TestPodAdmission(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
if !test.ignoreTestNamespaceNodeSelector {
|
||||
namespace.ObjectMeta.Annotations = map[string]string{"scheduler.alpha.kubernetes.io/node-selector": test.namespaceNodeSelector}
|
||||
informerFactory.Core().InternalVersion().Namespaces().Informer().GetStore().Update(namespace)
|
||||
informerFactory.Core().V1().Namespaces().Informer().GetStore().Update(namespace)
|
||||
}
|
||||
handler.clusterNodeSelectors = make(map[string]string)
|
||||
handler.clusterNodeSelectors["clusterDefaultNodeSelector"] = test.defaultNodeSelector
|
||||
handler.clusterNodeSelectors[namespace.Name] = test.whitelist
|
||||
pod.Spec = api.PodSpec{NodeSelector: test.podNodeSelector}
|
||||
|
||||
err := handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||
err := handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if test.admit && err != nil {
|
||||
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
|
||||
} else if !test.admit && err == nil {
|
||||
@ -175,7 +176,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
if test.admit && !labels.Equals(test.mergedNodeSelector, labels.Set(pod.Spec.NodeSelector)) {
|
||||
t.Errorf("Test: %s, expected: %s but got: %s", test.testName, test.mergedNodeSelector, pod.Spec.NodeSelector)
|
||||
}
|
||||
err = handler.Validate(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||
err = handler.Validate(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if test.admit && err != nil {
|
||||
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
|
||||
} else if !test.admit && err == nil {
|
||||
@ -183,7 +184,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
}
|
||||
|
||||
// handles update of uninitialized pod like it's newly created.
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, nil))
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if test.admit && err != nil {
|
||||
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
|
||||
} else if !test.admit && err == nil {
|
||||
@ -192,7 +193,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
if test.admit && !labels.Equals(test.mergedNodeSelector, labels.Set(pod.Spec.NodeSelector)) {
|
||||
t.Errorf("Test: %s, expected: %s but got: %s", test.testName, test.mergedNodeSelector, pod.Spec.NodeSelector)
|
||||
}
|
||||
err = handler.Validate(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, nil))
|
||||
err = handler.Validate(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if test.admit && err != nil {
|
||||
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
|
||||
} else if !test.admit && err == nil {
|
||||
@ -216,7 +217,15 @@ func TestHandles(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIgnoreUpdatingInitializedPod(t *testing.T) {
|
||||
mockClient := &fake.Clientset{}
|
||||
namespaceNodeSelector := "infra=true"
|
||||
namespace := &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "testNamespace",
|
||||
Namespace: "",
|
||||
Annotations: map[string]string{"scheduler.alpha.kubernetes.io/node-selector": namespaceNodeSelector},
|
||||
},
|
||||
}
|
||||
mockClient := fake.NewSimpleClientset(namespace)
|
||||
handler, informerFactory, err := newHandlerForTest(mockClient)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error initializing handler: %v", err)
|
||||
@ -229,31 +238,23 @@ func TestIgnoreUpdatingInitializedPod(t *testing.T) {
|
||||
Spec: api.PodSpec{NodeSelector: podNodeSelector},
|
||||
}
|
||||
// this conflicts with podNodeSelector
|
||||
namespaceNodeSelector := "infra=true"
|
||||
namespace := &api.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "testNamespace",
|
||||
Namespace: "",
|
||||
Annotations: map[string]string{"scheduler.alpha.kubernetes.io/node-selector": namespaceNodeSelector},
|
||||
},
|
||||
}
|
||||
err = informerFactory.Core().InternalVersion().Namespaces().Informer().GetStore().Update(namespace)
|
||||
err = informerFactory.Core().V1().Namespaces().Informer().GetStore().Update(namespace)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// if the update of initialized pod is not ignored, an error will be returned because the pod's nodeSelector conflicts with namespace's nodeSelector.
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, pod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, nil))
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, pod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// newHandlerForTest returns the admission controller configured for testing.
|
||||
func newHandlerForTest(c clientset.Interface) (*podNodeSelector, informers.SharedInformerFactory, error) {
|
||||
func newHandlerForTest(c kubernetes.Interface) (*podNodeSelector, informers.SharedInformerFactory, error) {
|
||||
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
||||
handler := NewPodNodeSelector(nil)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
|
||||
pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil)
|
||||
pluginInitializer.Initialize(handler)
|
||||
err := admission.ValidateInitialization(handler)
|
||||
return handler, f, err
|
||||
|
42
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/BUILD
generated
vendored
42
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/BUILD
generated
vendored
@ -12,15 +12,16 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/settings:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/settings/internalversion:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/api/settings/v1alpha1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/settings/v1alpha1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -29,20 +30,19 @@ go_library(
|
||||
srcs = ["admission.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/podpreset",
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/api/ref:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/settings:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/settings/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//pkg/apis/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/api/settings/v1alpha1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/settings/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
123
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/admission.go
generated
vendored
123
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/admission.go
generated
vendored
@ -22,21 +22,20 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
|
||||
settingsv1alpha1 "k8s.io/api/settings/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/api/ref"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
settingsv1alpha1listers "k8s.io/client-go/listers/settings/v1alpha1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/settings"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
settingslisters "k8s.io/kubernetes/pkg/client/listers/settings/internalversion"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
apiscorev1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -54,14 +53,14 @@ func Register(plugins *admission.Plugins) {
|
||||
// podPresetPlugin is an implementation of admission.Interface.
|
||||
type podPresetPlugin struct {
|
||||
*admission.Handler
|
||||
client internalclientset.Interface
|
||||
client kubernetes.Interface
|
||||
|
||||
lister settingslisters.PodPresetLister
|
||||
lister settingsv1alpha1listers.PodPresetLister
|
||||
}
|
||||
|
||||
var _ admission.MutationInterface = &podPresetPlugin{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&podPresetPlugin{})
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&podPresetPlugin{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&podPresetPlugin{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeClientSet(&podPresetPlugin{})
|
||||
|
||||
// NewPlugin creates a new pod preset admission plugin.
|
||||
func NewPlugin() *podPresetPlugin {
|
||||
@ -80,12 +79,12 @@ func (plugin *podPresetPlugin) ValidateInitialization() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *podPresetPlugin) SetInternalKubeClientSet(client internalclientset.Interface) {
|
||||
func (a *podPresetPlugin) SetExternalKubeClientSet(client kubernetes.Interface) {
|
||||
a.client = client
|
||||
}
|
||||
|
||||
func (a *podPresetPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
podPresetInformer := f.Settings().InternalVersion().PodPresets()
|
||||
func (a *podPresetPlugin) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
podPresetInformer := f.Settings().V1alpha1().PodPresets()
|
||||
a.lister = podPresetInformer.Lister()
|
||||
a.SetReadyFunc(podPresetInformer.Informer().HasSynced)
|
||||
}
|
||||
@ -109,7 +108,7 @@ func (c *podPresetPlugin) Admit(a admission.Attributes) error {
|
||||
|
||||
// Ignore if exclusion annotation is present
|
||||
if podAnnotations := pod.GetAnnotations(); podAnnotations != nil {
|
||||
glog.V(5).Infof("Looking at pod annotations, found: %v", podAnnotations)
|
||||
klog.V(5).Infof("Looking at pod annotations, found: %v", podAnnotations)
|
||||
if podAnnotations[api.PodPresetOptOutAnnotationKey] == "true" {
|
||||
return nil
|
||||
}
|
||||
@ -138,21 +137,21 @@ func (c *podPresetPlugin) Admit(a admission.Attributes) error {
|
||||
err = safeToApplyPodPresetsOnPod(pod, matchingPPs)
|
||||
if err != nil {
|
||||
// conflict, ignore the error, but raise an event
|
||||
glog.Warningf("conflict occurred while applying podpresets: %s on pod: %v err: %v",
|
||||
klog.Warningf("conflict occurred while applying podpresets: %s on pod: %v err: %v",
|
||||
strings.Join(presetNames, ","), pod.GetGenerateName(), err)
|
||||
return nil
|
||||
}
|
||||
|
||||
applyPodPresetsOnPod(pod, matchingPPs)
|
||||
|
||||
glog.Infof("applied podpresets: %s successfully on Pod: %+v ", strings.Join(presetNames, ","), pod.GetGenerateName())
|
||||
klog.Infof("applied podpresets: %s successfully on Pod: %+v ", strings.Join(presetNames, ","), pod.GetGenerateName())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// filterPodPresets returns list of PodPresets which match given Pod.
|
||||
func filterPodPresets(list []*settings.PodPreset, pod *api.Pod) ([]*settings.PodPreset, error) {
|
||||
var matchingPPs []*settings.PodPreset
|
||||
func filterPodPresets(list []*settingsv1alpha1.PodPreset, pod *api.Pod) ([]*settingsv1alpha1.PodPreset, error) {
|
||||
var matchingPPs []*settingsv1alpha1.PodPreset
|
||||
|
||||
for _, pp := range list {
|
||||
selector, err := metav1.LabelSelectorAsSelector(&pp.Spec.Selector)
|
||||
@ -164,7 +163,7 @@ func filterPodPresets(list []*settings.PodPreset, pod *api.Pod) ([]*settings.Pod
|
||||
if !selector.Matches(labels.Set(pod.Labels)) {
|
||||
continue
|
||||
}
|
||||
glog.V(4).Infof("PodPreset %s matches pod %s labels", pp.GetName(), pod.GetName())
|
||||
klog.V(4).Infof("PodPreset %s matches pod %s labels", pp.GetName(), pod.GetName())
|
||||
matchingPPs = append(matchingPPs, pp)
|
||||
}
|
||||
return matchingPPs, nil
|
||||
@ -172,7 +171,7 @@ func filterPodPresets(list []*settings.PodPreset, pod *api.Pod) ([]*settings.Pod
|
||||
|
||||
// safeToApplyPodPresetsOnPod determines if there is any conflict in information
|
||||
// injected by given PodPresets in the Pod.
|
||||
func safeToApplyPodPresetsOnPod(pod *api.Pod, podPresets []*settings.PodPreset) error {
|
||||
func safeToApplyPodPresetsOnPod(pod *api.Pod, podPresets []*settingsv1alpha1.PodPreset) error {
|
||||
var errs []error
|
||||
|
||||
// volumes attribute is defined at the Pod level, so determine if volumes
|
||||
@ -190,7 +189,7 @@ func safeToApplyPodPresetsOnPod(pod *api.Pod, podPresets []*settings.PodPreset)
|
||||
|
||||
// safeToApplyPodPresetsOnContainer determines if there is any conflict in
|
||||
// information injected by given PodPresets in the given container.
|
||||
func safeToApplyPodPresetsOnContainer(ctr *api.Container, podPresets []*settings.PodPreset) error {
|
||||
func safeToApplyPodPresetsOnContainer(ctr *api.Container, podPresets []*settingsv1alpha1.PodPreset) error {
|
||||
var errs []error
|
||||
// check if it is safe to merge env vars and volume mounts from given podpresets and
|
||||
// container's existing env vars.
|
||||
@ -206,7 +205,7 @@ func safeToApplyPodPresetsOnContainer(ctr *api.Container, podPresets []*settings
|
||||
|
||||
// mergeEnv merges a list of env vars with the env vars injected by given list podPresets.
|
||||
// It returns an error if it detects any conflict during the merge.
|
||||
func mergeEnv(envVars []api.EnvVar, podPresets []*settings.PodPreset) ([]api.EnvVar, error) {
|
||||
func mergeEnv(envVars []api.EnvVar, podPresets []*settingsv1alpha1.PodPreset) ([]api.EnvVar, error) {
|
||||
origEnv := map[string]api.EnvVar{}
|
||||
for _, v := range envVars {
|
||||
origEnv[v.Name] = v
|
||||
@ -219,16 +218,21 @@ func mergeEnv(envVars []api.EnvVar, podPresets []*settings.PodPreset) ([]api.Env
|
||||
|
||||
for _, pp := range podPresets {
|
||||
for _, v := range pp.Spec.Env {
|
||||
internalEnv := api.EnvVar{}
|
||||
if err := apiscorev1.Convert_v1_EnvVar_To_core_EnvVar(&v, &internalEnv, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
found, ok := origEnv[v.Name]
|
||||
if !ok {
|
||||
// if we don't already have it append it and continue
|
||||
origEnv[v.Name] = v
|
||||
mergedEnv = append(mergedEnv, v)
|
||||
origEnv[v.Name] = internalEnv
|
||||
mergedEnv = append(mergedEnv, internalEnv)
|
||||
continue
|
||||
}
|
||||
|
||||
// make sure they are identical or throw an error
|
||||
if !reflect.DeepEqual(found, v) {
|
||||
if !reflect.DeepEqual(found, internalEnv) {
|
||||
errs = append(errs, fmt.Errorf("merging env for %s has a conflict on %s: \n%#v\ndoes not match\n%#v\n in container", pp.GetName(), v.Name, v, found))
|
||||
}
|
||||
}
|
||||
@ -242,12 +246,19 @@ func mergeEnv(envVars []api.EnvVar, podPresets []*settings.PodPreset) ([]api.Env
|
||||
return mergedEnv, err
|
||||
}
|
||||
|
||||
func mergeEnvFrom(envSources []api.EnvFromSource, podPresets []*settings.PodPreset) ([]api.EnvFromSource, error) {
|
||||
func mergeEnvFrom(envSources []api.EnvFromSource, podPresets []*settingsv1alpha1.PodPreset) ([]api.EnvFromSource, error) {
|
||||
var mergedEnvFrom []api.EnvFromSource
|
||||
|
||||
mergedEnvFrom = append(mergedEnvFrom, envSources...)
|
||||
for _, pp := range podPresets {
|
||||
mergedEnvFrom = append(mergedEnvFrom, pp.Spec.EnvFrom...)
|
||||
for _, envFromSource := range pp.Spec.EnvFrom {
|
||||
internalEnvFrom := api.EnvFromSource{}
|
||||
if err := apiscorev1.Convert_v1_EnvFromSource_To_core_EnvFromSource(&envFromSource, &internalEnvFrom, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mergedEnvFrom = append(mergedEnvFrom, internalEnvFrom)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return mergedEnvFrom, nil
|
||||
@ -255,7 +266,7 @@ func mergeEnvFrom(envSources []api.EnvFromSource, podPresets []*settings.PodPres
|
||||
|
||||
// mergeVolumeMounts merges given list of VolumeMounts with the volumeMounts
|
||||
// injected by given podPresets. It returns an error if it detects any conflict during the merge.
|
||||
func mergeVolumeMounts(volumeMounts []api.VolumeMount, podPresets []*settings.PodPreset) ([]api.VolumeMount, error) {
|
||||
func mergeVolumeMounts(volumeMounts []api.VolumeMount, podPresets []*settingsv1alpha1.PodPreset) ([]api.VolumeMount, error) {
|
||||
|
||||
origVolumeMounts := map[string]api.VolumeMount{}
|
||||
volumeMountsByPath := map[string]api.VolumeMount{}
|
||||
@ -271,15 +282,19 @@ func mergeVolumeMounts(volumeMounts []api.VolumeMount, podPresets []*settings.Po
|
||||
|
||||
for _, pp := range podPresets {
|
||||
for _, v := range pp.Spec.VolumeMounts {
|
||||
internalVolumeMount := api.VolumeMount{}
|
||||
if err := apiscorev1.Convert_v1_VolumeMount_To_core_VolumeMount(&v, &internalVolumeMount, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
found, ok := origVolumeMounts[v.Name]
|
||||
if !ok {
|
||||
// if we don't already have it append it and continue
|
||||
origVolumeMounts[v.Name] = v
|
||||
mergedVolumeMounts = append(mergedVolumeMounts, v)
|
||||
origVolumeMounts[v.Name] = internalVolumeMount
|
||||
mergedVolumeMounts = append(mergedVolumeMounts, internalVolumeMount)
|
||||
} else {
|
||||
// make sure they are identical or throw an error
|
||||
// shall we throw an error for identical volumeMounts ?
|
||||
if !reflect.DeepEqual(found, v) {
|
||||
if !reflect.DeepEqual(found, internalVolumeMount) {
|
||||
errs = append(errs, fmt.Errorf("merging volume mounts for %s has a conflict on %s: \n%#v\ndoes not match\n%#v\n in container", pp.GetName(), v.Name, v, found))
|
||||
}
|
||||
}
|
||||
@ -287,10 +302,10 @@ func mergeVolumeMounts(volumeMounts []api.VolumeMount, podPresets []*settings.Po
|
||||
found, ok = volumeMountsByPath[v.MountPath]
|
||||
if !ok {
|
||||
// if we don't already have it append it and continue
|
||||
volumeMountsByPath[v.MountPath] = v
|
||||
volumeMountsByPath[v.MountPath] = internalVolumeMount
|
||||
} else {
|
||||
// make sure they are identical or throw an error
|
||||
if !reflect.DeepEqual(found, v) {
|
||||
if !reflect.DeepEqual(found, internalVolumeMount) {
|
||||
errs = append(errs, fmt.Errorf("merging volume mounts for %s has a conflict on mount path %s: \n%#v\ndoes not match\n%#v\n in container", pp.GetName(), v.MountPath, v, found))
|
||||
}
|
||||
}
|
||||
@ -307,7 +322,7 @@ func mergeVolumeMounts(volumeMounts []api.VolumeMount, podPresets []*settings.Po
|
||||
|
||||
// mergeVolumes merges given list of Volumes with the volumes injected by given
|
||||
// podPresets. It returns an error if it detects any conflict during the merge.
|
||||
func mergeVolumes(volumes []api.Volume, podPresets []*settings.PodPreset) ([]api.Volume, error) {
|
||||
func mergeVolumes(volumes []api.Volume, podPresets []*settingsv1alpha1.PodPreset) ([]api.Volume, error) {
|
||||
origVolumes := map[string]api.Volume{}
|
||||
for _, v := range volumes {
|
||||
origVolumes[v.Name] = v
|
||||
@ -320,16 +335,20 @@ func mergeVolumes(volumes []api.Volume, podPresets []*settings.PodPreset) ([]api
|
||||
|
||||
for _, pp := range podPresets {
|
||||
for _, v := range pp.Spec.Volumes {
|
||||
internalVolume := api.Volume{}
|
||||
if err := apiscorev1.Convert_v1_Volume_To_core_Volume(&v, &internalVolume, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
found, ok := origVolumes[v.Name]
|
||||
if !ok {
|
||||
// if we don't already have it append it and continue
|
||||
origVolumes[v.Name] = v
|
||||
mergedVolumes = append(mergedVolumes, v)
|
||||
origVolumes[v.Name] = internalVolume
|
||||
mergedVolumes = append(mergedVolumes, internalVolume)
|
||||
continue
|
||||
}
|
||||
|
||||
// make sure they are identical or throw an error
|
||||
if !reflect.DeepEqual(found, v) {
|
||||
if !reflect.DeepEqual(found, internalVolume) {
|
||||
errs = append(errs, fmt.Errorf("merging volumes for %s has a conflict on %s: \n%#v\ndoes not match\n%#v\n in container", pp.GetName(), v.Name, v, found))
|
||||
}
|
||||
}
|
||||
@ -347,32 +366,10 @@ func mergeVolumes(volumes []api.Volume, podPresets []*settings.PodPreset) ([]api
|
||||
return mergedVolumes, err
|
||||
}
|
||||
|
||||
func (c *podPresetPlugin) addEvent(pod *api.Pod, pip *settings.PodPreset, message string) {
|
||||
ref, err := ref.GetReference(legacyscheme.Scheme, pod)
|
||||
if err != nil {
|
||||
glog.Errorf("pip %s: get reference for pod %s failed: %v", pip.GetName(), pod.GetName(), err)
|
||||
return
|
||||
}
|
||||
|
||||
e := &api.Event{
|
||||
InvolvedObject: *ref,
|
||||
Message: message,
|
||||
Source: api.EventSource{
|
||||
Component: fmt.Sprintf("pip %s", pip.GetName()),
|
||||
},
|
||||
Type: "Warning",
|
||||
}
|
||||
|
||||
if _, err := c.client.Core().Events(pod.GetNamespace()).Create(e); err != nil {
|
||||
glog.Errorf("pip %s: creating pod event failed: %v", pip.GetName(), err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// applyPodPresetsOnPod updates the PodSpec with merged information from all the
|
||||
// applicable PodPresets. It ignores the errors of merge functions because merge
|
||||
// errors have already been checked in safeToApplyPodPresetsOnPod function.
|
||||
func applyPodPresetsOnPod(pod *api.Pod, podPresets []*settings.PodPreset) {
|
||||
func applyPodPresetsOnPod(pod *api.Pod, podPresets []*settingsv1alpha1.PodPreset) {
|
||||
if len(podPresets) == 0 {
|
||||
return
|
||||
}
|
||||
@ -398,7 +395,7 @@ func applyPodPresetsOnPod(pod *api.Pod, podPresets []*settings.PodPreset) {
|
||||
// applyPodPresetsOnContainer injects envVars, VolumeMounts and envFrom from
|
||||
// given podPresets in to the given container. It ignores conflict errors
|
||||
// because it assumes those have been checked already by the caller.
|
||||
func applyPodPresetsOnContainer(ctr *api.Container, podPresets []*settings.PodPreset) {
|
||||
func applyPodPresetsOnContainer(ctr *api.Container, podPresets []*settingsv1alpha1.PodPreset) {
|
||||
envVars, _ := mergeEnv(ctr.Env, podPresets)
|
||||
ctr.Env = envVars
|
||||
|
||||
|
186
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/admission_test.go
generated
vendored
186
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/admission_test.go
generated
vendored
@ -20,44 +20,45 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
settingsv1alpha1 "k8s.io/api/settings/v1alpha1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
kadmission "k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
settingsv1alpha1listers "k8s.io/client-go/listers/settings/v1alpha1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/settings"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
settingslisters "k8s.io/kubernetes/pkg/client/listers/settings/internalversion"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
)
|
||||
|
||||
func TestMergeEnv(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
orig []api.EnvVar
|
||||
mod []api.EnvVar
|
||||
mod []corev1.EnvVar
|
||||
result []api.EnvVar
|
||||
shouldFail bool
|
||||
}{
|
||||
"empty original": {
|
||||
mod: []api.EnvVar{{Name: "abc", Value: "value2"}, {Name: "ABC", Value: "value3"}},
|
||||
mod: []corev1.EnvVar{{Name: "abc", Value: "value2"}, {Name: "ABC", Value: "value3"}},
|
||||
result: []api.EnvVar{{Name: "abc", Value: "value2"}, {Name: "ABC", Value: "value3"}},
|
||||
shouldFail: false,
|
||||
},
|
||||
"good merge": {
|
||||
orig: []api.EnvVar{{Name: "abcd", Value: "value2"}, {Name: "hello", Value: "value3"}},
|
||||
mod: []api.EnvVar{{Name: "abc", Value: "value2"}, {Name: "ABC", Value: "value3"}},
|
||||
mod: []corev1.EnvVar{{Name: "abc", Value: "value2"}, {Name: "ABC", Value: "value3"}},
|
||||
result: []api.EnvVar{{Name: "abcd", Value: "value2"}, {Name: "hello", Value: "value3"}, {Name: "abc", Value: "value2"}, {Name: "ABC", Value: "value3"}},
|
||||
shouldFail: false,
|
||||
},
|
||||
"conflict": {
|
||||
orig: []api.EnvVar{{Name: "abc", Value: "value3"}},
|
||||
mod: []api.EnvVar{{Name: "abc", Value: "value2"}, {Name: "ABC", Value: "value3"}},
|
||||
mod: []corev1.EnvVar{{Name: "abc", Value: "value2"}, {Name: "ABC", Value: "value3"}},
|
||||
shouldFail: true,
|
||||
},
|
||||
"one is exact same": {
|
||||
orig: []api.EnvVar{{Name: "abc", Value: "value2"}, {Name: "hello", Value: "value3"}},
|
||||
mod: []api.EnvVar{{Name: "abc", Value: "value2"}, {Name: "ABC", Value: "value3"}},
|
||||
mod: []corev1.EnvVar{{Name: "abc", Value: "value2"}, {Name: "ABC", Value: "value3"}},
|
||||
result: []api.EnvVar{{Name: "abc", Value: "value2"}, {Name: "hello", Value: "value3"}, {Name: "ABC", Value: "value3"}},
|
||||
shouldFail: false,
|
||||
},
|
||||
@ -66,7 +67,7 @@ func TestMergeEnv(t *testing.T) {
|
||||
for name, test := range tests {
|
||||
result, err := mergeEnv(
|
||||
test.orig,
|
||||
[]*settings.PodPreset{{Spec: settings.PodPresetSpec{Env: test.mod}}},
|
||||
[]*settingsv1alpha1.PodPreset{{Spec: settingsv1alpha1.PodPresetSpec{Env: test.mod}}},
|
||||
)
|
||||
if test.shouldFail && err == nil {
|
||||
t.Fatalf("expected test %q to fail but got nil", name)
|
||||
@ -83,21 +84,21 @@ func TestMergeEnv(t *testing.T) {
|
||||
func TestMergeEnvFrom(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
orig []api.EnvFromSource
|
||||
mod []api.EnvFromSource
|
||||
mod []corev1.EnvFromSource
|
||||
result []api.EnvFromSource
|
||||
shouldFail bool
|
||||
}{
|
||||
"empty original": {
|
||||
mod: []api.EnvFromSource{
|
||||
mod: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Prefix: "pre_",
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -124,16 +125,16 @@ func TestMergeEnvFrom(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
mod: []api.EnvFromSource{
|
||||
mod: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Prefix: "pre_",
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -162,7 +163,7 @@ func TestMergeEnvFrom(t *testing.T) {
|
||||
for name, test := range tests {
|
||||
result, err := mergeEnvFrom(
|
||||
test.orig,
|
||||
[]*settings.PodPreset{{Spec: settings.PodPresetSpec{EnvFrom: test.mod}}},
|
||||
[]*settingsv1alpha1.PodPreset{{Spec: settingsv1alpha1.PodPresetSpec{EnvFrom: test.mod}}},
|
||||
)
|
||||
if test.shouldFail && err == nil {
|
||||
t.Fatalf("expected test %q to fail but got nil", name)
|
||||
@ -179,12 +180,12 @@ func TestMergeEnvFrom(t *testing.T) {
|
||||
func TestMergeVolumeMounts(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
orig []api.VolumeMount
|
||||
mod []api.VolumeMount
|
||||
mod []corev1.VolumeMount
|
||||
result []api.VolumeMount
|
||||
shouldFail bool
|
||||
}{
|
||||
"empty original": {
|
||||
mod: []api.VolumeMount{
|
||||
mod: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "simply-mounted-volume",
|
||||
MountPath: "/opt/",
|
||||
@ -199,7 +200,7 @@ func TestMergeVolumeMounts(t *testing.T) {
|
||||
shouldFail: false,
|
||||
},
|
||||
"good merge": {
|
||||
mod: []api.VolumeMount{
|
||||
mod: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "simply-mounted-volume",
|
||||
MountPath: "/opt/",
|
||||
@ -224,7 +225,7 @@ func TestMergeVolumeMounts(t *testing.T) {
|
||||
shouldFail: false,
|
||||
},
|
||||
"conflict": {
|
||||
mod: []api.VolumeMount{
|
||||
mod: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "simply-mounted-volume",
|
||||
MountPath: "/opt/",
|
||||
@ -243,7 +244,7 @@ func TestMergeVolumeMounts(t *testing.T) {
|
||||
shouldFail: true,
|
||||
},
|
||||
"conflict on mount path": {
|
||||
mod: []api.VolumeMount{
|
||||
mod: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "simply-mounted-volume",
|
||||
MountPath: "/opt/",
|
||||
@ -262,7 +263,7 @@ func TestMergeVolumeMounts(t *testing.T) {
|
||||
shouldFail: true,
|
||||
},
|
||||
"one is exact same": {
|
||||
mod: []api.VolumeMount{
|
||||
mod: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "simply-mounted-volume",
|
||||
MountPath: "/opt/",
|
||||
@ -295,7 +296,7 @@ func TestMergeVolumeMounts(t *testing.T) {
|
||||
for name, test := range tests {
|
||||
result, err := mergeVolumeMounts(
|
||||
test.orig,
|
||||
[]*settings.PodPreset{{Spec: settings.PodPresetSpec{VolumeMounts: test.mod}}},
|
||||
[]*settingsv1alpha1.PodPreset{{Spec: settingsv1alpha1.PodPresetSpec{VolumeMounts: test.mod}}},
|
||||
)
|
||||
if test.shouldFail && err == nil {
|
||||
t.Fatalf("expected test %q to fail but got nil", name)
|
||||
@ -312,14 +313,14 @@ func TestMergeVolumeMounts(t *testing.T) {
|
||||
func TestMergeVolumes(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
orig []api.Volume
|
||||
mod []api.Volume
|
||||
mod []corev1.Volume
|
||||
result []api.Volume
|
||||
shouldFail bool
|
||||
}{
|
||||
"empty original": {
|
||||
mod: []api.Volume{
|
||||
{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
{Name: "vol2", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
mod: []corev1.Volume{
|
||||
{Name: "vol", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}},
|
||||
{Name: "vol2", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}},
|
||||
},
|
||||
result: []api.Volume{
|
||||
{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
@ -332,9 +333,9 @@ func TestMergeVolumes(t *testing.T) {
|
||||
{Name: "vol3", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
{Name: "vol4", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
},
|
||||
mod: []api.Volume{
|
||||
{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
{Name: "vol2", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
mod: []corev1.Volume{
|
||||
{Name: "vol", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}},
|
||||
{Name: "vol2", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}},
|
||||
},
|
||||
result: []api.Volume{
|
||||
{Name: "vol3", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
@ -349,9 +350,9 @@ func TestMergeVolumes(t *testing.T) {
|
||||
{Name: "vol3", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
{Name: "vol4", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
},
|
||||
mod: []api.Volume{
|
||||
{Name: "vol3", VolumeSource: api.VolumeSource{HostPath: &api.HostPathVolumeSource{Path: "/etc/apparmor.d"}}},
|
||||
{Name: "vol2", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
mod: []corev1.Volume{
|
||||
{Name: "vol3", VolumeSource: corev1.VolumeSource{HostPath: &corev1.HostPathVolumeSource{Path: "/etc/apparmor.d"}}},
|
||||
{Name: "vol2", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}},
|
||||
},
|
||||
shouldFail: true,
|
||||
},
|
||||
@ -360,9 +361,9 @@ func TestMergeVolumes(t *testing.T) {
|
||||
{Name: "vol3", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
{Name: "vol4", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
},
|
||||
mod: []api.Volume{
|
||||
{Name: "vol3", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
{Name: "vol2", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
mod: []corev1.Volume{
|
||||
{Name: "vol3", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}},
|
||||
{Name: "vol2", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}},
|
||||
},
|
||||
result: []api.Volume{
|
||||
{Name: "vol3", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},
|
||||
@ -376,7 +377,7 @@ func TestMergeVolumes(t *testing.T) {
|
||||
for name, test := range tests {
|
||||
result, err := mergeVolumes(
|
||||
test.orig,
|
||||
[]*settings.PodPreset{{Spec: settings.PodPresetSpec{Volumes: test.mod}}},
|
||||
[]*settingsv1alpha1.PodPreset{{Spec: settingsv1alpha1.PodPresetSpec{Volumes: test.mod}}},
|
||||
)
|
||||
if test.shouldFail && err == nil {
|
||||
t.Fatalf("expected test %q to fail but got nil", name)
|
||||
@ -392,7 +393,7 @@ func TestMergeVolumes(t *testing.T) {
|
||||
|
||||
// NewTestAdmission provides an admission plugin with test implementations of internal structs. It uses
|
||||
// an authorizer that always returns true.
|
||||
func NewTestAdmission(lister settingslisters.PodPresetLister, objects ...runtime.Object) kadmission.MutationInterface {
|
||||
func NewTestAdmission(lister settingsv1alpha1listers.PodPresetLister, objects ...runtime.Object) kadmission.MutationInterface {
|
||||
// Build a test client that the admission plugin can use to look up the service account missing from its cache
|
||||
client := fake.NewSimpleClientset(objects...)
|
||||
|
||||
@ -424,12 +425,12 @@ func TestAdmitConflictWithDifferentNamespaceShouldDoNothing(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
pip := &settingsv1alpha1.PodPreset{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "othernamespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Spec: settingsv1alpha1.PodPresetSpec{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
@ -439,7 +440,7 @@ func TestAdmitConflictWithDifferentNamespaceShouldDoNothing(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []api.EnvVar{{Name: "abc", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
Env: []corev1.EnvVar{{Name: "abc", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
},
|
||||
}
|
||||
|
||||
@ -470,12 +471,12 @@ func TestAdmitConflictWithNonMatchingLabelsShouldNotError(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
pip := &settingsv1alpha1.PodPreset{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Spec: settingsv1alpha1.PodPresetSpec{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
@ -485,7 +486,7 @@ func TestAdmitConflictWithNonMatchingLabelsShouldNotError(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []api.EnvVar{{Name: "abc", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
Env: []corev1.EnvVar{{Name: "abc", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
},
|
||||
}
|
||||
|
||||
@ -517,12 +518,12 @@ func TestAdmitConflictShouldNotModifyPod(t *testing.T) {
|
||||
}
|
||||
origPod := *pod
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
pip := &settingsv1alpha1.PodPreset{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Spec: settingsv1alpha1.PodPresetSpec{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
@ -532,7 +533,7 @@ func TestAdmitConflictShouldNotModifyPod(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []api.EnvVar{{Name: "abc", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
Env: []corev1.EnvVar{{Name: "abc", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
},
|
||||
}
|
||||
|
||||
@ -566,12 +567,12 @@ func TestAdmit(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
pip := &settingsv1alpha1.PodPreset{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Spec: settingsv1alpha1.PodPresetSpec{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
@ -581,18 +582,18 @@ func TestAdmit(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},
|
||||
Env: []api.EnvVar{{Name: "abcd", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
EnvFrom: []api.EnvFromSource{
|
||||
Volumes: []corev1.Volume{{Name: "vol", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}}},
|
||||
Env: []corev1.EnvVar{{Name: "abcd", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Prefix: "pre_",
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -626,12 +627,12 @@ func TestAdmitMirrorPod(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
pip := &settingsv1alpha1.PodPreset{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Spec: settingsv1alpha1.PodPresetSpec{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
@ -641,18 +642,18 @@ func TestAdmitMirrorPod(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},
|
||||
Env: []api.EnvVar{{Name: "abcd", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
EnvFrom: []api.EnvFromSource{
|
||||
Volumes: []corev1.Volume{{Name: "vol", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}}},
|
||||
Env: []corev1.EnvVar{{Name: "abcd", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Prefix: "pre_",
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -696,12 +697,12 @@ func TestExclusionNoAdmit(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
pip := &settingsv1alpha1.PodPreset{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Spec: settingsv1alpha1.PodPresetSpec{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
@ -711,18 +712,18 @@ func TestExclusionNoAdmit(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},
|
||||
Env: []api.EnvVar{{Name: "abcd", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
EnvFrom: []api.EnvFromSource{
|
||||
Volumes: []corev1.Volume{{Name: "vol", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}}},
|
||||
Env: []corev1.EnvVar{{Name: "abcd", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Prefix: "pre_",
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -760,12 +761,12 @@ func TestAdmitEmptyPodNamespace(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
pip := &settingsv1alpha1.PodPreset{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "different", // (pod will be submitted to namespace 'namespace')
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Spec: settingsv1alpha1.PodPresetSpec{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
@ -775,18 +776,18 @@ func TestAdmitEmptyPodNamespace(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},
|
||||
Env: []api.EnvVar{{Name: "abcd", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
EnvFrom: []api.EnvFromSource{
|
||||
Volumes: []corev1.Volume{{Name: "vol", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}}},
|
||||
Env: []corev1.EnvVar{{Name: "abcd", Value: "value"}, {Name: "ABC", Value: "value"}},
|
||||
EnvFrom: []corev1.EnvFromSource{
|
||||
{
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Prefix: "pre_",
|
||||
ConfigMapRef: &api.ConfigMapEnvSource{
|
||||
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
|
||||
ConfigMapRef: &corev1.ConfigMapEnvSource{
|
||||
LocalObjectReference: corev1.LocalObjectReference{Name: "abc"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -804,11 +805,11 @@ func TestAdmitEmptyPodNamespace(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func admitPod(pod *api.Pod, pip *settings.PodPreset) error {
|
||||
func admitPod(pod *api.Pod, pip *settingsv1alpha1.PodPreset) error {
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
store := informerFactory.Settings().InternalVersion().PodPresets().Informer().GetStore()
|
||||
store := informerFactory.Settings().V1alpha1().PodPresets().Informer().GetStore()
|
||||
store.Add(pip)
|
||||
plugin := NewTestAdmission(informerFactory.Settings().InternalVersion().PodPresets().Lister())
|
||||
plugin := NewTestAdmission(informerFactory.Settings().V1alpha1().PodPresets().Lister())
|
||||
attrs := kadmission.NewAttributesRecord(
|
||||
pod,
|
||||
nil,
|
||||
@ -818,6 +819,7 @@ func admitPod(pod *api.Pod, pip *settings.PodPreset) error {
|
||||
api.Resource("pods").WithVersion("version"),
|
||||
"",
|
||||
kadmission.Create,
|
||||
false,
|
||||
&user.DefaultInfo{},
|
||||
)
|
||||
|
||||
|
50
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/BUILD
generated
vendored
50
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/BUILD
generated
vendored
@ -8,21 +8,27 @@ load(
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
srcs = [
|
||||
"admission_test.go",
|
||||
"main_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//pkg/scheduler/algorithm:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/scheduler/api:go_default_library",
|
||||
"//pkg/util/tolerations:go_default_library",
|
||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -37,24 +43,24 @@ go_library(
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/core/helper/qos:go_default_library",
|
||||
"//pkg/apis/core/v1:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/core/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//pkg/kubeapiserver/admission/util:go_default_library",
|
||||
"//pkg/scheduler/algorithm:go_default_library",
|
||||
"//pkg/scheduler/api:go_default_library",
|
||||
"//pkg/util/tolerations:go_default_library",
|
||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library",
|
||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/install:go_default_library",
|
||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1:go_default_library",
|
||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
36
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/admission.go
generated
vendored
36
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/admission.go
generated
vendored
@ -21,21 +21,22 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
qoshelper "k8s.io/kubernetes/pkg/apis/core/helper/qos"
|
||||
k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
"k8s.io/kubernetes/pkg/kubeapiserver/admission/util"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
|
||||
"k8s.io/kubernetes/pkg/util/tolerations"
|
||||
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
||||
)
|
||||
@ -61,12 +62,13 @@ const (
|
||||
|
||||
var _ admission.MutationInterface = &podTolerationsPlugin{}
|
||||
var _ admission.ValidationInterface = &podTolerationsPlugin{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&podTolerationsPlugin{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&podTolerationsPlugin{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeClientSet(&podTolerationsPlugin{})
|
||||
|
||||
type podTolerationsPlugin struct {
|
||||
*admission.Handler
|
||||
client clientset.Interface
|
||||
namespaceLister corelisters.NamespaceLister
|
||||
client kubernetes.Interface
|
||||
namespaceLister corev1listers.NamespaceLister
|
||||
pluginConfig *pluginapi.Configuration
|
||||
}
|
||||
|
||||
@ -129,7 +131,7 @@ func (p *podTolerationsPlugin) Admit(a admission.Attributes) error {
|
||||
if qoshelper.GetPodQOS(pod) != api.PodQOSBestEffort {
|
||||
finalTolerations = tolerations.MergeTolerations(finalTolerations, []api.Toleration{
|
||||
{
|
||||
Key: algorithm.TaintNodeMemoryPressure,
|
||||
Key: schedulerapi.TaintNodeMemoryPressure,
|
||||
Operator: api.TolerationOpExists,
|
||||
Effect: api.TaintEffectNoSchedule,
|
||||
},
|
||||
@ -186,7 +188,7 @@ func shouldIgnore(a admission.Attributes) bool {
|
||||
obj := a.GetObject()
|
||||
_, ok := obj.(*api.Pod)
|
||||
if !ok {
|
||||
glog.Errorf("expected pod but got %s", a.GetKind().Kind)
|
||||
klog.Errorf("expected pod but got %s", a.GetKind().Kind)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -200,12 +202,12 @@ func NewPodTolerationsPlugin(pluginConfig *pluginapi.Configuration) *podTolerati
|
||||
}
|
||||
}
|
||||
|
||||
func (a *podTolerationsPlugin) SetInternalKubeClientSet(client clientset.Interface) {
|
||||
func (a *podTolerationsPlugin) SetExternalKubeClientSet(client kubernetes.Interface) {
|
||||
a.client = client
|
||||
}
|
||||
|
||||
func (p *podTolerationsPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
namespaceInformer := f.Core().InternalVersion().Namespaces()
|
||||
func (p *podTolerationsPlugin) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
namespaceInformer := f.Core().V1().Namespaces()
|
||||
p.namespaceLister = namespaceInformer.Lister()
|
||||
p.SetReadyFunc(namespaceInformer.Informer().HasSynced)
|
||||
|
||||
@ -222,11 +224,11 @@ func (p *podTolerationsPlugin) ValidateInitialization() error {
|
||||
}
|
||||
|
||||
// in exceptional cases, this can result in two live calls, but once the cache catches up, that will stop.
|
||||
func (p *podTolerationsPlugin) getNamespace(nsName string) (*api.Namespace, error) {
|
||||
func (p *podTolerationsPlugin) getNamespace(nsName string) (*corev1.Namespace, error) {
|
||||
namespace, err := p.namespaceLister.Get(nsName)
|
||||
if errors.IsNotFound(err) {
|
||||
// in case of latency in our caches, make a call direct to storage to verify that it truly exists or not
|
||||
namespace, err = p.client.Core().Namespaces().Get(nsName, metav1.GetOptions{})
|
||||
namespace, err = p.client.CoreV1().Namespaces().Get(nsName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
return nil, err
|
||||
@ -262,7 +264,7 @@ func (p *podTolerationsPlugin) getNamespaceTolerationsWhitelist(nsName string) (
|
||||
// unset (nil), extractNSTolerations returns nil. If the value to these
|
||||
// keys are set to empty, an empty toleration is returned, otherwise
|
||||
// configured tolerations are returned.
|
||||
func extractNSTolerations(ns *api.Namespace, key string) ([]api.Toleration, error) {
|
||||
func extractNSTolerations(ns *corev1.Namespace, key string) ([]api.Toleration, error) {
|
||||
// if a namespace does not have any annotations
|
||||
if len(ns.Annotations) == 0 {
|
||||
return nil, nil
|
||||
|
59
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/admission_test.go
generated
vendored
59
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/admission_test.go
generated
vendored
@ -21,16 +21,19 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
kubeadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
|
||||
"k8s.io/kubernetes/pkg/util/tolerations"
|
||||
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
||||
)
|
||||
@ -82,9 +85,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
if err := utilfeature.DefaultFeatureGate.Set("TaintNodesByCondition=true"); err != nil {
|
||||
t.Errorf("Failed to enable TaintByCondition feature: %v.", err)
|
||||
}
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.TaintNodesByCondition, true)()
|
||||
|
||||
tests := []struct {
|
||||
pod *api.Pod
|
||||
@ -98,7 +99,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
testName string
|
||||
}{
|
||||
{
|
||||
pod: bestEffortPod,
|
||||
pod: bestEffortPod,
|
||||
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
namespaceTolerations: nil,
|
||||
podTolerations: []api.Toleration{},
|
||||
@ -107,7 +108,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
testName: "default cluster tolerations with empty pod tolerations and nil namespace tolerations",
|
||||
},
|
||||
{
|
||||
pod: bestEffortPod,
|
||||
pod: bestEffortPod,
|
||||
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
namespaceTolerations: []api.Toleration{},
|
||||
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
@ -116,7 +117,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
testName: "default cluster tolerations with pod tolerations specified",
|
||||
},
|
||||
{
|
||||
pod: bestEffortPod,
|
||||
pod: bestEffortPod,
|
||||
defaultClusterTolerations: []api.Toleration{},
|
||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
@ -125,7 +126,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
testName: "namespace tolerations",
|
||||
},
|
||||
{
|
||||
pod: bestEffortPod,
|
||||
pod: bestEffortPod,
|
||||
defaultClusterTolerations: []api.Toleration{},
|
||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
podTolerations: []api.Toleration{},
|
||||
@ -134,7 +135,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
testName: "no pod tolerations",
|
||||
},
|
||||
{
|
||||
pod: bestEffortPod,
|
||||
pod: bestEffortPod,
|
||||
defaultClusterTolerations: []api.Toleration{},
|
||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
@ -142,7 +143,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
testName: "conflicting pod and namespace tolerations",
|
||||
},
|
||||
{
|
||||
pod: bestEffortPod,
|
||||
pod: bestEffortPod,
|
||||
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue2", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
namespaceTolerations: []api.Toleration{},
|
||||
podTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
@ -151,7 +152,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
testName: "conflicting pod and default cluster tolerations but overridden by empty namespace tolerations",
|
||||
},
|
||||
{
|
||||
pod: bestEffortPod,
|
||||
pod: bestEffortPod,
|
||||
defaultClusterTolerations: []api.Toleration{},
|
||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
whitelist: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
@ -161,7 +162,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
testName: "merged pod tolerations satisfy whitelist",
|
||||
},
|
||||
{
|
||||
pod: bestEffortPod,
|
||||
pod: bestEffortPod,
|
||||
defaultClusterTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
namespaceTolerations: []api.Toleration{},
|
||||
podTolerations: []api.Toleration{},
|
||||
@ -179,7 +180,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
testName: "pod toleration conflicts with default cluster white list which is overridden by empty namespace whitelist",
|
||||
},
|
||||
{
|
||||
pod: bestEffortPod,
|
||||
pod: bestEffortPod,
|
||||
defaultClusterTolerations: []api.Toleration{},
|
||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
whitelist: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
@ -188,26 +189,26 @@ func TestPodAdmission(t *testing.T) {
|
||||
testName: "merged pod tolerations conflict with the whitelist",
|
||||
},
|
||||
{
|
||||
pod: burstablePod,
|
||||
pod: burstablePod,
|
||||
defaultClusterTolerations: []api.Toleration{},
|
||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
whitelist: []api.Toleration{},
|
||||
podTolerations: []api.Toleration{},
|
||||
mergedTolerations: []api.Toleration{
|
||||
{Key: algorithm.TaintNodeMemoryPressure, Operator: api.TolerationOpExists, Effect: api.TaintEffectNoSchedule, TolerationSeconds: nil},
|
||||
{Key: schedulerapi.TaintNodeMemoryPressure, Operator: api.TolerationOpExists, Effect: api.TaintEffectNoSchedule, TolerationSeconds: nil},
|
||||
{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil},
|
||||
},
|
||||
admit: true,
|
||||
testName: "added memoryPressure/DiskPressure for Burstable pod",
|
||||
},
|
||||
{
|
||||
pod: guaranteedPod,
|
||||
pod: guaranteedPod,
|
||||
defaultClusterTolerations: []api.Toleration{},
|
||||
namespaceTolerations: []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil}},
|
||||
whitelist: []api.Toleration{},
|
||||
podTolerations: []api.Toleration{},
|
||||
mergedTolerations: []api.Toleration{
|
||||
{Key: algorithm.TaintNodeMemoryPressure, Operator: api.TolerationOpExists, Effect: api.TaintEffectNoSchedule, TolerationSeconds: nil},
|
||||
{Key: schedulerapi.TaintNodeMemoryPressure, Operator: api.TolerationOpExists, Effect: api.TaintEffectNoSchedule, TolerationSeconds: nil},
|
||||
{Key: "testKey", Operator: "Equal", Value: "testValue", Effect: "NoSchedule", TolerationSeconds: nil},
|
||||
},
|
||||
admit: true,
|
||||
@ -216,7 +217,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.testName, func(t *testing.T) {
|
||||
namespace := &api.Namespace{
|
||||
namespace := &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "testNamespace",
|
||||
Namespace: "",
|
||||
@ -258,7 +259,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
oldPod.Initializers = &metav1.Initializers{Pending: []metav1.Initializer{{Name: "init"}}}
|
||||
oldPod.Spec.Tolerations = []api.Toleration{{Key: "testKey", Operator: "Equal", Value: "testValue1", Effect: "NoSchedule", TolerationSeconds: nil}}
|
||||
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if test.admit && err != nil {
|
||||
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
|
||||
} else if !test.admit && err == nil {
|
||||
@ -271,7 +272,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
}
|
||||
|
||||
// handles update of uninitialized pod like it's newly created.
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, nil))
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, &oldPod, api.Kind("Pod").WithVersion("version"), "testNamespace", namespace.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if test.admit && err != nil {
|
||||
t.Errorf("Test: %s, expected no error but got: %s", test.testName, err)
|
||||
} else if !test.admit && err == nil {
|
||||
@ -335,27 +336,27 @@ func TestIgnoreUpdatingInitializedPod(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("error in marshalling namespace tolerations %v", namespaceTolerations)
|
||||
}
|
||||
namespace := &api.Namespace{
|
||||
namespace := &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "testNamespace",
|
||||
Namespace: "",
|
||||
},
|
||||
}
|
||||
namespace.Annotations = map[string]string{NSDefaultTolerations: string(tolerationsStr)}
|
||||
err = informerFactory.Core().InternalVersion().Namespaces().Informer().GetStore().Update(namespace)
|
||||
err = informerFactory.Core().V1().Namespaces().Informer().GetStore().Update(namespace)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// if the update of initialized pod is not ignored, an error will be returned because the pod's Tolerations conflicts with namespace's Tolerations.
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, pod, api.Kind("Pod").WithVersion("version"), "testNamespace", pod.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, nil))
|
||||
err = handler.Admit(admission.NewAttributesRecord(pod, pod, api.Kind("Pod").WithVersion("version"), "testNamespace", pod.ObjectMeta.Name, api.Resource("pods").WithVersion("version"), "", admission.Update, false, nil))
|
||||
if err != nil {
|
||||
t.Errorf("expected no error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// newHandlerForTest returns the admission controller configured for testing.
|
||||
func newHandlerForTest(c clientset.Interface) (*podTolerationsPlugin, informers.SharedInformerFactory, error) {
|
||||
func newHandlerForTest(c kubernetes.Interface) (*podTolerationsPlugin, informers.SharedInformerFactory, error) {
|
||||
f := informers.NewSharedInformerFactory(c, 5*time.Minute)
|
||||
pluginConfig, err := loadConfiguration(nil)
|
||||
// must not fail
|
||||
@ -363,7 +364,7 @@ func newHandlerForTest(c clientset.Interface) (*podTolerationsPlugin, informers.
|
||||
return nil, nil, err
|
||||
}
|
||||
handler := NewPodTolerationsPlugin(pluginConfig)
|
||||
pluginInitializer := kubeadmission.NewPluginInitializer(c, f, nil, nil, nil)
|
||||
pluginInitializer := genericadmissioninitializer.New(c, f, nil, nil)
|
||||
pluginInitializer.Initialize(handler)
|
||||
err = admission.ValidateInitialization(handler)
|
||||
return handler, f, err
|
||||
|
@ -16,9 +16,9 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -12,8 +12,8 @@ go_library(
|
||||
deps = [
|
||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library",
|
||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -20,11 +20,11 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=podtolerationrestriction.admission.k8s.io
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the API.
|
||||
// +groupName=podtolerationrestriction.admission.k8s.io
|
||||
package v1alpha1 // import "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/v1alpha1"
|
||||
|
@ -36,11 +36,18 @@ func init() {
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(scheme *runtime.Scheme) error {
|
||||
return scheme.AddGeneratedConversionFuncs(
|
||||
Convert_v1alpha1_Configuration_To_podtolerationrestriction_Configuration,
|
||||
Convert_podtolerationrestriction_Configuration_To_v1alpha1_Configuration,
|
||||
)
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*Configuration)(nil), (*podtolerationrestriction.Configuration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_Configuration_To_podtolerationrestriction_Configuration(a.(*Configuration), b.(*podtolerationrestriction.Configuration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*podtolerationrestriction.Configuration)(nil), (*Configuration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_podtolerationrestriction_Configuration_To_v1alpha1_Configuration(a.(*podtolerationrestriction.Configuration), b.(*Configuration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_Configuration_To_podtolerationrestriction_Configuration(in *Configuration, out *podtolerationrestriction.Configuration, s conversion.Scope) error {
|
||||
|
@ -13,7 +13,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/core/validation:go_default_library",
|
||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
29
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/main_test.go
generated
vendored
Normal file
29
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/main_test.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package podtolerationrestriction
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
_ "k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
utilfeaturetesting.VerifyFeatureGatesUnchanged(utilfeature.DefaultFeatureGate, m.Run)
|
||||
}
|
39
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/BUILD
generated
vendored
39
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/BUILD
generated
vendored
@ -8,19 +8,25 @@ load(
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
srcs = [
|
||||
"admission_test.go",
|
||||
"main_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/scheduling:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/apis/scheduling/v1beta1:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/api/scheduling/v1beta1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -31,17 +37,18 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/scheduling:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/scheduling/internalversion:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//pkg/kubelet/types:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/api/scheduling/v1beta1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/scheduling/v1beta1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
40
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission.go
generated
vendored
40
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission.go
generated
vendored
@ -20,18 +20,19 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
schedulingv1beta1 "k8s.io/api/scheduling/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
genericadmissioninitializers "k8s.io/apiserver/pkg/admission/initializer"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
schedulingv1beta1listers "k8s.io/client-go/listers/scheduling/v1beta1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/scheduling"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
schedulinglisters "k8s.io/kubernetes/pkg/client/listers/scheduling/internalversion"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
kubelettypes "k8s.io/kubernetes/pkg/kubelet/types"
|
||||
)
|
||||
|
||||
@ -50,14 +51,14 @@ func Register(plugins *admission.Plugins) {
|
||||
// priorityPlugin is an implementation of admission.Interface.
|
||||
type priorityPlugin struct {
|
||||
*admission.Handler
|
||||
client internalclientset.Interface
|
||||
lister schedulinglisters.PriorityClassLister
|
||||
client kubernetes.Interface
|
||||
lister schedulingv1beta1listers.PriorityClassLister
|
||||
}
|
||||
|
||||
var _ admission.MutationInterface = &priorityPlugin{}
|
||||
var _ admission.ValidationInterface = &priorityPlugin{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&priorityPlugin{})
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&priorityPlugin{})
|
||||
var _ = genericadmissioninitializers.WantsExternalKubeInformerFactory(&priorityPlugin{})
|
||||
var _ = genericadmissioninitializers.WantsExternalKubeClientSet(&priorityPlugin{})
|
||||
|
||||
// NewPlugin creates a new priority admission plugin.
|
||||
func newPlugin() *priorityPlugin {
|
||||
@ -78,13 +79,13 @@ func (p *priorityPlugin) ValidateInitialization() error {
|
||||
}
|
||||
|
||||
// SetInternalKubeClientSet implements the WantsInternalKubeClientSet interface.
|
||||
func (p *priorityPlugin) SetInternalKubeClientSet(client internalclientset.Interface) {
|
||||
func (p *priorityPlugin) SetExternalKubeClientSet(client kubernetes.Interface) {
|
||||
p.client = client
|
||||
}
|
||||
|
||||
// SetInternalKubeInformerFactory implements the WantsInternalKubeInformerFactory interface.
|
||||
func (p *priorityPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
priorityInformer := f.Scheduling().InternalVersion().PriorityClasses()
|
||||
func (p *priorityPlugin) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
priorityInformer := f.Scheduling().V1beta1().PriorityClasses()
|
||||
p.lister = priorityInformer.Lister()
|
||||
p.SetReadyFunc(priorityInformer.Informer().HasSynced)
|
||||
}
|
||||
@ -187,10 +188,12 @@ func (p *priorityPlugin) admitPod(a admission.Attributes) error {
|
||||
}
|
||||
if len(pod.Spec.PriorityClassName) == 0 {
|
||||
var err error
|
||||
priority, err = p.getDefaultPriority()
|
||||
var pcName string
|
||||
pcName, priority, err = p.getDefaultPriority()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get default priority class: %v", err)
|
||||
}
|
||||
pod.Spec.PriorityClassName = pcName
|
||||
} else {
|
||||
pcName := pod.Spec.PriorityClassName
|
||||
if !priorityClassPermittedInNamespace(pcName, a.GetNamespace()) {
|
||||
@ -241,14 +244,14 @@ func (p *priorityPlugin) validatePriorityClass(a admission.Attributes) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *priorityPlugin) getDefaultPriorityClass() (*scheduling.PriorityClass, error) {
|
||||
func (p *priorityPlugin) getDefaultPriorityClass() (*schedulingv1beta1.PriorityClass, error) {
|
||||
list, err := p.lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// In case more than one global default priority class is added as a result of a race condition,
|
||||
// we pick the one with the lowest priority value.
|
||||
var defaultPC *scheduling.PriorityClass
|
||||
var defaultPC *schedulingv1beta1.PriorityClass
|
||||
for _, pci := range list {
|
||||
if pci.GlobalDefault {
|
||||
if defaultPC == nil || defaultPC.Value > pci.Value {
|
||||
@ -259,13 +262,14 @@ func (p *priorityPlugin) getDefaultPriorityClass() (*scheduling.PriorityClass, e
|
||||
return defaultPC, nil
|
||||
}
|
||||
|
||||
func (p *priorityPlugin) getDefaultPriority() (int32, error) {
|
||||
func (p *priorityPlugin) getDefaultPriority() (string, int32, error) {
|
||||
dpc, err := p.getDefaultPriorityClass()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
return "", 0, err
|
||||
}
|
||||
if dpc != nil {
|
||||
return dpc.Value, nil
|
||||
return dpc.Name, dpc.Value, nil
|
||||
}
|
||||
return int32(scheduling.DefaultPriorityWhenNoDefaultClassExists), nil
|
||||
|
||||
return "", int32(scheduling.DefaultPriorityWhenNoDefaultClassExists), nil
|
||||
}
|
||||
|
151
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission_test.go
generated
vendored
151
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission_test.go
generated
vendored
@ -17,29 +17,36 @@ limitations under the License.
|
||||
package priority
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
|
||||
schedulingv1beta1 "k8s.io/api/scheduling/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
"k8s.io/client-go/informers"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/scheduling"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
"k8s.io/kubernetes/pkg/apis/scheduling/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func addPriorityClasses(ctrl *priorityPlugin, priorityClasses []*scheduling.PriorityClass) {
|
||||
func addPriorityClasses(ctrl *priorityPlugin, priorityClasses []*scheduling.PriorityClass) error {
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
ctrl.SetInternalKubeInformerFactory(informerFactory)
|
||||
ctrl.SetExternalKubeInformerFactory(informerFactory)
|
||||
// First add the existing classes to the cache.
|
||||
for _, c := range priorityClasses {
|
||||
informerFactory.Scheduling().InternalVersion().PriorityClasses().Informer().GetStore().Add(c)
|
||||
s := &schedulingv1beta1.PriorityClass{}
|
||||
if err := v1beta1.Convert_scheduling_PriorityClass_To_v1beta1_PriorityClass(c, s, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
informerFactory.Scheduling().V1beta1().PriorityClasses().Informer().GetStore().Add(s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var defaultClass1 = &scheduling.PriorityClass{
|
||||
@ -131,11 +138,13 @@ func TestPriorityClassAdmission(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
glog.V(4).Infof("starting test %q", test.name)
|
||||
klog.V(4).Infof("starting test %q", test.name)
|
||||
|
||||
ctrl := newPlugin()
|
||||
// Add existing priority classes.
|
||||
addPriorityClasses(ctrl, test.existingClasses)
|
||||
if err := addPriorityClasses(ctrl, test.existingClasses); err != nil {
|
||||
t.Errorf("Test %q: unable to add object to informer: %v", test.name, err)
|
||||
}
|
||||
// Now add the new class.
|
||||
attrs := admission.NewAttributesRecord(
|
||||
test.newClass,
|
||||
@ -146,10 +155,11 @@ func TestPriorityClassAdmission(t *testing.T) {
|
||||
scheduling.Resource("priorityclasses").WithVersion("version"),
|
||||
"",
|
||||
admission.Create,
|
||||
false,
|
||||
test.userInfo,
|
||||
)
|
||||
err := ctrl.Validate(attrs)
|
||||
glog.Infof("Got %v", err)
|
||||
klog.Infof("Got %v", err)
|
||||
if err != nil && !test.expectError {
|
||||
t.Errorf("Test %q: unexpected error received: %v", test.name, err)
|
||||
}
|
||||
@ -167,65 +177,81 @@ func TestDefaultPriority(t *testing.T) {
|
||||
updatedDefaultClass1.GlobalDefault = false
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
classesBefore []*scheduling.PriorityClass
|
||||
classesAfter []*scheduling.PriorityClass
|
||||
attributes admission.Attributes
|
||||
expectedDefaultBefore int32
|
||||
expectedDefaultAfter int32
|
||||
name string
|
||||
classesBefore []*scheduling.PriorityClass
|
||||
classesAfter []*scheduling.PriorityClass
|
||||
attributes admission.Attributes
|
||||
expectedDefaultBefore int32
|
||||
expectedDefaultNameBefore string
|
||||
expectedDefaultAfter int32
|
||||
expectedDefaultNameAfter string
|
||||
}{
|
||||
{
|
||||
name: "simple resolution with a default class",
|
||||
classesBefore: []*scheduling.PriorityClass{defaultClass1},
|
||||
classesAfter: []*scheduling.PriorityClass{defaultClass1},
|
||||
attributes: nil,
|
||||
expectedDefaultBefore: defaultClass1.Value,
|
||||
expectedDefaultAfter: defaultClass1.Value,
|
||||
name: "simple resolution with a default class",
|
||||
classesBefore: []*scheduling.PriorityClass{defaultClass1},
|
||||
classesAfter: []*scheduling.PriorityClass{defaultClass1},
|
||||
attributes: nil,
|
||||
expectedDefaultBefore: defaultClass1.Value,
|
||||
expectedDefaultNameBefore: defaultClass1.Name,
|
||||
expectedDefaultAfter: defaultClass1.Value,
|
||||
expectedDefaultNameAfter: defaultClass1.Name,
|
||||
},
|
||||
{
|
||||
name: "add a default class",
|
||||
classesBefore: []*scheduling.PriorityClass{nondefaultClass1},
|
||||
classesAfter: []*scheduling.PriorityClass{nondefaultClass1, defaultClass1},
|
||||
attributes: admission.NewAttributesRecord(defaultClass1, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Create, nil),
|
||||
expectedDefaultBefore: scheduling.DefaultPriorityWhenNoDefaultClassExists,
|
||||
expectedDefaultAfter: defaultClass1.Value,
|
||||
name: "add a default class",
|
||||
classesBefore: []*scheduling.PriorityClass{nondefaultClass1},
|
||||
classesAfter: []*scheduling.PriorityClass{nondefaultClass1, defaultClass1},
|
||||
attributes: admission.NewAttributesRecord(defaultClass1, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Create, false, nil),
|
||||
expectedDefaultBefore: scheduling.DefaultPriorityWhenNoDefaultClassExists,
|
||||
expectedDefaultNameBefore: "",
|
||||
expectedDefaultAfter: defaultClass1.Value,
|
||||
expectedDefaultNameAfter: defaultClass1.Name,
|
||||
},
|
||||
{
|
||||
name: "multiple default classes resolves to the minimum value among them",
|
||||
classesBefore: []*scheduling.PriorityClass{defaultClass1, defaultClass2},
|
||||
classesAfter: []*scheduling.PriorityClass{defaultClass2},
|
||||
attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, nil),
|
||||
expectedDefaultBefore: defaultClass1.Value,
|
||||
expectedDefaultAfter: defaultClass2.Value,
|
||||
name: "multiple default classes resolves to the minimum value among them",
|
||||
classesBefore: []*scheduling.PriorityClass{defaultClass1, defaultClass2},
|
||||
classesAfter: []*scheduling.PriorityClass{defaultClass2},
|
||||
attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, false, nil),
|
||||
expectedDefaultBefore: defaultClass1.Value,
|
||||
expectedDefaultNameBefore: defaultClass1.Name,
|
||||
expectedDefaultAfter: defaultClass2.Value,
|
||||
expectedDefaultNameAfter: defaultClass2.Name,
|
||||
},
|
||||
{
|
||||
name: "delete default priority class",
|
||||
classesBefore: []*scheduling.PriorityClass{defaultClass1},
|
||||
classesAfter: []*scheduling.PriorityClass{},
|
||||
attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, nil),
|
||||
expectedDefaultBefore: defaultClass1.Value,
|
||||
expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists,
|
||||
name: "delete default priority class",
|
||||
classesBefore: []*scheduling.PriorityClass{defaultClass1},
|
||||
classesAfter: []*scheduling.PriorityClass{},
|
||||
attributes: admission.NewAttributesRecord(nil, nil, pcKind, "", defaultClass1.Name, pcResource, "", admission.Delete, false, nil),
|
||||
expectedDefaultBefore: defaultClass1.Value,
|
||||
expectedDefaultNameBefore: defaultClass1.Name,
|
||||
expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists,
|
||||
expectedDefaultNameAfter: "",
|
||||
},
|
||||
{
|
||||
name: "update default class and remove its global default",
|
||||
classesBefore: []*scheduling.PriorityClass{defaultClass1},
|
||||
classesAfter: []*scheduling.PriorityClass{&updatedDefaultClass1},
|
||||
attributes: admission.NewAttributesRecord(&updatedDefaultClass1, defaultClass1, pcKind, "", defaultClass1.Name, pcResource, "", admission.Update, nil),
|
||||
expectedDefaultBefore: defaultClass1.Value,
|
||||
expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists,
|
||||
name: "update default class and remove its global default",
|
||||
classesBefore: []*scheduling.PriorityClass{defaultClass1},
|
||||
classesAfter: []*scheduling.PriorityClass{&updatedDefaultClass1},
|
||||
attributes: admission.NewAttributesRecord(&updatedDefaultClass1, defaultClass1, pcKind, "", defaultClass1.Name, pcResource, "", admission.Update, false, nil),
|
||||
expectedDefaultBefore: defaultClass1.Value,
|
||||
expectedDefaultNameBefore: defaultClass1.Name,
|
||||
expectedDefaultAfter: scheduling.DefaultPriorityWhenNoDefaultClassExists,
|
||||
expectedDefaultNameAfter: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
glog.V(4).Infof("starting test %q", test.name)
|
||||
klog.V(4).Infof("starting test %q", test.name)
|
||||
ctrl := newPlugin()
|
||||
addPriorityClasses(ctrl, test.classesBefore)
|
||||
defaultPriority, err := ctrl.getDefaultPriority()
|
||||
if err := addPriorityClasses(ctrl, test.classesBefore); err != nil {
|
||||
t.Errorf("Test %q: unable to add object to informer: %v", test.name, err)
|
||||
}
|
||||
pcName, defaultPriority, err := ctrl.getDefaultPriority()
|
||||
if err != nil {
|
||||
t.Errorf("Test %q: unexpected error while getting default priority: %v", test.name, err)
|
||||
}
|
||||
if err == nil && defaultPriority != test.expectedDefaultBefore {
|
||||
t.Errorf("Test %q: expected default priority %d, but got %d", test.name, test.expectedDefaultBefore, defaultPriority)
|
||||
if err == nil &&
|
||||
(defaultPriority != test.expectedDefaultBefore || pcName != test.expectedDefaultNameBefore) {
|
||||
t.Errorf("Test %q: expected default priority %s(%d), but got %s(%d)",
|
||||
test.name, test.expectedDefaultNameBefore, test.expectedDefaultBefore, pcName, defaultPriority)
|
||||
}
|
||||
if test.attributes != nil {
|
||||
err := ctrl.Validate(test.attributes)
|
||||
@ -233,13 +259,17 @@ func TestDefaultPriority(t *testing.T) {
|
||||
t.Errorf("Test %q: unexpected error received: %v", test.name, err)
|
||||
}
|
||||
}
|
||||
addPriorityClasses(ctrl, test.classesAfter)
|
||||
defaultPriority, err = ctrl.getDefaultPriority()
|
||||
if err := addPriorityClasses(ctrl, test.classesAfter); err != nil {
|
||||
t.Errorf("Test %q: unable to add object to informer: %v", test.name, err)
|
||||
}
|
||||
pcName, defaultPriority, err = ctrl.getDefaultPriority()
|
||||
if err != nil {
|
||||
t.Errorf("Test %q: unexpected error while getting default priority: %v", test.name, err)
|
||||
}
|
||||
if err == nil && defaultPriority != test.expectedDefaultAfter {
|
||||
t.Errorf("Test %q: expected default priority %d, but got %d", test.name, test.expectedDefaultAfter, defaultPriority)
|
||||
if err == nil &&
|
||||
(defaultPriority != test.expectedDefaultAfter || pcName != test.expectedDefaultNameAfter) {
|
||||
t.Errorf("Test %q: expected default priority %s(%d), but got %s(%d)",
|
||||
test.name, test.expectedDefaultNameAfter, test.expectedDefaultAfter, pcName, defaultPriority)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -438,9 +468,9 @@ func TestPodAdmission(t *testing.T) {
|
||||
},
|
||||
}
|
||||
// Enable PodPriority feature gate.
|
||||
utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.PodPriority))
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodPriority, true)()
|
||||
// Enable ExperimentalCriticalPodAnnotation feature gate.
|
||||
utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.ExperimentalCriticalPodAnnotation))
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExperimentalCriticalPodAnnotation, true)()
|
||||
tests := []struct {
|
||||
name string
|
||||
existingClasses []*scheduling.PriorityClass
|
||||
@ -552,11 +582,13 @@ func TestPodAdmission(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
glog.V(4).Infof("starting test %q", test.name)
|
||||
klog.V(4).Infof("starting test %q", test.name)
|
||||
|
||||
ctrl := newPlugin()
|
||||
// Add existing priority classes.
|
||||
addPriorityClasses(ctrl, test.existingClasses)
|
||||
if err := addPriorityClasses(ctrl, test.existingClasses); err != nil {
|
||||
t.Errorf("Test %q: unable to add object to informer: %v", test.name, err)
|
||||
}
|
||||
|
||||
// Create pod.
|
||||
attrs := admission.NewAttributesRecord(
|
||||
@ -568,10 +600,11 @@ func TestPodAdmission(t *testing.T) {
|
||||
api.Resource("pods").WithVersion("version"),
|
||||
"",
|
||||
admission.Create,
|
||||
false,
|
||||
nil,
|
||||
)
|
||||
err := ctrl.Admit(attrs)
|
||||
glog.Infof("Got %v", err)
|
||||
klog.Infof("Got %v", err)
|
||||
if !test.expectError {
|
||||
if err != nil {
|
||||
t.Errorf("Test %q: unexpected error received: %v", test.name, err)
|
||||
|
29
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/main_test.go
generated
vendored
Normal file
29
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/main_test.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package priority
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
_ "k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
utilfeaturetesting.VerifyFeatureGatesUnchanged(utilfeature.DefaultFeatureGate, m.Run)
|
||||
}
|
73
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/BUILD
generated
vendored
73
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/BUILD
generated
vendored
@ -17,57 +17,64 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/resourcequota",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/core/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//pkg/quota:go_default_library",
|
||||
"//pkg/quota/generic:go_default_library",
|
||||
"//pkg/quota/v1:go_default_library",
|
||||
"//pkg/quota/v1/generic:go_default_library",
|
||||
"//pkg/util/reflector/prometheus:go_default_library",
|
||||
"//pkg/util/workqueue/prometheus:go_default_library",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota/install:go_default_library",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1:go_default_library",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1:go_default_library",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota/validation:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/storage/etcd:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
|
||||
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/storage/etcd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/workqueue:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
srcs = [
|
||||
"admission_test.go",
|
||||
"main_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/quota/generic:go_default_library",
|
||||
"//pkg/quota/install:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/quota/v1/generic:go_default_library",
|
||||
"//pkg/quota/v1/install:go_default_library",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
|
||||
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//vendor/k8s.io/client-go/testing:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
22
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission.go
generated
vendored
22
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission.go
generated
vendored
@ -21,13 +21,14 @@ import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
genericadmissioninitializer "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
"k8s.io/kubernetes/pkg/quota"
|
||||
"k8s.io/kubernetes/pkg/quota/generic"
|
||||
quota "k8s.io/kubernetes/pkg/quota/v1"
|
||||
"k8s.io/kubernetes/pkg/quota/v1/generic"
|
||||
resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
"k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/validation"
|
||||
)
|
||||
@ -65,12 +66,13 @@ type QuotaAdmission struct {
|
||||
}
|
||||
|
||||
var _ admission.ValidationInterface = &QuotaAdmission{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&QuotaAdmission{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&QuotaAdmission{})
|
||||
var _ = genericadmissioninitializer.WantsExternalKubeClientSet(&QuotaAdmission{})
|
||||
var _ = kubeapiserveradmission.WantsQuotaConfiguration(&QuotaAdmission{})
|
||||
|
||||
type liveLookupEntry struct {
|
||||
expiry time.Time
|
||||
items []*api.ResourceQuota
|
||||
items []*corev1.ResourceQuota
|
||||
}
|
||||
|
||||
// NewResourceQuota configures an admission controller that can enforce quota constraints
|
||||
@ -91,12 +93,12 @@ func NewResourceQuota(config *resourcequotaapi.Configuration, numEvaluators int,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *QuotaAdmission) SetInternalKubeClientSet(client internalclientset.Interface) {
|
||||
func (a *QuotaAdmission) SetExternalKubeClientSet(client kubernetes.Interface) {
|
||||
a.quotaAccessor.client = client
|
||||
}
|
||||
|
||||
func (a *QuotaAdmission) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
a.quotaAccessor.lister = f.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
func (a *QuotaAdmission) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
a.quotaAccessor.lister = f.Core().V1().ResourceQuotas().Lister()
|
||||
}
|
||||
|
||||
func (a *QuotaAdmission) SetQuotaConfiguration(c quota.Configuration) {
|
||||
|
1102
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission_test.go
generated
vendored
1102
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission_test.go
generated
vendored
File diff suppressed because it is too large
Load Diff
9
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/BUILD
generated
vendored
9
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/BUILD
generated
vendored
@ -15,10 +15,10 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -35,6 +35,7 @@ filegroup(
|
||||
":package-srcs",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota/install:all-srcs",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1:all-srcs",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1:all-srcs",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota/validation:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
|
@ -12,8 +12,9 @@ go_library(
|
||||
deps = [
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -23,11 +23,13 @@ import (
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
resourcequotav1alpha1 "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1"
|
||||
resourcequotav1beta1 "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1"
|
||||
)
|
||||
|
||||
// Install registers the API group and adds types to a scheme
|
||||
func Install(scheme *runtime.Scheme) {
|
||||
utilruntime.Must(resourcequotaapi.AddToScheme(scheme))
|
||||
utilruntime.Must(resourcequotav1beta1.AddToScheme(scheme))
|
||||
utilruntime.Must(resourcequotav1alpha1.AddToScheme(scheme))
|
||||
utilruntime.Must(scheme.SetVersionPriority(resourcequotav1alpha1.SchemeGroupVersion))
|
||||
utilruntime.Must(scheme.SetVersionPriority(resourcequotav1beta1.SchemeGroupVersion, resourcequotav1alpha1.SchemeGroupVersion))
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ limitations under the License.
|
||||
package resourcequota
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
@ -68,5 +68,5 @@ type LimitedResource struct {
|
||||
// "PriorityClassNameIn=cluster-services"
|
||||
// +optional
|
||||
// MatchScopes []string `json:"matchScopes,omitempty"`
|
||||
MatchScopes []core.ScopedResourceSelectorRequirement `json:"matchScopes,omitempty"`
|
||||
MatchScopes []corev1.ScopedResourceSelectorRequirement `json:"matchScopes,omitempty"`
|
||||
}
|
||||
|
@ -18,13 +18,12 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=resourcequota.admission.k8s.io
|
||||
|
||||
// Package v1alpha1 is the v1alpha1 version of the API.
|
||||
// +groupName=resourcequota.admission.k8s.io
|
||||
package v1alpha1 // import "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1"
|
||||
|
@ -26,7 +26,6 @@ import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
core "k8s.io/kubernetes/pkg/apis/core"
|
||||
resourcequota "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
)
|
||||
|
||||
@ -36,13 +35,28 @@ func init() {
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(scheme *runtime.Scheme) error {
|
||||
return scheme.AddGeneratedConversionFuncs(
|
||||
Convert_v1alpha1_Configuration_To_resourcequota_Configuration,
|
||||
Convert_resourcequota_Configuration_To_v1alpha1_Configuration,
|
||||
Convert_v1alpha1_LimitedResource_To_resourcequota_LimitedResource,
|
||||
Convert_resourcequota_LimitedResource_To_v1alpha1_LimitedResource,
|
||||
)
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*Configuration)(nil), (*resourcequota.Configuration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_Configuration_To_resourcequota_Configuration(a.(*Configuration), b.(*resourcequota.Configuration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*resourcequota.Configuration)(nil), (*Configuration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_resourcequota_Configuration_To_v1alpha1_Configuration(a.(*resourcequota.Configuration), b.(*Configuration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*LimitedResource)(nil), (*resourcequota.LimitedResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_LimitedResource_To_resourcequota_LimitedResource(a.(*LimitedResource), b.(*resourcequota.LimitedResource), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*resourcequota.LimitedResource)(nil), (*LimitedResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_resourcequota_LimitedResource_To_v1alpha1_LimitedResource(a.(*resourcequota.LimitedResource), b.(*LimitedResource), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_Configuration_To_resourcequota_Configuration(in *Configuration, out *resourcequota.Configuration, s conversion.Scope) error {
|
||||
@ -69,7 +83,7 @@ func autoConvert_v1alpha1_LimitedResource_To_resourcequota_LimitedResource(in *L
|
||||
out.APIGroup = in.APIGroup
|
||||
out.Resource = in.Resource
|
||||
out.MatchContains = *(*[]string)(unsafe.Pointer(&in.MatchContains))
|
||||
out.MatchScopes = *(*[]core.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchScopes))
|
||||
out.MatchScopes = *(*[]v1.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchScopes))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
41
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/BUILD
generated
vendored
Normal file
41
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/BUILD
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"defaults.go",
|
||||
"doc.go",
|
||||
"register.go",
|
||||
"types.go",
|
||||
"zz_generated.conversion.go",
|
||||
"zz_generated.deepcopy.go",
|
||||
"zz_generated.defaults.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1",
|
||||
deps = [
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
25
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/defaults.go
generated
vendored
Normal file
25
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/defaults.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import kruntime "k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
func addDefaultingFuncs(scheme *kruntime.Scheme) error {
|
||||
return RegisterDefaults(scheme)
|
||||
}
|
||||
|
||||
func SetDefaults_Configuration(obj *Configuration) {}
|
23
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/doc.go
generated
vendored
Normal file
23
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/doc.go
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=resourcequota.admission.k8s.io
|
||||
|
||||
// Package v1beta1 is the v1beta1 version of the API.
|
||||
package v1beta1 // import "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1"
|
50
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/register.go
generated
vendored
Normal file
50
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/register.go
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name use in this package
|
||||
const GroupName = "resourcequota.admission.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
|
||||
|
||||
var (
|
||||
// TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api.
|
||||
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func init() {
|
||||
// We only register manually written functions here. The registration of the
|
||||
// generated functions takes place in the generated files. The separation
|
||||
// makes the code compile even when the generated files are missing.
|
||||
localSchemeBuilder.Register(addKnownTypes, addDefaultingFuncs)
|
||||
}
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Configuration{},
|
||||
)
|
||||
return nil
|
||||
}
|
69
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/types.go
generated
vendored
Normal file
69
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/types.go
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// Configuration provides configuration for the ResourceQuota admission controller.
|
||||
type Configuration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
||||
// LimitedResources whose consumption is limited by default.
|
||||
// +optional
|
||||
LimitedResources []LimitedResource `json:"limitedResources"`
|
||||
}
|
||||
|
||||
// LimitedResource matches a resource whose consumption is limited by default.
|
||||
// To consume the resource, there must exist an associated quota that limits
|
||||
// its consumption.
|
||||
type LimitedResource struct {
|
||||
|
||||
// APIGroup is the name of the APIGroup that contains the limited resource.
|
||||
// +optional
|
||||
APIGroup string `json:"apiGroup,omitempty"`
|
||||
|
||||
// Resource is the name of the resource this rule applies to.
|
||||
// For example, if the administrator wants to limit consumption
|
||||
// of a storage resource associated with persistent volume claims,
|
||||
// the value would be "persistentvolumeclaims".
|
||||
Resource string `json:"resource"`
|
||||
|
||||
// For each intercepted request, the quota system will evaluate
|
||||
// its resource usage. It will iterate through each resource consumed
|
||||
// and if the resource contains any substring in this listing, the
|
||||
// quota system will ensure that there is a covering quota. In the
|
||||
// absence of a covering quota, the quota system will deny the request.
|
||||
// For example, if an administrator wants to globally enforce that
|
||||
// that a quota must exist to consume persistent volume claims associated
|
||||
// with any storage class, the list would include
|
||||
// ".storageclass.storage.k8s.io/requests.storage"
|
||||
MatchContains []string `json:"matchContains,omitempty"`
|
||||
// For each intercepted request, the quota system will figure out if the input object
|
||||
// satisfies a scope which is present in this listing, then
|
||||
// quota system will ensure that there is a covering quota. In the
|
||||
// absence of a covering quota, the quota system will deny the request.
|
||||
// For example, if an administrator wants to globally enforce that
|
||||
// a quota must exist to create a pod with "cluster-services" priorityclass
|
||||
// the list would include "scopeName=PriorityClass, Operator=In, Value=cluster-services"
|
||||
// +optional
|
||||
MatchScopes []v1.ScopedResourceSelectorRequirement `json:"matchScopes,omitempty"`
|
||||
}
|
106
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/zz_generated.conversion.go
generated
vendored
Normal file
106
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/zz_generated.conversion.go
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
resourcequota "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(RegisterConversions)
|
||||
}
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*Configuration)(nil), (*resourcequota.Configuration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_Configuration_To_resourcequota_Configuration(a.(*Configuration), b.(*resourcequota.Configuration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*resourcequota.Configuration)(nil), (*Configuration)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_resourcequota_Configuration_To_v1beta1_Configuration(a.(*resourcequota.Configuration), b.(*Configuration), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*LimitedResource)(nil), (*resourcequota.LimitedResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1beta1_LimitedResource_To_resourcequota_LimitedResource(a.(*LimitedResource), b.(*resourcequota.LimitedResource), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*resourcequota.LimitedResource)(nil), (*LimitedResource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_resourcequota_LimitedResource_To_v1beta1_LimitedResource(a.(*resourcequota.LimitedResource), b.(*LimitedResource), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_Configuration_To_resourcequota_Configuration(in *Configuration, out *resourcequota.Configuration, s conversion.Scope) error {
|
||||
out.LimitedResources = *(*[]resourcequota.LimitedResource)(unsafe.Pointer(&in.LimitedResources))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_Configuration_To_resourcequota_Configuration is an autogenerated conversion function.
|
||||
func Convert_v1beta1_Configuration_To_resourcequota_Configuration(in *Configuration, out *resourcequota.Configuration, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_Configuration_To_resourcequota_Configuration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_resourcequota_Configuration_To_v1beta1_Configuration(in *resourcequota.Configuration, out *Configuration, s conversion.Scope) error {
|
||||
out.LimitedResources = *(*[]LimitedResource)(unsafe.Pointer(&in.LimitedResources))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_resourcequota_Configuration_To_v1beta1_Configuration is an autogenerated conversion function.
|
||||
func Convert_resourcequota_Configuration_To_v1beta1_Configuration(in *resourcequota.Configuration, out *Configuration, s conversion.Scope) error {
|
||||
return autoConvert_resourcequota_Configuration_To_v1beta1_Configuration(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_LimitedResource_To_resourcequota_LimitedResource(in *LimitedResource, out *resourcequota.LimitedResource, s conversion.Scope) error {
|
||||
out.APIGroup = in.APIGroup
|
||||
out.Resource = in.Resource
|
||||
out.MatchContains = *(*[]string)(unsafe.Pointer(&in.MatchContains))
|
||||
out.MatchScopes = *(*[]v1.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchScopes))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_LimitedResource_To_resourcequota_LimitedResource is an autogenerated conversion function.
|
||||
func Convert_v1beta1_LimitedResource_To_resourcequota_LimitedResource(in *LimitedResource, out *resourcequota.LimitedResource, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_LimitedResource_To_resourcequota_LimitedResource(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_resourcequota_LimitedResource_To_v1beta1_LimitedResource(in *resourcequota.LimitedResource, out *LimitedResource, s conversion.Scope) error {
|
||||
out.APIGroup = in.APIGroup
|
||||
out.Resource = in.Resource
|
||||
out.MatchContains = *(*[]string)(unsafe.Pointer(&in.MatchContains))
|
||||
out.MatchScopes = *(*[]v1.ScopedResourceSelectorRequirement)(unsafe.Pointer(&in.MatchScopes))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_resourcequota_LimitedResource_To_v1beta1_LimitedResource is an autogenerated conversion function.
|
||||
func Convert_resourcequota_LimitedResource_To_v1beta1_LimitedResource(in *resourcequota.LimitedResource, out *LimitedResource, s conversion.Scope) error {
|
||||
return autoConvert_resourcequota_LimitedResource_To_v1beta1_LimitedResource(in, out, s)
|
||||
}
|
86
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/zz_generated.deepcopy.go
generated
vendored
Normal file
86
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/zz_generated.deepcopy.go
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Configuration) DeepCopyInto(out *Configuration) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
if in.LimitedResources != nil {
|
||||
in, out := &in.LimitedResources, &out.LimitedResources
|
||||
*out = make([]LimitedResource, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Configuration.
|
||||
func (in *Configuration) DeepCopy() *Configuration {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Configuration)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *Configuration) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *LimitedResource) DeepCopyInto(out *LimitedResource) {
|
||||
*out = *in
|
||||
if in.MatchContains != nil {
|
||||
in, out := &in.MatchContains, &out.MatchContains
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.MatchScopes != nil {
|
||||
in, out := &in.MatchScopes, &out.MatchScopes
|
||||
*out = make([]v1.ScopedResourceSelectorRequirement, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LimitedResource.
|
||||
func (in *LimitedResource) DeepCopy() *LimitedResource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(LimitedResource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
37
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/zz_generated.defaults.go
generated
vendored
Normal file
37
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1/zz_generated.defaults.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
scheme.AddTypeDefaultingFunc(&Configuration{}, func(obj interface{}) { SetObjectDefaults_Configuration(obj.(*Configuration)) })
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetObjectDefaults_Configuration(in *Configuration) {
|
||||
SetDefaults_Configuration(in)
|
||||
}
|
@ -12,7 +12,7 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/validation",
|
||||
deps = [
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -21,8 +21,8 @@ limitations under the License.
|
||||
package resourcequota
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
core "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
@ -67,7 +67,7 @@ func (in *LimitedResource) DeepCopyInto(out *LimitedResource) {
|
||||
}
|
||||
if in.MatchScopes != nil {
|
||||
in, out := &in.MatchScopes, &out.MatchScopes
|
||||
*out = make([]core.ScopedResourceSelectorRequirement, len(*in))
|
||||
*out = make([]v1.ScopedResourceSelectorRequirement, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
|
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/config.go
generated
vendored
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/config.go
generated
vendored
@ -25,7 +25,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
"k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/install"
|
||||
resourcequotav1alpha1 "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1"
|
||||
resourcequotav1beta1 "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1beta1"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -41,7 +41,7 @@ func init() {
|
||||
func LoadConfiguration(config io.Reader) (*resourcequotaapi.Configuration, error) {
|
||||
// if no config is provided, return a default configuration
|
||||
if config == nil {
|
||||
externalConfig := &resourcequotav1alpha1.Configuration{}
|
||||
externalConfig := &resourcequotav1beta1.Configuration{}
|
||||
scheme.Default(externalConfig)
|
||||
internalConfig := &resourcequotaapi.Configuration{}
|
||||
if err := scheme.Convert(externalConfig, internalConfig, nil); err != nil {
|
||||
|
83
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/controller.go
generated
vendored
83
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/controller.go
generated
vendored
@ -23,8 +23,9 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@ -34,9 +35,8 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/quota"
|
||||
"k8s.io/kubernetes/pkg/quota/generic"
|
||||
quota "k8s.io/kubernetes/pkg/quota/v1"
|
||||
"k8s.io/kubernetes/pkg/quota/v1/generic"
|
||||
_ "k8s.io/kubernetes/pkg/util/reflector/prometheus" // for reflector metric registration
|
||||
_ "k8s.io/kubernetes/pkg/util/workqueue/prometheus" // for workqueue metric registration
|
||||
resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
@ -52,7 +52,7 @@ type Evaluator interface {
|
||||
type quotaEvaluator struct {
|
||||
quotaAccessor QuotaAccessor
|
||||
// lockAcquisitionFunc acquires any required locks and returns a cleanup method to defer
|
||||
lockAcquisitionFunc func([]api.ResourceQuota) func()
|
||||
lockAcquisitionFunc func([]corev1.ResourceQuota) func()
|
||||
|
||||
ignoredResources map[schema.GroupResource]struct{}
|
||||
|
||||
@ -111,7 +111,7 @@ func newAdmissionWaiter(a admission.Attributes) *admissionWaiter {
|
||||
// NewQuotaEvaluator configures an admission controller that can enforce quota constraints
|
||||
// using the provided registry. The registry must have the capability to handle group/kinds that
|
||||
// are persisted by the server this admission controller is intercepting
|
||||
func NewQuotaEvaluator(quotaAccessor QuotaAccessor, ignoredResources map[schema.GroupResource]struct{}, quotaRegistry quota.Registry, lockAcquisitionFunc func([]api.ResourceQuota) func(), config *resourcequotaapi.Configuration, workers int, stopCh <-chan struct{}) Evaluator {
|
||||
func NewQuotaEvaluator(quotaAccessor QuotaAccessor, ignoredResources map[schema.GroupResource]struct{}, quotaRegistry quota.Registry, lockAcquisitionFunc func([]corev1.ResourceQuota) func(), config *resourcequotaapi.Configuration, workers int, stopCh <-chan struct{}) Evaluator {
|
||||
// if we get a nil config, just create an empty default.
|
||||
if config == nil {
|
||||
config = &resourcequotaapi.Configuration{}
|
||||
@ -143,7 +143,7 @@ func (e *quotaEvaluator) run() {
|
||||
go wait.Until(e.doWork, time.Second, e.stopCh)
|
||||
}
|
||||
<-e.stopCh
|
||||
glog.Infof("Shutting down quota evaluator")
|
||||
klog.Infof("Shutting down quota evaluator")
|
||||
e.queue.ShutDown()
|
||||
}
|
||||
|
||||
@ -162,7 +162,7 @@ func (e *quotaEvaluator) doWork() {
|
||||
}
|
||||
for {
|
||||
if quit := workFunc(); quit {
|
||||
glog.Infof("quota evaluator worker shutdown")
|
||||
klog.Infof("quota evaluator worker shutdown")
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -214,7 +214,7 @@ func (e *quotaEvaluator) checkAttributes(ns string, admissionAttributes []*admis
|
||||
// updates failed on conflict errors and we have retries left, re-get the failed quota from our cache for the latest version
|
||||
// and recurse into this method with the subset. It's safe for us to evaluate ONLY the subset, because the other quota
|
||||
// documents for these waiters have already been evaluated. Step 1, will mark all the ones that should already have succeeded.
|
||||
func (e *quotaEvaluator) checkQuotas(quotas []api.ResourceQuota, admissionAttributes []*admissionWaiter, remainingRetries int) {
|
||||
func (e *quotaEvaluator) checkQuotas(quotas []corev1.ResourceQuota, admissionAttributes []*admissionWaiter, remainingRetries int) {
|
||||
// yet another copy to compare against originals to see if we actually have deltas
|
||||
originalQuotas, err := copyQuotas(quotas)
|
||||
if err != nil {
|
||||
@ -231,6 +231,12 @@ func (e *quotaEvaluator) checkQuotas(quotas []api.ResourceQuota, admissionAttrib
|
||||
continue
|
||||
}
|
||||
|
||||
// Don't update quota for admissionAttributes that correspond to dry-run requests
|
||||
if admissionAttribute.attributes.IsDryRun() {
|
||||
admissionAttribute.result = nil
|
||||
continue
|
||||
}
|
||||
|
||||
// if the new quotas are the same as the old quotas, then this particular one doesn't issue any updates
|
||||
// that means that no quota docs applied, so it can get a pass
|
||||
atLeastOneChangeForThisWaiter := false
|
||||
@ -258,7 +264,7 @@ func (e *quotaEvaluator) checkQuotas(quotas []api.ResourceQuota, admissionAttrib
|
||||
// 1. check to see if the quota changed. If not, skip.
|
||||
// 2. if the quota changed and the update passes, be happy
|
||||
// 3. if the quota changed and the update fails, add the original to a retry list
|
||||
var updatedFailedQuotas []api.ResourceQuota
|
||||
var updatedFailedQuotas []corev1.ResourceQuota
|
||||
var lastErr error
|
||||
for i := range quotas {
|
||||
newQuota := quotas[i]
|
||||
@ -312,7 +318,7 @@ func (e *quotaEvaluator) checkQuotas(quotas []api.ResourceQuota, admissionAttrib
|
||||
|
||||
// this logic goes through our cache to find the new version of all quotas that failed update. If something has been removed
|
||||
// it is skipped on this retry. After all, you removed it.
|
||||
quotasToCheck := []api.ResourceQuota{}
|
||||
quotasToCheck := []corev1.ResourceQuota{}
|
||||
for _, newQuota := range newQuotas {
|
||||
for _, oldQuota := range updatedFailedQuotas {
|
||||
if newQuota.Name == oldQuota.Name {
|
||||
@ -324,8 +330,8 @@ func (e *quotaEvaluator) checkQuotas(quotas []api.ResourceQuota, admissionAttrib
|
||||
e.checkQuotas(quotasToCheck, admissionAttributes, remainingRetries-1)
|
||||
}
|
||||
|
||||
func copyQuotas(in []api.ResourceQuota) ([]api.ResourceQuota, error) {
|
||||
out := make([]api.ResourceQuota, 0, len(in))
|
||||
func copyQuotas(in []corev1.ResourceQuota) ([]corev1.ResourceQuota, error) {
|
||||
out := make([]corev1.ResourceQuota, 0, len(in))
|
||||
for _, quota := range in {
|
||||
out = append(out, *quota.DeepCopy())
|
||||
}
|
||||
@ -349,8 +355,8 @@ func filterLimitedResourcesByGroupResource(input []resourcequotaapi.LimitedResou
|
||||
// limitedByDefault determines from the specified usage and limitedResources the set of resources names
|
||||
// that must be present in a covering quota. It returns empty set if it was unable to determine if
|
||||
// a resource was not limited by default.
|
||||
func limitedByDefault(usage api.ResourceList, limitedResources []resourcequotaapi.LimitedResource) []api.ResourceName {
|
||||
result := []api.ResourceName{}
|
||||
func limitedByDefault(usage corev1.ResourceList, limitedResources []resourcequotaapi.LimitedResource) []corev1.ResourceName {
|
||||
result := []corev1.ResourceName{}
|
||||
for _, limitedResource := range limitedResources {
|
||||
for k, v := range usage {
|
||||
// if a resource is consumed, we need to check if it matches on the limited resource list.
|
||||
@ -368,13 +374,13 @@ func limitedByDefault(usage api.ResourceList, limitedResources []resourcequotaap
|
||||
return result
|
||||
}
|
||||
|
||||
func getMatchedLimitedScopes(evaluator quota.Evaluator, inputObject runtime.Object, limitedResources []resourcequotaapi.LimitedResource) ([]api.ScopedResourceSelectorRequirement, error) {
|
||||
scopes := []api.ScopedResourceSelectorRequirement{}
|
||||
func getMatchedLimitedScopes(evaluator quota.Evaluator, inputObject runtime.Object, limitedResources []resourcequotaapi.LimitedResource) ([]corev1.ScopedResourceSelectorRequirement, error) {
|
||||
scopes := []corev1.ScopedResourceSelectorRequirement{}
|
||||
for _, limitedResource := range limitedResources {
|
||||
matched, err := evaluator.MatchingScopes(inputObject, limitedResource.MatchScopes)
|
||||
if err != nil {
|
||||
glog.Errorf("Error while matching limited Scopes: %v", err)
|
||||
return []api.ScopedResourceSelectorRequirement{}, err
|
||||
klog.Errorf("Error while matching limited Scopes: %v", err)
|
||||
return []corev1.ScopedResourceSelectorRequirement{}, err
|
||||
}
|
||||
for _, scope := range matched {
|
||||
scopes = append(scopes, scope)
|
||||
@ -385,13 +391,17 @@ func getMatchedLimitedScopes(evaluator quota.Evaluator, inputObject runtime.Obje
|
||||
|
||||
// checkRequest verifies that the request does not exceed any quota constraint. it returns a copy of quotas not yet persisted
|
||||
// that capture what the usage would be if the request succeeded. It return an error if there is insufficient quota to satisfy the request
|
||||
func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.Attributes) ([]api.ResourceQuota, error) {
|
||||
namespace := a.GetNamespace()
|
||||
func (e *quotaEvaluator) checkRequest(quotas []corev1.ResourceQuota, a admission.Attributes) ([]corev1.ResourceQuota, error) {
|
||||
evaluator := e.registry.Get(a.GetResource().GroupResource())
|
||||
if evaluator == nil {
|
||||
return quotas, nil
|
||||
}
|
||||
return CheckRequest(quotas, a, evaluator, e.config.LimitedResources)
|
||||
}
|
||||
|
||||
// CheckRequest is a static version of quotaEvaluator.checkRequest, possible to be called from outside.
|
||||
func CheckRequest(quotas []corev1.ResourceQuota, a admission.Attributes, evaluator quota.Evaluator,
|
||||
limited []resourcequotaapi.LimitedResource) ([]corev1.ResourceQuota, error) {
|
||||
if !evaluator.Handles(a) {
|
||||
return quotas, nil
|
||||
}
|
||||
@ -400,14 +410,14 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At
|
||||
inputObject := a.GetObject()
|
||||
|
||||
// Check if object matches AdmissionConfiguration matchScopes
|
||||
limitedScopes, err := getMatchedLimitedScopes(evaluator, inputObject, e.config.LimitedResources)
|
||||
limitedScopes, err := getMatchedLimitedScopes(evaluator, inputObject, limited)
|
||||
if err != nil {
|
||||
return quotas, nil
|
||||
}
|
||||
|
||||
// determine the set of resource names that must exist in a covering quota
|
||||
limitedResourceNames := []api.ResourceName{}
|
||||
limitedResources := filterLimitedResourcesByGroupResource(e.config.LimitedResources, a.GetResource().GroupResource())
|
||||
limitedResourceNames := []corev1.ResourceName{}
|
||||
limitedResources := filterLimitedResourcesByGroupResource(limited, a.GetResource().GroupResource())
|
||||
if len(limitedResources) > 0 {
|
||||
deltaUsage, err := evaluator.Usage(inputObject)
|
||||
if err != nil {
|
||||
@ -426,7 +436,7 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At
|
||||
// this is needed to know if we have satisfied any constraints where consumption
|
||||
// was limited by default.
|
||||
restrictedResourcesSet := sets.String{}
|
||||
restrictedScopes := []api.ScopedResourceSelectorRequirement{}
|
||||
restrictedScopes := []corev1.ScopedResourceSelectorRequirement{}
|
||||
for i := range quotas {
|
||||
resourceQuota := quotas[i]
|
||||
scopeSelectors := getScopeSelectorsFromQuota(resourceQuota)
|
||||
@ -440,7 +450,7 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At
|
||||
|
||||
match, err := evaluator.Matches(&resourceQuota, inputObject)
|
||||
if err != nil {
|
||||
glog.Errorf("Error occurred while matching resource quota, %v, against input object. Err: %v", resourceQuota, err)
|
||||
klog.Errorf("Error occurred while matching resource quota, %v, against input object. Err: %v", resourceQuota, err)
|
||||
return quotas, err
|
||||
}
|
||||
if !match {
|
||||
@ -487,6 +497,7 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At
|
||||
// the resource represents a number of unique references to external
|
||||
// resource. In such a case an evaluator needs to process other objects in
|
||||
// the same namespace which needs to be known.
|
||||
namespace := a.GetNamespace()
|
||||
if accessor, err := meta.Accessor(inputObject); namespace != "" && err == nil {
|
||||
if accessor.GetNamespace() == "" {
|
||||
accessor.SetNamespace(namespace)
|
||||
@ -560,12 +571,12 @@ func (e *quotaEvaluator) checkRequest(quotas []api.ResourceQuota, a admission.At
|
||||
return outQuotas, nil
|
||||
}
|
||||
|
||||
func getScopeSelectorsFromQuota(quota api.ResourceQuota) []api.ScopedResourceSelectorRequirement {
|
||||
selectors := []api.ScopedResourceSelectorRequirement{}
|
||||
func getScopeSelectorsFromQuota(quota corev1.ResourceQuota) []corev1.ScopedResourceSelectorRequirement {
|
||||
selectors := []corev1.ScopedResourceSelectorRequirement{}
|
||||
for _, scope := range quota.Spec.Scopes {
|
||||
selectors = append(selectors, api.ScopedResourceSelectorRequirement{
|
||||
selectors = append(selectors, corev1.ScopedResourceSelectorRequirement{
|
||||
ScopeName: scope,
|
||||
Operator: api.ScopeSelectorOpExists})
|
||||
Operator: corev1.ScopeSelectorOpExists})
|
||||
}
|
||||
if quota.Spec.ScopeSelector != nil {
|
||||
for _, scopeSelector := range quota.Spec.ScopeSelector.MatchExpressions {
|
||||
@ -592,9 +603,9 @@ func (e *quotaEvaluator) Evaluate(a admission.Attributes) error {
|
||||
if evaluator == nil {
|
||||
// create an object count evaluator if no evaluator previously registered
|
||||
// note, we do not need aggregate usage here, so we pass a nil informer func
|
||||
evaluator = generic.NewObjectCountEvaluator(false, gr, nil, "")
|
||||
evaluator = generic.NewObjectCountEvaluator(gr, nil, "")
|
||||
e.registry.Add(evaluator)
|
||||
glog.Infof("quota admission added evaluator for: %s", gr)
|
||||
klog.Infof("quota admission added evaluator for: %s", gr)
|
||||
}
|
||||
// for this kind, check if the operation could mutate any quota resources
|
||||
// if no resources tracked by quota are impacted, then just return
|
||||
@ -669,7 +680,7 @@ func (e *quotaEvaluator) getWork() (string, []*admissionWaiter, bool) {
|
||||
|
||||
// prettyPrint formats a resource list for usage in errors
|
||||
// it outputs resources sorted in increasing order
|
||||
func prettyPrint(item api.ResourceList) string {
|
||||
func prettyPrint(item corev1.ResourceList) string {
|
||||
parts := []string{}
|
||||
keys := []string{}
|
||||
for key := range item {
|
||||
@ -677,14 +688,14 @@ func prettyPrint(item api.ResourceList) string {
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, key := range keys {
|
||||
value := item[api.ResourceName(key)]
|
||||
value := item[corev1.ResourceName(key)]
|
||||
constraint := key + "=" + value.String()
|
||||
parts = append(parts, constraint)
|
||||
}
|
||||
return strings.Join(parts, ",")
|
||||
}
|
||||
|
||||
func prettyPrintResourceNames(a []api.ResourceName) string {
|
||||
func prettyPrintResourceNames(a []corev1.ResourceName) string {
|
||||
values := []string{}
|
||||
for _, value := range a {
|
||||
values = append(values, string(value))
|
||||
@ -694,7 +705,7 @@ func prettyPrintResourceNames(a []api.ResourceName) string {
|
||||
}
|
||||
|
||||
// hasUsageStats returns true if for each hard constraint there is a value for its current usage
|
||||
func hasUsageStats(resourceQuota *api.ResourceQuota) bool {
|
||||
func hasUsageStats(resourceQuota *corev1.ResourceQuota) bool {
|
||||
for resourceName := range resourceQuota.Status.Hard {
|
||||
if _, found := resourceQuota.Status.Used[resourceName]; !found {
|
||||
return false
|
||||
|
29
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/main_test.go
generated
vendored
Normal file
29
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/main_test.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resourcequota
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
_ "k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
utilfeaturetesting.VerifyFeatureGatesUnchanged(utilfeature.DefaultFeatureGate, m.Run)
|
||||
}
|
28
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/resource_access.go
generated
vendored
28
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/resource_access.go
generated
vendored
@ -20,14 +20,14 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/hashicorp/golang-lru"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apiserver/pkg/storage/etcd"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
corev1listers "k8s.io/client-go/listers/core/v1"
|
||||
)
|
||||
|
||||
// QuotaAccessor abstracts the get/set logic from the rest of the Evaluator. This could be a test stub, a straight passthrough,
|
||||
@ -35,17 +35,17 @@ import (
|
||||
type QuotaAccessor interface {
|
||||
// UpdateQuotaStatus is called to persist final status. This method should write to persistent storage.
|
||||
// An error indicates that write didn't complete successfully.
|
||||
UpdateQuotaStatus(newQuota *api.ResourceQuota) error
|
||||
UpdateQuotaStatus(newQuota *corev1.ResourceQuota) error
|
||||
|
||||
// GetQuotas gets all possible quotas for a given namespace
|
||||
GetQuotas(namespace string) ([]api.ResourceQuota, error)
|
||||
GetQuotas(namespace string) ([]corev1.ResourceQuota, error)
|
||||
}
|
||||
|
||||
type quotaAccessor struct {
|
||||
client clientset.Interface
|
||||
client kubernetes.Interface
|
||||
|
||||
// lister can list/get quota objects from a shared informer's cache
|
||||
lister corelisters.ResourceQuotaLister
|
||||
lister corev1listers.ResourceQuotaLister
|
||||
|
||||
// liveLookups holds the last few live lookups we've done to help ammortize cost on repeated lookup failures.
|
||||
// This lets us handle the case of latent caches, by looking up actual results for a namespace on cache miss/no results.
|
||||
@ -77,8 +77,8 @@ func newQuotaAccessor() (*quotaAccessor, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e *quotaAccessor) UpdateQuotaStatus(newQuota *api.ResourceQuota) error {
|
||||
updatedQuota, err := e.client.Core().ResourceQuotas(newQuota.Namespace).UpdateStatus(newQuota)
|
||||
func (e *quotaAccessor) UpdateQuotaStatus(newQuota *corev1.ResourceQuota) error {
|
||||
updatedQuota, err := e.client.CoreV1().ResourceQuotas(newQuota.Namespace).UpdateStatus(newQuota)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -93,13 +93,13 @@ var etcdVersioner = etcd.APIObjectVersioner{}
|
||||
// checkCache compares the passed quota against the value in the look-aside cache and returns the newer
|
||||
// if the cache is out of date, it deletes the stale entry. This only works because of etcd resourceVersions
|
||||
// being monotonically increasing integers
|
||||
func (e *quotaAccessor) checkCache(quota *api.ResourceQuota) *api.ResourceQuota {
|
||||
func (e *quotaAccessor) checkCache(quota *corev1.ResourceQuota) *corev1.ResourceQuota {
|
||||
key := quota.Namespace + "/" + quota.Name
|
||||
uncastCachedQuota, ok := e.updatedQuotas.Get(key)
|
||||
if !ok {
|
||||
return quota
|
||||
}
|
||||
cachedQuota := uncastCachedQuota.(*api.ResourceQuota)
|
||||
cachedQuota := uncastCachedQuota.(*corev1.ResourceQuota)
|
||||
|
||||
if etcdVersioner.CompareResourceVersion(quota, cachedQuota) >= 0 {
|
||||
e.updatedQuotas.Remove(key)
|
||||
@ -108,7 +108,7 @@ func (e *quotaAccessor) checkCache(quota *api.ResourceQuota) *api.ResourceQuota
|
||||
return cachedQuota
|
||||
}
|
||||
|
||||
func (e *quotaAccessor) GetQuotas(namespace string) ([]api.ResourceQuota, error) {
|
||||
func (e *quotaAccessor) GetQuotas(namespace string) ([]corev1.ResourceQuota, error) {
|
||||
// determine if there are any quotas in this namespace
|
||||
// if there are no quotas, we don't need to do anything
|
||||
items, err := e.lister.ResourceQuotas(namespace).List(labels.Everything())
|
||||
@ -142,7 +142,7 @@ func (e *quotaAccessor) GetQuotas(namespace string) ([]api.ResourceQuota, error)
|
||||
}
|
||||
}
|
||||
|
||||
resourceQuotas := []api.ResourceQuota{}
|
||||
resourceQuotas := []corev1.ResourceQuota{}
|
||||
for i := range items {
|
||||
quota := items[i]
|
||||
quota = e.checkCache(quota)
|
||||
|
47
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/BUILD
generated
vendored
47
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/BUILD
generated
vendored
@ -14,21 +14,21 @@ go_library(
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/apis/policy:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/client/listers/policy/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//pkg/registry/rbac:go_default_library",
|
||||
"//pkg/security/podsecuritypolicy:go_default_library",
|
||||
"//pkg/security/podsecuritypolicy/util:go_default_library",
|
||||
"//pkg/serviceaccount:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||
"//staging/src/k8s.io/api/policy/v1beta1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission/initializer:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/policy/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -39,24 +39,25 @@ go_test(
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/policy:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
"//pkg/apis/core/v1:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/security/apparmor:go_default_library",
|
||||
"//pkg/security/podsecuritypolicy:go_default_library",
|
||||
"//pkg/security/podsecuritypolicy/seccomp:go_default_library",
|
||||
"//pkg/security/podsecuritypolicy/util:go_default_library",
|
||||
"//pkg/util/pointer:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/api/policy/v1beta1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library",
|
||||
"//vendor/k8s.io/utils/pointer:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
9
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/OWNERS
generated
vendored
9
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/OWNERS
generated
vendored
@ -1,6 +1,7 @@
|
||||
approvers:
|
||||
- tallclair
|
||||
- liggitt
|
||||
- sig-auth-policy-approvers
|
||||
reviewers:
|
||||
- pweil-
|
||||
- php-coder
|
||||
- sig-auth-policy-reviewers
|
||||
labels:
|
||||
- sig/auth
|
||||
|
||||
|
42
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission.go
generated
vendored
42
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission.go
generated
vendored
@ -22,8 +22,9 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
|
||||
policyv1beta1 "k8s.io/api/policy/v1beta1"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
@ -31,12 +32,11 @@ import (
|
||||
genericadmissioninit "k8s.io/apiserver/pkg/admission/initializer"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/client-go/informers"
|
||||
policylisters "k8s.io/client-go/listers/policy/v1beta1"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
policylisters "k8s.io/kubernetes/pkg/client/listers/policy/internalversion"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
rbacregistry "k8s.io/kubernetes/pkg/registry/rbac"
|
||||
psp "k8s.io/kubernetes/pkg/security/podsecuritypolicy"
|
||||
psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
|
||||
@ -83,7 +83,7 @@ func (plugin *PodSecurityPolicyPlugin) ValidateInitialization() error {
|
||||
var _ admission.MutationInterface = &PodSecurityPolicyPlugin{}
|
||||
var _ admission.ValidationInterface = &PodSecurityPolicyPlugin{}
|
||||
var _ genericadmissioninit.WantsAuthorizer = &PodSecurityPolicyPlugin{}
|
||||
var _ kubeapiserveradmission.WantsInternalKubeInformerFactory = &PodSecurityPolicyPlugin{}
|
||||
var _ genericadmissioninit.WantsExternalKubeInformerFactory = &PodSecurityPolicyPlugin{}
|
||||
var auditKeyPrefix = strings.ToLower(PluginName) + "." + policy.GroupName + ".k8s.io"
|
||||
|
||||
// newPlugin creates a new PSP admission plugin.
|
||||
@ -95,8 +95,8 @@ func newPlugin(strategyFactory psp.StrategyFactory, failOnNoPolicies bool) *PodS
|
||||
}
|
||||
}
|
||||
|
||||
func (a *PodSecurityPolicyPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
podSecurityPolicyInformer := f.Policy().InternalVersion().PodSecurityPolicies()
|
||||
func (a *PodSecurityPolicyPlugin) SetExternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
podSecurityPolicyInformer := f.Policy().V1beta1().PodSecurityPolicies()
|
||||
a.lister = podSecurityPolicyInformer.Lister()
|
||||
a.SetReadyFunc(podSecurityPolicyInformer.Informer().HasSynced)
|
||||
}
|
||||
@ -132,20 +132,20 @@ func (c *PodSecurityPolicyPlugin) Admit(a admission.Attributes) error {
|
||||
if allowedPod != nil {
|
||||
*pod = *allowedPod
|
||||
// annotate and accept the pod
|
||||
glog.V(4).Infof("pod %s (generate: %s) in namespace %s validated against provider %s", pod.Name, pod.GenerateName, a.GetNamespace(), pspName)
|
||||
klog.V(4).Infof("pod %s (generate: %s) in namespace %s validated against provider %s", pod.Name, pod.GenerateName, a.GetNamespace(), pspName)
|
||||
if pod.ObjectMeta.Annotations == nil {
|
||||
pod.ObjectMeta.Annotations = map[string]string{}
|
||||
}
|
||||
pod.ObjectMeta.Annotations[psputil.ValidatedPSPAnnotation] = pspName
|
||||
key := auditKeyPrefix + "/" + "admit-policy"
|
||||
if err := a.AddAnnotation(key, pspName); err != nil {
|
||||
glog.Warningf("failed to set admission audit annotation %s to %s: %v", key, pspName, err)
|
||||
klog.Warningf("failed to set admission audit annotation %s to %s: %v", key, pspName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// we didn't validate against any provider, reject the pod and give the errors for each attempt
|
||||
glog.V(4).Infof("unable to validate pod %s (generate: %s) in namespace %s against any pod security policy: %v", pod.Name, pod.GenerateName, a.GetNamespace(), validationErrs)
|
||||
klog.V(4).Infof("unable to validate pod %s (generate: %s) in namespace %s against any pod security policy: %v", pod.Name, pod.GenerateName, a.GetNamespace(), validationErrs)
|
||||
return admission.NewForbidden(a, fmt.Errorf("unable to validate against any pod security policy: %v", validationErrs))
|
||||
}
|
||||
|
||||
@ -166,13 +166,13 @@ func (c *PodSecurityPolicyPlugin) Validate(a admission.Attributes) error {
|
||||
if apiequality.Semantic.DeepEqual(pod, allowedPod) {
|
||||
key := auditKeyPrefix + "/" + "validate-policy"
|
||||
if err := a.AddAnnotation(key, pspName); err != nil {
|
||||
glog.Warningf("failed to set admission audit annotation %s to %s: %v", key, pspName, err)
|
||||
klog.Warningf("failed to set admission audit annotation %s to %s: %v", key, pspName, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// we didn't validate against any provider, reject the pod and give the errors for each attempt
|
||||
glog.V(4).Infof("unable to validate pod %s (generate: %s) in namespace %s against any pod security policy: %v", pod.Name, pod.GenerateName, a.GetNamespace(), validationErrs)
|
||||
klog.V(4).Infof("unable to validate pod %s (generate: %s) in namespace %s against any pod security policy: %v", pod.Name, pod.GenerateName, a.GetNamespace(), validationErrs)
|
||||
return admission.NewForbidden(a, fmt.Errorf("unable to validate against any pod security policy: %v", validationErrs))
|
||||
}
|
||||
|
||||
@ -207,7 +207,7 @@ func shouldIgnore(a admission.Attributes) (bool, error) {
|
||||
// saved in kubernetes.io/psp annotation. This psp is usually the one we are looking for.
|
||||
func (c *PodSecurityPolicyPlugin) computeSecurityContext(a admission.Attributes, pod *api.Pod, specMutationAllowed bool, validatedPSPHint string) (*api.Pod, string, field.ErrorList, error) {
|
||||
// get all constraints that are usable by the user
|
||||
glog.V(4).Infof("getting pod security policies for pod %s (generate: %s)", pod.Name, pod.GenerateName)
|
||||
klog.V(4).Infof("getting pod security policies for pod %s (generate: %s)", pod.Name, pod.GenerateName)
|
||||
var saInfo user.Info
|
||||
if len(pod.Spec.ServiceAccountName) > 0 {
|
||||
saInfo = serviceaccount.UserInfo(a.GetNamespace(), pod.Spec.ServiceAccountName, "")
|
||||
@ -241,7 +241,7 @@ func (c *PodSecurityPolicyPlugin) computeSecurityContext(a admission.Attributes,
|
||||
|
||||
providers, errs := c.createProvidersFromPolicies(policies, pod.Namespace)
|
||||
for _, err := range errs {
|
||||
glog.V(4).Infof("provider creation error: %v", err)
|
||||
klog.V(4).Infof("provider creation error: %v", err)
|
||||
}
|
||||
|
||||
if len(providers) == 0 {
|
||||
@ -258,7 +258,7 @@ func (c *PodSecurityPolicyPlugin) computeSecurityContext(a admission.Attributes,
|
||||
for _, provider := range providers {
|
||||
podCopy := pod.DeepCopy()
|
||||
|
||||
if errs := assignSecurityContext(provider, podCopy, field.NewPath(fmt.Sprintf("provider %s: ", provider.GetPSPName()))); len(errs) > 0 {
|
||||
if errs := assignSecurityContext(provider, podCopy); len(errs) > 0 {
|
||||
validationErrs[provider.GetPSPName()] = errs
|
||||
continue
|
||||
}
|
||||
@ -303,7 +303,7 @@ func (c *PodSecurityPolicyPlugin) computeSecurityContext(a admission.Attributes,
|
||||
// assignSecurityContext creates a security context for each container in the pod
|
||||
// and validates that the sc falls within the psp constraints. All containers must validate against
|
||||
// the same psp or is not considered valid.
|
||||
func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.Path) field.ErrorList {
|
||||
func assignSecurityContext(provider psp.Provider, pod *api.Pod) field.ErrorList {
|
||||
errs := field.ErrorList{}
|
||||
|
||||
err := provider.DefaultPodSecurityContext(pod)
|
||||
@ -311,7 +311,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
|
||||
errs = append(errs, field.Invalid(field.NewPath("spec", "securityContext"), pod.Spec.SecurityContext, err.Error()))
|
||||
}
|
||||
|
||||
errs = append(errs, provider.ValidatePod(pod, field.NewPath("spec", "securityContext"))...)
|
||||
errs = append(errs, provider.ValidatePod(pod)...)
|
||||
|
||||
for i := range pod.Spec.InitContainers {
|
||||
err := provider.DefaultContainerSecurityContext(pod, &pod.Spec.InitContainers[i])
|
||||
@ -319,7 +319,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
|
||||
errs = append(errs, field.Invalid(field.NewPath("spec", "initContainers").Index(i).Child("securityContext"), "", err.Error()))
|
||||
continue
|
||||
}
|
||||
errs = append(errs, provider.ValidateContainerSecurityContext(pod, &pod.Spec.InitContainers[i], field.NewPath("spec", "initContainers").Index(i).Child("securityContext"))...)
|
||||
errs = append(errs, provider.ValidateContainer(pod, &pod.Spec.InitContainers[i], field.NewPath("spec", "initContainers").Index(i))...)
|
||||
}
|
||||
|
||||
for i := range pod.Spec.Containers {
|
||||
@ -328,7 +328,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
|
||||
errs = append(errs, field.Invalid(field.NewPath("spec", "containers").Index(i).Child("securityContext"), "", err.Error()))
|
||||
continue
|
||||
}
|
||||
errs = append(errs, provider.ValidateContainerSecurityContext(pod, &pod.Spec.Containers[i], field.NewPath("spec", "containers").Index(i).Child("securityContext"))...)
|
||||
errs = append(errs, provider.ValidateContainer(pod, &pod.Spec.Containers[i], field.NewPath("spec", "containers").Index(i))...)
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
@ -338,7 +338,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
|
||||
}
|
||||
|
||||
// createProvidersFromPolicies creates providers from the constraints supplied.
|
||||
func (c *PodSecurityPolicyPlugin) createProvidersFromPolicies(psps []*policy.PodSecurityPolicy, namespace string) ([]psp.Provider, []error) {
|
||||
func (c *PodSecurityPolicyPlugin) createProvidersFromPolicies(psps []*policyv1beta1.PodSecurityPolicy, namespace string) ([]psp.Provider, []error) {
|
||||
var (
|
||||
// collected providers
|
||||
providers []psp.Provider
|
||||
@ -379,7 +379,7 @@ func authorizedForPolicyInAPIGroup(info user.Info, namespace, policyName, apiGro
|
||||
attr := buildAttributes(info, namespace, policyName, apiGroupName)
|
||||
decision, reason, err := authz.Authorize(attr)
|
||||
if err != nil {
|
||||
glog.V(5).Infof("cannot authorize for policy: %v,%v", reason, err)
|
||||
klog.V(5).Infof("cannot authorize for policy: %v,%v", reason, err)
|
||||
}
|
||||
return (decision == authorizer.DecisionAllow)
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
policy "k8s.io/api/policy/v1beta1"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
@ -33,16 +34,16 @@ import (
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
kapi "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/security/apparmor"
|
||||
kpsp "k8s.io/kubernetes/pkg/security/podsecuritypolicy"
|
||||
"k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp"
|
||||
psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
|
||||
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
const defaultContainerName = "test-c"
|
||||
@ -50,11 +51,11 @@ const defaultContainerName = "test-c"
|
||||
// NewTestAdmission provides an admission plugin with test implementations of internal structs.
|
||||
func NewTestAdmission(psps []*policy.PodSecurityPolicy, authz authorizer.Authorizer) *PodSecurityPolicyPlugin {
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
store := informerFactory.Policy().InternalVersion().PodSecurityPolicies().Informer().GetStore()
|
||||
store := informerFactory.Policy().V1beta1().PodSecurityPolicies().Informer().GetStore()
|
||||
for _, psp := range psps {
|
||||
store.Add(psp)
|
||||
}
|
||||
lister := informerFactory.Policy().InternalVersion().PodSecurityPolicies().Lister()
|
||||
lister := informerFactory.Policy().V1beta1().PodSecurityPolicies().Lister()
|
||||
if authz == nil {
|
||||
authz = &TestAuthorizer{}
|
||||
}
|
||||
@ -472,7 +473,7 @@ func TestAdmitPreferNonmutating(t *testing.T) {
|
||||
func TestFailClosedOnInvalidPod(t *testing.T) {
|
||||
plugin := NewTestAdmission(nil, nil)
|
||||
pod := &v1.Pod{}
|
||||
attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, &user.DefaultInfo{})
|
||||
attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, pod.Name, kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, false, &user.DefaultInfo{})
|
||||
|
||||
err := plugin.Admit(attrs)
|
||||
if err == nil {
|
||||
@ -502,19 +503,19 @@ func TestAdmitCaps(t *testing.T) {
|
||||
|
||||
allowsFooInAllowed := restrictivePSP()
|
||||
allowsFooInAllowed.Name = "allowCapInAllowed"
|
||||
allowsFooInAllowed.Spec.AllowedCapabilities = []kapi.Capability{"foo"}
|
||||
allowsFooInAllowed.Spec.AllowedCapabilities = []v1.Capability{"foo"}
|
||||
|
||||
allowsFooInRequired := restrictivePSP()
|
||||
allowsFooInRequired.Name = "allowCapInRequired"
|
||||
allowsFooInRequired.Spec.DefaultAddCapabilities = []kapi.Capability{"foo"}
|
||||
allowsFooInRequired.Spec.DefaultAddCapabilities = []v1.Capability{"foo"}
|
||||
|
||||
requiresFooToBeDropped := restrictivePSP()
|
||||
requiresFooToBeDropped.Name = "requireDrop"
|
||||
requiresFooToBeDropped.Spec.RequiredDropCapabilities = []kapi.Capability{"foo"}
|
||||
requiresFooToBeDropped.Spec.RequiredDropCapabilities = []v1.Capability{"foo"}
|
||||
|
||||
allowAllInAllowed := restrictivePSP()
|
||||
allowAllInAllowed.Name = "allowAllCapsInAllowed"
|
||||
allowAllInAllowed.Spec.AllowedCapabilities = []kapi.Capability{policy.AllowAllCapabilities}
|
||||
allowAllInAllowed.Spec.AllowedCapabilities = []v1.Capability{policy.AllowAllCapabilities}
|
||||
|
||||
tc := map[string]struct {
|
||||
pod *kapi.Pod
|
||||
@ -959,12 +960,18 @@ func TestAdmitSELinux(t *testing.T) {
|
||||
mustRunAs := permissivePSP()
|
||||
mustRunAs.Name = "mustRunAs"
|
||||
mustRunAs.Spec.SELinux.Rule = policy.SELinuxStrategyMustRunAs
|
||||
mustRunAs.Spec.SELinux.SELinuxOptions = &kapi.SELinuxOptions{}
|
||||
mustRunAs.Spec.SELinux.SELinuxOptions = &v1.SELinuxOptions{}
|
||||
mustRunAs.Spec.SELinux.SELinuxOptions.Level = "level"
|
||||
mustRunAs.Spec.SELinux.SELinuxOptions.Role = "role"
|
||||
mustRunAs.Spec.SELinux.SELinuxOptions.Type = "type"
|
||||
mustRunAs.Spec.SELinux.SELinuxOptions.User = "user"
|
||||
|
||||
getInternalSEOptions := func(policy *policy.PodSecurityPolicy) *kapi.SELinuxOptions {
|
||||
opt := kapi.SELinuxOptions{}
|
||||
k8s_api_v1.Convert_v1_SELinuxOptions_To_core_SELinuxOptions(policy.Spec.SELinux.SELinuxOptions, &opt, nil)
|
||||
return &opt
|
||||
}
|
||||
|
||||
tests := map[string]struct {
|
||||
pod *kapi.Pod
|
||||
psps []*policy.PodSecurityPolicy
|
||||
@ -1047,7 +1054,7 @@ func TestAdmitSELinux(t *testing.T) {
|
||||
psps: []*policy.PodSecurityPolicy{mustRunAs},
|
||||
shouldPassAdmit: true,
|
||||
shouldPassValidate: true,
|
||||
expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: mustRunAs.Spec.SELinux.SELinuxOptions},
|
||||
expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: getInternalSEOptions(mustRunAs)},
|
||||
expectedContainerSC: nil,
|
||||
expectedPSP: mustRunAs.Name,
|
||||
},
|
||||
@ -1059,7 +1066,7 @@ func TestAdmitSELinux(t *testing.T) {
|
||||
psps: []*policy.PodSecurityPolicy{mustRunAs},
|
||||
shouldPassAdmit: true,
|
||||
shouldPassValidate: true,
|
||||
expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: mustRunAs.Spec.SELinux.SELinuxOptions},
|
||||
expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: getInternalSEOptions(mustRunAs)},
|
||||
expectedContainerSC: nil,
|
||||
expectedPSP: mustRunAs.Name,
|
||||
},
|
||||
@ -1071,7 +1078,7 @@ func TestAdmitSELinux(t *testing.T) {
|
||||
psps: []*policy.PodSecurityPolicy{mustRunAs},
|
||||
shouldPassAdmit: true,
|
||||
shouldPassValidate: true,
|
||||
expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: mustRunAs.Spec.SELinux.SELinuxOptions},
|
||||
expectedPodSC: &kapi.PodSecurityContext{SELinuxOptions: getInternalSEOptions(mustRunAs)},
|
||||
expectedContainerSC: nil,
|
||||
expectedPSP: mustRunAs.Name,
|
||||
},
|
||||
@ -1769,7 +1776,7 @@ func testPSPAdmitAdvanced(testCaseName string, op kadmission.Operation, psps []*
|
||||
originalPod := pod.DeepCopy()
|
||||
plugin := NewTestAdmission(psps, authz)
|
||||
|
||||
attrs := kadmission.NewAttributesRecord(pod, oldPod, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, "", kapi.Resource("pods").WithVersion("version"), "", op, userInfo)
|
||||
attrs := kadmission.NewAttributesRecord(pod, oldPod, kapi.Kind("Pod").WithVersion("version"), pod.Namespace, "", kapi.Resource("pods").WithVersion("version"), "", op, false, userInfo)
|
||||
annotations := make(map[string]string)
|
||||
attrs = &fakeAttributes{attrs, annotations}
|
||||
err := plugin.Admit(attrs)
|
||||
@ -1876,7 +1883,7 @@ func TestAssignSecurityContext(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range testCases {
|
||||
errs := assignSecurityContext(provider, v.pod, nil)
|
||||
errs := assignSecurityContext(provider, v.pod)
|
||||
if v.shouldValidate && len(errs) > 0 {
|
||||
t.Errorf("%s expected to validate but received errors %v", k, errs)
|
||||
continue
|
||||
@ -1907,6 +1914,9 @@ func TestCreateProvidersFromConstraints(t *testing.T) {
|
||||
RunAsUser: policy.RunAsUserStrategyOptions{
|
||||
Rule: policy.RunAsUserStrategyRunAsAny,
|
||||
},
|
||||
RunAsGroup: &policy.RunAsGroupStrategyOptions{
|
||||
Rule: policy.RunAsGroupStrategyRunAsAny,
|
||||
},
|
||||
FSGroup: policy.FSGroupStrategyOptions{
|
||||
Rule: policy.FSGroupStrategyRunAsAny,
|
||||
},
|
||||
@ -1930,6 +1940,9 @@ func TestCreateProvidersFromConstraints(t *testing.T) {
|
||||
RunAsUser: policy.RunAsUserStrategyOptions{
|
||||
Rule: policy.RunAsUserStrategyMustRunAs,
|
||||
},
|
||||
RunAsGroup: &policy.RunAsGroupStrategyOptions{
|
||||
Rule: policy.RunAsGroupStrategyRunAsAny,
|
||||
},
|
||||
FSGroup: policy.FSGroupStrategyOptions{
|
||||
Rule: policy.FSGroupStrategyRunAsAny,
|
||||
},
|
||||
@ -2227,7 +2240,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) {
|
||||
pod.Spec.SecurityContext.HostPID = true
|
||||
|
||||
plugin := NewTestAdmission(tc.inPolicies, authz)
|
||||
attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), ns, "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, &user.DefaultInfo{Name: userName})
|
||||
attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), ns, "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, false, &user.DefaultInfo{Name: userName})
|
||||
|
||||
allowedPod, _, validationErrs, err := plugin.computeSecurityContext(attrs, pod, true, "")
|
||||
assert.Nil(t, allowedPod)
|
||||
@ -2320,7 +2333,7 @@ func TestPreferValidatedPSP(t *testing.T) {
|
||||
pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = &allowPrivilegeEscalation
|
||||
|
||||
plugin := NewTestAdmission(tc.inPolicies, authz)
|
||||
attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), "ns", "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Update, &user.DefaultInfo{Name: "test"})
|
||||
attrs := kadmission.NewAttributesRecord(pod, nil, kapi.Kind("Pod").WithVersion("version"), "ns", "", kapi.Resource("pods").WithVersion("version"), "", kadmission.Update, false, &user.DefaultInfo{Name: "test"})
|
||||
|
||||
_, pspName, validationErrs, err := plugin.computeSecurityContext(attrs, pod, false, tc.validatedPSPHint)
|
||||
assert.NoError(t, err)
|
||||
@ -2331,21 +2344,29 @@ func TestPreferValidatedPSP(t *testing.T) {
|
||||
}
|
||||
|
||||
func restrictivePSP() *policy.PodSecurityPolicy {
|
||||
allowPrivilegeEscalation := false
|
||||
return &policy.PodSecurityPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "restrictive",
|
||||
Annotations: map[string]string{},
|
||||
},
|
||||
Spec: policy.PodSecurityPolicySpec{
|
||||
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
|
||||
RunAsUser: policy.RunAsUserStrategyOptions{
|
||||
Rule: policy.RunAsUserStrategyMustRunAs,
|
||||
Ranges: []policy.IDRange{
|
||||
{Min: int64(999), Max: int64(999)},
|
||||
},
|
||||
},
|
||||
RunAsGroup: &policy.RunAsGroupStrategyOptions{
|
||||
Rule: policy.RunAsGroupStrategyMustRunAs,
|
||||
Ranges: []policy.IDRange{
|
||||
{Min: int64(999), Max: int64(999)},
|
||||
},
|
||||
},
|
||||
SELinux: policy.SELinuxStrategyOptions{
|
||||
Rule: policy.SELinuxStrategyMustRunAs,
|
||||
SELinuxOptions: &kapi.SELinuxOptions{
|
||||
SELinuxOptions: &v1.SELinuxOptions{
|
||||
Level: "s9:z0,z1",
|
||||
},
|
||||
},
|
||||
@ -2366,22 +2387,26 @@ func restrictivePSP() *policy.PodSecurityPolicy {
|
||||
}
|
||||
|
||||
func permissivePSP() *policy.PodSecurityPolicy {
|
||||
allowPrivilegeEscalation := true
|
||||
return &policy.PodSecurityPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "privileged",
|
||||
Annotations: map[string]string{},
|
||||
},
|
||||
Spec: policy.PodSecurityPolicySpec{
|
||||
AllowPrivilegeEscalation: true,
|
||||
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
|
||||
HostIPC: true,
|
||||
HostNetwork: true,
|
||||
HostPID: true,
|
||||
HostPorts: []policy.HostPortRange{{Min: 0, Max: 65536}},
|
||||
Volumes: []policy.FSType{policy.All},
|
||||
AllowedCapabilities: []kapi.Capability{policy.AllowAllCapabilities},
|
||||
AllowedCapabilities: []v1.Capability{policy.AllowAllCapabilities},
|
||||
RunAsUser: policy.RunAsUserStrategyOptions{
|
||||
Rule: policy.RunAsUserStrategyRunAsAny,
|
||||
},
|
||||
RunAsGroup: &policy.RunAsGroupStrategyOptions{
|
||||
Rule: policy.RunAsGroupStrategyRunAsAny,
|
||||
},
|
||||
SELinux: policy.SELinuxStrategyOptions{
|
||||
Rule: policy.SELinuxStrategyRunAsAny,
|
||||
},
|
||||
|
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny/BUILD
generated
vendored
@ -12,8 +12,8 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -23,7 +23,7 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -82,7 +82,7 @@ func TestAdmission(t *testing.T) {
|
||||
p.Spec.SecurityContext = tc.podSc
|
||||
p.Spec.Containers[0].SecurityContext = tc.sc
|
||||
|
||||
err := handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil))
|
||||
err := handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
|
||||
if err != nil && !tc.expectError {
|
||||
t.Errorf("%v: unexpected error: %v", tc.name, err)
|
||||
} else if err == nil && tc.expectError {
|
||||
@ -96,7 +96,7 @@ func TestAdmission(t *testing.T) {
|
||||
p.Spec.InitContainers = p.Spec.Containers
|
||||
p.Spec.Containers = nil
|
||||
|
||||
err = handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil))
|
||||
err = handler.Validate(admission.NewAttributesRecord(p, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
|
||||
if err != nil && !tc.expectError {
|
||||
t.Errorf("%v: unexpected error: %v", tc.name, err)
|
||||
} else if err == nil && tc.expectError {
|
||||
@ -140,7 +140,7 @@ func TestPodSecurityContextAdmission(t *testing.T) {
|
||||
}
|
||||
for _, test := range tests {
|
||||
pod.Spec.SecurityContext = &test.securityContext
|
||||
err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", nil))
|
||||
err := handler.Validate(admission.NewAttributesRecord(&pod, nil, api.Kind("Pod").WithVersion("version"), "foo", "name", api.Resource("pods").WithVersion("version"), "", "ignored", false, nil))
|
||||
|
||||
if test.errorExpected && err == nil {
|
||||
t.Errorf("Expected error for security context %+v but did not get an error", test.securityContext)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user