rbcli 0.1.10 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile.lock +12 -12
- data/LICENSE.txt +674 -21
- data/README.md +80 -443
- data/bin/console +19 -0
- data/bin/setup +20 -0
- data/docs/404.html +639 -0
- data/docs/advanced/automatic_updates/index.html +791 -0
- data/docs/advanced/command_types/index.html +946 -0
- data/docs/advanced/distributed_state_locking/index.html +777 -0
- data/docs/advanced/hooks/index.html +836 -0
- data/docs/advanced/state_storage/index.html +957 -0
- data/docs/advanced/user_config_files/index.html +818 -0
- data/docs/assets/fonts/font-awesome.css +4 -0
- data/docs/assets/fonts/material-icons.css +13 -0
- data/docs/assets/fonts/specimen/FontAwesome.ttf +0 -0
- data/docs/assets/fonts/specimen/FontAwesome.woff +0 -0
- data/docs/assets/fonts/specimen/FontAwesome.woff2 +0 -0
- data/docs/assets/fonts/specimen/MaterialIcons-Regular.ttf +0 -0
- data/docs/assets/fonts/specimen/MaterialIcons-Regular.woff +0 -0
- data/docs/assets/fonts/specimen/MaterialIcons-Regular.woff2 +0 -0
- data/docs/assets/images/favicon.png +0 -0
- data/docs/assets/images/icons/bitbucket.1b09e088.svg +20 -0
- data/docs/assets/images/icons/github.f0b8504a.svg +18 -0
- data/docs/assets/images/icons/gitlab.6dd19c00.svg +38 -0
- data/docs/assets/javascripts/application.a59e2a89.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.da.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.de.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.du.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.es.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.fi.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.fr.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.hu.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.it.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.jp.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.multi.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.no.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.pt.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.ro.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.ru.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.stemmer.support.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.sv.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.tr.js +1 -0
- data/docs/assets/javascripts/lunr/tinyseg.js +1 -0
- data/docs/assets/javascripts/modernizr.1aa3b519.js +1 -0
- data/docs/assets/stylesheets/application-palette.6079476c.css +2 -0
- data/docs/assets/stylesheets/application.ba0fd1a6.css +2 -0
- data/docs/development/code_of_conduct/index.html +883 -0
- data/docs/development/contributing/index.html +744 -0
- data/docs/development/license/index.html +715 -0
- data/docs/imported/changelog/index.html +853 -0
- data/docs/imported/quick_reference/index.html +1057 -0
- data/docs/index.html +732 -0
- data/docs/search/search_index.json +569 -0
- data/docs/sitemap.xml +93 -0
- data/docs/tutorial/10-getting_started/index.html +806 -0
- data/docs/tutorial/20-project_layout/index.html +972 -0
- data/docs/tutorial/30-your_first_command/index.html +906 -0
- data/docs/tutorial/40-options_parameters_and_arguments/index.html +1049 -0
- data/docs/tutorial/50-publishing/index.html +838 -0
- data/docs/whoami/index.html +709 -0
- data/docs-src/docs/advanced/automatic_updates.md +42 -0
- data/docs-src/docs/advanced/command_types.md +144 -0
- data/docs-src/docs/advanced/distributed_state_locking.md +33 -0
- data/docs-src/docs/advanced/hooks.md +65 -0
- data/docs-src/docs/advanced/logging.md +35 -0
- data/docs-src/docs/advanced/state_storage.md +117 -0
- data/docs-src/docs/advanced/user_config_files.md +47 -0
- data/docs-src/docs/development/code_of_conduct.md +74 -0
- data/docs-src/docs/development/contributing.md +49 -0
- data/docs-src/docs/development/license.md +10 -0
- data/docs-src/docs/imported/changelog.md +31 -0
- data/docs-src/docs/imported/quick_reference.md +150 -0
- data/docs-src/docs/index.md +38 -0
- data/docs-src/docs/tutorial/10-getting_started.md +41 -0
- data/docs-src/docs/tutorial/20-project_layout.md +115 -0
- data/docs-src/docs/tutorial/30-your_first_command.md +126 -0
- data/docs-src/docs/tutorial/40-options_parameters_and_arguments.md +251 -0
- data/docs-src/docs/tutorial/50-publishing.md +47 -0
- data/docs-src/docs/whoami.md +28 -0
- data/docs-src/makesite.sh +14 -0
- data/docs-src/mkdocs.yml +76 -0
- data/docs-src/runsite.sh +3 -0
- data/exe/rbcli +76 -5
- data/lib/rbcli/autoupdate/autoupdate.rb +24 -4
- data/lib/rbcli/autoupdate/gem_updater.rb +23 -2
- data/lib/rbcli/autoupdate/github_updater.rb +22 -1
- data/lib/rbcli/configuration/config.rb +22 -1
- data/lib/rbcli/configuration/configurate.rb +24 -2
- data/lib/rbcli/engine/command.rb +26 -6
- data/lib/rbcli/engine/load_project.rb +29 -3
- data/lib/rbcli/engine/parser.rb +25 -4
- data/lib/rbcli/logging/logging.rb +21 -0
- data/lib/rbcli/scriptwrapping/scriptwrapper.rb +30 -11
- data/lib/rbcli/stateful_systems/configuratestorage.rb +20 -0
- data/lib/rbcli/stateful_systems/state_storage.rb +20 -0
- data/lib/rbcli/stateful_systems/storagetypes/localstate.rb +20 -0
- data/lib/rbcli/stateful_systems/storagetypes/remote_state_connectors/dynamodb.rb +20 -0
- data/lib/rbcli/stateful_systems/storagetypes/remotestate_dynamodb.rb +20 -0
- data/lib/rbcli/util/hash_deep_symbolize.rb +43 -22
- data/lib/rbcli/util/string_colorize.rb +20 -0
- data/lib/rbcli/version.rb +21 -1
- data/lib/rbcli-tool/generators.rb +20 -0
- data/lib/rbcli-tool/mdless_fix.rb +20 -0
- data/lib/rbcli-tool/project.rb +27 -2
- data/lib/rbcli-tool/util.rb +20 -0
- data/lib/rbcli-tool.rb +20 -0
- data/lib/rbcli.rb +20 -0
- data/lib-sh/lib-rbcli.sh +19 -0
- data/rbcli.gemspec +22 -3
- data/skeletons/project/CODE_OF_CONDUCT.md +1 -1
- data/skeletons/project/README.md +17 -2
- data/skeletons/project/application/commands/command.erb +10 -8
- data/skeletons/project/application/commands/script.erb +3 -1
- data/skeletons/project/application/commands/scripts/script.sh +2 -2
- data/skeletons/project/application/options.rb +12 -3
- data/skeletons/project/config/autoupdate.rb +5 -2
- data/skeletons/project/config/storage.rb +7 -6
- data/skeletons/project/config/userspace.rb +6 -1
- data/skeletons/project/exe/executable +1 -1
- data/skeletons/project/lib/.keep +0 -0
- data/skeletons/project/untitled.gemspec +4 -4
- data/skeletons/project/{default_user_configs → userconf}/user_defaults.yml +0 -0
- metadata +85 -9
- data/examples/defaults.yml +0 -4
- data/examples/myscript.sh +0 -23
- data/examples/mytool +0 -95
@@ -0,0 +1,42 @@
|
|
1
|
+
# Automatic Updates
|
2
|
+
|
3
|
+
RBCli can automatically notify users when an update is available. If `force_update` is set (see below), RBCli can halt execution until the user updates their application.
|
4
|
+
|
5
|
+
Two sources are currently supported: __Github__ (including Enterprise) and __RubyGems__.
|
6
|
+
|
7
|
+
## GitHub Update Check
|
8
|
+
|
9
|
+
The GitHub update check works best when paired with GitHub's best practices on releases, where new releases are tagged on master with the format __vX.X.X__. See [Github's release documentation][github_release_documentation] to learn more.
|
10
|
+
|
11
|
+
RBCli will check your github repo's tags and compare that version number with one specified in your application at `config/version.rb`.
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
autoupdate github_repo: '<your_user>/<your_repo>', access_token: nil, enterprise_hostname: nil, force_update: false, message: nil
|
15
|
+
```
|
16
|
+
The `github_repo` should point to the repo using the `user/repo` syntax.
|
17
|
+
|
18
|
+
The `access_token` can be overridden by the user via their config file, so it can be left as `nil` if you enable [Userspace Configuration][userspace_configuration]. The token is not needed at all if using a public repo. For instructions on generating a new access token, see [here][github_generate_token].
|
19
|
+
|
20
|
+
The `enterprise_hostname` setting allows you to point RBCli at a local GitHub Enterprise server.
|
21
|
+
|
22
|
+
Setting `force_update: true` will halt execution if an update is available, forcing the user to update.
|
23
|
+
|
24
|
+
The `message` parameter allows setting a custom message that will be displayed when an update is available. Leaving it as `nil` will use the default message provided by RBCli.
|
25
|
+
|
26
|
+
## Rubygems.org Update Check
|
27
|
+
|
28
|
+
The Rubygems update check will check if there is a new published version of the gem on Rubygems.org. The latest published version is compared to the version number you configured RBCli with.
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
autoupdate gem: '<your_gem>', force_update: false, message: nil
|
32
|
+
```
|
33
|
+
|
34
|
+
The `gem` parameter should simply state the name of the gem.
|
35
|
+
|
36
|
+
Setting `force_update: true` will halt execution if an update is available, forcing the user to update.
|
37
|
+
|
38
|
+
The `message` parameter allows setting a custom message that will be displayed when an update is available. Leaving it as `nil` will use the default message provided by RBCli.
|
39
|
+
|
40
|
+
[github_release_documentation]: https://help.github.com/articles/creating-releases/
|
41
|
+
[userspace_configuration]: user_config_files.md
|
42
|
+
[github_generate_token]: https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# Advanced Command Types
|
2
|
+
|
3
|
+
RBCli has three different command types:
|
4
|
+
|
5
|
+
* __Standard Commands__ (Ruby-based)
|
6
|
+
* __Scripted Commands__ (Ruby+Bash based)
|
7
|
+
* __External Commands__ (Wrapping a 3rd party application)
|
8
|
+
|
9
|
+
|
10
|
+
This document is provided to be a reference. If you would like an in-depth tutorial, please see [Your First Command][your_first_command].
|
11
|
+
|
12
|
+
|
13
|
+
## General Command Structure
|
14
|
+
|
15
|
+
Commands in RBCli are created by subclassing `Rbcli::Command`. All commands share a certain common structure:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
class List < Rbcli::Command # Declare a new command by subclassing Rbcli::Command
|
19
|
+
description 'TODO: Description goes here' # (Required) Short description for the global help
|
20
|
+
usage <<-EOF
|
21
|
+
TODO: Usage text goes here
|
22
|
+
EOF # (Required) Long description for the command-specific help
|
23
|
+
parameter :force, 'Force testing', type: :boolean, default: false, required: false # (Optional, Multiple) Add a command-specific CLI parameter. Can be called multiple times
|
24
|
+
|
25
|
+
config_default :myopt2, description: 'My Option #2', default: 'Default Value Here' # (Optional, Multiple) Specify an individual configuration parameter and set a default value. These will also be included in generated user config.
|
26
|
+
# Alternatively, you can simply create a yaml file in the `default_user_configs` directory in your project that specifies the default values of all options
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
* `description`
|
31
|
+
* A short description of the command, which will appear in the top-level help (when the user runs `mytool -h`).
|
32
|
+
* `usage`
|
33
|
+
* A description of how the command is meant to be used. This description can be as long as you want, and can be as in-depth as you'd like. It will show up as a long, multi-line description when the user runs the command-sepcific help (`mytool list -h`).
|
34
|
+
* `parameter`
|
35
|
+
* Command-line tags that the user can enter that are specific to only this command. We will get into these in the next section on [Options, Parameters, and Arguments][parameters_documentation]
|
36
|
+
* `config_default`
|
37
|
+
* This sets a single item in the config file that will be made available to the user. More information can be found in the documentation on [User Config Files][user_config_documentation]
|
38
|
+
|
39
|
+
## Standard Commands
|
40
|
+
|
41
|
+
Standard commands are written as ruby code. To create a standard command called `list`, run:
|
42
|
+
|
43
|
+
```bash
|
44
|
+
rbcli command --name=list
|
45
|
+
#or
|
46
|
+
rbcli command -n list
|
47
|
+
```
|
48
|
+
|
49
|
+
A standard command can be identified by the presence of an `action` block in the definition:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
class List < Rbcli::Command
|
53
|
+
action do |params, args, global_opts, config|
|
54
|
+
# Code goes here
|
55
|
+
end
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
Your application's __parameters__, __arguments__, __options__, and __config__ are available in the variables passed into the block. For more information on these, see [Options, Parameters, and Arguments][parameters_documentation].
|
60
|
+
|
61
|
+
|
62
|
+
## Scripted Commands
|
63
|
+
|
64
|
+
Scripted commands are part Ruby, part Bash scripting. They are a good choice to use if you feel something might be easier or more performant to script with Bash, or if you already have a Bash script you'd like to use in your project. You can create one with:
|
65
|
+
|
66
|
+
```bash
|
67
|
+
rbcli script -n list
|
68
|
+
```
|
69
|
+
|
70
|
+
This will create two files in your RBCli project: a Ruby file with the common command declaration (see [General Command Structure](#general-command-structure)), and a bash script in the folder `application/commands/scripts/`.
|
71
|
+
|
72
|
+
You can tell a command is a script by the line:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
class List < Rbcli::Command
|
76
|
+
extern path: :default # (Required): Do not edit this line. Do delete it if you wish to manually specify a script path and set environment variables.
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
RBCli will pass along your applications config and CLI parameters through JSON environment variables. To make things easy, a Bash library is provided that makes retrieving and parsing these variables easy. It is already imported when you generate the command, with the line:
|
81
|
+
|
82
|
+
```bash
|
83
|
+
source $(echo $(cd "$(dirname $(gem which rbcli))/../lib-sh" && pwd)/lib-rbcli.sh)
|
84
|
+
```
|
85
|
+
|
86
|
+
This will find the library which is stored on the system as part of the RBCli gem.
|
87
|
+
|
88
|
+
You can then retrieve the values present in your variables like such:
|
89
|
+
|
90
|
+
```bash
|
91
|
+
rbcli params
|
92
|
+
rbcli args
|
93
|
+
rbcli global_opts
|
94
|
+
rbcli config
|
95
|
+
rbcli myvars
|
96
|
+
|
97
|
+
echo "Usage Examples:"
|
98
|
+
echo "Log Level: $(rbcli config .logger.log_level)"
|
99
|
+
echo "Log Target: $(rbcli config .logger.log_target)"
|
100
|
+
echo "First Argument (if passed): $(rbcli args .[0])"
|
101
|
+
```
|
102
|
+
|
103
|
+
For your convenience, the script will have all the instructions needed there. For more instructions on how to use JQ syntax to parse values, see the [JQ documentation][jq_documentation].
|
104
|
+
|
105
|
+
## External Commands
|
106
|
+
|
107
|
+
External Commands are used to wrap 3rd party applications. RBCli accomplishes this by allowing you to set environment variables and command line parameters based on your input variables.
|
108
|
+
|
109
|
+
RBCli provides this feature through the `extern` keyword. It provides two modes -- __direct path__ and __variable path__ -- which work similarly.
|
110
|
+
|
111
|
+
|
112
|
+
### Direct Path Mode
|
113
|
+
|
114
|
+
Direct path mode is the simpler mode of the two External Command modes. It allows you to provide a specific command with environment variables set, though it does not allow using RBCli parameters, arguments, options, and config.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
class List < Rbcli::Command
|
118
|
+
extern path: 'path/to/application', envvars: {MYVAR: 'some_value'} # (Required) Runs a given application, with optional environment variables, when the user runs the command.
|
119
|
+
end
|
120
|
+
```
|
121
|
+
|
122
|
+
Here, we supply a string to run the command. We can optioanlly provide environment variables which will be set for the external application.
|
123
|
+
|
124
|
+
### Variable Path Mode
|
125
|
+
|
126
|
+
Variable Path mode works the same as Direct Path Mode, only instead of providing a string we provide a block that returns a string (which will be the command executed). This allows us to generate different commands based on the CLI parameters that the user passed, or pass configuration as CLI parameters to the external application:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
class Test < Rbcli::Command
|
130
|
+
extern envvars: {MY_OTHER_VAR: 'another_value'} do |params, args, global_opts, config| # Alternate usage. Supplying a block instead of a path allows us to modify the command based on the arguments and configuration supplied by the user. This allows passing config settings as command line arguments to external applications. The block must return a string, which is the command to be executed.
|
131
|
+
cmd = '/path/to/application'
|
132
|
+
cmd += ' --test-script foo --ignore-errors' if params[:force]
|
133
|
+
cmd
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
__NOTE__: Passing user-supplied data as part of the command string may be a security risk (example: `/path/to/application --name #{params[:name]}`). It is highly recommended to provide the fixed strings yourself, and only select which strings are used based on the variables provided. This is demonstrated in the example above.
|
139
|
+
|
140
|
+
|
141
|
+
[your_first_command]: ../tutorial/30-your_first_command.md
|
142
|
+
[parameters_documentation]: ../tutorial/40-options_parameters_and_arguments.md
|
143
|
+
[user_config_documentation]: ../advanced/user_config_files.md
|
144
|
+
[jq_documentation]: https://stedolan.github.io/jq/manual/
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Distributed Locking and State Sharing
|
2
|
+
|
3
|
+
Distributed Locking allows a [Remote State][state_storage] to be shared among multiple users of the application to make writes appear atomic between sessions. To use it, simply set the `locking:` parameter to `true` when enabling remote state.
|
4
|
+
|
5
|
+
This is how locking works:
|
6
|
+
|
7
|
+
1. The application attempts to acquire a lock on the remote state when you first access it
|
8
|
+
2. If the backend is locked by a different application, wait and try again
|
9
|
+
3. If it succeeds, the lock is held and refreshed periodically
|
10
|
+
4. When the application exits, the lock is released
|
11
|
+
5. If the application does not refresh its lock, or fails to release it when it exits, the lock will automatically expire within 60 seconds
|
12
|
+
6. If another application steals the lock (unlikely but possible), and the application tries to save data, a `StandardError` will be thrown
|
13
|
+
7. You can manually attempt to lock/unlock by calling `Rbcli.remote_state.lock` or `Rbcli.remote_state.unlock`, respectively.
|
14
|
+
|
15
|
+
|
16
|
+
## Manual Locking
|
17
|
+
|
18
|
+
Remember: all state in Rbcli is lazy-loaded. Therefore, RBCli wll only attempt to lock the data when you first try to access it. If you need to make sure that the data is locked before executing a block of code, use:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
Rbcli.remote_state.refresh
|
22
|
+
```
|
23
|
+
|
24
|
+
to force the lock and retrieve the latest data. You can force an unlock by calling:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
Rbcli.remote_state.disconnect
|
28
|
+
```
|
29
|
+
|
30
|
+
Even if you do not want to store any data, you can leverage manual locking to control access to a different shared resource, such as a stateful API. For example, if you write a cloud deployment toolkit, you can ensure that only one user is attempting to modify a deployment at any given time.
|
31
|
+
|
32
|
+
|
33
|
+
[state_storage]: state_storage.md
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# Execution Hooks
|
2
|
+
|
3
|
+
RBCli provides you with hooks that can be used to have code execute at certain places in the execution chain. These hooks are optional, and do not have to be defined for your application to run.
|
4
|
+
|
5
|
+
All hooks will be created in the `hooks/` folder in your project.
|
6
|
+
|
7
|
+
## The Defailt Action Hook
|
8
|
+
|
9
|
+
The Default hook is called when a user calls your application without providing a command. If the hook is not provided, the application will automatically display the help text (the same as running it with `-h`).
|
10
|
+
|
11
|
+
To create it in your project, run:
|
12
|
+
|
13
|
+
```bash
|
14
|
+
rbcli hook --default
|
15
|
+
# or
|
16
|
+
rbcli hook -d
|
17
|
+
```
|
18
|
+
|
19
|
+
You will then find the hook under `hooks/default_action.rb`.
|
20
|
+
|
21
|
+
|
22
|
+
## The Pre-Execution Hook
|
23
|
+
|
24
|
+
The Pre-Execution hook is called after the global command line options are parsed and before a command is executed.
|
25
|
+
|
26
|
+
To create it in your project, run:
|
27
|
+
|
28
|
+
```bash
|
29
|
+
rbcli hook --pre
|
30
|
+
# or
|
31
|
+
rbcli hook -p
|
32
|
+
```
|
33
|
+
|
34
|
+
You will then find the hook under `hooks/pre_execution.rb`.
|
35
|
+
|
36
|
+
## The Post-Execution Hook
|
37
|
+
|
38
|
+
The Pre-Execution hook is called after a command is executed.
|
39
|
+
|
40
|
+
To create it in your project, run:
|
41
|
+
|
42
|
+
```bash
|
43
|
+
rbcli hook --post
|
44
|
+
# or
|
45
|
+
rbcli hook -o
|
46
|
+
```
|
47
|
+
|
48
|
+
You will then find the hook under `hooks/post_execution.rb`.
|
49
|
+
|
50
|
+
## The First-Run Hook
|
51
|
+
|
52
|
+
The First-Run hook is called the first time a user executes your application. Using the first-run hook requires enabling [Local State Storage][state_storage] for persistence.
|
53
|
+
|
54
|
+
To create it in your project, run:
|
55
|
+
|
56
|
+
```bash
|
57
|
+
rbcli hook --firstrun
|
58
|
+
# or
|
59
|
+
rbcli hook -f
|
60
|
+
```
|
61
|
+
|
62
|
+
You will then find the hook under `hooks/first_run.rb`.
|
63
|
+
|
64
|
+
|
65
|
+
[state_storage]: state_storage.md
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Logging
|
2
|
+
|
3
|
+
Logging with RBCli is straightforward - it looks at the config file for logging settings, and instantiates a single, globally accessible [Logger][ruby_logger] object. You can access it within a standard command like this:
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
Rbcli::log.info { 'These logs can go to STDERR, STDOUT, or a file' }
|
7
|
+
```
|
8
|
+
|
9
|
+
## Enabling Logging
|
10
|
+
|
11
|
+
To enable logging, simply set the default values in the `config/logging.rb` file:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
log_level :info
|
15
|
+
log_target 'stderr'
|
16
|
+
```
|
17
|
+
|
18
|
+
* `log_level`
|
19
|
+
* You can set the default log level using either numeric or standard Ruby logger levels: 0-5, or DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
|
20
|
+
* `log_target`
|
21
|
+
* This specifies where the logs will be placed. Valid values are nil (disables logging), 'STDOUT', 'STDERR', or a file path (all as strings).
|
22
|
+
|
23
|
+
## Userspace Config Overrides
|
24
|
+
|
25
|
+
If [Userspace Configuration][userspace_configuration] is enabled, these options will also be present in the user's config file to override defaults:
|
26
|
+
|
27
|
+
```yaml
|
28
|
+
# Log Settings
|
29
|
+
logger:
|
30
|
+
log_level: warn # 0-5, or DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
|
31
|
+
log_target: stderr # STDOUT, STDERR, or a file path
|
32
|
+
```
|
33
|
+
|
34
|
+
[ruby_logger]: https://ruby-doc.org/stdlib-2.4.0/libdoc/logger/rdoc/Logger.html
|
35
|
+
[userspace_configuration]: user_config_files.md
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# State Storage
|
2
|
+
|
3
|
+
RBCli supports both local and remote state storage. This is done by synchronizing a Hash with either the local disk or a remote database.
|
4
|
+
|
5
|
+
## Local State
|
6
|
+
|
7
|
+
RBCli's local state storage gives you access to a hash that is automatically persisted to disk when changes are made.
|
8
|
+
|
9
|
+
### Configuration
|
10
|
+
|
11
|
+
You can configure it in `config/storage.rb`.
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
local_state '/var/mytool/localstate', force_creation: true, halt_on_error: true
|
15
|
+
```
|
16
|
+
|
17
|
+
There are three parameters to configure it with:
|
18
|
+
|
19
|
+
* The `path` as a string (self-explanatory)
|
20
|
+
* `force_creation`
|
21
|
+
* This will attempt to create the path and file if it does not exist (equivalent to an `mkdir -p` and `touch` in linux)
|
22
|
+
* `halt_on_error`
|
23
|
+
* RBCli's default behavior is to raise an exception if the file can not be created, read, or updated at any point in time
|
24
|
+
* If this is set to `false`, RBCli will silence any errors pertaining to file access and will fall back to whatever data is available. Note that if this is enabled, changes made to the state may not be persisted to disk.
|
25
|
+
* If creation fails and file does not exist, you start with an empty hash
|
26
|
+
* If file exists but can't be read, you will have an empty hash
|
27
|
+
* If file can be read but not written, the hash will be populated with the data. Writes will be stored in memory while the application is running, but will not be persisted to disk.
|
28
|
+
|
29
|
+
|
30
|
+
### Access and Usage
|
31
|
+
|
32
|
+
Once configured you can access it with a standard hash syntax in your Standard Commands:
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
Rbcli.local_state[:yourkeyhere]
|
36
|
+
```
|
37
|
+
|
38
|
+
The methods available for use at the top level are as follows:
|
39
|
+
|
40
|
+
Hash native methods:
|
41
|
+
|
42
|
+
* `[]` (Regular hash syntax. Keys are accessed via either symbols or strings indifferently.)
|
43
|
+
* `[]=` (Assignment operator)
|
44
|
+
* `delete`
|
45
|
+
* `each`
|
46
|
+
* `key?`
|
47
|
+
|
48
|
+
Additional methods:
|
49
|
+
|
50
|
+
* `commit`
|
51
|
+
* Every assignment to the top level of the hash will result in a write to disk (for example: `Rbcli.local_state[:yourkey] = 'foo'`). However, if you are manipulating nested hashes, these saves will not be triggered. You can trigger them manually by calling `commit`.
|
52
|
+
* `clear`
|
53
|
+
* Resets the data back to an empty hash.
|
54
|
+
* `refresh`
|
55
|
+
* Loads the most current version of the data from the disk
|
56
|
+
* `disconnect`
|
57
|
+
* Removes the data from memory and sets `Rbcli.local_state = nil`. Data will be read from disk again on next access.
|
58
|
+
|
59
|
+
|
60
|
+
Every assignment will result in a write to disk, so if an operation will require a large number of assignments/writes it should be performed to a different hash before beign assigned to this one.
|
61
|
+
|
62
|
+
|
63
|
+
## Remote State
|
64
|
+
|
65
|
+
RBCli's remote state storage gives you access to a hash that is automatically persisted to a remote storage location when changes are made. It has optional locking built-in, meaning that multiple users may share remote state without any data consistency issues.
|
66
|
+
|
67
|
+
Currently, this feature requires AWS DynamoDB, though other backend systems will be added in the future.
|
68
|
+
|
69
|
+
### Configuration
|
70
|
+
|
71
|
+
Before DynamoDB can be used, AWS API credentials have to be created and made available. RBCli will attempt to find credentials from the following locations in order:
|
72
|
+
|
73
|
+
1. User's config file
|
74
|
+
2. Environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
|
75
|
+
3. User's AWSCLI configuration at `~/.aws/credentials`
|
76
|
+
|
77
|
+
For more information about generating and storing AWS credentials, see [Configuring the AWS SDK for Ruby][aws_sdk_credentials]. Please make sure that your users are aware that they will need to provide their own credentials to use this feature.
|
78
|
+
|
79
|
+
You can configure it in `config/storage.rb`.
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
remote_state_dynamodb table_name: 'mytable', region: 'us-east-1', force_creation: true, halt_on_error: true, locking: false
|
83
|
+
```
|
84
|
+
|
85
|
+
These are the parameters:
|
86
|
+
|
87
|
+
* `table_name`
|
88
|
+
* The name of the DynamoDB table to use.
|
89
|
+
* `region`
|
90
|
+
* The AWS region that the database is located
|
91
|
+
* `force_creation`
|
92
|
+
* Creates the DynamoDB table if it does not already exist
|
93
|
+
* `halt_on_error`
|
94
|
+
* Similar to the way [Local State](#local-state) works, setting this to `false` will silence any errors in connecting to the DynamoDB table. Instead, your application will simply have access to an empty hash that does not get persisted anywhere.
|
95
|
+
* This is good for use cases that involve using this storage as a cache, where a connection error might mean the feature doesn't work but its not important enough to interrupt the user.
|
96
|
+
* `locking`
|
97
|
+
* Setting this to `true` enables locking, meaning only one instance of your application can access the shared data at any given time. For more information see [Distributed State Locking][distributed_state_locking].
|
98
|
+
|
99
|
+
|
100
|
+
### Access and Usage
|
101
|
+
|
102
|
+
Once configured you can access it with a standard hash syntax:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
Rbcli.remote_state[:yourkeyhere]
|
106
|
+
```
|
107
|
+
|
108
|
+
This works the same way that [Local State](#local-state) does, with the same performance caveats (try not to write too frequently).
|
109
|
+
|
110
|
+
Note that all state in Rbcli is __lazy-loaded__, so no connections will be made until your code attempts to access the data even if the feature is enabled.
|
111
|
+
|
112
|
+
For more information on the available commands, see the documentation on [Local State](#local-state)
|
113
|
+
|
114
|
+
|
115
|
+
[aws_sdk_credentials]: https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html
|
116
|
+
[distributed_state_locking]: distributed_state_locking.md
|
117
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Configuration Files
|
2
|
+
|
3
|
+
RBCli provides built-in support for creating and managing userspace configuration files. It does this through two chains: the __defaults chain__ and the __user chain__.
|
4
|
+
|
5
|
+
## Defaults chain
|
6
|
+
|
7
|
+
The defaults chain allows you to specify sane defaults for your CLI tool throughout your code. This gives you the ability to declare configuration alongside the code, and allows RBCli to generate a user config automatically given your defaults. There are two ways to set them:
|
8
|
+
|
9
|
+
* YAML Files
|
10
|
+
* You can store your defaults in one or more YAML files and RBCli will import and combine them. Note that when generating the user config, RBCli will use the YAML text as-is, so comments are transferred as well. This allows you to write descriptions for the options directly in the file that the user can see.
|
11
|
+
* This is good for tools with large or complex configuration that needs user documentation written inline
|
12
|
+
* These YAML files should be placed in the `userconf/` directory in your project and they will automatically be loaded
|
13
|
+
* DSL Statements
|
14
|
+
* In the DSL, you can specify options individually by providing a name, description, and default value
|
15
|
+
* This is good for simpler configuration, as the descriptions provided are written out as comments in the generated user config
|
16
|
+
* You can put global configuration options in `config/userspace.rb`
|
17
|
+
* Command-specific confiugration can be placed in the command declarations in `application/commands/*.rb`
|
18
|
+
|
19
|
+
DSL statements appear in both of the above locations as the following:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
config_default :name, description: '<description_help_text>', default: '<default_value>'
|
23
|
+
```
|
24
|
+
## User chain
|
25
|
+
|
26
|
+
The user chain has two functions: generating and loading configuration from a YAML file on the end user's machine.
|
27
|
+
|
28
|
+
Rbcli will determine the correct location to locate the user configuration based on two factors:
|
29
|
+
|
30
|
+
1. The default location set in `config/userspace.rb`
|
31
|
+
2. The location specified on the command line using the `--config-file=<filename>` option (overrides #1)
|
32
|
+
|
33
|
+
To configure the default location, edit `config/userspace.rb`:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
config_userfile '~/.mytool', merge_defaults: true, required: false
|
37
|
+
```
|
38
|
+
|
39
|
+
* `path/to/config/file`
|
40
|
+
* Self explanatory. Recommended locations are a dotfile in the user's home directory, or a file under `/etc` such as `/etc/mytool/userconf.yaml`
|
41
|
+
* `merge_defaults`
|
42
|
+
* If set to `true`, user settings override default settings. If set to `false`, default settings are not loaded at all and the user is required to have all values specified in their config.
|
43
|
+
* `required`
|
44
|
+
* If set to `true` the application will not run if the file does not exist. A message will be displayed to the user to run your application with the `--generate-config` option to generate the file given your specified defaults.
|
45
|
+
|
46
|
+
|
47
|
+
Users can generate configs by running `yourclitool --generate-config`. This will generate a config file at the tool's default location specified in the DSL. This location can be overridden via the `--config-file=<filename>` option.
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at andrew@blacknex.us. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contribution Guide
|
2
|
+
|
3
|
+
Contributing to RBCli is the same as most open source projects:
|
4
|
+
|
5
|
+
1. Fork the repository
|
6
|
+
2. Create your own branch
|
7
|
+
3. Submit a pull request when ready
|
8
|
+
|
9
|
+
That's all there is to it! We've also kept our acceptance criteria pretty simple, as you'll see below. Feel free to submit a pull request even if you don't meet it if you would like your code or feature to be reviewed first; we do want to be mindful of your time and will review submissions before they are polished.
|
10
|
+
|
11
|
+
# Code Acceptance Criteria
|
12
|
+
|
13
|
+
## Tabs, Not Spaces
|
14
|
+
|
15
|
+
Please, and thanks. We all like to use different indentation levels and styles, and this will keep us consistent between editors.
|
16
|
+
|
17
|
+
For filetypes where tabs are not supported (such as YAML), please stick to using two (2) spaces.
|
18
|
+
|
19
|
+
## Documentation for User Features
|
20
|
+
|
21
|
+
For any modification that alters the way RBCli is used -- we're talking additional features, options, keyword changes, major behavioral changes, and the like -- the documentation will need to be updated as well. You'll be happy to know we designed it to make the process relatively painless.
|
22
|
+
|
23
|
+
RBCli's documentation is essentially a collection of markdown files that have been compiled into a static site using [MkDocs](https://www.mkdocs.org). If you already have python and pip on your system, you can install it by running:
|
24
|
+
|
25
|
+
```bash
|
26
|
+
pip install mkdocs mkdocs-material
|
27
|
+
```
|
28
|
+
|
29
|
+
You can find the source markdown files in the `docs-src/docs` folder, and the menu organization in `docs-src/mkdocs.yml`. To preview your changes on a live site, run:
|
30
|
+
|
31
|
+
```bash
|
32
|
+
mkdocs serve
|
33
|
+
```
|
34
|
+
|
35
|
+
Also, don't forget to update the __Quick Reference Guide__ in the `README.md` file (the main project one) with information about your changes.
|
36
|
+
|
37
|
+
Once you've completed your edits, run the `makesite.sh` command to build the actual HTML pages automatically in the `docs` folder, from where they will be served when live.
|
38
|
+
|
39
|
+
# Maintainer's Notes
|
40
|
+
|
41
|
+
To install this gem onto your local machine from source, run `bundle exec rake install`.
|
42
|
+
|
43
|
+
To release a new version, follow theese steps:
|
44
|
+
|
45
|
+
1. Update the version number in `version.rb`
|
46
|
+
2. Run `bundle exec rake install`, which will update `gemfile.lock` with the correct version and all dependency changes
|
47
|
+
3. Run `docs-src/makesite.sh`, which re-compiles the documentation and pulls in the changelog and quick reference automatically
|
48
|
+
4. Commit the above changes to master, but do not push
|
49
|
+
5. Run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# How RBCli is Licensed
|
2
|
+
|
3
|
+
We want to help the developer community build tooling faster and with less work. That's why RBCli was built. And let's face it - most of us aren't lawyers, and don't want to worry about legal fine print when building awesome software. That's why RBCli is released under the __GPLv3 License__. So you're free to use RBCli as you see fit to write free software. If you wish to use RBCli in a commercial offering, please contact me at [andrew@blacknex.us](mailto:andrew@blacknex.us).
|
4
|
+
|
5
|
+
|
6
|
+
# The License
|
7
|
+
|
8
|
+
You can view the offical license for RBCli [Here](https://github.com/akhoury6/rbcli/blob/master/LICENSE.txt).
|
9
|
+
|
10
|
+
For more details about the GPLv3 License, see [Here](https://choosealicense.com/licenses/gplv3/).
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 0.2.0 (Aug 5, 2018)
|
4
|
+
|
5
|
+
### Features
|
6
|
+
|
7
|
+
* Official documentation created and hosted with Github Pages
|
8
|
+
* RBCli released under GPLv3
|
9
|
+
* Copyright/License notice displayed via RBCli tool with `rbcli license` in accordance with GPLv3 guidelines
|
10
|
+
|
11
|
+
### Bugfixes
|
12
|
+
|
13
|
+
* Fixed version number loading for projects
|
14
|
+
* Cleaned up command usage help output
|
15
|
+
* Fixed script and external command generation
|
16
|
+
|
17
|
+
### Improvements
|
18
|
+
|
19
|
+
* A quick reference guide can now be found in README.md
|
20
|
+
* CLI tool Autoupdate Enabled; when an upgrade to RBCli is detected, the RBCli CLI tool will notify the developer.
|
21
|
+
* Autoupdate feature now allows supplying a custom message
|
22
|
+
* Direct Path Mode for External Commands now
|
23
|
+
* Added support for a `lib` folder in projects, as a place for custom code, which is automatically added to `$LOAD_PATH` for developers
|
24
|
+
* Improved language regarding external commands: Documentation now differentiates between Standard, Scripted, and External Commands
|
25
|
+
* Improved language regarding user config files: Now called Userspace Config
|
26
|
+
* Options and Parameters now allow specifying the letter to be used for the short version, or to disable it altogether
|
27
|
+
* Userspace config can now be disabled by setting the path to nil or removing the declaration
|
28
|
+
|
29
|
+
### Deprecations/Changes
|
30
|
+
|
31
|
+
* Removed deprecated and broken examples from the examples folder
|