mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 05:57:25 +00:00
API
This commit is contained in:
parent
e4aa9db258
commit
5bfacf59f6
@ -104,7 +104,7 @@ func TestConfigMapController(t *testing.T) {
|
|||||||
// There should be 2 updates to add both the finalizers.
|
// There should be 2 updates to add both the finalizers.
|
||||||
updatedConfigMap := GetConfigMapFromChan(configmapUpdateChan)
|
updatedConfigMap := GetConfigMapFromChan(configmapUpdateChan)
|
||||||
assert.True(t, configmapController.hasFinalizerFunc(updatedConfigMap, deletionhelper.FinalizerDeleteFromUnderlyingClusters))
|
assert.True(t, configmapController.hasFinalizerFunc(updatedConfigMap, deletionhelper.FinalizerDeleteFromUnderlyingClusters))
|
||||||
assert.True(t, configmapController.hasFinalizerFunc(updatedConfigMap, metav1.FinalizerOrphan))
|
assert.True(t, configmapController.hasFinalizerFunc(updatedConfigMap, metav1.FinalizerOrphanDependents))
|
||||||
|
|
||||||
// Verify that the configmap is created in underlying cluster1.
|
// Verify that the configmap is created in underlying cluster1.
|
||||||
createdConfigMap := GetConfigMapFromChan(cluster1CreateChan)
|
createdConfigMap := GetConfigMapFromChan(cluster1CreateChan)
|
||||||
|
@ -105,7 +105,7 @@ func TestDaemonSetController(t *testing.T) {
|
|||||||
// There should be an update to add both the finalizers.
|
// There should be an update to add both the finalizers.
|
||||||
updatedDaemonSet := GetDaemonSetFromChan(daemonsetUpdateChan)
|
updatedDaemonSet := GetDaemonSetFromChan(daemonsetUpdateChan)
|
||||||
assert.True(t, daemonsetController.hasFinalizerFunc(updatedDaemonSet, deletionhelper.FinalizerDeleteFromUnderlyingClusters))
|
assert.True(t, daemonsetController.hasFinalizerFunc(updatedDaemonSet, deletionhelper.FinalizerDeleteFromUnderlyingClusters))
|
||||||
assert.True(t, daemonsetController.hasFinalizerFunc(updatedDaemonSet, metav1.FinalizerOrphan))
|
assert.True(t, daemonsetController.hasFinalizerFunc(updatedDaemonSet, metav1.FinalizerOrphanDependents))
|
||||||
daemonset1 = *updatedDaemonSet
|
daemonset1 = *updatedDaemonSet
|
||||||
|
|
||||||
createdDaemonSet := GetDaemonSetFromChan(cluster1CreateChan)
|
createdDaemonSet := GetDaemonSetFromChan(cluster1CreateChan)
|
||||||
|
@ -146,7 +146,7 @@ func TestIngressController(t *testing.T) {
|
|||||||
// There should be an update to add both the finalizers.
|
// There should be an update to add both the finalizers.
|
||||||
updatedIngress := GetIngressFromChan(t, fedIngressUpdateChan)
|
updatedIngress := GetIngressFromChan(t, fedIngressUpdateChan)
|
||||||
assert.True(t, ingressController.hasFinalizerFunc(updatedIngress, deletionhelper.FinalizerDeleteFromUnderlyingClusters))
|
assert.True(t, ingressController.hasFinalizerFunc(updatedIngress, deletionhelper.FinalizerDeleteFromUnderlyingClusters))
|
||||||
assert.True(t, ingressController.hasFinalizerFunc(updatedIngress, metav1.FinalizerOrphan), fmt.Sprintf("ingress does not have the orphan finalizer: %v", updatedIngress))
|
assert.True(t, ingressController.hasFinalizerFunc(updatedIngress, metav1.FinalizerOrphanDependents), fmt.Sprintf("ingress does not have the orphan finalizer: %v", updatedIngress))
|
||||||
fedIngress = *updatedIngress
|
fedIngress = *updatedIngress
|
||||||
|
|
||||||
t.Log("Checking that Ingress was correctly created in cluster 1")
|
t.Log("Checking that Ingress was correctly created in cluster 1")
|
||||||
@ -319,7 +319,7 @@ func WaitForFinalizersInFederationStore(ingressController *IngressController, st
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
ingress := obj.(*extensionsv1beta1.Ingress)
|
ingress := obj.(*extensionsv1beta1.Ingress)
|
||||||
if ingressController.hasFinalizerFunc(ingress, metav1.FinalizerOrphan) &&
|
if ingressController.hasFinalizerFunc(ingress, metav1.FinalizerOrphanDependents) &&
|
||||||
ingressController.hasFinalizerFunc(ingress, deletionhelper.FinalizerDeleteFromUnderlyingClusters) {
|
ingressController.hasFinalizerFunc(ingress, deletionhelper.FinalizerDeleteFromUnderlyingClusters) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ func TestNamespaceController(t *testing.T) {
|
|||||||
// Delete the namespace with orphan finalizer (let namespaces
|
// Delete the namespace with orphan finalizer (let namespaces
|
||||||
// in underlying clusters be as is).
|
// in underlying clusters be as is).
|
||||||
// TODO: Add a test without orphan finalizer.
|
// TODO: Add a test without orphan finalizer.
|
||||||
ns1.ObjectMeta.Finalizers = append(ns1.ObjectMeta.Finalizers, metav1.FinalizerOrphan)
|
ns1.ObjectMeta.Finalizers = append(ns1.ObjectMeta.Finalizers, metav1.FinalizerOrphanDependents)
|
||||||
ns1.DeletionTimestamp = &metav1.Time{Time: time.Now()}
|
ns1.DeletionTimestamp = &metav1.Time{Time: time.Now()}
|
||||||
namespaceWatch.Modify(&ns1)
|
namespaceWatch.Modify(&ns1)
|
||||||
assert.Equal(t, ns1.Name, GetStringFromChan(nsDeleteChan))
|
assert.Equal(t, ns1.Name, GetStringFromChan(nsDeleteChan))
|
||||||
|
@ -105,7 +105,7 @@ func TestSecretController(t *testing.T) {
|
|||||||
// There should be an update to add both the finalizers.
|
// There should be an update to add both the finalizers.
|
||||||
updatedSecret := GetSecretFromChan(secretUpdateChan)
|
updatedSecret := GetSecretFromChan(secretUpdateChan)
|
||||||
assert.True(t, secretController.hasFinalizerFunc(updatedSecret, deletionhelper.FinalizerDeleteFromUnderlyingClusters))
|
assert.True(t, secretController.hasFinalizerFunc(updatedSecret, deletionhelper.FinalizerDeleteFromUnderlyingClusters))
|
||||||
assert.True(t, secretController.hasFinalizerFunc(updatedSecret, metav1.FinalizerOrphan))
|
assert.True(t, secretController.hasFinalizerFunc(updatedSecret, metav1.FinalizerOrphanDependents))
|
||||||
secret1 = *updatedSecret
|
secret1 = *updatedSecret
|
||||||
|
|
||||||
// Verify that the secret is created in underlying cluster1.
|
// Verify that the secret is created in underlying cluster1.
|
||||||
|
@ -93,8 +93,8 @@ func (dh *DeletionHelper) EnsureFinalizers(obj runtime.Object) (
|
|||||||
if !dh.hasFinalizerFunc(obj, FinalizerDeleteFromUnderlyingClusters) {
|
if !dh.hasFinalizerFunc(obj, FinalizerDeleteFromUnderlyingClusters) {
|
||||||
finalizers = append(finalizers, FinalizerDeleteFromUnderlyingClusters)
|
finalizers = append(finalizers, FinalizerDeleteFromUnderlyingClusters)
|
||||||
}
|
}
|
||||||
if !dh.hasFinalizerFunc(obj, metav1.FinalizerOrphan) {
|
if !dh.hasFinalizerFunc(obj, metav1.FinalizerOrphanDependents) {
|
||||||
finalizers = append(finalizers, metav1.FinalizerOrphan)
|
finalizers = append(finalizers, metav1.FinalizerOrphanDependents)
|
||||||
}
|
}
|
||||||
if len(finalizers) != 0 {
|
if len(finalizers) != 0 {
|
||||||
glog.V(2).Infof("Adding finalizers %v to %s", finalizers, dh.objNameFunc(obj))
|
glog.V(2).Infof("Adding finalizers %v to %s", finalizers, dh.objNameFunc(obj))
|
||||||
@ -117,7 +117,7 @@ func (dh *DeletionHelper) HandleObjectInUnderlyingClusters(obj runtime.Object) (
|
|||||||
glog.V(2).Infof("obj does not have %s finalizer. Nothing to do", FinalizerDeleteFromUnderlyingClusters)
|
glog.V(2).Infof("obj does not have %s finalizer. Nothing to do", FinalizerDeleteFromUnderlyingClusters)
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
hasOrphanFinalizer := dh.hasFinalizerFunc(obj, metav1.FinalizerOrphan)
|
hasOrphanFinalizer := dh.hasFinalizerFunc(obj, metav1.FinalizerOrphanDependents)
|
||||||
if hasOrphanFinalizer {
|
if hasOrphanFinalizer {
|
||||||
glog.V(2).Infof("Found finalizer orphan. Nothing to do, just remove the finalizer")
|
glog.V(2).Infof("Found finalizer orphan. Nothing to do, just remove the finalizer")
|
||||||
// If the obj has FinalizerOrphan finalizer, then we need to orphan the
|
// If the obj has FinalizerOrphan finalizer, then we need to orphan the
|
||||||
@ -127,7 +127,7 @@ func (dh *DeletionHelper) HandleObjectInUnderlyingClusters(obj runtime.Object) (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return obj, err
|
return obj, err
|
||||||
}
|
}
|
||||||
return dh.removeFinalizerFunc(obj, metav1.FinalizerOrphan)
|
return dh.removeFinalizerFunc(obj, metav1.FinalizerOrphanDependents)
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.V(2).Infof("Deleting obj %s from underlying clusters", objName)
|
glog.V(2).Infof("Deleting obj %s from underlying clusters", objName)
|
||||||
|
@ -244,7 +244,7 @@ func IsServiceIPRequested(service *Service) bool {
|
|||||||
|
|
||||||
var standardFinalizers = sets.NewString(
|
var standardFinalizers = sets.NewString(
|
||||||
string(FinalizerKubernetes),
|
string(FinalizerKubernetes),
|
||||||
metav1.FinalizerOrphan,
|
metav1.FinalizerOrphanDependents,
|
||||||
)
|
)
|
||||||
|
|
||||||
// HasAnnotation returns a bool if passed in annotation exists
|
// HasAnnotation returns a bool if passed in annotation exists
|
||||||
|
@ -20,8 +20,6 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/gofuzz"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@ -31,50 +29,6 @@ import (
|
|||||||
|
|
||||||
var _ metav1.Object = &metav1.ObjectMeta{}
|
var _ metav1.Object = &metav1.ObjectMeta{}
|
||||||
|
|
||||||
func getObjectMetaAndOwnerReferences() (objectMeta metav1.ObjectMeta, metaOwnerReferences []metav1.OwnerReference) {
|
|
||||||
fuzz.New().NilChance(.5).NumElements(1, 5).Fuzz(&objectMeta)
|
|
||||||
references := objectMeta.OwnerReferences
|
|
||||||
metaOwnerReferences = make([]metav1.OwnerReference, 0)
|
|
||||||
for i := 0; i < len(references); i++ {
|
|
||||||
metaOwnerReferences = append(metaOwnerReferences, metav1.OwnerReference{
|
|
||||||
Kind: references[i].Kind,
|
|
||||||
Name: references[i].Name,
|
|
||||||
UID: references[i].UID,
|
|
||||||
APIVersion: references[i].APIVersion,
|
|
||||||
Controller: references[i].Controller,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if len(references) == 0 {
|
|
||||||
objectMeta.OwnerReferences = make([]metav1.OwnerReference, 0)
|
|
||||||
}
|
|
||||||
return objectMeta, metaOwnerReferences
|
|
||||||
}
|
|
||||||
|
|
||||||
func testGetOwnerReferences(t *testing.T) {
|
|
||||||
meta, expected := getObjectMetaAndOwnerReferences()
|
|
||||||
refs := meta.GetOwnerReferences()
|
|
||||||
if !reflect.DeepEqual(refs, expected) {
|
|
||||||
t.Errorf("expect %v\n got %v", expected, refs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testSetOwnerReferences(t *testing.T) {
|
|
||||||
expected, newRefs := getObjectMetaAndOwnerReferences()
|
|
||||||
objectMeta := &metav1.ObjectMeta{}
|
|
||||||
objectMeta.SetOwnerReferences(newRefs)
|
|
||||||
if !reflect.DeepEqual(expected.OwnerReferences, objectMeta.OwnerReferences) {
|
|
||||||
t.Errorf("expect: %#v\n got: %#v", expected.OwnerReferences, objectMeta.OwnerReferences)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAccessOwnerReferences(t *testing.T) {
|
|
||||||
fuzzIter := 5
|
|
||||||
for i := 0; i < fuzzIter; i++ {
|
|
||||||
testGetOwnerReferences(t)
|
|
||||||
testSetOwnerReferences(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAccessorImplementations(t *testing.T) {
|
func TestAccessorImplementations(t *testing.T) {
|
||||||
for _, gv := range api.Registry.EnabledVersions() {
|
for _, gv := range api.Registry.EnabledVersions() {
|
||||||
internalGV := schema.GroupVersion{Group: gv.Group, Version: runtime.APIVersionInternal}
|
internalGV := schema.GroupVersion{Group: gv.Group, Version: runtime.APIVersionInternal}
|
||||||
|
@ -3000,6 +3000,20 @@ type Preconditions struct {
|
|||||||
UID *types.UID
|
UID *types.UID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeletionPropagation decides whether and how garbage collection will be performed.
|
||||||
|
type DeletionPropagation string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Orphans the dependents.
|
||||||
|
DeletePropagationOrphan DeletionPropagation = "Orphan"
|
||||||
|
// Deletes the object from the key-value store, the garbage collector will delete the dependents in the background.
|
||||||
|
DeletePropagationBackground DeletionPropagation = "Background"
|
||||||
|
// The object exists in the key-value store until the garbage collector deletes all the dependents whose ownerReference.blockOwnerDeletion=true from the key-value store.
|
||||||
|
// API sever will put the "DeletingDependents" finalizer on the object, and sets its deletionTimestamp.
|
||||||
|
// This policy is cascading, i.e., the dependents will be deleted with Foreground.
|
||||||
|
DeletePropagationForeground DeletionPropagation = "Foreground"
|
||||||
|
)
|
||||||
|
|
||||||
// DeleteOptions may be provided when deleting an API object
|
// DeleteOptions may be provided when deleting an API object
|
||||||
// DEPRECATED: This type has been moved to meta/v1 and will be removed soon.
|
// DEPRECATED: This type has been moved to meta/v1 and will be removed soon.
|
||||||
type DeleteOptions struct {
|
type DeleteOptions struct {
|
||||||
@ -3016,10 +3030,18 @@ type DeleteOptions struct {
|
|||||||
// +optional
|
// +optional
|
||||||
Preconditions *Preconditions
|
Preconditions *Preconditions
|
||||||
|
|
||||||
|
// Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7.
|
||||||
// Should the dependent objects be orphaned. If true/false, the "orphan"
|
// Should the dependent objects be orphaned. If true/false, the "orphan"
|
||||||
// finalizer will be added to/removed from the object's finalizers list.
|
// finalizer will be added to/removed from the object's finalizers list.
|
||||||
|
// Either this field or PropagationPolicy may be set, but not both.
|
||||||
// +optional
|
// +optional
|
||||||
OrphanDependents *bool
|
OrphanDependents *bool
|
||||||
|
|
||||||
|
// Whether and how garbage collection will be performed.
|
||||||
|
// Defaults to Default.
|
||||||
|
// Either this field or OrphanDependents may be set, but not both.
|
||||||
|
// +optional
|
||||||
|
PropagationPolicy *DeletionPropagation
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListOptions is the query options to a standard REST list call, and has future support for
|
// ListOptions is the query options to a standard REST list call, and has future support for
|
||||||
|
@ -84,7 +84,7 @@ func IsServiceIPRequested(service *Service) bool {
|
|||||||
|
|
||||||
var standardFinalizers = sets.NewString(
|
var standardFinalizers = sets.NewString(
|
||||||
string(FinalizerKubernetes),
|
string(FinalizerKubernetes),
|
||||||
metav1.FinalizerOrphan,
|
metav1.FinalizerOrphanDependents,
|
||||||
)
|
)
|
||||||
|
|
||||||
func IsStandardFinalizerName(str string) bool {
|
func IsStandardFinalizerName(str string) bool {
|
||||||
|
@ -63,6 +63,10 @@ func (meta *ObjectMeta) GetOwnerReferences() []metav1.OwnerReference {
|
|||||||
value := *meta.OwnerReferences[i].Controller
|
value := *meta.OwnerReferences[i].Controller
|
||||||
ret[i].Controller = &value
|
ret[i].Controller = &value
|
||||||
}
|
}
|
||||||
|
if meta.OwnerReferences[i].BlockOwnerDeletion != nil {
|
||||||
|
value := *meta.OwnerReferences[i].BlockOwnerDeletion
|
||||||
|
ret[i].BlockOwnerDeletion = &value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@ -78,6 +82,10 @@ func (meta *ObjectMeta) SetOwnerReferences(references []metav1.OwnerReference) {
|
|||||||
value := *references[i].Controller
|
value := *references[i].Controller
|
||||||
newReferences[i].Controller = &value
|
newReferences[i].Controller = &value
|
||||||
}
|
}
|
||||||
|
if references[i].BlockOwnerDeletion != nil {
|
||||||
|
value := *references[i].BlockOwnerDeletion
|
||||||
|
newReferences[i].BlockOwnerDeletion = &value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
meta.OwnerReferences = newReferences
|
meta.OwnerReferences = newReferences
|
||||||
}
|
}
|
||||||
|
@ -3432,6 +3432,20 @@ type Preconditions struct {
|
|||||||
UID *types.UID `json:"uid,omitempty" protobuf:"bytes,1,opt,name=uid,casttype=k8s.io/apimachinery/pkg/types.UID"`
|
UID *types.UID `json:"uid,omitempty" protobuf:"bytes,1,opt,name=uid,casttype=k8s.io/apimachinery/pkg/types.UID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeletionPropagation decides if a deletion will propagate to the dependents of the object, and how the garbage collector will handle the propagation.
|
||||||
|
type DeletionPropagation string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Orphans the dependents.
|
||||||
|
DeletePropagationOrphan DeletionPropagation = "Orphan"
|
||||||
|
// Deletes the object from the key-value store, the garbage collector will delete the dependents in the background.
|
||||||
|
DeletePropagationBackground DeletionPropagation = "Background"
|
||||||
|
// The object exists in the key-value store until the garbage collector deletes all the dependents whose ownerReference.blockOwnerDeletion=true from the key-value store.
|
||||||
|
// API sever will put the "DeletingDependents" finalizer on the object, and sets its deletionTimestamp.
|
||||||
|
// This policy is cascading, i.e., the dependents will be deleted with Foreground.
|
||||||
|
DeletePropagationForeground DeletionPropagation = "Foreground"
|
||||||
|
)
|
||||||
|
|
||||||
// DeleteOptions may be provided when deleting an API object
|
// DeleteOptions may be provided when deleting an API object
|
||||||
// DEPRECATED: This type has been moved to meta/v1 and will be removed soon.
|
// DEPRECATED: This type has been moved to meta/v1 and will be removed soon.
|
||||||
// +k8s:openapi-gen=false
|
// +k8s:openapi-gen=false
|
||||||
@ -3450,10 +3464,18 @@ type DeleteOptions struct {
|
|||||||
// +optional
|
// +optional
|
||||||
Preconditions *Preconditions `json:"preconditions,omitempty" protobuf:"bytes,2,opt,name=preconditions"`
|
Preconditions *Preconditions `json:"preconditions,omitempty" protobuf:"bytes,2,opt,name=preconditions"`
|
||||||
|
|
||||||
|
// Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7.
|
||||||
// Should the dependent objects be orphaned. If true/false, the "orphan"
|
// Should the dependent objects be orphaned. If true/false, the "orphan"
|
||||||
// finalizer will be added to/removed from the object's finalizers list.
|
// finalizer will be added to/removed from the object's finalizers list.
|
||||||
|
// Either this field or PropagationPolicy may be set, but not both.
|
||||||
// +optional
|
// +optional
|
||||||
OrphanDependents *bool `json:"orphanDependents,omitempty" protobuf:"varint,3,opt,name=orphanDependents"`
|
OrphanDependents *bool `json:"orphanDependents,omitempty" protobuf:"varint,3,opt,name=orphanDependents"`
|
||||||
|
|
||||||
|
// Whether and how garbage collection will be performed.
|
||||||
|
// Defaults to Default.
|
||||||
|
// Either this field or OrphanDependents may be set, but not both.
|
||||||
|
// +optional
|
||||||
|
PropagationPolicy *DeletionPropagation
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListOptions is the query options to a standard REST list call.
|
// ListOptions is the query options to a standard REST list call.
|
||||||
|
@ -295,7 +295,6 @@ func ValidateObjectMeta(meta *metav1.ObjectMeta, requiresNamespace bool, nameFn
|
|||||||
for i := range meta.Finalizers {
|
for i := range meta.Finalizers {
|
||||||
allErrs = append(allErrs, validateKubeFinalizerName(string(meta.Finalizers[i]), fldPath.Child("finalizers").Index(i))...)
|
allErrs = append(allErrs, validateKubeFinalizerName(string(meta.Finalizers[i]), fldPath.Child("finalizers").Index(i))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +335,7 @@ type MyAPIObject2 struct {
|
|||||||
metav1.ObjectMeta
|
metav1.ObjectMeta
|
||||||
}
|
}
|
||||||
|
|
||||||
func getObjectMetaAndOwnerRefereneces() (myAPIObject2 MyAPIObject2, metaOwnerReferences []metav1.OwnerReference) {
|
func getObjectMetaAndOwnerReferences() (myAPIObject2 MyAPIObject2, metaOwnerReferences []metav1.OwnerReference) {
|
||||||
fuzz.New().NilChance(.5).NumElements(1, 5).Fuzz(&myAPIObject2)
|
fuzz.New().NilChance(.5).NumElements(1, 5).Fuzz(&myAPIObject2)
|
||||||
references := myAPIObject2.ObjectMeta.OwnerReferences
|
references := myAPIObject2.ObjectMeta.OwnerReferences
|
||||||
// This is necessary for the test to pass because the getter will return a
|
// This is necessary for the test to pass because the getter will return a
|
||||||
@ -343,11 +343,12 @@ func getObjectMetaAndOwnerRefereneces() (myAPIObject2 MyAPIObject2, metaOwnerRef
|
|||||||
metaOwnerReferences = make([]metav1.OwnerReference, 0)
|
metaOwnerReferences = make([]metav1.OwnerReference, 0)
|
||||||
for i := 0; i < len(references); i++ {
|
for i := 0; i < len(references); i++ {
|
||||||
metaOwnerReferences = append(metaOwnerReferences, metav1.OwnerReference{
|
metaOwnerReferences = append(metaOwnerReferences, metav1.OwnerReference{
|
||||||
Kind: references[i].Kind,
|
Kind: references[i].Kind,
|
||||||
Name: references[i].Name,
|
Name: references[i].Name,
|
||||||
UID: references[i].UID,
|
UID: references[i].UID,
|
||||||
APIVersion: references[i].APIVersion,
|
APIVersion: references[i].APIVersion,
|
||||||
Controller: references[i].Controller,
|
Controller: references[i].Controller,
|
||||||
|
BlockOwnerDeletion: references[i].BlockOwnerDeletion,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if len(references) == 0 {
|
if len(references) == 0 {
|
||||||
@ -359,7 +360,7 @@ func getObjectMetaAndOwnerRefereneces() (myAPIObject2 MyAPIObject2, metaOwnerRef
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testGetOwnerReferences(t *testing.T) {
|
func testGetOwnerReferences(t *testing.T) {
|
||||||
obj, expected := getObjectMetaAndOwnerRefereneces()
|
obj, expected := getObjectMetaAndOwnerReferences()
|
||||||
accessor, err := meta.Accessor(&obj)
|
accessor, err := meta.Accessor(&obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
@ -371,7 +372,7 @@ func testGetOwnerReferences(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testSetOwnerReferences(t *testing.T) {
|
func testSetOwnerReferences(t *testing.T) {
|
||||||
expected, references := getObjectMetaAndOwnerRefereneces()
|
expected, references := getObjectMetaAndOwnerReferences()
|
||||||
obj := MyAPIObject2{}
|
obj := MyAPIObject2{}
|
||||||
accessor, err := meta.Accessor(&obj)
|
accessor, err := meta.Accessor(&obj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -123,6 +123,7 @@ func TestDecode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUnstructuredGetters(t *testing.T) {
|
func TestUnstructuredGetters(t *testing.T) {
|
||||||
|
trueVar := true
|
||||||
unstruct := unstructured.Unstructured{
|
unstruct := unstructured.Unstructured{
|
||||||
Object: map[string]interface{}{
|
Object: map[string]interface{}{
|
||||||
"kind": "test_kind",
|
"kind": "test_kind",
|
||||||
@ -154,6 +155,10 @@ func TestUnstructuredGetters(t *testing.T) {
|
|||||||
"name": "podb",
|
"name": "podb",
|
||||||
"apiVersion": "v1",
|
"apiVersion": "v1",
|
||||||
"uid": "2",
|
"uid": "2",
|
||||||
|
// though these fields are of type *bool, but when
|
||||||
|
// decoded from JSON, they are unmarshalled as bool.
|
||||||
|
"controller": true,
|
||||||
|
"blockOwnerDeletion": true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"finalizers": []interface{}{
|
"finalizers": []interface{}{
|
||||||
@ -221,10 +226,12 @@ func TestUnstructuredGetters(t *testing.T) {
|
|||||||
UID: "1",
|
UID: "1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Kind: "Pod",
|
Kind: "Pod",
|
||||||
Name: "podb",
|
Name: "podb",
|
||||||
APIVersion: "v1",
|
APIVersion: "v1",
|
||||||
UID: "2",
|
UID: "2",
|
||||||
|
Controller: &trueVar,
|
||||||
|
BlockOwnerDeletion: &trueVar,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if got, want := refs, expectedOwnerReferences; !reflect.DeepEqual(got, want) {
|
if got, want := refs, expectedOwnerReferences; !reflect.DeepEqual(got, want) {
|
||||||
@ -263,18 +270,20 @@ func TestUnstructuredSetters(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"ownerReferences": []map[string]interface{}{
|
"ownerReferences": []map[string]interface{}{
|
||||||
{
|
{
|
||||||
"kind": "Pod",
|
"kind": "Pod",
|
||||||
"name": "poda",
|
"name": "poda",
|
||||||
"apiVersion": "v1",
|
"apiVersion": "v1",
|
||||||
"uid": "1",
|
"uid": "1",
|
||||||
"controller": (*bool)(nil),
|
"controller": (*bool)(nil),
|
||||||
|
"blockOwnerDeletion": (*bool)(nil),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": "Pod",
|
"kind": "Pod",
|
||||||
"name": "podb",
|
"name": "podb",
|
||||||
"apiVersion": "v1",
|
"apiVersion": "v1",
|
||||||
"uid": "2",
|
"uid": "2",
|
||||||
"controller": &trueVar,
|
"controller": &trueVar,
|
||||||
|
"blockOwnerDeletion": &trueVar,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"finalizers": []interface{}{
|
"finalizers": []interface{}{
|
||||||
@ -307,11 +316,12 @@ func TestUnstructuredSetters(t *testing.T) {
|
|||||||
UID: "1",
|
UID: "1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Kind: "Pod",
|
Kind: "Pod",
|
||||||
Name: "podb",
|
Name: "podb",
|
||||||
APIVersion: "v1",
|
APIVersion: "v1",
|
||||||
UID: "2",
|
UID: "2",
|
||||||
Controller: &trueVar,
|
Controller: &trueVar,
|
||||||
|
BlockOwnerDeletion: &trueVar,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
unstruct.SetOwnerReferences(newOwnerReferences)
|
unstruct.SetOwnerReferences(newOwnerReferences)
|
||||||
|
@ -143,7 +143,7 @@ func (r *REST) Delete(ctx genericapirequest.Context, name string, options *metav
|
|||||||
newFinalizers := []string{}
|
newFinalizers := []string{}
|
||||||
for i := range existingNamespace.ObjectMeta.Finalizers {
|
for i := range existingNamespace.ObjectMeta.Finalizers {
|
||||||
finalizer := existingNamespace.ObjectMeta.Finalizers[i]
|
finalizer := existingNamespace.ObjectMeta.Finalizers[i]
|
||||||
if string(finalizer) != metav1.FinalizerOrphan {
|
if string(finalizer) != metav1.FinalizerOrphanDependents {
|
||||||
newFinalizers = append(newFinalizers, finalizer)
|
newFinalizers = append(newFinalizers, finalizer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -334,6 +334,14 @@ func extractFromOwnerReference(v reflect.Value, o *metav1.OwnerReference) error
|
|||||||
controller := *controllerPtr
|
controller := *controllerPtr
|
||||||
o.Controller = &controller
|
o.Controller = &controller
|
||||||
}
|
}
|
||||||
|
var blockOwnerDeletionPtr *bool
|
||||||
|
if err := runtime.Field(v, "BlockOwnerDeletion", &blockOwnerDeletionPtr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if blockOwnerDeletionPtr != nil {
|
||||||
|
block := *blockOwnerDeletionPtr
|
||||||
|
o.BlockOwnerDeletion = &block
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,6 +365,12 @@ func setOwnerReference(v reflect.Value, o *metav1.OwnerReference) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if o.BlockOwnerDeletion != nil {
|
||||||
|
block := *(o.BlockOwnerDeletion)
|
||||||
|
if err := runtime.SetField(&block, v, "BlockOwnerDeletion"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,8 +171,26 @@ func ValidateObjectMeta(meta *metav1.ObjectMeta, requiresNamespace bool, nameFn
|
|||||||
allErrs = append(allErrs, v1validation.ValidateLabels(meta.Labels, fldPath.Child("labels"))...)
|
allErrs = append(allErrs, v1validation.ValidateLabels(meta.Labels, fldPath.Child("labels"))...)
|
||||||
allErrs = append(allErrs, ValidateAnnotations(meta.Annotations, fldPath.Child("annotations"))...)
|
allErrs = append(allErrs, ValidateAnnotations(meta.Annotations, fldPath.Child("annotations"))...)
|
||||||
allErrs = append(allErrs, ValidateOwnerReferences(meta.OwnerReferences, fldPath.Child("ownerReferences"))...)
|
allErrs = append(allErrs, ValidateOwnerReferences(meta.OwnerReferences, fldPath.Child("ownerReferences"))...)
|
||||||
for _, finalizer := range meta.Finalizers {
|
allErrs = append(allErrs, ValidateFinalizers(meta.Finalizers, fldPath.Child("finalizers"))...)
|
||||||
allErrs = append(allErrs, ValidateFinalizerName(finalizer, fldPath.Child("finalizers"))...)
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateFinalizers tests if the finalizers name are valid, and if there are conflicting finalizers.
|
||||||
|
func ValidateFinalizers(finalizers []string, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
hasFinalizerOrphanDependents := false
|
||||||
|
hasFinalizerDeleteDependents := false
|
||||||
|
for _, finalizer := range finalizers {
|
||||||
|
allErrs = append(allErrs, ValidateFinalizerName(finalizer, fldPath)...)
|
||||||
|
if finalizer == metav1.FinalizerOrphanDependents {
|
||||||
|
hasFinalizerOrphanDependents = true
|
||||||
|
}
|
||||||
|
if finalizer == metav1.FinalizerDeleteDependents {
|
||||||
|
hasFinalizerDeleteDependents = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hasFinalizerDeleteDependents && hasFinalizerOrphanDependents {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath, finalizers, fmt.Sprintf("finalizer %s and %s cannot be both set", metav1.FinalizerOrphanDependents, metav1.FinalizerDeleteDependents)))
|
||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
@ -277,6 +277,28 @@ func TestValidateFinalizersUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateFinalizersPreventConflictingFinalizers(t *testing.T) {
|
||||||
|
testcases := map[string]struct {
|
||||||
|
ObjectMeta metav1.ObjectMeta
|
||||||
|
ExpectedErr string
|
||||||
|
}{
|
||||||
|
"conflicting finalizers": {
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "test", ResourceVersion: "1", Finalizers: []string{metav1.FinalizerOrphanDependents, metav1.FinalizerDeleteDependents}},
|
||||||
|
ExpectedErr: "cannot be both set",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, tc := range testcases {
|
||||||
|
errs := ValidateObjectMeta(&tc.ObjectMeta, false, NameIsDNSSubdomain, field.NewPath("field"))
|
||||||
|
if len(errs) == 0 {
|
||||||
|
if len(tc.ExpectedErr) != 0 {
|
||||||
|
t.Errorf("case: %q, expected error to contain %q", name, tc.ExpectedErr)
|
||||||
|
}
|
||||||
|
} else if e, a := tc.ExpectedErr, errs.ToAggregate().Error(); !strings.Contains(a, e) {
|
||||||
|
t.Errorf("case: %q, expected error to contain %q, got error %q", name, e, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestValidateObjectMetaUpdatePreventsDeletionFieldMutation(t *testing.T) {
|
func TestValidateObjectMetaUpdatePreventsDeletionFieldMutation(t *testing.T) {
|
||||||
now := metav1.NewTime(time.Unix(1000, 0).UTC())
|
now := metav1.NewTime(time.Unix(1000, 0).UTC())
|
||||||
later := metav1.NewTime(time.Unix(2000, 0).UTC())
|
later := metav1.NewTime(time.Unix(2000, 0).UTC())
|
||||||
|
@ -174,6 +174,10 @@ func (meta *ObjectMeta) GetOwnerReferences() []OwnerReference {
|
|||||||
value := *meta.OwnerReferences[i].Controller
|
value := *meta.OwnerReferences[i].Controller
|
||||||
ret[i].Controller = &value
|
ret[i].Controller = &value
|
||||||
}
|
}
|
||||||
|
if meta.OwnerReferences[i].BlockOwnerDeletion != nil {
|
||||||
|
value := *meta.OwnerReferences[i].BlockOwnerDeletion
|
||||||
|
ret[i].BlockOwnerDeletion = &value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@ -189,6 +193,10 @@ func (meta *ObjectMeta) SetOwnerReferences(references []OwnerReference) {
|
|||||||
value := *references[i].Controller
|
value := *references[i].Controller
|
||||||
newReferences[i].Controller = &value
|
newReferences[i].Controller = &value
|
||||||
}
|
}
|
||||||
|
if references[i].BlockOwnerDeletion != nil {
|
||||||
|
value := *references[i].BlockOwnerDeletion
|
||||||
|
newReferences[i].BlockOwnerDeletion = &value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
meta.OwnerReferences = newReferences
|
meta.OwnerReferences = newReferences
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,8 @@ type ListMeta struct {
|
|||||||
|
|
||||||
// These are internal finalizer values for Kubernetes-like APIs, must be qualified name unless defined here
|
// These are internal finalizer values for Kubernetes-like APIs, must be qualified name unless defined here
|
||||||
const (
|
const (
|
||||||
FinalizerOrphan string = "orphan"
|
FinalizerOrphanDependents string = "orphan"
|
||||||
|
FinalizerDeleteDependents string = "foregroundDeletion"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ObjectMeta is metadata that all persisted resources must have, which includes all objects
|
// ObjectMeta is metadata that all persisted resources must have, which includes all objects
|
||||||
@ -255,6 +256,14 @@ type OwnerReference struct {
|
|||||||
// If true, this reference points to the managing controller.
|
// If true, this reference points to the managing controller.
|
||||||
// +optional
|
// +optional
|
||||||
Controller *bool `json:"controller,omitempty" protobuf:"varint,6,opt,name=controller"`
|
Controller *bool `json:"controller,omitempty" protobuf:"varint,6,opt,name=controller"`
|
||||||
|
// If true, AND if the owner has the "foregroundDeletion" finalizer, then
|
||||||
|
// the owner cannot be deleted from the key-value store until this
|
||||||
|
// reference is removed.
|
||||||
|
// Defaults to false.
|
||||||
|
// To set this field, a user needs "delete" permission of the owner,
|
||||||
|
// otherwise 422 (Unprocessable Entity) will be returned.
|
||||||
|
// +optional
|
||||||
|
BlockOwnerDeletion *bool `json:"blockOwnerDeletion,omitempty" protobuf:"varint,7,opt,name=blockOwnerDeletion"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListOptions is the query options to a standard REST list call.
|
// ListOptions is the query options to a standard REST list call.
|
||||||
@ -305,6 +314,24 @@ type GetOptions struct {
|
|||||||
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,1,opt,name=resourceVersion"`
|
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,1,opt,name=resourceVersion"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeletionPropagation decides if a deletion will propagate to the dependents of
|
||||||
|
// the object, and how the garbage collector will handle the propagation.
|
||||||
|
type DeletionPropagation string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Orphans the dependents.
|
||||||
|
DeletePropagationOrphan DeletionPropagation = "Orphan"
|
||||||
|
// Deletes the object from the key-value store, the garbage collector will
|
||||||
|
// delete the dependents in the background.
|
||||||
|
DeletePropagationBackground DeletionPropagation = "Background"
|
||||||
|
// The object exists in the key-value store until the garbage collector
|
||||||
|
// deletes all the dependents whose ownerReference.blockOwnerDeletion=true
|
||||||
|
// from the key-value store. API sever will put the "foregroundDeletion"
|
||||||
|
// finalizer on the object, and sets its deletionTimestamp. This policy is
|
||||||
|
// cascading, i.e., the dependents will be deleted with Foreground.
|
||||||
|
DeletePropagationForeground DeletionPropagation = "Foreground"
|
||||||
|
)
|
||||||
|
|
||||||
// DeleteOptions may be provided when deleting an API object.
|
// DeleteOptions may be provided when deleting an API object.
|
||||||
type DeleteOptions struct {
|
type DeleteOptions struct {
|
||||||
TypeMeta `json:",inline"`
|
TypeMeta `json:",inline"`
|
||||||
@ -321,10 +348,18 @@ type DeleteOptions struct {
|
|||||||
// +optional
|
// +optional
|
||||||
Preconditions *Preconditions `json:"preconditions,omitempty" protobuf:"bytes,2,opt,name=preconditions"`
|
Preconditions *Preconditions `json:"preconditions,omitempty" protobuf:"bytes,2,opt,name=preconditions"`
|
||||||
|
|
||||||
|
// Deprecated: please use the PropagationPolicy, this field will be deprecated in 1.7.
|
||||||
// Should the dependent objects be orphaned. If true/false, the "orphan"
|
// Should the dependent objects be orphaned. If true/false, the "orphan"
|
||||||
// finalizer will be added to/removed from the object's finalizers list.
|
// finalizer will be added to/removed from the object's finalizers list.
|
||||||
|
// Either this field or PropagationPolicy may be set, but not both.
|
||||||
// +optional
|
// +optional
|
||||||
OrphanDependents *bool `json:"orphanDependents,omitempty" protobuf:"varint,3,opt,name=orphanDependents"`
|
OrphanDependents *bool `json:"orphanDependents,omitempty" protobuf:"varint,3,opt,name=orphanDependents"`
|
||||||
|
|
||||||
|
// Whether and how garbage collection will be performed.
|
||||||
|
// Defaults to Default.
|
||||||
|
// Either this field or OrphanDependents may be set, but not both.
|
||||||
|
// +optional
|
||||||
|
PropagationPolicy *DeletionPropagation `json:"propagationPolicy,omitempty" protobuf:"varint,4,opt,name=propagationPolicy"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.
|
// Preconditions must be fulfilled before an operation (update, delete, etc.) is carried out.
|
||||||
|
@ -204,21 +204,31 @@ func (u *Unstructured) setNestedMap(value map[string]string, fields ...string) {
|
|||||||
|
|
||||||
func extractOwnerReference(src interface{}) metav1.OwnerReference {
|
func extractOwnerReference(src interface{}) metav1.OwnerReference {
|
||||||
v := src.(map[string]interface{})
|
v := src.(map[string]interface{})
|
||||||
controllerPtr, ok := (getNestedField(v, "controller")).(*bool)
|
// though this field is a *bool, but when decoded from JSON, it's
|
||||||
|
// unmarshalled as bool.
|
||||||
|
var controllerPtr *bool
|
||||||
|
controller, ok := (getNestedField(v, "controller")).(bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
controllerPtr = nil
|
controllerPtr = nil
|
||||||
} else {
|
} else {
|
||||||
if controllerPtr != nil {
|
controllerCopy := controller
|
||||||
controller := *controllerPtr
|
controllerPtr = &controllerCopy
|
||||||
controllerPtr = &controller
|
}
|
||||||
}
|
var blockOwnerDeletionPtr *bool
|
||||||
|
blockOwnerDeletion, ok := (getNestedField(v, "blockOwnerDeletion")).(bool)
|
||||||
|
if !ok {
|
||||||
|
blockOwnerDeletionPtr = nil
|
||||||
|
} else {
|
||||||
|
blockOwnerDeletionCopy := blockOwnerDeletion
|
||||||
|
blockOwnerDeletionPtr = &blockOwnerDeletionCopy
|
||||||
}
|
}
|
||||||
return metav1.OwnerReference{
|
return metav1.OwnerReference{
|
||||||
Kind: getNestedString(v, "kind"),
|
Kind: getNestedString(v, "kind"),
|
||||||
Name: getNestedString(v, "name"),
|
Name: getNestedString(v, "name"),
|
||||||
APIVersion: getNestedString(v, "apiVersion"),
|
APIVersion: getNestedString(v, "apiVersion"),
|
||||||
UID: (types.UID)(getNestedString(v, "uid")),
|
UID: (types.UID)(getNestedString(v, "uid")),
|
||||||
Controller: controllerPtr,
|
Controller: controllerPtr,
|
||||||
|
BlockOwnerDeletion: blockOwnerDeletionPtr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,11 +239,17 @@ func setOwnerReference(src metav1.OwnerReference) map[string]interface{} {
|
|||||||
controller := *controllerPtr
|
controller := *controllerPtr
|
||||||
controllerPtr = &controller
|
controllerPtr = &controller
|
||||||
}
|
}
|
||||||
|
blockOwnerDeletionPtr := src.BlockOwnerDeletion
|
||||||
|
if blockOwnerDeletionPtr != nil {
|
||||||
|
blockOwnerDeletion := *blockOwnerDeletionPtr
|
||||||
|
blockOwnerDeletionPtr = &blockOwnerDeletion
|
||||||
|
}
|
||||||
setNestedField(ret, src.Kind, "kind")
|
setNestedField(ret, src.Kind, "kind")
|
||||||
setNestedField(ret, src.Name, "name")
|
setNestedField(ret, src.Name, "name")
|
||||||
setNestedField(ret, src.APIVersion, "apiVersion")
|
setNestedField(ret, src.APIVersion, "apiVersion")
|
||||||
setNestedField(ret, string(src.UID), "uid")
|
setNestedField(ret, string(src.UID), "uid")
|
||||||
setNestedField(ret, controllerPtr, "controller")
|
setNestedField(ret, controllerPtr, "controller")
|
||||||
|
setNestedField(ret, blockOwnerDeletionPtr, "blockOwnerDeletion")
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ limitations under the License.
|
|||||||
package validation
|
package validation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/validation"
|
"k8s.io/apimachinery/pkg/util/validation"
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
@ -72,3 +74,17 @@ func ValidateLabels(labels map[string]string, fldPath *field.Path) field.ErrorLi
|
|||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ValidateDeleteOptions(options *metav1.DeleteOptions) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
if options.OrphanDependents != nil && options.PropagationPolicy != nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(field.NewPath(""), options, "OrphanDependents and DeletionPropagation cannot be both set"))
|
||||||
|
}
|
||||||
|
if options.PropagationPolicy != nil &&
|
||||||
|
*options.PropagationPolicy != metav1.DeletePropagationForeground &&
|
||||||
|
*options.PropagationPolicy != metav1.DeletePropagationBackground &&
|
||||||
|
*options.PropagationPolicy != metav1.DeletePropagationOrphan {
|
||||||
|
allErrs = append(allErrs, field.Invalid(field.NewPath(""), options, fmt.Sprintf("DeletionPropagation need to be one of %q, %q, %q or nil", metav1.DeletePropagationForeground, metav1.DeletePropagationBackground, metav1.DeletePropagationOrphan)))
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
@ -244,7 +244,7 @@ func IsServiceIPRequested(service *Service) bool {
|
|||||||
|
|
||||||
var standardFinalizers = sets.NewString(
|
var standardFinalizers = sets.NewString(
|
||||||
string(FinalizerKubernetes),
|
string(FinalizerKubernetes),
|
||||||
metav1.FinalizerOrphan,
|
metav1.FinalizerOrphanDependents,
|
||||||
)
|
)
|
||||||
|
|
||||||
// HasAnnotation returns a bool if passed in annotation exists
|
// HasAnnotation returns a bool if passed in annotation exists
|
||||||
|
@ -84,7 +84,7 @@ func IsServiceIPRequested(service *Service) bool {
|
|||||||
|
|
||||||
var standardFinalizers = sets.NewString(
|
var standardFinalizers = sets.NewString(
|
||||||
string(FinalizerKubernetes),
|
string(FinalizerKubernetes),
|
||||||
metav1.FinalizerOrphan,
|
metav1.FinalizerOrphanDependents,
|
||||||
)
|
)
|
||||||
|
|
||||||
func IsStandardFinalizerName(str string) bool {
|
func IsStandardFinalizerName(str string) bool {
|
||||||
|
Loading…
Reference in New Issue
Block a user