vop 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +39 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile.lock +34 -47
  5. data/README.md +118 -16
  6. data/bin/sidekiq.sh +10 -0
  7. data/exe/vop +2 -2
  8. data/lib/core/cache/cache.plugin +0 -0
  9. data/lib/core/cache/commands/invalidate_cache.rb +9 -0
  10. data/lib/core/{structure → meta}/commands/list_commands.rb +2 -1
  11. data/lib/core/meta/commands/list_filters.rb +3 -0
  12. data/lib/core/meta/commands/list_plugins.rb +3 -0
  13. data/lib/core/meta/commands/new_plugin.rb +3 -7
  14. data/lib/core/shell/commands/detail.rb +21 -0
  15. data/lib/core/shell/commands/edit.rb +5 -2
  16. data/lib/core/shell/commands/help.rb +1 -1
  17. data/lib/core/shell/commands/source.rb +10 -4
  18. data/lib/core/structure/commands/collect_contributions.rb +8 -2
  19. data/lib/core/structure/commands/generate_entity_commands.rb +19 -10
  20. data/lib/core/structure/commands/generate_invalidation_commands.rb +19 -9
  21. data/lib/core/structure/commands/list_contribution_targets.rb +9 -0
  22. data/lib/core/structure/commands/list_contributors.rb +1 -1
  23. data/lib/core/structure/structure.plugin +1 -1
  24. data/lib/vop/objects/chain.rb +6 -3
  25. data/lib/vop/objects/command.rb +14 -5
  26. data/lib/vop/objects/command_param.rb +22 -0
  27. data/lib/vop/objects/entities.rb +8 -8
  28. data/lib/vop/objects/entity.rb +57 -16
  29. data/lib/vop/objects/entity_definition.rb +22 -0
  30. data/lib/vop/objects/plugin.rb +46 -4
  31. data/lib/vop/objects/request.rb +9 -5
  32. data/lib/vop/parts/dependency_resolver.rb +0 -4
  33. data/lib/vop/parts/entity_loader.rb +0 -3
  34. data/lib/vop/parts/executor.rb +33 -8
  35. data/lib/vop/parts/plugin_finder.rb +6 -16
  36. data/lib/vop/search_path.rb +12 -0
  37. data/lib/vop/shell/shell.rb +134 -87
  38. data/lib/vop/shell/shell_formatter.rb +32 -17
  39. data/lib/vop/shell/shell_input_readline.rb +3 -0
  40. data/lib/vop/shell/shell_input_testable.rb +9 -3
  41. data/lib/vop/syntax/command_syntax.rb +22 -17
  42. data/lib/vop/syntax/entity_syntax.rb +21 -6
  43. data/lib/vop/syntax/plugin_syntax.rb +6 -0
  44. data/lib/vop/util/pluralizer.rb +9 -1
  45. data/lib/vop/version.rb +1 -1
  46. data/lib/vop/vop.rb +70 -44
  47. data/lib/vop.rb +11 -1
  48. data/vop.gemspec +8 -6
  49. metadata +103 -28
  50. data/lib/core/meta/commands/search_gems_for_plugins.rb +0 -38
  51. data/lib/core/meta/commands/search_path.rb +0 -6
  52. data/lib/core/structure/commands/list_plugins.rb +0 -3
  53. data/lib/vop/util/worker.rb +0 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2e82b43bd88a68ea52a0cc6fa550fa47fb063cbd
4
- data.tar.gz: d88c69b59fb9b4e44d8b17f5d8f8b369ad40cf15
2
+ SHA256:
3
+ metadata.gz: 701c7d9de56bad966ff63365cd24f6feecf5f63314b0dfbd480a5890f23a98b8
4
+ data.tar.gz: 83f8ac7420c3d9a95bb5087c19d70ebaf6ebd228716201588b693f6b89667818
5
5
  SHA512:
