Commit 07f85565 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #36721 from smarterclayton/initializers

Automatic merge from submit-queue Add initializer support to admission and uninitialized filtering to rest storage Initializers are the opposite of finalizers - they allow API clients to react to object creation and populate fields prior to other clients seeing them. High level description: 1. Add `metadata.initializers` field to all objects 2. By default, filter objects with > 0 initializers from LIST and WATCH to preserve legacy client behavior (known as partially-initialized objects) 3. Add an admission controller that populates .initializer values per type, and denies mutation of initializers except by certain privilege levels (you must have the `initialize` verb on a resource) 4. Allow partially-initialized objects to be viewed via LIST and WATCH for initializer types 5. When creating objects, the object is "held" by the server until the initializers list is empty 6. Allow some creators to bypass initialization (set initializers to `[]`), or to have the result returned immediately when the object is created. The code here should be backwards compatible for all clients because they do not see partially initialized objects unless they GET the resource directly. The watch cache makes checking for partially initialized objects cheap. Some reflectors may need to change to ask for partially-initialized objects. ```release-note Kubernetes resources, when the `Initializers` admission controller is enabled, can be initialized (defaulting or other additive functions) by other agents in the system prior to those resources being visible to other clients. An initialized resource is not visible to clients unless they request (for get, list, or watch) to see uninitialized resources with the `?includeUninitialized=true` query parameter. Once the initializers have completed the resource is then visible. Clients must have the the ability to perform the `initialize` action on a resource in order to modify it prior to initialization being completed. ```
parents e6c74bba b993f7d3
...@@ -120,7 +120,7 @@ export FLANNEL_NET=${FLANNEL_NET:-"172.16.0.0/16"} ...@@ -120,7 +120,7 @@ export FLANNEL_NET=${FLANNEL_NET:-"172.16.0.0/16"}
# Admission Controllers to invoke prior to persisting objects in cluster # Admission Controllers to invoke prior to persisting objects in cluster
# If we included ResourceQuota, we should keep it at the end of the list to prevent incrementing quota usage prematurely. # If we included ResourceQuota, we should keep it at the end of the list to prevent incrementing quota usage prematurely.
export ADMISSION_CONTROL=${ADMISSION_CONTROL:-"NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultTolerationSeconds,ResourceQuota"} export ADMISSION_CONTROL=${ADMISSION_CONTROL:-"Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultTolerationSeconds,ResourceQuota"}
# Extra options to set on the Docker command line. # Extra options to set on the Docker command line.
# This is useful for setting --insecure-registry for local registries. # This is useful for setting --insecure-registry for local registries.
......
...@@ -219,7 +219,7 @@ fi ...@@ -219,7 +219,7 @@ fi
# Admission Controllers to invoke prior to persisting objects in cluster # Admission Controllers to invoke prior to persisting objects in cluster
# If we included ResourceQuota, we should keep it at the end of the list to prevent incrementing quota usage prematurely. # If we included ResourceQuota, we should keep it at the end of the list to prevent incrementing quota usage prematurely.
ADMISSION_CONTROL=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota ADMISSION_CONTROL=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota
# Optional: if set to true kube-up will automatically check for existing resources and clean them up. # Optional: if set to true kube-up will automatically check for existing resources and clean them up.
KUBE_UP_AUTOMATIC_CLEANUP=${KUBE_UP_AUTOMATIC_CLEANUP:-false} KUBE_UP_AUTOMATIC_CLEANUP=${KUBE_UP_AUTOMATIC_CLEANUP:-false}
......
...@@ -249,7 +249,7 @@ if [ ${ENABLE_IP_ALIASES} = true ]; then ...@@ -249,7 +249,7 @@ if [ ${ENABLE_IP_ALIASES} = true ]; then
fi fi
# If we included ResourceQuota, we should keep it at the end of the list to prevent incrementing quota usage prematurely. # If we included ResourceQuota, we should keep it at the end of the list to prevent incrementing quota usage prematurely.
ADMISSION_CONTROL="${KUBE_ADMISSION_CONTROL:-NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,PodPreset,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota}" ADMISSION_CONTROL="${KUBE_ADMISSION_CONTROL:-Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,PodPreset,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota}"
# Optional: if set to true kube-up will automatically check for existing resources and clean them up. # Optional: if set to true kube-up will automatically check for existing resources and clean them up.
KUBE_UP_AUTOMATIC_CLEANUP=${KUBE_UP_AUTOMATIC_CLEANUP:-false} KUBE_UP_AUTOMATIC_CLEANUP=${KUBE_UP_AUTOMATIC_CLEANUP:-false}
......
...@@ -791,6 +791,7 @@ def configure_master_services(): ...@@ -791,6 +791,7 @@ def configure_master_services():
api_opts.add('insecure-port', '8080') api_opts.add('insecure-port', '8080')
api_opts.add('storage-backend', 'etcd2') # FIXME: add etcd3 support api_opts.add('storage-backend', 'etcd2') # FIXME: add etcd3 support
admission_control = [ admission_control = [
'Initializers',
'NamespaceLifecycle', 'NamespaceLifecycle',
'LimitRanger', 'LimitRanger',
'ServiceAccount', 'ServiceAccount',
......
...@@ -27,7 +27,7 @@ source "$KUBE_ROOT/cluster/common.sh" ...@@ -27,7 +27,7 @@ source "$KUBE_ROOT/cluster/common.sh"
export LIBVIRT_DEFAULT_URI=qemu:///system export LIBVIRT_DEFAULT_URI=qemu:///system
export SERVICE_ACCOUNT_LOOKUP=${SERVICE_ACCOUNT_LOOKUP:-true} export SERVICE_ACCOUNT_LOOKUP=${SERVICE_ACCOUNT_LOOKUP:-true}
export ADMISSION_CONTROL=${ADMISSION_CONTROL:-NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota} export ADMISSION_CONTROL=${ADMISSION_CONTROL:-Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota}
readonly POOL=kubernetes readonly POOL=kubernetes
readonly POOL_PATH=/var/lib/libvirt/images/kubernetes readonly POOL_PATH=/var/lib/libvirt/images/kubernetes
......
...@@ -57,7 +57,7 @@ write_files: ...@@ -57,7 +57,7 @@ write_files:
dns_domain: cluster.local dns_domain: cluster.local
enable_dns_horizontal_autoscaler: "false" enable_dns_horizontal_autoscaler: "false"
instance_prefix: kubernetes instance_prefix: kubernetes
admission_control: NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota admission_control: Initializers,NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota
enable_cpu_cfs_quota: "true" enable_cpu_cfs_quota: "true"
network_provider: none network_provider: none
cluster_cidr: "$cluster_cidr" cluster_cidr: "$cluster_cidr"
......
...@@ -122,5 +122,5 @@ dns_domain: $DNS_DOMAIN ...@@ -122,5 +122,5 @@ dns_domain: $DNS_DOMAIN
e2e_storage_test_environment: "${E2E_STORAGE_TEST_ENVIRONMENT:-false}" e2e_storage_test_environment: "${E2E_STORAGE_TEST_ENVIRONMENT:-false}"
cluster_cidr: "$NODE_IP_RANGES" cluster_cidr: "$NODE_IP_RANGES"
allocate_node_cidrs: "${ALLOCATE_NODE_CIDRS:-true}" allocate_node_cidrs: "${ALLOCATE_NODE_CIDRS:-true}"
admission_control: NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota admission_control: Initializers,NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota
EOF EOF
...@@ -56,7 +56,7 @@ MASTER_PASSWD="${MASTER_PASSWD:-vagrant}" ...@@ -56,7 +56,7 @@ MASTER_PASSWD="${MASTER_PASSWD:-vagrant}"
# Admission Controllers to invoke prior to persisting objects in cluster # Admission Controllers to invoke prior to persisting objects in cluster
# If we included ResourceQuota, we should keep it at the end of the list to prevent incrementing quota usage prematurely. # If we included ResourceQuota, we should keep it at the end of the list to prevent incrementing quota usage prematurely.
ADMISSION_CONTROL=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota ADMISSION_CONTROL=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota
# Optional: Enable node logging. # Optional: Enable node logging.
ENABLE_NODE_LOGGING=false ENABLE_NODE_LOGGING=false
......
...@@ -52,6 +52,7 @@ go_library( ...@@ -52,6 +52,7 @@ go_library(
"//plugin/pkg/admission/exec:go_default_library", "//plugin/pkg/admission/exec:go_default_library",
"//plugin/pkg/admission/gc:go_default_library", "//plugin/pkg/admission/gc:go_default_library",
"//plugin/pkg/admission/imagepolicy:go_default_library", "//plugin/pkg/admission/imagepolicy:go_default_library",
"//plugin/pkg/admission/initialization:go_default_library",
"//plugin/pkg/admission/initialresources:go_default_library", "//plugin/pkg/admission/initialresources:go_default_library",
"//plugin/pkg/admission/limitranger:go_default_library", "//plugin/pkg/admission/limitranger:go_default_library",
"//plugin/pkg/admission/namespace/autoprovision:go_default_library", "//plugin/pkg/admission/namespace/autoprovision:go_default_library",
......
...@@ -33,6 +33,7 @@ import ( ...@@ -33,6 +33,7 @@ import (
"k8s.io/kubernetes/plugin/pkg/admission/exec" "k8s.io/kubernetes/plugin/pkg/admission/exec"
"k8s.io/kubernetes/plugin/pkg/admission/gc" "k8s.io/kubernetes/plugin/pkg/admission/gc"
"k8s.io/kubernetes/plugin/pkg/admission/imagepolicy" "k8s.io/kubernetes/plugin/pkg/admission/imagepolicy"
"k8s.io/kubernetes/plugin/pkg/admission/initialization"
"k8s.io/kubernetes/plugin/pkg/admission/initialresources" "k8s.io/kubernetes/plugin/pkg/admission/initialresources"
"k8s.io/kubernetes/plugin/pkg/admission/limitranger" "k8s.io/kubernetes/plugin/pkg/admission/limitranger"
"k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision" "k8s.io/kubernetes/plugin/pkg/admission/namespace/autoprovision"
...@@ -60,6 +61,7 @@ func registerAllAdmissionPlugins(plugins *admission.Plugins) { ...@@ -60,6 +61,7 @@ func registerAllAdmissionPlugins(plugins *admission.Plugins) {
exec.Register(plugins) exec.Register(plugins)
gc.Register(plugins) gc.Register(plugins)
imagepolicy.Register(plugins) imagepolicy.Register(plugins)
initialization.Register(plugins)
initialresources.Register(plugins) initialresources.Register(plugins)
limitranger.Register(plugins) limitranger.Register(plugins)
autoprovision.Register(plugins) autoprovision.Register(plugins)
......
...@@ -93,7 +93,7 @@ const ( ...@@ -93,7 +93,7 @@ const (
MinExternalEtcdVersion = "3.0.14" MinExternalEtcdVersion = "3.0.14"
// DefaultAdmissionControl specifies the default admission control options that will be used // DefaultAdmissionControl specifies the default admission control options that will be used
DefaultAdmissionControl = "NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds" DefaultAdmissionControl = "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds"
) )
var ( var (
......
...@@ -522,7 +522,7 @@ func TestGetAPIServerCommand(t *testing.T) { ...@@ -522,7 +522,7 @@ func TestGetAPIServerCommand(t *testing.T) {
expected: []string{ expected: []string{
"kube-apiserver", "kube-apiserver",
"--insecure-port=0", "--insecure-port=0",
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds", "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds",
"--service-cluster-ip-range=bar", "--service-cluster-ip-range=bar",
"--service-account-key-file=" + testCertsDir + "/sa.pub", "--service-account-key-file=" + testCertsDir + "/sa.pub",
"--client-ca-file=" + testCertsDir + "/ca.crt", "--client-ca-file=" + testCertsDir + "/ca.crt",
...@@ -554,7 +554,7 @@ func TestGetAPIServerCommand(t *testing.T) { ...@@ -554,7 +554,7 @@ func TestGetAPIServerCommand(t *testing.T) {
expected: []string{ expected: []string{
"kube-apiserver", "kube-apiserver",
"--insecure-port=0", "--insecure-port=0",
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds", "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds",
"--service-cluster-ip-range=bar", "--service-cluster-ip-range=bar",
"--service-account-key-file=" + testCertsDir + "/sa.pub", "--service-account-key-file=" + testCertsDir + "/sa.pub",
"--client-ca-file=" + testCertsDir + "/ca.crt", "--client-ca-file=" + testCertsDir + "/ca.crt",
...@@ -587,7 +587,7 @@ func TestGetAPIServerCommand(t *testing.T) { ...@@ -587,7 +587,7 @@ func TestGetAPIServerCommand(t *testing.T) {
expected: []string{ expected: []string{
"kube-apiserver", "kube-apiserver",
"--insecure-port=0", "--insecure-port=0",
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds", "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds",
"--service-cluster-ip-range=bar", "--service-cluster-ip-range=bar",
"--service-account-key-file=" + testCertsDir + "/sa.pub", "--service-account-key-file=" + testCertsDir + "/sa.pub",
"--client-ca-file=" + testCertsDir + "/ca.crt", "--client-ca-file=" + testCertsDir + "/ca.crt",
...@@ -622,7 +622,7 @@ func TestGetAPIServerCommand(t *testing.T) { ...@@ -622,7 +622,7 @@ func TestGetAPIServerCommand(t *testing.T) {
expected: []string{ expected: []string{
"kube-apiserver", "kube-apiserver",
"--insecure-port=0", "--insecure-port=0",
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds", "--admission-control=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds",
"--service-cluster-ip-range=bar", "--service-cluster-ip-range=bar",
"--service-account-key-file=" + testCertsDir + "/sa.pub", "--service-account-key-file=" + testCertsDir + "/sa.pub",
"--client-ca-file=" + testCertsDir + "/ca.crt", "--client-ca-file=" + testCertsDir + "/ca.crt",
......
...@@ -258,7 +258,7 @@ function create-federation-api-objects { ...@@ -258,7 +258,7 @@ function create-federation-api-objects {
export FEDERATION_APISERVER_KEY_BASE64="${FEDERATION_APISERVER_KEY_BASE64}" export FEDERATION_APISERVER_KEY_BASE64="${FEDERATION_APISERVER_KEY_BASE64}"
# Enable the NamespaceLifecycle admission control by default. # Enable the NamespaceLifecycle admission control by default.
export FEDERATION_ADMISSION_CONTROL="${FEDERATION_ADMISSION_CONTROL:-NamespaceLifecycle}" export FEDERATION_ADMISSION_CONTROL="${FEDERATION_ADMISSION_CONTROL:-Initializers,NamespaceLifecycle}"
for file in federation-etcd-pvc.yaml federation-apiserver-{deployment,secrets}.yaml federation-controller-manager-deployment.yaml; do for file in federation-etcd-pvc.yaml federation-apiserver-{deployment,secrets}.yaml federation-controller-manager-deployment.yaml; do
echo "Creating manifest: ${file}" echo "Creating manifest: ${file}"
......
...@@ -67,6 +67,7 @@ go_library( ...@@ -67,6 +67,7 @@ go_library(
"//plugin/pkg/admission/admit:go_default_library", "//plugin/pkg/admission/admit:go_default_library",
"//plugin/pkg/admission/deny:go_default_library", "//plugin/pkg/admission/deny:go_default_library",
"//plugin/pkg/admission/gc:go_default_library", "//plugin/pkg/admission/gc:go_default_library",
"//plugin/pkg/admission/initialization:go_default_library",
"//vendor/github.com/go-openapi/spec:go_default_library", "//vendor/github.com/go-openapi/spec:go_default_library",
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library",
......
...@@ -28,6 +28,7 @@ import ( ...@@ -28,6 +28,7 @@ import (
"k8s.io/kubernetes/plugin/pkg/admission/admit" "k8s.io/kubernetes/plugin/pkg/admission/admit"
"k8s.io/kubernetes/plugin/pkg/admission/deny" "k8s.io/kubernetes/plugin/pkg/admission/deny"
"k8s.io/kubernetes/plugin/pkg/admission/gc" "k8s.io/kubernetes/plugin/pkg/admission/gc"
"k8s.io/kubernetes/plugin/pkg/admission/initialization"
) )
// registerAllAdmissionPlugins registers all admission plugins // registerAllAdmissionPlugins registers all admission plugins
...@@ -35,4 +36,5 @@ func registerAllAdmissionPlugins(plugins *admission.Plugins) { ...@@ -35,4 +36,5 @@ func registerAllAdmissionPlugins(plugins *admission.Plugins) {
admit.Register(plugins) admit.Register(plugins)
deny.Register(plugins) deny.Register(plugins)
gc.Register(plugins) gc.Register(plugins)
initialization.Register(plugins)
} }
...@@ -692,7 +692,7 @@ func createAPIServer(clientset client.Interface, namespace, name, federationName ...@@ -692,7 +692,7 @@ func createAPIServer(clientset client.Interface, namespace, name, federationName
"--client-ca-file": "/etc/federation/apiserver/ca.crt", "--client-ca-file": "/etc/federation/apiserver/ca.crt",
"--tls-cert-file": "/etc/federation/apiserver/server.crt", "--tls-cert-file": "/etc/federation/apiserver/server.crt",
"--tls-private-key-file": "/etc/federation/apiserver/server.key", "--tls-private-key-file": "/etc/federation/apiserver/server.key",
"--admission-control": "NamespaceLifecycle", "--admission-control": "Initializers,NamespaceLifecycle",
} }
if advertiseAddress != "" { if advertiseAddress != "" {
......
...@@ -869,7 +869,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na ...@@ -869,7 +869,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
fmt.Sprintf("--secure-port=%d", apiServerSecurePort), fmt.Sprintf("--secure-port=%d", apiServerSecurePort),
"--tls-cert-file=/etc/federation/apiserver/server.crt", "--tls-cert-file=/etc/federation/apiserver/server.crt",
"--tls-private-key-file=/etc/federation/apiserver/server.key", "--tls-private-key-file=/etc/federation/apiserver/server.key",
"--admission-control=NamespaceLifecycle", "--admission-control=Initializers,NamespaceLifecycle",
fmt.Sprintf("--advertise-address=%s", address), fmt.Sprintf("--advertise-address=%s", address),
} }
......
...@@ -68,7 +68,7 @@ func (s *storage) GetCluster(ctx genericapirequest.Context, name string, options ...@@ -68,7 +68,7 @@ func (s *storage) GetCluster(ctx genericapirequest.Context, name string, options
} }
func (s *storage) CreateCluster(ctx genericapirequest.Context, cluster *federation.Cluster) error { func (s *storage) CreateCluster(ctx genericapirequest.Context, cluster *federation.Cluster) error {
_, err := s.Create(ctx, cluster) _, err := s.Create(ctx, cluster, false)
return err return err
} }
......
...@@ -48,12 +48,12 @@ func ClusterToSelectableFields(cluster *federation.Cluster) fields.Set { ...@@ -48,12 +48,12 @@ func ClusterToSelectableFields(cluster *federation.Cluster) fields.Set {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
cluster, ok := obj.(*federation.Cluster) cluster, ok := obj.(*federation.Cluster)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not a cluster.") return nil, nil, false, fmt.Errorf("given object is not a cluster.")
} }
return labels.Set(cluster.ObjectMeta.Labels), ClusterToSelectableFields(cluster), nil return labels.Set(cluster.ObjectMeta.Labels), ClusterToSelectableFields(cluster), cluster.Initializers != nil, nil
} }
func MatchCluster(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate { func MatchCluster(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
......
...@@ -401,7 +401,7 @@ function start_apiserver { ...@@ -401,7 +401,7 @@ function start_apiserver {
fi fi
# Admission Controllers to invoke prior to persisting objects in cluster # Admission Controllers to invoke prior to persisting objects in cluster
ADMISSION_CONTROL=NamespaceLifecycle,LimitRanger,ServiceAccount${security_admission},ResourceQuota,DefaultStorageClass,DefaultTolerationSeconds ADMISSION_CONTROL=Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount${security_admission},ResourceQuota,DefaultStorageClass,DefaultTolerationSeconds
# This is the default dir and filename where the apiserver will generate a self-signed cert # This is the default dir and filename where the apiserver will generate a self-signed cert
# which should be able to be used as the CA to verify itself # which should be able to be used as the CA to verify itself
......
...@@ -34,7 +34,7 @@ function run_kube_apiserver() { ...@@ -34,7 +34,7 @@ function run_kube_apiserver() {
kube::log::status "Starting kube-apiserver" kube::log::status "Starting kube-apiserver"
# Admission Controllers to invoke prior to persisting objects in cluster # Admission Controllers to invoke prior to persisting objects in cluster
ADMISSION_CONTROL="NamespaceLifecycle,LimitRanger,ResourceQuota" ADMISSION_CONTROL="Initializers,NamespaceLifecycle,LimitRanger,ResourceQuota"
# Include RBAC (to exercise bootstrapping), and AlwaysAllow to allow all actions # Include RBAC (to exercise bootstrapping), and AlwaysAllow to allow all actions
AUTHORIZATION_MODE="RBAC,AlwaysAllow" AUTHORIZATION_MODE="RBAC,AlwaysAllow"
......
...@@ -34,7 +34,7 @@ function run_federation_apiserver() { ...@@ -34,7 +34,7 @@ function run_federation_apiserver() {
kube::log::status "Starting federation-apiserver" kube::log::status "Starting federation-apiserver"
# Admission Controllers to invoke prior to persisting objects in cluster # Admission Controllers to invoke prior to persisting objects in cluster
ADMISSION_CONTROL="NamespaceLifecycle" ADMISSION_CONTROL="Initializers,NamespaceLifecycle"
"${KUBE_OUTPUT_HOSTBIN}/federation-apiserver" \ "${KUBE_OUTPUT_HOSTBIN}/federation-apiserver" \
--insecure-port="${API_PORT}" \ --insecure-port="${API_PORT}" \
......
...@@ -297,7 +297,7 @@ func (m *ThirdPartyResourceServer) migrateThirdPartyResourceData(gvk schema.Grou ...@@ -297,7 +297,7 @@ func (m *ThirdPartyResourceServer) migrateThirdPartyResourceData(gvk schema.Grou
// Store CustomResource. // Store CustomResource.
obj := &unstructured.Unstructured{Object: objMap} obj := &unstructured.Unstructured{Object: objMap}
createCtx := request.WithNamespace(ctx, obj.GetNamespace()) createCtx := request.WithNamespace(ctx, obj.GetNamespace())
if _, err := storage.Create(createCtx, obj); err != nil { if _, err := storage.Create(createCtx, obj, false); err != nil {
errs = append(errs, fmt.Errorf("can't create CustomResource for TPR data %q: %v", item.Name, err)) errs = append(errs, fmt.Errorf("can't create CustomResource for TPR data %q: %v", item.Name, err))
continue continue
} }
......
...@@ -106,15 +106,15 @@ func MatchExternalAdmissionHookConfiguration(label labels.Selector, field fields ...@@ -106,15 +106,15 @@ func MatchExternalAdmissionHookConfiguration(label labels.Selector, field fields
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
ic, ok := obj.(*admissionregistration.ExternalAdmissionHookConfiguration) ic, ok := obj.(*admissionregistration.ExternalAdmissionHookConfiguration)
if !ok { if !ok {
return nil, nil, fmt.Errorf("Given object is not a ExternalAdmissionHookConfiguration.") return nil, nil, false, fmt.Errorf("Given object is not a ExternalAdmissionHookConfiguration.")
} }
return labels.Set(ic.ObjectMeta.Labels), ExternalAdmissionHookConfigurationToSelectableFields(ic), nil return labels.Set(ic.ObjectMeta.Labels), ExternalAdmissionHookConfigurationToSelectableFields(ic), ic.Initializers != nil, nil
} }
// ExternalAdmissionHookConfigurationToSelectableFields returns a field set that represents the object. // ExternalAdmissionHookConfigurationToSelectableFields returns a field set that represents the object.
func ExternalAdmissionHookConfigurationToSelectableFields(ic *admissionregistration.ExternalAdmissionHookConfiguration) fields.Set { func ExternalAdmissionHookConfigurationToSelectableFields(ic *admissionregistration.ExternalAdmissionHookConfiguration) fields.Set {
return generic.ObjectMetaFieldsSet(&ic.ObjectMeta, true) return generic.ObjectMetaFieldsSet(&ic.ObjectMeta, false)
} }
...@@ -106,15 +106,15 @@ func MatchInitializerConfiguration(label labels.Selector, field fields.Selector) ...@@ -106,15 +106,15 @@ func MatchInitializerConfiguration(label labels.Selector, field fields.Selector)
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
ic, ok := obj.(*admissionregistration.InitializerConfiguration) ic, ok := obj.(*admissionregistration.InitializerConfiguration)
if !ok { if !ok {
return nil, nil, fmt.Errorf("Given object is not a InitializerConfiguration.") return nil, nil, false, fmt.Errorf("Given object is not a InitializerConfiguration.")
} }
return labels.Set(ic.ObjectMeta.Labels), InitializerConfigurationToSelectableFields(ic), nil return labels.Set(ic.ObjectMeta.Labels), InitializerConfigurationToSelectableFields(ic), ic.ObjectMeta.Initializers != nil, nil
} }
// InitializerConfigurationToSelectableFields returns a field set that represents the object. // InitializerConfigurationToSelectableFields returns a field set that represents the object.
func InitializerConfigurationToSelectableFields(ic *admissionregistration.InitializerConfiguration) fields.Set { func InitializerConfigurationToSelectableFields(ic *admissionregistration.InitializerConfiguration) fields.Set {
return generic.ObjectMetaFieldsSet(&ic.ObjectMeta, true) return generic.ObjectMetaFieldsSet(&ic.ObjectMeta, false)
} }
...@@ -90,12 +90,12 @@ func ControllerRevisionToSelectableFields(revision *apps.ControllerRevision) fie ...@@ -90,12 +90,12 @@ func ControllerRevisionToSelectableFields(revision *apps.ControllerRevision) fie
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
history, ok := obj.(*apps.ControllerRevision) history, ok := obj.(*apps.ControllerRevision)
if !ok { if !ok {
return nil, nil, errors.New("supplied object is not an ControllerRevision") return nil, nil, false, errors.New("supplied object is not an ControllerRevision")
} }
return labels.Set(history.ObjectMeta.Labels), ControllerRevisionToSelectableFields(history), nil return labels.Set(history.ObjectMeta.Labels), ControllerRevisionToSelectableFields(history), history.Initializers != nil, nil
} }
// MatchControllerRevision returns a generic matcher for a given label and field selector. // MatchControllerRevision returns a generic matcher for a given label and field selector.
......
...@@ -140,10 +140,13 @@ func TestControllerRevisionToSelectableFields(t *testing.T) { ...@@ -140,10 +140,13 @@ func TestControllerRevisionToSelectableFields(t *testing.T) {
func TestGetAttrs(t *testing.T) { func TestGetAttrs(t *testing.T) {
rev := newControllerRevision("validname", "validns", newObject(), 0) rev := newControllerRevision("validname", "validns", newObject(), 0)
labelSet, fieldSet, err := GetAttrs(rev) labelSet, fieldSet, uninitialized, err := GetAttrs(rev)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if uninitialized {
t.Errorf("unexpected attrs")
}
if fieldSet.Get("metadata.name") != rev.Name { if fieldSet.Get("metadata.name") != rev.Name {
t.Errorf("expeted %s found %s", rev.Name, fieldSet.Get("metadata.name")) t.Errorf("expeted %s found %s", rev.Name, fieldSet.Get("metadata.name"))
} }
......
...@@ -42,7 +42,7 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) ...@@ -42,7 +42,7 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer)
// createStatefulSet is a helper function that returns a StatefulSet with the updated resource version. // createStatefulSet is a helper function that returns a StatefulSet with the updated resource version.
func createStatefulSet(storage *REST, ps apps.StatefulSet, t *testing.T) (apps.StatefulSet, error) { func createStatefulSet(storage *REST, ps apps.StatefulSet, t *testing.T) (apps.StatefulSet, error) {
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), ps.Namespace) ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), ps.Namespace)
obj, err := storage.Create(ctx, &ps) obj, err := storage.Create(ctx, &ps, false)
if err != nil { if err != nil {
t.Errorf("Failed to create StatefulSet, %v", err) t.Errorf("Failed to create StatefulSet, %v", err)
} }
......
...@@ -112,12 +112,12 @@ func StatefulSetToSelectableFields(statefulSet *apps.StatefulSet) fields.Set { ...@@ -112,12 +112,12 @@ func StatefulSetToSelectableFields(statefulSet *apps.StatefulSet) fields.Set {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
statefulSet, ok := obj.(*apps.StatefulSet) statefulSet, ok := obj.(*apps.StatefulSet)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not an StatefulSet.") return nil, nil, false, fmt.Errorf("given object is not an StatefulSet.")
} }
return labels.Set(statefulSet.ObjectMeta.Labels), StatefulSetToSelectableFields(statefulSet), nil return labels.Set(statefulSet.ObjectMeta.Labels), StatefulSetToSelectableFields(statefulSet), statefulSet.Initializers != nil, nil
} }
// MatchStatefulSet is the filter used by the generic etcd backend to watch events // MatchStatefulSet is the filter used by the generic etcd backend to watch events
......
...@@ -39,7 +39,7 @@ func (r *REST) New() runtime.Object { ...@@ -39,7 +39,7 @@ func (r *REST) New() runtime.Object {
return &authentication.TokenReview{} return &authentication.TokenReview{}
} }
func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
tokenReview, ok := obj.(*authentication.TokenReview) tokenReview, ok := obj.(*authentication.TokenReview)
if !ok { if !ok {
return nil, apierrors.NewBadRequest(fmt.Sprintf("not a TokenReview: %#v", obj)) return nil, apierrors.NewBadRequest(fmt.Sprintf("not a TokenReview: %#v", obj))
......
...@@ -40,7 +40,7 @@ func (r *REST) New() runtime.Object { ...@@ -40,7 +40,7 @@ func (r *REST) New() runtime.Object {
return &authorizationapi.LocalSubjectAccessReview{} return &authorizationapi.LocalSubjectAccessReview{}
} }
func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
localSubjectAccessReview, ok := obj.(*authorizationapi.LocalSubjectAccessReview) localSubjectAccessReview, ok := obj.(*authorizationapi.LocalSubjectAccessReview)
if !ok { if !ok {
return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a LocaLocalSubjectAccessReview: %#v", obj)) return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a LocaLocalSubjectAccessReview: %#v", obj))
......
...@@ -40,7 +40,7 @@ func (r *REST) New() runtime.Object { ...@@ -40,7 +40,7 @@ func (r *REST) New() runtime.Object {
return &authorizationapi.SelfSubjectAccessReview{} return &authorizationapi.SelfSubjectAccessReview{}
} }
func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
selfSAR, ok := obj.(*authorizationapi.SelfSubjectAccessReview) selfSAR, ok := obj.(*authorizationapi.SelfSubjectAccessReview)
if !ok { if !ok {
return nil, apierrors.NewBadRequest(fmt.Sprintf("not a SelfSubjectAccessReview: %#v", obj)) return nil, apierrors.NewBadRequest(fmt.Sprintf("not a SelfSubjectAccessReview: %#v", obj))
......
...@@ -40,7 +40,7 @@ func (r *REST) New() runtime.Object { ...@@ -40,7 +40,7 @@ func (r *REST) New() runtime.Object {
return &authorizationapi.SubjectAccessReview{} return &authorizationapi.SubjectAccessReview{}
} }
func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
subjectAccessReview, ok := obj.(*authorizationapi.SubjectAccessReview) subjectAccessReview, ok := obj.(*authorizationapi.SubjectAccessReview)
if !ok { if !ok {
return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a SubjectAccessReview: %#v", obj)) return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a SubjectAccessReview: %#v", obj))
......
...@@ -176,7 +176,7 @@ func TestCreate(t *testing.T) { ...@@ -176,7 +176,7 @@ func TestCreate(t *testing.T) {
} }
rest := NewREST(auth) rest := NewREST(auth)
result, err := rest.Create(genericapirequest.NewContext(), &authorizationapi.SubjectAccessReview{Spec: tc.spec}) result, err := rest.Create(genericapirequest.NewContext(), &authorizationapi.SubjectAccessReview{Spec: tc.spec}, false)
if err != nil { if err != nil {
if tc.expectedErr != "" { if tc.expectedErr != "" {
if !strings.Contains(err.Error(), tc.expectedErr) { if !strings.Contains(err.Error(), tc.expectedErr) {
......
...@@ -91,12 +91,12 @@ func AutoscalerToSelectableFields(hpa *autoscaling.HorizontalPodAutoscaler) fiel ...@@ -91,12 +91,12 @@ func AutoscalerToSelectableFields(hpa *autoscaling.HorizontalPodAutoscaler) fiel
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
hpa, ok := obj.(*autoscaling.HorizontalPodAutoscaler) hpa, ok := obj.(*autoscaling.HorizontalPodAutoscaler)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not a horizontal pod autoscaler.") return nil, nil, false, fmt.Errorf("given object is not a horizontal pod autoscaler.")
} }
return labels.Set(hpa.ObjectMeta.Labels), AutoscalerToSelectableFields(hpa), nil return labels.Set(hpa.ObjectMeta.Labels), AutoscalerToSelectableFields(hpa), hpa.Initializers != nil, nil
} }
func MatchAutoscaler(label labels.Selector, field fields.Selector) storage.SelectionPredicate { func MatchAutoscaler(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
......
...@@ -112,12 +112,12 @@ func CronJobToSelectableFields(cronJob *batch.CronJob) fields.Set { ...@@ -112,12 +112,12 @@ func CronJobToSelectableFields(cronJob *batch.CronJob) fields.Set {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
cronJob, ok := obj.(*batch.CronJob) cronJob, ok := obj.(*batch.CronJob)
if !ok { if !ok {
return nil, nil, fmt.Errorf("Given object is not a scheduled job.") return nil, nil, false, fmt.Errorf("given object is not a scheduled job.")
} }
return labels.Set(cronJob.ObjectMeta.Labels), CronJobToSelectableFields(cronJob), nil return labels.Set(cronJob.ObjectMeta.Labels), CronJobToSelectableFields(cronJob), cronJob.Initializers != nil, nil
} }
// MatchCronJob is the filter used by the generic etcd backend to route // MatchCronJob is the filter used by the generic etcd backend to route
......
...@@ -174,12 +174,12 @@ func JobToSelectableFields(job *batch.Job) fields.Set { ...@@ -174,12 +174,12 @@ func JobToSelectableFields(job *batch.Job) fields.Set {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
job, ok := obj.(*batch.Job) job, ok := obj.(*batch.Job)
if !ok { if !ok {
return nil, nil, fmt.Errorf("Given object is not a job.") return nil, nil, false, fmt.Errorf("given object is not a job.")
} }
return labels.Set(job.ObjectMeta.Labels), JobToSelectableFields(job), nil return labels.Set(job.ObjectMeta.Labels), JobToSelectableFields(job), job.Initializers != nil, nil
} }
// MatchJob is the filter used by the generic etcd backend to route // MatchJob is the filter used by the generic etcd backend to route
......
...@@ -57,7 +57,7 @@ func (s *storage) ListCSRs(ctx genericapirequest.Context, options *metainternalv ...@@ -57,7 +57,7 @@ func (s *storage) ListCSRs(ctx genericapirequest.Context, options *metainternalv
} }
func (s *storage) CreateCSR(ctx genericapirequest.Context, csr *certificates.CertificateSigningRequest) error { func (s *storage) CreateCSR(ctx genericapirequest.Context, csr *certificates.CertificateSigningRequest) error {
_, err := s.Create(ctx, csr) _, err := s.Create(ctx, csr, false)
return err return err
} }
......
...@@ -178,12 +178,12 @@ func (csrApprovalStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, ol ...@@ -178,12 +178,12 @@ func (csrApprovalStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, ol
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
sa, ok := obj.(*certificates.CertificateSigningRequest) sa, ok := obj.(*certificates.CertificateSigningRequest)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a CertificateSigningRequest") return nil, nil, false, fmt.Errorf("not a CertificateSigningRequest")
} }
return labels.Set(sa.Labels), SelectableFields(sa), nil return labels.Set(sa.Labels), SelectableFields(sa), sa.Initializers != nil, nil
} }
// Matcher returns a generic matcher for a given label and field selector. // Matcher returns a generic matcher for a given label and field selector.
......
...@@ -69,7 +69,7 @@ func (s *storage) GetConfigMap(ctx genericapirequest.Context, name string, optio ...@@ -69,7 +69,7 @@ func (s *storage) GetConfigMap(ctx genericapirequest.Context, name string, optio
} }
func (s *storage) CreateConfigMap(ctx genericapirequest.Context, cfg *api.ConfigMap) (*api.ConfigMap, error) { func (s *storage) CreateConfigMap(ctx genericapirequest.Context, cfg *api.ConfigMap) (*api.ConfigMap, error) {
obj, err := s.Create(ctx, cfg) obj, err := s.Create(ctx, cfg, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -91,12 +91,12 @@ func ConfigMapToSelectableFields(cfg *api.ConfigMap) fields.Set { ...@@ -91,12 +91,12 @@ func ConfigMapToSelectableFields(cfg *api.ConfigMap) fields.Set {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
cfg, ok := obj.(*api.ConfigMap) cfg, ok := obj.(*api.ConfigMap)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not a ConfigMap") return nil, nil, false, fmt.Errorf("given object is not a ConfigMap")
} }
return labels.Set(cfg.ObjectMeta.Labels), ConfigMapToSelectableFields(cfg), nil return labels.Set(cfg.ObjectMeta.Labels), ConfigMapToSelectableFields(cfg), cfg.Initializers != nil, nil
} }
// MatchConfigMap returns a generic matcher for a given label and field selector. // MatchConfigMap returns a generic matcher for a given label and field selector.
......
...@@ -82,12 +82,12 @@ func (endpointsStrategy) AllowUnconditionalUpdate() bool { ...@@ -82,12 +82,12 @@ func (endpointsStrategy) AllowUnconditionalUpdate() bool {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
endpoints, ok := obj.(*api.Endpoints) endpoints, ok := obj.(*api.Endpoints)
if !ok { if !ok {
return nil, nil, fmt.Errorf("invalid object type %#v", obj) return nil, nil, false, fmt.Errorf("invalid object type %#v", obj)
} }
return endpoints.Labels, EndpointsToSelectableFields(endpoints), nil return endpoints.Labels, EndpointsToSelectableFields(endpoints), endpoints.Initializers != nil, nil
} }
// MatchEndpoints returns a generic matcher for a given label and field selector. // MatchEndpoints returns a generic matcher for a given label and field selector.
......
...@@ -73,12 +73,12 @@ func (eventStrategy) AllowUnconditionalUpdate() bool { ...@@ -73,12 +73,12 @@ func (eventStrategy) AllowUnconditionalUpdate() bool {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
event, ok := obj.(*api.Event) event, ok := obj.(*api.Event)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not an event") return nil, nil, false, fmt.Errorf("not an event")
} }
return labels.Set(event.Labels), EventToSelectableFields(event), nil return labels.Set(event.Labels), EventToSelectableFields(event), event.Initializers != nil, nil
} }
func MatchEvent(label labels.Selector, field fields.Selector) storage.SelectionPredicate { func MatchEvent(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
......
...@@ -88,12 +88,12 @@ func (limitrangeStrategy) Export(genericapirequest.Context, runtime.Object, bool ...@@ -88,12 +88,12 @@ func (limitrangeStrategy) Export(genericapirequest.Context, runtime.Object, bool
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
lr, ok := obj.(*api.LimitRange) lr, ok := obj.(*api.LimitRange)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not a limit range.") return nil, nil, false, fmt.Errorf("given object is not a limit range.")
} }
return labels.Set(lr.ObjectMeta.Labels), LimitRangeToSelectableFields(lr), nil return labels.Set(lr.ObjectMeta.Labels), LimitRangeToSelectableFields(lr), lr.Initializers != nil, nil
} }
func MatchLimitRange(label labels.Selector, field fields.Selector) storage.SelectionPredicate { func MatchLimitRange(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
......
...@@ -67,7 +67,7 @@ func (s *storage) GetNamespace(ctx genericapirequest.Context, namespaceName stri ...@@ -67,7 +67,7 @@ func (s *storage) GetNamespace(ctx genericapirequest.Context, namespaceName stri
} }
func (s *storage) CreateNamespace(ctx genericapirequest.Context, namespace *api.Namespace) error { func (s *storage) CreateNamespace(ctx genericapirequest.Context, namespace *api.Namespace) error {
_, err := s.Create(ctx, namespace) _, err := s.Create(ctx, namespace, false)
return err return err
} }
......
...@@ -92,8 +92,8 @@ func (r *REST) List(ctx genericapirequest.Context, options *metainternalversion. ...@@ -92,8 +92,8 @@ func (r *REST) List(ctx genericapirequest.Context, options *metainternalversion.
return r.store.List(ctx, options) return r.store.List(ctx, options)
} }
func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
return r.store.Create(ctx, obj) return r.store.Create(ctx, obj, includeUninitialized)
} }
func (r *REST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) { func (r *REST) Update(ctx genericapirequest.Context, name string, objInfo rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
......
...@@ -67,7 +67,7 @@ func TestCreateSetsFields(t *testing.T) { ...@@ -67,7 +67,7 @@ func TestCreateSetsFields(t *testing.T) {
defer storage.store.DestroyFunc() defer storage.store.DestroyFunc()
namespace := validNewNamespace() namespace := validNewNamespace()
ctx := genericapirequest.NewContext() ctx := genericapirequest.NewContext()
_, err := storage.Create(ctx, namespace) _, err := storage.Create(ctx, namespace, false)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
......
...@@ -138,12 +138,12 @@ func (namespaceFinalizeStrategy) PrepareForUpdate(ctx genericapirequest.Context, ...@@ -138,12 +138,12 @@ func (namespaceFinalizeStrategy) PrepareForUpdate(ctx genericapirequest.Context,
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
namespaceObj, ok := obj.(*api.Namespace) namespaceObj, ok := obj.(*api.Namespace)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a namespace") return nil, nil, false, fmt.Errorf("not a namespace")
} }
return labels.Set(namespaceObj.Labels), NamespaceToSelectableFields(namespaceObj), nil return labels.Set(namespaceObj.Labels), NamespaceToSelectableFields(namespaceObj), namespaceObj.Initializers != nil, nil
} }
// MatchNamespace returns a generic matcher for a given label and field selector. // MatchNamespace returns a generic matcher for a given label and field selector.
......
...@@ -56,7 +56,7 @@ func (s *storage) ListNodes(ctx genericapirequest.Context, options *metainternal ...@@ -56,7 +56,7 @@ func (s *storage) ListNodes(ctx genericapirequest.Context, options *metainternal
} }
func (s *storage) CreateNode(ctx genericapirequest.Context, node *api.Node) error { func (s *storage) CreateNode(ctx genericapirequest.Context, node *api.Node) error {
_, err := s.Create(ctx, node) _, err := s.Create(ctx, node, false)
return err return err
} }
......
...@@ -148,12 +148,12 @@ func NodeToSelectableFields(node *api.Node) fields.Set { ...@@ -148,12 +148,12 @@ func NodeToSelectableFields(node *api.Node) fields.Set {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
nodeObj, ok := obj.(*api.Node) nodeObj, ok := obj.(*api.Node)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a node") return nil, nil, false, fmt.Errorf("not a node")
} }
return labels.Set(nodeObj.ObjectMeta.Labels), NodeToSelectableFields(nodeObj), nil return labels.Set(nodeObj.ObjectMeta.Labels), NodeToSelectableFields(nodeObj), nodeObj.Initializers != nil, nil
} }
// MatchNode returns a generic matcher for a given label and field selector. // MatchNode returns a generic matcher for a given label and field selector.
......
...@@ -102,12 +102,12 @@ func (persistentvolumeStatusStrategy) ValidateUpdate(ctx genericapirequest.Conte ...@@ -102,12 +102,12 @@ func (persistentvolumeStatusStrategy) ValidateUpdate(ctx genericapirequest.Conte
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
persistentvolumeObj, ok := obj.(*api.PersistentVolume) persistentvolumeObj, ok := obj.(*api.PersistentVolume)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a persistentvolume") return nil, nil, false, fmt.Errorf("not a persistentvolume")
} }
return labels.Set(persistentvolumeObj.Labels), PersistentVolumeToSelectableFields(persistentvolumeObj), nil return labels.Set(persistentvolumeObj.Labels), PersistentVolumeToSelectableFields(persistentvolumeObj), persistentvolumeObj.Initializers != nil, nil
} }
// MatchPersistentVolume returns a generic matcher for a given label and field selector. // MatchPersistentVolume returns a generic matcher for a given label and field selector.
......
...@@ -98,12 +98,12 @@ func (persistentvolumeclaimStatusStrategy) ValidateUpdate(ctx genericapirequest. ...@@ -98,12 +98,12 @@ func (persistentvolumeclaimStatusStrategy) ValidateUpdate(ctx genericapirequest.
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
persistentvolumeclaimObj, ok := obj.(*api.PersistentVolumeClaim) persistentvolumeclaimObj, ok := obj.(*api.PersistentVolumeClaim)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a persistentvolumeclaim") return nil, nil, false, fmt.Errorf("not a persistentvolumeclaim")
} }
return labels.Set(persistentvolumeclaimObj.Labels), PersistentVolumeClaimToSelectableFields(persistentvolumeclaimObj), nil return labels.Set(persistentvolumeclaimObj.Labels), PersistentVolumeClaimToSelectableFields(persistentvolumeclaimObj), persistentvolumeclaimObj.Initializers != nil, nil
} }
// MatchPersistentVolumeClaim returns a generic matcher for a given label and field selector. // MatchPersistentVolumeClaim returns a generic matcher for a given label and field selector.
......
...@@ -71,7 +71,7 @@ func (r *EvictionREST) New() runtime.Object { ...@@ -71,7 +71,7 @@ func (r *EvictionREST) New() runtime.Object {
} }
// Create attempts to create a new eviction. That is, it tries to evict a pod. // Create attempts to create a new eviction. That is, it tries to evict a pod.
func (r *EvictionREST) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (r *EvictionREST) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
eviction := obj.(*policy.Eviction) eviction := obj.(*policy.Eviction)
obj, err := r.store.Get(ctx, eviction.Name, &metav1.GetOptions{}) obj, err := r.store.Get(ctx, eviction.Name, &metav1.GetOptions{})
......
...@@ -130,7 +130,7 @@ func (r *BindingREST) New() runtime.Object { ...@@ -130,7 +130,7 @@ func (r *BindingREST) New() runtime.Object {
var _ = rest.Creater(&BindingREST{}) var _ = rest.Creater(&BindingREST{})
// Create ensures a pod is bound to a specific host. // Create ensures a pod is bound to a specific host.
func (r *BindingREST) Create(ctx genericapirequest.Context, obj runtime.Object) (out runtime.Object, err error) { func (r *BindingREST) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (out runtime.Object, err error) {
binding := obj.(*api.Binding) binding := obj.(*api.Binding)
// TODO: move me to a binding strategy // TODO: move me to a binding strategy
......
...@@ -185,7 +185,7 @@ func TestIgnoreDeleteNotFound(t *testing.T) { ...@@ -185,7 +185,7 @@ func TestIgnoreDeleteNotFound(t *testing.T) {
} }
// create pod // create pod
_, err = registry.Create(testContext, pod) _, err = registry.Create(testContext, pod, false)
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error: %v", err)
} }
...@@ -222,7 +222,7 @@ func TestCreateSetsFields(t *testing.T) { ...@@ -222,7 +222,7 @@ func TestCreateSetsFields(t *testing.T) {
defer server.Terminate(t) defer server.Terminate(t)
defer storage.Store.DestroyFunc() defer storage.Store.DestroyFunc()
pod := validNewPod() pod := validNewPod()
_, err := storage.Create(genericapirequest.NewDefaultContext(), pod) _, err := storage.Create(genericapirequest.NewDefaultContext(), pod, false)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -486,7 +486,7 @@ func TestEtcdCreate(t *testing.T) { ...@@ -486,7 +486,7 @@ func TestEtcdCreate(t *testing.T) {
defer server.Terminate(t) defer server.Terminate(t)
defer storage.Store.DestroyFunc() defer storage.Store.DestroyFunc()
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
_, err := storage.Create(ctx, validNewPod()) _, err := storage.Create(ctx, validNewPod(), false)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -495,7 +495,7 @@ func TestEtcdCreate(t *testing.T) { ...@@ -495,7 +495,7 @@ func TestEtcdCreate(t *testing.T) {
_, err = bindingStorage.Create(ctx, &api.Binding{ _, err = bindingStorage.Create(ctx, &api.Binding{
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"}, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"},
Target: api.ObjectReference{Name: "machine"}, Target: api.ObjectReference{Name: "machine"},
}) }, false)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -521,7 +521,7 @@ func TestEtcdCreateBindingNoPod(t *testing.T) { ...@@ -521,7 +521,7 @@ func TestEtcdCreateBindingNoPod(t *testing.T) {
_, err := bindingStorage.Create(ctx, &api.Binding{ _, err := bindingStorage.Create(ctx, &api.Binding{
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"}, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"},
Target: api.ObjectReference{Name: "machine"}, Target: api.ObjectReference{Name: "machine"},
}) }, false)
if err == nil { if err == nil {
t.Fatalf("Expected not-found-error but got nothing") t.Fatalf("Expected not-found-error but got nothing")
} }
...@@ -544,7 +544,7 @@ func TestEtcdCreateFailsWithoutNamespace(t *testing.T) { ...@@ -544,7 +544,7 @@ func TestEtcdCreateFailsWithoutNamespace(t *testing.T) {
defer storage.Store.DestroyFunc() defer storage.Store.DestroyFunc()
pod := validNewPod() pod := validNewPod()
pod.Namespace = "" pod.Namespace = ""
_, err := storage.Create(genericapirequest.NewContext(), pod) _, err := storage.Create(genericapirequest.NewContext(), pod, false)
// Accept "namespace" or "Namespace". // Accept "namespace" or "Namespace".
if err == nil || !strings.Contains(err.Error(), "amespace") { if err == nil || !strings.Contains(err.Error(), "amespace") {
t.Fatalf("expected error that namespace was missing from context, got: %v", err) t.Fatalf("expected error that namespace was missing from context, got: %v", err)
...@@ -556,7 +556,7 @@ func TestEtcdCreateWithContainersNotFound(t *testing.T) { ...@@ -556,7 +556,7 @@ func TestEtcdCreateWithContainersNotFound(t *testing.T) {
defer server.Terminate(t) defer server.Terminate(t)
defer storage.Store.DestroyFunc() defer storage.Store.DestroyFunc()
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
_, err := storage.Create(ctx, validNewPod()) _, err := storage.Create(ctx, validNewPod(), false)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -569,7 +569,7 @@ func TestEtcdCreateWithContainersNotFound(t *testing.T) { ...@@ -569,7 +569,7 @@ func TestEtcdCreateWithContainersNotFound(t *testing.T) {
Annotations: map[string]string{"label1": "value1"}, Annotations: map[string]string{"label1": "value1"},
}, },
Target: api.ObjectReference{Name: "machine"}, Target: api.ObjectReference{Name: "machine"},
}) }, false)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -591,7 +591,7 @@ func TestEtcdCreateWithConflict(t *testing.T) { ...@@ -591,7 +591,7 @@ func TestEtcdCreateWithConflict(t *testing.T) {
defer storage.Store.DestroyFunc() defer storage.Store.DestroyFunc()
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
_, err := storage.Create(ctx, validNewPod()) _, err := storage.Create(ctx, validNewPod(), false)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -605,12 +605,12 @@ func TestEtcdCreateWithConflict(t *testing.T) { ...@@ -605,12 +605,12 @@ func TestEtcdCreateWithConflict(t *testing.T) {
}, },
Target: api.ObjectReference{Name: "machine"}, Target: api.ObjectReference{Name: "machine"},
} }
_, err = bindingStorage.Create(ctx, &binding) _, err = bindingStorage.Create(ctx, &binding, false)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
_, err = bindingStorage.Create(ctx, &binding) _, err = bindingStorage.Create(ctx, &binding, false)
if err == nil || !errors.IsConflict(err) { if err == nil || !errors.IsConflict(err) {
t.Fatalf("expected resource conflict error, not: %v", err) t.Fatalf("expected resource conflict error, not: %v", err)
} }
...@@ -621,7 +621,7 @@ func TestEtcdCreateWithExistingContainers(t *testing.T) { ...@@ -621,7 +621,7 @@ func TestEtcdCreateWithExistingContainers(t *testing.T) {
defer server.Terminate(t) defer server.Terminate(t)
defer storage.Store.DestroyFunc() defer storage.Store.DestroyFunc()
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
_, err := storage.Create(ctx, validNewPod()) _, err := storage.Create(ctx, validNewPod(), false)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -630,7 +630,7 @@ func TestEtcdCreateWithExistingContainers(t *testing.T) { ...@@ -630,7 +630,7 @@ func TestEtcdCreateWithExistingContainers(t *testing.T) {
_, err = bindingStorage.Create(ctx, &api.Binding{ _, err = bindingStorage.Create(ctx, &api.Binding{
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"}, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"},
Target: api.ObjectReference{Name: "machine"}, Target: api.ObjectReference{Name: "machine"},
}) }, false)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
...@@ -680,10 +680,10 @@ func TestEtcdCreateBinding(t *testing.T) { ...@@ -680,10 +680,10 @@ func TestEtcdCreateBinding(t *testing.T) {
for k, test := range testCases { for k, test := range testCases {
storage, bindingStorage, _, server := newStorage(t) storage, bindingStorage, _, server := newStorage(t)
if _, err := storage.Create(ctx, validNewPod()); err != nil { if _, err := storage.Create(ctx, validNewPod(), false); err != nil {
t.Fatalf("%s: unexpected error: %v", k, err) t.Fatalf("%s: unexpected error: %v", k, err)
} }
if _, err := bindingStorage.Create(ctx, &test.binding); !test.errOK(err) { if _, err := bindingStorage.Create(ctx, &test.binding, false); !test.errOK(err) {
t.Errorf("%s: unexpected error: %v", k, err) t.Errorf("%s: unexpected error: %v", k, err)
} else if err == nil { } else if err == nil {
// If bind succeeded, verify Host field in pod's Spec. // If bind succeeded, verify Host field in pod's Spec.
...@@ -705,7 +705,7 @@ func TestEtcdUpdateNotScheduled(t *testing.T) { ...@@ -705,7 +705,7 @@ func TestEtcdUpdateNotScheduled(t *testing.T) {
defer storage.Store.DestroyFunc() defer storage.Store.DestroyFunc()
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
if _, err := storage.Create(ctx, validNewPod()); err != nil { if _, err := storage.Create(ctx, validNewPod(), false); err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
......
...@@ -165,12 +165,12 @@ func (podStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old ...@@ -165,12 +165,12 @@ func (podStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
pod, ok := obj.(*api.Pod) pod, ok := obj.(*api.Pod)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a pod") return nil, nil, false, fmt.Errorf("not a pod")
} }
return labels.Set(pod.ObjectMeta.Labels), PodToSelectableFields(pod), nil return labels.Set(pod.ObjectMeta.Labels), PodToSelectableFields(pod), pod.Initializers != nil, nil
} }
// MatchPod returns a generic matcher for a given label and field selector. // MatchPod returns a generic matcher for a given label and field selector.
......
...@@ -89,12 +89,12 @@ func PodTemplateToSelectableFields(podTemplate *api.PodTemplate) fields.Set { ...@@ -89,12 +89,12 @@ func PodTemplateToSelectableFields(podTemplate *api.PodTemplate) fields.Set {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
pt, ok := obj.(*api.PodTemplate) pt, ok := obj.(*api.PodTemplate)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not a pod template.") return nil, nil, false, fmt.Errorf("given object is not a pod template.")
} }
return labels.Set(pt.ObjectMeta.Labels), PodTemplateToSelectableFields(pt), nil return labels.Set(pt.ObjectMeta.Labels), PodTemplateToSelectableFields(pt), pt.Initializers != nil, nil
} }
func MatchPodTemplate(label labels.Selector, field fields.Selector) storage.SelectionPredicate { func MatchPodTemplate(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
......
...@@ -74,7 +74,7 @@ func (s *storage) GetController(ctx genericapirequest.Context, controllerID stri ...@@ -74,7 +74,7 @@ func (s *storage) GetController(ctx genericapirequest.Context, controllerID stri
} }
func (s *storage) CreateController(ctx genericapirequest.Context, controller *api.ReplicationController) (*api.ReplicationController, error) { func (s *storage) CreateController(ctx genericapirequest.Context, controller *api.ReplicationController) (*api.ReplicationController, error) {
obj, err := s.Create(ctx, controller) obj, err := s.Create(ctx, controller, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -55,7 +55,7 @@ func newStorage(t *testing.T) (ControllerStorage, *etcdtesting.EtcdTestServer) { ...@@ -55,7 +55,7 @@ func newStorage(t *testing.T) (ControllerStorage, *etcdtesting.EtcdTestServer) {
// createController is a helper function that returns a controller with the updated resource version. // createController is a helper function that returns a controller with the updated resource version.
func createController(storage *REST, rc api.ReplicationController, t *testing.T) (api.ReplicationController, error) { func createController(storage *REST, rc api.ReplicationController, t *testing.T) (api.ReplicationController, error) {
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), rc.Namespace) ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), rc.Namespace)
obj, err := storage.Create(ctx, &rc) obj, err := storage.Create(ctx, &rc, false)
if err != nil { if err != nil {
t.Errorf("Failed to create controller, %v", err) t.Errorf("Failed to create controller, %v", err)
} }
......
...@@ -145,12 +145,12 @@ func ControllerToSelectableFields(controller *api.ReplicationController) fields. ...@@ -145,12 +145,12 @@ func ControllerToSelectableFields(controller *api.ReplicationController) fields.
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
rc, ok := obj.(*api.ReplicationController) rc, ok := obj.(*api.ReplicationController)
if !ok { if !ok {
return nil, nil, fmt.Errorf("Given object is not a replication controller.") return nil, nil, false, fmt.Errorf("given object is not a replication controller.")
} }
return labels.Set(rc.ObjectMeta.Labels), ControllerToSelectableFields(rc), nil return labels.Set(rc.ObjectMeta.Labels), ControllerToSelectableFields(rc), rc.Initializers != nil, nil
} }
// MatchController is the filter used by the generic etcd backend to route // MatchController is the filter used by the generic etcd backend to route
......
...@@ -87,7 +87,7 @@ func TestCreateSetsFields(t *testing.T) { ...@@ -87,7 +87,7 @@ func TestCreateSetsFields(t *testing.T) {
defer storage.Store.DestroyFunc() defer storage.Store.DestroyFunc()
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
resourcequota := validNewResourceQuota() resourcequota := validNewResourceQuota()
_, err := storage.Create(genericapirequest.NewDefaultContext(), resourcequota) _, err := storage.Create(genericapirequest.NewDefaultContext(), resourcequota, false)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
......
...@@ -101,12 +101,12 @@ func (resourcequotaStatusStrategy) ValidateUpdate(ctx genericapirequest.Context, ...@@ -101,12 +101,12 @@ func (resourcequotaStatusStrategy) ValidateUpdate(ctx genericapirequest.Context,
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
resourcequotaObj, ok := obj.(*api.ResourceQuota) resourcequotaObj, ok := obj.(*api.ResourceQuota)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a resourcequota") return nil, nil, false, fmt.Errorf("not a resourcequota")
} }
return labels.Set(resourcequotaObj.Labels), ResourceQuotaToSelectableFields(resourcequotaObj), nil return labels.Set(resourcequotaObj.Labels), ResourceQuotaToSelectableFields(resourcequotaObj), resourcequotaObj.Initializers != nil, nil
} }
// MatchResourceQuota returns a generic matcher for a given label and field selector. // MatchResourceQuota returns a generic matcher for a given label and field selector.
......
...@@ -67,7 +67,7 @@ func (s *storage) GetSecret(ctx genericapirequest.Context, name string, options ...@@ -67,7 +67,7 @@ func (s *storage) GetSecret(ctx genericapirequest.Context, name string, options
} }
func (s *storage) CreateSecret(ctx genericapirequest.Context, secret *api.Secret) (*api.Secret, error) { func (s *storage) CreateSecret(ctx genericapirequest.Context, secret *api.Secret) (*api.Secret, error) {
obj, err := s.Create(ctx, secret) obj, err := s.Create(ctx, secret, false)
return obj.(*api.Secret), err return obj.(*api.Secret), err
} }
......
...@@ -97,12 +97,12 @@ func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exac ...@@ -97,12 +97,12 @@ func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exac
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
secret, ok := obj.(*api.Secret) secret, ok := obj.(*api.Secret)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a secret") return nil, nil, false, fmt.Errorf("not a secret")
} }
return labels.Set(secret.Labels), SelectableFields(secret), nil return labels.Set(secret.Labels), SelectableFields(secret), secret.Initializers != nil, nil
} }
// Matcher returns a generic matcher for a given label and field selector. // Matcher returns a generic matcher for a given label and field selector.
......
...@@ -58,7 +58,7 @@ func (s *storage) ListServices(ctx genericapirequest.Context, options *metainter ...@@ -58,7 +58,7 @@ func (s *storage) ListServices(ctx genericapirequest.Context, options *metainter
} }
func (s *storage) CreateService(ctx genericapirequest.Context, svc *api.Service) (*api.Service, error) { func (s *storage) CreateService(ctx genericapirequest.Context, svc *api.Service) (*api.Service, error) {
obj, err := s.Create(ctx, svc) obj, err := s.Create(ctx, svc, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -77,7 +77,8 @@ func NewStorage(registry Registry, endpoints endpoint.Registry, serviceIPs ipall ...@@ -77,7 +77,8 @@ func NewStorage(registry Registry, endpoints endpoint.Registry, serviceIPs ipall
} }
} }
func (rs *REST) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { // TODO: implement includeUninitialized by refactoring this to move to store
func (rs *REST) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
service := obj.(*api.Service) service := obj.(*api.Service)
if err := rest.BeforeCreate(Strategy, ctx, obj); err != nil { if err := rest.BeforeCreate(Strategy, ctx, obj); err != nil {
......
...@@ -101,7 +101,7 @@ func TestServiceRegistryCreate(t *testing.T) { ...@@ -101,7 +101,7 @@ func TestServiceRegistryCreate(t *testing.T) {
}, },
} }
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
created_svc, err := storage.Create(ctx, svc) created_svc, err := storage.Create(ctx, svc, false)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
...@@ -225,7 +225,7 @@ func TestServiceRegistryCreateMultiNodePortsService(t *testing.T) { ...@@ -225,7 +225,7 @@ func TestServiceRegistryCreateMultiNodePortsService(t *testing.T) {
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
for _, test := range testCases { for _, test := range testCases {
created_svc, err := storage.Create(ctx, test.svc) created_svc, err := storage.Create(ctx, test.svc, false)
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
...@@ -296,7 +296,7 @@ func TestServiceStorageValidatesCreate(t *testing.T) { ...@@ -296,7 +296,7 @@ func TestServiceStorageValidatesCreate(t *testing.T) {
} }
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
for _, failureCase := range failureCases { for _, failureCase := range failureCases {
c, err := storage.Create(ctx, &failureCase) c, err := storage.Create(ctx, &failureCase, false)
if c != nil { if c != nil {
t.Errorf("Expected nil object") t.Errorf("Expected nil object")
} }
...@@ -425,7 +425,7 @@ func TestServiceRegistryExternalService(t *testing.T) { ...@@ -425,7 +425,7 @@ func TestServiceRegistryExternalService(t *testing.T) {
}}, }},
}, },
} }
_, err := storage.Create(ctx, svc) _, err := storage.Create(ctx, svc, false)
if err != nil { if err != nil {
t.Errorf("Failed to create service: %#v", err) t.Errorf("Failed to create service: %#v", err)
} }
...@@ -500,7 +500,7 @@ func TestServiceRegistryUpdateExternalService(t *testing.T) { ...@@ -500,7 +500,7 @@ func TestServiceRegistryUpdateExternalService(t *testing.T) {
}}, }},
}, },
} }
if _, err := storage.Create(ctx, svc1); err != nil { if _, err := storage.Create(ctx, svc1, false); err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
...@@ -543,7 +543,7 @@ func TestServiceRegistryUpdateMultiPortExternalService(t *testing.T) { ...@@ -543,7 +543,7 @@ func TestServiceRegistryUpdateMultiPortExternalService(t *testing.T) {
}}, }},
}, },
} }
if _, err := storage.Create(ctx, svc1); err != nil { if _, err := storage.Create(ctx, svc1, false); err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
...@@ -740,7 +740,7 @@ func TestServiceRegistryIPAllocation(t *testing.T) { ...@@ -740,7 +740,7 @@ func TestServiceRegistryIPAllocation(t *testing.T) {
}, },
} }
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
created_svc1, _ := storage.Create(ctx, svc1) created_svc1, _ := storage.Create(ctx, svc1, false)
created_service_1 := created_svc1.(*api.Service) created_service_1 := created_svc1.(*api.Service)
if created_service_1.Name != "foo" { if created_service_1.Name != "foo" {
t.Errorf("Expected foo, but got %v", created_service_1.Name) t.Errorf("Expected foo, but got %v", created_service_1.Name)
...@@ -762,7 +762,7 @@ func TestServiceRegistryIPAllocation(t *testing.T) { ...@@ -762,7 +762,7 @@ func TestServiceRegistryIPAllocation(t *testing.T) {
}}, }},
}} }}
ctx = genericapirequest.NewDefaultContext() ctx = genericapirequest.NewDefaultContext()
created_svc2, _ := storage.Create(ctx, svc2) created_svc2, _ := storage.Create(ctx, svc2, false)
created_service_2 := created_svc2.(*api.Service) created_service_2 := created_svc2.(*api.Service)
if created_service_2.Name != "bar" { if created_service_2.Name != "bar" {
t.Errorf("Expected bar, but got %v", created_service_2.Name) t.Errorf("Expected bar, but got %v", created_service_2.Name)
...@@ -795,7 +795,7 @@ func TestServiceRegistryIPAllocation(t *testing.T) { ...@@ -795,7 +795,7 @@ func TestServiceRegistryIPAllocation(t *testing.T) {
}, },
} }
ctx = genericapirequest.NewDefaultContext() ctx = genericapirequest.NewDefaultContext()
created_svc3, err := storage.Create(ctx, svc3) created_svc3, err := storage.Create(ctx, svc3, false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -822,7 +822,7 @@ func TestServiceRegistryIPReallocation(t *testing.T) { ...@@ -822,7 +822,7 @@ func TestServiceRegistryIPReallocation(t *testing.T) {
}, },
} }
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
created_svc1, _ := storage.Create(ctx, svc1) created_svc1, _ := storage.Create(ctx, svc1, false)
created_service_1 := created_svc1.(*api.Service) created_service_1 := created_svc1.(*api.Service)
if created_service_1.Name != "foo" { if created_service_1.Name != "foo" {
t.Errorf("Expected foo, but got %v", created_service_1.Name) t.Errorf("Expected foo, but got %v", created_service_1.Name)
...@@ -850,7 +850,7 @@ func TestServiceRegistryIPReallocation(t *testing.T) { ...@@ -850,7 +850,7 @@ func TestServiceRegistryIPReallocation(t *testing.T) {
}, },
} }
ctx = genericapirequest.NewDefaultContext() ctx = genericapirequest.NewDefaultContext()
created_svc2, _ := storage.Create(ctx, svc2) created_svc2, _ := storage.Create(ctx, svc2, false)
created_service_2 := created_svc2.(*api.Service) created_service_2 := created_svc2.(*api.Service)
if created_service_2.Name != "bar" { if created_service_2.Name != "bar" {
t.Errorf("Expected bar, but got %v", created_service_2.Name) t.Errorf("Expected bar, but got %v", created_service_2.Name)
...@@ -877,7 +877,7 @@ func TestServiceRegistryIPUpdate(t *testing.T) { ...@@ -877,7 +877,7 @@ func TestServiceRegistryIPUpdate(t *testing.T) {
}, },
} }
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
created_svc, _ := storage.Create(ctx, svc) created_svc, _ := storage.Create(ctx, svc, false)
created_service := created_svc.(*api.Service) created_service := created_svc.(*api.Service)
if created_service.Spec.Ports[0].Port != 6502 { if created_service.Spec.Ports[0].Port != 6502 {
t.Errorf("Expected port 6502, but got %v", created_service.Spec.Ports[0].Port) t.Errorf("Expected port 6502, but got %v", created_service.Spec.Ports[0].Port)
...@@ -931,7 +931,7 @@ func TestServiceRegistryIPLoadBalancer(t *testing.T) { ...@@ -931,7 +931,7 @@ func TestServiceRegistryIPLoadBalancer(t *testing.T) {
}, },
} }
ctx := genericapirequest.NewDefaultContext() ctx := genericapirequest.NewDefaultContext()
created_svc, _ := storage.Create(ctx, svc) created_svc, _ := storage.Create(ctx, svc, false)
created_service := created_svc.(*api.Service) created_service := created_svc.(*api.Service)
if created_service.Spec.Ports[0].Port != 6502 { if created_service.Spec.Ports[0].Port != 6502 {
t.Errorf("Expected port 6502, but got %v", created_service.Spec.Ports[0].Port) t.Errorf("Expected port 6502, but got %v", created_service.Spec.Ports[0].Port)
...@@ -985,7 +985,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortAllocation(t *testing. ...@@ -985,7 +985,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortAllocation(t *testing.
ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyTypeLocal, ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyTypeLocal,
}, },
} }
created_svc, err := storage.Create(ctx, svc) created_svc, err := storage.Create(ctx, svc, false)
if created_svc == nil || err != nil { if created_svc == nil || err != nil {
t.Errorf("Unexpected failure creating service %v", err) t.Errorf("Unexpected failure creating service %v", err)
} }
...@@ -1023,7 +1023,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortAllocationBeta(t *test ...@@ -1023,7 +1023,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortAllocationBeta(t *test
}}, }},
}, },
} }
created_svc, err := storage.Create(ctx, svc) created_svc, err := storage.Create(ctx, svc, false)
if created_svc == nil || err != nil { if created_svc == nil || err != nil {
t.Errorf("Unexpected failure creating service %v", err) t.Errorf("Unexpected failure creating service %v", err)
} }
...@@ -1059,7 +1059,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortUserAllocation(t *test ...@@ -1059,7 +1059,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortUserAllocation(t *test
HealthCheckNodePort: randomNodePort, HealthCheckNodePort: randomNodePort,
}, },
} }
created_svc, err := storage.Create(ctx, svc) created_svc, err := storage.Create(ctx, svc, false)
if created_svc == nil || err != nil { if created_svc == nil || err != nil {
t.Fatalf("Unexpected failure creating service :%v", err) t.Fatalf("Unexpected failure creating service :%v", err)
} }
...@@ -1101,7 +1101,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortUserAllocationBeta(t * ...@@ -1101,7 +1101,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortUserAllocationBeta(t *
}}, }},
}, },
} }
created_svc, err := storage.Create(ctx, svc) created_svc, err := storage.Create(ctx, svc, false)
if created_svc == nil || err != nil { if created_svc == nil || err != nil {
t.Fatalf("Unexpected failure creating service :%v", err) t.Fatalf("Unexpected failure creating service :%v", err)
} }
...@@ -1137,7 +1137,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortNegative(t *testing.T) ...@@ -1137,7 +1137,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortNegative(t *testing.T)
HealthCheckNodePort: int32(-1), HealthCheckNodePort: int32(-1),
}, },
} }
created_svc, err := storage.Create(ctx, svc) created_svc, err := storage.Create(ctx, svc, false)
if created_svc == nil || err != nil { if created_svc == nil || err != nil {
return return
} }
...@@ -1167,7 +1167,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortNegativeBeta(t *testin ...@@ -1167,7 +1167,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortNegativeBeta(t *testin
}}, }},
}, },
} }
created_svc, err := storage.Create(ctx, svc) created_svc, err := storage.Create(ctx, svc, false)
if created_svc == nil || err != nil { if created_svc == nil || err != nil {
return return
} }
...@@ -1192,7 +1192,7 @@ func TestServiceRegistryExternalTrafficGlobal(t *testing.T) { ...@@ -1192,7 +1192,7 @@ func TestServiceRegistryExternalTrafficGlobal(t *testing.T) {
ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyTypeGlobal, ExternalTrafficPolicy: api.ServiceExternalTrafficPolicyTypeGlobal,
}, },
} }
created_svc, err := storage.Create(ctx, svc) created_svc, err := storage.Create(ctx, svc, false)
if created_svc == nil || err != nil { if created_svc == nil || err != nil {
t.Errorf("Unexpected failure creating service %v", err) t.Errorf("Unexpected failure creating service %v", err)
} }
...@@ -1229,7 +1229,7 @@ func TestServiceRegistryExternalTrafficGlobalBeta(t *testing.T) { ...@@ -1229,7 +1229,7 @@ func TestServiceRegistryExternalTrafficGlobalBeta(t *testing.T) {
}}, }},
}, },
} }
created_svc, err := storage.Create(ctx, svc) created_svc, err := storage.Create(ctx, svc, false)
if created_svc == nil || err != nil { if created_svc == nil || err != nil {
t.Errorf("Unexpected failure creating service %v", err) t.Errorf("Unexpected failure creating service %v", err)
} }
...@@ -1265,7 +1265,7 @@ func TestServiceRegistryExternalTrafficAnnotationClusterIP(t *testing.T) { ...@@ -1265,7 +1265,7 @@ func TestServiceRegistryExternalTrafficAnnotationClusterIP(t *testing.T) {
}}, }},
}, },
} }
created_svc, err := storage.Create(ctx, svc) created_svc, err := storage.Create(ctx, svc, false)
if created_svc == nil || err != nil { if created_svc == nil || err != nil {
t.Errorf("Unexpected failure creating service %v", err) t.Errorf("Unexpected failure creating service %v", err)
} }
......
...@@ -104,12 +104,12 @@ func (svcStrategy) Export(ctx genericapirequest.Context, obj runtime.Object, exa ...@@ -104,12 +104,12 @@ func (svcStrategy) Export(ctx genericapirequest.Context, obj runtime.Object, exa
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
service, ok := obj.(*api.Service) service, ok := obj.(*api.Service)
if !ok { if !ok {
return nil, nil, fmt.Errorf("Given object is not a service") return nil, nil, false, fmt.Errorf("given object is not a service")
} }
return labels.Set(service.ObjectMeta.Labels), ServiceToSelectableFields(service), nil return labels.Set(service.ObjectMeta.Labels), ServiceToSelectableFields(service), service.Initializers != nil, nil
} }
func MatchServices(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate { func MatchServices(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
......
...@@ -67,7 +67,7 @@ func (s *storage) GetServiceAccount(ctx genericapirequest.Context, name string, ...@@ -67,7 +67,7 @@ func (s *storage) GetServiceAccount(ctx genericapirequest.Context, name string,
} }
func (s *storage) CreateServiceAccount(ctx genericapirequest.Context, serviceAccount *api.ServiceAccount) error { func (s *storage) CreateServiceAccount(ctx genericapirequest.Context, serviceAccount *api.ServiceAccount) error {
_, err := s.Create(ctx, serviceAccount) _, err := s.Create(ctx, serviceAccount, false)
return err return err
} }
......
...@@ -80,12 +80,12 @@ func (strategy) AllowUnconditionalUpdate() bool { ...@@ -80,12 +80,12 @@ func (strategy) AllowUnconditionalUpdate() bool {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
sa, ok := obj.(*api.ServiceAccount) sa, ok := obj.(*api.ServiceAccount)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a serviceaccount") return nil, nil, false, fmt.Errorf("not a serviceaccount")
} }
return labels.Set(sa.Labels), SelectableFields(sa), nil return labels.Set(sa.Labels), SelectableFields(sa), sa.Initializers != nil, nil
} }
// Matcher returns a generic matcher for a given label and field selector. // Matcher returns a generic matcher for a given label and field selector.
......
...@@ -131,12 +131,12 @@ func DaemonSetToSelectableFields(daemon *extensions.DaemonSet) fields.Set { ...@@ -131,12 +131,12 @@ func DaemonSetToSelectableFields(daemon *extensions.DaemonSet) fields.Set {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
ds, ok := obj.(*extensions.DaemonSet) ds, ok := obj.(*extensions.DaemonSet)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not a ds.") return nil, nil, false, fmt.Errorf("given object is not a ds.")
} }
return labels.Set(ds.ObjectMeta.Labels), DaemonSetToSelectableFields(ds), nil return labels.Set(ds.ObjectMeta.Labels), DaemonSetToSelectableFields(ds), ds.Initializers != nil, nil
} }
// MatchSetDaemon is the filter used by the generic etcd backend to route // MatchSetDaemon is the filter used by the generic etcd backend to route
......
...@@ -66,7 +66,7 @@ func (s *storage) GetDeployment(ctx genericapirequest.Context, deploymentID stri ...@@ -66,7 +66,7 @@ func (s *storage) GetDeployment(ctx genericapirequest.Context, deploymentID stri
} }
func (s *storage) CreateDeployment(ctx genericapirequest.Context, deployment *extensions.Deployment) (*extensions.Deployment, error) { func (s *storage) CreateDeployment(ctx genericapirequest.Context, deployment *extensions.Deployment) (*extensions.Deployment, error) {
obj, err := s.Create(ctx, deployment) obj, err := s.Create(ctx, deployment, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -123,7 +123,7 @@ func (r *RollbackREST) New() runtime.Object { ...@@ -123,7 +123,7 @@ func (r *RollbackREST) New() runtime.Object {
var _ = rest.Creater(&RollbackREST{}) var _ = rest.Creater(&RollbackREST{})
func (r *RollbackREST) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (r *RollbackREST) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
rollback, ok := obj.(*extensions.DeploymentRollback) rollback, ok := obj.(*extensions.DeploymentRollback)
if !ok { if !ok {
return nil, errors.NewBadRequest(fmt.Sprintf("not a DeploymentRollback: %#v", obj)) return nil, errors.NewBadRequest(fmt.Sprintf("not a DeploymentRollback: %#v", obj))
......
...@@ -340,10 +340,10 @@ func TestEtcdCreateDeploymentRollback(t *testing.T) { ...@@ -340,10 +340,10 @@ func TestEtcdCreateDeploymentRollback(t *testing.T) {
storage, server := newStorage(t) storage, server := newStorage(t)
rollbackStorage := storage.Rollback rollbackStorage := storage.Rollback
if _, err := storage.Deployment.Create(ctx, validNewDeployment()); err != nil { if _, err := storage.Deployment.Create(ctx, validNewDeployment(), false); err != nil {
t.Fatalf("%s: unexpected error: %v", k, err) t.Fatalf("%s: unexpected error: %v", k, err)
} }
if _, err := rollbackStorage.Create(ctx, &test.rollback); !test.errOK(err) { if _, err := rollbackStorage.Create(ctx, &test.rollback, false); !test.errOK(err) {
t.Errorf("%s: unexpected error: %v", k, err) t.Errorf("%s: unexpected error: %v", k, err)
} else if err == nil { } else if err == nil {
// If rollback succeeded, verify Rollback field of deployment // If rollback succeeded, verify Rollback field of deployment
...@@ -372,7 +372,7 @@ func TestEtcdCreateDeploymentRollbackNoDeployment(t *testing.T) { ...@@ -372,7 +372,7 @@ func TestEtcdCreateDeploymentRollbackNoDeployment(t *testing.T) {
Name: name, Name: name,
UpdatedAnnotations: map[string]string{}, UpdatedAnnotations: map[string]string{},
RollbackTo: extensions.RollbackConfig{Revision: 1}, RollbackTo: extensions.RollbackConfig{Revision: 1},
}) }, false)
if err == nil { if err == nil {
t.Fatalf("Expected not-found-error but got nothing") t.Fatalf("Expected not-found-error but got nothing")
} }
......
...@@ -126,12 +126,12 @@ func DeploymentToSelectableFields(deployment *extensions.Deployment) fields.Set ...@@ -126,12 +126,12 @@ func DeploymentToSelectableFields(deployment *extensions.Deployment) fields.Set
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
deployment, ok := obj.(*extensions.Deployment) deployment, ok := obj.(*extensions.Deployment)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not a deployment.") return nil, nil, false, fmt.Errorf("given object is not a deployment.")
} }
return labels.Set(deployment.ObjectMeta.Labels), DeploymentToSelectableFields(deployment), nil return labels.Set(deployment.ObjectMeta.Labels), DeploymentToSelectableFields(deployment), deployment.Initializers != nil, nil
} }
// MatchDeployment is the filter used by the generic etcd backend to route // MatchDeployment is the filter used by the generic etcd backend to route
......
...@@ -106,12 +106,12 @@ func IngressToSelectableFields(ingress *extensions.Ingress) fields.Set { ...@@ -106,12 +106,12 @@ func IngressToSelectableFields(ingress *extensions.Ingress) fields.Set {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
ingress, ok := obj.(*extensions.Ingress) ingress, ok := obj.(*extensions.Ingress)
if !ok { if !ok {
return nil, nil, fmt.Errorf("Given object is not an Ingress.") return nil, nil, false, fmt.Errorf("given object is not an Ingress.")
} }
return labels.Set(ingress.ObjectMeta.Labels), IngressToSelectableFields(ingress), nil return labels.Set(ingress.ObjectMeta.Labels), IngressToSelectableFields(ingress), ingress.Initializers != nil, nil
} }
// MatchIngress is the filter used by the generic etcd backend to ingress // MatchIngress is the filter used by the generic etcd backend to ingress
......
...@@ -45,7 +45,7 @@ func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) { ...@@ -45,7 +45,7 @@ func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) {
// createNetworkPolicy is a helper function that returns a NetworkPolicy with the updated resource version. // createNetworkPolicy is a helper function that returns a NetworkPolicy with the updated resource version.
func createNetworkPolicy(storage *REST, np extensions.NetworkPolicy, t *testing.T) (extensions.NetworkPolicy, error) { func createNetworkPolicy(storage *REST, np extensions.NetworkPolicy, t *testing.T) (extensions.NetworkPolicy, error) {
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), np.Namespace) ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), np.Namespace)
obj, err := storage.Create(ctx, &np) obj, err := storage.Create(ctx, &np, false)
if err != nil { if err != nil {
t.Errorf("Failed to create NetworkPolicy, %v", err) t.Errorf("Failed to create NetworkPolicy, %v", err)
} }
......
...@@ -99,12 +99,12 @@ func NetworkPolicyToSelectableFields(networkPolicy *extensions.NetworkPolicy) fi ...@@ -99,12 +99,12 @@ func NetworkPolicyToSelectableFields(networkPolicy *extensions.NetworkPolicy) fi
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
networkPolicy, ok := obj.(*extensions.NetworkPolicy) networkPolicy, ok := obj.(*extensions.NetworkPolicy)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not a NetworkPolicy.") return nil, nil, false, fmt.Errorf("given object is not a NetworkPolicy.")
} }
return labels.Set(networkPolicy.ObjectMeta.Labels), NetworkPolicyToSelectableFields(networkPolicy), nil return labels.Set(networkPolicy.ObjectMeta.Labels), NetworkPolicyToSelectableFields(networkPolicy), networkPolicy.Initializers != nil, nil
} }
// MatchNetworkPolicy is the filter used by the generic etcd backend to watch events // MatchNetworkPolicy is the filter used by the generic etcd backend to watch events
......
...@@ -77,12 +77,12 @@ func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.O ...@@ -77,12 +77,12 @@ func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.O
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
psp, ok := obj.(*extensions.PodSecurityPolicy) psp, ok := obj.(*extensions.PodSecurityPolicy)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not a pod security policy.") return nil, nil, false, fmt.Errorf("given object is not a pod security policy.")
} }
return labels.Set(psp.ObjectMeta.Labels), PodSecurityPolicyToSelectableFields(psp), nil return labels.Set(psp.ObjectMeta.Labels), PodSecurityPolicyToSelectableFields(psp), psp.Initializers != nil, nil
} }
// Matcher returns a generic matcher for a given label and field selector. // Matcher returns a generic matcher for a given label and field selector.
......
...@@ -75,7 +75,7 @@ func (s *storage) GetReplicaSet(ctx genericapirequest.Context, replicaSetID stri ...@@ -75,7 +75,7 @@ func (s *storage) GetReplicaSet(ctx genericapirequest.Context, replicaSetID stri
} }
func (s *storage) CreateReplicaSet(ctx genericapirequest.Context, replicaSet *extensions.ReplicaSet) (*extensions.ReplicaSet, error) { func (s *storage) CreateReplicaSet(ctx genericapirequest.Context, replicaSet *extensions.ReplicaSet) (*extensions.ReplicaSet, error) {
obj, err := s.Create(ctx, replicaSet) obj, err := s.Create(ctx, replicaSet, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -47,7 +47,7 @@ func newStorage(t *testing.T) (*ReplicaSetStorage, *etcdtesting.EtcdTestServer) ...@@ -47,7 +47,7 @@ func newStorage(t *testing.T) (*ReplicaSetStorage, *etcdtesting.EtcdTestServer)
// createReplicaSet is a helper function that returns a ReplicaSet with the updated resource version. // createReplicaSet is a helper function that returns a ReplicaSet with the updated resource version.
func createReplicaSet(storage *REST, rs extensions.ReplicaSet, t *testing.T) (extensions.ReplicaSet, error) { func createReplicaSet(storage *REST, rs extensions.ReplicaSet, t *testing.T) (extensions.ReplicaSet, error) {
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), rs.Namespace) ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), rs.Namespace)
obj, err := storage.Create(ctx, &rs) obj, err := storage.Create(ctx, &rs, false)
if err != nil { if err != nil {
t.Errorf("Failed to create ReplicaSet, %v", err) t.Errorf("Failed to create ReplicaSet, %v", err)
} }
......
...@@ -122,12 +122,12 @@ func ReplicaSetToSelectableFields(rs *extensions.ReplicaSet) fields.Set { ...@@ -122,12 +122,12 @@ func ReplicaSetToSelectableFields(rs *extensions.ReplicaSet) fields.Set {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
rs, ok := obj.(*extensions.ReplicaSet) rs, ok := obj.(*extensions.ReplicaSet)
if !ok { if !ok {
return nil, nil, fmt.Errorf("Given object is not a ReplicaSet.") return nil, nil, false, fmt.Errorf("given object is not a ReplicaSet.")
} }
return labels.Set(rs.ObjectMeta.Labels), ReplicaSetToSelectableFields(rs), nil return labels.Set(rs.ObjectMeta.Labels), ReplicaSetToSelectableFields(rs), rs.Initializers != nil, nil
} }
// MatchReplicaSet is the filter used by the generic etcd backend to route // MatchReplicaSet is the filter used by the generic etcd backend to route
......
...@@ -79,12 +79,12 @@ func (strategy) AllowUnconditionalUpdate() bool { ...@@ -79,12 +79,12 @@ func (strategy) AllowUnconditionalUpdate() bool {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
tpr, ok := obj.(*extensions.ThirdPartyResource) tpr, ok := obj.(*extensions.ThirdPartyResource)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a ThirdPartyResource") return nil, nil, false, fmt.Errorf("not a ThirdPartyResource")
} }
return labels.Set(tpr.Labels), SelectableFields(tpr), nil return labels.Set(tpr.Labels), SelectableFields(tpr), tpr.Initializers != nil, nil
} }
// Matcher returns a generic matcher for a given label and field selector. // Matcher returns a generic matcher for a given label and field selector.
......
...@@ -68,7 +68,7 @@ func (s *storage) GetThirdPartyResourceData(ctx genericapirequest.Context, name ...@@ -68,7 +68,7 @@ func (s *storage) GetThirdPartyResourceData(ctx genericapirequest.Context, name
} }
func (s *storage) CreateThirdPartyResourceData(ctx genericapirequest.Context, ThirdPartyResourceData *extensions.ThirdPartyResourceData) (*extensions.ThirdPartyResourceData, error) { func (s *storage) CreateThirdPartyResourceData(ctx genericapirequest.Context, ThirdPartyResourceData *extensions.ThirdPartyResourceData) (*extensions.ThirdPartyResourceData, error) {
obj, err := s.Create(ctx, ThirdPartyResourceData) obj, err := s.Create(ctx, ThirdPartyResourceData, false)
return obj.(*extensions.ThirdPartyResourceData), err return obj.(*extensions.ThirdPartyResourceData), err
} }
......
...@@ -55,11 +55,11 @@ func (r *REST) isFrozen() bool { ...@@ -55,11 +55,11 @@ func (r *REST) isFrozen() bool {
} }
// Create is a wrapper to support Freeze. // Create is a wrapper to support Freeze.
func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
if r.isFrozen() { if r.isFrozen() {
return nil, errFrozen return nil, errFrozen
} }
return r.Store.Create(ctx, obj) return r.Store.Create(ctx, obj, includeUninitialized)
} }
// Update is a wrapper to support Freeze. // Update is a wrapper to support Freeze.
......
...@@ -77,12 +77,12 @@ func (strategy) AllowUnconditionalUpdate() bool { ...@@ -77,12 +77,12 @@ func (strategy) AllowUnconditionalUpdate() bool {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
tprd, ok := obj.(*extensions.ThirdPartyResourceData) tprd, ok := obj.(*extensions.ThirdPartyResourceData)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a ThirdPartyResourceData") return nil, nil, false, fmt.Errorf("not a ThirdPartyResourceData")
} }
return labels.Set(tprd.Labels), SelectableFields(tprd), nil return labels.Set(tprd.Labels), SelectableFields(tprd), tprd.Initializers != nil, nil
} }
// Matcher returns a generic matcher for a given label and field selector. // Matcher returns a generic matcher for a given label and field selector.
......
...@@ -57,7 +57,7 @@ func (s *storage) ListNetworkPolicies(ctx genericapirequest.Context, options *me ...@@ -57,7 +57,7 @@ func (s *storage) ListNetworkPolicies(ctx genericapirequest.Context, options *me
} }
func (s *storage) CreateNetworkPolicy(ctx genericapirequest.Context, np *networking.NetworkPolicy) error { func (s *storage) CreateNetworkPolicy(ctx genericapirequest.Context, np *networking.NetworkPolicy) error {
_, err := s.Create(ctx, np) _, err := s.Create(ctx, np, false)
return err return err
} }
......
...@@ -98,12 +98,12 @@ func SelectableFields(networkPolicy *networking.NetworkPolicy) fields.Set { ...@@ -98,12 +98,12 @@ func SelectableFields(networkPolicy *networking.NetworkPolicy) fields.Set {
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
networkPolicy, ok := obj.(*networking.NetworkPolicy) networkPolicy, ok := obj.(*networking.NetworkPolicy)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not a NetworkPolicy.") return nil, nil, false, fmt.Errorf("given object is not a NetworkPolicy.")
} }
return labels.Set(networkPolicy.ObjectMeta.Labels), SelectableFields(networkPolicy), nil return labels.Set(networkPolicy.ObjectMeta.Labels), SelectableFields(networkPolicy), networkPolicy.Initializers != nil, nil
} }
// Matcher is the filter used by the generic etcd backend to watch events // Matcher is the filter used by the generic etcd backend to watch events
......
...@@ -42,7 +42,7 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer) ...@@ -42,7 +42,7 @@ func newStorage(t *testing.T) (*REST, *StatusREST, *etcdtesting.EtcdTestServer)
// createPodDisruptionBudget is a helper function that returns a PodDisruptionBudget with the updated resource version. // createPodDisruptionBudget is a helper function that returns a PodDisruptionBudget with the updated resource version.
func createPodDisruptionBudget(storage *REST, pdb policy.PodDisruptionBudget, t *testing.T) (policy.PodDisruptionBudget, error) { func createPodDisruptionBudget(storage *REST, pdb policy.PodDisruptionBudget, t *testing.T) (policy.PodDisruptionBudget, error) {
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), pdb.Namespace) ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), pdb.Namespace)
obj, err := storage.Create(ctx, &pdb) obj, err := storage.Create(ctx, &pdb, false)
if err != nil { if err != nil {
t.Errorf("Failed to create PodDisruptionBudget, %v", err) t.Errorf("Failed to create PodDisruptionBudget, %v", err)
} }
......
...@@ -105,12 +105,12 @@ func PodDisruptionBudgetToSelectableFields(podDisruptionBudget *policy.PodDisrup ...@@ -105,12 +105,12 @@ func PodDisruptionBudgetToSelectableFields(podDisruptionBudget *policy.PodDisrup
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
podDisruptionBudget, ok := obj.(*policy.PodDisruptionBudget) podDisruptionBudget, ok := obj.(*policy.PodDisruptionBudget)
if !ok { if !ok {
return nil, nil, fmt.Errorf("given object is not a PodDisruptionBudget.") return nil, nil, false, fmt.Errorf("given object is not a PodDisruptionBudget.")
} }
return labels.Set(podDisruptionBudget.ObjectMeta.Labels), PodDisruptionBudgetToSelectableFields(podDisruptionBudget), nil return labels.Set(podDisruptionBudget.ObjectMeta.Labels), PodDisruptionBudgetToSelectableFields(podDisruptionBudget), podDisruptionBudget.Initializers != nil, nil
} }
// MatchPodDisruptionBudget is the filter used by the generic etcd backend to watch events // MatchPodDisruptionBudget is the filter used by the generic etcd backend to watch events
......
...@@ -39,9 +39,9 @@ func NewStorage(s rest.StandardStorage, ruleResolver rbacregistryvalidation.Auth ...@@ -39,9 +39,9 @@ func NewStorage(s rest.StandardStorage, ruleResolver rbacregistryvalidation.Auth
return &Storage{s, ruleResolver} return &Storage{s, ruleResolver}
} }
func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
if rbacregistry.EscalationAllowed(ctx) { if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Create(ctx, obj) return s.StandardStorage.Create(ctx, obj, includeUninitialized)
} }
clusterRole := obj.(*rbac.ClusterRole) clusterRole := obj.(*rbac.ClusterRole)
...@@ -49,7 +49,7 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run ...@@ -49,7 +49,7 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
return nil, errors.NewForbidden(groupResource, clusterRole.Name, err) return nil, errors.NewForbidden(groupResource, clusterRole.Name, err)
} }
return s.StandardStorage.Create(ctx, obj) return s.StandardStorage.Create(ctx, obj, includeUninitialized)
} }
func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) { func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
......
...@@ -57,7 +57,7 @@ func (s *storage) ListClusterRoles(ctx genericapirequest.Context, options *metai ...@@ -57,7 +57,7 @@ func (s *storage) ListClusterRoles(ctx genericapirequest.Context, options *metai
} }
func (s *storage) CreateClusterRole(ctx genericapirequest.Context, clusterRole *rbac.ClusterRole) error { func (s *storage) CreateClusterRole(ctx genericapirequest.Context, clusterRole *rbac.ClusterRole) error {
_, err := s.Create(ctx, clusterRole) _, err := s.Create(ctx, clusterRole, false)
return err return err
} }
......
...@@ -104,12 +104,12 @@ func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exac ...@@ -104,12 +104,12 @@ func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exac
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
role, ok := obj.(*rbac.ClusterRole) role, ok := obj.(*rbac.ClusterRole)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a ClusterRole") return nil, nil, false, fmt.Errorf("not a ClusterRole")
} }
return labels.Set(role.Labels), SelectableFields(role), nil return labels.Set(role.Labels), SelectableFields(role), role.Initializers != nil, nil
} }
// Matcher returns a generic matcher for a given label and field selector. // Matcher returns a generic matcher for a given label and field selector.
......
...@@ -43,14 +43,14 @@ func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleRe ...@@ -43,14 +43,14 @@ func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleRe
return &Storage{s, authorizer, ruleResolver} return &Storage{s, authorizer, ruleResolver}
} }
func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
if rbacregistry.EscalationAllowed(ctx) { if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Create(ctx, obj) return s.StandardStorage.Create(ctx, obj, includeUninitialized)
} }
clusterRoleBinding := obj.(*rbac.ClusterRoleBinding) clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
if rbacregistry.BindingAuthorized(ctx, clusterRoleBinding.RoleRef, metav1.NamespaceNone, s.authorizer) { if rbacregistry.BindingAuthorized(ctx, clusterRoleBinding.RoleRef, metav1.NamespaceNone, s.authorizer) {
return s.StandardStorage.Create(ctx, obj) return s.StandardStorage.Create(ctx, obj, includeUninitialized)
} }
rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, metav1.NamespaceNone) rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, metav1.NamespaceNone)
...@@ -60,7 +60,7 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run ...@@ -60,7 +60,7 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
return nil, errors.NewForbidden(groupResource, clusterRoleBinding.Name, err) return nil, errors.NewForbidden(groupResource, clusterRoleBinding.Name, err)
} }
return s.StandardStorage.Create(ctx, obj) return s.StandardStorage.Create(ctx, obj, includeUninitialized)
} }
func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) { func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
......
...@@ -57,7 +57,7 @@ func (s *storage) ListClusterRoleBindings(ctx genericapirequest.Context, options ...@@ -57,7 +57,7 @@ func (s *storage) ListClusterRoleBindings(ctx genericapirequest.Context, options
} }
func (s *storage) CreateClusterRoleBinding(ctx genericapirequest.Context, clusterRoleBinding *rbac.ClusterRoleBinding) error { func (s *storage) CreateClusterRoleBinding(ctx genericapirequest.Context, clusterRoleBinding *rbac.ClusterRoleBinding) error {
_, err := s.Create(ctx, clusterRoleBinding) _, err := s.Create(ctx, clusterRoleBinding, false)
return err return err
} }
......
...@@ -104,12 +104,12 @@ func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exac ...@@ -104,12 +104,12 @@ func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exac
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
roleBinding, ok := obj.(*rbac.ClusterRoleBinding) roleBinding, ok := obj.(*rbac.ClusterRoleBinding)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a ClusterRoleBinding") return nil, nil, false, fmt.Errorf("not a ClusterRoleBinding")
} }
return labels.Set(roleBinding.Labels), SelectableFields(roleBinding), nil return labels.Set(roleBinding.Labels), SelectableFields(roleBinding), roleBinding.Initializers != nil, nil
} }
// Matcher returns a generic matcher for a given label and field selector. // Matcher returns a generic matcher for a given label and field selector.
......
...@@ -39,9 +39,9 @@ func NewStorage(s rest.StandardStorage, ruleResolver rbacregistryvalidation.Auth ...@@ -39,9 +39,9 @@ func NewStorage(s rest.StandardStorage, ruleResolver rbacregistryvalidation.Auth
return &Storage{s, ruleResolver} return &Storage{s, ruleResolver}
} }
func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
if rbacregistry.EscalationAllowed(ctx) { if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Create(ctx, obj) return s.StandardStorage.Create(ctx, obj, includeUninitialized)
} }
role := obj.(*rbac.Role) role := obj.(*rbac.Role)
...@@ -49,7 +49,7 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run ...@@ -49,7 +49,7 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
return nil, errors.NewForbidden(groupResource, role.Name, err) return nil, errors.NewForbidden(groupResource, role.Name, err)
} }
return s.StandardStorage.Create(ctx, obj) return s.StandardStorage.Create(ctx, obj, includeUninitialized)
} }
func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) { func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
......
...@@ -57,7 +57,7 @@ func (s *storage) ListRoles(ctx genericapirequest.Context, options *metainternal ...@@ -57,7 +57,7 @@ func (s *storage) ListRoles(ctx genericapirequest.Context, options *metainternal
} }
func (s *storage) CreateRole(ctx genericapirequest.Context, role *rbac.Role) error { func (s *storage) CreateRole(ctx genericapirequest.Context, role *rbac.Role) error {
_, err := s.Create(ctx, role) _, err := s.Create(ctx, role, false)
return err return err
} }
......
...@@ -104,12 +104,12 @@ func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exac ...@@ -104,12 +104,12 @@ func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exac
} }
// GetAttrs returns labels and fields of a given object for filtering purposes. // GetAttrs returns labels and fields of a given object for filtering purposes.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) { func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
role, ok := obj.(*rbac.Role) role, ok := obj.(*rbac.Role)
if !ok { if !ok {
return nil, nil, fmt.Errorf("not a Role") return nil, nil, false, fmt.Errorf("not a Role")
} }
return labels.Set(role.Labels), SelectableFields(role), nil return labels.Set(role.Labels), SelectableFields(role), role.Initializers != nil, nil
} }
// Matcher returns a generic matcher for a given label and field selector. // Matcher returns a generic matcher for a given label and field selector.
......
...@@ -42,9 +42,9 @@ func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleRe ...@@ -42,9 +42,9 @@ func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleRe
return &Storage{s, authorizer, ruleResolver} return &Storage{s, authorizer, ruleResolver}
} }
func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) { func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object, includeUninitialized bool) (runtime.Object, error) {
if rbacregistry.EscalationAllowed(ctx) { if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Create(ctx, obj) return s.StandardStorage.Create(ctx, obj, includeUninitialized)
} }
// Get the namespace from the context (populated from the URL). // Get the namespace from the context (populated from the URL).
...@@ -56,7 +56,7 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run ...@@ -56,7 +56,7 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run
roleBinding := obj.(*rbac.RoleBinding) roleBinding := obj.(*rbac.RoleBinding)
if rbacregistry.BindingAuthorized(ctx, roleBinding.RoleRef, namespace, s.authorizer) { if rbacregistry.BindingAuthorized(ctx, roleBinding.RoleRef, namespace, s.authorizer) {
return s.StandardStorage.Create(ctx, obj) return s.StandardStorage.Create(ctx, obj, includeUninitialized)
} }
rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, namespace) rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, namespace)
...@@ -66,7 +66,7 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run ...@@ -66,7 +66,7 @@ func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (run
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil { if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
return nil, errors.NewForbidden(groupResource, roleBinding.Name, err) return nil, errors.NewForbidden(groupResource, roleBinding.Name, err)
} }
return s.StandardStorage.Create(ctx, obj) return s.StandardStorage.Create(ctx, obj, includeUninitialized)
} }
func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) { func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment