glazed 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e764c4f949d82239b29b22b0d38b300f260e31818bf41adc5fb47ad6c091468a
4
- data.tar.gz: 5788a04e0b8da61d1c46e436520ad9e3f78641310b4e0f66c210c524d0041e64
3
+ metadata.gz: d56201f127db708c89e5f41d4eb15e7bb6e1324a009b5ee81717790208df5b60
4
+ data.tar.gz: a56fea960e5bb3649add5be49c4c5ae9f537786ac1b945109bd093eec2d8303c
5
5
  SHA512:
6
- metadata.gz: f456a6b2116655636c1c19e3c8253131aecc266e2d72201ecc6d531faa7ee2e8d64d4ca92147bed91f2153a7e6810c5db8268ca31c257d2cbb08db1160731a02
7
- data.tar.gz: 9d4d631c639884e667c90b718476d1c99a2d37c49085bdf9c48eb7c9a4f2d96626b2681cd5cd12a62abc20e1169b5371ce313d29d6ddffcfea430e8f65cd2776
6
+ metadata.gz: e076356375eb72fa7a7464220b425a68ee32757138c85a22e87f0e5af3350b20fd5c3024c16d7c2f28c3e29c440527b34c2dda6b09df2fcf9ab50555fad4197f
7
+ data.tar.gz: 5490b94175310aef06a49685c7dd564fc958263bad22dff1a4bdbd1c99fab94e57b76a0b4481ced7874b61db92cae94429b0e2e77bee2a08e288a557b0fd43ef
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## [0.4.0] - 2026-10-18
2
+
3
+ ### Breaking changes
4
+
5
+ - Every `*_seconds` setting is a `google.protobuf.Duration` without the suffix, written as a string such as `"900s"` in ProtoJSON, and the old fields are reserved: `timeout` of the `fetch`, `command` and `batch_command` steps, command inventories and command secrets; `poll`, `inventory_refresh`, `lease`, `schedule.interval`, `schedule.retry_interval`, `schedule.jitter`, `debounce.delay`, `debounce.max_wait` of the orchestrator; `grace` of `glazed.v1.CheckTask`; and `cache` of `ssm` secrets. Configs using the old names are rejected
6
+ - `Glazed::Coordinator#sync_inventory` and `#signal` take `Glazed::Proto::V1::Node`s instead of names, and `#complete` takes the inventory's nodes as `nodes:`
7
+
8
+ ### Enhancements
9
+
10
+ - `schedule_rules` of an orchestrated workflow give nodes their own `schedule` and `debounce`, selected by `names`, `groups` or `name_regexp`
11
+
1
12
  ## [0.3.0] - 2026-10-17
2
13
 
3
14
  ### Breaking changes
@@ -53,8 +53,8 @@ module Glazed
53
53
  settings = load_config(config)
54
54
  orchestration = orchestrator_settings(settings, config)
55
55
  workflows = select_orchestrated(orchestration, workflow)
56
- inventory = Sources.nodes(settings.inventory.to_a).map(&:name)
57
- select_nodes(inventory.map { Proto::V1::Node.new(name: it) }, nodes)
56
+ inventory = Sources.nodes(settings.inventory.to_a)
57
+ select_nodes(inventory, nodes)
58
58
  context = StepContext.from_proto(settings.storages, listener: json_listener)
59
59
  backend = state_backend(orchestration, context)
60
60
  at = Time.now
@@ -9,6 +9,7 @@ require 'glazed/proto'
9
9
  require 'glazed/proto_json'
10
10
  require 'glazed/state_backends/base'
11
11
  require 'glazed/step_context'
12
+ require 'glazed/durations'
12
13
 
13
14
  module Glazed
14
15
  module Command
@@ -51,7 +52,7 @@ module Glazed
51
52
  records.select!(&:last_failed) if failing
52
53
 
53
54
  now = Time.now
54
- poll_seconds = orchestration.poll_seconds.zero? ? Orchestrator::DEFAULT_POLL : orchestration.poll_seconds
55
+ poll_seconds = Durations.seconds(orchestration.poll, Orchestrator::DEFAULT_POLL)
55
56
  if json
56
57
  records.each { out.puts ProtoJson.dump(it) }
57
58
  else
@@ -75,9 +76,9 @@ module Glazed
75
76
 
76
77
  # @param record [Proto::V1::NodeSchedule] the record
77
78
  # @param now [Time] current time
78
- # @param poll_seconds [Integer] seconds between the orchestrator's checks for due nodes
79
+ # @param poll_seconds [Numeric] seconds between the orchestrator's checks for due nodes
79
80
  # @return [Array<String>] the cells, then the notes
80
- #: (Proto::V1::NodeSchedule record, now: Time, poll_seconds: Integer) -> Status::row
81
+ #: (Proto::V1::NodeSchedule record, now: Time, poll_seconds: Numeric) -> Status::row
81
82
  private def row(record, now:, poll_seconds:)
82
83
  status = status(record, now:, poll_seconds:)
83
84
  due = time(record.due_at)
@@ -88,16 +89,16 @@ module Glazed
88
89
 
89
90
  # @param record [Proto::V1::NodeSchedule] the record
90
91
  # @param now [Time] current time
91
- # @param poll_seconds [Integer] seconds between the orchestrator's checks for due nodes
92
+ # @param poll_seconds [Numeric] seconds between the orchestrator's checks for due nodes
92
93
  # @return [String] "running", "overdue" when due for more than a poll interval, "due", or "waiting"
93
- #: (Proto::V1::NodeSchedule record, now: Time, poll_seconds: Integer) -> String
94
+ #: (Proto::V1::NodeSchedule record, now: Time, poll_seconds: Numeric) -> String
94
95
  private def status(record, now:, poll_seconds:)
95
96
  return 'running' if Orchestrator::Policy.running?(record, now)
96
97
 
97
98
  due = time(record.due_at)
98
99
  return 'waiting' if due.nil? || due > now
99
100
 
100
- now - due > poll_seconds ? 'overdue' : 'due'
101
+ now - due > poll_seconds.to_f ? 'overdue' : 'due'
101
102
  end
102
103
 
103
104
  # @param record [Proto::V1::NodeSchedule] the record
data/lib/glazed/config.rb CHANGED
@@ -41,10 +41,28 @@ module Glazed
41
41
  end
42
42
 
43
43
  requires.each { require it }
44
- ProtoJson.load(Proto::V1::Config, json).tap { Validation.validate!(it, origin:) }
44
+ ProtoJson.load(Proto::V1::Config, json).tap do
45
+ Validation.validate!(it, origin:)
46
+ check_name_regexps(it, origin:)
47
+ end
45
48
  rescue Google::Protobuf::ParseError, JSON::ParserError => e
46
49
  hint = e.message.include?('Type was not found') ? '; list the gem providing that plugin type in requires' : ''
47
50
  raise Glazed::Error, "#{origin}: #{e.message}#{hint}"
48
51
  end
52
+
53
+ # @param config [Proto::V1::Config] the config
54
+ # @param origin [String] where the config comes from, for error messages
55
+ # @return [void]
56
+ # @raise [InvalidMessage] when a schedule rule's name_regexp does not compile
57
+ #: (Proto::V1::Config config, origin: String) -> void
58
+ private_class_method def self.check_name_regexps(config, origin:)
59
+ config.orchestrator&.workflows&.each do |workflow, orchestration|
60
+ orchestration.schedule_rules.each_with_index do |rule, index|
61
+ Regexp.new(rule.match&.name_regexp.to_s)
62
+ rescue RegexpError => e
63
+ raise InvalidMessage, "#{origin}: orchestrator.workflows.#{workflow}.schedule_rules[#{index}].match.name_regexp: #{e.message}"
64
+ end
65
+ end
66
+ end
49
67
  end
50
68
  end
@@ -10,6 +10,7 @@ require 'glazed/proto'
10
10
  require 'glazed/runner'
11
11
  require 'glazed/steps'
12
12
  require 'glazed/workflow'
13
+ require 'glazed/durations'
13
14
 
14
15
  module Glazed
15
16
  class Coordinator
@@ -65,12 +66,12 @@ module Glazed
65
66
  # @return [Proto::V1::Armed] when to wake up, if at all
66
67
  #: (Proto::V1::CheckTask task) -> Proto::V1::Armed
67
68
  private def check(task)
68
- nodes = load_inventory.keys
69
+ nodes = load_inventory.values
69
70
  @coordinator.sync_inventory(nodes)
70
71
  @coordinator.signal(task.signals.to_a, nodes:) unless task.signals.empty?
71
72
  wake = @coordinator.arm(
72
73
  token: task.token, cycle: task.cycle, max_cycles: task.max_cycles.zero? ? DEFAULT_MAX_CYCLES : task.max_cycles,
73
- grace: task.grace_seconds.zero? ? nil : task.grace_seconds,
74
+ grace: Durations.seconds(task.grace, 0).then { it.zero? ? nil : it },
74
75
  )
75
76
  Proto::V1::Armed.new(wait_until: wake && Google::Protobuf::Timestamp.from_time(wake))
76
77
  end
@@ -79,7 +80,7 @@ module Glazed
79
80
  #: () -> Proto::V1::PreparedBatches
80
81
  private def prepare
81
82
  inventory = load_inventory
82
- @coordinator.sync_inventory(inventory.keys)
83
+ @coordinator.sync_inventory(inventory.values)
83
84
  batches = @workflows.keys.to_h do |workflow|
84
85
  owner, names = @coordinator.claim(workflow)
85
86
  nodes = names.filter_map { inventory[it] }.map { Proto::V1::NodeOutcome.new(state: Proto::V1::NodeState.new(node: it)) }
@@ -147,7 +148,7 @@ module Glazed
147
148
  error = failure ? "#{failure.step}: #{failure.error}" : batch.error
