# Module setup # * [Description](#description) * [Function Index](#index) * [Function Details](#functions) Setup utility for erlang applications. ## Description ## This API contains: * Support functions for system install ([`find_hooks/0`](#find_hooks-0), [`run_hooks/0`](#run_hooks-0), [`lib_dirs/0`](#lib_dirs-0)). * Functions for managing and inspecting the system environment ([`home/0`](#home-0), [`log_dir/0`](#log_dir-0), [`data_dir/0`](#data_dir-0), [`verify_directories/0`](#verify_directories-0), [`verify_dir/0`](#verify_dir-0)). * Support functions for application environments ([`get_env/2`](#get_env-2), [`get_all_env/1`](#get_all_env-1), [`find_env_vars/1`](#find_env_vars-1), [`expand_value/2`](#expand_value-2)). * Functions for controlling dynamic load/upgrade of applications ([`find_app/1`](#find_app-1), [`pick_vsn/3`](#pick_vsn-3), [`reload_app/1`](#reload_app-1), [`patch_app/1`](#patch_app-1)). ### Variable expansion ### Setup supports variable substitution in application environments. It provides some global variables, `"$HOME", "$DATA_DIR", "$LOG_DIR"`, corresponding to the API functions [`home/0`](#home-0), [`data_dir/0`](#data_dir-0) and [`log_dir`](log_dir.md), as well as some application-specific variables, `"$APP", "$PRIV_DIR", "$LIB_DIR". The normal way to use these variables is by embedding them in file names, e.g. `{my_logs, "$LOG_DIR/$APP"}`, but a variable can also be referenced as: * `{'$value',Var}` - The variable's value is used as-is (which means that `{'$value', "$APP"}` expands to an atom corresponding to the current app name.) * `{'$string', Var}` - The value is represented as a string (list). If the value isn't a "string type", `io_lib:format("~w",[Value])` is used. * `{'$binary', Var}` - Like `'$string`', but using binary representation. Custom variables can be defined by using either: * *global scope* - The `setup` environment variable `vars`, containing a list of `{VarName, Definition}` tuples * *application-local scope* - Defining an application-local environment variable `'$setup_vars`', on the same format as above. The `VarName` shall be a string, e.g. `"MYVAR"` (no `$` prefix). `Definition` can be one of: * `{value, Val}` - the value of the variable is exactly `Val` * `{expand, Val}` - `Val` is expanded in its turn * `{apply, M, F, A}` - Use the return value of `apply(M, F, A)`. When using a variable expansion, either insert the variable reference in a string (or binary), or use one of the following formats: * `'{'$value', Var}`' - Use value as-is * `'{'$string', Var}`' - Use the string representation of the value * `'{'$binary', Var}`' - Use the binary representation of the value. Example: ```erlang 2> application:set_env(setup, vars, [{"PLUS", {apply,erlang,'+',[1,2]}}, 2> {"FOO", {value, {foo,1}}}]). ok 3> application:set_env(stdlib, '$setup_vars', 3> [{"MINUS", {apply,erlang,'-',[4,3]}}, 3> {"BAR", {value, "bar"}}]). ok 4> application:set_env(setup, v1, "/$BAR/$PLUS/$MINUS/$FOO"). ok 5> setup:get_env(setup,v1). {ok,"/$BAR/3/$MINUS/{foo,1}"} 6> application:set_env(stdlib, v1, "/$BAR/$PLUS/$MINUS/$FOO"). ok 7> setup:get_env(stdlib,v1). {ok,"/bar/3/1/{foo,1}"} ``` In the above example, the first expansion (command no. 5), leaves `$BAR` and `$MINUS` unexpanded, since they are defined in the `stdlib` application, and thus not known to `setup`. In command no. 6, however, they _are_ in context, and are expanded. The variables `$PLUS` and `$FOO` have global context and are expanded in both cases. It is also possible to refer to environment variables in the same application. These are referenced as `"$env(VarName)"`. The corresponding values are expanded in turn - take care not to create expansion loops! The same rules for expansion as above apply. Example: ```erlang 2> application:set_env(setup,foo,"foo"). ok 3> application:set_env(setup,foo_dir,"$HOME/$env(foo)"). ok 4> setup:get_env(setup,foo_dir). {ok,"/Users/uwiger/git/setup/foo"} ``` ### Customizing setup ### The following environment variables can be used to customize `setup`: * `{home, Dir}` - The topmost directory of the running system. This should be a writeable area. * `{data_dir, Dir}` - A directory where applications are allowed to create their own subdirectories and save data. Default is `Home/data.Node`. * `{log_dir, Dir}` - A directory for logging. Default is `Home/log.Node`. * `{stop_when_done, true|false}` - When invoking `setup` for an install, `setup` normally remains running, allowing for other operations to be * `{stop_delay, Millisecs}` - If `stop_when_done` is true, and the node is going to shut down, setup will first wait for a specified number of milliseconds (default: 5000). This can be useful in order to allow asynchronous operations to complete before shutting down. performed from the shell or otherwise. If `{stop_when_done, true}`, the node is shut down once `setup` is finished. * `{abort_on_error, true|false}` - When running install or upgrade hooks, `setup` will normally keep going even if some hooks fail. A more strict semantics can be had by setting `{abort_on_error, true}`, in which case `setup` will raise an exception if an error occurs. * `{mode, atom()}` - Specifies the context for running 'setup'. Default is `normal`. The `setup` mode has special significance, since it's the default mode for setup hooks, if no other mode is specified and the node has been started with the setup-generated `install.boot` script. In theory, one may specify any atom value, but it's probably wise to stick to the values 'normal', 'setup' and 'upgrade' as global contexts, and instead trigger other mode hooks by explicitly calling [`run_hooks/1`](#run_hooks-1). * `{verify_directories, boolean()}` - At startup, setup will normally ensure that the directories used by setup actually exist. This behavior can be disabled through the environment variable `{verify_directories, false}`. This can be desirable if setup is used mainly e.g. for environment variable expansion, but not for disk storage. * `{run_timeout, Millisecs}` - Set a time limit for how long it may take for setup to process the setup hooks. Default is `infinity`. If the timeout is exceeded, the application start sequence will be aborted, which will cause a (rather inelegant) boot sequence failure. ## Function Index ##
applications/0 | Find all applications - either from the boot script or all loaded apps. |
data_dir/0 | Returns the configured data dir, or a best guess (home()/data.Node ). |
expand_value/2 | Expand Value using global variables and the variables of App |
expand_value/3 | Expand Value using global variables and the variables of App |
find_app/1 | Equivalent to find_app(A, lib_dirs()). |
find_app/2 | Locates application A along LibDirs (see lib_dirs/0 and
lib_dirs/1 ) or under the OTP root, returning all found candidates. |
find_env_vars/1 | Searches all loaded apps for instances of the Env environment variable. |
find_hooks/0 | Finds all custom setup hooks in all applications. |
find_hooks/1 | Find all setup hooks for Mode in all applications. |
find_hooks/2 | Find all setup hooks for Mode in Applications . |
get_all_env/1 | Like application:get_all_env/1 , but with variable expansion. |
get_env/2 | |
get_env/3 | |
home/0 | Returns the configured home directory, or a best guess ($CWD ). |
keep_release/1 | Generates a release based on what's running in the current node. |
lib_dirs/0 | Equivalent to union(lib_dirs("ERL_SETUP_LIBS"), lib_dirs("ERL_LIBS")). |
lib_dirs/1 | Returns an expanded list of application directories under a lib path. |
lib_dirs_under_path/1 | |
log_dir/0 | Returns the configured log dir, or a best guess (home()/log.Node ). |
mode/0 | Returns the current "setup mode". |
ok/1 | |
patch_app/1 | Adds an application's "development" path to a target system. |
patch_app/3 | |
pick_vsn/3 | Picks the specified version out of a list returned by find_app/1 |
read_config_script/3 | |
read_config_script/4 | |
reload_app/1 | Equivalent to reload_app(AppName, latest). |
reload_app/2 | Equivalent to reload_app(AppName, latest, lib_dirs()). |
reload_app/3 | Loads or upgrades an application to the specified version. |
run_hooks/0 | Execute all setup hooks for current mode in order. |
run_hooks/1 | Execute setup hooks for current mode in Applications in order. |
run_hooks/2 | Execute setup hooks for Mode in Applications in order. |
run_selected_hooks/2 | Execute specified setup hooks in order. |
verify_dir/1 | Ensures that the directory Dir exists and is writable. |
verify_directories/0 | Ensures that essential directories exist and are writable. |
applications() -> [atom()]
data_dir() -> Directory
expand_value(App::atom(), Value::any()) -> any()
expand_value(App::atom(), Key::atom(), Value::any()) -> any()
find_app(A::atom()) -> [{Vsn, Dir}]
find_app(A::atom(), LibDirs::[string()]) -> [{Vsn, Dir}]
find_env_vars(Env) -> [{AppName, Value}]
find_hooks() -> [{PhaseNo, [{M, F, A}]}]
find_hooks(Mode) -> [{PhaseNo, [{M, F, A}]}]
find_hooks(Mode, Applications) -> [{PhaseNo, [{M, F, A}]}]
get_all_env(A::atom()) -> [{atom(), any()}]
home() -> Directory
keep_release(RelVsn) -> ok
lib_dirs() -> [string()]
lib_dirs(Env::string()) -> [string()]
log_dir() -> Directory
mode() -> normal | atom()
patch_app(AppName::atom()) -> true | {error, Reason}
pick_vsn(App::atom(), Dirs::[{Vsn::string(), Dir::string()}], Vsn::Which) -> {Vsn, Dir}
Which = latest | next | Regexp
reload_app(AppName::atom()) -> {ok, NotPurged} | {error, Reason}
reload_app(AppName::atom(), ToVsn) -> {ok, UnPurged} | {error, Reason}
reload_app(AppName::atom(), ToVsn0::ToVsn, LibDirs) -> {ok, Unpurged} | {error, Reason}
ToVsn = latest | next | Vsn
LibDirs = [string()]
Vsn = string()
run_hooks() -> ok
run_hooks(Apps::Applications) -> ok
run_hooks(Mode, Apps::Applications) -> ok
run_selected_hooks(Mode, Hooks) -> ok
verify_dir(Directory::Dir) -> Dir
verify_directories() -> ok