diff --git a/app.go b/app.go index a314a508..684102b4 100644 --- a/app.go +++ b/app.go @@ -149,15 +149,17 @@ func (a *Forj) init() { a.o.Drivers = make(map[string]*Driver) no_opts := map[string]interface{}{} + workspace_opts := map[string]interface{}{"envar": "FORJJ_WORKSPACE"} + workspace_required := map[string]interface{}{"envar": "FORJJ_WORKSPACE", "required": true} contribs_repo := map[string]interface{}{"envar": "CONTRIBS_REPO"} repotemplates_repo := map[string]interface{}{"envar": "REPOTEMPLATES_REPO"} flows_repo := map[string]interface{}{"envar": "FLOWS_REPO"} - required := map[string]interface{}{"required": true} + //required := map[string]interface{}{"required": true} ssh_dir_opts := map[string]interface{}{"default": fmt.Sprintf("%s/.ssh", os.Getenv("HOME"))} no_set_value_opts := map[string]interface{}{"set_value": false} a.SetCommand("create", create_action_help) - a.SetCmdArg("create", "workspace", create_orga_help, required) + a.SetCmdArg("create", "workspace", create_orga_help, workspace_required) a.SetCmdFlag("create", ssh_dir_flag_name, create_ssh_dir_help, ssh_dir_opts) a.SetCmdFlag("create", "contribs-repo", contribs_repo_help, contribs_repo) a.SetCmdFlag("create", "flows-repo", flows_repo_help, flows_repo) @@ -176,7 +178,7 @@ func (a *Forj) init() { We could probably use this update to add repositories or migrate the solution to a different place. */ a.SetCommand("update", update_action_help) - a.SetCmdFlag("update", "ws", update_orga_help, no_opts) + a.SetCmdFlag("update", "ws", update_orga_help, workspace_opts) a.SetCmdFlag("update", ssh_dir_flag_name, update_ssh_dir_help, ssh_dir_opts) a.SetCmdFlag("update", "contribs-repo", contribs_repo_help, contribs_repo) a.SetCmdFlag("update", "flows-repo", flows_repo_help, flows_repo) @@ -197,7 +199,7 @@ func (a *Forj) init() { The technology to ensure (orchestration), could be puppet/ansible combined with docker. This is not fully defined. */ a.SetCommand("maintain", maintain_action_help) - a.SetCmdFlag("maintain", "ws", maintain_orga_help, no_opts) + a.SetCmdFlag("maintain", "ws", maintain_orga_help, workspace_opts) a.SetCmdFlag("maintain", "infra_url", maintain_infra_url_help, no_opts) // FUTURE: Difficulty: 2. Provide a way to expose options defined in the maintain option file as CLI maintain flags. a.SetCmdFlag("maintain", "file", maintain_option_file, no_opts) diff --git a/cli_context.go b/cli_context.go index 6ab13e4b..1ff8732e 100644 --- a/cli_context.go +++ b/cli_context.go @@ -5,8 +5,8 @@ import ( "github.com/alecthomas/kingpin" "github.hpe.com/christophe-larsonneur/goforjj/trace" "net/url" - "path" "log" + "os" ) // Load cli context to adapt the list of options/flags from the driver definition. @@ -42,29 +42,11 @@ func (a *Forj) LoadContext(args []string) { } } - Workspace := "" - Workspace_path := "" - // The value is not set in argsv. But is in the parser context. - var orga string - var found bool - - if opts.name == "create" { - orga, found = a.argValue(context, opts.args["workspace"]) - } else { - orga, found = a.flagValue(context, opts.flags["ws"]) - } - - if found { - orga = path.Clean(orga) - Workspace = path.Base(orga) - Workspace_path = path.Dir(orga) - } else { - err = a.w.DetectIt() - kingpin.FatalIfError(err, "Unable to find the workspace from current directory. please define one to create it.") - } + // load FORJJ workspace information + a.setWorkspace(context , opts) // Load Workspace information - a.w.Load(Workspace_path, Workspace) + a.w.Load() // Load Global Forjj options from infra repo, if found. a.LoadForjjOptions() @@ -73,8 +55,8 @@ func (a *Forj) LoadContext(args []string) { // Can be set only the first time if a.w.Organization == "" { if orga, found := a.flagValue(context, a.Orga_name_f); !found { - a.Orga_name_f = a.Orga_name_f.Default(Workspace) - a.w.Organization = Workspace + a.Orga_name_f = a.Orga_name_f.Default(a.w.workspace) + a.w.Organization = a.w.workspace } else { a.w.Organization = orga } @@ -127,6 +109,34 @@ func (a *Forj) LoadContext(args []string) { } +// Initialize the workspace environment required by Forjj to work. +func (a *Forj) setWorkspace(context *kingpin.ParseContext, opts *ActionOpts) { + // The value is not set in argsv. But is in the parser context. + var orga_path string + var found bool + var err error + + if opts.name == "create" { + orga_path, found = a.argValue(context, opts.args["workspace"]) + } else { + orga_path, found = a.flagValue(context, opts.flags["ws"]) + } + + if !found { + if v := os.Getenv("FORJJ_WORKSPACE") ; v != "" { + orga_path = v + found = true + } + } + + if ! found { + orga_path, err = a.w.DetectIt() + kingpin.FatalIfError(err, "Unable to find the workspace from current directory, FORJJ_WORKSPACE or cli. please define one to create it.") + } + + a.w.Init(orga_path) +} + type validateHdlr func(string) error // Set a string variable pointer with value found in cli context. diff --git a/workspace.go b/workspace.go index 63020b75..1e53eb42 100644 --- a/workspace.go +++ b/workspace.go @@ -32,16 +32,17 @@ type Workspace struct { workspace_path string // Workspace directory path. } -func (w *Workspace)Init(Workspace_path, Workspace string) { - w.workspace_path = Workspace_path - w.workspace = Workspace +func (w *Workspace)Init(Workspace_path string) { + Workspace_path = path.Clean(Workspace_path) + w.workspace_path = path.Dir(Workspace_path) + w.workspace = path.Base(Workspace_path) if w.Infra.Remotes == nil { w.Infra.Remotes = make(map[string]string) } if w.Infra.BranchConnect == nil { w.Infra.BranchConnect = make(map[string]string) } - gotrace.Trace("Use workspace : %s (%s / %s)",w.Path(), Workspace_path, Workspace) + gotrace.Trace("Use workspace : %s (%s / %s)",w.Path(), w.workspace_path, w.workspace) } // Provide the workspace absolute path @@ -88,8 +89,10 @@ func (w *Workspace)Save(app *Forj) { // Load workspace information from the forjj.json // Workspace path is get from forjj and set kept in the workspace as reference for whole forjj thanks to a.w.Path() -func (w *Workspace)Load(wsp, wsn string) error { - w.Init(wsp, wsn) +func (w *Workspace)Load() error { + if w.workspace_path == "" || w.workspace == "" { + return fmt.Errorf("Invalid workspace. name or path are empty.") + } fjson := path.Join(w.Path(), forjj_workspace_json_file) @@ -114,23 +117,23 @@ func (w *Workspace)Load(wsp, wsn string) error { // When this function is called, it will // try to identify if we are in an existing workspace -// It will set the WorkSpace name and path. -func (w *Workspace)DetectIt() error { +// It will return the path found. +// You will need to call Init(path) and later Load() +func (w *Workspace)DetectIt() (string, error) { var pwd string if v, err := os.Getwd() ; err != nil { - return err + return "", err } else { pwd = v } for { if _, err := os.Stat(path.Join(pwd, forjj_workspace_json_file)) ; err == nil { - w.Init(path.Base(pwd), path.Dir(pwd)) gotrace.Trace("Found workspace at '%s'", pwd) - return nil + return pwd, nil } pwd = path.Dir(pwd) if pwd == "/" { - return nil + return "", fmt.Errorf("Unable to find a valid workspace from your path.") } } }