148
149
  errors[outcome.state&.node&.name.to_s] = error unless error.empty?
149
150
  end
150
- @coordinator.complete(batch.workflow, owner: batch.owner, names:, errors:)
151
+ @coordinator.complete(batch.workflow, owner: batch.owner, names:, errors:, nodes: load_inventory)
151
152
  notify(level: 'info', workflow: batch.workflow, message: 'batch finished', nodes: names.size, failed: errors.size)
152
153
  batch
153
154
  end
@@ -12,6 +12,7 @@ require 'glazed/orchestrator/policy'
12
12
  require 'glazed/proto'
13
13
  require 'glazed/runner'
14
14
  require 'glazed/state_backends/base'
15
+ require 'glazed/durations'
15
16
 
16
17
  module Glazed
17
18
  # Changes node schedules in a state backend as the orchestrated workflows
@@ -63,13 +64,13 @@ module Glazed
63
64
  #: () -> Array[String]
64
65
  def workflows = @settings.workflows.keys
65
66
 
66
- # @return [Integer] seconds between checks for due nodes
67
- #: () -> Integer
68
- def poll_seconds = @settings.poll_seconds.zero? ? DEFAULT_POLL : @settings.poll_seconds
67
+ # @return [Float] seconds between checks for due nodes
68
+ #: () -> Float
69
+ def poll_seconds = Durations.seconds(@settings.poll, DEFAULT_POLL)
69
70
 
70
- # @return [Integer] the longest seconds a lease of any workflow lasts
71
- #: () -> Integer
72
- def longest_lease = @settings.workflows.values.map { lease_seconds(it) }.max || DEFAULT_LEASE
71
+ # @return [Float] the longest seconds a lease of any workflow lasts
72
+ #: () -> Float
73
+ def longest_lease = @settings.workflows.values.map { lease_seconds(it) }.max || DEFAULT_LEASE.to_f
73
74
 
74
75
  # @param workflow [String] workflow name
75
76
  # @return [Proto::V1::Orchestration] how the workflow is orchestrated
@@ -82,24 +83,26 @@ module Glazed
82
83
  # Adds records for nodes new to the inventory, due within the schedule's
83
84
  # jitter, and deletes those of nodes gone, in every workflow.
84
85
  #
85
- # @param nodes [Array<String>] names of every node in the inventory
86
+ # @param nodes [Array<Proto::V1::Node>] every node in the inventory
86
87
  # @return [void]
87
- #: (Array[String] nodes) -> void
88
+ #: (Array[Proto::V1::Node] nodes) -> void
88
89
  def sync_inventory(nodes)
89
90
  now = @clock.call
91
+ by_name = nodes.to_h { [it.name, it] }
90
92
  workflows.each do |workflow|
91
93
  known = @backend.list(workflow).map(&:node)
92
- added = nodes - known
93
- removed = known - nodes
94
+ added = by_name.keys - known
95
+ removed = known - by_name.keys
94
96
  next if added.empty? && removed.empty?
95
97
 
96
- schedule = orchestration(workflow).schedule
98
+ orchestration = orchestration(workflow)
97
99
  @backend.update_all(workflow, added + removed) do |node, record|
98
100
  next nil if removed.include?(node)
99
101
 
102
+ schedule = Orchestrator::Policy.schedule_for(orchestration, by_name.fetch(node))
100
103
  record || Orchestrator::Policy.discovered(workflow, node, now:, schedule:, random: @random)
101
104
  end
102
- notify(level: 'info', workflow:, message: 'inventory changed', nodes: nodes.size, added:, removed:)
105
+ notify(level: 'info', workflow:, message: 'inventory changed', nodes: by_name.size, added:, removed:)
103
106
  end
104
107
  end
105
108
 
@@ -107,11 +110,13 @@ module Glazed
107
110
  # Signals naming a node or workflow unknown here are reported and skipped.
108
111
  #
109
112
  # @param signals [Array<Proto::V1::Signal>] the signals
110
- # @param nodes [Array<String>] names of every node in the inventory, which all_nodes signals stand for
113
+ # @param nodes [Array<Proto::V1::Node>] every node in the inventory, which all_nodes signals stand for
111
114
  # @return [Hash{String => Hash{String => Proto::V1::NodeSchedule}}] the resulting records, by workflow and node name
112
- #: (Array[Proto::V1::Signal] signals, nodes: Array[String]) -> Hash[String, Hash[String, Proto::V1::NodeSchedule]]
115
+ #: (Array[Proto::V1::Signal] signals, nodes: Array[Proto::V1::Node]) -> Hash[String, Hash[String, Proto::V1::NodeSchedule]]
113
116
  def signal(signals, nodes:)
114
117
  now = @clock.call
118
+ by_name = nodes.to_h { [it.name, it] }
119
+ nodes = by_name.keys
115
120
  pending = {} #: Hash[String, Hash[String, Array[Proto::V1::Signal]]]
116
121
  signals.each do |signal|
117
122
  targets = signal.all_nodes ? nodes : [signal.node]
@@ -131,8 +136,9 @@ module Glazed
131
136
  end
132
137
 
133
138
  pending.to_h do |workflow, by_node|
134
- debounce = orchestration(workflow).debounce
139
+ orchestration = orchestration(workflow)
135
140
  records = @backend.update_all(workflow, by_node.keys) do |node, record|
141
+ debounce = Orchestrator::Policy.debounce_for(orchestration, by_name.fetch(node))
136
142
  by_node.fetch(node).inject(record) { |current, signal| Orchestrator::Policy.signal(current, signal, workflow:, now:, debounce:) }
137
143
  end
138
144
  [workflow, records]
@@ -166,12 +172,15 @@ module Glazed
166
172
  # @param owner [String] identifier of the batch
167
173
  # @param names [Array<String>] names of the nodes the batch ran
168
174
  # @param errors [Hash{String => String}] why nodes failed, by node name
175
+ # @param nodes [Hash{String => Proto::V1::Node}] nodes of the inventory, by name; those missing follow the workflow's schedule
169
176
  # @return [void]
170
- #: (String workflow, owner: String, names: Array[String], errors: Hash[String, String]) -> void
171
- def complete(workflow, owner:, names:, errors:)
177
+ #: (String workflow, owner: String, names: Array[String], errors: Hash[String, String], nodes: Hash[String, Proto::V1::Node]) -> void
178
+ def complete(workflow, owner:, names:, errors:, nodes:)
172
179
  finished_at = @clock.call
173
- schedule = orchestration(workflow).schedule
180
+ orchestration = orchestration(workflow)
174
181
  @backend.update_all(workflow, names) do |node, record|
182
+ found = nodes[node]
183
+ schedule = found ? Orchestrator::Policy.schedule_for(orchestration, found) : orchestration.schedule
175
184
  Orchestrator::Policy.completed(record, owner:, finished_at:, error: errors[node], schedule:, random: @random)
176
185
  end
177
186
  end
@@ -232,9 +241,9 @@ module Glazed
232
241
  end
233
242
 
234
243
  # @param settings [Proto::V1::Orchestration] how a workflow is orchestrated
235
- # @return [Integer] seconds a lease of the workflow lasts
236
- #: (Proto::V1::Orchestration settings) -> Integer
237
- private def lease_seconds(settings) = settings.lease_seconds.zero? ? DEFAULT_LEASE : settings.lease_seconds
244
+ # @return [Float] seconds a lease of the workflow lasts
245
+ #: (Proto::V1::Orchestration settings) -> Float
246
+ private def lease_seconds(settings) = Durations.seconds(settings.lease, DEFAULT_LEASE)
238
247
 
239
248
  # @param signal [Proto::V1::Signal] a signal for one node or every node
240
249
  # @param node [String] node name
@@ -0,0 +1,21 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ # SPDX-License-Identifier: Apache-2.0
5
+
6
+ require 'google/protobuf'
7
+ require 'google/protobuf/well_known_types'
8
+
9
+ module Glazed
10
+ # Reads google.protobuf.Duration settings.
11
+ module Durations
12
+ # @param duration [Google::Protobuf::Duration, nil] the setting
13
+ # @param default [Numeric] seconds used when the setting is unset or 0
14
+ # @return [Float] seconds
15
+ #: (Google::Protobuf::Duration? duration, Numeric default) -> Float
16
+ def self.seconds(duration, default)
17
+ value = duration&.to_f
18
+ value.nil? || value.zero? ? default.to_f : value
19
+ end
20
+ end
21
+ end
@@ -6,6 +6,8 @@
6
6
  require 'google/protobuf'
7
7
  require 'glazed'
8
8
  require 'glazed/proto'
9
+ require 'glazed/must'
10
+ require 'glazed/durations'
9
11
 
10
12
  module Glazed
11
13
  class Orchestrator
@@ -20,6 +22,35 @@ module Glazed
20
22
  # Seconds after the first signal by which a node runs when the debounce sets none.
21
23
  DEFAULT_MAX_WAIT = 600 #: Integer
22
24
 
