mirror of https://github.com/knative/func.git
feat: delete pipeline and resources with `func delete` (#763)
* feat: delete pipeline and resources with `func delete` Signed-off-by: Zbynek Roubalik <zroubali@redhat.com> * fix test and prompt Signed-off-by: Zbynek Roubalik <zroubali@redhat.com>
This commit is contained in:
parent
6649a71f4d
commit
d478f555cc
46
client.go
46
client.go
|
@ -185,6 +185,7 @@ type DNSProvider interface {
|
|||
// PipelinesProvider manages lifecyle of CI/CD pipelines used by a Function
|
||||
type PipelinesProvider interface {
|
||||
Run(context.Context, Function) error
|
||||
Remove(context.Context, Function) error
|
||||
}
|
||||
|
||||
// New client for Function management.
|
||||
|
@ -788,25 +789,47 @@ func (c *Client) List(ctx context.Context) ([]ListItem, error) {
|
|||
|
||||
// Remove a Function. Name takes precidence. If no name is provided,
|
||||
// the Function defined at root is used if it exists.
|
||||
func (c *Client) Remove(ctx context.Context, cfg Function) error {
|
||||
func (c *Client) Remove(ctx context.Context, cfg Function, deleteAll bool) error {
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
c.progressListener.Stopping()
|
||||
}()
|
||||
// If name is provided, it takes precidence.
|
||||
// Otherwise load the Function deined at root.
|
||||
if cfg.Name != "" {
|
||||
return c.remover.Remove(ctx, cfg.Name)
|
||||
// Otherwise load the Function defined at root.
|
||||
functionName := cfg.Name
|
||||
if cfg.Name == "" {
|
||||
f, err := NewFunction(cfg.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !f.Initialized() {
|
||||
return fmt.Errorf("Function at %v can not be removed unless initialized. Try removing by name", f.Root)
|
||||
}
|
||||
functionName = f.Name
|
||||
cfg = f
|
||||
}
|
||||
|
||||
f, err := NewFunction(cfg.Root)
|
||||
if err != nil {
|
||||
return err
|
||||
// Delete Knative Service and dependent resources in parallel
|
||||
c.progressListener.Increment(fmt.Sprintf("Removing Knative Service: %v", functionName))
|
||||
errChan := make(chan error)
|
||||
go func() {
|
||||
errChan <- c.remover.Remove(ctx, functionName)
|
||||
}()
|
||||
|
||||
var errResources error
|
||||
if deleteAll {
|
||||
c.progressListener.Increment(fmt.Sprintf("Removing Knative Service '%v' and all dependent resources", functionName))
|
||||
errResources = c.pipelinesProvider.Remove(ctx, cfg)
|
||||
}
|
||||
if !f.Initialized() {
|
||||
return fmt.Errorf("Function at %v can not be removed unless initialized. Try removing by name", f.Root)
|
||||
|
||||
errService := <-errChan
|
||||
|
||||
if errService != nil && errResources != nil {
|
||||
return fmt.Errorf("%s\n%s", errService, errResources)
|
||||
} else if errResources != nil {
|
||||
return errResources
|
||||
}
|
||||
return c.remover.Remove(ctx, f.Name)
|
||||
return errService
|
||||
}
|
||||
|
||||
// Invoke is a convenience method for triggering the execution of a Function
|
||||
|
@ -917,7 +940,8 @@ func (n *noopDescriber) Describe(context.Context, string) (Instance, error) {
|
|||
// PipelinesProvider
|
||||
type noopPipelinesProvider struct{}
|
||||
|
||||
func (n *noopPipelinesProvider) Run(ctx context.Context, _ Function) error { return nil }
|
||||
func (n *noopPipelinesProvider) Run(ctx context.Context, _ Function) error { return nil }
|
||||
func (n *noopPipelinesProvider) Remove(ctx context.Context, _ Function) error { return nil }
|
||||
|
||||
// DNSProvider
|
||||
type noopDNSProvider struct{ output io.Writer }
|
||||
|
|
|
@ -135,7 +135,7 @@ func TestRemove(t *testing.T) {
|
|||
}
|
||||
waitFor(t, client, "remove")
|
||||
|
||||
if err := client.Remove(context.Background(), fn.Function{Name: "remove"}); err != nil {
|
||||
if err := client.Remove(context.Background(), fn.Function{Name: "remove"}, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ func newClient(verbose bool) *fn.Client {
|
|||
func del(t *testing.T, c *fn.Client, name string) {
|
||||
t.Helper()
|
||||
waitFor(t, c, name)
|
||||
if err := c.Remove(context.Background(), fn.Function{Name: name}); err != nil {
|
||||
if err := c.Remove(context.Background(), fn.Function{Name: name}, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -673,7 +673,7 @@ func TestClient_Remove_ByPath(t *testing.T) {
|
|||
return nil
|
||||
}
|
||||
|
||||
if err := client.Remove(context.Background(), fn.Function{Root: root}); err != nil {
|
||||
if err := client.Remove(context.Background(), fn.Function{Root: root}, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -683,6 +683,94 @@ func TestClient_Remove_ByPath(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
// TestClient_Remove_DeleteAll ensures that the remover is invoked to remove
|
||||
// and that dependent resources are removed as well -> pipeline provider is invoked
|
||||
// the Function with the name of the function at the provided root.
|
||||
func TestClient_Remove_DeleteAll(t *testing.T) {
|
||||
var (
|
||||
root = "testdata/example.com/testRemoveDeleteAll"
|
||||
expectedName = "testRemoveDeleteAll"
|
||||
remover = mock.NewRemover()
|
||||
pipelinesProvider = mock.NewPipelinesProvider()
|
||||
deleteAll = true
|
||||
)
|
||||
|
||||
defer Using(t, root)()
|
||||
|
||||
client := fn.New(
|
||||
fn.WithRegistry(TestRegistry),
|
||||
fn.WithRemover(remover),
|
||||
fn.WithPipelinesProvider(pipelinesProvider))
|
||||
|
||||
if err := client.New(context.Background(), fn.Function{Runtime: TestRuntime, Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
remover.RemoveFn = func(name string) error {
|
||||
if name != expectedName {
|
||||
t.Fatalf("Expected to remove '%v', got '%v'", expectedName, name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := client.Remove(context.Background(), fn.Function{Root: root}, deleteAll); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !remover.RemoveInvoked {
|
||||
t.Fatal("remover was not invoked")
|
||||
}
|
||||
|
||||
if !pipelinesProvider.RemoveInvoked {
|
||||
t.Fatal("pipelinesprovider was not invoked")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestClient_Remove_Dont_DeleteAll ensures that the remover is invoked to remove
|
||||
// and that dependent resources are not removed as well -> pipeline provider not is invoked
|
||||
// the Function with the name of the function at the provided root.
|
||||
func TestClient_Remove_Dont_DeleteAll(t *testing.T) {
|
||||
var (
|
||||
root = "testdata/example.com/testRemoveDontDeleteAll"
|
||||
expectedName = "testRemoveDontDeleteAll"
|
||||
remover = mock.NewRemover()
|
||||
pipelinesProvider = mock.NewPipelinesProvider()
|
||||
deleteAll = false
|
||||
)
|
||||
|
||||
defer Using(t, root)()
|
||||
|
||||
client := fn.New(
|
||||
fn.WithRegistry(TestRegistry),
|
||||
fn.WithRemover(remover),
|
||||
fn.WithPipelinesProvider(pipelinesProvider))
|
||||
|
||||
if err := client.New(context.Background(), fn.Function{Runtime: TestRuntime, Root: root}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
remover.RemoveFn = func(name string) error {
|
||||
if name != expectedName {
|
||||
t.Fatalf("Expected to remove '%v', got '%v'", expectedName, name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := client.Remove(context.Background(), fn.Function{Root: root}, deleteAll); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !remover.RemoveInvoked {
|
||||
t.Fatal("remover was not invoked")
|
||||
}
|
||||
|
||||
if pipelinesProvider.RemoveInvoked {
|
||||
t.Fatal("pipelinesprovider was invoked, but should not")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestClient_Remove_ByName ensures that the remover is invoked to remove the function
|
||||
// of the name provided, with precidence over a provided root path.
|
||||
func TestClient_Remove_ByName(t *testing.T) {
|
||||
|
@ -710,12 +798,12 @@ func TestClient_Remove_ByName(t *testing.T) {
|
|||
}
|
||||
|
||||
// Run remove with only a name
|
||||
if err := client.Remove(context.Background(), fn.Function{Name: expectedName}); err != nil {
|
||||
if err := client.Remove(context.Background(), fn.Function{Name: expectedName}, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Run remove with a name and a root, which should be ignored in favor of the name.
|
||||
if err := client.Remove(context.Background(), fn.Function{Name: expectedName, Root: root}); err != nil {
|
||||
if err := client.Remove(context.Background(), fn.Function{Name: expectedName, Root: root}, false); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -746,7 +834,7 @@ func TestClient_Remove_UninitializedFails(t *testing.T) {
|
|||
fn.WithRemover(remover))
|
||||
|
||||
// Attempt to remove by path (uninitialized), expecting an error.
|
||||
if err := client.Remove(context.Background(), fn.Function{Root: root}); err == nil {
|
||||
if err := client.Remove(context.Background(), fn.Function{Root: root}, false); err == nil {
|
||||
t.Fatalf("did not received expeced error removing an uninitialized func")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import (
|
|||
|
||||
fn "knative.dev/kn-plugin-func"
|
||||
"knative.dev/kn-plugin-func/knative"
|
||||
"knative.dev/kn-plugin-func/pipelines/tekton"
|
||||
"knative.dev/kn-plugin-func/progress"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -23,15 +25,26 @@ func init() {
|
|||
// Testing note: This method is swapped out during testing to allow
|
||||
// mocking the remover or the client itself to fabricate test states.
|
||||
func newDeleteClient(cfg deleteConfig) (*fn.Client, error) {
|
||||
listener := progress.New()
|
||||
remover, err := knative.NewRemover(cfg.Namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pipelinesProvider, err := tekton.NewPipelinesProvider(
|
||||
tekton.WithNamespace(cfg.Namespace))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener.Verbose = cfg.Verbose
|
||||
remover.Verbose = cfg.Verbose
|
||||
pipelinesProvider.Verbose = cfg.Verbose
|
||||
|
||||
return fn.New(
|
||||
fn.WithProgressListener(listener),
|
||||
fn.WithRemover(remover),
|
||||
fn.WithPipelinesProvider(pipelinesProvider),
|
||||
fn.WithVerbose(cfg.Verbose)), nil
|
||||
}
|
||||
|
||||
|
@ -59,10 +72,11 @@ kn func delete -n apps myfunc
|
|||
`,
|
||||
SuggestFor: []string{"remove", "rm", "del"},
|
||||
ValidArgsFunction: CompleteFunctionList,
|
||||
PreRunE: bindEnv("path", "confirm", "namespace"),
|
||||
PreRunE: bindEnv("path", "confirm", "namespace", "all"),
|
||||
}
|
||||
|
||||
cmd.Flags().BoolP("confirm", "c", false, "Prompt to confirm all configuration options (Env: $FUNC_CONFIRM)")
|
||||
cmd.Flags().StringP("all", "a", "true", "Delete all resources created for a function, eg. Pipelines, Secrets, etc. (Env: $FUNC_ALL) (allowed values: \"true\", \"false\")")
|
||||
setNamespaceFlag(cmd)
|
||||
setPathFlag(cmd)
|
||||
|
||||
|
@ -117,13 +131,14 @@ func runDelete(cmd *cobra.Command, args []string, clientFn deleteClientFn) (err
|
|||
}
|
||||
|
||||
// Invoke remove using the concrete client impl
|
||||
return client.Remove(cmd.Context(), function)
|
||||
return client.Remove(cmd.Context(), function, config.DeleteAll)
|
||||
}
|
||||
|
||||
type deleteConfig struct {
|
||||
Name string
|
||||
Namespace string
|
||||
Path string
|
||||
DeleteAll bool
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
|
@ -137,6 +152,7 @@ func newDeleteConfig(args []string) deleteConfig {
|
|||
return deleteConfig{
|
||||
Path: viper.GetString("path"),
|
||||
Namespace: viper.GetString("namespace"),
|
||||
DeleteAll: viper.GetBool("all"),
|
||||
Name: deriveName(name, viper.GetString("path")), // args[0] or derived
|
||||
Verbose: viper.GetBool("verbose"), // defined on root
|
||||
}
|
||||
|
@ -150,11 +166,35 @@ func (c deleteConfig) Prompt() (deleteConfig, error) {
|
|||
return c, nil
|
||||
}
|
||||
|
||||
dc := deleteConfig{}
|
||||
dc := c
|
||||
var qs = []*survey.Question{
|
||||
{
|
||||
Name: "name",
|
||||
Prompt: &survey.Input{
|
||||
Message: "Function to remove:",
|
||||
Default: deriveName(c.Name, c.Path)},
|
||||
Validate: survey.Required,
|
||||
},
|
||||
{
|
||||
Name: "all",
|
||||
Prompt: &survey.Confirm{
|
||||
Message: "Do you want to delete all resources?",
|
||||
Default: c.DeleteAll,
|
||||
},
|
||||
},
|
||||
}
|
||||
answers := struct {
|
||||
Name string
|
||||
All bool
|
||||
}{}
|
||||
|
||||
return dc, survey.AskOne(
|
||||
&survey.Input{
|
||||
Message: "Function to remove:",
|
||||
Default: deriveName(c.Name, c.Path)},
|
||||
&dc.Name, survey.WithValidator(survey.Required))
|
||||
err := survey.Ask(qs, &answers)
|
||||
if err != nil {
|
||||
return dc, err
|
||||
}
|
||||
|
||||
dc.Name = answers.Name
|
||||
dc.DeleteAll = answers.All
|
||||
|
||||
return dc, err
|
||||
}
|
||||
|
|
|
@ -41,3 +41,12 @@ func CreatePersistentVolumeClaim(ctx context.Context, name, namespaceOverride st
|
|||
_, err = client.CoreV1().PersistentVolumeClaims(namespace).Create(ctx, pvc, metav1.CreateOptions{})
|
||||
return
|
||||
}
|
||||
|
||||
func DeletePersistentVolumeClaims(ctx context.Context, namespaceOverride string, listOptions metav1.ListOptions) (err error) {
|
||||
client, namespace, err := NewClientAndResolvedNamespace(namespaceOverride)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return client.CoreV1().PersistentVolumeClaims(namespace).DeleteCollection(ctx, metav1.DeleteOptions{}, listOptions)
|
||||
}
|
||||
|
|
|
@ -35,3 +35,12 @@ func CreateRoleBindingForServiceAccount(ctx context.Context, name, namespaceOver
|
|||
_, err = client.RbacV1().RoleBindings(namespace).Create(ctx, rb, metav1.CreateOptions{})
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteRoleBindings(ctx context.Context, namespaceOverride string, listOptions metav1.ListOptions) (err error) {
|
||||
client, namespace, err := NewClientAndResolvedNamespace(namespaceOverride)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return client.RbacV1().RoleBindings(namespace).DeleteCollection(ctx, metav1.DeleteOptions{}, listOptions)
|
||||
}
|
||||
|
|
|
@ -36,6 +36,15 @@ func ListSecretsNames(ctx context.Context, namespaceOverride string) (names []st
|
|||
return
|
||||
}
|
||||
|
||||
func DeleteSecrets(ctx context.Context, namespaceOverride string, listOptions metav1.ListOptions) (err error) {
|
||||
client, namespace, err := NewClientAndResolvedNamespace(namespaceOverride)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return client.CoreV1().Secrets(namespace).DeleteCollection(ctx, metav1.DeleteOptions{}, listOptions)
|
||||
}
|
||||
|
||||
func CreateDockerRegistrySecret(ctx context.Context, name, namespaceOverride string, labels map[string]string, username, password, server string) (err error) {
|
||||
client, namespace, err := NewClientAndResolvedNamespace(namespaceOverride)
|
||||
if err != nil {
|
||||
|
|
|
@ -31,3 +31,12 @@ func CreateServiceAccountWithSecret(ctx context.Context, name, namespaceOverride
|
|||
_, err = client.CoreV1().ServiceAccounts(namespace).Create(ctx, sa, metav1.CreateOptions{})
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteServiceAccounts(ctx context.Context, namespaceOverride string, listOptions metav1.ListOptions) (err error) {
|
||||
client, namespace, err := NewClientAndResolvedNamespace(namespaceOverride)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return client.CoreV1().ServiceAccounts(namespace).DeleteCollection(ctx, metav1.DeleteOptions{}, listOptions)
|
||||
}
|
||||
|
|
|
@ -33,8 +33,6 @@ func (remover *Remover) Remove(ctx context.Context, name string) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
fmt.Printf("Removing Knative Service: %v\n", name)
|
||||
|
||||
err = client.DeleteService(ctx, name, RemoveTimeout)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("knative remover failed to delete the service: %v", err)
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package mock
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
fn "knative.dev/kn-plugin-func"
|
||||
)
|
||||
|
||||
type PipelinesProvider struct {
|
||||
RunInvoked bool
|
||||
RunFn func(fn.Function) error
|
||||
RemoveInvoked bool
|
||||
RemoveFn func(fn.Function) error
|
||||
}
|
||||
|
||||
func NewPipelinesProvider() *PipelinesProvider {
|
||||
return &PipelinesProvider{
|
||||
RunFn: func(fn.Function) error { return nil },
|
||||
RemoveFn: func(fn.Function) error { return nil },
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PipelinesProvider) Run(ctx context.Context, f fn.Function) error {
|
||||
p.RunInvoked = true
|
||||
return p.RunFn(f)
|
||||
}
|
||||
|
||||
func (p *PipelinesProvider) Remove(ctx context.Context, f fn.Function) error {
|
||||
p.RemoveInvoked = true
|
||||
return p.RemoveFn(f)
|
||||
}
|
|
@ -7,7 +7,6 @@ import (
|
|||
|
||||
"github.com/google/go-containerregistry/pkg/authn"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
|
||||
"github.com/tektoncd/cli/pkg/pipelinerun"
|
||||
"github.com/tektoncd/cli/pkg/taskrun"
|
||||
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
|
||||
|
@ -15,6 +14,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
k8slabels "k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
fn "knative.dev/kn-plugin-func"
|
||||
"knative.dev/kn-plugin-func/docker"
|
||||
|
@ -184,6 +184,59 @@ func (pp *PipelinesProvider) Run(ctx context.Context, f fn.Function) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (pp *PipelinesProvider) Remove(ctx context.Context, f fn.Function) error {
|
||||
|
||||
l := k8slabels.SelectorFromSet(k8slabels.Set(map[string]string{labels.FunctionNameKey: f.Name}))
|
||||
listOptions := metav1.ListOptions{
|
||||
LabelSelector: l.String(),
|
||||
}
|
||||
|
||||
// let's try to delete all resources in parallel, so the operation doesn't take long
|
||||
wg := sync.WaitGroup{}
|
||||
deleteFunctions := []func(context.Context, string, metav1.ListOptions) error{
|
||||
deletePipelines,
|
||||
deletePipelineRuns,
|
||||
k8s.DeleteRoleBindings,
|
||||
k8s.DeleteServiceAccounts,
|
||||
k8s.DeleteSecrets,
|
||||
k8s.DeletePersistentVolumeClaims,
|
||||
}
|
||||
|
||||
wg.Add(len(deleteFunctions))
|
||||
errChan := make(chan error, len(deleteFunctions))
|
||||
|
||||
for i := range deleteFunctions {
|
||||
df := deleteFunctions[i]
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := df(ctx, pp.namespace, listOptions)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
errChan <- err
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
close(errChan)
|
||||
|
||||
// collect all errors and print them
|
||||
var err error
|
||||
errMsg := ""
|
||||
anyError := false
|
||||
for e := range errChan {
|
||||
if !anyError {
|
||||
anyError = true
|
||||
errMsg = "error deleting resources:"
|
||||
}
|
||||
errMsg += fmt.Sprintf("\n %v", e)
|
||||
}
|
||||
|
||||
if anyError {
|
||||
err = fmt.Errorf("%s", errMsg)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// watchPipelineRunProgress watches the progress of the input PipelineRun
|
||||
// and prints detailed description of the currently executed Tekton Task.
|
||||
func (pp *PipelinesProvider) watchPipelineRunProgress(pr *v1beta1.PipelineRun) error {
|
||||
|
|
|
@ -1,15 +1,35 @@
|
|||
package tekton
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
pplnv1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
fn "knative.dev/kn-plugin-func"
|
||||
)
|
||||
|
||||
func deletePipelines(ctx context.Context, namespace string, listOptions metav1.ListOptions) (err error) {
|
||||
client, err := NewTektonClient()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return client.Pipelines(namespace).DeleteCollection(ctx, metav1.DeleteOptions{}, listOptions)
|
||||
}
|
||||
|
||||
func deletePipelineRuns(ctx context.Context, namespace string, listOptions metav1.ListOptions) (err error) {
|
||||
client, err := NewTektonClient()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return client.PipelineRuns(namespace).DeleteCollection(ctx, metav1.DeleteOptions{}, listOptions)
|
||||
}
|
||||
|
||||
func generatePipeline(f fn.Function, labels map[string]string) *pplnv1beta1.Pipeline {
|
||||
pipelineName := getPipelineName(f)
|
||||
|
||||
|
|
Loading…
Reference in New Issue