mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
vendor updates
This commit is contained in:
6
vendor/k8s.io/kubernetes/plugin/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/plugin/BUILD
generated
vendored
@ -11,7 +11,6 @@ filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//plugin/cmd/kube-scheduler:all-srcs",
|
||||
"//plugin/pkg/admission/admit:all-srcs",
|
||||
"//plugin/pkg/admission/alwayspullimages:all-srcs",
|
||||
"//plugin/pkg/admission/antiaffinity:all-srcs",
|
||||
@ -29,7 +28,6 @@ filegroup(
|
||||
"//plugin/pkg/admission/noderestriction:all-srcs",
|
||||
"//plugin/pkg/admission/persistentvolume/label:all-srcs",
|
||||
"//plugin/pkg/admission/persistentvolume/resize:all-srcs",
|
||||
"//plugin/pkg/admission/persistentvolumeclaim/pvcprotection:all-srcs",
|
||||
"//plugin/pkg/admission/podnodeselector:all-srcs",
|
||||
"//plugin/pkg/admission/podpreset:all-srcs",
|
||||
"//plugin/pkg/admission/podtolerationrestriction:all-srcs",
|
||||
@ -38,9 +36,9 @@ filegroup(
|
||||
"//plugin/pkg/admission/security:all-srcs",
|
||||
"//plugin/pkg/admission/securitycontext/scdeny:all-srcs",
|
||||
"//plugin/pkg/admission/serviceaccount:all-srcs",
|
||||
"//plugin/pkg/admission/storageclass/setdefault:all-srcs",
|
||||
"//plugin/pkg/admission/storage/storageclass/setdefault:all-srcs",
|
||||
"//plugin/pkg/admission/storage/storageobjectinuseprotection:all-srcs",
|
||||
"//plugin/pkg/auth:all-srcs",
|
||||
"//plugin/pkg/scheduler:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
51
vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/BUILD
generated
vendored
51
vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/BUILD
generated
vendored
@ -1,51 +0,0 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
)
|
||||
load("//pkg/version:def.bzl", "version_x_defs")
|
||||
|
||||
go_binary(
|
||||
name = "kube-scheduler",
|
||||
gc_linkopts = [
|
||||
"-linkmode",
|
||||
"external",
|
||||
"-extldflags",
|
||||
"-static",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/plugin/cmd/kube-scheduler",
|
||||
library = ":go_default_library",
|
||||
x_defs = version_x_defs(),
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["scheduler.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/cmd/kube-scheduler",
|
||||
deps = [
|
||||
"//pkg/client/metrics/prometheus:go_default_library",
|
||||
"//pkg/version/prometheus:go_default_library",
|
||||
"//plugin/cmd/kube-scheduler/app:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/logs:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//plugin/cmd/kube-scheduler/app:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
4
vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/OWNERS
generated
vendored
4
vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/OWNERS
generated
vendored
@ -1,4 +0,0 @@
|
||||
approvers:
|
||||
- sig-scheduling-maintainers
|
||||
reviewers:
|
||||
- sig-scheduling
|
66
vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/BUILD
generated
vendored
66
vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/BUILD
generated
vendored
@ -1,66 +0,0 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["server.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/cmd/kube-scheduler/app",
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/componentconfig:go_default_library",
|
||||
"//pkg/apis/componentconfig/v1alpha1:go_default_library",
|
||||
"//pkg/client/leaderelectionconfig:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubectl/cmd/util:go_default_library",
|
||||
"//pkg/master/ports:go_default_library",
|
||||
"//pkg/util/configz:go_default_library",
|
||||
"//pkg/version:go_default_library",
|
||||
"//pkg/version/verflag:go_default_library",
|
||||
"//plugin/pkg/scheduler:go_default_library",
|
||||
"//plugin/pkg/scheduler/algorithmprovider:go_default_library",
|
||||
"//plugin/pkg/scheduler/api:go_default_library",
|
||||
"//plugin/pkg/scheduler/api/latest:go_default_library",
|
||||
"//plugin/pkg/scheduler/factory:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag: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/runtime: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/wait:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/server/healthz:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers/storage/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/leaderelection:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/leaderelection/resourcelock:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/record:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
708
vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/server.go
generated
vendored
708
vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/server.go
generated
vendored
@ -1,708 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 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 app implements a Server object for running the scheduler.
|
||||
package app
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
"os"
|
||||
"reflect"
|
||||
goruntime "runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/server/healthz"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/informers"
|
||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||
storageinformers "k8s.io/client-go/informers/storage/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/client-go/tools/leaderelection"
|
||||
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/apis/componentconfig"
|
||||
componentconfigv1alpha1 "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1"
|
||||
"k8s.io/kubernetes/pkg/client/leaderelectionconfig"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/master/ports"
|
||||
"k8s.io/kubernetes/pkg/util/configz"
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
"k8s.io/kubernetes/pkg/version/verflag"
|
||||
"k8s.io/kubernetes/plugin/pkg/scheduler"
|
||||
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithmprovider"
|
||||
schedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api"
|
||||
latestschedulerapi "k8s.io/kubernetes/plugin/pkg/scheduler/api/latest"
|
||||
|
||||
"k8s.io/kubernetes/plugin/pkg/scheduler/factory"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// SchedulerServer has all the context and params needed to run a Scheduler
|
||||
type Options struct {
|
||||
// ConfigFile is the location of the scheduler server's configuration file.
|
||||
ConfigFile string
|
||||
|
||||
// config is the scheduler server's configuration object.
|
||||
config *componentconfig.KubeSchedulerConfiguration
|
||||
|
||||
scheme *runtime.Scheme
|
||||
codecs serializer.CodecFactory
|
||||
|
||||
// The fields below here are placeholders for flags that can't be directly
|
||||
// mapped into componentconfig.KubeSchedulerConfiguration.
|
||||
//
|
||||
// TODO remove these fields once the deprecated flags are removed.
|
||||
|
||||
// master is the address of the Kubernetes API server (overrides any
|
||||
// value in kubeconfig).
|
||||
master string
|
||||
healthzAddress string
|
||||
healthzPort int32
|
||||
policyConfigFile string
|
||||
policyConfigMapName string
|
||||
policyConfigMapNamespace string
|
||||
useLegacyPolicyConfig bool
|
||||
algorithmProvider string
|
||||
}
|
||||
|
||||
// AddFlags adds flags for a specific SchedulerServer to the specified FlagSet
|
||||
func AddFlags(options *Options, fs *pflag.FlagSet) {
|
||||
fs.StringVar(&options.ConfigFile, "config", options.ConfigFile, "The path to the configuration file.")
|
||||
|
||||
// All flags below here are deprecated and will eventually be removed.
|
||||
|
||||
fs.Int32Var(&options.healthzPort, "port", ports.SchedulerPort, "The port that the scheduler's http service runs on")
|
||||
fs.StringVar(&options.healthzAddress, "address", options.healthzAddress, "The IP address to serve on (set to 0.0.0.0 for all interfaces)")
|
||||
fs.StringVar(&options.algorithmProvider, "algorithm-provider", options.algorithmProvider, "The scheduling algorithm provider to use, one of: "+factory.ListAlgorithmProviders())
|
||||
fs.StringVar(&options.policyConfigFile, "policy-config-file", options.policyConfigFile, "File with scheduler policy configuration. This file is used if policy ConfigMap is not provided or --use-legacy-policy-config==true")
|
||||
usage := fmt.Sprintf("Name of the ConfigMap object that contains scheduler's policy configuration. It must exist in the system namespace before scheduler initialization if --use-legacy-policy-config==false. The config must be provided as the value of an element in 'Data' map with the key='%v'", componentconfig.SchedulerPolicyConfigMapKey)
|
||||
fs.StringVar(&options.policyConfigMapName, "policy-configmap", options.policyConfigMapName, usage)
|
||||
fs.StringVar(&options.policyConfigMapNamespace, "policy-configmap-namespace", options.policyConfigMapNamespace, "The namespace where policy ConfigMap is located. The system namespace will be used if this is not provided or is empty.")
|
||||
fs.BoolVar(&options.useLegacyPolicyConfig, "use-legacy-policy-config", false, "When set to true, scheduler will ignore policy ConfigMap and uses policy config file")
|
||||
fs.BoolVar(&options.config.EnableProfiling, "profiling", options.config.EnableProfiling, "Enable profiling via web interface host:port/debug/pprof/")
|
||||
fs.BoolVar(&options.config.EnableContentionProfiling, "contention-profiling", options.config.EnableContentionProfiling, "Enable lock contention profiling, if profiling is enabled")
|
||||
fs.StringVar(&options.master, "master", options.master, "The address of the Kubernetes API server (overrides any value in kubeconfig)")
|
||||
fs.StringVar(&options.config.ClientConnection.KubeConfigFile, "kubeconfig", options.config.ClientConnection.KubeConfigFile, "Path to kubeconfig file with authorization and master location information.")
|
||||
fs.StringVar(&options.config.ClientConnection.ContentType, "kube-api-content-type", options.config.ClientConnection.ContentType, "Content type of requests sent to apiserver.")
|
||||
fs.Float32Var(&options.config.ClientConnection.QPS, "kube-api-qps", options.config.ClientConnection.QPS, "QPS to use while talking with kubernetes apiserver")
|
||||
fs.Int32Var(&options.config.ClientConnection.Burst, "kube-api-burst", options.config.ClientConnection.Burst, "Burst to use while talking with kubernetes apiserver")
|
||||
fs.StringVar(&options.config.SchedulerName, "scheduler-name", options.config.SchedulerName, "Name of the scheduler, used to select which pods will be processed by this scheduler, based on pod's \"spec.SchedulerName\".")
|
||||
fs.StringVar(&options.config.LeaderElection.LockObjectNamespace, "lock-object-namespace", options.config.LeaderElection.LockObjectNamespace, "Define the namespace of the lock object.")
|
||||
fs.StringVar(&options.config.LeaderElection.LockObjectName, "lock-object-name", options.config.LeaderElection.LockObjectName, "Define the name of the lock object.")
|
||||
fs.Int32Var(&options.config.HardPodAffinitySymmetricWeight, "hard-pod-affinity-symmetric-weight", options.config.HardPodAffinitySymmetricWeight,
|
||||
"RequiredDuringScheduling affinity is not symmetric, but there is an implicit PreferredDuringScheduling affinity rule corresponding "+
|
||||
"to every RequiredDuringScheduling affinity rule. --hard-pod-affinity-symmetric-weight represents the weight of implicit PreferredDuringScheduling affinity rule.")
|
||||
fs.MarkDeprecated("hard-pod-affinity-symmetric-weight", "This option was moved to the policy configuration file")
|
||||
fs.StringVar(&options.config.FailureDomains, "failure-domains", options.config.FailureDomains, "Indicate the \"all topologies\" set for an empty topologyKey when it's used for PreferredDuringScheduling pod anti-affinity.")
|
||||
fs.MarkDeprecated("failure-domains", "Doesn't have any effect. Will be removed in future version.")
|
||||
leaderelectionconfig.BindFlags(&options.config.LeaderElection.LeaderElectionConfiguration, fs)
|
||||
utilfeature.DefaultFeatureGate.AddFlag(fs)
|
||||
}
|
||||
|
||||
func NewOptions() (*Options, error) {
|
||||
o := &Options{
|
||||
config: new(componentconfig.KubeSchedulerConfiguration),
|
||||
}
|
||||
|
||||
o.scheme = runtime.NewScheme()
|
||||
o.codecs = serializer.NewCodecFactory(o.scheme)
|
||||
|
||||
if err := componentconfig.AddToScheme(o.scheme); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := componentconfigv1alpha1.AddToScheme(o.scheme); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func (o *Options) Complete() error {
|
||||
if len(o.ConfigFile) == 0 {
|
||||
glog.Warning("WARNING: all flags than --config are deprecated. Please begin using a config file ASAP.")
|
||||
o.applyDeprecatedHealthzAddressToConfig()
|
||||
o.applyDeprecatedHealthzPortToConfig()
|
||||
o.applyDeprecatedAlgorithmSourceOptionsToConfig()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// applyDeprecatedHealthzAddressToConfig sets o.config.HealthzBindAddress and
|
||||
// o.config.MetricsBindAddress from flags passed on the command line based on
|
||||
// the following rules:
|
||||
//
|
||||
// 1. If --address is empty, leave the config as-is.
|
||||
// 2. Otherwise, use the value of --address for the address portion of
|
||||
// o.config.HealthzBindAddress
|
||||
func (o *Options) applyDeprecatedHealthzAddressToConfig() {
|
||||
if len(o.healthzAddress) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
_, port, err := net.SplitHostPort(o.config.HealthzBindAddress)
|
||||
if err != nil {
|
||||
glog.Fatalf("invalid healthz bind address %q: %v", o.config.HealthzBindAddress, err)
|
||||
}
|
||||
o.config.HealthzBindAddress = net.JoinHostPort(o.healthzAddress, port)
|
||||
o.config.MetricsBindAddress = net.JoinHostPort(o.healthzAddress, port)
|
||||
}
|
||||
|
||||
// applyDeprecatedHealthzPortToConfig sets o.config.HealthzBindAddress and
|
||||
// o.config.MetricsBindAddress from flags passed on the command line based on
|
||||
// the following rules:
|
||||
//
|
||||
// 1. If --port is -1, disable the healthz server.
|
||||
// 2. Otherwise, use the value of --port for the port portion of
|
||||
// o.config.HealthzBindAddress
|
||||
func (o *Options) applyDeprecatedHealthzPortToConfig() {
|
||||
if o.healthzPort == -1 {
|
||||
o.config.HealthzBindAddress = ""
|
||||
return
|
||||
}
|
||||
|
||||
host, _, err := net.SplitHostPort(o.config.HealthzBindAddress)
|
||||
if err != nil {
|
||||
glog.Fatalf("invalid healthz bind address %q: %v", o.config.HealthzBindAddress, err)
|
||||
}
|
||||
o.config.HealthzBindAddress = net.JoinHostPort(host, strconv.Itoa(int(o.healthzPort)))
|
||||
o.config.MetricsBindAddress = net.JoinHostPort(host, strconv.Itoa(int(o.healthzPort)))
|
||||
}
|
||||
|
||||
// applyDeprecatedAlgorithmSourceOptionsToConfig sets o.config.AlgorithmSource from
|
||||
// flags passed on the command line in the following precedence order:
|
||||
//
|
||||
// 1. --use-legacy-policy-config to use a policy file.
|
||||
// 2. --policy-configmap to use a policy config map value.
|
||||
// 3. --algorithm-provider to use a named algorithm provider.
|
||||
func (o *Options) applyDeprecatedAlgorithmSourceOptionsToConfig() {
|
||||
switch {
|
||||
case o.useLegacyPolicyConfig:
|
||||
o.config.AlgorithmSource = componentconfig.SchedulerAlgorithmSource{
|
||||
Policy: &componentconfig.SchedulerPolicySource{
|
||||
File: &componentconfig.SchedulerPolicyFileSource{
|
||||
Path: o.policyConfigFile,
|
||||
},
|
||||
},
|
||||
}
|
||||
case len(o.policyConfigMapName) > 0:
|
||||
o.config.AlgorithmSource = componentconfig.SchedulerAlgorithmSource{
|
||||
Policy: &componentconfig.SchedulerPolicySource{
|
||||
ConfigMap: &componentconfig.SchedulerPolicyConfigMapSource{
|
||||
Name: o.policyConfigMapName,
|
||||
Namespace: o.policyConfigMapNamespace,
|
||||
},
|
||||
},
|
||||
}
|
||||
case len(o.algorithmProvider) > 0:
|
||||
o.config.AlgorithmSource = componentconfig.SchedulerAlgorithmSource{
|
||||
Provider: &o.algorithmProvider,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate validates all the required options.
|
||||
func (o *Options) Validate(args []string) error {
|
||||
if len(args) != 0 {
|
||||
return errors.New("no arguments are supported")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadConfigFromFile loads the contents of file and decodes it as a
|
||||
// KubeSchedulerConfiguration object.
|
||||
func (o *Options) loadConfigFromFile(file string) (*componentconfig.KubeSchedulerConfiguration, error) {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return o.loadConfig(data)
|
||||
}
|
||||
|
||||
// loadConfig decodes data as a KubeSchedulerConfiguration object.
|
||||
func (o *Options) loadConfig(data []byte) (*componentconfig.KubeSchedulerConfiguration, error) {
|
||||
configObj, gvk, err := o.codecs.UniversalDecoder().Decode(data, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config, ok := configObj.(*componentconfig.KubeSchedulerConfiguration)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("got unexpected config type: %v", gvk)
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (o *Options) ApplyDefaults(in *componentconfig.KubeSchedulerConfiguration) (*componentconfig.KubeSchedulerConfiguration, error) {
|
||||
external, err := o.scheme.ConvertToVersion(in, componentconfigv1alpha1.SchemeGroupVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
o.scheme.Default(external)
|
||||
|
||||
internal, err := o.scheme.ConvertToVersion(external, componentconfig.SchemeGroupVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := internal.(*componentconfig.KubeSchedulerConfiguration)
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (o *Options) Run() error {
|
||||
config := o.config
|
||||
|
||||
if len(o.ConfigFile) > 0 {
|
||||
if c, err := o.loadConfigFromFile(o.ConfigFile); err != nil {
|
||||
return err
|
||||
} else {
|
||||
config = c
|
||||
}
|
||||
}
|
||||
|
||||
// Apply algorithms based on feature gates.
|
||||
// TODO: make configurable?
|
||||
algorithmprovider.ApplyFeatureGates()
|
||||
|
||||
server, err := NewSchedulerServer(config, o.master)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stop := make(chan struct{})
|
||||
return server.Run(stop)
|
||||
}
|
||||
|
||||
// NewSchedulerCommand creates a *cobra.Command object with default parameters
|
||||
func NewSchedulerCommand() *cobra.Command {
|
||||
opts, err := NewOptions()
|
||||
if err != nil {
|
||||
glog.Fatalf("unable to initialize command options: %v", err)
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "kube-scheduler",
|
||||
Long: `The Kubernetes scheduler is a policy-rich, topology-aware,
|
||||
workload-specific function that significantly impacts availability, performance,
|
||||
and capacity. The scheduler needs to take into account individual and collective
|
||||
resource requirements, quality of service requirements, hardware/software/policy
|
||||
constraints, affinity and anti-affinity specifications, data locality, inter-workload
|
||||
interference, deadlines, and so on. Workload-specific requirements will be exposed
|
||||
through the API as necessary.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
verflag.PrintAndExitIfRequested()
|
||||
cmdutil.CheckErr(opts.Complete())
|
||||
cmdutil.CheckErr(opts.Validate(args))
|
||||
cmdutil.CheckErr(opts.Run())
|
||||
},
|
||||
}
|
||||
|
||||
opts.config, err = opts.ApplyDefaults(opts.config)
|
||||
if err != nil {
|
||||
glog.Fatalf("unable to apply config defaults: %v", err)
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
AddFlags(opts, flags)
|
||||
|
||||
cmd.MarkFlagFilename("config", "yaml", "yml", "json")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// SchedulerServer represents all the parameters required to start the
|
||||
// Kubernetes scheduler server.
|
||||
type SchedulerServer struct {
|
||||
SchedulerName string
|
||||
Client clientset.Interface
|
||||
InformerFactory informers.SharedInformerFactory
|
||||
PodInformer coreinformers.PodInformer
|
||||
AlgorithmSource componentconfig.SchedulerAlgorithmSource
|
||||
HardPodAffinitySymmetricWeight int32
|
||||
EventClient v1core.EventsGetter
|
||||
Recorder record.EventRecorder
|
||||
Broadcaster record.EventBroadcaster
|
||||
// LeaderElection is optional.
|
||||
LeaderElection *leaderelection.LeaderElectionConfig
|
||||
// HealthzServer is optional.
|
||||
HealthzServer *http.Server
|
||||
// MetricsServer is optional.
|
||||
MetricsServer *http.Server
|
||||
}
|
||||
|
||||
// NewSchedulerServer creates a runnable SchedulerServer from configuration.
|
||||
func NewSchedulerServer(config *componentconfig.KubeSchedulerConfiguration, master string) (*SchedulerServer, error) {
|
||||
if config == nil {
|
||||
return nil, errors.New("config is required")
|
||||
}
|
||||
|
||||
// Configz registration.
|
||||
if c, err := configz.New("componentconfig"); err == nil {
|
||||
c.Set(config)
|
||||
} else {
|
||||
return nil, fmt.Errorf("unable to register configz: %s", err)
|
||||
}
|
||||
|
||||
// Prepare some Kube clients.
|
||||
client, leaderElectionClient, eventClient, err := createClients(config.ClientConnection, master)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Prepare event clients.
|
||||
eventBroadcaster := record.NewBroadcaster()
|
||||
recorder := eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: config.SchedulerName})
|
||||
|
||||
// Set up leader election if enabled.
|
||||
var leaderElectionConfig *leaderelection.LeaderElectionConfig
|
||||
if config.LeaderElection.LeaderElect {
|
||||
leaderElectionConfig, err = makeLeaderElectionConfig(config.LeaderElection, leaderElectionClient, recorder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare a healthz server. If the metrics bind address is the same as the
|
||||
// healthz bind address, consolidate the servers into one.
|
||||
var healthzServer *http.Server
|
||||
if len(config.HealthzBindAddress) != 0 {
|
||||
healthzServer = makeHealthzServer(config)
|
||||
}
|
||||
|
||||
// Prepare a separate metrics server only if the bind address differs from the
|
||||
// healthz bind address.
|
||||
var metricsServer *http.Server
|
||||
if len(config.MetricsBindAddress) > 0 && config.HealthzBindAddress != config.MetricsBindAddress {
|
||||
metricsServer = makeMetricsServer(config)
|
||||
}
|
||||
|
||||
return &SchedulerServer{
|
||||
SchedulerName: config.SchedulerName,
|
||||
Client: client,
|
||||
InformerFactory: informers.NewSharedInformerFactory(client, 0),
|
||||
PodInformer: factory.NewPodInformer(client, 0, config.SchedulerName),
|
||||
AlgorithmSource: config.AlgorithmSource,
|
||||
HardPodAffinitySymmetricWeight: config.HardPodAffinitySymmetricWeight,
|
||||
EventClient: eventClient,
|
||||
Recorder: recorder,
|
||||
Broadcaster: eventBroadcaster,
|
||||
LeaderElection: leaderElectionConfig,
|
||||
HealthzServer: healthzServer,
|
||||
MetricsServer: metricsServer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// makeLeaderElectionConfig builds a leader election configuration. It will
|
||||
// create a new resource lock associated with the configuration.
|
||||
func makeLeaderElectionConfig(config componentconfig.KubeSchedulerLeaderElectionConfiguration, client clientset.Interface, recorder record.EventRecorder) (*leaderelection.LeaderElectionConfig, error) {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get hostname: %v", err)
|
||||
}
|
||||
|
||||
rl, err := resourcelock.New(config.ResourceLock,
|
||||
config.LockObjectNamespace,
|
||||
config.LockObjectName,
|
||||
client.CoreV1(),
|
||||
resourcelock.ResourceLockConfig{
|
||||
Identity: hostname,
|
||||
EventRecorder: recorder,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't create resource lock: %v", err)
|
||||
}
|
||||
|
||||
return &leaderelection.LeaderElectionConfig{
|
||||
Lock: rl,
|
||||
LeaseDuration: config.LeaseDuration.Duration,
|
||||
RenewDeadline: config.RenewDeadline.Duration,
|
||||
RetryPeriod: config.RetryPeriod.Duration,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// makeHealthzServer creates a healthz server from the config, and will also
|
||||
// embed the metrics handler if the healthz and metrics address configurations
|
||||
// are the same.
|
||||
func makeHealthzServer(config *componentconfig.KubeSchedulerConfiguration) *http.Server {
|
||||
mux := http.NewServeMux()
|
||||
healthz.InstallHandler(mux)
|
||||
if config.HealthzBindAddress == config.MetricsBindAddress {
|
||||
configz.InstallHandler(mux)
|
||||
mux.Handle("/metrics", prometheus.Handler())
|
||||
}
|
||||
if config.EnableProfiling {
|
||||
mux.HandleFunc("/debug/pprof/", pprof.Index)
|
||||
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
|
||||
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
|
||||
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
|
||||
if config.EnableContentionProfiling {
|
||||
goruntime.SetBlockProfileRate(1)
|
||||
}
|
||||
}
|
||||
return &http.Server{
|
||||
Addr: config.HealthzBindAddress,
|
||||
Handler: mux,
|
||||
}
|
||||
}
|
||||
|
||||
// makeMetricsServer builds a metrics server from the config.
|
||||
func makeMetricsServer(config *componentconfig.KubeSchedulerConfiguration) *http.Server {
|
||||
mux := http.NewServeMux()
|
||||
configz.InstallHandler(mux)
|
||||
mux.Handle("/metrics", prometheus.Handler())
|
||||
if config.EnableProfiling {
|
||||
mux.HandleFunc("/debug/pprof/", pprof.Index)
|
||||
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
|
||||
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
|
||||
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
|
||||
if config.EnableContentionProfiling {
|
||||
goruntime.SetBlockProfileRate(1)
|
||||
}
|
||||
}
|
||||
return &http.Server{
|
||||
Addr: config.MetricsBindAddress,
|
||||
Handler: mux,
|
||||
}
|
||||
}
|
||||
|
||||
// createClients creates a kube client and an event client from the given config and masterOverride.
|
||||
// TODO remove masterOverride when CLI flags are removed.
|
||||
func createClients(config componentconfig.ClientConnectionConfiguration, masterOverride string) (clientset.Interface, clientset.Interface, v1core.EventsGetter, error) {
|
||||
if len(config.KubeConfigFile) == 0 && len(masterOverride) == 0 {
|
||||
glog.Warningf("Neither --kubeconfig nor --master was specified. Using default API client. This might not work.")
|
||||
}
|
||||
|
||||
// This creates a client, first loading any specified kubeconfig
|
||||
// file, and then overriding the Master flag, if non-empty.
|
||||
kubeConfig, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
|
||||
&clientcmd.ClientConfigLoadingRules{ExplicitPath: config.KubeConfigFile},
|
||||
&clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: masterOverride}}).ClientConfig()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
kubeConfig.AcceptContentTypes = config.AcceptContentTypes
|
||||
kubeConfig.ContentType = config.ContentType
|
||||
kubeConfig.QPS = config.QPS
|
||||
//TODO make config struct use int instead of int32?
|
||||
kubeConfig.Burst = int(config.Burst)
|
||||
|
||||
client, err := clientset.NewForConfig(restclient.AddUserAgent(kubeConfig, "scheduler"))
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
leaderElectionClient, err := clientset.NewForConfig(restclient.AddUserAgent(kubeConfig, "leader-election"))
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
eventClient, err := clientset.NewForConfig(kubeConfig)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return client, leaderElectionClient, eventClient.CoreV1(), nil
|
||||
}
|
||||
|
||||
// Run runs the SchedulerServer. This should never exit.
|
||||
func (s *SchedulerServer) Run(stop chan struct{}) error {
|
||||
// To help debugging, immediately log version
|
||||
glog.Infof("Version: %+v", version.Get())
|
||||
|
||||
// Build a scheduler config from the provided algorithm source.
|
||||
schedulerConfig, err := s.SchedulerConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create the scheduler.
|
||||
sched := scheduler.NewFromConfig(schedulerConfig)
|
||||
|
||||
// Prepare the event broadcaster.
|
||||
if !reflect.ValueOf(s.Broadcaster).IsNil() && !reflect.ValueOf(s.EventClient).IsNil() {
|
||||
s.Broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: s.EventClient.Events("")})
|
||||
}
|
||||
|
||||
// Start up the healthz server.
|
||||
if s.HealthzServer != nil {
|
||||
go wait.Until(func() {
|
||||
glog.Infof("starting healthz server on %v", s.HealthzServer.Addr)
|
||||
err := s.HealthzServer.ListenAndServe()
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("failed to start healthz server: %v", err))
|
||||
}
|
||||
}, 5*time.Second, stop)
|
||||
}
|
||||
|
||||
// Start up the metrics server.
|
||||
if s.MetricsServer != nil {
|
||||
go wait.Until(func() {
|
||||
glog.Infof("starting metrics server on %v", s.MetricsServer.Addr)
|
||||
err := s.MetricsServer.ListenAndServe()
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("failed to start metrics server: %v", err))
|
||||
}
|
||||
}, 5*time.Second, stop)
|
||||
}
|
||||
|
||||
// Start all informers.
|
||||
go s.PodInformer.Informer().Run(stop)
|
||||
s.InformerFactory.Start(stop)
|
||||
|
||||
// Wait for all caches to sync before scheduling.
|
||||
s.InformerFactory.WaitForCacheSync(stop)
|
||||
controller.WaitForCacheSync("scheduler", stop, s.PodInformer.Informer().HasSynced)
|
||||
|
||||
// Prepare a reusable run function.
|
||||
run := func(stopCh <-chan struct{}) {
|
||||
sched.Run()
|
||||
<-stopCh
|
||||
}
|
||||
|
||||
// If leader election is enabled, run via LeaderElector until done and exit.
|
||||
if s.LeaderElection != nil {
|
||||
s.LeaderElection.Callbacks = leaderelection.LeaderCallbacks{
|
||||
OnStartedLeading: run,
|
||||
OnStoppedLeading: func() {
|
||||
utilruntime.HandleError(fmt.Errorf("lost master"))
|
||||
},
|
||||
}
|
||||
leaderElector, err := leaderelection.NewLeaderElector(*s.LeaderElection)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't create leader elector: %v", err)
|
||||
}
|
||||
|
||||
leaderElector.Run()
|
||||
|
||||
return fmt.Errorf("lost lease")
|
||||
}
|
||||
|
||||
// Leader election is disabled, so run inline until done.
|
||||
run(stop)
|
||||
return fmt.Errorf("finished without leader elect")
|
||||
}
|
||||
|
||||
// SchedulerConfig creates the scheduler configuration. This is exposed for use
|
||||
// by tests.
|
||||
func (s *SchedulerServer) SchedulerConfig() (*scheduler.Config, error) {
|
||||
var storageClassInformer storageinformers.StorageClassInformer
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
storageClassInformer = s.InformerFactory.Storage().V1().StorageClasses()
|
||||
}
|
||||
|
||||
// Set up the configurator which can create schedulers from configs.
|
||||
configurator := factory.NewConfigFactory(
|
||||
s.SchedulerName,
|
||||
s.Client,
|
||||
s.InformerFactory.Core().V1().Nodes(),
|
||||
s.PodInformer,
|
||||
s.InformerFactory.Core().V1().PersistentVolumes(),
|
||||
s.InformerFactory.Core().V1().PersistentVolumeClaims(),
|
||||
s.InformerFactory.Core().V1().ReplicationControllers(),
|
||||
s.InformerFactory.Extensions().V1beta1().ReplicaSets(),
|
||||
s.InformerFactory.Apps().V1beta1().StatefulSets(),
|
||||
s.InformerFactory.Core().V1().Services(),
|
||||
s.InformerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||
storageClassInformer,
|
||||
s.HardPodAffinitySymmetricWeight,
|
||||
utilfeature.DefaultFeatureGate.Enabled(features.EnableEquivalenceClassCache),
|
||||
)
|
||||
|
||||
source := s.AlgorithmSource
|
||||
var config *scheduler.Config
|
||||
switch {
|
||||
case source.Provider != nil:
|
||||
// Create the config from a named algorithm provider.
|
||||
sc, err := configurator.CreateFromProvider(*source.Provider)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't create scheduler using provider %q: %v", *source.Provider, err)
|
||||
}
|
||||
config = sc
|
||||
case source.Policy != nil:
|
||||
// Create the config from a user specified policy source.
|
||||
policy := &schedulerapi.Policy{}
|
||||
switch {
|
||||
case source.Policy.File != nil:
|
||||
// Use a policy serialized in a file.
|
||||
policyFile := source.Policy.File.Path
|
||||
_, err := os.Stat(policyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("missing policy config file %s", policyFile)
|
||||
}
|
||||
data, err := ioutil.ReadFile(policyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't read policy config: %v", err)
|
||||
}
|
||||
err = runtime.DecodeInto(latestschedulerapi.Codec, []byte(data), policy)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid policy: %v", err)
|
||||
}
|
||||
case source.Policy.ConfigMap != nil:
|
||||
// Use a policy serialized in a config map value.
|
||||
policyRef := source.Policy.ConfigMap
|
||||
policyConfigMap, err := s.Client.CoreV1().ConfigMaps(policyRef.Namespace).Get(policyRef.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't get policy config map %s/%s: %v", policyRef.Namespace, policyRef.Name, err)
|
||||
}
|
||||
data, found := policyConfigMap.Data[componentconfig.SchedulerPolicyConfigMapKey]
|
||||
if !found {
|
||||
return nil, fmt.Errorf("missing policy config map value at key %q", componentconfig.SchedulerPolicyConfigMapKey)
|
||||
}
|
||||
err = runtime.DecodeInto(latestschedulerapi.Codec, []byte(data), policy)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid policy: %v", err)
|
||||
}
|
||||
}
|
||||
sc, err := configurator.CreateFromConfig(*policy)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't create scheduler from policy: %v", err)
|
||||
}
|
||||
config = sc
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported algorithm source: %v", source)
|
||||
}
|
||||
// Additional tweaks to the config produced by the configurator.
|
||||
config.Recorder = s.Recorder
|
||||
return config, nil
|
||||
}
|
47
vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/scheduler.go
generated
vendored
47
vendor/k8s.io/kubernetes/plugin/cmd/kube-scheduler/scheduler.go
generated
vendored
@ -1,47 +0,0 @@
|
||||
/*
|
||||
Copyright 2014 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 main
|
||||
|
||||
import (
|
||||
goflag "flag"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
utilflag "k8s.io/apiserver/pkg/util/flag"
|
||||
"k8s.io/apiserver/pkg/util/logs"
|
||||
_ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration
|
||||
_ "k8s.io/kubernetes/pkg/version/prometheus" // for version metric registration
|
||||
"k8s.io/kubernetes/plugin/cmd/kube-scheduler/app"
|
||||
)
|
||||
|
||||
func main() {
|
||||
command := app.NewSchedulerCommand()
|
||||
|
||||
// TODO: once we switch everything over to Cobra commands, we can go back to calling
|
||||
// utilflag.InitFlags() (by removing its pflag.Parse() call). For now, we have to set the
|
||||
// normalize func and add the go flag set by hand.
|
||||
pflag.CommandLine.SetNormalizeFunc(utilflag.WordSepNormalizeFunc)
|
||||
pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
|
||||
// utilflag.InitFlags()
|
||||
logs.InitLogs()
|
||||
defer logs.FlushLogs()
|
||||
|
||||
if err := command.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
8
vendor/k8s.io/kubernetes/plugin/pkg/admission/admit/BUILD
generated
vendored
8
vendor/k8s.io/kubernetes/plugin/pkg/admission/admit/BUILD
generated
vendored
@ -10,14 +10,16 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["admission.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/admit",
|
||||
deps = ["//vendor/k8s.io/apiserver/pkg/admission:go_default_library"],
|
||||
deps = [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/admit",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
|
28
vendor/k8s.io/kubernetes/plugin/pkg/admission/admit/admission.go
generated
vendored
28
vendor/k8s.io/kubernetes/plugin/pkg/admission/admit/admission.go
generated
vendored
@ -19,40 +19,46 @@ package admit
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "AlwaysAdmit"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("AlwaysAdmit", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewAlwaysAdmit(), nil
|
||||
})
|
||||
}
|
||||
|
||||
// AlwaysAdmit is an implementation of admission.Interface which always says yes to an admit request.
|
||||
// It is useful in tests and when using kubernetes in an open manner.
|
||||
type AlwaysAdmit struct{}
|
||||
// alwaysAdmit is an implementation of admission.Interface which always says yes to an admit request.
|
||||
type alwaysAdmit struct{}
|
||||
|
||||
var _ admission.MutationInterface = AlwaysAdmit{}
|
||||
var _ admission.ValidationInterface = AlwaysAdmit{}
|
||||
var _ admission.MutationInterface = alwaysAdmit{}
|
||||
var _ admission.ValidationInterface = alwaysAdmit{}
|
||||
|
||||
// Admit makes an admission decision based on the request attributes
|
||||
func (AlwaysAdmit) Admit(a admission.Attributes) (err error) {
|
||||
func (alwaysAdmit) Admit(a admission.Attributes) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate.
|
||||
func (AlwaysAdmit) Validate(a admission.Attributes) (err error) {
|
||||
func (alwaysAdmit) Validate(a admission.Attributes) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Handles returns true if this admission controller can handle the given operation
|
||||
// where operation can be one of CREATE, UPDATE, DELETE, or CONNECT
|
||||
func (AlwaysAdmit) Handles(operation admission.Operation) bool {
|
||||
func (alwaysAdmit) Handles(operation admission.Operation) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// NewAlwaysAdmit creates a new always admit admission handler
|
||||
func NewAlwaysAdmit() *AlwaysAdmit {
|
||||
return new(AlwaysAdmit)
|
||||
func NewAlwaysAdmit() admission.Interface {
|
||||
// DEPRECATED: AlwaysAdmit admit all admission request, it is no use.
|
||||
glog.Warningf("%s admission controller is deprecated. "+
|
||||
"Please remove this controller from your configuration files and scripts.", PluginName)
|
||||
return new(alwaysAdmit)
|
||||
}
|
||||
|
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/admit/admission_test.go
generated
vendored
4
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.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, nil))
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned from admission handler")
|
||||
}
|
||||
@ -33,7 +33,7 @@ func TestAdmissionNonNilAttribute(t *testing.T) {
|
||||
|
||||
func TestAdmissionNilAttribute(t *testing.T) {
|
||||
handler := NewAlwaysAdmit()
|
||||
err := handler.Admit(nil)
|
||||
err := handler.(*alwaysAdmit).Admit(nil)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error returned from admission handler")
|
||||
}
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages/BUILD
generated
vendored
@ -21,8 +21,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
|
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages/admission.go
generated
vendored
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/alwayspullimages/admission.go
generated
vendored
@ -33,9 +33,12 @@ import (
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "AlwaysPullImages"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("AlwaysPullImages", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewAlwaysPullImages(), nil
|
||||
})
|
||||
}
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/antiaffinity/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/antiaffinity/BUILD
generated
vendored
@ -24,8 +24,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/antiaffinity",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
|
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/antiaffinity/admission.go
generated
vendored
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/antiaffinity/admission.go
generated
vendored
@ -26,9 +26,11 @@ import (
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
)
|
||||
|
||||
const PluginName = "LimitPodHardAntiAffinityTopology"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("LimitPodHardAntiAffinityTopology", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewInterPodAntiAffinity(), nil
|
||||
})
|
||||
}
|
||||
|
7
vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/BUILD
generated
vendored
7
vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/BUILD
generated
vendored
@ -9,12 +9,11 @@ load(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/core/helper:go_default_library",
|
||||
"//plugin/pkg/scheduler/algorithm:go_default_library",
|
||||
"//pkg/scheduler/algorithm:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
@ -26,7 +25,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/core/helper:go_default_library",
|
||||
"//plugin/pkg/scheduler/algorithm: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",
|
||||
],
|
||||
|
7
vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/admission.go
generated
vendored
7
vendor/k8s.io/kubernetes/plugin/pkg/admission/defaulttolerationseconds/admission.go
generated
vendored
@ -25,9 +25,12 @@ import (
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "DefaultTolerationSeconds"
|
||||
|
||||
var (
|
||||
defaultNotReadyTolerationSeconds = flag.Int64("default-not-ready-toleration-seconds", 300,
|
||||
"Indicates the tolerationSeconds of the toleration for notReady:NoExecute"+
|
||||
@ -40,7 +43,7 @@ var (
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("DefaultTolerationSeconds", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewDefaultTolerationSeconds(), nil
|
||||
})
|
||||
}
|
||||
|
@ -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/plugin/pkg/scheduler/algorithm"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm"
|
||||
)
|
||||
|
||||
func TestForgivenessAdmission(t *testing.T) {
|
||||
|
8
vendor/k8s.io/kubernetes/plugin/pkg/admission/deny/BUILD
generated
vendored
8
vendor/k8s.io/kubernetes/plugin/pkg/admission/deny/BUILD
generated
vendored
@ -10,14 +10,16 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["admission.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/deny",
|
||||
deps = ["//vendor/k8s.io/apiserver/pkg/admission:go_default_library"],
|
||||
deps = [
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/deny",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
|
33
vendor/k8s.io/kubernetes/plugin/pkg/admission/deny/admission.go
generated
vendored
33
vendor/k8s.io/kubernetes/plugin/pkg/admission/deny/admission.go
generated
vendored
@ -20,40 +20,47 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "AlwaysDeny"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("AlwaysDeny", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewAlwaysDeny(), nil
|
||||
})
|
||||
}
|
||||
|
||||
// AlwaysDeny is an implementation of admission.Interface which always says no to an admission request.
|
||||
// It is useful in unit tests to force an operation to be forbidden.
|
||||
type AlwaysDeny struct{}
|
||||
// alwaysDeny is an implementation of admission.Interface which always says no to an admission request.
|
||||
type alwaysDeny struct{}
|
||||
|
||||
var _ admission.MutationInterface = AlwaysDeny{}
|
||||
var _ admission.ValidationInterface = AlwaysDeny{}
|
||||
var _ admission.MutationInterface = alwaysDeny{}
|
||||
var _ admission.ValidationInterface = alwaysDeny{}
|
||||
|
||||
// Admit makes an admission decision based on the request attributes.
|
||||
func (AlwaysDeny) Admit(a admission.Attributes) (err error) {
|
||||
return admission.NewForbidden(a, errors.New("Admission control is denying all modifications"))
|
||||
func (alwaysDeny) Admit(a admission.Attributes) (err error) {
|
||||
return admission.NewForbidden(a, errors.New("admission control is denying all modifications"))
|
||||
}
|
||||
|
||||
// Validate makes an admission decision based on the request attributes. It is NOT allowed to mutate.
|
||||
func (AlwaysDeny) Validate(a admission.Attributes) (err error) {
|
||||
return admission.NewForbidden(a, errors.New("Admission control is denying all modifications"))
|
||||
func (alwaysDeny) Validate(a admission.Attributes) (err error) {
|
||||
return admission.NewForbidden(a, errors.New("admission control is denying all modifications"))
|
||||
}
|
||||
|
||||
// Handles returns true if this admission controller can handle the given operation
|
||||
// where operation can be one of CREATE, UPDATE, DELETE, or CONNECT
|
||||
func (AlwaysDeny) Handles(operation admission.Operation) bool {
|
||||
func (alwaysDeny) Handles(operation admission.Operation) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// NewAlwaysDeny creates an always deny admission handler
|
||||
func NewAlwaysDeny() *AlwaysDeny {
|
||||
return new(AlwaysDeny)
|
||||
func NewAlwaysDeny() admission.Interface {
|
||||
// DEPRECATED: AlwaysDeny denys all admission request, it is no use.
|
||||
glog.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.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, nil))
|
||||
if err == nil {
|
||||
t.Error("Expected error returned from admission handler")
|
||||
}
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/BUILD
generated
vendored
@ -12,8 +12,7 @@ go_test(
|
||||
"admission_test.go",
|
||||
"cache_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//plugin/pkg/admission/eventratelimit/apis/eventratelimit:go_default_library",
|
||||
|
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/admission.go
generated
vendored
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/admission.go
generated
vendored
@ -26,9 +26,12 @@ import (
|
||||
"k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/validation"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "EventRateLimit"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("EventRateLimit",
|
||||
plugins.Register(PluginName,
|
||||
func(config io.Reader) (admission.Interface, error) {
|
||||
// load the configuration provided (if any)
|
||||
configuration, err := LoadConfiguration(config)
|
||||
|
@ -16,15 +16,16 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by conversion-gen. Do not edit it manually!
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
eventratelimit "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
@ -50,9 +50,8 @@ func (in *Configuration) DeepCopy() *Configuration {
|
||||
func (in *Configuration) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by defaulter-gen. Do not edit it manually!
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
|
@ -32,7 +32,6 @@ filegroup(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["validation_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/eventratelimit/apis/eventratelimit/validation",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = ["//plugin/pkg/admission/eventratelimit/apis/eventratelimit:go_default_library"],
|
||||
)
|
||||
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package eventratelimit
|
||||
|
||||
@ -50,9 +50,8 @@ func (in *Configuration) DeepCopy() *Configuration {
|
||||
func (in *Configuration) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/exec/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/exec/BUILD
generated
vendored
@ -24,8 +24,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/exec",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
|
58
vendor/k8s.io/kubernetes/plugin/pkg/admission/exec/admission.go
generated
vendored
58
vendor/k8s.io/kubernetes/plugin/pkg/admission/exec/admission.go
generated
vendored
@ -29,15 +29,23 @@ import (
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
)
|
||||
|
||||
const (
|
||||
// DenyEscalatingExec indicates name of admission plugin.
|
||||
DenyEscalatingExec = "DenyEscalatingExec"
|
||||
// DenyExecOnPrivileged indicates name of admission plugin.
|
||||
// Deprecated, should use DenyEscalatingExec instead.
|
||||
DenyExecOnPrivileged = "DenyExecOnPrivileged"
|
||||
)
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("DenyEscalatingExec", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(DenyEscalatingExec, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewDenyEscalatingExec(), nil
|
||||
})
|
||||
|
||||
// This is for legacy support of the DenyExecOnPrivileged admission controller. Most
|
||||
// of the time DenyEscalatingExec should be preferred.
|
||||
plugins.Register("DenyExecOnPrivileged", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(DenyExecOnPrivileged, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewDenyExecOnPrivileged(), nil
|
||||
})
|
||||
}
|
||||
@ -49,9 +57,10 @@ type DenyExec struct {
|
||||
client internalclientset.Interface
|
||||
|
||||
// these flags control which items will be checked to deny exec/attach
|
||||
hostIPC bool
|
||||
hostPID bool
|
||||
privileged bool
|
||||
hostNetwork bool
|
||||
hostIPC bool
|
||||
hostPID bool
|
||||
privileged bool
|
||||
}
|
||||
|
||||
var _ admission.ValidationInterface = &DenyExec{}
|
||||
@ -62,22 +71,24 @@ var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&DenyExec{})
|
||||
// using host based configurations.
|
||||
func NewDenyEscalatingExec() *DenyExec {
|
||||
return &DenyExec{
|
||||
Handler: admission.NewHandler(admission.Connect),
|
||||
hostIPC: true,
|
||||
hostPID: true,
|
||||
privileged: true,
|
||||
Handler: admission.NewHandler(admission.Connect),
|
||||
hostNetwork: true,
|
||||
hostIPC: true,
|
||||
hostPID: true,
|
||||
privileged: true,
|
||||
}
|
||||
}
|
||||
|
||||
// NewDenyExecOnPrivileged creates a new admission controller that is only checking the privileged
|
||||
// option. This is for legacy support of the DenyExecOnPrivileged admission controller. Most
|
||||
// of the time NewDenyEscalatingExec should be preferred.
|
||||
// option. This is for legacy support of the DenyExecOnPrivileged admission controller.
|
||||
// Most of the time NewDenyEscalatingExec should be preferred.
|
||||
func NewDenyExecOnPrivileged() *DenyExec {
|
||||
return &DenyExec{
|
||||
Handler: admission.NewHandler(admission.Connect),
|
||||
hostIPC: false,
|
||||
hostPID: false,
|
||||
privileged: true,
|
||||
Handler: admission.NewHandler(admission.Connect),
|
||||
hostNetwork: false,
|
||||
hostIPC: false,
|
||||
hostPID: false,
|
||||
privileged: true,
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,12 +107,19 @@ func (d *DenyExec) Validate(a admission.Attributes) (err error) {
|
||||
return admission.NewForbidden(a, err)
|
||||
}
|
||||
|
||||
if d.hostPID && pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.HostPID {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot exec into or attach to a container using host pid"))
|
||||
}
|
||||
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.hostIPC && pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.HostIPC {
|
||||
return admission.NewForbidden(a, fmt.Errorf("cannot exec into or attach to a container using host ipc"))
|
||||
if d.hostPID && securityContext.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.privileged && isPrivileged(pod) {
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/extendedresourcetoleration/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/extendedresourcetoleration/BUILD
generated
vendored
@ -17,8 +17,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/extendedresourcetoleration",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/core/helper:go_default_library",
|
||||
|
@ -27,9 +27,12 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "ExtendedResourceToleration"
|
||||
|
||||
// Register is called by the apiserver to register the plugin factory.
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("ExtendedResourceToleration", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return newExtendedResourceToleration(), nil
|
||||
})
|
||||
}
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/BUILD
generated
vendored
@ -25,8 +25,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["gc_admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/gc",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
|
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission.go
generated
vendored
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/gc/gc_admission.go
generated
vendored
@ -30,9 +30,12 @@ import (
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "OwnerReferencesPermissionEnforcement"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("OwnerReferencesPermissionEnforcement", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
// the pods/status endpoint is ignored by this plugin since old kubelets
|
||||
// corrupt them. the pod status strategy ensures status updates cannot mutate
|
||||
// ownerRef.
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/BUILD
generated
vendored
@ -37,8 +37,7 @@ go_test(
|
||||
"certs_test.go",
|
||||
"config_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/imagepolicy",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/imagepolicy/install:go_default_library",
|
||||
|
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/admission.go
generated
vendored
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/imagepolicy/admission.go
generated
vendored
@ -43,13 +43,16 @@ import (
|
||||
_ "k8s.io/kubernetes/pkg/apis/imagepolicy/install"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "ImagePolicyWebhook"
|
||||
|
||||
var (
|
||||
groupVersions = []schema.GroupVersion{v1alpha1.SchemeGroupVersion}
|
||||
)
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("ImagePolicyWebhook", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
newImagePolicyWebhook, err := NewImagePolicyWebhook(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/BUILD
generated
vendored
@ -43,8 +43,7 @@ go_test(
|
||||
"hawkular_test.go",
|
||||
"influxdb_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/initialresources",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||
|
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/admission.go
generated
vendored
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/initialresources/admission.go
generated
vendored
@ -42,12 +42,14 @@ const (
|
||||
samplesThreshold = 30
|
||||
week = 7 * 24 * time.Hour
|
||||
month = 30 * 24 * time.Hour
|
||||
// PluginName indicates name of admission plugin.
|
||||
PluginName = "InitialResources"
|
||||
)
|
||||
|
||||
// Register registers a plugin
|
||||
// WARNING: this feature is experimental and will definitely change.
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("InitialResources", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
// TODO: remove the usage of flags in favor of reading versioned configuration
|
||||
s, err := newDataSource(*source)
|
||||
if err != nil {
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/BUILD
generated
vendored
@ -33,8 +33,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/limitranger",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
|
16
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/admission.go
generated
vendored
16
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/admission.go
generated
vendored
@ -41,11 +41,13 @@ import (
|
||||
|
||||
const (
|
||||
limitRangerAnnotation = "kubernetes.io/limit-ranger"
|
||||
// PluginName indicates name of admission plugin.
|
||||
PluginName = "LimitRanger"
|
||||
)
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("LimitRanger", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewLimitRanger(&DefaultLimitRangerActions{})
|
||||
})
|
||||
}
|
||||
@ -113,6 +115,18 @@ func (l *LimitRanger) runLimitFunc(a admission.Attributes, limitFn func(limitRan
|
||||
}
|
||||
}
|
||||
|
||||
// ignore all objects marked for deletion
|
||||
oldObj := a.GetOldObject()
|
||||
if oldObj != nil {
|
||||
oldAccessor, err := meta.Accessor(oldObj)
|
||||
if err != nil {
|
||||
return admission.NewForbidden(a, err)
|
||||
}
|
||||
if oldAccessor.GetDeletionTimestamp() != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
items, err := l.GetLimitRanges(a)
|
||||
if err != nil {
|
||||
return err
|
||||
|
9
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/admission_test.go
generated
vendored
9
vendor/k8s.io/kubernetes/plugin/pkg/admission/limitranger/admission_test.go
generated
vendored
@ -733,6 +733,15 @@ func TestLimitRangerAdmitPod(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("Should have ignored calls to any subresource of pod %v", err)
|
||||
}
|
||||
|
||||
// a pod that is undergoing termination should never be blocked
|
||||
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))
|
||||
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
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision/BUILD
generated
vendored
@ -25,8 +25,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
|
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision/admission.go
generated
vendored
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision/admission.go
generated
vendored
@ -30,9 +30,12 @@ import (
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "NamespaceAutoProvision"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("NamespaceAutoProvision", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewProvision(), nil
|
||||
})
|
||||
}
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/exists/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/exists/BUILD
generated
vendored
@ -25,8 +25,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/namespace/exists",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
|
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/exists/admission.go
generated
vendored
5
vendor/k8s.io/kubernetes/plugin/pkg/admission/namespace/exists/admission.go
generated
vendored
@ -30,9 +30,12 @@ import (
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "NamespaceExists"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("NamespaceExists", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewExists(), nil
|
||||
})
|
||||
}
|
||||
|
8
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/BUILD
generated
vendored
8
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/BUILD
generated
vendored
@ -12,6 +12,7 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/noderestriction",
|
||||
deps = [
|
||||
"//pkg/api/pod:go_default_library",
|
||||
"//pkg/apis/authentication:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/policy:go_default_library",
|
||||
"//pkg/auth/nodeidentifier:go_default_library",
|
||||
@ -31,17 +32,20 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/noderestriction",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/authentication:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/policy:go_default_library",
|
||||
"//pkg/auth/nodeidentifier:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/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",
|
||||
],
|
||||
)
|
||||
|
||||
|
60
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission.go
generated
vendored
60
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission.go
generated
vendored
@ -27,6 +27,7 @@ import (
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
podutil "k8s.io/kubernetes/pkg/api/pod"
|
||||
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
|
||||
@ -53,6 +54,7 @@ func NewPlugin(nodeIdentifier nodeidentifier.NodeIdentifier) *nodePlugin {
|
||||
return &nodePlugin{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update, admission.Delete),
|
||||
nodeIdentifier: nodeIdentifier,
|
||||
features: utilfeature.DefaultFeatureGate,
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,6 +63,8 @@ type nodePlugin struct {
|
||||
*admission.Handler
|
||||
nodeIdentifier nodeidentifier.NodeIdentifier
|
||||
podsGetter coreinternalversion.PodsGetter
|
||||
// allows overriding for testing
|
||||
features utilfeature.FeatureGate
|
||||
}
|
||||
|
||||
var (
|
||||
@ -83,9 +87,10 @@ func (p *nodePlugin) ValidateInitialization() error {
|
||||
}
|
||||
|
||||
var (
|
||||
podResource = api.Resource("pods")
|
||||
nodeResource = api.Resource("nodes")
|
||||
pvcResource = api.Resource("persistentvolumeclaims")
|
||||
podResource = api.Resource("pods")
|
||||
nodeResource = api.Resource("nodes")
|
||||
pvcResource = api.Resource("persistentvolumeclaims")
|
||||
svcacctResource = api.Resource("serviceaccounts")
|
||||
)
|
||||
|
||||
func (c *nodePlugin) Admit(a admission.Attributes) error {
|
||||
@ -125,6 +130,12 @@ func (c *nodePlugin) Admit(a admission.Attributes) error {
|
||||
return admission.NewForbidden(a, fmt.Errorf("may only update PVC status"))
|
||||
}
|
||||
|
||||
case svcacctResource:
|
||||
if c.features.Enabled(features.TokenRequest) {
|
||||
return c.admitServiceAccount(nodeName, a)
|
||||
}
|
||||
return nil
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@ -256,7 +267,7 @@ func (c *nodePlugin) admitPodEviction(nodeName string, a admission.Attributes) e
|
||||
func (c *nodePlugin) admitPVCStatus(nodeName string, a admission.Attributes) error {
|
||||
switch a.GetOperation() {
|
||||
case admission.Update:
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) {
|
||||
if !c.features.Enabled(features.ExpandPersistentVolumes) {
|
||||
return admission.NewForbidden(a, fmt.Errorf("node %q may not update persistentvolumeclaim metadata", nodeName))
|
||||
}
|
||||
|
||||
@ -340,3 +351,44 @@ func (c *nodePlugin) admitNode(nodeName string, a admission.Attributes) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *nodePlugin) admitServiceAccount(nodeName string, a admission.Attributes) error {
|
||||
if a.GetOperation() != admission.Create {
|
||||
return nil
|
||||
}
|
||||
if a.GetSubresource() != "token" {
|
||||
return nil
|
||||
}
|
||||
tr, ok := a.GetObject().(*authenticationapi.TokenRequest)
|
||||
if !ok {
|
||||
return admission.NewForbidden(a, fmt.Errorf("unexpected type %T", a.GetObject()))
|
||||
}
|
||||
|
||||
// TokenRequests from a node must have a pod binding. That pod must be
|
||||
// scheduled on the node.
|
||||
ref := tr.Spec.BoundObjectRef
|
||||
if ref == nil ||
|
||||
ref.APIVersion != "v1" ||
|
||||
ref.Kind != "Pod" ||
|
||||
ref.Name == "" {
|
||||
return admission.NewForbidden(a, fmt.Errorf("node requested token not bound to a pod"))
|
||||
}
|
||||
if ref.UID == "" {
|
||||
return admission.NewForbidden(a, fmt.Errorf("node requested token with a pod binding without a uid"))
|
||||
}
|
||||
pod, err := c.podsGetter.Pods(a.GetNamespace()).Get(ref.Name, v1.GetOptions{})
|
||||
if errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return admission.NewForbidden(a, err)
|
||||
}
|
||||
if ref.UID != pod.UID {
|
||||
return admission.NewForbidden(a, fmt.Errorf("the UID in the bound object reference (%s) does not match the UID in record (%s). The object might have been deleted and then recreated", ref.UID, pod.UID))
|
||||
}
|
||||
if pod.Spec.NodeName != nodeName {
|
||||
return admission.NewForbidden(a, fmt.Errorf("node requested token bound to a pod scheduled on a different node"))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
82
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission_test.go
generated
vendored
82
vendor/k8s.io/kubernetes/plugin/pkg/admission/noderestriction/admission_test.go
generated
vendored
@ -21,19 +21,37 @@ import (
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
policyapi "k8s.io/kubernetes/pkg/apis/policy"
|
||||
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
coreinternalversion "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
var (
|
||||
trEnabledFeature = utilfeature.NewFeatureGate()
|
||||
trDisabledFeature = utilfeature.NewFeatureGate()
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := trEnabledFeature.Add(map[utilfeature.Feature]utilfeature.FeatureSpec{features.TokenRequest: {Default: true}}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := trDisabledFeature.Add(map[utilfeature.Feature]utilfeature.FeatureSpec{features.TokenRequest: {Default: false}}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func makeTestPod(namespace, name, node string, mirror bool) *api.Pod {
|
||||
pod := &api.Pod{}
|
||||
pod.Namespace = namespace
|
||||
pod.UID = types.UID("pod-uid")
|
||||
pod.Name = name
|
||||
pod.Spec.NodeName = node
|
||||
if mirror {
|
||||
@ -48,6 +66,23 @@ func makeTestPodEviction(name string) *policy.Eviction {
|
||||
return eviction
|
||||
}
|
||||
|
||||
func makeTokenRequest(podname string, poduid types.UID) *authenticationapi.TokenRequest {
|
||||
tr := &authenticationapi.TokenRequest{
|
||||
Spec: authenticationapi.TokenRequestSpec{
|
||||
Audiences: []string{"foo"},
|
||||
},
|
||||
}
|
||||
if podname != "" {
|
||||
tr.Spec.BoundObjectRef = &authenticationapi.BoundObjectReference{
|
||||
Kind: "Pod",
|
||||
APIVersion: "v1",
|
||||
Name: podname,
|
||||
UID: poduid,
|
||||
}
|
||||
}
|
||||
return tr
|
||||
}
|
||||
|
||||
func Test_nodePlugin_Admit(t *testing.T) {
|
||||
var (
|
||||
mynode = &user.DefaultInfo{Name: "system:node:mynode", Groups: []string{"system:nodes"}}
|
||||
@ -82,11 +117,14 @@ func Test_nodePlugin_Admit(t *testing.T) {
|
||||
|
||||
podResource = api.Resource("pods").WithVersion("v1")
|
||||
podKind = api.Kind("Pod").WithVersion("v1")
|
||||
evictionKind = policyapi.Kind("Eviction").WithVersion("v1beta1")
|
||||
evictionKind = policy.Kind("Eviction").WithVersion("v1beta1")
|
||||
|
||||
nodeResource = api.Resource("nodes").WithVersion("v1")
|
||||
nodeKind = api.Kind("Node").WithVersion("v1")
|
||||
|
||||
svcacctResource = api.Resource("serviceaccounts").WithVersion("v1")
|
||||
tokenrequestKind = api.Kind("TokenRequest").WithVersion("v1")
|
||||
|
||||
noExistingPods = fake.NewSimpleClientset().Core()
|
||||
existingPods = fake.NewSimpleClientset(mymirrorpod, othermirrorpod, unboundmirrorpod, mypod, otherpod, unboundpod).Core()
|
||||
)
|
||||
@ -107,6 +145,7 @@ func Test_nodePlugin_Admit(t *testing.T) {
|
||||
name string
|
||||
podsGetter coreinternalversion.PodsGetter
|
||||
attributes admission.Attributes
|
||||
features utilfeature.FeatureGate
|
||||
err string
|
||||
}{
|
||||
// Mirror pods bound to us
|
||||
@ -654,6 +693,42 @@ func Test_nodePlugin_Admit(t *testing.T) {
|
||||
err: "cannot modify node",
|
||||
},
|
||||
|
||||
// Service accounts
|
||||
{
|
||||
name: "forbid create of unbound token",
|
||||
podsGetter: noExistingPods,
|
||||
features: trEnabledFeature,
|
||||
attributes: admission.NewAttributesRecord(makeTokenRequest("", ""), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, mynode),
|
||||
err: "not bound to a pod",
|
||||
},
|
||||
{
|
||||
name: "forbid create of token bound to nonexistant pod",
|
||||
podsGetter: noExistingPods,
|
||||
features: trEnabledFeature,
|
||||
attributes: admission.NewAttributesRecord(makeTokenRequest("nopod", "someuid"), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, mynode),
|
||||
err: "not found",
|
||||
},
|
||||
{
|
||||
name: "forbid create of token bound to pod without uid",
|
||||
podsGetter: existingPods,
|
||||
features: trEnabledFeature,
|
||||
attributes: admission.NewAttributesRecord(makeTokenRequest(mypod.Name, ""), nil, tokenrequestKind, "ns", "mysa", svcacctResource, "token", admission.Create, mynode),
|
||||
err: "pod binding without a uid",
|
||||
},
|
||||
{
|
||||
name: "forbid create of token bound to pod scheduled on another node",
|
||||
podsGetter: existingPods,
|
||||
features: trEnabledFeature,
|
||||
attributes: admission.NewAttributesRecord(makeTokenRequest(otherpod.Name, otherpod.UID), nil, tokenrequestKind, otherpod.Namespace, "mysa", svcacctResource, "token", admission.Create, mynode),
|
||||
err: "pod scheduled on a different node",
|
||||
},
|
||||
{
|
||||
name: "allow create of token bound to pod scheduled this node",
|
||||
podsGetter: existingPods,
|
||||
features: trEnabledFeature,
|
||||
attributes: admission.NewAttributesRecord(makeTokenRequest(mypod.Name, mypod.UID), nil, tokenrequestKind, mypod.Namespace, "mysa", svcacctResource, "token", admission.Create, mynode),
|
||||
},
|
||||
|
||||
// Unrelated objects
|
||||
{
|
||||
name: "allow create of unrelated object",
|
||||
@ -715,6 +790,9 @@ func Test_nodePlugin_Admit(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := NewPlugin(nodeidentifier.NewDefaultNodeIdentifier())
|
||||
if tt.features != nil {
|
||||
c.features = tt.features
|
||||
}
|
||||
c.podsGetter = tt.podsGetter
|
||||
err := c.Admit(tt.attributes)
|
||||
if (err == nil) != (len(tt.err) == 0) {
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/BUILD
generated
vendored
@ -29,8 +29,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/cloudprovider/providers/aws:go_default_library",
|
||||
|
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/admission.go
generated
vendored
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/label/admission.go
generated
vendored
@ -33,9 +33,11 @@ import (
|
||||
vol "k8s.io/kubernetes/pkg/volume"
|
||||
)
|
||||
|
||||
const PluginName = "PersistentVolumeLabel"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("PersistentVolumeLabel", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
persistentVolumeLabelAdmission := NewPersistentVolumeLabel()
|
||||
return persistentVolumeLabelAdmission, nil
|
||||
})
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/BUILD
generated
vendored
@ -9,8 +9,7 @@ load(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/admission.go
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/persistentvolume/resize/admission.go
generated
vendored
@ -161,5 +161,8 @@ func (pvcr *persistentVolumeClaimResize) checkVolumePlugin(pv *api.PersistentVol
|
||||
return true
|
||||
}
|
||||
|
||||
if pv.Spec.AzureFile != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -1,111 +0,0 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package pvcprotection
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
admission "k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/util/feature"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
||||
const (
|
||||
// PluginName is the name of this admission controller plugin
|
||||
PluginName = "PVCProtection"
|
||||
)
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
plugin := newPlugin()
|
||||
return plugin, nil
|
||||
})
|
||||
}
|
||||
|
||||
// pvcProtectionPlugin holds state for and implements the admission plugin.
|
||||
type pvcProtectionPlugin struct {
|
||||
*admission.Handler
|
||||
lister corelisters.PersistentVolumeClaimLister
|
||||
}
|
||||
|
||||
var _ admission.Interface = &pvcProtectionPlugin{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&pvcProtectionPlugin{})
|
||||
|
||||
// newPlugin creates a new admission plugin.
|
||||
func newPlugin() *pvcProtectionPlugin {
|
||||
return &pvcProtectionPlugin{
|
||||
Handler: admission.NewHandler(admission.Create),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *pvcProtectionPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
informer := f.Core().InternalVersion().PersistentVolumeClaims()
|
||||
c.lister = informer.Lister()
|
||||
c.SetReadyFunc(informer.Informer().HasSynced)
|
||||
}
|
||||
|
||||
// ValidateInitialization ensures lister is set.
|
||||
func (c *pvcProtectionPlugin) ValidateInitialization() error {
|
||||
if c.lister == nil {
|
||||
return fmt.Errorf("missing lister")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Admit sets finalizer on all PVCs. The finalizer is removed by
|
||||
// PVCProtectionController when it's not referenced by any pod.
|
||||
//
|
||||
// This prevents users from deleting a PVC that's used by a running pod.
|
||||
func (c *pvcProtectionPlugin) Admit(a admission.Attributes) error {
|
||||
if !feature.DefaultFeatureGate.Enabled(features.PVCProtection) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if a.GetResource().GroupResource() != api.Resource("persistentvolumeclaims") {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(a.GetSubresource()) != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
pvc, ok := a.GetObject().(*api.PersistentVolumeClaim)
|
||||
// if we can't convert then we don't handle this object so just return
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, f := range pvc.Finalizers {
|
||||
if f == volumeutil.PVCProtectionFinalizer {
|
||||
// Finalizer is already present, nothing to do
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
glog.V(4).Infof("adding PVC protection finalizer to %s/%s", pvc.Namespace, pvc.Name)
|
||||
pvc.Finalizers = append(pvc.Finalizers, volumeutil.PVCProtectionFinalizer)
|
||||
return nil
|
||||
}
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/podnodeselector/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/podnodeselector/BUILD
generated
vendored
@ -29,8 +29,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/podnodeselector",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
|
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/podnodeselector/admission.go
generated
vendored
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/podnodeselector/admission.go
generated
vendored
@ -40,9 +40,11 @@ import (
|
||||
// node selectors labels to namespaces
|
||||
var NamespaceNodeSelectors = []string{"scheduler.alpha.kubernetes.io/node-selector"}
|
||||
|
||||
const PluginName = "PodNodeSelector"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("PodNodeSelector", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
// TODO move this to a versioned configuration file format.
|
||||
pluginConfig := readConfig(config)
|
||||
plugin := NewPodNodeSelector(pluginConfig.PodNodeSelectorPluginConfig)
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/BUILD
generated
vendored
@ -9,8 +9,7 @@ load(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/podpreset",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/settings:go_default_library",
|
||||
|
8
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/admission.go
generated
vendored
8
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/admission.go
generated
vendored
@ -41,12 +41,12 @@ import (
|
||||
|
||||
const (
|
||||
annotationPrefix = "podpreset.admission.kubernetes.io"
|
||||
pluginName = "PodPreset"
|
||||
PluginName = "PodPreset"
|
||||
)
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register(pluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewPlugin(), nil
|
||||
})
|
||||
}
|
||||
@ -72,10 +72,10 @@ func NewPlugin() *podPresetPlugin {
|
||||
|
||||
func (plugin *podPresetPlugin) ValidateInitialization() error {
|
||||
if plugin.client == nil {
|
||||
return fmt.Errorf("%s requires a client", pluginName)
|
||||
return fmt.Errorf("%s requires a client", PluginName)
|
||||
}
|
||||
if plugin.lister == nil {
|
||||
return fmt.Errorf("%s requires a lister", pluginName)
|
||||
return fmt.Errorf("%s requires a lister", PluginName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
57
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/admission_test.go
generated
vendored
57
vendor/k8s.io/kubernetes/plugin/pkg/admission/podpreset/admission_test.go
generated
vendored
@ -20,7 +20,6 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
kadmission "k8s.io/apiserver/pkg/admission"
|
||||
@ -426,16 +425,16 @@ func TestAdmitConflictWithDifferentNamespaceShouldDoNothing(t *testing.T) {
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "othernamespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Selector: v1.LabelSelector{
|
||||
MatchExpressions: []v1.LabelSelectorRequirement{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "security",
|
||||
Operator: v1.LabelSelectorOpIn,
|
||||
Operator: metav1.LabelSelectorOpIn,
|
||||
Values: []string{"S2"},
|
||||
},
|
||||
},
|
||||
@ -472,16 +471,16 @@ func TestAdmitConflictWithNonMatchingLabelsShouldNotError(t *testing.T) {
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Selector: v1.LabelSelector{
|
||||
MatchExpressions: []v1.LabelSelectorRequirement{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "security",
|
||||
Operator: v1.LabelSelectorOpIn,
|
||||
Operator: metav1.LabelSelectorOpIn,
|
||||
Values: []string{"S3"},
|
||||
},
|
||||
},
|
||||
@ -519,16 +518,16 @@ func TestAdmitConflictShouldNotModifyPod(t *testing.T) {
|
||||
origPod := *pod
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Selector: v1.LabelSelector{
|
||||
MatchExpressions: []v1.LabelSelectorRequirement{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "security",
|
||||
Operator: v1.LabelSelectorOpIn,
|
||||
Operator: metav1.LabelSelectorOpIn,
|
||||
Values: []string{"S2"},
|
||||
},
|
||||
},
|
||||
@ -568,16 +567,16 @@ func TestAdmit(t *testing.T) {
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Selector: v1.LabelSelector{
|
||||
MatchExpressions: []v1.LabelSelectorRequirement{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "security",
|
||||
Operator: v1.LabelSelectorOpIn,
|
||||
Operator: metav1.LabelSelectorOpIn,
|
||||
Values: []string{"S2"},
|
||||
},
|
||||
},
|
||||
@ -628,16 +627,16 @@ func TestAdmitMirrorPod(t *testing.T) {
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Selector: v1.LabelSelector{
|
||||
MatchExpressions: []v1.LabelSelectorRequirement{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "security",
|
||||
Operator: v1.LabelSelectorOpIn,
|
||||
Operator: metav1.LabelSelectorOpIn,
|
||||
Values: []string{"S2"},
|
||||
},
|
||||
},
|
||||
@ -698,16 +697,16 @@ func TestExclusionNoAdmit(t *testing.T) {
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Selector: v1.LabelSelector{
|
||||
MatchExpressions: []v1.LabelSelectorRequirement{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "security",
|
||||
Operator: v1.LabelSelectorOpIn,
|
||||
Operator: metav1.LabelSelectorOpIn,
|
||||
Values: []string{"S2"},
|
||||
},
|
||||
},
|
||||
@ -762,16 +761,16 @@ func TestAdmitEmptyPodNamespace(t *testing.T) {
|
||||
}
|
||||
|
||||
pip := &settings.PodPreset{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "hello",
|
||||
Namespace: "different", // (pod will be submitted to namespace 'namespace')
|
||||
},
|
||||
Spec: settings.PodPresetSpec{
|
||||
Selector: v1.LabelSelector{
|
||||
MatchExpressions: []v1.LabelSelectorRequirement{
|
||||
Selector: metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "security",
|
||||
Operator: v1.LabelSelectorOpIn,
|
||||
Operator: metav1.LabelSelectorOpIn,
|
||||
Values: []string{"S2"},
|
||||
},
|
||||
},
|
||||
|
7
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/BUILD
generated
vendored
7
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/BUILD
generated
vendored
@ -9,17 +9,16 @@ load(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction",
|
||||
library = ":go_default_library",
|
||||
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/util/tolerations:go_default_library",
|
||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library",
|
||||
"//plugin/pkg/scheduler/algorithm: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",
|
||||
@ -43,12 +42,12 @@ go_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/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",
|
||||
"//plugin/pkg/scheduler/algorithm: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",
|
||||
|
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/admission.go
generated
vendored
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/admission.go
generated
vendored
@ -35,14 +35,16 @@ import (
|
||||
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"
|
||||
"k8s.io/kubernetes/pkg/util/tolerations"
|
||||
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
||||
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
||||
)
|
||||
|
||||
const PluginName = "PodTolerationRestriction"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("PodTolerationRestriction", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
pluginConfig, err := loadConfiguration(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -30,9 +30,9 @@ import (
|
||||
"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/util/tolerations"
|
||||
pluginapi "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
||||
"k8s.io/kubernetes/plugin/pkg/scheduler/algorithm"
|
||||
)
|
||||
|
||||
// TestPodAdmission verifies various scenarios involving pod/namespace tolerations
|
||||
|
@ -16,17 +16,18 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by conversion-gen. Do not edit it manually!
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
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"
|
||||
podtolerationrestriction "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
@ -60,7 +60,6 @@ func (in *Configuration) DeepCopy() *Configuration {
|
||||
func (in *Configuration) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by defaulter-gen. Do not edit it manually!
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
|
@ -33,8 +33,7 @@ filegroup(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["validation_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction/validation",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//plugin/pkg/admission/podtolerationrestriction/apis/podtolerationrestriction:go_default_library",
|
||||
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package podtolerationrestriction
|
||||
|
||||
@ -60,7 +60,6 @@ func (in *Configuration) DeepCopy() *Configuration {
|
||||
func (in *Configuration) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/BUILD
generated
vendored
@ -9,14 +9,14 @@ load(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/priority",
|
||||
library = ":go_default_library",
|
||||
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/controller:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/scheduler/api: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",
|
||||
@ -36,6 +36,8 @@ go_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",
|
||||
"//pkg/scheduler/api:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
|
123
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission.go
generated
vendored
123
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission.go
generated
vendored
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package admission
|
||||
package priority
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -31,69 +31,59 @@ import (
|
||||
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"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
|
||||
)
|
||||
|
||||
const (
|
||||
pluginName = "Priority"
|
||||
|
||||
// HighestUserDefinablePriority is the highest priority for user defined priority classes. Priority values larger than 1 billion are reserved for Kubernetes system use.
|
||||
HighestUserDefinablePriority = 1000000000
|
||||
// SystemCriticalPriority is the beginning of the range of priority values for critical system components.
|
||||
SystemCriticalPriority = 2 * HighestUserDefinablePriority
|
||||
// PluginName indicates name of admission plugin.
|
||||
PluginName = "Priority"
|
||||
)
|
||||
|
||||
// SystemPriorityClasses defines special priority classes which are used by system critical pods that should not be preempted by workload pods.
|
||||
var SystemPriorityClasses = map[string]int32{
|
||||
"system-cluster-critical": SystemCriticalPriority,
|
||||
"system-node-critical": SystemCriticalPriority + 1000,
|
||||
}
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register(pluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewPlugin(), nil
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return newPlugin(), nil
|
||||
})
|
||||
}
|
||||
|
||||
// PriorityPlugin is an implementation of admission.Interface.
|
||||
type PriorityPlugin struct {
|
||||
// priorityPlugin is an implementation of admission.Interface.
|
||||
type priorityPlugin struct {
|
||||
*admission.Handler
|
||||
client internalclientset.Interface
|
||||
lister schedulinglisters.PriorityClassLister
|
||||
// globalDefaultPriority caches the value of global default priority class.
|
||||
globalDefaultPriority *int32
|
||||
}
|
||||
|
||||
var _ admission.MutationInterface = &PriorityPlugin{}
|
||||
var _ admission.ValidationInterface = &PriorityPlugin{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&PriorityPlugin{})
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&PriorityPlugin{})
|
||||
var _ admission.MutationInterface = &priorityPlugin{}
|
||||
var _ admission.ValidationInterface = &priorityPlugin{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&priorityPlugin{})
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeClientSet(&priorityPlugin{})
|
||||
|
||||
// NewPlugin creates a new priority admission plugin.
|
||||
func NewPlugin() *PriorityPlugin {
|
||||
return &PriorityPlugin{
|
||||
func newPlugin() *priorityPlugin {
|
||||
return &priorityPlugin{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update, admission.Delete),
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateInitialization implements the InitializationValidator interface.
|
||||
func (p *PriorityPlugin) ValidateInitialization() error {
|
||||
func (p *priorityPlugin) ValidateInitialization() error {
|
||||
if p.client == nil {
|
||||
return fmt.Errorf("%s requires a client", pluginName)
|
||||
return fmt.Errorf("%s requires a client", PluginName)
|
||||
}
|
||||
if p.lister == nil {
|
||||
return fmt.Errorf("%s requires a lister", pluginName)
|
||||
return fmt.Errorf("%s requires a lister", PluginName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetInternalKubeClientSet implements the WantsInternalKubeClientSet interface.
|
||||
func (p *PriorityPlugin) SetInternalKubeClientSet(client internalclientset.Interface) {
|
||||
func (p *priorityPlugin) SetInternalKubeClientSet(client internalclientset.Interface) {
|
||||
p.client = client
|
||||
}
|
||||
|
||||
// SetInternalKubeInformerFactory implements the WantsInternalKubeInformerFactory interface.
|
||||
func (p *PriorityPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
func (p *priorityPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
priorityInformer := f.Scheduling().InternalVersion().PriorityClasses()
|
||||
p.lister = priorityInformer.Lister()
|
||||
p.SetReadyFunc(priorityInformer.Informer().HasSynced)
|
||||
@ -106,7 +96,7 @@ var (
|
||||
|
||||
// Admit checks Pods and admits or rejects them. It also resolves the priority of pods based on their PriorityClass.
|
||||
// Note that pod validation mechanism prevents update of a pod priority.
|
||||
func (p *PriorityPlugin) Admit(a admission.Attributes) error {
|
||||
func (p *priorityPlugin) Admit(a admission.Attributes) error {
|
||||
operation := a.GetOperation()
|
||||
// Ignore all calls to subresources
|
||||
if len(a.GetSubresource()) != 0 {
|
||||
@ -126,7 +116,7 @@ func (p *PriorityPlugin) Admit(a admission.Attributes) error {
|
||||
}
|
||||
|
||||
// Validate checks PriorityClasses and admits or rejects them.
|
||||
func (p *PriorityPlugin) Validate(a admission.Attributes) error {
|
||||
func (p *priorityPlugin) Validate(a admission.Attributes) error {
|
||||
operation := a.GetOperation()
|
||||
// Ignore all calls to subresources
|
||||
if len(a.GetSubresource()) != 0 {
|
||||
@ -138,10 +128,6 @@ func (p *PriorityPlugin) Validate(a admission.Attributes) error {
|
||||
if operation == admission.Create || operation == admission.Update {
|
||||
return p.validatePriorityClass(a)
|
||||
}
|
||||
if operation == admission.Delete {
|
||||
p.invalidateCachedDefaultPriority()
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
|
||||
default:
|
||||
@ -150,21 +136,26 @@ func (p *PriorityPlugin) Validate(a admission.Attributes) error {
|
||||
}
|
||||
|
||||
// admitPod makes sure a new pod does not set spec.Priority field. It also makes sure that the PriorityClassName exists if it is provided and resolves the pod priority from the PriorityClassName.
|
||||
func (p *PriorityPlugin) admitPod(a admission.Attributes) error {
|
||||
func (p *priorityPlugin) admitPod(a admission.Attributes) error {
|
||||
operation := a.GetOperation()
|
||||
pod, ok := a.GetObject().(*api.Pod)
|
||||
if !ok {
|
||||
return errors.NewBadRequest("resource was marked with kind Pod but was unable to be converted")
|
||||
}
|
||||
if _, isMirrorPod := pod.Annotations[api.MirrorPodAnnotationKey]; isMirrorPod {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Make sure that the client has not set `priority` at the time of pod creation.
|
||||
if operation == admission.Create && pod.Spec.Priority != nil {
|
||||
return admission.NewForbidden(a, fmt.Errorf("the integer value of priority must not be provided in pod spec. Priority admission controller populates the value from the given PriorityClass name"))
|
||||
}
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.PodPriority) {
|
||||
var priority int32
|
||||
// TODO: @ravig - This is for backwards compatibility to ensure that critical pods with annotations just work fine.
|
||||
// Remove when no longer needed.
|
||||
if len(pod.Spec.PriorityClassName) == 0 &&
|
||||
utilfeature.DefaultFeatureGate.Enabled(features.ExperimentalCriticalPodAnnotation) &&
|
||||
kubelettypes.IsCritical(a.GetNamespace(), pod.Annotations) {
|
||||
pod.Spec.PriorityClassName = schedulerapi.SystemClusterCritical
|
||||
}
|
||||
if len(pod.Spec.PriorityClassName) == 0 {
|
||||
var err error
|
||||
priority, err = p.getDefaultPriority()
|
||||
@ -173,16 +164,19 @@ func (p *PriorityPlugin) admitPod(a admission.Attributes) error {
|
||||
}
|
||||
} else {
|
||||
// First try to resolve by system priority classes.
|
||||
priority, ok = SystemPriorityClasses[pod.Spec.PriorityClassName]
|
||||
priority, ok = schedulerapi.SystemPriorityClasses[pod.Spec.PriorityClassName]
|
||||
if !ok {
|
||||
// Now that we didn't find any system priority, try resolving by user defined priority classes.
|
||||
pc, err := p.lister.Get(pod.Spec.PriorityClassName)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get default priority class %s: %v", pod.Spec.PriorityClassName, err)
|
||||
}
|
||||
if pc == nil {
|
||||
return admission.NewForbidden(a, fmt.Errorf("no PriorityClass with name %v was found", pod.Spec.PriorityClassName))
|
||||
if errors.IsNotFound(err) {
|
||||
return admission.NewForbidden(a, fmt.Errorf("no PriorityClass with name %v was found", pod.Spec.PriorityClassName))
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to get PriorityClass with name %s: %v", pod.Spec.PriorityClassName, err)
|
||||
}
|
||||
|
||||
priority = pc.Value
|
||||
}
|
||||
}
|
||||
@ -192,16 +186,16 @@ func (p *PriorityPlugin) admitPod(a admission.Attributes) error {
|
||||
}
|
||||
|
||||
// validatePriorityClass ensures that the value field is not larger than the highest user definable priority. If the GlobalDefault is set, it ensures that there is no other PriorityClass whose GlobalDefault is set.
|
||||
func (p *PriorityPlugin) validatePriorityClass(a admission.Attributes) error {
|
||||
func (p *priorityPlugin) validatePriorityClass(a admission.Attributes) error {
|
||||
operation := a.GetOperation()
|
||||
pc, ok := a.GetObject().(*scheduling.PriorityClass)
|
||||
if !ok {
|
||||
return errors.NewBadRequest("resource was marked with kind PriorityClass but was unable to be converted")
|
||||
}
|
||||
if pc.Value > HighestUserDefinablePriority {
|
||||
return admission.NewForbidden(a, fmt.Errorf("maximum allowed value of a user defined priority is %v", HighestUserDefinablePriority))
|
||||
if pc.Value > schedulerapi.HighestUserDefinablePriority {
|
||||
return admission.NewForbidden(a, fmt.Errorf("maximum allowed value of a user defined priority is %v", schedulerapi.HighestUserDefinablePriority))
|
||||
}
|
||||
if _, ok := SystemPriorityClasses[pc.Name]; ok {
|
||||
if _, ok := schedulerapi.SystemPriorityClasses[pc.Name]; ok {
|
||||
return admission.NewForbidden(a, fmt.Errorf("the name of the priority class is a reserved name for system use only: %v", pc.Name))
|
||||
}
|
||||
// If the new PriorityClass tries to be the default priority, make sure that no other priority class is marked as default.
|
||||
@ -217,43 +211,34 @@ func (p *PriorityPlugin) validatePriorityClass(a admission.Attributes) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
// We conservatively invalidate our cache of global default priority upon any changes to any of the existing classes or creation of a new class.
|
||||
p.invalidateCachedDefaultPriority()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PriorityPlugin) getDefaultPriorityClass() (*scheduling.PriorityClass, error) {
|
||||
func (p *priorityPlugin) getDefaultPriorityClass() (*scheduling.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
|
||||
for _, pci := range list {
|
||||
if pci.GlobalDefault {
|
||||
return pci, nil
|
||||
if defaultPC == nil || defaultPC.Value > pci.Value {
|
||||
defaultPC = pci
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
return defaultPC, nil
|
||||
}
|
||||
|
||||
func (p *PriorityPlugin) getDefaultPriority() (int32, error) {
|
||||
// If global default priority is cached, return it.
|
||||
if p.globalDefaultPriority != nil {
|
||||
return *p.globalDefaultPriority, nil
|
||||
}
|
||||
func (p *priorityPlugin) getDefaultPriority() (int32, error) {
|
||||
dpc, err := p.getDefaultPriorityClass()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
priority := int32(scheduling.DefaultPriorityWhenNoDefaultClassExists)
|
||||
if dpc != nil {
|
||||
priority = dpc.Value
|
||||
return dpc.Value, nil
|
||||
}
|
||||
// Cache the value.
|
||||
p.globalDefaultPriority = &priority
|
||||
return priority, nil
|
||||
}
|
||||
|
||||
// invalidateCachedDefaultPriority sets global default priority to nil to indicate that it should be looked up again.
|
||||
func (p *PriorityPlugin) invalidateCachedDefaultPriority() {
|
||||
p.globalDefaultPriority = nil
|
||||
return int32(scheduling.DefaultPriorityWhenNoDefaultClassExists), nil
|
||||
}
|
||||
|
99
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission_test.go
generated
vendored
99
vendor/k8s.io/kubernetes/plugin/pkg/admission/priority/admission_test.go
generated
vendored
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package admission
|
||||
package priority
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -30,9 +30,10 @@ import (
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
|
||||
)
|
||||
|
||||
func addPriorityClasses(ctrl *PriorityPlugin, priorityClasses []*scheduling.PriorityClass) {
|
||||
func addPriorityClasses(ctrl *priorityPlugin, priorityClasses []*scheduling.PriorityClass) {
|
||||
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
|
||||
ctrl.SetInternalKubeInformerFactory(informerFactory)
|
||||
// First add the existing classes to the cache.
|
||||
@ -82,7 +83,7 @@ func TestPriorityClassAdmission(t *testing.T) {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "toohighclass",
|
||||
},
|
||||
Value: HighestUserDefinablePriority + 1,
|
||||
Value: schedulerapi.HighestUserDefinablePriority + 1,
|
||||
Description: "Just a test priority class",
|
||||
}
|
||||
|
||||
@ -91,9 +92,9 @@ func TestPriorityClassAdmission(t *testing.T) {
|
||||
Kind: "PriorityClass",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "system-cluster-critical",
|
||||
Name: schedulerapi.SystemClusterCritical,
|
||||
},
|
||||
Value: HighestUserDefinablePriority + 1,
|
||||
Value: schedulerapi.HighestUserDefinablePriority + 1,
|
||||
Description: "Name conflicts with system priority class names",
|
||||
}
|
||||
|
||||
@ -132,7 +133,7 @@ func TestPriorityClassAdmission(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
glog.V(4).Infof("starting test %q", test.name)
|
||||
|
||||
ctrl := NewPlugin()
|
||||
ctrl := newPlugin()
|
||||
// Add existing priority classes.
|
||||
addPriorityClasses(ctrl, test.existingClasses)
|
||||
// Now add the new class.
|
||||
@ -189,6 +190,14 @@ func TestDefaultPriority(t *testing.T) {
|
||||
expectedDefaultBefore: scheduling.DefaultPriorityWhenNoDefaultClassExists,
|
||||
expectedDefaultAfter: defaultClass1.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, nil),
|
||||
expectedDefaultBefore: defaultClass1.Value,
|
||||
expectedDefaultAfter: defaultClass2.Value,
|
||||
},
|
||||
{
|
||||
name: "delete default priority class",
|
||||
classesBefore: []*scheduling.PriorityClass{defaultClass1},
|
||||
@ -209,7 +218,7 @@ func TestDefaultPriority(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
glog.V(4).Infof("starting test %q", test.name)
|
||||
ctrl := NewPlugin()
|
||||
ctrl := newPlugin()
|
||||
addPriorityClasses(ctrl, test.classesBefore)
|
||||
defaultPriority, err := ctrl.getDefaultPriority()
|
||||
if err != nil {
|
||||
@ -307,6 +316,22 @@ func TestPodAdmission(t *testing.T) {
|
||||
Name: "pod-w-system-priority",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: containerName,
|
||||
},
|
||||
},
|
||||
PriorityClassName: schedulerapi.SystemClusterCritical,
|
||||
},
|
||||
},
|
||||
// pod[5]: mirror Pod with a system priority class name
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mirror-pod-w-system-priority",
|
||||
Namespace: "namespace",
|
||||
Annotations: map[string]string{api.MirrorPodAnnotationKey: ""},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
@ -316,9 +341,44 @@ func TestPodAdmission(t *testing.T) {
|
||||
PriorityClassName: "system-cluster-critical",
|
||||
},
|
||||
},
|
||||
// pod[6]: mirror Pod with integer value of priority
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mirror-pod-w-integer-priority",
|
||||
Namespace: "namespace",
|
||||
Annotations: map[string]string{api.MirrorPodAnnotationKey: ""},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: containerName,
|
||||
},
|
||||
},
|
||||
PriorityClassName: "default1",
|
||||
Priority: &intPriority,
|
||||
},
|
||||
},
|
||||
// pod[7]: Pod with a critical priority annotation. This needs to be automatically assigned
|
||||
// system-cluster-critical
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod-w-system-priority",
|
||||
Namespace: "kube-system",
|
||||
Annotations: map[string]string{"scheduler.alpha.kubernetes.io/critical-pod": ""},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: containerName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
// Enable PodPriority feature gate.
|
||||
utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.PodPriority))
|
||||
// Enable ExperimentalCriticalPodAnnotation feature gate.
|
||||
utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%s=true", features.ExperimentalCriticalPodAnnotation))
|
||||
tests := []struct {
|
||||
name string
|
||||
existingClasses []*scheduling.PriorityClass
|
||||
@ -361,7 +421,7 @@ func TestPodAdmission(t *testing.T) {
|
||||
"pod with a system priority class",
|
||||
[]*scheduling.PriorityClass{},
|
||||
*pods[4],
|
||||
SystemCriticalPriority,
|
||||
schedulerapi.SystemCriticalPriority,
|
||||
false,
|
||||
},
|
||||
{
|
||||
@ -378,12 +438,33 @@ func TestPodAdmission(t *testing.T) {
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"mirror pod with system priority class",
|
||||
[]*scheduling.PriorityClass{},
|
||||
*pods[5],
|
||||
schedulerapi.SystemCriticalPriority,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"mirror pod with integer priority",
|
||||
[]*scheduling.PriorityClass{},
|
||||
*pods[6],
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pod with critical pod annotation",
|
||||
[]*scheduling.PriorityClass{},
|
||||
*pods[7],
|
||||
schedulerapi.SystemCriticalPriority,
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
glog.V(4).Infof("starting test %q", test.name)
|
||||
|
||||
ctrl := NewPlugin()
|
||||
ctrl := newPlugin()
|
||||
// Add existing priority classes.
|
||||
addPriorityClasses(ctrl, test.existingClasses)
|
||||
|
||||
|
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/BUILD
generated
vendored
@ -52,13 +52,13 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/resourcequota",
|
||||
library = ":go_default_library",
|
||||
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",
|
||||
"//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library",
|
||||
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
|
||||
|
12
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission.go
generated
vendored
12
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission.go
generated
vendored
@ -27,14 +27,16 @@ import (
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
"k8s.io/kubernetes/pkg/quota"
|
||||
"k8s.io/kubernetes/pkg/quota/generic"
|
||||
resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
resourcequotaapiv1alpha1 "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/v1alpha1"
|
||||
"k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/validation"
|
||||
)
|
||||
|
||||
const PluginName = "ResourceQuota"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("ResourceQuota",
|
||||
plugins.Register(PluginName,
|
||||
func(config io.Reader) (admission.Interface, error) {
|
||||
// load the configuration provided (if any)
|
||||
configuration, err := LoadConfiguration(config)
|
||||
@ -49,10 +51,6 @@ func Register(plugins *admission.Plugins) {
|
||||
}
|
||||
return NewResourceQuota(configuration, 5, make(chan struct{}))
|
||||
})
|
||||
|
||||
// add our config types
|
||||
resourcequotaapi.AddToScheme(plugins.ConfigScheme)
|
||||
resourcequotaapiv1alpha1.AddToScheme(plugins.ConfigScheme)
|
||||
}
|
||||
|
||||
// QuotaAdmission implements an admission controller that can enforce quota constraints
|
||||
@ -103,7 +101,7 @@ func (a *QuotaAdmission) SetInternalKubeInformerFactory(f informers.SharedInform
|
||||
|
||||
func (a *QuotaAdmission) SetQuotaConfiguration(c quota.Configuration) {
|
||||
a.quotaConfiguration = c
|
||||
a.evaluator = NewQuotaEvaluator(a.quotaAccessor, a.quotaConfiguration, nil, a.config, a.numEvaluators, a.stopCh)
|
||||
a.evaluator = NewQuotaEvaluator(a.quotaAccessor, a.quotaConfiguration.IgnoredResources(), generic.NewRegistry(a.quotaConfiguration.Evaluators()), nil, a.config, a.numEvaluators, a.stopCh)
|
||||
}
|
||||
|
||||
// ValidateInitialization ensures an authorizer is set.
|
||||
|
49
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission_test.go
generated
vendored
49
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/admission_test.go
generated
vendored
@ -35,6 +35,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/quota/generic"
|
||||
"k8s.io/kubernetes/pkg/quota/install"
|
||||
resourcequotaapi "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
)
|
||||
@ -133,7 +134,7 @@ func TestAdmissionIgnoresDelete(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -169,7 +170,7 @@ func TestAdmissionIgnoresSubresources(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -214,7 +215,7 @@ func TestAdmitBelowQuotaLimit(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -298,7 +299,7 @@ func TestAdmitHandlesOldObjects(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -405,7 +406,7 @@ func TestAdmitHandlesNegativePVCUpdates(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -472,7 +473,7 @@ func TestAdmitHandlesPVCUpdates(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -571,7 +572,7 @@ func TestAdmitHandlesCreatingUpdates(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -666,7 +667,7 @@ func TestAdmitExceedQuotaLimit(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -711,7 +712,7 @@ func TestAdmitEnforceQuotaConstraints(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -724,12 +725,6 @@ func TestAdmitEnforceQuotaConstraints(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Errorf("Expected an error because the pod does not specify a memory limit")
|
||||
}
|
||||
// verify the requests and limits are actually valid (in this case, we fail because the limits < requests)
|
||||
newPod = validPod("not-allowed-pod", 1, getResourceRequirements(getResourceList("200m", "2Gi"), getResourceList("100m", "1Gi")))
|
||||
err = handler.Validate(admission.NewAttributesRecord(newPod, nil, api.Kind("Pod").WithVersion("version"), newPod.Namespace, newPod.Name, api.Resource("pods").WithVersion("version"), "", admission.Create, nil))
|
||||
if err == nil {
|
||||
t.Errorf("Expected an error because the pod does not specify a memory limit")
|
||||
}
|
||||
}
|
||||
|
||||
// TestAdmitPodInNamespaceWithoutQuota ensures that if a namespace has no quota, that a pod can get in
|
||||
@ -766,7 +761,7 @@ func TestAdmitPodInNamespaceWithoutQuota(t *testing.T) {
|
||||
quotaAccessor.liveLookupCache = liveLookupCache
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -833,7 +828,7 @@ func TestAdmitBelowTerminatingQuotaLimit(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -939,7 +934,7 @@ func TestAdmitBelowBestEffortQuotaLimit(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1032,7 +1027,7 @@ func TestAdmitBestEffortQuotaLimitIgnoresBurstable(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1118,7 +1113,7 @@ func TestAdmissionSetsMissingNamespace(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1164,7 +1159,7 @@ func TestAdmitRejectsNegativeUsage(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1211,7 +1206,7 @@ func TestAdmitWhenUnrelatedResourceExceedsQuota(t *testing.T) {
|
||||
quotaAccessor.lister = informerFactory.Core().InternalVersion().ResourceQuotas().Lister()
|
||||
config := &resourcequotaapi.Configuration{}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1248,7 +1243,7 @@ func TestAdmitLimitedResourceNoQuota(t *testing.T) {
|
||||
},
|
||||
}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1282,7 +1277,7 @@ func TestAdmitLimitedResourceNoQuotaIgnoresNonMatchingResources(t *testing.T) {
|
||||
},
|
||||
}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1329,7 +1324,7 @@ func TestAdmitLimitedResourceWithQuota(t *testing.T) {
|
||||
},
|
||||
}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1388,7 +1383,7 @@ func TestAdmitLimitedResourceWithMultipleQuota(t *testing.T) {
|
||||
},
|
||||
}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
@ -1437,7 +1432,7 @@ func TestAdmitLimitedResourceWithQuotaThatDoesNotCover(t *testing.T) {
|
||||
},
|
||||
}
|
||||
quotaConfiguration := install.NewQuotaConfigurationForAdmission()
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration, nil, config, 5, stopCh)
|
||||
evaluator := NewQuotaEvaluator(quotaAccessor, quotaConfiguration.IgnoredResources(), generic.NewRegistry(quotaConfiguration.Evaluators()), nil, config, 5, stopCh)
|
||||
|
||||
handler := &QuotaAdmission{
|
||||
Handler: admission.NewHandler(admission.Create, admission.Update),
|
||||
|
@ -16,15 +16,16 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by conversion-gen. Do not edit it manually!
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
resourcequota "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
@ -52,9 +52,8 @@ func (in *Configuration) DeepCopy() *Configuration {
|
||||
func (in *Configuration) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by defaulter-gen. Do not edit it manually!
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
|
@ -32,7 +32,6 @@ filegroup(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["validation_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/resourcequota/apis/resourcequota/validation",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = ["//plugin/pkg/admission/resourcequota/apis/resourcequota:go_default_library"],
|
||||
)
|
||||
|
@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package resourcequota
|
||||
|
||||
@ -52,9 +52,8 @@ func (in *Configuration) DeepCopy() *Configuration {
|
||||
func (in *Configuration) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
|
11
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/controller.go
generated
vendored
11
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/controller.go
generated
vendored
@ -52,8 +52,7 @@ type quotaEvaluator struct {
|
||||
// lockAcquisitionFunc acquires any required locks and returns a cleanup method to defer
|
||||
lockAcquisitionFunc func([]api.ResourceQuota) func()
|
||||
|
||||
// how quota was configured
|
||||
quotaConfiguration quota.Configuration
|
||||
ignoredResources map[schema.GroupResource]struct{}
|
||||
|
||||
// registry that knows how to measure usage for objects
|
||||
registry quota.Registry
|
||||
@ -110,7 +109,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, quotaConfiguration quota.Configuration, 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([]api.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{}
|
||||
@ -120,8 +119,8 @@ func NewQuotaEvaluator(quotaAccessor QuotaAccessor, quotaConfiguration quota.Con
|
||||
quotaAccessor: quotaAccessor,
|
||||
lockAcquisitionFunc: lockAcquisitionFunc,
|
||||
|
||||
quotaConfiguration: quotaConfiguration,
|
||||
registry: generic.NewRegistry(quotaConfiguration.Evaluators()),
|
||||
ignoredResources: ignoredResources,
|
||||
registry: quotaRegistry,
|
||||
|
||||
queue: workqueue.NewNamed("admission_quota_controller"),
|
||||
work: map[string][]*admissionWaiter{},
|
||||
@ -524,7 +523,7 @@ func (e *quotaEvaluator) Evaluate(a admission.Attributes) error {
|
||||
// is this resource ignored?
|
||||
gvr := a.GetResource()
|
||||
gr := gvr.GroupResource()
|
||||
if _, ok := e.quotaConfiguration.IgnoredResources()[gr]; ok {
|
||||
if _, ok := e.ignoredResources[gr]; ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
2
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/resource_access.go
generated
vendored
2
vendor/k8s.io/kubernetes/plugin/pkg/admission/resourcequota/resource_access.go
generated
vendored
@ -48,7 +48,7 @@ type quotaAccessor struct {
|
||||
lister corelisters.ResourceQuotaLister
|
||||
|
||||
// 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.
|
||||
// This lets us handle the case of latent caches, by looking up actual results for a namespace on cache miss/no results.
|
||||
// We track the lookup result here so that for repeated requests, we don't look it up very often.
|
||||
liveLookupCache *lru.Cache
|
||||
liveTTL time.Duration
|
||||
|
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/BUILD
generated
vendored
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/BUILD
generated
vendored
@ -13,6 +13,7 @@ go_library(
|
||||
deps = [
|
||||
"//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/extensions/internalversion:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
@ -34,13 +35,13 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/core/helper: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/controller:go_default_library",
|
||||
"//pkg/security/apparmor:go_default_library",
|
||||
@ -56,6 +57,7 @@ go_test(
|
||||
"//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",
|
||||
],
|
||||
)
|
||||
|
||||
|
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/OWNERS
generated
vendored
Normal file
6
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/OWNERS
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
approvers:
|
||||
- tallclair
|
||||
- liggitt
|
||||
reviewers:
|
||||
- pweil-
|
||||
- php-coder
|
55
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission.go
generated
vendored
55
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission.go
generated
vendored
@ -33,6 +33,7 @@ import (
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
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"
|
||||
extensionslisters "k8s.io/kubernetes/pkg/client/listers/extensions/internalversion"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
@ -122,8 +123,8 @@ func (c *PodSecurityPolicyPlugin) Admit(a admission.Attributes) error {
|
||||
|
||||
pod := a.GetObject().(*api.Pod)
|
||||
|
||||
// compute the context
|
||||
allowedPod, pspName, validationErrs, err := c.computeSecurityContext(a, pod, true)
|
||||
// compute the context. Mutation is allowed. ValidatedPSPAnnotation is not taken into account.
|
||||
allowedPod, pspName, validationErrs, err := c.computeSecurityContext(a, pod, true, "")
|
||||
if err != nil {
|
||||
return admission.NewForbidden(a, err)
|
||||
}
|
||||
@ -152,8 +153,8 @@ func (c *PodSecurityPolicyPlugin) Validate(a admission.Attributes) error {
|
||||
|
||||
pod := a.GetObject().(*api.Pod)
|
||||
|
||||
// compute the context. Mutation is not allowed.
|
||||
allowedPod, _, validationErrs, err := c.computeSecurityContext(a, pod, false)
|
||||
// compute the context. Mutation is not allowed. ValidatedPSPAnnotation is used as a hint to gain same speed-up.
|
||||
allowedPod, _, validationErrs, err := c.computeSecurityContext(a, pod, false, pod.ObjectMeta.Annotations[psputil.ValidatedPSPAnnotation])
|
||||
if err != nil {
|
||||
return admission.NewForbidden(a, err)
|
||||
}
|
||||
@ -193,8 +194,9 @@ func shouldIgnore(a admission.Attributes) (bool, error) {
|
||||
|
||||
// computeSecurityContext derives a valid security context while trying to avoid any changes to the given pod. I.e.
|
||||
// if there is a matching policy with the same security context as given, it will be reused. If there is no
|
||||
// matching policy the returned pod will be nil and the pspName empty.
|
||||
func (c *PodSecurityPolicyPlugin) computeSecurityContext(a admission.Attributes, pod *api.Pod, specMutationAllowed bool) (*api.Pod, string, field.ErrorList, error) {
|
||||
// matching policy the returned pod will be nil and the pspName empty. validatedPSPHint is the validated psp name
|
||||
// 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)
|
||||
var saInfo user.Info
|
||||
@ -213,9 +215,18 @@ func (c *PodSecurityPolicyPlugin) computeSecurityContext(a admission.Attributes,
|
||||
return pod, "", nil, nil
|
||||
}
|
||||
|
||||
// sort by name to make order deterministic
|
||||
// sort policies by name to make order deterministic
|
||||
// If mutation is not allowed and validatedPSPHint is provided, check the validated policy first.
|
||||
// TODO(liggitt): add priority field to allow admins to bucket differently
|
||||
sort.SliceStable(policies, func(i, j int) bool {
|
||||
if !specMutationAllowed {
|
||||
if policies[i].Name == validatedPSPHint {
|
||||
return true
|
||||
}
|
||||
if policies[j].Name == validatedPSPHint {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return strings.Compare(policies[i].Name, policies[j].Name) < 0
|
||||
})
|
||||
|
||||
@ -244,7 +255,6 @@ func (c *PodSecurityPolicyPlugin) computeSecurityContext(a admission.Attributes,
|
||||
}
|
||||
|
||||
// the entire pod validated
|
||||
|
||||
mutated := !apiequality.Semantic.DeepEqual(pod, podCopy)
|
||||
if mutated && !specMutationAllowed {
|
||||
continue
|
||||
@ -287,35 +297,28 @@ func (c *PodSecurityPolicyPlugin) computeSecurityContext(a admission.Attributes,
|
||||
func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.Path) field.ErrorList {
|
||||
errs := field.ErrorList{}
|
||||
|
||||
psc, pscAnnotations, err := provider.CreatePodSecurityContext(pod)
|
||||
err := provider.DefaultPodSecurityContext(pod)
|
||||
if err != nil {
|
||||
errs = append(errs, field.Invalid(field.NewPath("spec", "securityContext"), pod.Spec.SecurityContext, err.Error()))
|
||||
}
|
||||
pod.Spec.SecurityContext = psc
|
||||
pod.Annotations = pscAnnotations
|
||||
|
||||
errs = append(errs, provider.ValidatePodSecurityContext(pod, field.NewPath("spec", "securityContext"))...)
|
||||
errs = append(errs, provider.ValidatePod(pod, field.NewPath("spec", "securityContext"))...)
|
||||
|
||||
for i := range pod.Spec.InitContainers {
|
||||
sc, scAnnotations, err := provider.CreateContainerSecurityContext(pod, &pod.Spec.InitContainers[i])
|
||||
err := provider.DefaultContainerSecurityContext(pod, &pod.Spec.InitContainers[i])
|
||||
if err != nil {
|
||||
errs = append(errs, field.Invalid(field.NewPath("spec", "initContainers").Index(i).Child("securityContext"), "", err.Error()))
|
||||
continue
|
||||
}
|
||||
pod.Spec.InitContainers[i].SecurityContext = sc
|
||||
pod.Annotations = scAnnotations
|
||||
errs = append(errs, provider.ValidateContainerSecurityContext(pod, &pod.Spec.InitContainers[i], field.NewPath("spec", "initContainers").Index(i).Child("securityContext"))...)
|
||||
}
|
||||
|
||||
for i := range pod.Spec.Containers {
|
||||
sc, scAnnotations, err := provider.CreateContainerSecurityContext(pod, &pod.Spec.Containers[i])
|
||||
err := provider.DefaultContainerSecurityContext(pod, &pod.Spec.Containers[i])
|
||||
if err != nil {
|
||||
errs = append(errs, field.Invalid(field.NewPath("spec", "containers").Index(i).Child("securityContext"), "", err.Error()))
|
||||
continue
|
||||
}
|
||||
|
||||
pod.Spec.Containers[i].SecurityContext = sc
|
||||
pod.Annotations = scAnnotations
|
||||
errs = append(errs, provider.ValidateContainerSecurityContext(pod, &pod.Spec.Containers[i], field.NewPath("spec", "containers").Index(i).Child("securityContext"))...)
|
||||
}
|
||||
|
||||
@ -352,11 +355,19 @@ func isAuthorizedForPolicy(user, sa user.Info, namespace, policyName string, aut
|
||||
}
|
||||
|
||||
// authorizedForPolicy returns true if info is authorized to perform the "use" verb on the policy resource.
|
||||
// TODO: check against only the policy group when PSP will be completely moved out of the extensions
|
||||
func authorizedForPolicy(info user.Info, namespace string, policyName string, authz authorizer.Authorizer) bool {
|
||||
// Check against extensions API group for backward compatibility
|
||||
return authorizedForPolicyInAPIGroup(info, namespace, policyName, policy.GroupName, authz) ||
|
||||
authorizedForPolicyInAPIGroup(info, namespace, policyName, extensions.GroupName, authz)
|
||||
}
|
||||
|
||||
// authorizedForPolicyInAPIGroup returns true if info is authorized to perform the "use" verb on the policy resource in the specified API group.
|
||||
func authorizedForPolicyInAPIGroup(info user.Info, namespace, policyName, apiGroupName string, authz authorizer.Authorizer) bool {
|
||||
if info == nil {
|
||||
return false
|
||||
}
|
||||
attr := buildAttributes(info, namespace, policyName)
|
||||
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)
|
||||
@ -365,14 +376,14 @@ func authorizedForPolicy(info user.Info, namespace string, policyName string, au
|
||||
}
|
||||
|
||||
// buildAttributes builds an attributes record for a SAR based on the user info and policy.
|
||||
func buildAttributes(info user.Info, namespace string, policyName string) authorizer.Attributes {
|
||||
func buildAttributes(info user.Info, namespace, policyName, apiGroupName string) authorizer.Attributes {
|
||||
// check against the namespace that the pod is being created in to allow per-namespace PSP grants.
|
||||
attr := authorizer.AttributesRecord{
|
||||
User: info,
|
||||
Verb: "use",
|
||||
Namespace: namespace,
|
||||
Name: policyName,
|
||||
APIGroup: extensions.GroupName,
|
||||
APIGroup: apiGroupName,
|
||||
Resource: "podsecuritypolicies",
|
||||
ResourceRequest: true,
|
||||
}
|
||||
|
209
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go
generated
vendored
209
vendor/k8s.io/kubernetes/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go
generated
vendored
@ -32,10 +32,12 @@ import (
|
||||
"k8s.io/apiserver/pkg/authentication/serviceaccount"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
kapi "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/security/apparmor"
|
||||
@ -65,11 +67,16 @@ func NewTestAdmission(psps []*extensions.PodSecurityPolicy, authz authorizer.Aut
|
||||
}
|
||||
}
|
||||
|
||||
// TestAlwaysAllowedAuthorizer is a testing struct for testing that fulfills the authorizer interface.
|
||||
// TestAuthorizer is a testing struct for testing that fulfills the authorizer interface.
|
||||
type TestAuthorizer struct {
|
||||
// usernameToNamespaceToAllowedPSPs contains the map of allowed PSPs.
|
||||
// if nil, all PSPs are allowed.
|
||||
usernameToNamespaceToAllowedPSPs map[string]map[string]map[string]bool
|
||||
// allowedAPIGroupName specifies an API Group name that contains PSP resources.
|
||||
// In order to be authorized, AttributesRecord must have this group name.
|
||||
// When empty, API Group name isn't taken into account.
|
||||
// TODO: remove this when PSP will be completely moved out of the extensions and we'll lookup only in "policy" group.
|
||||
allowedAPIGroupName string
|
||||
}
|
||||
|
||||
func (t *TestAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
|
||||
@ -78,7 +85,8 @@ func (t *TestAuthorizer) Authorize(a authorizer.Attributes) (authorized authoriz
|
||||
}
|
||||
allowedInNamespace := t.usernameToNamespaceToAllowedPSPs[a.GetUser().GetName()][a.GetNamespace()][a.GetName()]
|
||||
allowedClusterWide := t.usernameToNamespaceToAllowedPSPs[a.GetUser().GetName()][""][a.GetName()]
|
||||
if allowedInNamespace || allowedClusterWide {
|
||||
allowedAPIGroup := len(t.allowedAPIGroupName) == 0 || a.GetAPIGroup() == t.allowedAPIGroupName
|
||||
if allowedAPIGroup && (allowedInNamespace || allowedClusterWide) {
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
}
|
||||
return authorizer.DecisionNoOpinion, "", nil
|
||||
@ -344,15 +352,20 @@ func TestAdmitPreferNonmutating(t *testing.T) {
|
||||
gcChangedPod.OwnerReferences = []metav1.OwnerReference{{Kind: "Foo", Name: "bar"}}
|
||||
gcChangedPod.Finalizers = []string{"foo"}
|
||||
|
||||
podWithAnnotation := unprivilegedRunAsAnyPod.DeepCopy()
|
||||
podWithAnnotation.ObjectMeta.Annotations = map[string]string{
|
||||
// "mutating2" is lexicographically behind "mutating1", so "mutating1" should be
|
||||
// chosen because it's the canonical PSP order.
|
||||
psputil.ValidatedPSPAnnotation: mutating2.Name,
|
||||
}
|
||||
|
||||
tests := map[string]struct {
|
||||
operation kadmission.Operation
|
||||
pod *kapi.Pod
|
||||
podBeforeUpdate *kapi.Pod
|
||||
psps []*extensions.PodSecurityPolicy
|
||||
shouldPassAdmit bool
|
||||
shouldPassValidate bool
|
||||
expectMutation bool
|
||||
expectedPodUser *int64
|
||||
expectedContainerUser *int64
|
||||
expectedPSP string
|
||||
}{
|
||||
@ -360,10 +373,8 @@ func TestAdmitPreferNonmutating(t *testing.T) {
|
||||
operation: kadmission.Create,
|
||||
pod: unprivilegedRunAsAnyPod.DeepCopy(),
|
||||
psps: []*extensions.PodSecurityPolicy{privilegedPSP},
|
||||
shouldPassAdmit: true,
|
||||
shouldPassValidate: true,
|
||||
expectMutation: false,
|
||||
expectedPodUser: nil,
|
||||
expectedContainerUser: nil,
|
||||
expectedPSP: privilegedPSP.Name,
|
||||
},
|
||||
@ -371,10 +382,8 @@ func TestAdmitPreferNonmutating(t *testing.T) {
|
||||
operation: kadmission.Create,
|
||||
pod: unprivilegedRunAsAnyPod.DeepCopy(),
|
||||
psps: []*extensions.PodSecurityPolicy{mutating2, mutating1, privilegedPSP},
|
||||
shouldPassAdmit: true,
|
||||
shouldPassValidate: true,
|
||||
expectMutation: false,
|
||||
expectedPodUser: nil,
|
||||
expectedContainerUser: nil,
|
||||
expectedPSP: privilegedPSP.Name,
|
||||
},
|
||||
@ -382,10 +391,17 @@ func TestAdmitPreferNonmutating(t *testing.T) {
|
||||
operation: kadmission.Create,
|
||||
pod: unprivilegedRunAsAnyPod.DeepCopy(),
|
||||
psps: []*extensions.PodSecurityPolicy{mutating2, mutating1},
|
||||
shouldPassAdmit: true,
|
||||
shouldPassValidate: true,
|
||||
expectMutation: true,
|
||||
expectedPodUser: nil,
|
||||
expectedContainerUser: &mutating1.Spec.RunAsUser.Ranges[0].Min,
|
||||
expectedPSP: mutating1.Name,
|
||||
},
|
||||
"pod should use deterministic mutating PSP on create even if ValidatedPSPAnnotation is set": {
|
||||
operation: kadmission.Create,
|
||||
pod: podWithAnnotation,
|
||||
psps: []*extensions.PodSecurityPolicy{mutating2, mutating1},
|
||||
shouldPassValidate: true,
|
||||
expectMutation: true,
|
||||
expectedContainerUser: &mutating1.Spec.RunAsUser.Ranges[0].Min,
|
||||
expectedPSP: mutating1.Name,
|
||||
},
|
||||
@ -394,10 +410,8 @@ func TestAdmitPreferNonmutating(t *testing.T) {
|
||||
pod: changedPodWithSC.DeepCopy(),
|
||||
podBeforeUpdate: podWithSC.DeepCopy(),
|
||||
psps: []*extensions.PodSecurityPolicy{mutating2, mutating1, privilegedPSP},
|
||||
shouldPassAdmit: true,
|
||||
shouldPassValidate: true,
|
||||
expectMutation: false,
|
||||
expectedPodUser: nil,
|
||||
expectedContainerUser: nil,
|
||||
expectedPSP: privilegedPSP.Name,
|
||||
},
|
||||
@ -406,10 +420,8 @@ func TestAdmitPreferNonmutating(t *testing.T) {
|
||||
pod: changedPod.DeepCopy(),
|
||||
podBeforeUpdate: unprivilegedRunAsAnyPod.DeepCopy(),
|
||||
psps: []*extensions.PodSecurityPolicy{mutating2, mutating1},
|
||||
shouldPassAdmit: true,
|
||||
shouldPassValidate: false,
|
||||
expectMutation: false,
|
||||
expectedPodUser: nil,
|
||||
expectedContainerUser: nil,
|
||||
expectedPSP: "",
|
||||
},
|
||||
@ -418,10 +430,8 @@ func TestAdmitPreferNonmutating(t *testing.T) {
|
||||
pod: unprivilegedRunAsAnyPod.DeepCopy(),
|
||||
podBeforeUpdate: unprivilegedRunAsAnyPod.DeepCopy(),
|
||||
psps: []*extensions.PodSecurityPolicy{mutating2, mutating1},
|
||||
shouldPassAdmit: true,
|
||||
shouldPassValidate: true,
|
||||
expectMutation: false,
|
||||
expectedPodUser: nil,
|
||||
expectedContainerUser: nil,
|
||||
expectedPSP: "",
|
||||
},
|
||||
@ -430,38 +440,32 @@ func TestAdmitPreferNonmutating(t *testing.T) {
|
||||
pod: gcChangedPod.DeepCopy(),
|
||||
podBeforeUpdate: unprivilegedRunAsAnyPod.DeepCopy(),
|
||||
psps: []*extensions.PodSecurityPolicy{mutating2, mutating1},
|
||||
shouldPassAdmit: true,
|
||||
shouldPassValidate: true,
|
||||
expectMutation: false,
|
||||
expectedPodUser: nil,
|
||||
expectedContainerUser: nil,
|
||||
expectedPSP: "",
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range tests {
|
||||
testPSPAdmitAdvanced(k, v.operation, v.psps, nil, &user.DefaultInfo{}, v.pod, v.podBeforeUpdate, v.shouldPassAdmit, v.shouldPassValidate, v.expectMutation, v.expectedPSP, t)
|
||||
testPSPAdmitAdvanced(k, v.operation, v.psps, nil, &user.DefaultInfo{}, v.pod, v.podBeforeUpdate, true, v.shouldPassValidate, v.expectMutation, v.expectedPSP, t)
|
||||
|
||||
if v.shouldPassAdmit {
|
||||
actualPodUser := (*int64)(nil)
|
||||
if v.pod.Spec.SecurityContext != nil {
|
||||
actualPodUser = v.pod.Spec.SecurityContext.RunAsUser
|
||||
}
|
||||
if (actualPodUser == nil) != (v.expectedPodUser == nil) {
|
||||
t.Errorf("%s expected pod user %v, got %v", k, v.expectedPodUser, actualPodUser)
|
||||
} else if actualPodUser != nil && *actualPodUser != *v.expectedPodUser {
|
||||
t.Errorf("%s expected pod user %v, got %v", k, *v.expectedPodUser, *actualPodUser)
|
||||
}
|
||||
actualPodUser := (*int64)(nil)
|
||||
if v.pod.Spec.SecurityContext != nil {
|
||||
actualPodUser = v.pod.Spec.SecurityContext.RunAsUser
|
||||
}
|
||||
if actualPodUser != nil {
|
||||
t.Errorf("%s expected pod user nil, got %v", k, *actualPodUser)
|
||||
}
|
||||
|
||||
actualContainerUser := (*int64)(nil)
|
||||
if v.pod.Spec.Containers[0].SecurityContext != nil {
|
||||
actualContainerUser = v.pod.Spec.Containers[0].SecurityContext.RunAsUser
|
||||
}
|
||||
if (actualContainerUser == nil) != (v.expectedContainerUser == nil) {
|
||||
t.Errorf("%s expected container user %v, got %v", k, v.expectedContainerUser, actualContainerUser)
|
||||
} else if actualContainerUser != nil && *actualContainerUser != *v.expectedContainerUser {
|
||||
t.Errorf("%s expected container user %v, got %v", k, *v.expectedContainerUser, *actualContainerUser)
|
||||
}
|
||||
actualContainerUser := (*int64)(nil)
|
||||
if v.pod.Spec.Containers[0].SecurityContext != nil {
|
||||
actualContainerUser = v.pod.Spec.Containers[0].SecurityContext.RunAsUser
|
||||
}
|
||||
if (actualContainerUser == nil) != (v.expectedContainerUser == nil) {
|
||||
t.Errorf("%s expected container user %v, got %v", k, v.expectedContainerUser, actualContainerUser)
|
||||
} else if actualContainerUser != nil && *actualContainerUser != *v.expectedContainerUser {
|
||||
t.Errorf("%s expected container user %v, got %v", k, *v.expectedContainerUser, *actualContainerUser)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1999,8 +2003,9 @@ func TestPolicyAuthorization(t *testing.T) {
|
||||
expectedPolicy string
|
||||
inPolicies []*extensions.PodSecurityPolicy
|
||||
allowed map[string]map[string]map[string]bool
|
||||
allowedGroup string
|
||||
}{
|
||||
"policy allowed by user": {
|
||||
"policy allowed by user (extensions API Group)": {
|
||||
user: &user.DefaultInfo{Name: "user"},
|
||||
sa: "sa",
|
||||
ns: "test",
|
||||
@ -2012,7 +2017,7 @@ func TestPolicyAuthorization(t *testing.T) {
|
||||
inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")},
|
||||
expectedPolicy: "policy",
|
||||
},
|
||||
"policy allowed by sa": {
|
||||
"policy allowed by sa (extensions API Group)": {
|
||||
user: &user.DefaultInfo{Name: "user"},
|
||||
sa: "sa",
|
||||
ns: "test",
|
||||
@ -2024,6 +2029,32 @@ func TestPolicyAuthorization(t *testing.T) {
|
||||
inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")},
|
||||
expectedPolicy: "policy",
|
||||
},
|
||||
"policy allowed by user (policy API Group)": {
|
||||
user: &user.DefaultInfo{Name: "user"},
|
||||
sa: "sa",
|
||||
ns: "test",
|
||||
allowed: map[string]map[string]map[string]bool{
|
||||
"user": {
|
||||
"test": {"policy": true},
|
||||
},
|
||||
},
|
||||
inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")},
|
||||
expectedPolicy: "policy",
|
||||
allowedGroup: policy.GroupName,
|
||||
},
|
||||
"policy allowed by sa (policy API Group)": {
|
||||
user: &user.DefaultInfo{Name: "user"},
|
||||
sa: "sa",
|
||||
ns: "test",
|
||||
allowed: map[string]map[string]map[string]bool{
|
||||
serviceaccount.MakeUsername("test", "sa"): {
|
||||
"test": {"policy": true},
|
||||
},
|
||||
},
|
||||
inPolicies: []*extensions.PodSecurityPolicy{policyWithName("policy")},
|
||||
expectedPolicy: "policy",
|
||||
allowedGroup: policy.GroupName,
|
||||
},
|
||||
"no policies allowed": {
|
||||
user: &user.DefaultInfo{Name: "user"},
|
||||
sa: "sa",
|
||||
@ -2125,7 +2156,7 @@ func TestPolicyAuthorization(t *testing.T) {
|
||||
var (
|
||||
oldPod *kapi.Pod
|
||||
shouldPass = v.expectedPolicy != ""
|
||||
authz = &TestAuthorizer{usernameToNamespaceToAllowedPSPs: v.allowed}
|
||||
authz = &TestAuthorizer{usernameToNamespaceToAllowedPSPs: v.allowed, allowedAPIGroupName: v.allowedGroup}
|
||||
canMutate = true
|
||||
)
|
||||
pod := goodPod()
|
||||
@ -2150,7 +2181,6 @@ func TestPolicyAuthorizationErrors(t *testing.T) {
|
||||
)
|
||||
|
||||
tests := map[string]struct {
|
||||
priviliged bool
|
||||
inPolicies []*extensions.PodSecurityPolicy
|
||||
allowed map[string]map[string]map[string]bool
|
||||
expectValidationErrs int
|
||||
@ -2217,7 +2247,7 @@ func TestPolicyAuthorizationErrors(t *testing.T) {
|
||||
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})
|
||||
|
||||
allowedPod, _, validationErrs, err := plugin.computeSecurityContext(attrs, pod, true)
|
||||
allowedPod, _, validationErrs, err := plugin.computeSecurityContext(attrs, pod, true, "")
|
||||
assert.Nil(t, allowedPod)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, validationErrs, tc.expectValidationErrs)
|
||||
@ -2225,6 +2255,99 @@ func TestPolicyAuthorizationErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreferValidatedPSP(t *testing.T) {
|
||||
restrictivePSPWithName := func(name string) *extensions.PodSecurityPolicy {
|
||||
p := restrictivePSP()
|
||||
p.Name = name
|
||||
return p
|
||||
}
|
||||
|
||||
permissivePSPWithName := func(name string) *extensions.PodSecurityPolicy {
|
||||
p := permissivePSP()
|
||||
p.Name = name
|
||||
return p
|
||||
}
|
||||
|
||||
tests := map[string]struct {
|
||||
inPolicies []*extensions.PodSecurityPolicy
|
||||
expectValidationErrs int
|
||||
validatedPSPHint string
|
||||
expectedPSP string
|
||||
}{
|
||||
"no policy saved in annotations, PSPs are ordered lexicographically": {
|
||||
inPolicies: []*extensions.PodSecurityPolicy{
|
||||
restrictivePSPWithName("001restrictive"),
|
||||
restrictivePSPWithName("002restrictive"),
|
||||
permissivePSPWithName("002permissive"),
|
||||
permissivePSPWithName("001permissive"),
|
||||
permissivePSPWithName("003permissive"),
|
||||
},
|
||||
expectValidationErrs: 0,
|
||||
validatedPSPHint: "",
|
||||
expectedPSP: "001permissive",
|
||||
},
|
||||
"policy saved in annotations is preferred": {
|
||||
inPolicies: []*extensions.PodSecurityPolicy{
|
||||
restrictivePSPWithName("001restrictive"),
|
||||
restrictivePSPWithName("002restrictive"),
|
||||
permissivePSPWithName("001permissive"),
|
||||
permissivePSPWithName("002permissive"),
|
||||
permissivePSPWithName("003permissive"),
|
||||
},
|
||||
expectValidationErrs: 0,
|
||||
validatedPSPHint: "002permissive",
|
||||
expectedPSP: "002permissive",
|
||||
},
|
||||
"policy saved in annotations is invalid": {
|
||||
inPolicies: []*extensions.PodSecurityPolicy{
|
||||
restrictivePSPWithName("001restrictive"),
|
||||
restrictivePSPWithName("002restrictive"),
|
||||
},
|
||||
expectValidationErrs: 2,
|
||||
validatedPSPHint: "foo",
|
||||
expectedPSP: "",
|
||||
},
|
||||
"policy saved in annotations is disallowed anymore": {
|
||||
inPolicies: []*extensions.PodSecurityPolicy{
|
||||
restrictivePSPWithName("001restrictive"),
|
||||
restrictivePSPWithName("002restrictive"),
|
||||
},
|
||||
expectValidationErrs: 2,
|
||||
validatedPSPHint: "001restrictive",
|
||||
expectedPSP: "",
|
||||
},
|
||||
"policy saved in annotations is disallowed anymore, but find another one": {
|
||||
inPolicies: []*extensions.PodSecurityPolicy{
|
||||
restrictivePSPWithName("001restrictive"),
|
||||
restrictivePSPWithName("002restrictive"),
|
||||
permissivePSPWithName("002permissive"),
|
||||
permissivePSPWithName("001permissive"),
|
||||
},
|
||||
expectValidationErrs: 0,
|
||||
validatedPSPHint: "001restrictive",
|
||||
expectedPSP: "001permissive",
|
||||
},
|
||||
}
|
||||
for desc, tc := range tests {
|
||||
t.Run(desc, func(t *testing.T) {
|
||||
authz := authorizerfactory.NewAlwaysAllowAuthorizer()
|
||||
allowPrivilegeEscalation := true
|
||||
pod := goodPod()
|
||||
pod.Namespace = "ns"
|
||||
pod.Spec.ServiceAccountName = "sa"
|
||||
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"})
|
||||
|
||||
_, pspName, validationErrs, err := plugin.computeSecurityContext(attrs, pod, false, tc.validatedPSPHint)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, validationErrs, tc.expectValidationErrs)
|
||||
assert.Equal(t, pspName, tc.expectedPSP)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func restrictivePSP() *extensions.PodSecurityPolicy {
|
||||
return &extensions.PodSecurityPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny/BUILD
generated
vendored
@ -20,8 +20,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
|
20
vendor/k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny/admission.go
generated
vendored
20
vendor/k8s.io/kubernetes/plugin/pkg/admission/securitycontext/scdeny/admission.go
generated
vendored
@ -25,9 +25,12 @@ import (
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
)
|
||||
|
||||
// PluginName indicates name of admission plugin.
|
||||
const PluginName = "SecurityContextDeny"
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register("SecurityContextDeny", func(config io.Reader) (admission.Interface, error) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
return NewSecurityContextDeny(), nil
|
||||
})
|
||||
}
|
||||
@ -46,7 +49,7 @@ func NewSecurityContextDeny() *Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
// Validate will deny any pod that defines SELinuxOptions or RunAsUser.
|
||||
// Validate will deny any pod that defines SupplementalGroups, SELinuxOptions, RunAsUser or FSGroup
|
||||
func (p *Plugin) Validate(a admission.Attributes) (err error) {
|
||||
if a.GetSubresource() != "" || a.GetResource().GroupResource() != api.Resource("pods") {
|
||||
return nil
|
||||
@ -57,20 +60,19 @@ func (p *Plugin) Validate(a admission.Attributes) (err error) {
|
||||
return apierrors.NewBadRequest("Resource was marked with kind Pod but was unable to be converted")
|
||||
}
|
||||
|
||||
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SupplementalGroups != nil {
|
||||
return apierrors.NewForbidden(a.GetResource().GroupResource(), pod.Name, fmt.Errorf("SecurityContext.SupplementalGroups is forbidden"))
|
||||
}
|
||||
if pod.Spec.SecurityContext != nil {
|
||||
if pod.Spec.SecurityContext.SupplementalGroups != nil {
|
||||
return apierrors.NewForbidden(a.GetResource().GroupResource(), pod.Name, fmt.Errorf("pod.Spec.SecurityContext.SupplementalGroups is forbidden"))
|
||||
}
|
||||
if pod.Spec.SecurityContext.SELinuxOptions != nil {
|
||||
return apierrors.NewForbidden(a.GetResource().GroupResource(), pod.Name, fmt.Errorf("pod.Spec.SecurityContext.SELinuxOptions is forbidden"))
|
||||
}
|
||||
if pod.Spec.SecurityContext.RunAsUser != nil {
|
||||
return apierrors.NewForbidden(a.GetResource().GroupResource(), pod.Name, fmt.Errorf("pod.Spec.SecurityContext.RunAsUser is forbidden"))
|
||||
}
|
||||
}
|
||||
|
||||
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.FSGroup != nil {
|
||||
return apierrors.NewForbidden(a.GetResource().GroupResource(), pod.Name, fmt.Errorf("SecurityContext.FSGroup is forbidden"))
|
||||
if pod.Spec.SecurityContext.FSGroup != nil {
|
||||
return apierrors.NewForbidden(a.GetResource().GroupResource(), pod.Name, fmt.Errorf("pod.Spec.SecurityContext.FSGroup is forbidden"))
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range pod.Spec.InitContainers {
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/BUILD
generated
vendored
@ -35,8 +35,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
|
||||
|
@ -9,7 +9,7 @@ load(
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["admission.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/storageclass/setdefault",
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/storage/storageclass/setdefault",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/core/helper:go_default_library",
|
||||
@ -28,8 +28,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/storageclass/setdefault",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
@ -35,6 +35,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// PluginName is the name of this admission controller plugin
|
||||
PluginName = "DefaultStorageClass"
|
||||
)
|
||||
|
||||
@ -84,16 +85,16 @@ func (a *claimDefaulterPlugin) ValidateInitialization() error {
|
||||
// 1. Find available StorageClasses.
|
||||
// 2. Figure which is the default
|
||||
// 3. Write to the PVClaim
|
||||
func (c *claimDefaulterPlugin) Admit(a admission.Attributes) error {
|
||||
if a.GetResource().GroupResource() != api.Resource("persistentvolumeclaims") {
|
||||
func (a *claimDefaulterPlugin) Admit(attr admission.Attributes) error {
|
||||
if attr.GetResource().GroupResource() != api.Resource("persistentvolumeclaims") {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(a.GetSubresource()) != 0 {
|
||||
if len(attr.GetSubresource()) != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
pvc, ok := a.GetObject().(*api.PersistentVolumeClaim)
|
||||
pvc, ok := attr.GetObject().(*api.PersistentVolumeClaim)
|
||||
// if we can't convert then we don't handle this object so just return
|
||||
if !ok {
|
||||
return nil
|
||||
@ -106,9 +107,9 @@ func (c *claimDefaulterPlugin) Admit(a admission.Attributes) error {
|
||||
|
||||
glog.V(4).Infof("no storage class for claim %s (generate: %s)", pvc.Name, pvc.GenerateName)
|
||||
|
||||
def, err := getDefaultClass(c.lister)
|
||||
def, err := getDefaultClass(a.lister)
|
||||
if err != nil {
|
||||
return admission.NewForbidden(a, err)
|
||||
return admission.NewForbidden(attr, err)
|
||||
}
|
||||
if def == nil {
|
||||
// No default class selected, do nothing about the PVC.
|
@ -3,7 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["admission.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/persistentvolumeclaim/pvcprotection",
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/storage/storageobjectinuseprotection",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
@ -21,8 +21,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["admission_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/admission/persistentvolumeclaim/pvcprotection",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion:go_default_library",
|
||||
@ -31,6 +30,7 @@ go_test(
|
||||
"//vendor/github.com/davecgh/go-spew/spew: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/util/feature:go_default_library",
|
||||
],
|
156
vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/storageobjectinuseprotection/admission.go
generated
vendored
Normal file
156
vendor/k8s.io/kubernetes/plugin/pkg/admission/storage/storageobjectinuseprotection/admission.go
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
Copyright 2017 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package storageobjectinuseprotection
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
admission "k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/util/feature"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion"
|
||||
corelisters "k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
||||
const (
|
||||
// PluginName is the name of this admission controller plugin
|
||||
PluginName = "StorageObjectInUseProtection"
|
||||
)
|
||||
|
||||
// Register registers a plugin
|
||||
func Register(plugins *admission.Plugins) {
|
||||
plugins.Register(PluginName, func(config io.Reader) (admission.Interface, error) {
|
||||
plugin := newPlugin()
|
||||
return plugin, nil
|
||||
})
|
||||
}
|
||||
|
||||
// storageProtectionPlugin holds state for and implements the admission plugin.
|
||||
type storageProtectionPlugin struct {
|
||||
*admission.Handler
|
||||
|
||||
pvcLister corelisters.PersistentVolumeClaimLister
|
||||
pvLister corelisters.PersistentVolumeLister
|
||||
}
|
||||
|
||||
var _ admission.Interface = &storageProtectionPlugin{}
|
||||
var _ = kubeapiserveradmission.WantsInternalKubeInformerFactory(&storageProtectionPlugin{})
|
||||
|
||||
// newPlugin creates a new admission plugin.
|
||||
func newPlugin() *storageProtectionPlugin {
|
||||
return &storageProtectionPlugin{
|
||||
Handler: admission.NewHandler(admission.Create),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *storageProtectionPlugin) SetInternalKubeInformerFactory(f informers.SharedInformerFactory) {
|
||||
pvcInformer := f.Core().InternalVersion().PersistentVolumeClaims()
|
||||
c.pvcLister = pvcInformer.Lister()
|
||||
pvInformer := f.Core().InternalVersion().PersistentVolumes()
|
||||
c.pvLister = pvInformer.Lister()
|
||||
c.SetReadyFunc(func() bool {
|
||||
return pvcInformer.Informer().HasSynced() && pvInformer.Informer().HasSynced()
|
||||
})
|
||||
}
|
||||
|
||||
// ValidateInitialization ensures lister is set.
|
||||
func (c *storageProtectionPlugin) ValidateInitialization() error {
|
||||
if c.pvcLister == nil {
|
||||
return fmt.Errorf("missing PVC lister")
|
||||
}
|
||||
if c.pvLister == nil {
|
||||
return fmt.Errorf("missing PV lister")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pvResource = api.Resource("persistentvolumes")
|
||||
pvcResource = api.Resource("persistentvolumeclaims")
|
||||
)
|
||||
|
||||
// Admit sets finalizer on all PVCs(PVs). The finalizer is removed by
|
||||
// PVCProtectionController(PVProtectionController) when it's not referenced.
|
||||
//
|
||||
// This prevents users from deleting a PVC that's used by a running pod.
|
||||
// This also prevents admin from deleting a PV that's bound by a PVC
|
||||
func (c *storageProtectionPlugin) Admit(a admission.Attributes) error {
|
||||
if !feature.DefaultFeatureGate.Enabled(features.StorageObjectInUseProtection) {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch a.GetResource().GroupResource() {
|
||||
case pvResource:
|
||||
return c.admitPV(a)
|
||||
case pvcResource:
|
||||
return c.admitPVC(a)
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *storageProtectionPlugin) admitPV(a admission.Attributes) error {
|
||||
if len(a.GetSubresource()) != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
pv, ok := a.GetObject().(*api.PersistentVolume)
|
||||
// if we can't convert the obj to PV, just return
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
for _, f := range pv.Finalizers {
|
||||
if f == volumeutil.PVProtectionFinalizer {
|
||||
// Finalizer is already present, nothing to do
|
||||
return nil
|
||||
}
|
||||
}
|
||||
glog.V(4).Infof("adding PV protection finalizer to %s", pv.Name)
|
||||
pv.Finalizers = append(pv.Finalizers, volumeutil.PVProtectionFinalizer)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *storageProtectionPlugin) admitPVC(a admission.Attributes) error {
|
||||
if len(a.GetSubresource()) != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
pvc, ok := a.GetObject().(*api.PersistentVolumeClaim)
|
||||
// if we can't convert the obj to PVC, just return
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, f := range pvc.Finalizers {
|
||||
if f == volumeutil.PVCProtectionFinalizer {
|
||||
// Finalizer is already present, nothing to do
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
glog.V(4).Infof("adding PVC protection finalizer to %s/%s", pvc.Namespace, pvc.Name)
|
||||
pvc.Finalizers = append(pvc.Finalizers, volumeutil.PVCProtectionFinalizer)
|
||||
return nil
|
||||
}
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package pvcprotection
|
||||
package storageobjectinuseprotection
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -25,6 +25,7 @@ import (
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/util/feature"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
@ -43,32 +44,76 @@ func TestAdmit(t *testing.T) {
|
||||
Namespace: "ns",
|
||||
},
|
||||
}
|
||||
|
||||
pv := &api.PersistentVolume{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "PersistentVolume",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pv",
|
||||
},
|
||||
}
|
||||
claimWithFinalizer := claim.DeepCopy()
|
||||
claimWithFinalizer.Finalizers = []string{volumeutil.PVCProtectionFinalizer}
|
||||
|
||||
pvWithFinalizer := pv.DeepCopy()
|
||||
pvWithFinalizer.Finalizers = []string{volumeutil.PVProtectionFinalizer}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
resource schema.GroupVersionResource
|
||||
object runtime.Object
|
||||
expectedObject runtime.Object
|
||||
featureEnabled bool
|
||||
namespace string
|
||||
}{
|
||||
{
|
||||
"create -> add finalizer",
|
||||
api.SchemeGroupVersion.WithResource("persistentvolumeclaims"),
|
||||
claim,
|
||||
claimWithFinalizer,
|
||||
true,
|
||||
claim.Namespace,
|
||||
},
|
||||
{
|
||||
"finalizer already exists -> no new finalizer",
|
||||
api.SchemeGroupVersion.WithResource("persistentvolumeclaims"),
|
||||
claimWithFinalizer,
|
||||
claimWithFinalizer,
|
||||
true,
|
||||
claimWithFinalizer.Namespace,
|
||||
},
|
||||
{
|
||||
"disabled feature -> no finalizer",
|
||||
api.SchemeGroupVersion.WithResource("persistentvolumeclaims"),
|
||||
claim,
|
||||
claim,
|
||||
false,
|
||||
claim.Namespace,
|
||||
},
|
||||
{
|
||||
"create -> add finalizer",
|
||||
api.SchemeGroupVersion.WithResource("persistentvolumes"),
|
||||
pv,
|
||||
pvWithFinalizer,
|
||||
true,
|
||||
pv.Namespace,
|
||||
},
|
||||
{
|
||||
"finalizer already exists -> no new finalizer",
|
||||
api.SchemeGroupVersion.WithResource("persistentvolumes"),
|
||||
pvWithFinalizer,
|
||||
pvWithFinalizer,
|
||||
true,
|
||||
pvWithFinalizer.Namespace,
|
||||
},
|
||||
{
|
||||
"disabled feature -> no finalizer",
|
||||
api.SchemeGroupVersion.WithResource("persistentvolumes"),
|
||||
pv,
|
||||
pv,
|
||||
false,
|
||||
pv.Namespace,
|
||||
},
|
||||
}
|
||||
|
||||
@ -77,15 +122,15 @@ func TestAdmit(t *testing.T) {
|
||||
ctrl.SetInternalKubeInformerFactory(informerFactory)
|
||||
|
||||
for _, test := range tests {
|
||||
feature.DefaultFeatureGate.Set(fmt.Sprintf("PVCProtection=%v", test.featureEnabled))
|
||||
feature.DefaultFeatureGate.Set(fmt.Sprintf("StorageObjectInUseProtection=%v", test.featureEnabled))
|
||||
obj := test.object.DeepCopyObject()
|
||||
attrs := admission.NewAttributesRecord(
|
||||
obj, // new object
|
||||
obj.DeepCopyObject(), // old object, copy to be sure it's not modified
|
||||
api.Kind("PersistentVolumeClaim").WithVersion("version"),
|
||||
claim.Namespace,
|
||||
claim.Name,
|
||||
api.Resource("persistentvolumeclaims").WithVersion("version"),
|
||||
schema.GroupVersionKind{},
|
||||
test.namespace,
|
||||
"foo",
|
||||
test.resource,
|
||||
"", // subresource
|
||||
admission.Create,
|
||||
nil, // userInfo
|
||||
@ -102,5 +147,5 @@ func TestAdmit(t *testing.T) {
|
||||
|
||||
// Disable the feature for rest of the tests.
|
||||
// TODO: remove after alpha
|
||||
feature.DefaultFeatureGate.Set("PVCProtection=false")
|
||||
feature.DefaultFeatureGate.Set("StorageObjectInUseProtection=false")
|
||||
}
|
8
vendor/k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap/BUILD
generated
vendored
8
vendor/k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap/BUILD
generated
vendored
@ -9,16 +9,15 @@ load(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["bootstrap_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/bootstrap/api: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/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -28,12 +27,13 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/bootstrap/api:go_default_library",
|
||||
"//pkg/client/listers/core/internalversion: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/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/bootstrap/token/api:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/bootstrap/token/util:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
9
vendor/k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap.go
generated
vendored
9
vendor/k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/bootstrap/bootstrap.go
generated
vendored
@ -31,8 +31,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
|
||||
bootstraputil "k8s.io/client-go/tools/bootstrap/token/util"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api"
|
||||
"k8s.io/kubernetes/pkg/client/listers/core/internalversion"
|
||||
)
|
||||
|
||||
@ -149,7 +150,7 @@ func (t *TokenAuthenticator) AuthenticateToken(token string) (user.Info, bool, e
|
||||
}, true, nil
|
||||
}
|
||||
|
||||
// Copied from k8s.io/kubernetes/pkg/bootstrap/api
|
||||
// Copied from k8s.io/client-go/tools/bootstrap/token/api
|
||||
func getSecretString(secret *api.Secret, key string) string {
|
||||
if secret.Data == nil {
|
||||
return ""
|
||||
@ -160,7 +161,7 @@ func getSecretString(secret *api.Secret, key string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Copied from k8s.io/kubernetes/pkg/bootstrap/api
|
||||
// Copied from k8s.io/client-go/tools/bootstrap/token/api
|
||||
func isSecretExpired(secret *api.Secret) bool {
|
||||
expiration := getSecretString(secret, bootstrapapi.BootstrapTokenExpirationKey)
|
||||
if len(expiration) > 0 {
|
||||
@ -209,7 +210,7 @@ func getGroups(secret *api.Secret) ([]string, error) {
|
||||
|
||||
// validate the names of the extra groups
|
||||
for _, group := range strings.Split(extraGroupsString, ",") {
|
||||
if err := bootstrapapi.ValidateBootstrapGroupName(group); err != nil {
|
||||
if err := bootstraputil.ValidateBootstrapGroupName(group); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groups.Insert(group)
|
||||
|
@ -25,8 +25,8 @@ import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
bootstrapapi "k8s.io/client-go/tools/bootstrap/token/api"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api"
|
||||
)
|
||||
|
||||
type lister struct {
|
||||
|
9
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/BUILD
generated
vendored
9
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/BUILD
generated
vendored
@ -9,15 +9,17 @@ load(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["node_authorizer_test.go"],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/node",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/auth/nodeidentifier:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//plugin/pkg/auth/authorizer/rbac/bootstrappolicy:go_default_library",
|
||||
"//vendor/k8s.io/api/storage/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1: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/util/feature:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -34,6 +36,7 @@ go_library(
|
||||
"//pkg/api/pod:go_default_library",
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//pkg/auth/nodeidentifier:go_default_library",
|
||||
"//pkg/client/informers/informers_generated/internalversion/core/internalversion:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
@ -42,9 +45,11 @@ go_library(
|
||||
"//third_party/forked/gonum/graph/simple:go_default_library",
|
||||
"//third_party/forked/gonum/graph/traverse:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/storage/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers/storage/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
|
||||
],
|
||||
)
|
||||
|
54
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph.go
generated
vendored
54
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph.go
generated
vendored
@ -106,15 +106,19 @@ const (
|
||||
pvcVertexType
|
||||
pvVertexType
|
||||
secretVertexType
|
||||
vaVertexType
|
||||
serviceAccountVertexType
|
||||
)
|
||||
|
||||
var vertexTypes = map[vertexType]string{
|
||||
configMapVertexType: "configmap",
|
||||
nodeVertexType: "node",
|
||||
podVertexType: "pod",
|
||||
pvcVertexType: "pvc",
|
||||
pvVertexType: "pv",
|
||||
secretVertexType: "secret",
|
||||
configMapVertexType: "configmap",
|
||||
nodeVertexType: "node",
|
||||
podVertexType: "pod",
|
||||
pvcVertexType: "pvc",
|
||||
pvVertexType: "pv",
|
||||
secretVertexType: "secret",
|
||||
vaVertexType: "volumeattachment",
|
||||
serviceAccountVertexType: "serviceAccount",
|
||||
}
|
||||
|
||||
// must be called under a write lock
|
||||
@ -202,6 +206,7 @@ func (g *Graph) deleteVertex_locked(vertexType vertexType, namespace, name strin
|
||||
// secret -> pod
|
||||
// configmap -> pod
|
||||
// pvc -> pod
|
||||
// svcacct -> pod
|
||||
func (g *Graph) AddPod(pod *api.Pod) {
|
||||
g.lock.Lock()
|
||||
defer g.lock.Unlock()
|
||||
@ -211,6 +216,14 @@ func (g *Graph) AddPod(pod *api.Pod) {
|
||||
nodeVertex := g.getOrCreateVertex_locked(nodeVertexType, "", pod.Spec.NodeName)
|
||||
g.graph.SetEdge(newDestinationEdge(podVertex, nodeVertex, nodeVertex))
|
||||
|
||||
// TODO(mikedanese): If the pod doesn't mount the service account secrets,
|
||||
// should the node still get access to the service account?
|
||||
//
|
||||
// ref https://github.com/kubernetes/kubernetes/issues/58790
|
||||
if len(pod.Spec.ServiceAccountName) > 0 {
|
||||
g.graph.SetEdge(newDestinationEdge(g.getOrCreateVertex_locked(serviceAccountVertexType, pod.Namespace, pod.Spec.ServiceAccountName), podVertex, nodeVertex))
|
||||
}
|
||||
|
||||
podutil.VisitPodSecretNames(pod, func(secret string) bool {
|
||||
g.graph.SetEdge(newDestinationEdge(g.getOrCreateVertex_locked(secretVertexType, pod.Namespace, secret), podVertex, nodeVertex))
|
||||
return true
|
||||
@ -251,9 +264,11 @@ func (g *Graph) AddPV(pv *api.PersistentVolume) {
|
||||
|
||||
// since we don't know the other end of the pvc -> pod -> node chain (or it may not even exist yet), we can't decorate these edges with kubernetes node info
|
||||
g.graph.SetEdge(simple.Edge{F: pvVertex, T: g.getOrCreateVertex_locked(pvcVertexType, pv.Spec.ClaimRef.Namespace, pv.Spec.ClaimRef.Name)})
|
||||
pvutil.VisitPVSecretNames(pv, func(namespace, secret string) bool {
|
||||
pvutil.VisitPVSecretNames(pv, func(namespace, secret string, kubeletVisible bool) bool {
|
||||
// This grants access to the named secret in the same namespace as the bound PVC
|
||||
g.graph.SetEdge(simple.Edge{F: g.getOrCreateVertex_locked(secretVertexType, namespace, secret), T: pvVertex})
|
||||
if kubeletVisible {
|
||||
g.graph.SetEdge(simple.Edge{F: g.getOrCreateVertex_locked(secretVertexType, namespace, secret), T: pvVertex})
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
@ -263,3 +278,26 @@ func (g *Graph) DeletePV(name string) {
|
||||
defer g.lock.Unlock()
|
||||
g.deleteVertex_locked(pvVertexType, "", name)
|
||||
}
|
||||
|
||||
// AddVolumeAttachment sets up edges for the following relationships:
|
||||
//
|
||||
// volume attachment -> node
|
||||
func (g *Graph) AddVolumeAttachment(attachmentName, nodeName string) {
|
||||
g.lock.Lock()
|
||||
defer g.lock.Unlock()
|
||||
|
||||
// clear existing edges
|
||||
g.deleteVertex_locked(vaVertexType, "", attachmentName)
|
||||
|
||||
// if we have a node, establish new edges
|
||||
if len(nodeName) > 0 {
|
||||
vaVertex := g.getOrCreateVertex_locked(vaVertexType, "", attachmentName)
|
||||
nodeVertex := g.getOrCreateVertex_locked(nodeVertexType, "", nodeName)
|
||||
g.graph.SetEdge(newDestinationEdge(vaVertex, nodeVertex, nodeVertex))
|
||||
}
|
||||
}
|
||||
func (g *Graph) DeleteVolumeAttachment(name string) {
|
||||
g.lock.Lock()
|
||||
defer g.lock.Unlock()
|
||||
g.deleteVertex_locked(vaVertexType, "", name)
|
||||
}
|
||||
|
47
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph_populator.go
generated
vendored
47
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/graph_populator.go
generated
vendored
@ -19,16 +19,25 @@ package node
|
||||
import (
|
||||
"github.com/golang/glog"
|
||||
|
||||
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
storageinformers "k8s.io/client-go/informers/storage/v1beta1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
coreinformers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/core/internalversion"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
type graphPopulator struct {
|
||||
graph *Graph
|
||||
}
|
||||
|
||||
func AddGraphEventHandlers(graph *Graph, pods coreinformers.PodInformer, pvs coreinformers.PersistentVolumeInformer) {
|
||||
func AddGraphEventHandlers(
|
||||
graph *Graph,
|
||||
pods coreinformers.PodInformer,
|
||||
pvs coreinformers.PersistentVolumeInformer,
|
||||
attachments storageinformers.VolumeAttachmentInformer,
|
||||
) {
|
||||
g := &graphPopulator{
|
||||
graph: graph,
|
||||
}
|
||||
@ -44,6 +53,14 @@ func AddGraphEventHandlers(graph *Graph, pods coreinformers.PodInformer, pvs cor
|
||||
UpdateFunc: g.updatePV,
|
||||
DeleteFunc: g.deletePV,
|
||||
})
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) {
|
||||
attachments.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: g.addVolumeAttachment,
|
||||
UpdateFunc: g.updateVolumeAttachment,
|
||||
DeleteFunc: g.deleteVolumeAttachment,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (g *graphPopulator) addPod(obj interface{}) {
|
||||
@ -106,3 +123,31 @@ func (g *graphPopulator) deletePV(obj interface{}) {
|
||||
}
|
||||
g.graph.DeletePV(pv.Name)
|
||||
}
|
||||
|
||||
func (g *graphPopulator) addVolumeAttachment(obj interface{}) {
|
||||
g.updateVolumeAttachment(nil, obj)
|
||||
}
|
||||
|
||||
func (g *graphPopulator) updateVolumeAttachment(oldObj, obj interface{}) {
|
||||
attachment := obj.(*storagev1beta1.VolumeAttachment)
|
||||
if oldObj != nil {
|
||||
// skip add if node name is identical
|
||||
oldAttachment := oldObj.(*storagev1beta1.VolumeAttachment)
|
||||
if oldAttachment.Spec.NodeName == attachment.Spec.NodeName {
|
||||
return
|
||||
}
|
||||
}
|
||||
g.graph.AddVolumeAttachment(attachment.Name, attachment.Spec.NodeName)
|
||||
}
|
||||
|
||||
func (g *graphPopulator) deleteVolumeAttachment(obj interface{}) {
|
||||
if tombstone, ok := obj.(cache.DeletedFinalStateUnknown); ok {
|
||||
obj = tombstone.Obj
|
||||
}
|
||||
attachment, ok := obj.(*api.PersistentVolume)
|
||||
if !ok {
|
||||
glog.Infof("unexpected type %T", obj)
|
||||
return
|
||||
}
|
||||
g.graph.DeleteVolumeAttachment(attachment.Name)
|
||||
}
|
||||
|
44
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer.go
generated
vendored
44
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer.go
generated
vendored
@ -26,6 +26,7 @@ import (
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
rbacapi "k8s.io/kubernetes/pkg/apis/rbac"
|
||||
storageapi "k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac"
|
||||
@ -48,6 +49,9 @@ type NodeAuthorizer struct {
|
||||
graph *Graph
|
||||
identifier nodeidentifier.NodeIdentifier
|
||||
nodeRules []rbacapi.PolicyRule
|
||||
|
||||
// allows overriding for testing
|
||||
features utilfeature.FeatureGate
|
||||
}
|
||||
|
||||
// NewAuthorizer returns a new node authorizer
|
||||
@ -56,6 +60,7 @@ func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules
|
||||
graph: graph,
|
||||
identifier: identifier,
|
||||
nodeRules: rules,
|
||||
features: utilfeature.DefaultFeatureGate,
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,6 +69,8 @@ var (
|
||||
secretResource = api.Resource("secrets")
|
||||
pvcResource = api.Resource("persistentvolumeclaims")
|
||||
pvResource = api.Resource("persistentvolumes")
|
||||
vaResource = storageapi.Resource("volumeattachments")
|
||||
svcAcctResource = api.Resource("serviceaccounts")
|
||||
)
|
||||
|
||||
func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Decision, string, error) {
|
||||
@ -87,7 +94,7 @@ func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Deci
|
||||
case configMapResource:
|
||||
return r.authorizeGet(nodeName, configMapVertexType, attrs)
|
||||
case pvcResource:
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) {
|
||||
if r.features.Enabled(features.ExpandPersistentVolumes) {
|
||||
if attrs.GetSubresource() == "status" {
|
||||
return r.authorizeStatusUpdate(nodeName, pvcVertexType, attrs)
|
||||
}
|
||||
@ -95,6 +102,16 @@ func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Deci
|
||||
return r.authorizeGet(nodeName, pvcVertexType, attrs)
|
||||
case pvResource:
|
||||
return r.authorizeGet(nodeName, pvVertexType, attrs)
|
||||
case vaResource:
|
||||
if r.features.Enabled(features.CSIPersistentVolume) {
|
||||
return r.authorizeGet(nodeName, vaVertexType, attrs)
|
||||
}
|
||||
return authorizer.DecisionNoOpinion, fmt.Sprintf("disabled by feature gate %s", features.CSIPersistentVolume), nil
|
||||
case svcAcctResource:
|
||||
if r.features.Enabled(features.TokenRequest) {
|
||||
return r.authorizeCreateToken(nodeName, serviceAccountVertexType, attrs)
|
||||
}
|
||||
return authorizer.DecisionNoOpinion, fmt.Sprintf("disabled by feature gate %s", features.TokenRequest), nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,6 +171,31 @@ func (r *NodeAuthorizer) authorize(nodeName string, startingType vertexType, att
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
}
|
||||
|
||||
// authorizeCreateToken authorizes "create" requests to serviceaccounts 'token'
|
||||
// subresource of pods running on a node
|
||||
func (r *NodeAuthorizer) authorizeCreateToken(nodeName string, startingType vertexType, attrs authorizer.Attributes) (authorizer.Decision, string, error) {
|
||||
if attrs.GetVerb() != "create" || len(attrs.GetName()) == 0 {
|
||||
glog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs)
|
||||
return authorizer.DecisionNoOpinion, "can only create tokens for individual service accounts", nil
|
||||
}
|
||||
|
||||
if attrs.GetSubresource() != "token" {
|
||||
glog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs)
|
||||
return authorizer.DecisionNoOpinion, "can only create token subresource of serviceaccount", nil
|
||||
}
|
||||
|
||||
ok, err := r.hasPathFrom(nodeName, startingType, attrs.GetNamespace(), attrs.GetName())
|
||||
if err != nil {
|
||||
glog.V(2).Infof("NODE DENY: %v", err)
|
||||
return authorizer.DecisionNoOpinion, "no path found to object", nil
|
||||
}
|
||||
if !ok {
|
||||
glog.V(2).Infof("NODE DENY: %q %#v", nodeName, attrs)
|
||||
return authorizer.DecisionNoOpinion, "no path found to object", nil
|
||||
}
|
||||
return authorizer.DecisionAllow, "", nil
|
||||
}
|
||||
|
||||
// hasPathFrom returns true if there is a directed path from the specified type/namespace/name to the specified Node
|
||||
func (r *NodeAuthorizer) hasPathFrom(nodeName string, startingType vertexType, startingNamespace, startingName string) (bool, error) {
|
||||
r.graph.lock.RLock()
|
||||
|
162
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer_test.go
generated
vendored
162
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/node/node_authorizer_test.go
generated
vendored
@ -24,14 +24,39 @@ import (
|
||||
|
||||
"os"
|
||||
|
||||
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy"
|
||||
)
|
||||
|
||||
var (
|
||||
csiEnabledFeature = utilfeature.NewFeatureGate()
|
||||
csiDisabledFeature = utilfeature.NewFeatureGate()
|
||||
trEnabledFeature = utilfeature.NewFeatureGate()
|
||||
trDisabledFeature = utilfeature.NewFeatureGate()
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := csiEnabledFeature.Add(map[utilfeature.Feature]utilfeature.FeatureSpec{features.CSIPersistentVolume: {Default: true}}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := csiDisabledFeature.Add(map[utilfeature.Feature]utilfeature.FeatureSpec{features.CSIPersistentVolume: {Default: false}}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := trEnabledFeature.Add(map[utilfeature.Feature]utilfeature.FeatureSpec{features.TokenRequest: {Default: true}}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := trDisabledFeature.Add(map[utilfeature.Feature]utilfeature.FeatureSpec{features.TokenRequest: {Default: false}}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthorizer(t *testing.T) {
|
||||
g := NewGraph()
|
||||
|
||||
@ -39,6 +64,7 @@ func TestAuthorizer(t *testing.T) {
|
||||
nodes: 2,
|
||||
namespaces: 2,
|
||||
podsPerNode: 2,
|
||||
attachmentsPerNode: 1,
|
||||
sharedConfigMapsPerPod: 0,
|
||||
uniqueConfigMapsPerPod: 1,
|
||||
sharedSecretsPerPod: 1,
|
||||
@ -46,18 +72,19 @@ func TestAuthorizer(t *testing.T) {
|
||||
sharedPVCsPerPod: 0,
|
||||
uniquePVCsPerPod: 1,
|
||||
}
|
||||
pods, pvs := generate(opts)
|
||||
populate(g, pods, pvs)
|
||||
pods, pvs, attachments := generate(opts)
|
||||
populate(g, pods, pvs, attachments)
|
||||
|
||||
identifier := nodeidentifier.NewDefaultNodeIdentifier()
|
||||
authz := NewAuthorizer(g, identifier, bootstrappolicy.NodeRules())
|
||||
authz := NewAuthorizer(g, identifier, bootstrappolicy.NodeRules()).(*NodeAuthorizer)
|
||||
|
||||
node0 := &user.DefaultInfo{Name: "system:node:node0", Groups: []string{"system:nodes"}}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
attrs authorizer.AttributesRecord
|
||||
expect authorizer.Decision
|
||||
name string
|
||||
attrs authorizer.AttributesRecord
|
||||
expect authorizer.Decision
|
||||
features utilfeature.FeatureGate
|
||||
}{
|
||||
{
|
||||
name: "allowed configmap",
|
||||
@ -115,10 +142,63 @@ func TestAuthorizer(t *testing.T) {
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumes", Name: "pv0-pod0-node1-ns0", Namespace: ""},
|
||||
expect: authorizer.DecisionNoOpinion,
|
||||
},
|
||||
{
|
||||
name: "disallowed attachment - no relationship",
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "volumeattachments", APIGroup: "storage.k8s.io", Name: "attachment0-node1"},
|
||||
features: csiEnabledFeature,
|
||||
expect: authorizer.DecisionNoOpinion,
|
||||
},
|
||||
{
|
||||
name: "disallowed attachment - feature disabled",
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "volumeattachments", APIGroup: "storage.k8s.io", Name: "attachment0-node0"},
|
||||
features: csiDisabledFeature,
|
||||
expect: authorizer.DecisionNoOpinion,
|
||||
},
|
||||
{
|
||||
name: "allowed attachment - feature enabled",
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "volumeattachments", APIGroup: "storage.k8s.io", Name: "attachment0-node0"},
|
||||
features: csiEnabledFeature,
|
||||
expect: authorizer.DecisionAllow,
|
||||
},
|
||||
{
|
||||
name: "allowed svcacct token create - feature enabled",
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "create", Resource: "serviceaccounts", Subresource: "token", Name: "svcacct0-node0", Namespace: "ns0"},
|
||||
features: trEnabledFeature,
|
||||
expect: authorizer.DecisionAllow,
|
||||
},
|
||||
{
|
||||
name: "disallowed svcacct token create - serviceaccount not attached to node",
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "create", Resource: "serviceaccounts", Subresource: "token", Name: "svcacct0-node1", Namespace: "ns0"},
|
||||
features: trEnabledFeature,
|
||||
expect: authorizer.DecisionNoOpinion,
|
||||
},
|
||||
{
|
||||
name: "disallowed svcacct token create - feature disabled",
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "create", Resource: "serviceaccounts", Subresource: "token", Name: "svcacct0-node0", Namespace: "ns0"},
|
||||
features: trDisabledFeature,
|
||||
expect: authorizer.DecisionNoOpinion,
|
||||
},
|
||||
{
|
||||
name: "disallowed svcacct token create - no subresource",
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "create", Resource: "serviceaccounts", Name: "svcacct0-node0", Namespace: "ns0"},
|
||||
features: trEnabledFeature,
|
||||
expect: authorizer.DecisionNoOpinion,
|
||||
},
|
||||
{
|
||||
name: "disallowed svcacct token create - non create",
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "update", Resource: "serviceaccounts", Subresource: "token", Name: "svcacct0-node0", Namespace: "ns0"},
|
||||
features: trEnabledFeature,
|
||||
expect: authorizer.DecisionNoOpinion,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if tc.features == nil {
|
||||
authz.features = utilfeature.DefaultFeatureGate
|
||||
} else {
|
||||
authz.features = tc.features
|
||||
}
|
||||
decision, _, _ := authz.Authorize(tc.attrs)
|
||||
if decision != tc.expect {
|
||||
t.Errorf("expected %v, got %v", tc.expect, decision)
|
||||
@ -204,6 +284,8 @@ type sampleDataOpts struct {
|
||||
|
||||
podsPerNode int
|
||||
|
||||
attachmentsPerNode int
|
||||
|
||||
sharedConfigMapsPerPod int
|
||||
sharedSecretsPerPod int
|
||||
sharedPVCsPerPod int
|
||||
@ -218,6 +300,7 @@ func BenchmarkPopulationAllocation(b *testing.B) {
|
||||
nodes: 500,
|
||||
namespaces: 200,
|
||||
podsPerNode: 200,
|
||||
attachmentsPerNode: 20,
|
||||
sharedConfigMapsPerPod: 0,
|
||||
uniqueConfigMapsPerPod: 1,
|
||||
sharedSecretsPerPod: 1,
|
||||
@ -226,12 +309,12 @@ func BenchmarkPopulationAllocation(b *testing.B) {
|
||||
uniquePVCsPerPod: 1,
|
||||
}
|
||||
|
||||
pods, pvs := generate(opts)
|
||||
pods, pvs, attachments := generate(opts)
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
g := NewGraph()
|
||||
populate(g, pods, pvs)
|
||||
populate(g, pods, pvs, attachments)
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,6 +331,7 @@ func BenchmarkPopulationRetention(b *testing.B) {
|
||||
nodes: 500,
|
||||
namespaces: 200,
|
||||
podsPerNode: 200,
|
||||
attachmentsPerNode: 20,
|
||||
sharedConfigMapsPerPod: 0,
|
||||
uniqueConfigMapsPerPod: 1,
|
||||
sharedSecretsPerPod: 1,
|
||||
@ -256,14 +340,14 @@ func BenchmarkPopulationRetention(b *testing.B) {
|
||||
uniquePVCsPerPod: 1,
|
||||
}
|
||||
|
||||
pods, pvs := generate(opts)
|
||||
pods, pvs, attachments := generate(opts)
|
||||
// Garbage collect before the first iteration
|
||||
runtime.GC()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
g := NewGraph()
|
||||
populate(g, pods, pvs)
|
||||
populate(g, pods, pvs, attachments)
|
||||
|
||||
if i == 0 {
|
||||
f, _ := os.Create("BenchmarkPopulationRetention.profile")
|
||||
@ -283,6 +367,7 @@ func BenchmarkAuthorization(b *testing.B) {
|
||||
nodes: 500,
|
||||
namespaces: 200,
|
||||
podsPerNode: 200,
|
||||
attachmentsPerNode: 20,
|
||||
sharedConfigMapsPerPod: 0,
|
||||
uniqueConfigMapsPerPod: 1,
|
||||
sharedSecretsPerPod: 1,
|
||||
@ -290,18 +375,19 @@ func BenchmarkAuthorization(b *testing.B) {
|
||||
sharedPVCsPerPod: 0,
|
||||
uniquePVCsPerPod: 1,
|
||||
}
|
||||
pods, pvs := generate(opts)
|
||||
populate(g, pods, pvs)
|
||||
pods, pvs, attachments := generate(opts)
|
||||
populate(g, pods, pvs, attachments)
|
||||
|
||||
identifier := nodeidentifier.NewDefaultNodeIdentifier()
|
||||
authz := NewAuthorizer(g, identifier, bootstrappolicy.NodeRules())
|
||||
authz := NewAuthorizer(g, identifier, bootstrappolicy.NodeRules()).(*NodeAuthorizer)
|
||||
|
||||
node0 := &user.DefaultInfo{Name: "system:node:node0", Groups: []string{"system:nodes"}}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
attrs authorizer.AttributesRecord
|
||||
expect authorizer.Decision
|
||||
name string
|
||||
attrs authorizer.AttributesRecord
|
||||
expect authorizer.Decision
|
||||
features utilfeature.FeatureGate
|
||||
}{
|
||||
{
|
||||
name: "allowed configmap",
|
||||
@ -343,10 +429,33 @@ func BenchmarkAuthorization(b *testing.B) {
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumes", Name: "pv0-pod0-node1-ns0", Namespace: ""},
|
||||
expect: authorizer.DecisionNoOpinion,
|
||||
},
|
||||
{
|
||||
name: "disallowed attachment - no relationship",
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "volumeattachments", APIGroup: "storage.k8s.io", Name: "attachment0-node1"},
|
||||
features: csiEnabledFeature,
|
||||
expect: authorizer.DecisionNoOpinion,
|
||||
},
|
||||
{
|
||||
name: "disallowed attachment - feature disabled",
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "volumeattachments", APIGroup: "storage.k8s.io", Name: "attachment0-node0"},
|
||||
features: csiDisabledFeature,
|
||||
expect: authorizer.DecisionNoOpinion,
|
||||
},
|
||||
{
|
||||
name: "allowed attachment - feature enabled",
|
||||
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "volumeattachments", APIGroup: "storage.k8s.io", Name: "attachment0-node0"},
|
||||
features: csiEnabledFeature,
|
||||
expect: authorizer.DecisionAllow,
|
||||
},
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for _, tc := range tests {
|
||||
if tc.features == nil {
|
||||
authz.features = utilfeature.DefaultFeatureGate
|
||||
} else {
|
||||
authz.features = tc.features
|
||||
}
|
||||
b.Run(tc.name, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
decision, _, _ := authz.Authorize(tc.attrs)
|
||||
@ -358,7 +467,7 @@ func BenchmarkAuthorization(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func populate(graph *Graph, pods []*api.Pod, pvs []*api.PersistentVolume) {
|
||||
func populate(graph *Graph, pods []*api.Pod, pvs []*api.PersistentVolume, attachments []*storagev1beta1.VolumeAttachment) {
|
||||
p := &graphPopulator{}
|
||||
p.graph = graph
|
||||
for _, pod := range pods {
|
||||
@ -367,15 +476,19 @@ func populate(graph *Graph, pods []*api.Pod, pvs []*api.PersistentVolume) {
|
||||
for _, pv := range pvs {
|
||||
p.addPV(pv)
|
||||
}
|
||||
for _, attachment := range attachments {
|
||||
p.addVolumeAttachment(attachment)
|
||||
}
|
||||
}
|
||||
|
||||
// generate creates sample pods and persistent volumes based on the provided options.
|
||||
// the secret/configmap/pvc/node references in the pod and pv objects are named to indicate the connections between the objects.
|
||||
// for example, secret0-pod0-node0 is a secret referenced by pod0 which is bound to node0.
|
||||
// when populated into the graph, the node authorizer should allow node0 to access that secret, but not node1.
|
||||
func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume) {
|
||||
func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume, []*storagev1beta1.VolumeAttachment) {
|
||||
pods := make([]*api.Pod, 0, opts.nodes*opts.podsPerNode)
|
||||
pvs := make([]*api.PersistentVolume, 0, (opts.nodes*opts.podsPerNode*opts.uniquePVCsPerPod)+(opts.sharedPVCsPerPod*opts.namespaces))
|
||||
attachments := make([]*storagev1beta1.VolumeAttachment, 0, opts.nodes*opts.attachmentsPerNode)
|
||||
|
||||
for n := 0; n < opts.nodes; n++ {
|
||||
nodeName := fmt.Sprintf("node%d", n)
|
||||
@ -384,6 +497,7 @@ func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume) {
|
||||
pod.Namespace = fmt.Sprintf("ns%d", p%opts.namespaces)
|
||||
pod.Name = fmt.Sprintf("pod%d-%s", p, nodeName)
|
||||
pod.Spec.NodeName = nodeName
|
||||
pod.Spec.ServiceAccountName = fmt.Sprintf("svcacct%d-%s", p, nodeName)
|
||||
|
||||
for i := 0; i < opts.uniqueSecretsPerPod; i++ {
|
||||
pod.Spec.Volumes = append(pod.Spec.Volumes, api.Volume{VolumeSource: api.VolumeSource{
|
||||
@ -410,7 +524,7 @@ func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume) {
|
||||
for i := 0; i < opts.uniquePVCsPerPod; i++ {
|
||||
pv := &api.PersistentVolume{}
|
||||
pv.Name = fmt.Sprintf("pv%d-%s-%s", i, pod.Name, pod.Namespace)
|
||||
pv.Spec.FlexVolume = &api.FlexVolumeSource{SecretRef: &api.LocalObjectReference{Name: fmt.Sprintf("secret-%s", pv.Name)}}
|
||||
pv.Spec.FlexVolume = &api.FlexPersistentVolumeSource{SecretRef: &api.SecretReference{Name: fmt.Sprintf("secret-%s", pv.Name)}}
|
||||
pv.Spec.ClaimRef = &api.ObjectReference{Name: fmt.Sprintf("pvc%d-%s", i, pod.Name), Namespace: pod.Namespace}
|
||||
pvs = append(pvs, pv)
|
||||
|
||||
@ -421,7 +535,7 @@ func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume) {
|
||||
for i := 0; i < opts.sharedPVCsPerPod; i++ {
|
||||
pv := &api.PersistentVolume{}
|
||||
pv.Name = fmt.Sprintf("pv%d-shared-%s", i, pod.Namespace)
|
||||
pv.Spec.FlexVolume = &api.FlexVolumeSource{SecretRef: &api.LocalObjectReference{Name: fmt.Sprintf("secret-%s", pv.Name)}}
|
||||
pv.Spec.FlexVolume = &api.FlexPersistentVolumeSource{SecretRef: &api.SecretReference{Name: fmt.Sprintf("secret-%s", pv.Name)}}
|
||||
pv.Spec.ClaimRef = &api.ObjectReference{Name: fmt.Sprintf("pvc%d-shared", i), Namespace: pod.Namespace}
|
||||
pvs = append(pvs, pv)
|
||||
|
||||
@ -432,6 +546,12 @@ func generate(opts sampleDataOpts) ([]*api.Pod, []*api.PersistentVolume) {
|
||||
|
||||
pods = append(pods, pod)
|
||||
}
|
||||
for a := 0; a < opts.attachmentsPerNode; a++ {
|
||||
attachment := &storagev1beta1.VolumeAttachment{}
|
||||
attachment.Name = fmt.Sprintf("attachment%d-%s", a, nodeName)
|
||||
attachment.Spec.NodeName = nodeName
|
||||
attachments = append(attachments, attachment)
|
||||
}
|
||||
}
|
||||
return pods, pvs
|
||||
return pods, pvs, attachments
|
||||
}
|
||||
|
3
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/BUILD
generated
vendored
@ -31,8 +31,7 @@ go_test(
|
||||
"rbac_test.go",
|
||||
"subject_locator_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/registry/rbac/validation:go_default_library",
|
||||
|
4
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/BUILD
generated
vendored
4
vendor/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/BUILD
generated
vendored
@ -32,7 +32,6 @@ go_test(
|
||||
data = glob([
|
||||
"testdata/*",
|
||||
]),
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy_test",
|
||||
deps = [
|
||||
":go_default_library",
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
@ -55,8 +54,7 @@ go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["controller_policy_test.go"],
|
||||
data = glob(["testdata/**"]),
|
||||
importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user