Skip to content

As an application developer I want a consistent CLI command structure so that I can easily reason about command usage. #216

@JadeRedworth

Description

@JadeRedworth

This issue changes the Fn CLI to use a [verb][noun] structure, resulting in a more intuitive, human-readable approach that would bring a consistent feel to the CLI. It is a common pattern among other CLI's that developers may be using alongside Fn. (A more detailed analysis of the Fn CLI and other CLI's can be found here: CLI Analysis)

The Verb Noun matrix shows how many of the nouns are unrelated to a verb. Therefore these should be their own high-level commands along with all other verbs:

verbs nouns
build app[s]
bump call[s]
call config
create context
delete lambda
deploy logs
get route[s]
help server
import
init
list
pull?
run
set
start
stop
test
update
use

There is confusion about the use of apps/routes vs app/route (singular use of app/route/call/image). Looking back at Singular vs Plural the use of both plural and singular nouns are both valid:

~ $ fn create app/apps <app>
~ $ fn delete route/routes <app> </route>

When using 'fn get' and 'fn list', get is used to return a single object, specificly a function call, and list is used to return multiple apps/routes/calls etc. The command 'inspect' allows you to retrieve on or all apps/routes properties. However, this essentially performs the same as 'get' and will, therefore, be deprecated.

~ $ fn list apps
java-app
string-reverse-app

~ $ fn list routes java-app
/hello-java-function  <dockerhub_username>/hello2:0.0.2	   localhost:8080/r/java-app/hello-java-function
/test-route           <dockerhub_username>/hello2:0.0.2	   localhost:8080/r/java-app/test-route

~ $ fn list calls <app>
ID: 01C9RQPM7G47WG200000000000
App: java-app
Route: /hello-java-function
Created At: 2018-03-29T11:18:49.840Z
Started At: 2018-03-29T11:18:50.366Z
Completed At: 2018-03-29T11:18:50.367Z
Status: success

ID: 01C9RG0N7147WGA00000000000
App: java-app
Route: /test-route  
Created At: 2018-03-29T09:04:29.921Z
Started At: 2018-03-29T09:04:30.432Z
Completed At: 2018-03-29T09:04:30.441Z
Status: success

All subcommands of 'fn images' exist as top-level commands, this makes the use of images redundant and will be removed:

~ $ fn images build/bump/call/deploy/push/run/test ...
~ $ fn build/bump/call/deploy/push/run/test ...

Logical Grouping of Verbs

Its common practice for other CLI's to logically group commands together within the help text, this makes it easier for developers to scan through a more structure help text.

Management Development Server Other Removed
create build start help apps
delete bump stop version routes
get call stop inspect
list deploy calls
set import logs
update init images
run push
test

Help Text:

The result of fn help would be as follows:

Fn command line tool

ENVIRONMENT VARIABLES:
   FN_API_URL - Fn server address
   FN_REGISTRY - Docker registry to push images to, use username only to push to Docker Hub - [[registry.hub.docker.com/]USERNAME]

SERVER COMMANDS:
     start         start a functions server
     stop          stop a functions server
     pull | update | upgrade ?       pulls latest functions server

MANAGEMENT COMMANDS:
     create, c     create a new object
     delete, d     delete an object
     get, g        get information or properties for an object
     list, l       list all instances of an object
     set, s        set features or properties for an object
     unset         unset features or properties for an object
     update, u     update an object
     
DEVELOPMENT COMMANDS:
     build         build function version
     bump          bump function version
     call          call a remote function
     deploy        deploys a function to the functions server. (bumps, build, pushes and updates route)
     import        import an existing external function
     init          create a local func.yaml file
     push          push function to Docker Hub
     run           run a function locally
     test          run functions test if present

OTHER COMMANDS:
     help          shows a list of commands or help for one command
     version       displays server and cli versions

GLOBAL OPTIONS:
   --verbose, -v    use --verbose to enable verbose mode for debugging
   --help, -h       show help
   --version        print only the cli version

LEARN MORE:
   https://github.com/fnproject/fn

Help Text for Commands/Verbs

create, c

COMMANDS:
     app      create a new app
     context  create a new context
     route    create a new route

EXAMPLE:
     fn create app <app>
     fn create context <context>
     fn create route <app> </path> 

delete, d

COMMANDS:
     app       delete an app
     context  delete a context
     route     delete a route

EXAMPLE:
     fn delete app <app>
     fn delete route <app> </path> 

update, u

COMMANDS:
     app      create an app
     route    update a route

