From d23ed572f976af4df279a0f807f293de75ac1e07 Mon Sep 17 00:00:00 2001 From: Sanket Sudake Date: Fri, 17 Nov 2023 14:08:38 +0530 Subject: [PATCH] Add tests for preupgradchecks and spec/archive CLI (#2874) * Add tests for preupgradchecks * Add spec tests * Add package archive tests * Wait for cleanup * Fix test and coverage --------- Signed-off-by: Sanket Sudake --- .codecov.yml | 3 +- cmd/preupgradechecks/checks.go | 12 +-- cmd/preupgradechecks/checks_test.go | 31 +++++++ cmd/preupgradechecks/main.go | 15 ++-- pkg/fission-cli/cliwrapper/cli/cli.go | 7 ++ .../cliwrapper/driver/cobra/cobra.go | 9 ++ .../cliwrapper/driver/dummy/dummy.go | 10 +++ pkg/fission-cli/cmd/archive/delete.go | 2 +- pkg/fission-cli/cmd/archive/geturl.go | 5 +- pkg/fission-cli/cmd/archive/upload.go | 3 +- pkg/fission-cli/cmd/httptrigger/create.go | 9 -- pkg/fission-cli/cmd/package/util/util.go | 16 ++-- pkg/fission-cli/util/util.go | 26 +----- test/e2e/cli/cli_test.go | 85 +++++++++++++++++-- test/e2e/framework/cli/cli.go | 2 + test/e2e/framework/framework.go | 15 ++-- test/e2e/framework/services/services.go | 11 ++- test/tests/test_archive_cli.sh | 2 +- 18 files changed, 186 insertions(+), 77 deletions(-) create mode 100644 cmd/preupgradechecks/checks_test.go diff --git a/.codecov.yml b/.codecov.yml index cfa8ef65..7196677d 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -2,7 +2,8 @@ ignore: - "charts" - "test/" - "tools" - - "pkg/apis/genclient" + - "pkg/generated" # generated code + - "pkg/apis/*/*/zz_generated*" # generated code coverage: status: project: diff --git a/cmd/preupgradechecks/checks.go b/cmd/preupgradechecks/checks.go index 243ad3c1..56bdc28c 100644 --- a/cmd/preupgradechecks/checks.go +++ b/cmd/preupgradechecks/checks.go @@ -124,7 +124,7 @@ func (client *PreUpgradeTaskClient) LatestSchemaApplied(ctx context.Context) err // VerifyFunctionSpecReferences verifies that a function references secrets, configmaps, pkgs in its own namespace and // outputs a list of functions that don't adhere to this requirement. -func (client *PreUpgradeTaskClient) VerifyFunctionSpecReferences(ctx context.Context) { +func (client *PreUpgradeTaskClient) VerifyFunctionSpecReferences(ctx context.Context) error { client.logger.Info("verifying function spec references for all functions in the cluster") var err error @@ -140,9 +140,11 @@ func (client *PreUpgradeTaskClient) VerifyFunctionSpecReferences(ctx context.Con } if err != nil { - client.logger.Fatal("error listing functions after max retries", + client.logger.Error("error listing functions after max retries", zap.Error(err), zap.Int("max_retries", maxRetries)) + errs = errors.Join(errs, fmt.Errorf("error listing functions in namespace : %s", namespace)) + continue } // check that all secrets, configmaps, packages are in the same namespace @@ -169,10 +171,8 @@ func (client *PreUpgradeTaskClient) VerifyFunctionSpecReferences(ctx context.Con } if errs != nil { - client.logger.Fatal("installation failed", - zap.Error(errs), - zap.String("summary", "a function cannot reference secrets, configmaps and packages outside it's own namespace")) + return errs } - client.logger.Info("function spec references verified") + return nil } diff --git a/cmd/preupgradechecks/checks_test.go b/cmd/preupgradechecks/checks_test.go new file mode 100644 index 00000000..a6155c53 --- /dev/null +++ b/cmd/preupgradechecks/checks_test.go @@ -0,0 +1,31 @@ +package main + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/fission/fission/test/e2e/framework" +) + +func TestPreUpgradeTaskClient(t *testing.T) { + f := framework.NewFramework() + defer f.Logger().Sync() + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + err := f.Start(ctx) + require.NoError(t, err) + + preupgradeClient, err := makePreUpgradeTaskClient(f.ClientGen(), f.Logger()) + require.NoError(t, err) + + crd := preupgradeClient.GetFunctionCRD(ctx) + require.NotNil(t, crd) + + err = preupgradeClient.LatestSchemaApplied(ctx) + require.NoError(t, err) + + err = preupgradeClient.VerifyFunctionSpecReferences(ctx) + require.NoError(t, err) +} diff --git a/cmd/preupgradechecks/main.go b/cmd/preupgradechecks/main.go index 31748ffe..4ba0e460 100644 --- a/cmd/preupgradechecks/main.go +++ b/cmd/preupgradechecks/main.go @@ -28,22 +28,25 @@ func main() { logger := loggerfactory.GetLogger() defer logger.Sync() - crdBackedClient, err := makePreUpgradeTaskClient(crd.NewClientGenerator(), logger) + ctx := signals.SetupSignalHandler() + + preupgradeClient, err := makePreUpgradeTaskClient(crd.NewClientGenerator(), logger) if err != nil { logger.Fatal("error creating a crd client, please retry helm upgrade", zap.Error(err)) } - ctx := signals.SetupSignalHandler() - crd := crdBackedClient.GetFunctionCRD(ctx) + crd := preupgradeClient.GetFunctionCRD(ctx) if crd == nil { logger.Info("nothing to do since CRDs are not present on the cluster") return } - - err = crdBackedClient.LatestSchemaApplied(ctx) + err = preupgradeClient.LatestSchemaApplied(ctx) if err != nil { logger.Fatal("New CRDs are not applied", zap.Error(err)) } - crdBackedClient.VerifyFunctionSpecReferences(ctx) + err = preupgradeClient.VerifyFunctionSpecReferences(ctx) + if err != nil { + logger.Fatal("Function spec references are not valid", zap.Error(err)) + } } diff --git a/pkg/fission-cli/cliwrapper/cli/cli.go b/pkg/fission-cli/cliwrapper/cli/cli.go index bd4009ae..04e5e222 100644 --- a/pkg/fission-cli/cliwrapper/cli/cli.go +++ b/pkg/fission-cli/cliwrapper/cli/cli.go @@ -18,6 +18,7 @@ package cli import ( "context" + "io" "time" ) @@ -76,5 +77,11 @@ type ( // Duration returns time duration of given flag. Duration(key string) time.Duration + + // Stdout returns io.Writer for stdout. + Stdout() io.Writer + + // Stderr returns io.Writer for stderr. + Stderr() io.Writer } ) diff --git a/pkg/fission-cli/cliwrapper/driver/cobra/cobra.go b/pkg/fission-cli/cliwrapper/driver/cobra/cobra.go index 09a1094f..88e33f7e 100644 --- a/pkg/fission-cli/cliwrapper/driver/cobra/cobra.go +++ b/pkg/fission-cli/cliwrapper/driver/cobra/cobra.go @@ -19,6 +19,7 @@ package cobra import ( "context" "fmt" + "io" "strings" "time" @@ -311,3 +312,11 @@ func (u Cli) Duration(key string) time.Duration { v, _ := u.c.Flags().GetDuration(key) return v } + +func (u Cli) Stdout() io.Writer { + return u.c.OutOrStdout() +} + +func (u Cli) Stderr() io.Writer { + return u.c.OutOrStderr() +} diff --git a/pkg/fission-cli/cliwrapper/driver/dummy/dummy.go b/pkg/fission-cli/cliwrapper/driver/dummy/dummy.go index c9e3807f..ce9ab48b 100644 --- a/pkg/fission-cli/cliwrapper/driver/dummy/dummy.go +++ b/pkg/fission-cli/cliwrapper/driver/dummy/dummy.go @@ -18,6 +18,8 @@ package dummy import ( "context" + "io" + "os" "time" fCli "github.com/fission/fission/pkg/fission-cli/cliwrapper/cli" @@ -169,3 +171,11 @@ func (u Cli) Duration(key string) time.Duration { } return val.(time.Duration) } + +func (u Cli) Stdout() io.Writer { + return os.Stdout +} + +func (u Cli) Stderr() io.Writer { + return os.Stderr +} diff --git a/pkg/fission-cli/cmd/archive/delete.go b/pkg/fission-cli/cmd/archive/delete.go index 35e798cc..c3dd6769 100644 --- a/pkg/fission-cli/cmd/archive/delete.go +++ b/pkg/fission-cli/cmd/archive/delete.go @@ -50,7 +50,7 @@ func (opts *DeleteSubCommand) do(input cli.Input) error { return err } - fmt.Printf("Deleted archive with id: %s", archiveID) + fmt.Printf("Deleted archive with id: %s\n", archiveID) return nil } diff --git a/pkg/fission-cli/cmd/archive/geturl.go b/pkg/fission-cli/cmd/archive/geturl.go index e3cd1d04..e5a2ca15 100644 --- a/pkg/fission-cli/cmd/archive/geturl.go +++ b/pkg/fission-cli/cmd/archive/geturl.go @@ -66,12 +66,11 @@ func (opts *GetURLSubCommand) do(input cli.Input) error { storageType := resp.Header.Get("X-FISSION-STORAGETYPE") if storageType == "local" { - storageSvc, err := util.GetSvcName(input.Context(), opts.Client().KubernetesClient, "fission-storage") + storagesvcURL, err := util.GetStorageURL(input.Context(), opts.Client()) if err != nil { return err } - storagesvcURL := "http://" + storageSvc - client := storagesvcClient.MakeClient(storagesvcURL) + client := storagesvcClient.MakeClient(storagesvcURL.String()) fmt.Printf("URL: %s", client.GetUrl(archiveID)) } else if storageType == "s3" { storageBucket := resp.Header.Get("X-FISSION-BUCKET") diff --git a/pkg/fission-cli/cmd/archive/upload.go b/pkg/fission-cli/cmd/archive/upload.go index 3614b5c5..37c6e6e0 100644 --- a/pkg/fission-cli/cmd/archive/upload.go +++ b/pkg/fission-cli/cmd/archive/upload.go @@ -49,7 +49,6 @@ func (opts *UploadSubCommand) do(input cli.Input) error { return err } - fmt.Printf("File successfully uploaded with ID: %s ", archiveID) - + fmt.Fprintf(input.Stdout(), "File successfully uploaded with ID: %s\n", archiveID) return nil } diff --git a/pkg/fission-cli/cmd/httptrigger/create.go b/pkg/fission-cli/cmd/httptrigger/create.go index a078a097..909fa13e 100644 --- a/pkg/fission-cli/cmd/httptrigger/create.go +++ b/pkg/fission-cli/cmd/httptrigger/create.go @@ -124,15 +124,6 @@ func (opts *CreateSubCommand) complete(input cli.Input) error { // For Specs, the spec validate checks for function reference if input.Bool(flagkey.SpecSave) { - - htTrigger, err := opts.Client().FissionClientSet.CoreV1().HTTPTriggers(m.Namespace).Get(input.Context(), m.Name, metav1.GetOptions{}) - if err != nil && !kerrors.IsNotFound(err) { - return err - } - if htTrigger.Name != "" && htTrigger.Namespace != "" { - return errors.New("duplicate trigger exists, choose a different name or leave it empty for fission to auto-generate it") - } - specDir := util.GetSpecDir(input) specIgnore := util.GetSpecIgnore(input) fr, err := spec.ReadSpecs(specDir, specIgnore, false) diff --git a/pkg/fission-cli/cmd/package/util/util.go b/pkg/fission-cli/cmd/package/util/util.go index 05148701..53b3b520 100644 --- a/pkg/fission-cli/cmd/package/util/util.go +++ b/pkg/fission-cli/cmd/package/util/util.go @@ -51,7 +51,6 @@ func UploadArchiveFile(ctx context.Context, client cmd.Client, fileName string) return nil, err } } else { - storagesvcURL, err := util.GetStorageURL(ctx, client) if err != nil { return nil, errors.Wrapf(err, "error getting fission storage service URL") @@ -105,12 +104,11 @@ func getArchiveURL(ctx context.Context, client cmd.Client, archiveID string, ser storageType := resp.Header.Get("X-FISSION-STORAGETYPE") if storageType == "local" { - storageSvc, err := util.GetSvcName(ctx, client.KubernetesClient, "fission-storage") + storagesvcURL, err := util.GetStorageURL(ctx, client) if err != nil { return "", err } - storagesvcURL := "http://" + storageSvc - client := storageSvcClient.MakeClient(storagesvcURL) + client := storageSvcClient.MakeClient(storagesvcURL.String()) return client.GetUrl(archiveID), nil } else if storageType == "s3" { storageBucket := resp.Header.Get("X-FISSION-BUCKET") @@ -166,23 +164,19 @@ func DownloadURL(fileUrl string) (io.ReadCloser, error) { func DownloadStrorageURL(ctx context.Context, client cmd.Client, fileUrl string) (io.ReadCloser, error) { var resp *http.Response - storageSvc, err := util.GetSvcName(ctx, client.KubernetesClient, "fission-storage") + storagesvcURL, err := util.GetStorageURL(ctx, client) if err != nil { return nil, err } - if strings.HasPrefix(fileUrl, "http://"+storageSvc+"/v1/archive?id=") { + if strings.HasPrefix(fileUrl, storagesvcURL.String()+"/v1/archive?id=") { url, err := url.Parse(fileUrl) if err != nil { return nil, err } id := url.Query().Get("id") - storageAccessURL, err := util.GetStorageURL(ctx, client) - if err != nil { - return nil, err - } - client := storageSvcClient.MakeClient(storageAccessURL.String()) + client := storageSvcClient.MakeClient(storagesvcURL.String()) resp, err = client.GetFile(ctx, id) if err != nil { return nil, err diff --git a/pkg/fission-cli/util/util.go b/pkg/fission-cli/util/util.go index d06a646d..4f0530ee 100644 --- a/pkg/fission-cli/util/util.go +++ b/pkg/fission-cli/util/util.go @@ -448,6 +448,10 @@ func ApplyLabelsAndAnnotations(input cli.Input, objectMeta *metav1.ObjectMeta) e } func GetStorageURL(ctx context.Context, client cmd.Client) (*url.URL, error) { + storagesvcURL := os.Getenv("FISSION_STORAGESVC_URL") + if len(storagesvcURL) > 0 { + return url.Parse(storagesvcURL) + } storageLocalPort, err := SetupPortForward(ctx, client, GetFissionNamespace(), "application=fission-storage") if err != nil { return nil, err @@ -507,28 +511,6 @@ func ConfigMapExists(ctx context.Context, m *metav1.ObjectMeta, kClient kubernet return err } -func GetSvcName(ctx context.Context, kClient kubernetes.Interface, application string) (string, error) { - var podNamespace = os.Getenv("POD_NAMESPACE") - if podNamespace == "" { - podNamespace = "fission" - } - - appLabelSelector := "application=" + application - - services, err := kClient.CoreV1().Services(podNamespace).List(ctx, metav1.ListOptions{ - LabelSelector: appLabelSelector, - }) - if err != nil { - return "", err - } - - if len(services.Items) > 1 || len(services.Items) == 0 { - return "", errors.Errorf("more than one service found for application=%s", application) - } - service := services.Items[0] - return service.Name + "." + podNamespace, nil -} - // FunctionPodLogs : Get logs for a function directly from pod func FunctionPodLogs(ctx context.Context, fnName, ns string, client cmd.Client) (err error) { diff --git a/test/e2e/cli/cli_test.go b/test/e2e/cli/cli_test.go index 28cde909..5c5a81f2 100644 --- a/test/e2e/cli/cli_test.go +++ b/test/e2e/cli/cli_test.go @@ -2,6 +2,8 @@ package cli_test import ( "context" + "os" + "strings" "testing" "time" @@ -17,16 +19,17 @@ import ( ) func TestFissionCLI(t *testing.T) { - mgr := manager.New() - defer mgr.Wait() - f := framework.NewFramework() - defer f.Logger().Sync() ctx, cancel := context.WithCancel(context.Background()) - defer cancel() err := f.Start(ctx) require.NoError(t, err) + defer func() { + cancel() + mgr.Wait() + err = f.Stop() + require.NoError(t, err) + }() err = services.StartServices(ctx, f, mgr) require.NoError(t, err) @@ -220,7 +223,7 @@ func TestFissionCLI(t *testing.T) { _, err = cli.ExecCommand(f, ctx, "function", "create", "--name", "test-func", "--code", "./hello.js", "--env", "test-func-env") require.NoError(t, err) - _, err = cli.ExecCommand(f, ctx, "httptrigger", "create", "--name", "test-httptrigger", "--function", "test-func", "--url", "/hello") + _, err = cli.ExecCommand(f, ctx, "httptrigger", "create", "--name", "test-httptrigger", "--function", "test-func", "--url", "/hello", "--createingress") require.NoError(t, err) ht, err := fissionClient.CoreV1().HTTPTriggers(metav1.NamespaceDefault).Get(ctx, "test-httptrigger", metav1.GetOptions{}) @@ -371,5 +374,75 @@ func TestFissionCLI(t *testing.T) { t.Run("support-dump", func(t *testing.T) { _, err := cli.ExecCommand(f, ctx, "support", "dump") require.NoError(t, err) + + err = os.RemoveAll("fission-dump") + require.NoError(t, err) + }) + + t.Run("archive", func(t *testing.T) { + out, err := cli.ExecCommand(f, ctx, "archive", "upload", "--name", "hello.js") + require.NoError(t, err) + require.Contains(t, out, "File successfully uploaded with ID") + id := out[len("File successfully uploaded with ID: "):] + // split string by / and get the last element + id = strings.Split(id, "/")[len(strings.Split(id, "/"))-1] + id = strings.Trim(id, "\n") + + _, err = cli.ExecCommand(f, ctx, "archive", "list") + require.NoError(t, err) + + _, err = cli.ExecCommand(f, ctx, "archive", "get-url", "--id", id) + require.NoError(t, err) + + _, err = cli.ExecCommand(f, ctx, "archive", "download", "--id", id) + require.NoError(t, err) + + _, err = cli.ExecCommand(f, ctx, "archive", "delete", "--id", id) + require.NoError(t, err) + }) + + t.Run("spec", func(t *testing.T) { + // check if specs directory exists and delete it + if info, err := os.Stat("specs"); err == nil && info.IsDir() { + err = os.RemoveAll("specs") + require.NoError(t, err) + } + + _, err := cli.ExecCommand(f, ctx, "spec", "init") + require.NoError(t, err) + + // create resources + _, err = cli.ExecCommand(f, ctx, "env", "create", "--name", "test-func-env", "--image", "fission/python-env", "--spec") + require.NoError(t, err) + _, err = cli.ExecCommand(f, ctx, "function", "create", "--name", "test-func", "--code", "./hello.js", "--env", "test-func-env", "--spec") + require.NoError(t, err) + _, err = cli.ExecCommand(f, ctx, "httptrigger", "create", "--name", "test-httptrigger", "--function", "test-func", "--url", "/hello", "--spec", "--createingress") + require.NoError(t, err) + _, err = cli.ExecCommand(f, ctx, "timetrigger", "create", "--name", "test-tt", "--function", "test-func", "--cron", "@every 1m", "--spec") + require.NoError(t, err) + _, err = cli.ExecCommand(f, ctx, "mqtrigger", "create", "--name", "test-mqtrigger", "--function", "test-func", "--mqtype", "kafka", "--topic", "test-topic", "--resptopic", "test-resp-topic", "--spec") + require.NoError(t, err) + + _, err = cli.ExecCommand(f, ctx, "spec", "validate") + require.NoError(t, err) + + _, err = cli.ExecCommand(f, ctx, "spec", "apply") + require.NoError(t, err) + fn, err := fissionClient.CoreV1().Functions(metav1.NamespaceDefault).Get(ctx, "test-func", metav1.GetOptions{}) + require.NoError(t, err) + require.NotNil(t, fn) + require.Equal(t, "test-func", fn.Name) + + _, err = cli.ExecCommand(f, ctx, "spec", "list") + require.NoError(t, err) + + _, err = cli.ExecCommand(f, ctx, "spec", "destroy") + require.NoError(t, err) + _, err = fissionClient.CoreV1().Functions(metav1.NamespaceDefault).Get(ctx, "test-func", metav1.GetOptions{}) + require.Error(t, err) + + // cleanup specs directory + err = os.RemoveAll("specs") + require.NoError(t, err) }) } diff --git a/test/e2e/framework/cli/cli.go b/test/e2e/framework/cli/cli.go index 4d8e9d10..f43421cd 100644 --- a/test/e2e/framework/cli/cli.go +++ b/test/e2e/framework/cli/cli.go @@ -4,6 +4,7 @@ import ( "bytes" "context" + "go.uber.org/zap" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/fission/fission/cmd/fission-cli/app" @@ -12,6 +13,7 @@ import ( ) func ExecCommand(f *framework.Framework, ctx context.Context, args ...string) (string, error) { + f.Logger().Info("Executing command", zap.Strings("args", args)) cmd := app.App(cmd.ClientOptions{ RestConfig: f.RestConfig(), Namespace: metav1.NamespaceDefault, diff --git a/test/e2e/framework/framework.go b/test/e2e/framework/framework.go index dcef5c1f..8610040d 100644 --- a/test/e2e/framework/framework.go +++ b/test/e2e/framework/framework.go @@ -20,11 +20,6 @@ import ( "github.com/fission/fission/pkg/utils/loggerfactory" ) -const ( - EXECUTOR_URL = "http://executor.fission" - STORAGESVC_URL = "http://storagesvc.fission" -) - type ServiceInfo struct { Port int } @@ -61,10 +56,14 @@ func NewFramework() *Framework { if err != nil { panic(err) } + _, filename, _, _ := runtime.Caller(0) //nolint + root := filepath.Dir(filename) + crdPath := filepath.Join(root, "..", "..", "..", "crds", "v1") + return &Framework{ logger: loggerfactory.GetLogger(), env: &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("../../..", "crds", "v1")}, + CRDDirectoryPaths: []string{crdPath}, ErrorIfCRDPathMissing: true, CRDInstallOptions: envtest.CRDInstallOptions{ MaxTime: 60 * time.Second, @@ -111,9 +110,11 @@ func (f *Framework) ClientGen() *crd.ClientGenerator { } func (f *Framework) Stop() error { + f.logger.Info("Stopping test env") + _ = f.logger.Sync() err := f.env.Stop() if err != nil { - return fmt.Errorf("error stopping test env: %v", err) + return fmt.Errorf("error stopping test env: %w", err) } return nil } diff --git a/test/e2e/framework/services/services.go b/test/e2e/framework/services/services.go index 823c0c6e..4c4f6530 100644 --- a/test/e2e/framework/services/services.go +++ b/test/e2e/framework/services/services.go @@ -87,6 +87,11 @@ func StartServices(ctx context.Context, f *framework.Framework, mgr manager.Inte return fmt.Errorf("error starting storage service: %v", err) } f.AddServiceInfo("storagesvc", framework.ServiceInfo{Port: storageSvcPort}) + storagesvcURL, err := f.GetServiceURL("storagesvc") + if err != nil { + return fmt.Errorf("error getting storage service URL: %v", err) + } + os.Setenv("FISSION_STORAGESVC_URL", storagesvcURL) err = f.ToggleMetricAddr() if err != nil { return fmt.Errorf("error toggling metric address: %v", err) @@ -122,8 +127,10 @@ func StartServices(ctx context.Context, f *framework.Framework, mgr manager.Inte return fmt.Errorf("error starting router: %v", err) } f.AddServiceInfo("router", framework.ServiceInfo{Port: routerPort}) - - routerURL := fmt.Sprintf("http://localhost:%d", routerPort) + routerURL, err := f.GetServiceURL("router") + if err != nil { + return fmt.Errorf("error getting router URL: %v", err) + } os.Setenv("FISSION_ROUTER_URL", routerURL) err = timer.Start(ctx, f.ClientGen(), f.Logger(), mgr, routerURL) diff --git a/test/tests/test_archive_cli.sh b/test/tests/test_archive_cli.sh index a43c154d..caea7314 100755 --- a/test/tests/test_archive_cli.sh +++ b/test/tests/test_archive_cli.sh @@ -54,7 +54,7 @@ ls | grep "$fileID" # Test for get-url getURLResp=$(fission ar get-url --id "$filename") -echo "$getURLResp" | grep "http://storagesvc.fission/v1/archive?id=%2Ffission%2Ffission-functions%2F$fileID" +echo "$getURLResp" | grep "/v1/archive?id=%2Ffission%2Ffission-functions%2F$fileID" # Test for delete fission ar delete --id "$filename"