Support kubectl delete foreground

This commit is contained in:
zhouya0 2020-07-23 18:45:59 +08:00
parent d8937faf23
commit 383b5f6766
12 changed files with 170 additions and 104 deletions

View File

@ -244,7 +244,11 @@ func (o *ApplyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
return err return err
} }
o.DeleteOptions = o.DeleteFlags.ToOptions(o.DynamicClient, o.IOStreams) o.DeleteOptions, err = o.DeleteFlags.ToOptions(o.DynamicClient, o.IOStreams)
if err != nil {
return err
}
err = o.DeleteOptions.FilenameOptions.RequireFilenameOrKustomize() err = o.DeleteOptions.FilenameOptions.RequireFilenameOrKustomize()
if err != nil { if err != nil {
return err return err

View File

@ -25,6 +25,7 @@ import (
"github.com/jonboulle/clockwork" "github.com/jonboulle/clockwork"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
@ -58,7 +59,7 @@ type Patcher struct {
BackOff clockwork.Clock BackOff clockwork.Clock
Force bool Force bool
Cascade bool CascadingStrategy metav1.DeletionPropagation
Timeout time.Duration Timeout time.Duration
GracePeriod int GracePeriod int
@ -83,7 +84,7 @@ func newPatcher(o *ApplyOptions, info *resource.Info, helper *resource.Helper) (
Overwrite: o.Overwrite, Overwrite: o.Overwrite,
BackOff: clockwork.NewRealClock(), BackOff: clockwork.NewRealClock(),
Force: o.DeleteOptions.ForceDeletion, Force: o.DeleteOptions.ForceDeletion,
Cascade: o.DeleteOptions.Cascade, CascadingStrategy: o.DeleteOptions.CascadingStrategy,
Timeout: o.DeleteOptions.Timeout, Timeout: o.DeleteOptions.Timeout,
GracePeriod: o.DeleteOptions.GracePeriod, GracePeriod: o.DeleteOptions.GracePeriod,
OpenapiSchema: openapiSchema, OpenapiSchema: openapiSchema,
@ -92,7 +93,7 @@ func newPatcher(o *ApplyOptions, info *resource.Info, helper *resource.Helper) (
} }
func (p *Patcher) delete(namespace, name string) error { func (p *Patcher) delete(namespace, name string) error {
options := asDeleteOptions(p.Cascade, p.GracePeriod) options := asDeleteOptions(p.CascadingStrategy, p.GracePeriod)
_, err := p.Helper.DeleteWithOptions(namespace, name, &options) _, err := p.Helper.DeleteWithOptions(namespace, name, &options)
return err return err
} }

View File

@ -41,7 +41,7 @@ type pruner struct {
labelSelector string labelSelector string
fieldSelector string fieldSelector string
cascade bool cascadingStrategy metav1.DeletionPropagation
dryRunStrategy cmdutil.DryRunStrategy dryRunStrategy cmdutil.DryRunStrategy
gracePeriod int gracePeriod int
@ -59,7 +59,7 @@ func newPruner(o *ApplyOptions) pruner {
visitedUids: o.VisitedUids, visitedUids: o.VisitedUids,
visitedNamespaces: o.VisitedNamespaces, visitedNamespaces: o.VisitedNamespaces,
cascade: o.DeleteOptions.Cascade, cascadingStrategy: o.DeleteOptions.CascadingStrategy,
dryRunStrategy: o.DryRunStrategy, dryRunStrategy: o.DryRunStrategy,
gracePeriod: o.DeleteOptions.GracePeriod, gracePeriod: o.DeleteOptions.GracePeriod,
@ -139,27 +139,23 @@ func (p *pruner) prune(namespace string, mapping *meta.RESTMapping) error {
} }
func (p *pruner) delete(namespace, name string, mapping *meta.RESTMapping) error { func (p *pruner) delete(namespace, name string, mapping *meta.RESTMapping) error {
return runDelete(namespace, name, mapping, p.dynamicClient, p.cascade, p.gracePeriod, p.dryRunStrategy == cmdutil.DryRunServer) return runDelete(namespace, name, mapping, p.dynamicClient, p.cascadingStrategy, p.gracePeriod, p.dryRunStrategy == cmdutil.DryRunServer)
} }
func runDelete(namespace, name string, mapping *meta.RESTMapping, c dynamic.Interface, cascade bool, gracePeriod int, serverDryRun bool) error { func runDelete(namespace, name string, mapping *meta.RESTMapping, c dynamic.Interface, cascadingStrategy metav1.DeletionPropagation, gracePeriod int, serverDryRun bool) error {
options := asDeleteOptions(cascade, gracePeriod) options := asDeleteOptions(cascadingStrategy, gracePeriod)
if serverDryRun { if serverDryRun {
options.DryRun = []string{metav1.DryRunAll} options.DryRun = []string{metav1.DryRunAll}
} }
return c.Resource(mapping.Resource).Namespace(namespace).Delete(context.TODO(), name, options) return c.Resource(mapping.Resource).Namespace(namespace).Delete(context.TODO(), name, options)
} }
func asDeleteOptions(cascade bool, gracePeriod int) metav1.DeleteOptions { func asDeleteOptions(cascadingStrategy metav1.DeletionPropagation, gracePeriod int) metav1.DeleteOptions {
options := metav1.DeleteOptions{} options := metav1.DeleteOptions{}
if gracePeriod >= 0 { if gracePeriod >= 0 {
options = *metav1.NewDeleteOptions(int64(gracePeriod)) options = *metav1.NewDeleteOptions(int64(gracePeriod))
} }
policy := metav1.DeletePropagationForeground options.PropagationPolicy = &cascadingStrategy
if !cascade {
policy = metav1.DeletePropagationOrphan
}
options.PropagationPolicy = &policy
return options return options
} }

View File

@ -102,8 +102,8 @@ type DeleteOptions struct {
FieldSelector string FieldSelector string
DeleteAll bool DeleteAll bool
DeleteAllNamespaces bool DeleteAllNamespaces bool
CascadingStrategy metav1.DeletionPropagation
IgnoreNotFound bool IgnoreNotFound bool
Cascade bool
DeleteNow bool DeleteNow bool
ForceDeletion bool ForceDeletion bool
WaitForDeletion bool WaitForDeletion bool
@ -136,7 +136,8 @@ func NewCmdDelete(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra
Long: deleteLong, Long: deleteLong,
Example: deleteExample, Example: deleteExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
o := deleteFlags.ToOptions(nil, streams) o, err := deleteFlags.ToOptions(nil, streams)
cmdutil.CheckErr(err)
cmdutil.CheckErr(o.Complete(f, args, cmd)) cmdutil.CheckErr(o.Complete(f, args, cmd))
cmdutil.CheckErr(o.Validate()) cmdutil.CheckErr(o.Validate())
cmdutil.CheckErr(o.RunDelete(f)) cmdutil.CheckErr(o.RunDelete(f))
@ -301,11 +302,7 @@ func (o *DeleteOptions) DeleteResult(r *resource.Result) error {
if o.GracePeriod >= 0 { if o.GracePeriod >= 0 {
options = metav1.NewDeleteOptions(int64(o.GracePeriod)) options = metav1.NewDeleteOptions(int64(o.GracePeriod))
} }
policy := metav1.DeletePropagationBackground options.PropagationPolicy = &o.CascadingStrategy
if !o.Cascade {
policy = metav1.DeletePropagationOrphan
}
options.PropagationPolicy = &policy
if warnClusterScope && info.Mapping.Scope.Name() == meta.RESTScopeNameRoot { if warnClusterScope && info.Mapping.Scope.Name() == meta.RESTScopeNameRoot {
fmt.Fprintf(o.ErrOut, "warning: deleting cluster-scoped resources, not scoped to the provided namespace\n") fmt.Fprintf(o.ErrOut, "warning: deleting cluster-scoped resources, not scoped to the provided namespace\n")

View File

@ -17,12 +17,16 @@ limitations under the License.
package delete package delete
import ( import (
"fmt"
"strconv"
"time" "time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
"k8s.io/klog/v2"
) )
// DeleteFlags composes common printer flag structs // DeleteFlags composes common printer flag structs
@ -34,7 +38,7 @@ type DeleteFlags struct {
All *bool All *bool
AllNamespaces *bool AllNamespaces *bool
Cascade *bool CascadingStrategy *string
Force *bool Force *bool
GracePeriod *int GracePeriod *int
IgnoreNotFound *bool IgnoreNotFound *bool
@ -45,7 +49,7 @@ type DeleteFlags struct {
Raw *string Raw *string
} }
func (f *DeleteFlags) ToOptions(dynamicClient dynamic.Interface, streams genericclioptions.IOStreams) *DeleteOptions { func (f *DeleteFlags) ToOptions(dynamicClient dynamic.Interface, streams genericclioptions.IOStreams) (*DeleteOptions, error) {
options := &DeleteOptions{ options := &DeleteOptions{
DynamicClient: dynamicClient, DynamicClient: dynamicClient,
IOStreams: streams, IOStreams: streams,
@ -73,8 +77,12 @@ func (f *DeleteFlags) ToOptions(dynamicClient dynamic.Interface, streams generic
if f.AllNamespaces != nil { if f.AllNamespaces != nil {
options.DeleteAllNamespaces = *f.AllNamespaces options.DeleteAllNamespaces = *f.AllNamespaces
} }
if f.Cascade != nil { if f.CascadingStrategy != nil {
options.Cascade = *f.Cascade var err error
options.CascadingStrategy, err = getCascadingStrategy(*f.CascadingStrategy)
if err != nil {
return nil, err
}
} }
if f.Force != nil { if f.Force != nil {
options.ForceDeletion = *f.Force options.ForceDeletion = *f.Force
@ -98,7 +106,7 @@ func (f *DeleteFlags) ToOptions(dynamicClient dynamic.Interface, streams generic
options.Raw = *f.Raw options.Raw = *f.Raw
} }
return options return options, nil
} }
func (f *DeleteFlags) AddFlags(cmd *cobra.Command) { func (f *DeleteFlags) AddFlags(cmd *cobra.Command) {
@ -118,8 +126,13 @@ func (f *DeleteFlags) AddFlags(cmd *cobra.Command) {
if f.Force != nil { if f.Force != nil {
cmd.Flags().BoolVar(f.Force, "force", *f.Force, "If true, immediately remove resources from API and bypass graceful deletion. Note that immediate deletion of some resources may result in inconsistency or data loss and requires confirmation.") cmd.Flags().BoolVar(f.Force, "force", *f.Force, "If true, immediately remove resources from API and bypass graceful deletion. Note that immediate deletion of some resources may result in inconsistency or data loss and requires confirmation.")
} }
if f.Cascade != nil { if f.CascadingStrategy != nil {
cmd.Flags().BoolVar(f.Cascade, "cascade", *f.Cascade, "If true, run background cascade deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.") cmd.Flags().StringVar(
f.CascadingStrategy,
"cascade",
*f.CascadingStrategy,
`Must be "background", "orphan", or "foreground". Selects the deletion cascading strategy for the dependents (e.g. Pods created by a ReplicationController). Defaults to background.`)
cmd.Flags().Lookup("cascade").NoOptDefVal = "background"
} }
if f.Now != nil { if f.Now != nil {
cmd.Flags().BoolVar(f.Now, "now", *f.Now, "If true, resources are signaled for immediate shutdown (same as --grace-period=1).") cmd.Flags().BoolVar(f.Now, "now", *f.Now, "If true, resources are signaled for immediate shutdown (same as --grace-period=1).")
@ -146,7 +159,7 @@ func (f *DeleteFlags) AddFlags(cmd *cobra.Command) {
// NewDeleteCommandFlags provides default flags and values for use with the "delete" command // NewDeleteCommandFlags provides default flags and values for use with the "delete" command
func NewDeleteCommandFlags(usage string) *DeleteFlags { func NewDeleteCommandFlags(usage string) *DeleteFlags {
cascade := true cascadingStrategy := "background"
gracePeriod := -1 gracePeriod := -1
// setup command defaults // setup command defaults
@ -172,7 +185,7 @@ func NewDeleteCommandFlags(usage string) *DeleteFlags {
LabelSelector: &labelSelector, LabelSelector: &labelSelector,
FieldSelector: &fieldSelector, FieldSelector: &fieldSelector,
Cascade: &cascade, CascadingStrategy: &cascadingStrategy,
GracePeriod: &gracePeriod, GracePeriod: &gracePeriod,
All: &all, All: &all,
@ -189,7 +202,7 @@ func NewDeleteCommandFlags(usage string) *DeleteFlags {
// NewDeleteFlags provides default flags and values for use in commands outside of "delete" // NewDeleteFlags provides default flags and values for use in commands outside of "delete"
func NewDeleteFlags(usage string) *DeleteFlags { func NewDeleteFlags(usage string) *DeleteFlags {
cascade := true cascadingStrategy := "background"
gracePeriod := -1 gracePeriod := -1
force := false force := false
@ -203,7 +216,7 @@ func NewDeleteFlags(usage string) *DeleteFlags {
return &DeleteFlags{ return &DeleteFlags{
FileNameFlags: &genericclioptions.FileNameFlags{Usage: usage, Filenames: &filenames, Kustomize: &kustomize, Recursive: &recursive}, FileNameFlags: &genericclioptions.FileNameFlags{Usage: usage, Filenames: &filenames, Kustomize: &kustomize, Recursive: &recursive},
Cascade: &cascade, CascadingStrategy: &cascadingStrategy,
GracePeriod: &gracePeriod, GracePeriod: &gracePeriod,
// add non-defaults // add non-defaults
@ -212,3 +225,27 @@ func NewDeleteFlags(usage string) *DeleteFlags {
Wait: &wait, Wait: &wait,
} }
} }
func getCascadingStrategy(cascadingFlag string) (metav1.DeletionPropagation, error) {
b, err := strconv.ParseBool(cascadingFlag)
// The flag is not a boolean
if err != nil {
switch cascadingFlag {
case "orphan":
return metav1.DeletePropagationOrphan, nil
case "foreground":
return metav1.DeletePropagationForeground, nil
case "background":
return metav1.DeletePropagationBackground, nil
default:
return metav1.DeletePropagationBackground, fmt.Errorf(`Invalid cascade value (%v). Must be "background", "foreground", or "orphan".`, cascadingFlag)
}
}
// The flag was a boolean
if b {
klog.Warningf(`--cascade=%v is deprecated (boolean value) and can be replaced with --cascade=%s.`, cascadingFlag, "background")
return metav1.DeletePropagationBackground, nil
}
klog.Warningf(`--cascade=%v is deprecated (boolean value) and can be replaced with --cascade=%s.`, cascadingFlag, "orphan")
return metav1.DeletePropagationOrphan, nil
}

View File

@ -112,8 +112,8 @@ func hasExpectedPropagationPolicy(body io.ReadCloser, policy *metav1.DeletionPro
return *policy == *parsedBody.PropagationPolicy return *policy == *parsedBody.PropagationPolicy
} }
// Tests that DeleteOptions.OrphanDependents is appropriately set while deleting objects. // TestCascadingStrategy tests that DeleteOptions.DeletionPropagation is appropriately set while deleting objects.
func TestOrphanDependentsInDeleteObject(t *testing.T) { func TestCascadingStrategy(t *testing.T) {
cmdtesting.InitTestErrorHandler(t) cmdtesting.InitTestErrorHandler(t)
_, _, rc := cmdtesting.TestData() _, _, rc := cmdtesting.TestData()
@ -137,7 +137,7 @@ func TestOrphanDependentsInDeleteObject(t *testing.T) {
}), }),
} }
// DeleteOptions.PropagationPolicy should be Background, when cascade is true (default). // DeleteOptions.PropagationPolicy should be Background, when cascading strategy is empty (default).
backgroundPolicy := metav1.DeletePropagationBackground backgroundPolicy := metav1.DeletePropagationBackground
policy = &backgroundPolicy policy = &backgroundPolicy
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
@ -149,13 +149,26 @@ func TestOrphanDependentsInDeleteObject(t *testing.T) {
t.Errorf("unexpected output: %s", buf.String()) t.Errorf("unexpected output: %s", buf.String())
} }
// Test that delete options should be set to orphan when cascade is false. // DeleteOptions.PropagationPolicy should be Foreground, when cascading strategy is foreground.
foregroundPolicy := metav1.DeletePropagationForeground
policy = &foregroundPolicy
streams, _, buf, _ = genericclioptions.NewTestIOStreams()
cmd = NewCmdDelete(tf, streams)
cmd.Flags().Set("namespace", "test")
cmd.Flags().Set("cascade", "foreground")
cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{"secrets/mysecret"})
if buf.String() != "secret/mysecret\n" {
t.Errorf("unexpected output: %s", buf.String())
}
// Test that delete options should be set to orphan when cascading strategy is orphan.
orphanPolicy := metav1.DeletePropagationOrphan orphanPolicy := metav1.DeletePropagationOrphan
policy = &orphanPolicy policy = &orphanPolicy
streams, _, buf, _ = genericclioptions.NewTestIOStreams() streams, _, buf, _ = genericclioptions.NewTestIOStreams()
cmd = NewCmdDelete(tf, streams) cmd = NewCmdDelete(tf, streams)
cmd.Flags().Set("namespace", "test") cmd.Flags().Set("namespace", "test")
cmd.Flags().Set("cascade", "false") cmd.Flags().Set("cascade", "orphan")
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", "name")
cmd.Run(cmd, []string{"secrets/mysecret"}) cmd.Run(cmd, []string{"secrets/mysecret"})
if buf.String() != "secret/mysecret\n" { if buf.String() != "secret/mysecret\n" {
@ -428,7 +441,7 @@ func TestDeleteObjectNotFound(t *testing.T) {
Filenames: []string{"../../../testdata/redis-master-controller.yaml"}, Filenames: []string{"../../../testdata/redis-master-controller.yaml"},
}, },
GracePeriod: -1, GracePeriod: -1,
Cascade: false, CascadingStrategy: metav1.DeletePropagationOrphan,
Output: "name", Output: "name",
IOStreams: genericclioptions.NewTestIOStreamsDiscard(), IOStreams: genericclioptions.NewTestIOStreamsDiscard(),
} }
@ -506,7 +519,7 @@ func TestDeleteAllNotFound(t *testing.T) {
options := &DeleteOptions{ options := &DeleteOptions{
FilenameOptions: resource.FilenameOptions{}, FilenameOptions: resource.FilenameOptions{},
GracePeriod: -1, GracePeriod: -1,
Cascade: false, CascadingStrategy: metav1.DeletePropagationOrphan,
DeleteAll: true, DeleteAll: true,
IgnoreNotFound: false, IgnoreNotFound: false,
Output: "name", Output: "name",
@ -631,7 +644,7 @@ func TestDeleteMultipleObjectContinueOnMissing(t *testing.T) {
Filenames: []string{"../../../testdata/redis-master-controller.yaml", "../../../testdata/frontend-service.yaml"}, Filenames: []string{"../../../testdata/redis-master-controller.yaml", "../../../testdata/frontend-service.yaml"},
}, },
GracePeriod: -1, GracePeriod: -1,
Cascade: false, CascadingStrategy: metav1.DeletePropagationOrphan,
Output: "name", Output: "name",
IOStreams: streams, IOStreams: streams,
} }
@ -803,7 +816,7 @@ func TestResourceErrors(t *testing.T) {
options := &DeleteOptions{ options := &DeleteOptions{
FilenameOptions: resource.FilenameOptions{}, FilenameOptions: resource.FilenameOptions{},
GracePeriod: -1, GracePeriod: -1,
Cascade: false, CascadingStrategy: metav1.DeletePropagationOrphan,
Output: "name", Output: "name",
IOStreams: streams, IOStreams: streams,
} }

View File

@ -171,7 +171,10 @@ func (o *ReplaceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
return printer.PrintObj(obj, o.Out) return printer.PrintObj(obj, o.Out)
} }
deleteOpts := o.DeleteFlags.ToOptions(dynamicClient, o.IOStreams) deleteOpts, err := o.DeleteFlags.ToOptions(dynamicClient, o.IOStreams)
if err != nil {
return err
}
//Replace will create a resource if it doesn't exist already, so ignore not found error //Replace will create a resource if it doesn't exist already, so ignore not found error
deleteOpts.IgnoreNotFound = true deleteOpts.IgnoreNotFound = true

View File

@ -245,7 +245,11 @@ func (o *RunOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
return printer.PrintObj(obj, o.Out) return printer.PrintObj(obj, o.Out)
} }
deleteOpts := o.DeleteFlags.ToOptions(dynamicClient, o.IOStreams) deleteOpts, err := o.DeleteFlags.ToOptions(dynamicClient, o.IOStreams)
if err != nil {
return err
}
deleteOpts.IgnoreNotFound = true deleteOpts.IgnoreNotFound = true
deleteOpts.WaitForDeletion = false deleteOpts.WaitForDeletion = false
deleteOpts.GracePeriod = -1 deleteOpts.GracePeriod = -1

View File

@ -199,9 +199,14 @@ func TestRunArgsFollowDashRules(t *testing.T) {
} }
deleteFlags := delete.NewDeleteFlags("to use to replace the resource.") deleteFlags := delete.NewDeleteFlags("to use to replace the resource.")
deleteOptions, err := deleteFlags.ToOptions(nil, genericclioptions.NewTestIOStreamsDiscard())
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
opts := &RunOptions{ opts := &RunOptions{
PrintFlags: printFlags, PrintFlags: printFlags,
DeleteOptions: deleteFlags.ToOptions(nil, genericclioptions.NewTestIOStreamsDiscard()), DeleteOptions: deleteOptions,
IOStreams: genericclioptions.NewTestIOStreamsDiscard(), IOStreams: genericclioptions.NewTestIOStreamsDiscard(),
@ -371,9 +376,14 @@ func TestGenerateService(t *testing.T) {
ioStreams, _, buff, _ := genericclioptions.NewTestIOStreams() ioStreams, _, buff, _ := genericclioptions.NewTestIOStreams()
deleteFlags := delete.NewDeleteFlags("to use to replace the resource.") deleteFlags := delete.NewDeleteFlags("to use to replace the resource.")
deleteOptions, err := deleteFlags.ToOptions(nil, genericclioptions.NewTestIOStreamsDiscard())
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
opts := &RunOptions{ opts := &RunOptions{
PrintFlags: printFlags, PrintFlags: printFlags,
DeleteOptions: deleteFlags.ToOptions(nil, genericclioptions.NewTestIOStreamsDiscard()), DeleteOptions: deleteOptions,
IOStreams: ioStreams, IOStreams: ioStreams,

View File

@ -137,7 +137,7 @@ run_kubectl_apply_deployments_tests() {
# cleanup # cleanup
# need to explicitly remove replicasets and pods because we changed the deployment selector and orphaned things # need to explicitly remove replicasets and pods because we changed the deployment selector and orphaned things
kubectl delete deployments,rs,pods --all --cascade=false --grace-period=0 kubectl delete deployments,rs,pods --all --cascade=orphan --grace-period=0
# Post-Condition: no Deployments, ReplicaSets, Pods exist # Post-Condition: no Deployments, ReplicaSets, Pods exist
kube::test::wait_object_assert deployments "{{range.items}}{{${id_field:?}}}:{{end}}" '' kube::test::wait_object_assert deployments "{{range.items}}{{${id_field:?}}}:{{end}}" ''
kube::test::wait_object_assert replicasets "{{range.items}}{{${id_field:?}}}:{{end}}" '' kube::test::wait_object_assert replicasets "{{range.items}}{{${id_field:?}}}:{{end}}" ''
@ -246,10 +246,11 @@ run_deployment_tests() {
# Wait for rs to come up. # Wait for rs to come up.
kube::test::wait_object_assert rs "{{range.items}}{{${rs_replicas_field:?}}}{{end}}" '3' kube::test::wait_object_assert rs "{{range.items}}{{${rs_replicas_field:?}}}{{end}}" '3'
# Deleting the deployment should delete the rs. # Deleting the deployment should delete the rs.
kubectl delete deployment nginx-deployment "${kube_flags[@]:?}" # using empty value in cascade flag to make sure the backward compatibility.
kubectl delete deployment nginx-deployment "${kube_flags[@]:?}" --cascade
kube::test::wait_object_assert rs "{{range.items}}{{${id_field:?}}}:{{end}}" '' kube::test::wait_object_assert rs "{{range.items}}{{${id_field:?}}}:{{end}}" ''
## Test that rs is not deleted when deployment is deleted with cascade set to false. ## Test that rs is not deleted when deployment is deleted with cascading strategy set to orphan.
# Pre-condition: no deployment and rs exist # Pre-condition: no deployment and rs exist
kube::test::get_object_assert deployment "{{range.items}}{{${id_field:?}}}:{{end}}" '' kube::test::get_object_assert deployment "{{range.items}}{{${id_field:?}}}:{{end}}" ''
kube::test::get_object_assert rs "{{range.items}}{{${id_field:?}}}:{{end}}" '' kube::test::get_object_assert rs "{{range.items}}{{${id_field:?}}}:{{end}}" ''
@ -257,8 +258,8 @@ run_deployment_tests() {
kubectl create deployment nginx-deployment --image=k8s.gcr.io/nginx:test-cmd kubectl create deployment nginx-deployment --image=k8s.gcr.io/nginx:test-cmd
# Wait for rs to come up. # Wait for rs to come up.
kube::test::wait_object_assert rs "{{range.items}}{{${rs_replicas_field:?}}}{{end}}" '1' kube::test::wait_object_assert rs "{{range.items}}{{${rs_replicas_field:?}}}{{end}}" '1'
# Delete the deployment with cascade set to false. # Delete the deployment with cascading strategy set to orphan.
kubectl delete deployment nginx-deployment "${kube_flags[@]:?}" --cascade=false kubectl delete deployment nginx-deployment "${kube_flags[@]:?}" --cascade=orphan
# Wait for the deployment to be deleted and then verify that rs is not # Wait for the deployment to be deleted and then verify that rs is not
# deleted. # deleted.
kube::test::wait_object_assert deployment "{{range.items}}{{${id_field:?}}}:{{end}}" '' kube::test::wait_object_assert deployment "{{range.items}}{{${id_field:?}}}:{{end}}" ''
@ -545,7 +546,7 @@ run_rs_tests() {
# Post-condition: no pods from frontend replica set # Post-condition: no pods from frontend replica set
kube::test::wait_object_assert 'pods -l "tier=frontend"' "{{range.items}}{{${id_field:?}}}:{{end}}" '' kube::test::wait_object_assert 'pods -l "tier=frontend"' "{{range.items}}{{${id_field:?}}}:{{end}}" ''
### Create and then delete a replica set with cascade=false, make sure it doesn't delete pods. ### Create and then delete a replica set with cascading strategy set to orphan, make sure it doesn't delete pods.
# Pre-condition: no replica set exists # Pre-condition: no replica set exists
kube::test::get_object_assert rs "{{range.items}}{{${id_field:?}}}:{{end}}" '' kube::test::get_object_assert rs "{{range.items}}{{${id_field:?}}}:{{end}}" ''
# Command # Command
@ -553,7 +554,7 @@ run_rs_tests() {
# wait for all 3 pods to be set up # wait for all 3 pods to be set up
kube::test::wait_object_assert 'pods -l "tier=frontend"' "{{range.items}}{{${pod_container_name_field:?}}}:{{end}}" 'php-redis:php-redis:php-redis:' kube::test::wait_object_assert 'pods -l "tier=frontend"' "{{range.items}}{{${pod_container_name_field:?}}}:{{end}}" 'php-redis:php-redis:php-redis:'
kube::log::status "Deleting rs" kube::log::status "Deleting rs"
kubectl delete rs frontend "${kube_flags[@]:?}" --cascade=false kubectl delete rs frontend "${kube_flags[@]:?}" --cascade=orphan
# Wait for the rs to be deleted. # Wait for the rs to be deleted.
kube::test::wait_object_assert rs "{{range.items}}{{${id_field:?}}}:{{end}}" '' kube::test::wait_object_assert rs "{{range.items}}{{${id_field:?}}}:{{end}}" ''
# Post-condition: All 3 pods still remain from frontend replica set # Post-condition: All 3 pods still remain from frontend replica set

View File

@ -194,8 +194,8 @@ run_non_native_resource_tests() {
output_message=$(kubectl "${kube_flags[@]}" get kind.mygroup.example.com/myobj -o name) output_message=$(kubectl "${kube_flags[@]}" get kind.mygroup.example.com/myobj -o name)
kube::test::if_has_string "${output_message}" 'kind.mygroup.example.com/myobj' kube::test::if_has_string "${output_message}" 'kind.mygroup.example.com/myobj'
# Delete the resource with cascade. # Delete the resource with cascading strategy background.
kubectl "${kube_flags[@]}" delete resources myobj --cascade=true kubectl "${kube_flags[@]}" delete resources myobj --cascade=background
# Make sure it's gone # Make sure it's gone
kube::test::wait_object_assert resources "{{range.items}}{{$id_field}}:{{end}}" '' kube::test::wait_object_assert resources "{{range.items}}{{$id_field}}:{{end}}" ''
@ -275,8 +275,8 @@ run_non_native_resource_tests() {
kubectl "${kube_flags[@]}" describe foos | grep listlabel=true kubectl "${kube_flags[@]}" describe foos | grep listlabel=true
kubectl "${kube_flags[@]}" describe foos | grep itemlabel=true kubectl "${kube_flags[@]}" describe foos | grep itemlabel=true
# Delete the resource with cascade. # Delete the resource with cascading strategy background.
kubectl "${kube_flags[@]}" delete foos test --cascade=true kubectl "${kube_flags[@]}" delete foos test --cascade=background
# Make sure it's gone # Make sure it's gone
kube::test::wait_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" '' kube::test::wait_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" ''
@ -313,8 +313,8 @@ run_non_native_resource_tests() {
kill -9 "${patch_pid}" kill -9 "${patch_pid}"
kube::test::if_has_string "${watch_output}" 'bar.company.com/test' kube::test::if_has_string "${watch_output}" 'bar.company.com/test'
# Delete the resource without cascade. # Delete the resource with cascading strategy orphan.
kubectl "${kube_flags[@]}" delete bars test --cascade=false kubectl "${kube_flags[@]}" delete bars test --cascade=orphan
# Make sure it's gone # Make sure it's gone
kube::test::wait_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" '' kube::test::wait_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" ''

View File

@ -90,7 +90,7 @@ run_multi_resources_tests() {
fi fi
kubectl describe -f "${file}" "${kube_flags[@]}" kubectl describe -f "${file}" "${kube_flags[@]}"
# Command # Command
kubectl replace -f "${replace_file}" --force --cascade "${kube_flags[@]}" kubectl replace -f "${replace_file}" --force --cascade=background "${kube_flags[@]}"
# Post-condition: mock service (and mock2) and mock rc (and mock2) are replaced # Post-condition: mock service (and mock2) and mock rc (and mock2) are replaced
if [ "$has_svc" = true ]; then if [ "$has_svc" = true ]; then
kube::test::get_object_assert 'services mock' "{{${labels_field:?}.status}}" 'replaced' kube::test::get_object_assert 'services mock' "{{${labels_field:?}.status}}" 'replaced'