New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: decouple function name from function domain #127
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,6 @@ func init() { | |
createCmd.Flags().BoolP("confirm", "c", false, "Prompt to confirm all configuration options - $FAAS_CONFIRM") | ||
createCmd.Flags().StringP("image", "i", "", "Optional full image name, in form [registry]/[namespace]/[name]:[tag] for example quay.io/myrepo/project.name:latest (overrides --repository) - $FAAS_IMAGE") | ||
createCmd.Flags().StringP("namespace", "n", "", "Override namespace into which the Function is deployed (on supported platforms). Default is to use currently active underlying platform setting - $FAAS_NAMESPACE") | ||
createCmd.Flags().StringP("path", "p", cwd(), "Path to the new project directory - $FAAS_PATH") | ||
createCmd.Flags().StringP("repository", "r", "", "Repository for built images, ex 'docker.io/myuser' or just 'myuser'. Optional if --image provided. - $FAAS_REPOSITORY") | ||
createCmd.Flags().StringP("runtime", "l", faas.DefaultRuntime, "Function runtime language/framework. - $FAAS_RUNTIME") | ||
createCmd.Flags().StringP("templates", "", filepath.Join(configPath(), "templates"), "Extensible templates path. - $FAAS_TEMPLATES") | ||
|
@@ -38,18 +37,18 @@ func init() { | |
} | ||
|
||
var createCmd = &cobra.Command{ | ||
Use: "create <name>", | ||
Use: "create <path>", | ||
Short: "Create a new Function, including initialization of local files and deployment.", | ||
SuggestFor: []string{"cerate", "new"}, | ||
PreRunE: bindEnv("image", "namespace", "path", "repository", "runtime", "templates", "trigger", "confirm"), | ||
PreRunE: bindEnv("image", "namespace", "repository", "runtime", "templates", "trigger", "confirm"), | ||
RunE: runCreate, | ||
} | ||
|
||
func runCreate(cmd *cobra.Command, args []string) (err error) { | ||
config := newCreateConfig(args).Prompt() | ||
|
||
function := faas.Function{ | ||
Name: config.Name, | ||
Name: config.initConfig.Name, | ||
Root: config.initConfig.Path, | ||
Runtime: config.initConfig.Runtime, | ||
Trigger: config.Trigger, | ||
|
@@ -106,23 +105,24 @@ func newCreateConfig(args []string) createConfig { | |
} | ||
} | ||
|
||
// Prompt the user with value of config members, allowing for interaractive changes. | ||
// Prompt the user with value of config members, allowing for interactive changes. | ||
// Skipped if not in an interactive terminal (non-TTY), or if --confirm (agree to | ||
// all prompts) was not explicitly set. | ||
func (c createConfig) Prompt() createConfig { | ||
name := deriveName(c.Name, c.initConfig.Path) | ||
zroubalik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if !interactiveTerminal() || !c.initConfig.Confirm { | ||
// Just print the basics if not confirming | ||
fmt.Printf("Project path: %v\n", c.initConfig.Path) | ||
fmt.Printf("Project name: %v\n", name) | ||
fmt.Printf("Function name: %v\n", c.initConfig.Name) | ||
fmt.Printf("Runtime: %v\n", c.Runtime) | ||
fmt.Printf("Trigger: %v\n", c.Trigger) | ||
return c | ||
} | ||
|
||
derivedName, derivedPath := deriveNameAndAbsolutePathFromPath(prompt.ForString("Project path", c.initConfig.Path, prompt.WithRequired(true))) | ||
lance marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return createConfig{ | ||
initConfig: initConfig{ | ||
Path: prompt.ForString("Project path", c.initConfig.Path), | ||
Name: prompt.ForString("Project name", name, prompt.WithRequired(true)), | ||
Name: derivedName, | ||
Path: derivedPath, | ||
Comment on lines
-124
to
+125
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It appears to me that perhaps this omits the prompting of name and path entirely, right? I was actuall fond of the original idea: to prompt if the parameter were not provided as a flag. If that's not the plan anymore, no problem! But if we wanted to prompt the user when the parameters had not been provided, would we not instead leave things roughly as they were, and insteaed add here a conditional that only prompts if the flag does not exist (as provided by the CLI API)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@lkingland I may be misreading your comment, so disregard if so (or correct me). The prompt occurs on line 121. derivedName, derivedPath := deriveNameAndAbsolutePathFromPath(prompt.ForString("Project path", c.initConfig.Path, prompt.WithRequired(true))) |
||
Runtime: prompt.ForString("Runtime", c.Runtime), | ||
Trigger: prompt.ForString("Trigger", c.Trigger), | ||
// Templates intentionally omitted from prompt for being an edge case. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ import ( | |
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/mitchellh/go-homedir" | ||
"github.com/ory/viper" | ||
|
@@ -165,21 +166,42 @@ func functionWithOverrides(root, namespace, image string) (f faas.Function, err | |
|
||
// deriveName returns the explicit value (if provided) or attempts to derive | ||
// from the given path. Path is defaulted to current working directory, where | ||
// a function configuration, if it exists and contains a name, is used. Lastly | ||
// derivation using the path us used. | ||
// a Function configuration, if it exists and contains a name, is used. | ||
func deriveName(explicitName string, path string) string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if this function could be better named as it no longer really derives the name, but instead just pulls it from the configuration file or returns the passed value. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any suggestion? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I've been sitting here for 5 minutes trying to come up with a good name. I see why you asked. The best I've come up with is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hehe, yeah 😄 I don't like the name either, so I am happy to change it to anything else, that makes sense for everyone |
||
// If the name was explicitly provided, use it. | ||
if explicitName != "" { | ||
return explicitName | ||
} | ||
|
||
// If the directory at path contains an initialized Function, use the name therein | ||
f, err := faas.NewFunction(path) | ||
if err == nil && f.Name != "" { | ||
return f.Name | ||
} | ||
maxRecursion := faas.DefaultMaxRecursion | ||
derivedName, _ := faas.DerivedName(path, maxRecursion) | ||
return derivedName | ||
|
||
return "" | ||
} | ||
|
||
// deriveNameAndAbsolutePathFromPath returns resolved Function name and absolute path | ||
// to the Function project root. The input parameter path could be one of: | ||
// 'relative/path/to/foo', '/absolute/path/to/foo', 'foo' or '' | ||
func deriveNameAndAbsolutePathFromPath(path string) (string, string) { | ||
var absPath string | ||
|
||
// If path is not specifed, we would like to use current working dir | ||
if path == "" { | ||
path = cwd() | ||
} | ||
|
||
// Expand the passed Function name to its absolute path | ||
absPath, err := filepath.Abs(path) | ||
if err != nil { | ||
return "", "" | ||
} | ||
|
||
// Get the name of the Function, which equals to name of the current directory | ||
pathParts := strings.Split(strings.TrimRight(path, string(os.PathSeparator)), string(os.PathSeparator)) | ||
return pathParts[len(pathParts)-1], absPath | ||
} | ||
|
||
// deriveImage returns the same image name which will be used if no explicit | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the idea of creating the directory in which a function will be deployed because it would ensure the function is in a clean fresh directory. However, one small question: what do we do when a user wants to start over, without also removing their git history (
.git
) or other ancillary config files (.direnv
)? This is why the code exists to check if a directory is effectively empty: contains no visible files, and no .faas.yaml, before allowing a re-run ofcreate
orinit
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I am not mistaken, this command is not doing anything if the directory already exists (and contains some hidden files).
In that case user would do
mkdir my_dir_with_hidden_files && faas init my_dir_with_hidden_files