6
- metadata.gz: b1eba461ca7c2c0ec1ec030f0bfaa2918adc9e74678284daaf215ec16f69bbb5a8f2be5292253a9d55b6bfc86a5404b50e02761146a7a1e1ff0fcd21d4e52e3e
7
- data.tar.gz: b871a90a6488754cf5e5f984cbe893766a2d775e9f75fb86b0619c361354de36a749b619b2f62c42ba73aceb1567afdfb3a35866732a7d5da61469957750ac0e
6
+ metadata.gz: 8acbbc85ce5502380b618116fbe386675c804997e7bb72cd8f81bbec23ed16d06bd7d308dac28d7c3496d7c8f5cdfa0b9a220f9a509815a3629396b695e5ed3a
7
+ data.tar.gz: ed870d852b55a179bf4cd47d72058eeb111f81c456d5e338af1e086f9596a90021bc83b109dee537b0ea49cdbfa4ce0d931148229e4936b3f08c2b808a504a6b
@@ -0,0 +1,39 @@
1
+ # https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-ruby
2
+
3
+ name: CI
4
+
5
+ on:
6
+ push:
7
+ branches:
8
+ - master
9
+ - and-tonic
10
+ pull_request:
11
+ branches: [ master, and-tonic ]
12
+
13
+ jobs:
14
+ test:
15
+ runs-on: ubuntu-latest
16
+
17
+ services:
18
+ # https://docs.github.com/en/actions/using-containerized-services/creating-redis-service-containers
19
+ redis:
20
+ image: redis
21
+ # Set health checks to wait until redis has started
22
+ options: >-
23
+ --health-cmd "redis-cli ping"
24
+ --health-interval 10s
25
+ --health-timeout 5s
26
+ --health-retries 5
27
+ ports:
28
+ - 6379:6379
29
+
30
+ steps:
31
+ - uses: actions/checkout@v3
32
+ - name: Set up Ruby
33
+ uses: ruby/setup-ruby@359bebbc29cbe6c87da6bc9ea3bc930432750108
34
+ with:
35
+ ruby-version: '3.1'
36
+ - name: Install dependencies
37
+ run: bundle install
38
+ - name: Run tests
39
+ run: bundle exec rake
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.1.2
data/Gemfile.lock CHANGED
@@ -1,67 +1,54 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- vop (0.3.5)
5
- net-scp
6
- net-ssh
7
- redis
8
- sidekiq
4
+ vop (0.3.6)
5
+ byebug
6
+ json (~> 2.3)
9
7
  terminal-table
10
8
  xml-simple
11
9
 
12
10
  GEM
13
11
  remote: https://rubygems.org/
14
12
  specs:
15
- concurrent-ruby (1.0.5)
16
- connection_pool (2.2.1)
17
- diff-lcs (1.2.5)
18
- docile (1.1.5)
19
- json (1.8.6)
20
- net-scp (1.2.1)
21
- net-ssh (>= 2.6.5)
22
- net-ssh (4.2.0)
23
- rack (2.0.3)
24
- rack-protection (2.0.0)
25
- rack
26
- rake (10.5.0)
27
- redis (4.0.1)
28
- rspec (3.4.0)
29
- rspec-core (~> 3.4.0)
30
- rspec-expectations (~> 3.4.0)
31
- rspec-mocks (~> 3.4.0)
32
- rspec-core (3.4.1)
33
- rspec-support (~> 3.4.0)
34
- rspec-expectations (3.4.0)
13
+ byebug (11.1.3)
14
+ diff-lcs (1.5.0)
15
+ docile (1.4.0)
16
+ json (2.7.1)
17
+ rake (13.1.0)
18
+ rexml (3.2.6)
19
+ rspec (3.12.0)
20
+ rspec-core (~> 3.12.0)
21
+ rspec-expectations (~> 3.12.0)
22
+ rspec-mocks (~> 3.12.0)
23
+ rspec-core (3.12.2)
24
+ rspec-support (~> 3.12.0)
25
+ rspec-expectations (3.12.3)
35
26
  diff-lcs (>= 1.2.0, < 2.0)
36
- rspec-support (~> 3.4.0)
37
- rspec-mocks (3.4.0)
27
+ rspec-support (~> 3.12.0)
28
+ rspec-mocks (3.12.6)
38
29
  diff-lcs (>= 1.2.0, < 2.0)
39
- rspec-support (~> 3.4.0)
40
- rspec-support (3.4.1)
41
- sidekiq (5.0.5)
42
- concurrent-ruby (~> 1.0)
43
- connection_pool (~> 2.2, >= 2.2.0)
44
- rack-protection (>= 1.5.0)
45
- redis (>= 3.3.4, < 5)
46
- simplecov (0.11.2)
47
- docile (~> 1.1.0)
48
- json (~> 1.8)
49
- simplecov-html (~> 0.10.0)
50
- simplecov-html (0.10.0)
51
- terminal-table (1.8.0)
52
- unicode-display_width (~> 1.1, >= 1.1.1)
53
- unicode-display_width (1.3.0)
54
- xml-simple (1.1.5)
30
+ rspec-support (~> 3.12.0)
31
+ rspec-support (3.12.1)
32
+ simplecov (0.22.0)
33
+ docile (~> 1.1)
34
+ simplecov-html (~> 0.11)
35
+ simplecov_json_formatter (~> 0.1)
36
+ simplecov-html (0.12.3)
37
+ simplecov_json_formatter (0.1.4)
38
+ terminal-table (3.0.2)
39
+ unicode-display_width (>= 1.1.1, < 3)
40
+ unicode-display_width (2.5.0)
41
+ xml-simple (1.1.9)
42
+ rexml
55
43
 
