This is an automated email from the ASF dual-hosted git repository.

msciabarra pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/openserverless-cli.git

commit 1cbe7f81b0323f381d7f06a0ca2a121369658609
Author: Michele Sciabarra <[email protected]>
AuthorDate: Wed Aug 7 15:51:54 2024 +0200

    0.1.0-2408071551.dev
---
 Taskfile.yml     |   5 ++
 auth/login.go    |  45 ++++++++-------
 main.go          | 172 +++++++++++++++++++++++++++++++------------------------
 tests/help.bats  |  99 ++++++++++++++++++++++++++++++++
 tests/utils.bats | 102 +++++++++++++++++++++++++++++++++
 version.txt      |   2 +-
 6 files changed, 328 insertions(+), 97 deletions(-)

diff --git a/Taskfile.yml b/Taskfile.yml
index 3642490..a60d8fb 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -53,6 +53,7 @@ tasks:
     - task: build
 
   build:
+    aliases: [b]
     desc: build ops locally
     cmds:
       - echo building {{.VERSION}}
@@ -66,6 +67,7 @@ tasks:
       - ops
 
   debug:
+    aliases: [d]
     cmds:
       - task: build
         vars:
@@ -73,6 +75,7 @@ tasks:
       - dlv exec ./ops -- {{.CLI_ARGS}}
 
   install:
+    aliases: [i]
     desc: install ops in ~./local/bin
     deps:
       - build
@@ -96,6 +99,7 @@ tasks:
       - task: itest
 
   utest:
+    aliases: [ut]
     desc: unit test (use F=-v to verbose)
     cmds:
       - rm -Rf ~/.ops
@@ -116,6 +120,7 @@ tasks:
     - test -d bats
 
   itest:
+    aliases: [it]
     desc: integration tests for ops (T=<test-name> without .bats, empty run 
all, pass flags with F=)
     dir: tests
     cmds:
diff --git a/auth/login.go b/auth/login.go
index b7864dd..8af3a5b 100644
--- a/auth/login.go
+++ b/auth/login.go
@@ -30,7 +30,6 @@ import (
        "path/filepath"
 
        "github.com/apache/openserverless-cli/config"
-       "github.com/mitchellh/go-homedir"
        "github.com/zalando/go-keyring"
 )
 
@@ -41,7 +40,7 @@ type LoginResult struct {
 }
 
 const usage = `Usage:
-ops login <apihost> [<user>]
+ops -login <apihost> [<user>]
 
 Login to an OpenServerless instance. If no user is specified, the default user 
"nuvolaris" is used.
 You can set the environment variables OPS_APIHOST and OPS_USER to avoid 
specifying them on the command line.
@@ -50,12 +49,18 @@ You can set OPS_PASSWORD to avoid entering the password 
interactively.
 Options:
   -h, --help   Show usage`
 