25
+ # @param orchestration [Proto::V1::Orchestration] how the workflow is orchestrated
26
+ # @param node [Proto::V1::Node] the node
27
+ # @return [Proto::V1::Schedule, nil] schedule of the first rule matching the node that sets one, else the workflow's
28
+ #: (Proto::V1::Orchestration orchestration, Proto::V1::Node node) -> Proto::V1::Schedule?
29
+ def self.schedule_for(orchestration, node)
30
+ orchestration.schedule_rules.find { it.schedule && matches?(Must.because(it.match) { 'validation requires match' }, node) }&.schedule ||
31
+ orchestration.schedule
32
+ end
33
+
34
+ # @param orchestration [Proto::V1::Orchestration] how the workflow is orchestrated
35
+ # @param node [Proto::V1::Node] the node
36
+ # @return [Proto::V1::Debounce, nil] debounce of the first rule matching the node that sets one, else the workflow's
37
+ #: (Proto::V1::Orchestration orchestration, Proto::V1::Node node) -> Proto::V1::Debounce?
38
+ def self.debounce_for(orchestration, node)
39
+ orchestration.schedule_rules.find { it.debounce && matches?(Must.because(it.match) { 'validation requires match' }, node) }&.debounce ||
40
+ orchestration.debounce
41
+ end
42
+
43
+ # @param match [Proto::V1::NodeMatch] the criteria
44
+ # @param node [Proto::V1::Node] the node
45
+ # @return [Boolean] whether the node meets every criterion set
46
+ #: (Proto::V1::NodeMatch match, Proto::V1::Node node) -> bool
47
+ def self.matches?(match, node)
48
+ return false unless match.names.empty? || match.names.include?(node.name)
49
+ return false unless match.groups.empty? || match.groups.include?(node.group)
50
+
51
+ match.name_regexp.empty? || Regexp.new("\\A(?:#{match.name_regexp})\\z").match?(node.name)
52
+ end
53
+
23
54
  # Record of a node new to the inventory, due within the schedule's jitter.
24
55
  #
25
56
  # @param workflow [String] workflow name
@@ -58,7 +89,7 @@ module Glazed
58
89
  due = if signal.immediate
59
90
  at
60
91
  else
61
- [at + nonzero(debounce&.delay_seconds, DEFAULT_DELAY), window + nonzero(debounce&.max_wait_seconds, DEFAULT_MAX_WAIT)].min
92
+ [at + Durations.seconds(debounce&.delay, DEFAULT_DELAY), window + Durations.seconds(debounce&.max_wait, DEFAULT_MAX_WAIT)].min
62
93
  end
63
94
  scheduled = time(updated.scheduled_at)
64
95
  if !running && scheduled && scheduled <= due
@@ -76,9 +107,9 @@ module Glazed
76
107
  # @param record [Proto::V1::NodeSchedule, nil] the node's record
77
108
  # @param owner [String] identifier of the claiming orchestrator and batch
78
109
  # @param now [Time] current time
79
- # @param lease_seconds [Integer] seconds the lease lasts
110
+ # @param lease_seconds [Numeric] seconds the lease lasts
80
111
  # @return [Proto::V1::NodeSchedule, nil] the leased record; the record unchanged when it is not due or leased to another
81
- #: (Proto::V1::NodeSchedule? record, owner: String, now: Time, lease_seconds: Integer) -> Proto::V1::NodeSchedule?
112
+ #: (Proto::V1::NodeSchedule? record, owner: String, now: Time, lease_seconds: Numeric) -> Proto::V1::NodeSchedule?
82
113
  def self.claim(record, owner:, now:, lease_seconds:)
83
114
  return record unless record
84
115
  return record if running?(record, now)
@@ -107,8 +138,8 @@ module Glazed
107
138
  def self.completed(record, owner:, finished_at:, error:, schedule:, random:)
108
139
  return record unless record && record.lease_owner == owner
109
140
 
110
- interval = nonzero(schedule&.interval_seconds, DEFAULT_INTERVAL)
111
- interval = nonzero(schedule&.retry_interval_seconds, interval) if error
141
+ interval = Durations.seconds(schedule&.interval, DEFAULT_INTERVAL)
142
+ interval = Durations.seconds(schedule&.retry_interval, interval) if error
112
143
  due = finished_at + interval + jitter(schedule, random)
113
144
  window = time(record.signal_window_started_at)
114
145
  started = time(record.last_started_at)
@@ -156,14 +187,14 @@ module Glazed
156
187
  # @param token [String] identifies the deciding execution
157
188
  # @param next_due [Time, nil] when a node may next be claimed; nil when never
158
189
  # @param now [Time] current time
159
- # @param gap [Integer] seconds the execution waits at least after its first cycle
160
- # @param grace [Integer] seconds after waking until another execution may take over
190
+ # @param gap [Numeric] seconds the execution waits at least after its first cycle
191
+ # @param grace [Numeric] seconds after waking until another execution may take over
161
192
  # @param cycle [Integer] times the execution has run due nodes already
162
193
  # @param max_cycles [Integer] cycles after which the execution ends
163
194
  # @param alive [Proc] tells whether the execution of a waiter's token still runs
164
195
  # @return [Array(Proto::V1::Wakeup, Time), Array(Proto::V1::Wakeup, nil), Array(nil, nil)] the waiter
165
196
  # record to keep, and when to wake; nil when the execution ends
166
- #: (Proto::V1::Wakeup? record, token: String, next_due: Time?, now: Time, gap: Integer, grace: Integer, cycle: Integer, max_cycles: Integer, ?alive: ^(String) -> bool) -> [Proto::V1::Wakeup?, Time?]
197
+ #: (Proto::V1::Wakeup? record, token: String, next_due: Time?, now: Time, gap: Numeric, grace: Numeric, cycle: Integer, max_cycles: Integer, ?alive: ^(String) -> bool) -> [Proto::V1::Wakeup?, Time?]
167
198
  def self.arm(record, token:, next_due:, now:, gap:, grace:, cycle:, max_cycles:, alive: ->(_token) { true })
168
199
  own = record&.owner == token
169
200
  return [own ? nil : record, nil] if next_due.nil? || cycle >= max_cycles
@@ -199,18 +230,12 @@ module Glazed
199
230
 
200
231
  # @param schedule [Proto::V1::Schedule, nil] the schedule
201
232
  # @param random [Random] source of jitter
202
- # @return [Integer] seconds of jitter
203
- #: (Proto::V1::Schedule? schedule, Random random) -> Integer
233
+ # @return [Float, Integer] seconds of jitter
234
+ #: (Proto::V1::Schedule? schedule, Random random) -> (Float | Integer)
204
235
  private_class_method def self.jitter(schedule, random)
205
- max = schedule&.jitter_seconds || 0
206
- max.zero? ? 0 : random.rand(max + 1)
236
+ max = Durations.seconds(schedule&.jitter, 0)
237
+ max.zero? ? 0 : random.rand * max
207
238
  end
208
-
209
- # @param value [Integer, nil] configured value
210
- # @param default [Integer] value used when unset or 0
211
- # @return [Integer] the value
212
- #: (Integer? value, Integer default) -> Integer
213
- private_class_method def self.nonzero(value, default) = value.nil? || value.zero? ? default : value
214
239
  end
215
240
  end
216
241
  end
@@ -10,6 +10,7 @@ require 'glazed/proto'
10
10
  require 'glazed/runner'
11
11
  require 'glazed/state_backends/base'
12
12
  require 'glazed/workflow'
13
+ require 'glazed/durations'
13
14
 
14
15
  module Glazed
15
16
  # Runs workflows for nodes as they become due, until stopped. Due dates
@@ -128,12 +129,12 @@ module Glazed
128
129
  next_wait
129
130
  end
130
131
 
131
- # @return [Integer] seconds between inventory reloads
132
- #: () -> Integer
133
- private def inventory_refresh_seconds = @settings.inventory_refresh_seconds.zero? ? DEFAULT_INVENTORY_REFRESH : @settings.inventory_refresh_seconds
132
+ # @return [Float] seconds between inventory reloads
133
+ #: () -> Float
134
+ private def inventory_refresh_seconds = Durations.seconds(@settings.inventory_refresh, DEFAULT_INVENTORY_REFRESH)
134
135
 
135
- # @return [Integer] seconds between checks for due nodes
136
- #: () -> Integer
136
+ # @return [Float] seconds between checks for due nodes
137
+ #: () -> Float
137
138
  private def poll_seconds = @coordinator.poll_seconds
138
139
 
139
140
  # @param request [String] one byte naming the request
@@ -178,7 +179,7 @@ module Glazed
178
179
  @nodes = nodes.to_h { [it.name, it] }
179
180
  @inventory_loaded_at = now
180
181
  notify(level: 'info', message: 'inventory loaded', nodes: @nodes.size)
181
- @coordinator.sync_inventory(@nodes.keys)
182
+ @coordinator.sync_inventory(@nodes.values)
182
183
  end
183
184
 
184
185
  # Runs the workflow for leased nodes and records the outcomes. When
@@ -202,7 +203,7 @@ module Glazed
202
203
  raise
203
204
  end
204
205
  # Records of nodes gone from the inventory are deleted by the next reload.
205
- @coordinator.complete(workflow, owner:, names: names & @nodes.keys, errors:)
206
+ @coordinator.complete(workflow, owner:, names: names & @nodes.keys, errors:, nodes: @nodes)
206
207
  notify(level: 'info', workflow:, message: 'batch finished', nodes: nodes.size, failed: errors.size)
207
208
  end
208
209
 
@@ -9,6 +9,7 @@ require 'glazed/proto'
9
9
  require 'glazed/secret'
10
10
  require 'glazed/secrets'
11
11
  require 'glazed/shell_command'
12
+ require 'glazed/durations'
12
13
 
13
14
  module Glazed
14
15
  module Secrets
@@ -40,7 +41,7 @@ module Glazed
40
41
  #: (Google::Protobuf::MessageExts settings) -> Command
41
42
  def self.from_proto(settings)
42
43
  command = Must.be_a(settings, Proto::V1::CommandSecret)
43
- new(run: ShellCommand.run_of(command.run, command.exec), timeout: command.timeout_seconds.zero? ? DEFAULT_TIMEOUT : command.timeout_seconds)
44
+ new(run: ShellCommand.run_of(command.run, command.exec), timeout: Durations.seconds(command.timeout, DEFAULT_TIMEOUT))
44
45
  end
45
46
 
46
47
  # @return [String, Array<String>] command line, or program and its arguments
