Skip to content

Commit

Permalink
Feat: CLI Usability (#9)
Browse files Browse the repository at this point in the history
* Adding jimmy's suggestions

Signed-off-by: Shivansh Vij <shivanshvij@loopholelabs.io>

* Making sure push logs that it will push to the user's default organization

Signed-off-by: Shivansh Vij <shivanshvij@loopholelabs.io>

* Making sure pull attempts to pull from the registry if the fn is now available locally

Signed-off-by: Shivansh Vij <shivanshvij@loopholelabs.io>

* Adding pull down functionality

Signed-off-by: Shivansh Vij <shivanshvij@loopholelabs.io>

* Fixing some bugs

Signed-off-by: Shivansh Vij <shivanshvij@loopholelabs.io>

* Bumping versions

Signed-off-by: Shivansh Vij <shivanshvij@loopholelabs.io>

---------

Signed-off-by: Shivansh Vij <shivanshvij@loopholelabs.io>
  • Loading branch information
ShivanshVij committed Feb 28, 2023
1 parent 202714d commit edeb5f8
Show file tree
Hide file tree
Showing 16 changed files with 200 additions and 129 deletions.
6 changes: 3 additions & 3 deletions cmd/function/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ func BuildCmd(hidden bool) command.SetupCommand[*config.Config] {
}

if !scalefunc.ValidString(org) {
return fmt.Errorf("invalid organization %s", org)
return utils.InvalidStringError("organization", org)
}

if scaleFile.Name == "" || !scalefunc.ValidString(scaleFile.Name) {
return fmt.Errorf("invalid name %s", scaleFile.Name)
return utils.InvalidStringError("name", scaleFile.Name)
}

if scaleFile.Tag == "" || !scalefunc.ValidString(scaleFile.Tag) {
return fmt.Errorf("invalid tag %s", scaleFile.Tag)
return utils.InvalidStringError("tag", scaleFile.Tag)
}

end := ch.Printer.PrintProgress(fmt.Sprintf("Building scale function %s:%s...", scaleFile.Name, scaleFile.Tag))
Expand Down
8 changes: 4 additions & 4 deletions cmd/function/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@ func DeleteCmd() command.SetupCommand[*config.Config] {
parsed.Organization = utils.DefaultOrganization
}

if parsed.Organization == "" || !scalefunc.ValidString(parsed.Organization) {
return fmt.Errorf("invalid organization name: %s", parsed.Organization)
if parsed.Organization != "" && !scalefunc.ValidString(parsed.Organization) {
return utils.InvalidStringError("organization name", parsed.Organization)
}

if parsed.Name == "" || !scalefunc.ValidString(parsed.Name) {
return fmt.Errorf("invalid function name: %s", parsed.Name)
return utils.InvalidStringError("function name", parsed.Name)
}

if parsed.Tag == "" || !scalefunc.ValidString(parsed.Tag) {
return fmt.Errorf("invalid tag: %s", parsed.Tag)
return utils.InvalidStringError("function tag", parsed.Tag)
}

e, err := st.Get(parsed.Name, parsed.Tag, parsed.Organization, "")
Expand Down
26 changes: 18 additions & 8 deletions cmd/function/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
// ExportCmd encapsulates the commands for exporting Functions
func ExportCmd() command.SetupCommand[*config.Config] {
var outputName string
var raw bool
return func(cmd *cobra.Command, ch *cmdutils.Helper[*config.Config]) {
exportCmd := &cobra.Command{
Use: "export [<name>:<tag> | [<org>/<name>:<tag>] <output_path>",
Expand All @@ -54,16 +55,16 @@ func ExportCmd() command.SetupCommand[*config.Config] {
parsed.Organization = utils.DefaultOrganization
}

if parsed.Organization == "" || !scalefunc.ValidString(parsed.Organization) {
return fmt.Errorf("invalid organization name: %s", parsed.Organization)
if parsed.Organization != "" && !scalefunc.ValidString(parsed.Organization) {
return utils.InvalidStringError("organization name", parsed.Organization)
}

if parsed.Name == "" || !scalefunc.ValidString(parsed.Name) {
return fmt.Errorf("invalid function name: %s", parsed.Name)
return utils.InvalidStringError("function name", parsed.Name)
}

if parsed.Tag == "" || !scalefunc.ValidString(parsed.Tag) {
return fmt.Errorf("invalid tag: %s", parsed.Tag)
return utils.InvalidStringError("function tag", parsed.Tag)
}

e, err := st.Get(parsed.Name, parsed.Tag, parsed.Organization, "")
Expand All @@ -74,7 +75,7 @@ func ExportCmd() command.SetupCommand[*config.Config] {
return fmt.Errorf("function %s/%s:%s does not exist", parsed.Organization, parsed.Name, parsed.Tag)
}

output := args[3]
output := args[1]
oInfo, err := os.Stat(output)
if err != nil {
return fmt.Errorf("failed to stat output path %s: %w", output, err)
Expand All @@ -85,16 +86,24 @@ func ExportCmd() command.SetupCommand[*config.Config] {
}

if outputName == "" {
suffix := "scale"
if raw {
suffix = "wasm"
}
if parsed.Organization != utils.DefaultOrganization {
output = path.Join(output, fmt.Sprintf("%s-%s-%s.scale", parsed.Organization, parsed.Name, parsed.Tag))
output = path.Join(output, fmt.Sprintf("%s-%s-%s.%s", parsed.Organization, parsed.Name, parsed.Tag, suffix))
} else {
output = path.Join(output, fmt.Sprintf("%s-%s.scale", parsed.Name, parsed.Tag))
output = path.Join(output, fmt.Sprintf("%s-%s.%s", parsed.Name, parsed.Tag, suffix))
}
} else {
output = path.Join(output, outputName)
}

err = os.WriteFile(output, e.ScaleFunc.Encode(), 0644)
if raw {
err = os.WriteFile(output, e.ScaleFunc.Function, 0644)
} else {
err = os.WriteFile(output, e.ScaleFunc.Encode(), 0644)
}
if err != nil {
return fmt.Errorf("failed to write function to %s: %w", output, err)
}
Expand Down Expand Up @@ -123,6 +132,7 @@ func ExportCmd() command.SetupCommand[*config.Config] {
}

exportCmd.Flags().StringVarP(&outputName, "output-name", "o", "", "the (optional) output name of the function to export")
exportCmd.Flags().BoolVar(&raw, "raw", false, "export the raw wasm module instead of the compiled scale function")
cmd.AddCommand(exportCmd)
}
}
5 changes: 3 additions & 2 deletions cmd/function/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/loopholelabs/cmdutils"
"github.com/loopholelabs/cmdutils/pkg/command"
"github.com/loopholelabs/cmdutils/pkg/printer"
"github.com/loopholelabs/scale-cli/cmd/utils"
"github.com/loopholelabs/scale-cli/internal/config"
"github.com/loopholelabs/scale-cli/pkg/template"
"github.com/loopholelabs/scalefile"
Expand Down Expand Up @@ -55,7 +56,7 @@ func NewCmd(hidden bool) command.SetupCommand[*config.Config] {
RunE: func(cmd *cobra.Command, args []string) error {
name := args[0]
if name == "" || !scalefunc.ValidString(name) {
return fmt.Errorf("invalid name %s", name)
return utils.InvalidStringError("function name", name)
}

extension, ok := extensionLUT[language]
Expand All @@ -66,7 +67,7 @@ func NewCmd(hidden bool) command.SetupCommand[*config.Config] {
scaleFile := &scalefile.ScaleFile{
Version: scalefile.V1Alpha,
Name: name,
Tag: "v0.1.0",
Tag: utils.DefaultTag,
Signature: defaultSignature,
Language: scalefile.Language(language),
Source: fmt.Sprintf("scale.%s", extension),
Expand Down
52 changes: 39 additions & 13 deletions cmd/function/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/loopholelabs/scale-cli/internal/config"
adapter "github.com/loopholelabs/scale-http-adapters/fasthttp"
"github.com/loopholelabs/scale/go"
"github.com/loopholelabs/scale/go/registry"
"github.com/loopholelabs/scale/go/storage"
"github.com/loopholelabs/scalefile/scalefunc"
"github.com/spf13/cobra"
Expand All @@ -41,11 +42,13 @@ func RunCmd(hidden bool) command.SetupCommand[*config.Config] {
return func(cmd *cobra.Command, ch *cmdutils.Helper[*config.Config]) {
var listen string
runCmd := &cobra.Command{
Use: "run [ ...[ <name>:<tag> ] | [ <org>/<name>:<tag> ] ] [flags]",
Args: cobra.MinimumNArgs(1),
Short: "run a compiled scale function",
Long: "Run a compiled scale function by starting an HTTP server that will listen for incoming requests and execute the specified functions in a chain. It's possible to specify multiple functions to be executed in a chain. The functions will be executed in the order they are specified. The scalefile must be in the current directory or specified with the --directory flag.",
Hidden: hidden,
Use: "run [ ...[ <name>:<tag> ] | [ <org>/<name>:<tag> ] ] [flags]",
Args: cobra.MinimumNArgs(1),
Short: "run a compiled scale function",
Long: "Run a compiled scale function by starting an HTTP server that will listen for incoming requests and execute the specified functions in a chain. It's possible to specify multiple functions to be executed in a chain. The functions will be executed in the order they are specified. The scalefile must be in the current directory or specified with the --directory flag.",
Hidden: hidden,
PreRunE: utils.PreRunOptionalAuthenticatedAPI(ch),
PostRunE: utils.PostRunAuthenticatedAPI(ch),
RunE: func(cmd *cobra.Command, args []string) error {
st := storage.Default
if ch.Config.CacheDirectory != "" {
Expand All @@ -63,16 +66,16 @@ func RunCmd(hidden bool) command.SetupCommand[*config.Config] {
parsed.Organization = utils.DefaultOrganization
}

if parsed.Organization == "" || !scalefunc.ValidString(parsed.Organization) {
return fmt.Errorf("invalid organization name: %s", parsed.Organization)
if parsed.Organization != "" && !scalefunc.ValidString(parsed.Organization) {
return utils.InvalidStringError("organization name", parsed.Organization)
}

if parsed.Name == "" || !scalefunc.ValidString(parsed.Name) {
return fmt.Errorf("invalid function name: %s", parsed.Name)
return utils.InvalidStringError("function name", parsed.Name)
}

if parsed.Tag == "" || !scalefunc.ValidString(parsed.Tag) {
return fmt.Errorf("invalid tag: %s", parsed.Tag)
return utils.InvalidStringError("function tag", parsed.Tag)
}

e, err := st.Get(parsed.Name, parsed.Tag, parsed.Organization, "")
Expand All @@ -81,10 +84,33 @@ func RunCmd(hidden bool) command.SetupCommand[*config.Config] {
}

if e == nil {
return fmt.Errorf("function %s not found", f)
end := ch.Printer.PrintProgress(fmt.Sprintf("Function %s was not found not found, pulling from the registry...", printer.BoldGreen(f)))
var opts []registry.Option
opts = append(opts, registry.WithClient(ch.Config.APIClient()), registry.WithStorage(st))
if parsed.Organization != "" && parsed.Organization != utils.DefaultOrganization {
opts = append(opts, registry.WithOrganization(parsed.Organization))
}
sf, err := registry.New(parsed.Name, parsed.Tag, opts...)
end()
if err != nil {
if parsed.Organization == "" {
return fmt.Errorf("failed to pull function %s:%s: %w", parsed.Name, parsed.Tag, err)
} else {
return fmt.Errorf("failed to pull function %s/%s:%s: %w", parsed.Organization, parsed.Name, parsed.Tag, err)
}
}

if ch.Printer.Format() == printer.Human {
if parsed.Organization == "" {
ch.Printer.Printf("Pulled %s from the Scale Registry\n", printer.BoldGreen(fmt.Sprintf("%s:%s", sf.Name, sf.Tag)))
} else {
ch.Printer.Printf("Pulled %s from the Scale Registry\n", printer.BoldGreen(fmt.Sprintf("%s/%s:%s", parsed.Organization, sf.Name, sf.Tag)))
}
}
fns = append(fns, sf)
} else {
fns = append(fns, e.ScaleFunc)
}

fns = append(fns, e.ScaleFunc)
}

ctx := cmd.Context()
Expand All @@ -106,7 +132,7 @@ func RunCmd(hidden bool) command.SetupCommand[*config.Config] {
wg.Add(1)
go func() {
defer wg.Done()
ch.Printer.Printf("scale functions %s listening at %s", printer.BoldGreen(args), printer.BoldGreen(listen))
ch.Printer.Printf("Scale Functions %s listening at %s", printer.BoldGreen(args), printer.BoldGreen(listen))
err = server.ListenAndServe(listen)
if err != nil {
ch.Printer.Printf("error starting server: %v", printer.BoldRed(err))
Expand Down
16 changes: 8 additions & 8 deletions cmd/function/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,16 @@ func TagCmd() command.SetupCommand[*config.Config] {
parsed.Organization = utils.DefaultOrganization
}

if parsed.Organization == "" || !scalefunc.ValidString(parsed.Organization) {
return fmt.Errorf("invalid organization name: %s", parsed.Organization)
if parsed.Organization != "" && !scalefunc.ValidString(parsed.Organization) {
return utils.InvalidStringError("organization name", parsed.Organization)
}

if parsed.Name == "" || !scalefunc.ValidString(parsed.Name) {
return fmt.Errorf("invalid function name: %s", parsed.Name)
return utils.InvalidStringError("function name", parsed.Name)
}

if parsed.Tag == "" || !scalefunc.ValidString(parsed.Tag) {
return fmt.Errorf("invalid tag: %s", parsed.Tag)
return utils.InvalidStringError("function tag", parsed.Tag)
}

e, err := st.Get(parsed.Name, parsed.Tag, parsed.Organization, "")
Expand All @@ -74,16 +74,16 @@ func TagCmd() command.SetupCommand[*config.Config] {
newParsed.Organization = utils.DefaultOrganization
}

if newParsed.Organization == "" || !scalefunc.ValidString(newParsed.Organization) {
return fmt.Errorf("invalid organization name: %s", newParsed.Organization)
if newParsed.Organization != "" && !scalefunc.ValidString(newParsed.Organization) {
return utils.InvalidStringError("organization name", newParsed.Organization)
}

if newParsed.Name == "" || !scalefunc.ValidString(newParsed.Name) {
return fmt.Errorf("invalid function name: %s", newParsed.Name)
return utils.InvalidStringError("function name", newParsed.Name)
}

if newParsed.Tag == "" || !scalefunc.ValidString(newParsed.Tag) {
return fmt.Errorf("invalid tag: %s", newParsed.Tag)
return utils.InvalidStringError("function tag", newParsed.Tag)
}

e.ScaleFunc.Name = newParsed.Name
Expand Down
20 changes: 11 additions & 9 deletions cmd/registry/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,29 @@ import (
func DeleteCmd() command.SetupCommand[*config.Config] {
return func(cmd *cobra.Command, ch *cmdutils.Helper[*config.Config]) {
deleteCmd := &cobra.Command{
Use: "delete <org>/<name>:<tag> [flags]",
Short: "delete a scale function from the scale registry ",
Long: "Delete a scale functions from an organization in the registry.",
Args: cobra.ExactArgs(1),
Use: "delete <org>/<name>:<tag> [flags]",
Short: "delete a scale function from the scale registry ",
Long: "Delete a scale functions from an organization in the registry.",
Args: cobra.ExactArgs(1),
PreRunE: utils.PreRunAuthenticatedAPI(ch),
PostRunE: utils.PostRunAuthenticatedAPI(ch),
RunE: func(cmd *cobra.Command, args []string) error {
parsed := utils.ParseFunction(args[0])
if parsed.Organization == "" || !scalefunc.ValidString(parsed.Organization) {
return fmt.Errorf("invalid organization name: %s", parsed.Organization)
if parsed.Organization != "" && !scalefunc.ValidString(parsed.Organization) {
return utils.InvalidStringError("organization name", parsed.Organization)
}

if parsed.Name == "" || !scalefunc.ValidString(parsed.Name) {
return fmt.Errorf("invalid function name: %s", parsed.Name)
return utils.InvalidStringError("function name", parsed.Name)
}

if parsed.Tag == "" || !scalefunc.ValidString(parsed.Tag) {
return fmt.Errorf("invalid tag: %s", parsed.Tag)
return utils.InvalidStringError("function tag", parsed.Tag)
}

ctx := cmd.Context()
client := ch.Config.APIClient()
end := ch.Printer.PrintProgress(fmt.Sprintf("Pushing %s/%s:%s to Scale Registry...", parsed.Organization, parsed.Name, parsed.Tag))
end := ch.Printer.PrintProgress(fmt.Sprintf("Deleting %s/%s:%s from the Scale Registry...", parsed.Organization, parsed.Name, parsed.Tag))

_, err := client.Registry.DeleteRegistryFunctionOrganizationNameTag(registry.NewDeleteRegistryFunctionOrganizationNameTagParamsWithContext(ctx).WithOrganization(parsed.Organization).WithName(parsed.Name).WithTag(parsed.Tag))
end()
Expand Down
13 changes: 8 additions & 5 deletions cmd/registry/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/loopholelabs/cmdutils"
"github.com/loopholelabs/cmdutils/pkg/command"
"github.com/loopholelabs/cmdutils/pkg/printer"
"github.com/loopholelabs/scale-cli/cmd/utils"
"github.com/loopholelabs/scale-cli/internal/config"
"github.com/loopholelabs/scale/go/client/registry"
"github.com/loopholelabs/scale/go/client/userinfo"
Expand All @@ -32,10 +33,12 @@ import (
func ListCmd() command.SetupCommand[*config.Config] {
return func(cmd *cobra.Command, ch *cmdutils.Helper[*config.Config]) {
listCmd := &cobra.Command{
Use: "list [<org>] [flags]",
Short: "list all the scale function for an organization from the registry",
Long: "List all the scale functions available in an organization from the registry. If no org is specified, it will default to the user's organization.",
Args: cobra.RangeArgs(0, 1),
Use: "list [<org>] [flags]",
Short: "list all the scale function for an organization from the registry",
Long: "List all the scale functions available in an organization from the registry. If no org is specified, it will default to the user's organization.",
Args: cobra.RangeArgs(0, 1),
PreRunE: utils.PreRunAuthenticatedAPI(ch),
PostRunE: utils.PostRunAuthenticatedAPI(ch),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
client := ch.Config.APIClient()
Expand All @@ -50,7 +53,7 @@ func ListCmd() command.SetupCommand[*config.Config] {
org = args[0]
}
if org == "" || !scalefunc.ValidString(org) {
return fmt.Errorf("invalid organization name: %s", org)
return utils.InvalidStringError("organization name", org)
}

end := ch.Printer.PrintProgress(fmt.Sprintf("Retrieving Scale Functions for the '%s' organization from the Registry...", org))
Expand Down
22 changes: 12 additions & 10 deletions cmd/registry/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ func PullCmd(hidden bool) command.SetupCommand[*config.Config] {
var force bool
return func(cmd *cobra.Command, ch *cmdutils.Helper[*config.Config]) {
pullCmd := &cobra.Command{
Use: "pull [<name>:<tag> | [<org>/<name>:<tag>]",
Short: "pull a scale function from the registry",
Long: "Pull a scale function from the registry. If the org is not specified, it will default to the official `scale` organization.",
Hidden: hidden,
Args: cobra.ExactArgs(1),
Use: "pull [<name>:<tag> | [<org>/<name>:<tag>]",
Short: "pull a scale function from the registry",
Long: "Pull a scale function from the registry. If the org is not specified, it will default to the official `scale` organization.",
Hidden: hidden,
Args: cobra.ExactArgs(1),
PreRunE: utils.PreRunOptionalAuthenticatedAPI(ch),
PostRunE: utils.PostRunAuthenticatedAPI(ch),
RunE: func(cmd *cobra.Command, args []string) error {
st := storage.Default
if ch.Config.CacheDirectory != "" {
Expand All @@ -51,15 +53,15 @@ func PullCmd(hidden bool) command.SetupCommand[*config.Config] {

parsed := utils.ParseFunction(args[0])
if parsed.Organization != "" && !scalefunc.ValidString(parsed.Organization) {
return fmt.Errorf("invalid organization name: %s", parsed.Organization)
return utils.InvalidStringError("organization name", parsed.Organization)
}

if parsed.Name == "" || !scalefunc.ValidString(parsed.Name) {
return fmt.Errorf("invalid function name: %s", parsed.Name)
return utils.InvalidStringError("function name", parsed.Name)
}

if parsed.Tag == "" || !scalefunc.ValidString(parsed.Tag) {
return fmt.Errorf("invalid tag: %s", parsed.Tag)
return utils.InvalidStringError("function tag", parsed.Tag)
}

var end func()
Expand All @@ -83,9 +85,9 @@ func PullCmd(hidden bool) command.SetupCommand[*config.Config] {
end()
if err != nil {
if parsed.Organization == "" {
return fmt.Errorf("failed to instantiate function %s:%s: %w", parsed.Name, parsed.Tag, err)
return fmt.Errorf("failed to pull function %s:%s: %w", parsed.Name, parsed.Tag, err)
} else {
return fmt.Errorf("failed to instantiate function %s/%s:%s: %w", parsed.Organization, parsed.Name, parsed.Tag, err)
return fmt.Errorf("failed to pull function %s/%s:%s: %w", parsed.Organization, parsed.Name, parsed.Tag, err)
}
}

Expand Down
Loading

0 comments on commit edeb5f8

Please sign in to comment.