56
44
  PLATFORMS
57
- ruby
45
+ x86_64-linux
58
46
 
59
47
  DEPENDENCIES
60
- bundler (~> 1.15)
61
- rake (~> 10.0)
48
+ rake
62
49
  rspec (~> 3.0)
63
50
  simplecov
64
51
  vop!
65
52
 
66
53
  BUNDLED WITH
67
- 1.16.0
54
+ 2.4.10
data/README.md CHANGED
@@ -1,25 +1,23 @@
1
+ The vop is a scripting framework.
1
2
 
2
-
3
- The vop is a systems automation scripting framework.
4
-
5
- It organizes (ruby) scripts into commands living in plugins, defines services that can be installed and managed, and comes with a shell and a web interface.
6
-
7
- # Status: WIP
8
-
9
- This is work in progress. Do not assume everything you read to be totally accurate and/or stable.
3
+ It organizes ruby scripts as *commands* living in *plugins*, defines and manages *services*, and can be accessed from the command line or a web interface.
10
4
 
11
5
  # Installation
12
6
 
13
7
  ## as a gem:
14
8
 
15
- $ gem install vop
9
+ $ gem install vop
10
+
11
+ ## from source
12
+
13
+ * checkout the following repos from github.com/virtualop: vop, plugins, bundle
14
+ * install Ruby >= 3.1.2
15
+ * run `bundle install` in all working copies
16
16
 
17
17
  # Usage
18
18
 
19
19
  Call `vop` to start the shell.
20
20
 
21
- Use the tab key for completion, type "help" for more info, `list_plugins` and `list_commands` for an overview.
22
-
23
21
  # Syntax
24
22
 
25
23
  ## Plugins
@@ -51,27 +49,42 @@ hook :after_execute do |payload|
51
49
  end
52
50
  ```
53
51
 
52
+ config:
53
+ ```
54
+ config_param "foo" [, { options }]
55
+ config_param! "snafoo" [, { options }]
56
+ ```
57
+
58
+ accessing plugin config inside command:
59
+ ```
60
+ run do |plugin|
61
+ plugin.config["foo"]
62
+ end
63
+ ```
64
+
54
65
  ## Commands
55
66
 
56
67
  ...are loaded from the `commands` folder in a plugin.
57
68
 
58
- minimal:
69
+ Minimally, a command needs only a run block:
59
70
  ```
60
71
  run { 42 }
61
72
  ```
62
73
 
63
- optional:
74
+ Also, you can use any of these:
64
75
  ```
65
76
  description "Roses are red."
66
77
 
67
78
  read_only # => cacheable
79
+
80
+ dont_log
68
81
  ```
69
82
 
70
- defining param(eter)s:
83
+ A command can define parameters
71
84
  ```
72
85
  param "snafoo" # optional
73
86
  param! "snafoo" # mandatory
74
- param! :snafoo # entity
87
+ param! :snafoo # mandatory entity
75
88
  ```
76
89
  param syntax:
77
90
  ```
@@ -106,12 +119,38 @@ run do |machine|
106
119
  end
107
120
  ```
108
121
 
122
+ There is special handling in place for block parameters.
123
+
124
+ Declare one with
125
+ ```
126
+ block_param
127
+ ```
128
+ or
129
+ ```
130
+ block_param!
131
+ ```
132
+ and a block can be passed to the command like this:
133
+ ```
134
+ @op.foo do
135
+ # whatever you need to do
136
+ end
137
+ ```
138
+ From inside your command, you can access the block through the parameter called `block`.
139
+
109
140
  contribute:
110
141
  ```
111
142
  contribute to: "other_command" do |params|
112
143
  end
113
144
  ```
114
145
 
146
+ collect contributions:
147
+ ```
148
+ @op.collect_contributions(
149
+ command_name: "other_command",
150
+ raw_params: {}
151
+ )
152
+ ```
153
+
115
154
 
116
155
  show (display options for shell output):
117
156
  ```