@@ -9,6 +9,7 @@ require 'glazed/proto'
9
9
  require 'glazed/shell_command'
10
10
  require 'glazed/sources'
11
11
  require 'glazed/sources/base'
12
+ require 'glazed/durations'
12
13
 
13
14
  module Glazed
14
15
  module Sources
@@ -38,7 +39,7 @@ module Glazed
38
39
  #: (Google::Protobuf::MessageExts settings) -> Command
39
40
  def self.from_proto(settings)
40
41
  command = Must.be_a(settings, Proto::V1::CommandInventory)
41
- new(run: ShellCommand.run_of(command.run, command.exec), timeout: command.timeout_seconds.zero? ? DEFAULT_TIMEOUT : command.timeout_seconds)
42
+ new(run: ShellCommand.run_of(command.run, command.exec), timeout: Durations.seconds(command.timeout, DEFAULT_TIMEOUT))
42
43
  end
43
44
 
44
45
  # @return [String, Array<String>] command line, or program and its arguments
@@ -8,6 +8,7 @@ require 'glazed/proto'
8
8
  require 'glazed/proto_json'
9
9
  require 'glazed/shell_command'
10
10
  require 'glazed/steps'
11
+ require 'glazed/durations'
11
12
 
12
13
  module Glazed
13
14
  module Steps
@@ -40,7 +41,7 @@ module Glazed
40
41
  #: (String name, Google::Protobuf::MessageExts settings, context: StepContext) -> BatchCommand
41
42
  def self.from_proto(name, settings, context:)
42
43
  command = Must.be_a(settings, Proto::V1::BatchCommandStep)
43
- new(name:, run: ShellCommand.run_of(command.run, command.exec), timeout: command.timeout_seconds.zero? ? DEFAULT_TIMEOUT : command.timeout_seconds)
44
+ new(name:, run: ShellCommand.run_of(command.run, command.exec), timeout: Durations.seconds(command.timeout, DEFAULT_TIMEOUT))
44
45
  end
45
46
 
46
47
  # @param batch [Proto::V1::BatchState] node states
@@ -9,6 +9,7 @@ require 'glazed/proto_json'
9
9
  require 'glazed/shell_command'
10
10
  require 'glazed/steps'
11
11
  require 'glazed/storages'
12
+ require 'glazed/durations'
12
13
 
13
14
  module Glazed
14
15
  module Steps
@@ -59,7 +60,7 @@ module Glazed
59
60
  input: command.input.empty? ? nil : command.input,
60
61
  output: command.output.empty? ? nil : command.output,
61
62
  storage_name: command.storage.empty? ? nil : command.storage,
62
- timeout: command.timeout_seconds.zero? ? DEFAULT_TIMEOUT : command.timeout_seconds,
63
+ timeout: Durations.seconds(command.timeout, DEFAULT_TIMEOUT),
63
64
  )
64
65
  end
65
66
 
@@ -9,6 +9,7 @@ require 'glazed/must'
9
9
  require 'glazed/proto'
10
10
  require 'glazed/steps'
11
11
  require 'glazed/storages'
12
+ require 'glazed/durations'
12
13
 
13
14
  module Glazed
14
15
  module Steps
@@ -42,7 +43,7 @@ module Glazed
42
43
  #: (String name, Google::Protobuf::MessageExts settings, context: StepContext) -> Fetch
43
44
  def self.from_proto(name, settings, context:)
44
45
  fetch = Must.be_a(settings, Proto::V1::FetchStep)
45
- timeout = fetch.timeout_seconds.zero? ? CliSession::DEFAULT_TIMEOUT : fetch.timeout_seconds
46
+ timeout = Durations.seconds(fetch.timeout, CliSession::DEFAULT_TIMEOUT)
46
47
  new(name:, output: fetch.output, storage_name: fetch.storage, context:, timeout:)
47
48
  end
48
49
 
@@ -7,10 +7,11 @@ require 'google/protobuf'
7
7
  require 'buf/validate/validate_pb'
8
8
  require 'glazed/v1/orchestrator_pb'
9
9
  require 'glazed/v1/steps_pb'
10
+ require 'google/protobuf/duration_pb'
10
11
  require 'google/protobuf/timestamp_pb'
11
12
 
12
13
 
13
- descriptor_data = "\n\x1bglazed/v1/coordinator.proto\x12\tglazed.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x1cglazed/v1/orchestrator.proto\x1a\x15glazed/v1/steps.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xac\x02\n\x0f\x43oordinatorTask\x12,\n\x05\x63heck\x18\x01 \x01(\x0b\x32\x14.glazed.v1.CheckTaskH\x00R\x05\x63heck\x12\x32\n\x07prepare\x18\x02 \x01(\x0b\x32\x16.glazed.v1.PrepareTaskH\x00R\x07prepare\x12\x36\n\tnode_step\x18\x03 \x01(\x0b\x32\x17.glazed.v1.NodeStepTaskH\x00R\x08nodeStep\x12\x39\n\nbatch_step\x18\x04 \x01(\x0b\x32\x18.glazed.v1.BatchStepTaskH\x00R\tbatchStep\x12\x35\n\x08\x63omplete\x18\x05 \x01(\x0b\x32\x17.glazed.v1.CompleteTaskH\x00R\x08\x63ompleteB\r\n\x04task\x12\x05\xbaH\x02\x08\x01\"\xb1\x01\n\tCheckTask\x12+\n\x07signals\x18\x01 \x03(\x0b\x32\x11.glazed.v1.SignalR\x07signals\x12\x1d\n\x05token\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05token\x12\x14\n\x05\x63ycle\x18\x03 \x01(\rR\x05\x63ycle\x12#\n\rgrace_seconds\x18\x04 \x01(\rR\x0cgraceSeconds\x12\x1d\n\nmax_cycles\x18\x05 \x01(\rR\tmaxCycles\"B\n\x05\x41rmed\x12\x39\n\nwait_until\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\twaitUntil\"\r\n\x0bPrepareTask\"\xa2\x01\n\x0fPreparedBatches\x12\x41\n\x07\x62\x61tches\x18\x01 \x03(\x0b\x32\'.glazed.v1.PreparedBatches.BatchesEntryR\x07\x62\x61tches\x1aL\n\x0c\x42\x61tchesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12&\n\x05value\x18\x02 \x01(\x0b\x32\x10.glazed.v1.BatchR\x05value:\x02\x38\x01\"\x86\x01\n\x05\x42\x61tch\x12#\n\x08workflow\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x08workflow\x12\x14\n\x05owner\x18\x02 \x01(\tR\x05owner\x12,\n\x05nodes\x18\x03 \x03(\x0b\x32\x16.glazed.v1.NodeOutcomeR\x05nodes\x12\x14\n\x05\x65rror\x18\x04 \x01(\tR\x05\x65rror\"s\n\x0bNodeOutcome\x12\x32\n\x05state\x18\x01 \x01(\x0b\x32\x14.glazed.v1.NodeStateB\x06\xbaH\x03\xc8\x01\x01R\x05state\x12\x30\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32\x16.glazed.v1.StepFailureR\x07\x66\x61ilure\"7\n\x0bStepFailure\x12\x12\n\x04step\x18\x01 \x01(\tR\x04step\x12\x14\n\x05\x65rror\x18\x02 \x01(\tR\x05\x65rror\"\x8a\x01\n\x0cNodeStepTask\x12#\n\x08workflow\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x08workflow\x12\x1b\n\x04step\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04step\x12\x38\n\x07outcome\x18\x03 \x01(\x0b\x32\x16.glazed.v1.NodeOutcomeB\x06\xbaH\x03\xc8\x01\x01R\x07outcome\"\\\n\rBatchStepTask\x12\x1b\n\x04step\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04step\x12.\n\x05\x62\x61tch\x18\x02 \x01(\x0b\x32\x10.glazed.v1.BatchB\x06\xbaH\x03\xc8\x01\x01R\x05\x62\x61tch\">\n\x0c\x43ompleteTask\x12.\n\x05\x62\x61tch\x18\x01 \x01(\x0b\x32\x10.glazed.v1.BatchB\x06\xbaH\x03\xc8\x01\x01R\x05\x62\x61tchB\x14\xea\x02\x11Glazed::Proto::V1b\x06proto3"
14
+ descriptor_data = "\n\x1bglazed/v1/coordinator.proto\x12\tglazed.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x1cglazed/v1/orchestrator.proto\x1a\x15glazed/v1/steps.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xac\x02\n\x0f\x43oordinatorTask\x12,\n\x05\x63heck\x18\x01 \x01(\x0b\x32\x14.glazed.v1.CheckTaskH\x00R\x05\x63heck\x12\x32\n\x07prepare\x18\x02 \x01(\x0b\x32\x16.glazed.v1.PrepareTaskH\x00R\x07prepare\x12\x36\n\tnode_step\x18\x03 \x01(\x0b\x32\x17.glazed.v1.NodeStepTaskH\x00R\x08nodeStep\x12\x39\n\nbatch_step\x18\x04 \x01(\x0b\x32\x18.glazed.v1.BatchStepTaskH\x00R\tbatchStep\x12\x35\n\x08\x63omplete\x18\x05 \x01(\x0b\x32\x17.glazed.v1.CompleteTaskH\x00R\x08\x63ompleteB\r\n\x04task\x12\x05\xbaH\x02\x08\x01\"\xdc\x01\n\tCheckTask\x12+\n\x07signals\x18\x01 \x03(\x0b\x32\x11.glazed.v1.SignalR\x07signals\x12\x1d\n\x05token\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05token\x12\x14\n\x05\x63ycle\x18\x03 \x01(\rR\x05\x63ycle\x12\x39\n\x05grace\x18\x06 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x05grace\x12\x1d\n\nmax_cycles\x18\x05 \x01(\rR\tmaxCyclesJ\x04\x08\x04\x10\x05R\rgrace_seconds\"B\n\x05\x41rmed\x12\x39\n\nwait_until\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\twaitUntil\"\r\n\x0bPrepareTask\"\xa2\x01\n\x0fPreparedBatches\x12\x41\n\x07\x62\x61tches\x18\x01 \x03(\x0b\x32\'.glazed.v1.PreparedBatches.BatchesEntryR\x07\x62\x61tches\x1aL\n\x0c\x42\x61tchesEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12&\n\x05value\x18\x02 \x01(\x0b\x32\x10.glazed.v1.BatchR\x05value:\x02\x38\x01\"\x86\x01\n\x05\x42\x61tch\x12#\n\x08workflow\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x08workflow\x12\x14\n\x05owner\x18\x02 \x01(\tR\x05owner\x12,\n\x05nodes\x18\x03 \x03(\x0b\x32\x16.glazed.v1.NodeOutcomeR\x05nodes\x12\x14\n\x05\x65rror\x18\x04 \x01(\tR\x05\x65rror\"s\n\x0bNodeOutcome\x12\x32\n\x05state\x18\x01 \x01(\x0b\x32\x14.glazed.v1.NodeStateB\x06\xbaH\x03\xc8\x01\x01R\x05state\x12\x30\n\x07\x66\x61ilure\x18\x02 \x01(\x0b\x32\x16.glazed.v1.StepFailureR\x07\x66\x61ilure\"7\n\x0bStepFailure\x12\x12\n\x04step\x18\x01 \x01(\tR\x04step\x12\x14\n\x05\x65rror\x18\x02 \x01(\tR\x05\x65rror\"\x8a\x01\n\x0cNodeStepTask\x12#\n\x08workflow\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x08workflow\x12\x1b\n\x04step\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04step\x12\x38\n\x07outcome\x18\x03 \x01(\x0b\x32\x16.glazed.v1.NodeOutcomeB\x06\xbaH\x03\xc8\x01\x01R\x07outcome\"\\\n\rBatchStepTask\x12\x1b\n\x04step\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04step\x12.\n\x05\x62\x61tch\x18\x02 \x01(\x0b\x32\x10.glazed.v1.BatchB\x06\xbaH\x03\xc8\x01\x01R\x05\x62\x61tch\">\n\x0c\x43ompleteTask\x12.\n\x05\x62\x61tch\x18\x01 \x01(\x0b\x32\x10.glazed.v1.BatchB\x06\xbaH\x03\xc8\x01\x01R\x05\x62\x61tchB\x14\xea\x02\x11Glazed::Proto::V1b\x06proto3"
14
15
 