EXAMPLE:
     fn update app <app>
     fn update context <context> <args>
     fn update route <app> </path> 

get, g

COMMANDS:
     app       get a specified app
     config    get configuration for apps and routes
     context    get context
     call      get a specified call
     logs      get logs for a call
     route     get a specified route

EXAMPLE:
     fn get app <app>
     fn get route <app> </path> 
     fn get config app <app> <key>
     fn get call <app> [<call-id> | last]
     fn get logs <app> [<call-id> | last]

set, s

COMMANDS:
     config   set configuration for apps and routes 

EXAMPLE:
     fn set config app <app> <key> <value>
     fn set config route <app> </path> <key> <value>

unset

COMMANDS:
     config   unset configuration for apps and routes 

EXAMPLE:
     fn unset config app <app> <key> 
     fn unset config route <app> </path> <key> 

list, l

COMMANDS:
     apps     display all apps 
     routes   display all routes for specific
     calls    display all calls 
     config   display all configs for apps and routes
     
EXAMPLE:
     fn list apps 
     fn list routes <app>    (specific to an app)
     fn list calls <app>     (specific to an app)
     fn list config <app>
     fn list config <app> </path>

run

NAME:
   fn run - run a function locally

USAGE:
   fn run [command options] [arguments...]

OPTIONS:
   --env value, -e value  select environment variables to be sent to function
   --link value           select container links for the function
   --method value         http method for function
   --format default       format to use. default and `http` (hot) formats currently supported.
   --runs runs            for hot functions only, will call the function runs times in a row. (default: 0)
   --memory value         RAM to allocate for function, Units: MB (default: 0)
   --no-cache             Don't use Docker cache for the build

test

NAME:
   fn test - run functions test if present

USAGE:
   fn test [command options] [arguments...]

OPTIONS:
   --remote value  run tests against a remote fn server

call

EXAMPLE:
     fn call <app> </path> 

init

NAME:
   fn init - create a local func.yaml file

USAGE:
   fn init [command options] [FUNCTION_NAME]

DESCRIPTION:
   Creates a func.yaml file in the current directory.

OPTIONS:
   --name value              name of the function. Defaults to directory name in lowercase.
   --force                   overwrite existing func.yaml
   --runtime value           choose an existing runtime - dotnet, go, java8, java9, java, lambda-nodejs4.3, lambda-node-4, node, php, python, python3.6, ruby, rust, kotlin
   --entrypoint value        entrypoint is the command to run to start this function - equivalent to Dockerfile ENTRYPOINT.
   --cmd value               command to run to start this function - equivalent to Dockerfile CMD.
   --version value           set initial function version (default: "0.0.1")
   --image value, -i value   image name
   --memory value, -m value  memory in MiB (default: 0)
   --type value, -t value    route type - sync or async
   --config value, -c value  route configuration
   --headers value           route response headers
   --format value, -f value  hot container IO format - default or http
   --timeout value           route timeout (eg. 30) (default: 0)
   --idle-timeout value      route idle timeout (eg. 30) (default: 0)

deploy

NAME:
   fn deploy - deploys a function to the functions server. (bumps, build, pushes and updates route)

USAGE:
   fn deploy [command options] [arguments...]

OPTIONS:
   --app value                     app name to deploy to
   --verbose, -v                   verbose mode
   --no-cache                      Don't use Docker cache for the build
   --local, --skip-push            does not push Docker built images onto Docker Hub - useful for local development.
   --registry --registry username  Sets the Docker owner for images and optionally the registry. This will be prefixed to your function name for pushing to Docker registries. eg: --registry username will set your Docker Hub owner. `--registry registry.hub.docker.com/username` will set the registry and owner.
   --all app.yaml                  if in root directory containing app.yaml, this will deploy all functions

bump

NAME:
   fn bump - bump function version

USAGE:
   fn bump [command options] [arguments...]

OPTIONS:
   --major        bumps major version
   --minor        bumps minor version
   --verbose, -v  verbose mode

build

NAME:
   fn build - build function version

USAGE:
   fn build [command options] [arguments...]

OPTIONS:
   -v          verbose mode
   --no-cache  Don't use docker cache

push

NAME:
   fn push - push function to Docker Hub

USAGE:
   fn push [command options] [arguments...]

OPTIONS:
   -v                              verbose mode
   --registry --registry username  Sets the Docker owner for images and optionally the registry. This will be prefixed to your function name for pushing to Docker registries. eg: --registry username will set your Docker Hub owner. `--registry registry.hub.docker.com/username` will set the registry and owner.

import

NAME:
   fn import -  import an existing external function