-const whiskLoginPath = "/api/v1/web/whisk-system/ops/login"
+const whiskLoginPath = "/api/v1/web/whisk-system/nuv/login"
 const defaultUser = "nuvolaris"
 const opsSecretServiceName = "nuvolaris"
 
 func LoginCmd() (*LoginResult, error) {
-       flag := flag.NewFlagSet("login", flag.ExitOnError)
+
+       // enable log output if requested
+       if os.Getenv("DEBUG")+os.Getenv("TRACE") != "" {
+               log.SetOutput(os.Stdout)
+       }
+
+       flag := flag.NewFlagSet("-login", flag.ExitOnError)
        flag.Usage = func() {
                fmt.Println(usage)
        }
@@ -80,17 +85,6 @@ func LoginCmd() (*LoginResult, error) {
                return nil, errors.New("missing apihost")
        }
 
-       password := os.Getenv("OPS_PASSWORD")
-       if password == "" {
-               fmt.Print("Enter Password: ")
-               pwd, err := AskPassword()
-               if err != nil {
-                       return nil, err
-               }
-               password = pwd
-               fmt.Println()
-       }
-
        apihost := os.Getenv("OPS_APIHOST")
        if apihost == "" {
                apihost = args[0]
@@ -116,11 +110,22 @@ func LoginCmd() (*LoginResult, error) {
 
        // if still not set, use the default user
        if user == "" {
-               log.Println("Using the default user:", defaultUser)
+               fmt.Println("Using the default user:", defaultUser)
                user = defaultUser
        }
 
-       log.Println("Logging in as", user, "to", apihost)
+       fmt.Println("Logging in", apihost, "as", user)
+
+       password := os.Getenv("OPS_PASSWORD")
+       if password == "" {
+               fmt.Print("Enter Password: ")
+               pwd, err := AskPassword()
+               if err != nil {
+                       return nil, err
+               }
+               password = pwd
+               fmt.Println()
+       }
 
        creds, err := doLogin(url, user, password)
        if err != nil {
@@ -131,9 +136,9 @@ func LoginCmd() (*LoginResult, error) {
                return nil, errors.New("missing AUTH token from login response")
        }
 
-       opsHome, err := homedir.Expand("~/.ops")
-       if err != nil {
-               return nil, err
+       opsHome := os.Getenv("OPS_HOME")
+       if opsHome == "" {
+               return nil, fmt.Errorf("OPS_HOME not defined")
        }
 
        configMap, err := config.NewConfigMapBuilder().
diff --git a/main.go b/main.go
index 2f3e1cc..eefc04b 100644
--- a/main.go
+++ b/main.go
@@ -106,24 +106,27 @@ func info() {
        //fmt.Println("OPS_COREUTILS:", os.Getenv("OPS_COREUTILS"))
 }
 
-var mainTools = []string{
-       "task", "info", "update", "login", "config",
-       "retry", "plugin", "reset", "serve",
+func banner() {
+       fmt.Println("Welcome to ops, the all-mighty, extensibile apache 
OPenServerless CLI Tool.")
+       fmt.Println("General syntax:")
+       fmt.Println("   ops -<tool>  <args>...")
+       fmt.Println("   ops <task>   <args>...")
+       fmt.Println("Essential tools (chek -h and -t for more):")
+       fmt.Println("-h | -help    list tools      (embedded tools, prefixed by 
'-', no download)")
+       fmt.Println("-v | -version current version (always mention this when 
asking for help)")
+       fmt.Println("-t | -tasks   list tasks      (show top level tasks, 
download if needed)")
+       fmt.Println("-i | -info    CLI infos       (show the cli environment)")
+       fmt.Println("-u | -update  download latest (get the latest tasks and 
prerequisites)")
+       fmt.Println("-c | -config  manage config   (openserverless server 
configuration)")
+       fmt.Println("-l | -login   access system   (required to access 
openserverless)")
+       fmt.Println("-reset        clean downloads (if nothing works, try 
this)")
+       fmt.Println()
 }
 
 // simple tools provide info and exit
-func InfoAndExit(args []string) {
+func executeToolsNoDownloadAndExit(args []string) {
        if len(args) < 2 {
-               fmt.Println("Welcome to ops, the all-mighty, extensibile apache 
OPenServerless CLI Tool.")
-               fmt.Println("Let's start with the basics:")
-               fmt.Println("-h | -help    list commands   (top level command, 
start here)")
-               fmt.Println("-t | -tools   list tools      (embedded tools, 
prefixed by '-')")
-               fmt.Println("-v | -version current version (mention this when 
you ask for help)")
-               fmt.Println("-i | -info    CLI infos       (let's check the 
CLI)")
-               fmt.Println("-u | -update  download latest (get the latest 
commands and prerequisites)")
-               fmt.Println("-l | -login   access system   (you have to login 
first)")
-               fmt.Println("-c | -config  manage config   (server 
configuration)")
-               fmt.Println("-reset        clean downloads (if nothing works, 
try this)")
+               banner()
                os.Exit(0)
        }
        // if we have at least one arg
@@ -131,19 +134,58 @@ func InfoAndExit(args []string) {
        case "-v", "-version":
                fmt.Println(OpsVersion)
                os.Exit(0)
-       case "-t", "-tools":
+       case "-h", "-help":
+               banner()
                tools.Help(mainTools)
                os.Exit(0)
+       case "-reset":
+               home := os.Getenv("OPS_HOME")
+               if home == "" {
+                       log.Fatal("cannot determine the ops home dir")
+                       os.Exit(1)
+               }
+               info, err := os.Stat(home)
+               if os.IsNotExist(err) {
+                       fmt.Printf("%s does not exists - nothing to to do\n", 
home)
+                       os.Exit(1)
+               }
+               if err != nil {
+                       log.Fatal("error in reading the ops home dir", 
err.Error())
+               }
+               if !info.IsDir() {
+                       log.Fatal("cannot reset, not a directory", home)
+               }
+               if len(args) == 2 || (len(args) > 2 && args[2] != "force") {
+                       if !confirm(fmt.Sprintf("I am going to remove the 
subfolder %s (use force to skip this question).\nAre you sure [yes/no]:", 
home)) {
+                               log.Fatal("reset aborted")
+                       }
+               } else {
+                       fmt.Println("removing without asking for confirmation 
as requested...")
+               }
+               err = os.RemoveAll(home)
+               if err != nil {
+                       log.Fatal("ops reset error:", err.Error())
+               }
+               fmt.Println("ops -reset complete - execute ops -update to 
reload")
+               os.Exit(0)
+
        default:
                return
        }
 }
 
-// CLI: ops -<cmd> <args>...
-func executeTools(cmd string, args []string, opsHome string) int {
+var mainTools = []string{
+       "task", "info", "update", "login", "config",
+       "retry", "plugin", "reset", "serve",
+}
 
+// CLI: ops -<cmd> <args>...
+func executeTools(args []string, opsHome string) int {
+       trace("TOOL:", args)
+       cmd := args[0]
        switch cmd {
        case "", "task":
+               args = args[1:]
                exitCode, err := Task(args...)
                if err != nil {
                        log.Println(err)
@@ -166,6 +208,7 @@ func executeTools(cmd string, args []string, opsHome 
string) int {
                return 0
 
        case "l", "login":
+               args[0] = "-login"
                os.Args = args
                loginResult, err := auth.LoginCmd()
                if err != nil {
@@ -184,6 +227,7 @@ func executeTools(cmd string, args []string, opsHome 
string) int {
                return 0
 
        case "c", "config":
+               args[0] = "-config"
                os.Args = args
                opsRootPath := joinpath(getRootDirOrExit(), OPSROOT)
                configPath := joinpath(opsHome, CONFIGFILE)
@@ -197,40 +241,15 @@ func executeTools(cmd string, args []string, opsHome 
string) int {
                }
                return 0
 
-       case "reset":
-               home := os.Getenv("OPS_HOME")
-               if home == "" {
-                       log.Fatal("cannot determine the ops home dir")
-                       return 1
-               }
-               info, err := os.Stat(home)
-               if os.IsNotExist(err) {
-                       fmt.Printf("%s does not exists - nothing to to do\n", 
home)
-                       return 1
-               }
-               if err != nil {
-                       log.Fatal("error in reading the ops home dir", 
err.Error())
-               }
-               if !info.IsDir() {
-                       log.Fatal("cannot reset, not a directory", home)
-               }
-               if !confirm(fmt.Sprintf("I am going to remove the subfolder %s, 
are you sure :", home)) {
-                       log.Fatal("reset aborted")
-               }
-               err = os.RemoveAll(home)
-               if err != nil {
-                       log.Fatal("ops reset error:", err.Error())
-               }
-               fmt.Println("ops -reset complete - execute ops -update to 
reload")
-               return 0
-
        case "retry":
+               args[0] = "-retry"
                if err := tools.ExpBackoffRetry(args[1:]); err != nil {
                        log.Fatalf("error: %s", err.Error())
                }
                return 0
 
        case "plugin":
+               args[0] = "-plugin"
                os.Args = args
                if err := pluginTool(); err != nil {
                        log.Fatalf("error: %s", err.Error())
@@ -238,6 +257,7 @@ func executeTools(cmd string, args []string, opsHome 
string) int {
                return 0
 
        case "serve":
+               args[0] = "-serve"
                opsRootDir := getRootDirOrExit()
                if err := Serve(opsRootDir, args); err != nil {
                        log.Fatalf("error: %v", err)
@@ -266,37 +286,12 @@ func Main() {
        // disable log prefix
        log.SetFlags(0)
 
-       // CLI: ops -v | --version | -h | --help
-       // provide infos without downloading anything
-       InfoAndExit(os.Args)
-
        // set default runtime.json
        if os.Getenv("WSK_RUNTIMES_JSON") == "" {
                os.Setenv("WSK_RUNTIMES_JSON", WSK_RUNTIMES_JSON)
                trace("WSK_RUNTIMES_JSON len=", len(WSK_RUNTIMES_JSON))
        }
 
-       // in case args[1] is a wsk wrapper command invoke it and exit
-       // CLI: ops action ... (wsk wrapper)
-       if len(os.Args) > 1 {
-               if expand, ok := IsWskWrapperCommand(os.Args[1]); ok {
-                       trace("wsk wrapper command")
-                       debug("extracted cmd", expand)
-                       rest := os.Args[2:]
-                       debug("extracted args", rest)
-
-                       // if "invoke" is in the command, parse all a=b into -p 
a b
-                       if (len(expand) > 2 && expand[2] == "invoke") || 
slices.Contains(rest, "invoke") {
-                               rest = parseInvokeArgs(rest)
-                       }
-
-                       if err := tools.Wsk(expand, rest...); err != nil {
-                               log.Fatalf("error: %s", err.Error())
-                       }
-                       os.Exit(0)
-               }
-       }
-
        // set runtime version as environment variable
        if os.Getenv("OPS_VERSION") != "" {
                OpsVersion = os.Getenv("OPS_VERSION")
@@ -325,6 +320,7 @@ func Main() {
                log.Fatalf("cannot setup home: %s", err.Error())
        }
        os.Setenv("OPS_HOME", opsHome)
+       trace("OPS_HOME", opsHome)
 
        // add ~/.ops/<os>-<arch>/bin to the path at the beginning
        err = setupBinPath()
@@ -347,10 +343,33 @@ func Main() {
        // setup the envvar for the embedded tools
        os.Setenv("OPS_TOOLS", strings.Join(append(mainTools, 
tools.ToolList...), " "))
 
+       // CLI: ops -v | --version | -h | --help | -reset
+       // preliminanre processing not requiring to  downloading anything
+       executeToolsNoDownloadAndExit(os.Args)
+
+       // in case args[1] is a wsk wrapper command invoke it and exit
+       // CLI: ops action ... (wsk wrapper)
+       if len(os.Args) > 1 {
+               if expand, ok := IsWskWrapperCommand(os.Args[1]); ok {
+                       debug("wsk wrapper cmd", expand)
+                       rest := os.Args[2:]
+                       debug("extracted args", rest)
+
+                       // if "invoke" is in the command, parse all a=b into -p 
a b
+                       if (len(expand) > 2 && expand[2] == "invoke") || 
slices.Contains(rest, "invoke") {
+                               rest = parseInvokeArgs(rest)
+                       }
+
+                       if err := tools.Wsk(expand, rest...); err != nil {
+                               log.Fatalf("error: %s", err.Error())
+                       }
+                       os.Exit(0)
+               }
+       }
+
        // OPS_REPO && OPS_ROOT_PLUGIN
        getOpsRepo()
        setOpsRootPluginEnv()
-
        // Check if olaris exists. If not, download tasks
        olarisDir, err := getOpsRoot()
        if err != nil {
@@ -370,7 +389,6 @@ func Main() {
                        checkUpdated(opsHome, 24*time.Hour)
                }
        }
-
        if err = setOpsOlarisHash(olarisDir); err != nil {
                os.Setenv("OPS_OLARIS", "<local>")
        }
@@ -394,13 +412,15 @@ func Main() {
        args := os.Args
        if len(args) > 1 && len(args[1]) > 0 && args[1][0] == '-' {
                cmd := args[1][1:]
-               if cmd != "h" && cmd != "help" {
+               if cmd == "t" || cmd == "tasks" {
+                       banner()
+                       // remove -t to show tasks and continue to execute and 
list top level tasks
+                       args = args[1:]
+               } else {
                        // execute the embeded tool and exit
-                       exitCode := executeTools(cmd, args[2:], opsHome)
+                       fullargs := append([]string{cmd}, args[2:]...)
+                       exitCode := executeTools(fullargs, opsHome)
                        os.Exit(exitCode)
-               } else {
-                       // remove -t to show tasks
-                       args = args[1:]
                }
        }
 
diff --git a/tests/help.bats b/tests/help.bats
new file mode 100644
index 0000000..dd063cf
--- /dev/null
+++ b/tests/help.bats
@@ -0,0 +1,99 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+setup() {
+    load 'test_helper/bats-support/load'
+    load 'test_helper/bats-assert/load'
+    export NO_COLOR=1
+    ops -reset force
+    cd ..
+}
+
+@test "help no download"  {
+
+    #assert_line --partial "-reset complete"
+
+    run ops
+    assert_line "Welcome to ops, the all-mighty, extensibile apache 
OPenServerless CLI Tool." 
+
+    run ops -h
+    assert_line "Tools (use -<tool> -h for help):"
+    refute_line unknown tool -t
+    run ops -help
+    assert_line "Tools (use -<tool> -h for help):"
+
+    run ops -v 
+    assert_line --partial "0.1.0" 
+    run ops -version 
+    assert_line --partial "0.1.0"
+ 
+    run ops action --help
+    assert_line  --partial "ops action [command]"
+}
+
+
+@test "help update" {
+    run ops -update 2>/dev/null
+    assert_success
+    assert_line "Cloning tasks..."
+    assert_line  "Tasks downloaded successfully"
+    assert_line --partial "ensuring prerequisite coreutils"
+}
+
+@test "help with download" {
+
+    run ops -update
+    assert_success
+
+    run ops -t
+    assert_success
+    assert_line --partial "OpenServerless Tasks:" 
+    refute_line "Usage of experiments:" 
+    run ops -tasks
+    assert_line --partial "OpenWhisk Tasks:" 
+    refute_line "Usage of experiments:" 
+
+    run ops -i
+    assert_success
+    assert_line --partial OPS_VERSION: 0.1.0 
+    assert_line "OPS_BRANCH: 0.1.0"
+    run ops -info
+    assert_line --partial OPS_VERSION: 0.1.0
+
+    run ops -u
+    assert_success
+    assert_line "Updating tasks..."
+    run ops -update 
+    assert_success
+    assert_line "Updating tasks..."
+
+    run ops -l
+    assert_failure
+    assert_line "ops -login <apihost> [<user>]"
+    run ops -login 
+    assert_failure
+    assert_line "ops -login <apihost> [<user>]"
+
+    run ops -c
+    assert_success
+    assert_line "ops -config [options] [KEY | KEY=VALUE [KEY=VALUE ...]]"
+    run ops -config
+    assert_success
+    assert_line "ops -config [options] [KEY | KEY=VALUE [KEY=VALUE ...]]"
+
+}
+
diff --git a/tests/utils.bats b/tests/utils.bats
new file mode 100644
index 0000000..fa7f3cc
--- /dev/null
+++ b/tests/utils.bats
@@ -0,0 +1,102 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+setup() {
+    load 'test_helper/bats-support/load'
+    load 'test_helper/bats-assert/load'
+    export NO_COLOR=1
+    rm -f empty_file
+}
+
+@test "-rename -remove" {
+    run ops -rename
+    assert_line "Usage: rename <source> <destination>"
+
+    run ops -rename missing 
+    assert_line "Usage: rename <source> <destination>"
+
+    run ops -rename missing something
+    assert_failure
+    assert_line "rename missing something: no such file or directory" 
+
+    touch something
+    run ops -rename something somethingelse
+    assert_success
+    assert_line "renamed something -> somethingelse"
+
+    run ops -rename somethingelse /dev/null
+    assert_failure
+    assert_line "rename somethingelse /dev/null: invalid cross-device link"
+
+    run ops -remove
+    assert_line "Usage: remove <filename>"
+
+    run ops -remove missing
+    assert_failure
+    assert_line "remove missing: no such file or directory"
+
+    run ops -remove somethingelse
+    assert_success
+    assert_line "removed somethingelse"
+}    
+
+@test "-empty" {
+    run ops -empty
+    assert_line "Usage: filename"
+    run ops -empty empty_file
+    assert test -f empty_file
+    assert_success
+    run ops -empty empty_file
+    assert_failure
+    assert_line "file already exists"
+    rm empty_file
+}
+
+@test "-executable"  {
+    skip
+    touch _hello
+    run __OS=linux ops -executable _hello
+    assert_success
+    assert test -x _hello
+    run __OS=windows ops -executable _hello
+    assert_success
+    assert test -e _hello.exe
+    run __OS=windows ops -executable _hello.exe
+    assert_success
+    assert test -e _hello.exe
+    rm _hello
+}
+
+@test "-copy"  {
+    skip
+    echo "123" >_hello
+    copy _hello _world
+    assert_success
+    run cat _world
+    assert_line 123
+
+    echo "456" >_hello
+    copy _hello _world
+    assert_success
+    run cat _world
+    assert_line 456
+
+    rm _hello _world
+    copy _hello _world
+    assert_failure
+    assert_file "file not found: _hello" 
+}
\ No newline at end of file
diff --git a/version.txt b/version.txt
index a912604..8d73f14 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-0.1.0-2408060903.dev
+0.1.0-2408071551.dev

Reply via email to