15
16
  pool = ::Google::Protobuf::DescriptorPool.generated_pool
16
17
  pool.add_serialized_file(descriptor_data)
@@ -7,9 +7,10 @@ require 'google/protobuf'
7
7
  require 'buf/validate/validate_pb'
8
8
  require 'glazed/v1/secret_pb'
9
9
  require 'google/protobuf/any_pb'
10
+ require 'google/protobuf/duration_pb'
10
11
 
11
12
 
12
- descriptor_data = "\n\x19glazed/v1/inventory.proto\x12\tglazed.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x16glazed/v1/secret.proto\x1a\x19google/protobuf/any.proto\"\xb6\x05\n\x04Node\x12)\n\x04name\x18\x01 \x01(\tB\x15\xbaH\x12r\x10\x32\x07^[^/]*$Z\x01.Z\x02..R\x04name\x12\x30\n\x05group\x18\x02 \x01(\tB\x1a\xbaH\x17r\x15\x32\x13^([^/]+(/[^/]+)*)?$R\x05group\x12\x12\n\x04host\x18\x03 \x01(\tR\x04host\x12\x1d\n\x04port\x18\x04 \x01(\rB\t\xbaH\x06*\x04\x18\xff\xff\x03R\x04port\x12\x35\n\x07\x64ialect\x18\x05 \x01(\tB\x1b\xbaH\x18r\x16\x32\x14^([a-z][a-z0-9_]*)?$R\x07\x64ialect\x12\x39\n\ttransport\x18\x06 \x01(\tB\x1b\xbaH\x18r\x16\x32\x14^([a-z][a-z0-9_]*)?$R\ttransport\x12\x1a\n\x08username\x18\x07 \x01(\tR\x08username\x12\x30\n\x08password\x18\x08 \x01(\x0b\x32\x14.glazed.v1.SecretRefR\x08password\x12\x41\n\x06params\x18\t \x03(\x0b\x32\x1b.glazed.v1.Node.ParamsEntryB\x0c\xbaH\t\x9a\x01\x06\"\x04r\x02\x10\x01R\x06params\x12\x44\n\x07secrets\x18\n \x03(\x0b\x32\x1c.glazed.v1.Node.SecretsEntryB\x0c\xbaH\t\x9a\x01\x06\"\x04r\x02\x10\x01R\x07secrets\x12H\n\x11transport_options\x18\x0b \x01(\x0b\x32\x1b.glazed.v1.TransportOptionsR\x10transportOptions\x1a\x39\n\x0bParamsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x1aP\n\x0cSecretsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12*\n\x05value\x18\x02 \x01(\x0b\x32\x14.glazed.v1.SecretRefR\x05value:\x02\x38\x01\";\n\x10TransportOptions\x12\'\n\x03ssh\x18\x01 \x01(\x0b\x32\x15.glazed.v1.SshOptionsR\x03ssh\"\xf8\x07\n\nSshOptions\x12%\n\x04keys\x18\x01 \x03(\x0b\x32\x11.glazed.v1.SshKeyR\x04keys\x12\x34\n\npassphrase\x18\x02 \x01(\x0b\x32\x14.glazed.v1.SecretRefR\npassphrase\x12\x1b\n\tkeys_only\x18\x03 \x01(\x08R\x08keysOnly\x12/\n\x0c\x61uth_methods\x18\x04 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x0b\x61uthMethods\x12;\n\x1anumber_of_password_prompts\x18\x05 \x01(\rR\x17numberOfPasswordPrompts\x12[\n\x0fverify_host_key\x18\x06 \x01(\x0e\x32).glazed.v1.SshOptions.HostKeyVerificationB\x08\xbaH\x05\x82\x01\x02\x10\x01R\rverifyHostKey\x12?\n\x15user_known_hosts_file\x18\x07 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x12userKnownHostsFile\x12\x43\n\x17global_known_hosts_file\x18\x08 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x14globalKnownHostsFile\x12\'\n\x08host_key\x18\t \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x07hostKey\x12\x1e\n\x03kex\x18\n \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x03kex\x12,\n\nencryption\x18\x0b \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\nencryption\x12 \n\x04hmac\x18\x0c \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x04hmac\x12 \n\x0b\x63ompression\x18\r \x01(\x08R\x0b\x63ompression\x12#\n\rproxy_command\x18\x0e \x01(\tR\x0cproxyCommand\x12#\n\rforward_agent\x18\x0f \x01(\x08R\x0c\x66orwardAgent\x12)\n\x0euse_ssh_config\x18\x10 \x01(\x08H\x00R\x0cuseSshConfig\x88\x01\x01\"\xdb\x01\n\x13HostKeyVerification\x12%\n!HOST_KEY_VERIFICATION_UNSPECIFIED\x10\x00\x12\x1f\n\x1bHOST_KEY_VERIFICATION_NEVER\x10\x01\x12$\n HOST_KEY_VERIFICATION_ACCEPT_NEW\x10\x02\x12\x34\n0HOST_KEY_VERIFICATION_ACCEPT_NEW_OR_LOCAL_TUNNEL\x10\x03\x12 \n\x1cHOST_KEY_VERIFICATION_ALWAYS\x10\x04\x42\x11\n\x0f_use_ssh_config\"b\n\x06SshKey\x12\x1d\n\x04path\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01H\x00R\x04path\x12(\n\x03raw\x18\x02 \x01(\x0b\x32\x14.glazed.v1.SecretRefH\x00R\x03rawB\x0f\n\x06source\x12\x05\xbaH\x02\x08\x01\"\x89\x04\n\rInventoryFile\x12+\n\x08\x64\x65\x66\x61ults\x18\x01 \x01(\x0b\x32\x0f.glazed.v1.NodeR\x08\x64\x65\x66\x61ults\x12%\n\x05nodes\x18\x02 \x03(\x0b\x32\x0f.glazed.v1.NodeR\x05nodes:\xa3\x03\xbaH\x9f\x03\x1aP\n\x14inventory_file.names\x12\x17\x65very node needs a name\x1a\x1fthis.nodes.all(n, n.name != \'\')\x1aV\n\x1cinventory_file.defaults_name\x12\x1c\x64\x65\x66\x61ults must not set a name\x1a\x18this.defaults.name == \'\'\x1a\\\n\x1binventory_file.unique_names\x12\x19node names must be unique\x1a\"this.nodes.map(n, n.name).unique()\x1a\x94\x01\n\x16inventory_file.dialect\x12\x37\x65very node needs a dialect, from itself or the defaults\x1a\x41this.defaults.dialect != \'\' || this.nodes.all(n, n.dialect != \'\')\"\x81\x02\n\x0fInventorySource\x12>\n\njson_files\x18\x01 \x01(\x0b\x32\x1d.glazed.v1.JsonFilesInventoryH\x00R\tjsonFiles\x12\x32\n\x06inline\x18\x02 \x01(\x0b\x32\x18.glazed.v1.InventoryFileH\x00R\x06inline\x12.\n\x06plugin\x18\x03 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\x06plugin\x12\x37\n\x07\x63ommand\x18\x04 \x01(\x0b\x32\x1b.glazed.v1.CommandInventoryH\x00R\x07\x63ommandB\x11\n\x08provider\x12\x05\xbaH\x02\x08\x01\"\x83\x01\n\x10\x43ommandInventory\x12\x10\n\x03run\x18\x01 \x01(\tR\x03run\x12\'\n\x0ftimeout_seconds\x18\x02 \x01(\rR\x0etimeoutSeconds\x12 \n\x04\x65xec\x18\x03 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x04\x65xec:\x12\xbaH\x0f\"\r\n\x03run\n\x04\x65xec\x10\x01\":\n\x12JsonFilesInventory\x12$\n\x05paths\x18\x01 \x03(\tB\x0e\xbaH\x0b\x92\x01\x08\x08\x01\"\x04r\x02\x10\x01R\x05pathsB\x14\xea\x02\x11Glazed::Proto::V1b\x06proto3"
13
+ descriptor_data = "\n\x19glazed/v1/inventory.proto\x12\tglazed.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x16glazed/v1/secret.proto\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\"\xb6\x05\n\x04Node\x12)\n\x04name\x18\x01 \x01(\tB\x15\xbaH\x12r\x10\x32\x07^[^/]*$Z\x01.Z\x02..R\x04name\x12\x30\n\x05group\x18\x02 \x01(\tB\x1a\xbaH\x17r\x15\x32\x13^([^/]+(/[^/]+)*)?$R\x05group\x12\x12\n\x04host\x18\x03 \x01(\tR\x04host\x12\x1d\n\x04port\x18\x04 \x01(\rB\t\xbaH\x06*\x04\x18\xff\xff\x03R\x04port\x12\x35\n\x07\x64ialect\x18\x05 \x01(\tB\x1b\xbaH\x18r\x16\x32\x14^([a-z][a-z0-9_]*)?$R\x07\x64ialect\x12\x39\n\ttransport\x18\x06 \x01(\tB\x1b\xbaH\x18r\x16\x32\x14^([a-z][a-z0-9_]*)?$R\ttransport\x12\x1a\n\x08username\x18\x07 \x01(\tR\x08username\x12\x30\n\x08password\x18\x08 \x01(\x0b\x32\x14.glazed.v1.SecretRefR\x08password\x12\x41\n\x06params\x18\t \x03(\x0b\x32\x1b.glazed.v1.Node.ParamsEntryB\x0c\xbaH\t\x9a\x01\x06\"\x04r\x02\x10\x01R\x06params\x12\x44\n\x07secrets\x18\n \x03(\x0b\x32\x1c.glazed.v1.Node.SecretsEntryB\x0c\xbaH\t\x9a\x01\x06\"\x04r\x02\x10\x01R\x07secrets\x12H\n\x11transport_options\x18\x0b \x01(\x0b\x32\x1b.glazed.v1.TransportOptionsR\x10transportOptions\x1a\x39\n\x0bParamsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\x1aP\n\x0cSecretsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12*\n\x05value\x18\x02 \x01(\x0b\x32\x14.glazed.v1.SecretRefR\x05value:\x02\x38\x01\";\n\x10TransportOptions\x12\'\n\x03ssh\x18\x01 \x01(\x0b\x32\x15.glazed.v1.SshOptionsR\x03ssh\"\xf8\x07\n\nSshOptions\x12%\n\x04keys\x18\x01 \x03(\x0b\x32\x11.glazed.v1.SshKeyR\x04keys\x12\x34\n\npassphrase\x18\x02 \x01(\x0b\x32\x14.glazed.v1.SecretRefR\npassphrase\x12\x1b\n\tkeys_only\x18\x03 \x01(\x08R\x08keysOnly\x12/\n\x0c\x61uth_methods\x18\x04 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x0b\x61uthMethods\x12;\n\x1anumber_of_password_prompts\x18\x05 \x01(\rR\x17numberOfPasswordPrompts\x12[\n\x0fverify_host_key\x18\x06 \x01(\x0e\x32).glazed.v1.SshOptions.HostKeyVerificationB\x08\xbaH\x05\x82\x01\x02\x10\x01R\rverifyHostKey\x12?\n\x15user_known_hosts_file\x18\x07 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x12userKnownHostsFile\x12\x43\n\x17global_known_hosts_file\x18\x08 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x14globalKnownHostsFile\x12\'\n\x08host_key\x18\t \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x07hostKey\x12\x1e\n\x03kex\x18\n \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x03kex\x12,\n\nencryption\x18\x0b \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\nencryption\x12 \n\x04hmac\x18\x0c \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x04hmac\x12 \n\x0b\x63ompression\x18\r \x01(\x08R\x0b\x63ompression\x12#\n\rproxy_command\x18\x0e \x01(\tR\x0cproxyCommand\x12#\n\rforward_agent\x18\x0f \x01(\x08R\x0c\x66orwardAgent\x12)\n\x0euse_ssh_config\x18\x10 \x01(\x08H\x00R\x0cuseSshConfig\x88\x01\x01\"\xdb\x01\n\x13HostKeyVerification\x12%\n!HOST_KEY_VERIFICATION_UNSPECIFIED\x10\x00\x12\x1f\n\x1bHOST_KEY_VERIFICATION_NEVER\x10\x01\x12$\n HOST_KEY_VERIFICATION_ACCEPT_NEW\x10\x02\x12\x34\n0HOST_KEY_VERIFICATION_ACCEPT_NEW_OR_LOCAL_TUNNEL\x10\x03\x12 \n\x1cHOST_KEY_VERIFICATION_ALWAYS\x10\x04\x42\x11\n\x0f_use_ssh_config\"b\n\x06SshKey\x12\x1d\n\x04path\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01H\x00R\x04path\x12(\n\x03raw\x18\x02 \x01(\x0b\x32\x14.glazed.v1.SecretRefH\x00R\x03rawB\x0f\n\x06source\x12\x05\xbaH\x02\x08\x01\"\x89\x04\n\rInventoryFile\x12+\n\x08\x64\x65\x66\x61ults\x18\x01 \x01(\x0b\x32\x0f.glazed.v1.NodeR\x08\x64\x65\x66\x61ults\x12%\n\x05nodes\x18\x02 \x03(\x0b\x32\x0f.glazed.v1.NodeR\x05nodes:\xa3\x03\xbaH\x9f\x03\x1aP\n\x14inventory_file.names\x12\x17\x65very node needs a name\x1a\x1fthis.nodes.all(n, n.name != \'\')\x1aV\n\x1cinventory_file.defaults_name\x12\x1c\x64\x65\x66\x61ults must not set a name\x1a\x18this.defaults.name == \'\'\x1a\\\n\x1binventory_file.unique_names\x12\x19node names must be unique\x1a\"this.nodes.map(n, n.name).unique()\x1a\x94\x01\n\x16inventory_file.dialect\x12\x37\x65very node needs a dialect, from itself or the defaults\x1a\x41this.defaults.dialect != \'\' || this.nodes.all(n, n.dialect != \'\')\"\x81\x02\n\x0fInventorySource\x12>\n\njson_files\x18\x01 \x01(\x0b\x32\x1d.glazed.v1.JsonFilesInventoryH\x00R\tjsonFiles\x12\x32\n\x06inline\x18\x02 \x01(\x0b\x32\x18.glazed.v1.InventoryFileH\x00R\x06inline\x12.\n\x06plugin\x18\x03 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\x06plugin\x12\x37\n\x07\x63ommand\x18\x04 \x01(\x0b\x32\x1b.glazed.v1.CommandInventoryH\x00R\x07\x63ommandB\x11\n\x08provider\x12\x05\xbaH\x02\x08\x01\"\xb0\x01\n\x10\x43ommandInventory\x12\x10\n\x03run\x18\x01 \x01(\tR\x03run\x12=\n\x07timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x07timeout\x12 \n\x04\x65xec\x18\x03 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x04\x65xec:\x12\xbaH\x0f\"\r\n\x03run\n\x04\x65xec\x10\x01J\x04\x08\x02\x10\x03R\x0ftimeout_seconds\":\n\x12JsonFilesInventory\x12$\n\x05paths\x18\x01 \x03(\tB\x0e\xbaH\x0b\x92\x01\x08\x08\x01\"\x04r\x02\x10\x01R\x05pathsB\x14\xea\x02\x11Glazed::Proto::V1b\x06proto3"
13
14
 