USAGE:
   fn import [command] [command options] <arn> <region> <image/name>

COMMANDS:
    lamba 

OPTIONS:
   --payload value  Payload to pass to the function. This is usually a JSON object. (default: "{}")
   --version value  Version of the function to import. (default: "$LATEST")
   --download-only  Only download the function into a directory. Will not create a Docker image.
   --config value   function configuration

start

NAME:
   fn start - start a functions server container

USAGE:
   fn start [command] [command options] [arguments...]

OBJECTS:
   server

OPTIONS:
   --detach, -d          Run container in background.
   --env-file <value>    Path to Fn server configuration file.
   --log-level <value>   --log-level debug to enable debugging
   --port, -p <value>    Specify the port on which to expose the running server image.

stop

NAME:
   fn stop - stop a functions server

USAGE:
   fn stop [command]

OBJECTS:
   server

pull / upgrade

NAME:
   fn [pull | upgrade] - pulls latest functions server

USAGE:
   fn [pull | upgrade] [command]   

COMMANDS:
   server

version

NAME:
   fn version - displays cli and server versions

USAGE:
   fn version [arguments...]

help, h

EXAMPLE:
     fn help
     fn help create
     fn help apps

Help Text for Objects/Nouns

app[s]

~ fn help [app | apps]

USAGE: 
     fn command [app | apps] [command options] <app>

COMMANDS:
     create, c   create a new app
     update, u   update an `app`
     list, l     list all apps
     delete, d   delete an app

call[s]

~ fn help [call | calls]

USAGE:
     fn command [call | call] [command options] [argument...]

COMMANDS:
     get, g   get function call info per app
     list, l  list all calls for the specific app. Route is optional

route[s]

~ fn help [route | routes]

USAGE:
     fn command [route | routes] [command options] <app> </path>

COMMANDS:
     call        call a route
     list, l     list routes for `app`
     create, c   create a route in an `app`
     update, u   update a route in an `app`
     config      operate a route configuration set
     delete, d   delete a route from `app`

config

~ fn help config

USAGE:
      fn command config [app | route]  [command options] [argument...]

COMMANDS:
     set, s    store a configuration key for this route
     get, g    get configuration key for this route
     list, l   list configuration key/value pairs for this route
     unset, u  remove a configuration key for this route

context[s]

~ fn help context

USAGE:
      fn <command> context <context> [command options] [argument...]

COMMANDS:
     create, c  create a new context
     delete, d  delete context <context>
     get, g     display the details of a context
     list, l    list all contexts
     update, u  update a key/value pair in a context
     use        change the currently selected context

logs

~ fn help logs

USAGE:
     fn command logs [command options] [argument...]

COMMANDS:
     get, g  get logs for a call. Must provide call_id or last to retrieve the most recent calls logs.

server

~ fn help server

USAGE:
     fn command server [command options] [argument...]

COMMAND:
     start   start a function server
     stop    stop a function server
     pull | upgrade ?   pulls latest functions server 

lambda

~ fn help lambda

USAGE:
   fn command lambda [command options] [arguments...]

COMMANDS:
     import  import an existing function to an image, where the function code is downloaded to a directory in the current working directory that has the same name as the function.

Examples:

Developer user experience (initial):

~ $ fn init --runtime java <app>
~ $ fn run
~ $ fn create route <app> </path> --image <image>
~ $ fn list routes <app> 
~ $ fn deploy --app <app>
~ $ fn call <app> </path>
~ $ fn list calls <app>
~ $ fn get calls <app> [<call-id> | last]

Trouble Shooting:

~ $ fn get logs <app> [<call-id> | last]
~ $ fn list calls <app>
~ $ fn get calls <app> [<call-id> | last]

Configuration Management Process

~ $ fn set app config <app> <key> <value>
~ $ fn set route config <app> </path> <key> <value>

~ $ fn get app config <app> </path> <key>
~ $ fn get route config <app> </path> <key>

~ $ fn unset app config <app> <key>
~ $ fn unset route config <app> </path> <key>

~ $ fn list apps config <app>        
~ $ fn list routes config <app> </path>

Current Bugs

The global options, such as verbose, help and version should be non-positional. In order to enable verbose mode for debugging users must put --verbose/-v in a specific position:

~ $ fn --verbose deploy --app <app> --local ...

However, if --verbose is positioned anywhere else, it is not picked up:

~ $ fn deploy --verbose ...
~ $ fn deploy --app <app> --verbose ...

Users should be able to position the global options at any point after 'fn' within the command.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions