From 245506efe3d1156f42728d79b50dfd10308307bd Mon Sep 17 00:00:00 2001 From: smruthi2187 <34555664+smruthi2187@users.noreply.github.com> Date: Tue, 20 Feb 2018 15:21:10 -0800 Subject: [PATCH] Delete and list orphan pkgs (#468) * prevent leaking packages; add new clis to list and delete orphan packages. * Fixes after testing. * Address review comment. * Removing deleting orphan packages from fnUpdate and fnDelete. * goFmt and removing unwanted code. --- fission/main.go | 5 ++- fission/package.go | 97 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/fission/main.go b/fission/main.go index 70105edc..60de3ec7 100644 --- a/fission/main.go +++ b/fission/main.go @@ -158,14 +158,15 @@ func main() { pkgDeployArchiveFlag := cli.StringFlag{Name: "deployarchive, deploy", Usage: "Local path or URL for binary archive"} pkgBuildCmdFlag := cli.StringFlag{Name: "buildcmd", Usage: "Build command for builder to run with"} pkgOutputFlag := cli.StringFlag{Name: "output, o", Usage: "Output filename to save archive content"} + pkgOrphanFlag := cli.BoolFlag{Name: "orphan", Usage: "orphan packages that are not referenced by any function"} pkgSubCommands := []cli.Command{ {Name: "create", Usage: "Create new package", Flags: []cli.Flag{pkgEnvironmentFlag, pkgSrcArchiveFlag, pkgDeployArchiveFlag, pkgBuildCmdFlag}, Action: pkgCreate}, {Name: "update", Usage: "Update package", Flags: []cli.Flag{pkgNameFlag, pkgEnvironmentFlag, pkgSrcArchiveFlag, pkgDeployArchiveFlag, pkgBuildCmdFlag, pkgForceFlag}, Action: pkgUpdate}, {Name: "getsrc", Usage: "Get source archive content", Flags: []cli.Flag{pkgNameFlag, pkgOutputFlag}, Action: pkgSourceGet}, {Name: "getdeploy", Usage: "Get deployment archive content", Flags: []cli.Flag{pkgNameFlag, pkgOutputFlag}, Action: pkgDeployGet}, {Name: "info", Usage: "Show package information", Flags: []cli.Flag{pkgNameFlag}, Action: pkgInfo}, - {Name: "list", Usage: "List all packages", Flags: []cli.Flag{}, Action: pkgList}, - {Name: "delete", Usage: "Delete package", Flags: []cli.Flag{pkgNameFlag, pkgForceFlag}, Action: pkgDelete}, + {Name: "list", Usage: "List all packages", Flags: []cli.Flag{pkgOrphanFlag}, Action: pkgList}, + {Name: "delete", Usage: "Delete package", Flags: []cli.Flag{pkgNameFlag, pkgForceFlag, pkgOrphanFlag}, Action: pkgDelete}, } // upgrades, data migrations diff --git a/fission/package.go b/fission/package.go index 1d582383..fe115dfc 100644 --- a/fission/package.go +++ b/fission/package.go @@ -271,6 +271,8 @@ func pkgInfo(c *cli.Context) error { func pkgList(c *cli.Context) error { client := getClient(c.GlobalString("server")) + // option for the user to list all orphan packages (not referenced by any function) + listOrphans := c.Bool("orphan") pkgList, err := client.PackageList() if err != nil { @@ -279,47 +281,94 @@ func pkgList(c *cli.Context) error { w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) fmt.Fprintf(w, "%v\t%v\t%v\n", "NAME", "BUILD_STATUS", "ENV") - for _, pkg := range pkgList { - fmt.Fprintf(w, "%v\t%v\t%v\n", pkg.Metadata.Name, - pkg.Status.BuildStatus, pkg.Spec.Environment.Name) + if listOrphans { + for _, pkg := range pkgList { + fnList, err := getFunctionsByPackage(client, pkg.Metadata.Name) + checkErr(err, fmt.Sprintf("get functions sharing package %s", pkg.Metadata.Name)) + if len(fnList) == 0 { + fmt.Fprintf(w, "%v\t%v\t%v\n", pkg.Metadata.Name, pkg.Status.BuildStatus, pkg.Spec.Environment.Name) + } + } + } else { + for _, pkg := range pkgList { + fmt.Fprintf(w, "%v\t%v\t%v\n", pkg.Metadata.Name, + pkg.Status.BuildStatus, pkg.Spec.Environment.Name) + } } + w.Flush() return nil } +func deleteOrphanPkgs(client *client.Client) error { + pkgList, err := client.PackageList() + if err != nil { + return err + } + + // range through all packages and find out the ones not referenced by any function + for _, pkg := range pkgList { + fnList, err := getFunctionsByPackage(client, pkg.Metadata.Name) + checkErr(err, fmt.Sprintf("get functions sharing package %s", pkg.Metadata.Name)) + if len(fnList) == 0 { + err = deletePackage(client, pkg.Metadata.Name) + if err != nil { + return err + } + } + } + return nil +} + +func deletePackage(client *client.Client, pkgName string) error { + return client.PackageDelete(&metav1.ObjectMeta{ + Namespace: metav1.NamespaceDefault, + Name: pkgName, + }) +} + func pkgDelete(c *cli.Context) error { client := getClient(c.GlobalString("server")) pkgName := c.String("name") - if len(pkgName) == 0 { - fmt.Println("Need --name argument.") + deleteOrphans := c.Bool("orphan") + + if len(pkgName) == 0 && !deleteOrphans { + fmt.Println("Need --name argument or --orphan flag.") + return nil + } + if len(pkgName) != 0 && deleteOrphans { + fmt.Println("Need either --name argument or --orphan flag") return nil } - force := c.Bool("f") + if len(pkgName) != 0 { + force := c.Bool("f") - _, err := client.PackageGet(&metav1.ObjectMeta{ - Namespace: metav1.NamespaceDefault, - Name: pkgName, - }) - checkErr(err, "find package") + _, err := client.PackageGet(&metav1.ObjectMeta{ + Namespace: metav1.NamespaceDefault, + Name: pkgName, + }) + checkErr(err, "find package") - fnList, err := getFunctionsByPackage(client, pkgName) + fnList, err := getFunctionsByPackage(client, pkgName) - if !force && len(fnList) > 0 { - fatal("Package is used by at least one function, use -f to force delete") + if !force && len(fnList) > 0 { + fatal("Package is used by at least one function, use -f to force delete") + } + + err = deletePackage(client, pkgName) + if err != nil { + return err + } + + fmt.Printf("Package '%v' deleted\n", pkgName) + } else { + err := deleteOrphanPkgs(client) + checkErr(err, "error deleting orphan packages") + fmt.Println("Orphan packages deleted") } - err = client.PackageDelete(&metav1.ObjectMeta{ - Namespace: metav1.NamespaceDefault, - Name: pkgName, - }) - if err != nil { - return err - } - - fmt.Printf("Package '%v' deleted\n", pkgName) - return nil }