14
15
  pool = ::Google::Protobuf::DescriptorPool.generated_pool
15
16
  pool.add_serialized_file(descriptor_data)
@@ -6,10 +6,11 @@ require 'google/protobuf'
6
6
 
7
7
  require 'buf/validate/validate_pb'
8
8
  require 'glazed/v1/state_pb'
9
+ require 'google/protobuf/duration_pb'
9
10
  require 'google/protobuf/timestamp_pb'
10
11
 
11
12
 
12
- descriptor_data = "\n\x1cglazed/v1/orchestrator.proto\x12\tglazed.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x15glazed/v1/state.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xd8\x02\n\x0cOrchestrator\x12;\n\x05state\x18\x01 \x01(\x0b\x32\x1d.glazed.v1.StateBackendConfigB\x06\xbaH\x03\xc8\x01\x01R\x05state\x12T\n\tworkflows\x18\x02 \x03(\x0b\x32&.glazed.v1.Orchestrator.WorkflowsEntryB\x0e\xbaH\x0b\x9a\x01\x08\x08\x01\"\x04r\x02\x10\x01R\tworkflows\x12!\n\x0cpoll_seconds\x18\x03 \x01(\rR\x0bpollSeconds\x12:\n\x19inventory_refresh_seconds\x18\x04 \x01(\rR\x17inventoryRefreshSeconds\x1aV\n\x0eWorkflowsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x18.glazed.v1.OrchestrationR\x05value:\x02\x38\x01\"\xb5\x01\n\rOrchestration\x12/\n\x08schedule\x18\x01 \x01(\x0b\x32\x13.glazed.v1.ScheduleR\x08schedule\x12/\n\x08\x64\x65\x62ounce\x18\x02 \x01(\x0b\x32\x13.glazed.v1.DebounceR\x08\x64\x65\x62ounce\x12\x1d\n\nbatch_size\x18\x03 \x01(\rR\tbatchSize\x12#\n\rlease_seconds\x18\x04 \x01(\rR\x0cleaseSeconds\"\x92\x01\n\x08Schedule\x12)\n\x10interval_seconds\x18\x01 \x01(\rR\x0fintervalSeconds\x12\x34\n\x16retry_interval_seconds\x18\x02 \x01(\rR\x14retryIntervalSeconds\x12%\n\x0ejitter_seconds\x18\x03 \x01(\rR\rjitterSeconds\"Y\n\x08\x44\x65\x62ounce\x12#\n\rdelay_seconds\x18\x01 \x01(\rR\x0c\x64\x65laySeconds\x12(\n\x10max_wait_seconds\x18\x02 \x01(\rR\x0emaxWaitSeconds\"\xba\x02\n\x06Signal\x12\x12\n\x04node\x18\x01 \x01(\tR\x04node\x12\x1f\n\x06source\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06source\x12;\n\x0breceived_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nreceivedAt\x12\x1c\n\timmediate\x18\x04 \x01(\x08R\timmediate\x12\x1b\n\tall_nodes\x18\x05 \x01(\x08R\x08\x61llNodes\x12*\n\tworkflows\x18\x06 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\tworkflows:W\xbaHT\x1aR\n\rsignal.target\x12\x1cset either node or all_nodes\x1a#(this.node != \'\') != this.all_nodesB\x14\xea\x02\x11Glazed::Proto::V1b\x06proto3"
13
+ descriptor_data = "\n\x1cglazed/v1/orchestrator.proto\x12\tglazed.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x15glazed/v1/state.proto\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xb9\x03\n\x0cOrchestrator\x12;\n\x05state\x18\x01 \x01(\x0b\x32\x1d.glazed.v1.StateBackendConfigB\x06\xbaH\x03\xc8\x01\x01R\x05state\x12T\n\tworkflows\x18\x02 \x03(\x0b\x32&.glazed.v1.Orchestrator.WorkflowsEntryB\x0e\xbaH\x0b\x9a\x01\x08\x08\x01\"\x04r\x02\x10\x01R\tworkflows\x12\x37\n\x04poll\x18\x05 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x04poll\x12P\n\x11inventory_refresh\x18\x06 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x10inventoryRefresh\x1aV\n\x0eWorkflowsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12.\n\x05value\x18\x02 \x01(\x0b\x32\x18.glazed.v1.OrchestrationR\x05value:\x02\x38\x01J\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05R\x0cpoll_secondsR\x19inventory_refresh_seconds\"\xa0\x02\n\rOrchestration\x12/\n\x08schedule\x18\x01 \x01(\x0b\x32\x13.glazed.v1.ScheduleR\x08schedule\x12/\n\x08\x64\x65\x62ounce\x18\x02 \x01(\x0b\x32\x13.glazed.v1.DebounceR\x08\x64\x65\x62ounce\x12\x1d\n\nbatch_size\x18\x03 \x01(\rR\tbatchSize\x12\x39\n\x05lease\x18\x06 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x05lease\x12>\n\x0eschedule_rules\x18\x05 \x03(\x0b\x32\x17.glazed.v1.ScheduleRuleR\rscheduleRulesJ\x04\x08\x04\x10\x05R\rlease_seconds\"\x8d\x02\n\x0cScheduleRule\x12\x32\n\x05match\x18\x01 \x01(\x0b\x32\x14.glazed.v1.NodeMatchB\x06\xbaH\x03\xc8\x01\x01R\x05match\x12/\n\x08schedule\x18\x02 \x01(\x0b\x32\x13.glazed.v1.ScheduleR\x08schedule\x12/\n\x08\x64\x65\x62ounce\x18\x03 \x01(\x0b\x32\x13.glazed.v1.DebounceR\x08\x64\x65\x62ounce:g\xbaHd\x1a\x62\n\x16schedule_rule.settings\x12\x1eset schedule, debounce or both\x1a(has(this.schedule) || has(this.debounce)\"\x93\x02\n\tNodeMatch\x12\"\n\x05names\x18\x01 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x05names\x12$\n\x06groups\x18\x02 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x06groups\x12\x1f\n\x0bname_regexp\x18\x03 \x01(\tR\nnameRegexp:\x9a\x01\xbaH\x96\x01\x1a\x93\x01\n\x13node_match.criteria\x12\x31set at least one of names, groups and name_regexp\x1aIthis.names.size() > 0 || this.groups.size() > 0 || this.name_regexp != \'\'\"\xa0\x02\n\x08Schedule\x12?\n\x08interval\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x08interval\x12J\n\x0eretry_interval\x18\x05 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\rretryInterval\x12;\n\x06jitter\x18\x06 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x06jitterJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04R\x10interval_secondsR\x16retry_interval_secondsR\x0ejitter_seconds\"\xb2\x01\n\x08\x44\x65\x62ounce\x12\x39\n\x05\x64\x65lay\x18\x03 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x05\x64\x65lay\x12>\n\x08max_wait\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x07maxWaitJ\x04\x08\x01\x10\x02J\x04\x08\x02\x10\x03R\rdelay_secondsR\x10max_wait_seconds\"\xba\x02\n\x06Signal\x12\x12\n\x04node\x18\x01 \x01(\tR\x04node\x12\x1f\n\x06source\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06source\x12;\n\x0breceived_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nreceivedAt\x12\x1c\n\timmediate\x18\x04 \x01(\x08R\timmediate\x12\x1b\n\tall_nodes\x18\x05 \x01(\x08R\x08\x61llNodes\x12*\n\tworkflows\x18\x06 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\tworkflows:W\xbaHT\x1aR\n\rsignal.target\x12\x1cset either node or all_nodes\x1a#(this.node != \'\') != this.all_nodesB\x14\xea\x02\x11Glazed::Proto::V1b\x06proto3"
13
14
 
