mirror of https://github.com/knative/client.git
feat(wait): add sync revision delete operation (#688)
This commit is contained in:
parent
034a9b387e
commit
b14dc2dc7f
|
@ -21,8 +21,11 @@ kn revision delete NAME [flags]
|
|||
### Options
|
||||
|
||||
```
|
||||
--async DEPRECATED: please use --no-wait instead. Delete revision and don't wait for it to be deleted.
|
||||
-h, --help help for delete
|
||||
-n, --namespace string Specify the namespace to operate in.
|
||||
--no-wait Delete revision and don't wait for it to be deleted.
|
||||
--wait-timeout int Seconds to wait before giving up on waiting for revision to be deleted. (default 600)
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
|
|
@ -17,6 +17,7 @@ package revision
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
@ -25,6 +26,8 @@ import (
|
|||
|
||||
// NewRevisionDeleteCommand represent 'revision delete' command
|
||||
func NewRevisionDeleteCommand(p *commands.KnParams) *cobra.Command {
|
||||
var waitFlags commands.WaitFlags
|
||||
|
||||
RevisionDeleteCommand := &cobra.Command{
|
||||
Use: "delete NAME",
|
||||
Short: "Delete a revision.",
|
||||
|
@ -45,7 +48,11 @@ func NewRevisionDeleteCommand(p *commands.KnParams) *cobra.Command {
|
|||
}
|
||||
|
||||
for _, name := range args {
|
||||
err = client.DeleteRevision(name)
|
||||
timeout := time.Duration(0)
|
||||
if !waitFlags.NoWait {
|
||||
timeout = time.Duration(waitFlags.TimeoutInSeconds) * time.Second
|
||||
}
|
||||
err = client.DeleteRevision(name, timeout)
|
||||
if err != nil {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "%s.\n", err)
|
||||
} else {
|
||||
|
@ -56,5 +63,6 @@ func NewRevisionDeleteCommand(p *commands.KnParams) *cobra.Command {
|
|||
},
|
||||
}
|
||||
commands.AddNamespaceFlags(RevisionDeleteCommand.Flags(), false)
|
||||
waitFlags.AddConditionWaitFlags(RevisionDeleteCommand, commands.WaitDefaultTimeout, "Delete", "revision", "deleted")
|
||||
return RevisionDeleteCommand
|
||||
}
|
||||
|
|
|
@ -15,14 +15,19 @@
|
|||
package revision
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
clienttesting "k8s.io/client-go/testing"
|
||||
|
||||
"knative.dev/client/pkg/kn/commands"
|
||||
"knative.dev/client/pkg/util"
|
||||
"knative.dev/client/pkg/wait"
|
||||
servingv1 "knative.dev/serving/pkg/apis/serving/v1"
|
||||
)
|
||||
|
||||
func fakeRevisionDelete(args []string) (action clienttesting.Action, name string, output string, err error) {
|
||||
|
@ -35,6 +40,17 @@ func fakeRevisionDelete(args []string) (action clienttesting.Action, name string
|
|||
name = deleteAction.GetName()
|
||||
return true, nil, nil
|
||||
})
|
||||
fakeServing.AddWatchReactor("revisions",
|
||||
func(a clienttesting.Action) (bool, watch.Interface, error) {
|
||||
watchAction := a.(clienttesting.WatchAction)
|
||||
_, found := watchAction.GetWatchRestrictions().Fields.RequiresExactMatch("metadata.name")
|
||||
if !found {
|
||||
return true, nil, errors.New("no field selector on metadata.name found")
|
||||
}
|
||||
w := wait.NewFakeWatch(getRevisionDeleteEvents("test-revision"))
|
||||
w.Start()
|
||||
return true, w, nil
|
||||
})
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
if err != nil {
|
||||
|
@ -79,3 +95,10 @@ func TestMultipleRevisionDelete(t *testing.T) {
|
|||
assert.Check(t, util.ContainsAll(output, "Revision", revName2, "deleted", "namespace", commands.FakeNamespace))
|
||||
assert.Check(t, util.ContainsAll(output, "Revision", revName3, "deleted", "namespace", commands.FakeNamespace))
|
||||
}
|
||||
|
||||
func getRevisionDeleteEvents(name string) []watch.Event {
|
||||
return []watch.Event{
|
||||
{watch.Added, &servingv1.Revision{ObjectMeta: metav1.ObjectMeta{Name: name}}},
|
||||
{watch.Deleted, &servingv1.Revision{ObjectMeta: metav1.ObjectMeta{Name: name}}},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ type KnServingClient interface {
|
|||
ListRevisions(opts ...ListConfig) (*servingv1.RevisionList, error)
|
||||
|
||||
// Delete a revision
|
||||
DeleteRevision(name string) error
|
||||
DeleteRevision(name string, timeout time.Duration) error
|
||||
|
||||
// Get a route by its unique name
|
||||
GetRoute(name string) (*servingv1.Route, error)
|
||||
|
@ -177,6 +177,11 @@ func (cl *knServingClient) WatchService(name string, timeout time.Duration) (wat
|
|||
cl.client.RESTClient(), cl.namespace, "services", name, timeout)
|
||||
}
|
||||
|
||||
func (cl *knServingClient) WatchRevision(name string, timeout time.Duration) (watch.Interface, error) {
|
||||
return wait.NewWatcher(cl.client.Revisions(cl.namespace).Watch,
|
||||
cl.client.RESTClient(), cl.namespace, "revision", name, timeout)
|
||||
}
|
||||
|
||||
// List services
|
||||
func (cl *knServingClient) ListServices(config ...ListConfig) (*servingv1.ServiceList, error) {
|
||||
serviceList, err := cl.client.Services(cl.namespace).List(ListConfigs(config).toListOptions())
|
||||
|
@ -370,7 +375,25 @@ func getBaseRevision(cl KnServingClient, service *servingv1.Service) (*servingv1
|
|||
}
|
||||
|
||||
// Delete a revision by name
|
||||
func (cl *knServingClient) DeleteRevision(name string) error {
|
||||
func (cl *knServingClient) DeleteRevision(name string, timeout time.Duration) error {
|
||||
if timeout == 0 {
|
||||
return cl.deleteRevision(name)
|
||||
}
|
||||
waitC := make(chan error)
|
||||
go func() {
|
||||
waitForEvent := wait.NewWaitForEvent("revision", cl.WatchRevision, func(evt *watch.Event) bool { return evt.Type == watch.Deleted })
|
||||
err, _ := waitForEvent.Wait(name, timeout, wait.NoopMessageCallback())
|
||||
waitC <- err
|
||||
}()
|
||||
err := cl.deleteRevision(name)
|
||||
if err != nil {
|
||||
return clienterrors.GetError(err)
|
||||
}
|
||||
|
||||
return <-waitC
|
||||
}
|
||||
|
||||
func (cl *knServingClient) deleteRevision(name string) error {
|
||||
err := cl.client.Revisions(cl.namespace).Delete(name, &v1.DeleteOptions{})
|
||||
if err != nil {
|
||||
return clienterrors.GetError(err)
|
||||
|
|
|
@ -146,12 +146,12 @@ func (c *MockKnServingClient) ListRevisions(opts ...ListConfig) (*servingv1.Revi
|
|||
}
|
||||
|
||||
// Delete a revision
|
||||
func (sr *ServingRecorder) DeleteRevision(name interface{}, err error) {
|
||||
sr.r.Add("DeleteRevision", []interface{}{name}, []interface{}{err})
|
||||
func (sr *ServingRecorder) DeleteRevision(name, timeout interface{}, err error) {
|
||||
sr.r.Add("DeleteRevision", []interface{}{name, timeout}, []interface{}{err})
|
||||
}
|
||||
|
||||
func (c *MockKnServingClient) DeleteRevision(name string) error {
|
||||
call := c.recorder.r.VerifyCall("DeleteRevision", name)
|
||||
func (c *MockKnServingClient) DeleteRevision(name string, timeout time.Duration) error {
|
||||
call := c.recorder.r.VerifyCall("DeleteRevision", name, timeout)
|
||||
return mock.ErrorOrNil(call.Result[0])
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ func TestMockKnClient(t *testing.T) {
|
|||
recorder.WaitForService("hello", time.Duration(10)*time.Second, wait.NoopMessageCallback(), nil, 10*time.Second)
|
||||
recorder.GetRevision("hello", nil, nil)
|
||||
recorder.ListRevisions(mock.Any(), nil, nil)
|
||||
recorder.DeleteRevision("hello", nil)
|
||||
recorder.DeleteRevision("hello", time.Duration(10)*time.Second, nil)
|
||||
recorder.GetRoute("hello", nil, nil)
|
||||
recorder.ListRoutes(mock.Any(), nil, nil)
|
||||
recorder.GetConfiguration("hello", nil, nil)
|
||||
|
@ -54,7 +54,7 @@ func TestMockKnClient(t *testing.T) {
|
|||
client.WaitForService("hello", time.Duration(10)*time.Second, wait.NoopMessageCallback())
|
||||
client.GetRevision("hello")
|
||||
client.ListRevisions(WithName("blub"))
|
||||
client.DeleteRevision("hello")
|
||||
client.DeleteRevision("hello", time.Duration(10)*time.Second)
|
||||
client.GetRoute("hello")
|
||||
client.ListRoutes(WithName("blub"))
|
||||
client.GetConfiguration("hello")
|
||||
|
|
Loading…
Reference in New Issue