@@ -139,7 +178,18 @@ deploy package: <foo>
139
178
  deploy package: [ <foo>, <bar>, <baz> ]
140
179
  ```
141
180
 
142
- install (configuration for) a package repository:
181
+ install a virtualop service:
182
+ ```
183
+ deploy service: "plugin.service"
184
+ ```
185
+
186
+ deploy configuration from a template:
187
+ ```
188
+ deploy template: "foo.conf.erb",
189
+ to: "/etc/foo/conf.d/foo.conf"
190
+ ```
191
+
192
+ install (configuration for) a debian package repository:
143
193
  ```
144
194
  deploy repository: {
145
195
  alias: "funny-name",
@@ -157,6 +207,58 @@ deploy do |machine|
157
207
  end
158
208
  ```
159
209
 
210
+ ## Entities
211
+
212
+ Each entity is a file in the `/entities` subfolder of a plugin.
213
+
214
+ A minimal entity is an array of hashes, each with a unique "name" attribute:
215
+
216
+ ```
217
+ entity do
218
+ [
219
+ {
220
+ "name" => "foo"
221
+ }
222
+ ]
223
+ end
224
+ ```
225
+
226
+ Instead of "name", a differing key attribute can be specified with `key`:
227
+ ```
228
+ key "path"
229
+
230
+ entity do
231
+ [
232
+ {
233
+ "path" => "/bin/false"
234
+ }
235
+ ]
236
+ end
237
+ ```
238
+
239
+ The `on` keyword allows to stack entities onto another, e.g. the `log` entity living on a machine:
240
+ ```
241
+ key "path"
242
+
243
+ on :machine
244
+
245
+ entity do |machine|
246
+ # ...
247
+ end
248
+ ```
249
+ A stacked entity (or rather, the list command generated from the entity) automatically has a parameter for the entity it is stacked on - in the log example:
250
+ ```
251
+ >> logs?
252
+
253
+ logs
254
+
255
+ syntax:
256
+ logs <machine>
257
+
258
+ parameters:
259
+ machine
260
+ ```
261
+
160
262
  # Development
161
263
 
162
264
  ## required dependencies
data/bin/sidekiq.sh ADDED
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ VOP_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )
4
+
5
+ cd $VOP_DIR
6
+
7
+ export VOP_ORIGIN="sidekiq"
8
+ bundle exec sidekiq -r ./lib/boot.rb
9
+
10
+ cd - >/dev/null
data/exe/vop CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  require "vop"
4
4
 
5
- @op = Vop.boot()
6
- Vop::Shell.run(@op)
5
+ @op = Vop.boot(origin: "shell:#{Process.pid}@#{`hostname`.strip}")
6
+ Vop::Shell.run(@op, ARGV.join(" "))
File without changes
@@ -0,0 +1,9 @@
1
+ param! "command"
2
+ param! "raw_params", default: {}
3
+
4
+ run do |params|
5
+ @op.collect_contributions(
6
+ command_name: "invalidate_cache",
7
+ raw_params: params
8
+ )
9
+ end
@@ -1,4 +1,5 @@
1
- param "plugin_filter", description: "name of a plugin by which commands should be filtered"
1
+ param "plugin_filter", description: "name of a plugin by which commands should be filtered",
2
+ lookup: lambda { @op.list_plugins }
2
3
 
3
4
  run do |plugin_filter|
4
5
  result = @op.commands.values
@@ -0,0 +1,3 @@
1
+ run do
2
+ @op.filters.keys
3
+ end
@@ -0,0 +1,3 @@
1
+ run do |plugin|
2
+ @op.plugins.map(&:name).sort
3
+ end
@@ -18,25 +18,21 @@ run do |params|
18
18
 
19
19
  raise "no such path: #{params["path"]}" unless File.exists? params["path"]
20
20
 
21
- pp params
22
-
23
- # a plugin is a directory
21
+ # create a new plugin: a plugin is a directory
24
22
  plugin_path = File.join(params["path"], params["name"])
25
23
  puts "plugin path : #{plugin_path}"
26
24
  Dir.mkdir(plugin_path)
27
25
 
28
- # with subfolders for commands and helpers
26
+ # ...with subfolders for commands and helpers
29
27
  %w|commands helpers|.each do |thing|
30
28
  Dir.mkdir(File.join(plugin_path, thing))
31
29
  end
32
30
 
33
- # and a metadata file called "<name>.plugin"
31
+ # ...and a metadata file called "<name>.plugin"
34
32
  plugin_file = params["name"] + ".plugin"
35
33
  full_name = File.join(plugin_path, plugin_file)
36
34
  FileUtils.touch full_name
37
35
 
38
- # TODO content is [] - should probably be nil, though
39
- #puts "content: >>#{params["content"].pretty_inspect}<<"
40
36
  unless params["content"].nil?
41
37
  IO.write(full_name, params["content"])
42
38
  end
@@ -0,0 +1,21 @@
1
+ param "index"
2
+
3
+ show display_type: :raw
4
+
5
+ run do |shell, index|
6
+ last_result = shell.last_response&.result
7
+
8
+ result = if last_result
9
+ if last_result.is_a?(Array) && index
10
+ last_result[index.to_i]
11
+ else
12
+ last_result
13
+ end
14
+ end
15
+
16
+ if result.is_a? ::Vop::Entity
17
+ result.data
18
+ else
19
+ result
20
+ end
21
+ end
@@ -2,10 +2,13 @@ param! "name", lookup: lambda { @op.commands.keys }
2
2
 
3
3
  run do |params, name|
4
4
  has_vim = `which vim`
5
- editor = ENV["EDITOR"] || "vim" if has_vim
5
+ editor = ENV["EDITOR"]
6
+ if editor.nil?
7
+ editor = "vim" if has_vim
8
+ end
6
9
  raise "please set the EDITOR environment variable" unless editor
7
10
 
8
- command_file = @op.commands[name].source[:file_name]
11
+ command_file = @op.commands[name].source[:file_name]
9
12
  system("#{editor} #{command_file}")
10
13
 
11
14
  @op.reset
@@ -1,6 +1,6 @@
1
1
  param! "name",
2
2
  description: "a command for which help should be displayed",
3
- lookup: lambda { |params| @op.list_commands.split }
3
+ lookup: lambda { |params| @op.list_commands }
4
4
 
5
5
  run do |params, name|
6
6
  command = @op.commands[params["name"]]
@@ -1,6 +1,7 @@
1
1
  param! "name", lookup: lambda { @op.commands.keys + @op.entities.keys + @op.filters.keys }
2
+ param "numbers", default: true
2
3
 
3
- run do |name|
4
+ run do |name, numbers|
4
5
  (source, thing) = if @op.commands.keys.include? name
5
6
  [ :commands, @op.commands[name] ]
6
7
  elsif @op.entities.keys.include? name
@@ -13,9 +14,14 @@ run do |name|
13
14
 
14
15
  result = []
15
16
  result << " "
16
- code.lines.each_with_index { |line, idx|
17
- result << "%02d %s" % [idx+1, line.chomp]
18
- }
17
+ code.lines.each_with_index do |line, idx|
18
+ line.chomp!
19
+ line = numbers ?
20
+ "%02d %s" % [idx+1, line] :
21
+ line
22
+
23
+ result << line
24
+ end
19
25
  result << " "
20
26
  result.join("\n")
21
27
  end
@@ -31,11 +31,17 @@ run do |command_name, raw_params|
31
31
  contribution = @op.execute(short_name, raw_params)
32
32
 
33
33
  if contribution.nil?
34
- $logger.warn "command #{short_name} contributes a nil value"
34
+ $logger.debug "command #{short_name} contributes a nil value"
35
35
  else
36
36
  case display_type
37
37
  when :table
38
- result += contribution
38
+ if contribution.is_a? Array
39
+ result += contribution
40
+ else
41
+ if target.show_options[:display_type] == :table
42
+ $logger.warn "contribution from #{short_name} is not an Array (but a #{contribution.class}), though the :table display type would imply that (ignoring)"
43
+ end
44
+ end
39
45
  when :hash
40
46
  result.merge! contribution
41
47
  end
@@ -4,21 +4,23 @@ run do
4
4
  result = []
5
5
 
6
6
  @op.entities.each do |entity_name, definition|
7
- list_command_name = definition.name.carefully_pluralize
8
- $logger.debug "generating entity list command #{list_command_name} (#{definition.plugin.name})"
7
+ $logger.debug "generating entity list command #{definition.list_command_name} (#{definition.plugin.name})"
9
8
 
10
9
  plugin = definition.plugin
11
10
 
12
- list_command = Command.new(plugin, list_command_name)
13
- # TODO list_command.read_only = true
11
+ list_command = Command.new(plugin, definition.list_command_name)
12
+ list_command.read_only = definition.read_only
13
+ list_command.dont_log = true
14
+ list_command.show_options = definition.show_options
14
15
 
15
16
  if definition.on
16
- list_command.add_param(definition.on.to_s, mandatory: true)
17
+ list_command.add_param(definition.on.to_s, mandatory: true, entity: true)
17
18
  end
18
19
 
19
20
  list_command.block = lambda do |params, request, context, plugin|
20
21
  ex = Executor.new(@op)
21
22
  block_param_names = definition.block.parameters.map { |x| x.last }
23
+
22
24
  payload = ex.prepare_payload(request, context, block_param_names)
23
25
 
24
26
  hash_array = definition.block.call(*payload)
@@ -31,11 +33,15 @@ run do
31
33
  entity_array = []
32
34
  unless hash_array.empty?
33
35
  first = hash_array.first
34
- unless first.is_a? Hash
35
- raise "entity '#{definition.name}' returned unexpected data type : found #{first.class}, expected Hash"
36
- end
37
- entity_array = hash_array.map do |row|
38
- Entity.new(@op, definition.short_name, definition.key, row)
36
+ if first.is_a? Entity
37
+ entity_array = hash_array
38
+ else
39
+ unless first.is_a? Hash
40
+ raise "entity '#{definition.name}' returned unexpected data type : found #{first.class}, expected Hash"
41
+ end
42
+ entity_array = hash_array.map do |row|
43
+ Entity.new(@op, definition, row)
44
+ end
39
45
  end
40
46
  end
41
47
 
@@ -43,6 +49,9 @@ run do
43
49
  ::Vop::Entities.new(entity_array)
44
50
  end
45
51
  end
52
+
53
+ list_command.invalidation_block = definition.invalidation_block
54
+
46
55
  result << list_command
47
56
  end
48
57
 
@@ -2,26 +2,36 @@ description "all read-only commands get <command>! commands that invalidate auto
2
2
 
3
3
  run do
4
4
  count = 0
5
- @op.commands.values.each do |command|
6
- # actually, all read-only commands *and* all commands with an invalidation block
7
- if command.read_only || command.invalidation_block
8
- invalidation_command_name = "#{command.short_name}!"
5
+
6
+ def setup_invalidation_command(thing, invalidation_command_name, command_name)
7
+ if thing.read_only || thing.invalidation_block
9
8
  $logger.debug "generating invalidation command #{invalidation_command_name}"
10
9
 
11
- invalidation_command = Command.new(command.plugin, invalidation_command_name)
12
- invalidation_command.params = command.params
10
+ invalidation_command = Command.new(thing.plugin, invalidation_command_name)
11
+ invalidation_command.params = thing.params
13
12
 
14
13
  invalidation_command.block = lambda do |params|
15
14
  @op.invalidate_cache(
16
- "command" => command.short_name,
15
+ "command" => command_name,
17
16
  "raw_params" => params
18
17
  )
19
- @op.execute(command.short_name, params)
18
+ @op.execute(command_name, params)
20
19
  end
21
20
 
22
21
  @op << invalidation_command
23
- count += 1
24
22
  end
25
23
  end
24
+
25
+ @op.commands.values.each do |command|
26
+ setup_invalidation_command(command, "#{command.short_name}!", command.short_name)
27
+ count += 1
28
+ end
29
+
30
+ # not needed at the moment (because entity list commands are generated with an invalidation block)
31
+ # @op.entities.values.each do |entity|
32
+ # setup_invalidation_command(entity, "#{entity.list_command_name}!", entity.list_command_name)
33
+ # count += 1
34
+ # end
35
+
26
36
  count
27
37
  end
@@ -0,0 +1,9 @@
1
+ description "lists the target commands that a given command contributes to (the contributees so to speak)"
2
+
3
+ param! "source_command"
4
+
5
+ run do |plugin, source_command|
6
+ registry = plugin.state[:contributions] || {}
7
+
8
+ registry.select { |k,v| v.include? source_command.to_s.carefully_pluralize }.keys
9
+ end
@@ -3,7 +3,7 @@ param "command_name", description: "command for which contributors should be dis
3
3
  run do |plugin, command_name|
4
4
  registry = plugin.state[:contributions] || {}
5
5
  if command_name
6
- registry[command_name]
6
+ registry[command_name] || []
7
7
  else
8
8
  registry
9
9
  end
@@ -1,4 +1,4 @@
1
- hook :loading_finished do
1
+ hook :init_complete do
2
2
  @op.generate_entity_commands
3
3
  @op.generate_invalidation_commands
4
4
  end