14
15
  pool = ::Google::Protobuf::DescriptorPool.generated_pool
15
16
  pool.add_serialized_file(descriptor_data)
@@ -19,6 +20,8 @@ module Glazed
19
20
  module V1
20
21
  Orchestrator = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("glazed.v1.Orchestrator").msgclass
21
22
  Orchestration = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("glazed.v1.Orchestration").msgclass
23
+ ScheduleRule = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("glazed.v1.ScheduleRule").msgclass
24
+ NodeMatch = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("glazed.v1.NodeMatch").msgclass
22
25
  Schedule = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("glazed.v1.Schedule").msgclass
23
26
  Debounce = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("glazed.v1.Debounce").msgclass
24
27
  Signal = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("glazed.v1.Signal").msgclass
@@ -6,9 +6,10 @@ require 'google/protobuf'
6
6
 
7
7
  require 'buf/validate/validate_pb'
8
8
  require 'google/protobuf/any_pb'
9
+ require 'google/protobuf/duration_pb'
9
10
 
10
11
 
11
- descriptor_data = "\n\x16glazed/v1/secret.proto\x12\tglazed.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x19google/protobuf/any.proto\"\x9b\x02\n\tSecretRef\x12\x16\n\x05value\x18\x01 \x01(\tH\x00R\x05value\x12\x33\n\x03\x65nv\x18\x02 \x01(\tB\x1f\xbaH\x1cr\x1a\x32\x18^[A-Za-z_][A-Za-z0-9_]*$H\x00R\x03\x65nv\x12\x1d\n\x04\x66ile\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01H\x00R\x04\x66ile\x12.\n\x06plugin\x18\x04 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\x06plugin\x12+\n\x03ssm\x18\x05 \x01(\x0b\x32\x17.glazed.v1.SsmParameterH\x00R\x03ssm\x12\x34\n\x07\x63ommand\x18\x06 \x01(\x0b\x32\x18.glazed.v1.CommandSecretH\x00R\x07\x63ommandB\x0f\n\x06source\x12\x05\xbaH\x02\x08\x01\"h\n\x0cSsmParameter\x12\x1b\n\x04name\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04name\x12\x16\n\x06region\x18\x02 \x01(\tR\x06region\x12#\n\rcache_seconds\x18\x03 \x01(\rR\x0c\x63\x61\x63heSeconds\"\x80\x01\n\rCommandSecret\x12\x10\n\x03run\x18\x01 \x01(\tR\x03run\x12\'\n\x0ftimeout_seconds\x18\x02 \x01(\rR\x0etimeoutSeconds\x12 \n\x04\x65xec\x18\x03 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x04\x65xec:\x12\xbaH\x0f\"\r\n\x03run\n\x04\x65xec\x10\x01\x42\x14\xea\x02\x11Glazed::Proto::V1b\x06proto3"
12
+ descriptor_data = "\n\x16glazed/v1/secret.proto\x12\tglazed.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\"\x9b\x02\n\tSecretRef\x12\x16\n\x05value\x18\x01 \x01(\tH\x00R\x05value\x12\x33\n\x03\x65nv\x18\x02 \x01(\tB\x1f\xbaH\x1cr\x1a\x32\x18^[A-Za-z_][A-Za-z0-9_]*$H\x00R\x03\x65nv\x12\x1d\n\x04\x66ile\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01H\x00R\x04\x66ile\x12.\n\x06plugin\x18\x04 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\x06plugin\x12+\n\x03ssm\x18\x05 \x01(\x0b\x32\x17.glazed.v1.SsmParameterH\x00R\x03ssm\x12\x34\n\x07\x63ommand\x18\x06 \x01(\x0b\x32\x18.glazed.v1.CommandSecretH\x00R\x07\x63ommandB\x0f\n\x06source\x12\x05\xbaH\x02\x08\x01\"\x93\x01\n\x0cSsmParameter\x12\x1b\n\x04name\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04name\x12\x16\n\x06region\x18\x02 \x01(\tR\x06region\x12\x39\n\x05\x63\x61\x63he\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x05\x63\x61\x63heJ\x04\x08\x03\x10\x04R\rcache_seconds\"\xad\x01\n\rCommandSecret\x12\x10\n\x03run\x18\x01 \x01(\tR\x03run\x12=\n\x07timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x07timeout\x12 \n\x04\x65xec\x18\x03 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x04\x65xec:\x12\xbaH\x0f\"\r\n\x03run\n\x04\x65xec\x10\x01J\x04\x08\x02\x10\x03R\x0ftimeout_secondsB\x14\xea\x02\x11Glazed::Proto::V1b\x06proto3"
12
13
 
13
14
  pool = ::Google::Protobuf::DescriptorPool.generated_pool
14
15
  pool.add_serialized_file(descriptor_data)
@@ -7,9 +7,10 @@ require 'google/protobuf'
7
7
  require 'buf/validate/validate_pb'
8
8
  require 'glazed/v1/redaction_pb'
9
9
  require 'google/protobuf/any_pb'
10
+ require 'google/protobuf/duration_pb'
10
11
 
11
12
 
12
- descriptor_data = "\n\x18glazed/v1/workflow.proto\x12\tglazed.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x19glazed/v1/redaction.proto\x1a\x19google/protobuf/any.proto\"\x9d\x01\n\x08Workflow\x12/\n\x05steps\x18\x01 \x03(\x0b\x32\x0f.glazed.v1.StepB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x05steps:`\xbaH]\x1a[\n\x1aworkflow.unique_step_names\x12\x19step names must be unique\x1a\"this.steps.map(s, s.name).unique()\"\xef\x02\n\x04Step\x12\x1b\n\x04name\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04name\x12,\n\x05\x66\x65tch\x18\x02 \x01(\x0b\x32\x14.glazed.v1.FetchStepH\x00R\x05\x66\x65tch\x12/\n\x06redact\x18\x03 \x01(\x0b\x32\x15.glazed.v1.RedactStepH\x00R\x06redact\x12\x32\n\x07publish\x18\x04 \x01(\x0b\x32\x16.glazed.v1.PublishStepH\x00R\x07publish\x12\x32\n\x07\x63ommand\x18\x05 \x01(\x0b\x32\x16.glazed.v1.CommandStepH\x00R\x07\x63ommand\x12\x42\n\rbatch_command\x18\x06 \x01(\x0b\x32\x1b.glazed.v1.BatchCommandStepH\x00R\x0c\x62\x61tchCommand\x12.\n\x06plugin\x18\x07 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\x06pluginB\x0f\n\x06\x61\x63tion\x12\x05\xbaH\x02\x08\x01\"x\n\tFetchStep\x12\x1f\n\x06output\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06output\x12!\n\x07storage\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x07storage\x12\'\n\x0ftimeout_seconds\x18\x03 \x01(\rR\x0etimeoutSeconds\"\xa3\x01\n\nRedactStep\x12\x1d\n\x05input\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05input\x12\x1f\n\x06output\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06output\x12!\n\x07storage\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x07storage\x12\x32\n\tredaction\x18\x04 \x01(\x0b\x32\x14.glazed.v1.RedactionR\tredaction\"g\n\x0bPublishStep\x12\x1d\n\x05input\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05input\x12!\n\x07storage\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x07storage\x12\x16\n\x06output\x18\x03 \x01(\tR\x06output\"\xb2\x02\n\x0b\x43ommandStep\x12\x10\n\x03run\x18\x01 \x01(\tR\x03run\x12\x14\n\x05input\x18\x02 \x01(\tR\x05input\x12\x16\n\x06output\x18\x03 \x01(\tR\x06output\x12\x18\n\x07storage\x18\x04 \x01(\tR\x07storage\x12\'\n\x0ftimeout_seconds\x18\x05 \x01(\rR\x0etimeoutSeconds\x12 \n\x04\x65xec\x18\x06 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x04\x65xec:~\xbaH{\x1aj\n\x1b\x63ommand_step.output_storage\x12\x1eoutput and storage go together\x1a+(this.output == \'\') == (this.storage == \'\')\"\r\n\x03run\n\x04\x65xec\x10\x01\"\x83\x01\n\x10\x42\x61tchCommandStep\x12\x10\n\x03run\x18\x01 \x01(\tR\x03run\x12\'\n\x0ftimeout_seconds\x18\x02 \x01(\rR\x0etimeoutSeconds\x12 \n\x04\x65xec\x18\x03 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x04\x65xec:\x12\xbaH\x0f\"\r\n\x03run\n\x04\x65xec\x10\x01\x42\x14\xea\x02\x11Glazed::Proto::V1b\x06proto3"
13
+ descriptor_data = "\n\x18glazed/v1/workflow.proto\x12\tglazed.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x19glazed/v1/redaction.proto\x1a\x19google/protobuf/any.proto\x1a\x1egoogle/protobuf/duration.proto\"\x9d\x01\n\x08Workflow\x12/\n\x05steps\x18\x01 \x03(\x0b\x32\x0f.glazed.v1.StepB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x05steps:`\xbaH]\x1a[\n\x1aworkflow.unique_step_names\x12\x19step names must be unique\x1a\"this.steps.map(s, s.name).unique()\"\xef\x02\n\x04Step\x12\x1b\n\x04name\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04name\x12,\n\x05\x66\x65tch\x18\x02 \x01(\x0b\x32\x14.glazed.v1.FetchStepH\x00R\x05\x66\x65tch\x12/\n\x06redact\x18\x03 \x01(\x0b\x32\x15.glazed.v1.RedactStepH\x00R\x06redact\x12\x32\n\x07publish\x18\x04 \x01(\x0b\x32\x16.glazed.v1.PublishStepH\x00R\x07publish\x12\x32\n\x07\x63ommand\x18\x05 \x01(\x0b\x32\x16.glazed.v1.CommandStepH\x00R\x07\x63ommand\x12\x42\n\rbatch_command\x18\x06 \x01(\x0b\x32\x1b.glazed.v1.BatchCommandStepH\x00R\x0c\x62\x61tchCommand\x12.\n\x06plugin\x18\x07 \x01(\x0b\x32\x14.google.protobuf.AnyH\x00R\x06pluginB\x0f\n\x06\x61\x63tion\x12\x05\xbaH\x02\x08\x01\"\xa5\x01\n\tFetchStep\x12\x1f\n\x06output\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06output\x12!\n\x07storage\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x07storage\x12=\n\x07timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x07timeoutJ\x04\x08\x03\x10\x04R\x0ftimeout_seconds\"\xa3\x01\n\nRedactStep\x12\x1d\n\x05input\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05input\x12\x1f\n\x06output\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06output\x12!\n\x07storage\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x07storage\x12\x32\n\tredaction\x18\x04 \x01(\x0b\x32\x14.glazed.v1.RedactionR\tredaction\"g\n\x0bPublishStep\x12\x1d\n\x05input\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05input\x12!\n\x07storage\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x07storage\x12\x16\n\x06output\x18\x03 \x01(\tR\x06output\"\xdf\x02\n\x0b\x43ommandStep\x12\x10\n\x03run\x18\x01 \x01(\tR\x03run\x12\x14\n\x05input\x18\x02 \x01(\tR\x05input\x12\x16\n\x06output\x18\x03 \x01(\tR\x06output\x12\x18\n\x07storage\x18\x04 \x01(\tR\x07storage\x12=\n\x07timeout\x18\x07 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x07timeout\x12 \n\x04\x65xec\x18\x06 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x04\x65xec:~\xbaH{\x1aj\n\x1b\x63ommand_step.output_storage\x12\x1eoutput and storage go together\x1a+(this.output == \'\') == (this.storage == \'\')\"\r\n\x03run\n\x04\x65xec\x10\x01J\x04\x08\x05\x10\x06R\x0ftimeout_seconds\"\xb0\x01\n\x10\x42\x61tchCommandStep\x12\x10\n\x03run\x18\x01 \x01(\tR\x03run\x12=\n\x07timeout\x18\x04 \x01(\x0b\x32\x19.google.protobuf.DurationB\x08\xbaH\x05\xaa\x01\x02\x32\x00R\x07timeout\x12 \n\x04\x65xec\x18\x03 \x03(\tB\x0c\xbaH\t\x92\x01\x06\"\x04r\x02\x10\x01R\x04\x65xec:\x12\xbaH\x0f\"\r\n\x03run\n\x04\x65xec\x10\x01J\x04\x08\x02\x10\x03R\x0ftimeout_secondsB\x14\xea\x02\x11Glazed::Proto::V1b\x06proto3"
13
14
 
14
15
  pool = ::Google::Protobuf::DescriptorPool.generated_pool
15
16
  pool.add_serialized_file(descriptor_data)
@@ -5,5 +5,5 @@
5
5
 
6
6
  module Glazed
7
7
  # Gem version.
8
- VERSION = '0.3.0' #: String
8
+ VERSION = '0.4.0' #: String
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glazed
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sorah Fukumori
@@ -173,6 +173,7 @@ files:
173
173
  - lib/glazed/dialects/junos.rb
174
174
  - lib/glazed/dialects/nec_ix.rb
175
175
  - lib/glazed/dialects/routeros.rb
176
+ - lib/glazed/durations.rb
176
177
  - lib/glazed/finder.rb
177
178
  - lib/glazed/must.rb
178
179
  - lib/glazed/node_session.rb