tataru 0.1.0 → 0.2.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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/bin/console +15 -0
  4. data/bin/setup +8 -0
  5. data/lib/tataru.rb +70 -12
  6. data/lib/tataru/base_resource.rb +49 -0
  7. data/lib/tataru/base_resource_desc.rb +35 -0
  8. data/lib/tataru/compiler.rb +100 -0
  9. data/lib/tataru/create_subroutines.rb +31 -0
  10. data/lib/tataru/delete_subroutines.rb +42 -0
  11. data/lib/tataru/flattener.rb +81 -0
  12. data/lib/tataru/init_hash_compiler.rb +41 -0
  13. data/lib/tataru/instruction.rb +52 -7
  14. data/lib/tataru/instruction_hash.rb +54 -0
  15. data/lib/tataru/instructions/call_instruction.rb +19 -0
  16. data/lib/tataru/instructions/check_create_instruction.rb +27 -0
  17. data/lib/tataru/instructions/check_delete_instruction.rb +20 -0
  18. data/lib/tataru/instructions/check_instruction.rb +26 -0
  19. data/lib/tataru/instructions/check_update_instruction.rb +27 -0
  20. data/lib/tataru/instructions/clear_instruction.rb +12 -0
  21. data/lib/tataru/instructions/compare_instruction.rb +16 -0
  22. data/lib/tataru/instructions/create_instruction.rb +20 -0
  23. data/lib/tataru/instructions/delete_instruction.rb +14 -0
  24. data/lib/tataru/instructions/end_instruction.rb +12 -0
  25. data/lib/tataru/instructions/goto_if_instruction.rb +26 -0
  26. data/lib/tataru/instructions/immediate_mode_instruction.rb +12 -0
  27. data/lib/tataru/instructions/init_instruction.rb +27 -0
  28. data/lib/tataru/instructions/key_instruction.rb +12 -0
  29. data/lib/tataru/instructions/mark_deletable_instruction.rb +13 -0
  30. data/lib/tataru/instructions/read_instruction.rb +28 -0
  31. data/lib/tataru/instructions/rescmp_instruction.rb +34 -0
  32. data/lib/tataru/instructions/resource_instruction.rb +15 -0
  33. data/lib/tataru/instructions/return_instruction.rb +16 -0
  34. data/lib/tataru/instructions/update_instruction.rb +16 -0
  35. data/lib/tataru/instructions/value_instruction.rb +15 -0
  36. data/lib/tataru/instructions/value_rom_instruction.rb +23 -0
  37. data/lib/tataru/instructions/value_update_instruction.rb +18 -0
  38. data/lib/tataru/memory.rb +16 -0
  39. data/lib/tataru/quest.rb +43 -0
  40. data/lib/tataru/representation.rb +22 -0
  41. data/lib/tataru/representations/array_representation.rb +18 -0
  42. data/lib/tataru/representations/hash_representation.rb +20 -0
  43. data/lib/tataru/representations/literal_representation.rb +9 -0
  44. data/lib/tataru/representations/output_representation.rb +19 -0
  45. data/lib/tataru/representations/resource_representation.rb +49 -0
  46. data/lib/tataru/resolver.rb +39 -0
  47. data/lib/tataru/resource_dsl.rb +21 -71
  48. data/lib/tataru/resource_type_pool.rb +22 -0
  49. data/lib/tataru/rom_reader.rb +47 -0
  50. data/lib/tataru/runner.rb +48 -0
  51. data/lib/tataru/sub_planner.rb +41 -0
  52. data/lib/tataru/subroutine_compiler.rb +52 -0
  53. data/lib/tataru/top_dsl.rb +35 -0
  54. data/lib/tataru/update_subroutines.rb +111 -0
  55. data/lib/tataru/version.rb +1 -1
  56. data/spec/compiler_spec.rb +181 -0
  57. data/spec/flattener_spec.rb +88 -0
  58. data/spec/init_hash_compiler_spec.rb +85 -0
  59. data/spec/instruction_hash_spec.rb +63 -0
  60. data/spec/instruction_spec.rb +36 -0
  61. data/spec/instructions/call_instruction_spec.rb +28 -0
  62. data/spec/instructions/check_create_instruction_spec.rb +67 -0
  63. data/spec/instructions/check_delete_instruction_spec.rb +47 -0
  64. data/spec/instructions/check_update_instruction_spec.rb +67 -0
  65. data/spec/instructions/clear_instruction_spec.rb +16 -0
  66. data/spec/instructions/compare_instruction_spec.rb +29 -0
  67. data/spec/instructions/create_instruction_spec.rb +62 -0
  68. data/spec/instructions/delete_instruction_spec.rb +20 -0
  69. data/spec/instructions/end_instruction_spec.rb +15 -0
  70. data/spec/instructions/goto_if_instruction_spec.rb +42 -0
  71. data/spec/instructions/init_instruction_spec.rb +16 -0
  72. data/spec/instructions/key_instruction_spec.rb +15 -0
  73. data/spec/instructions/mark_deletable_instruction_spec.rb +20 -0
  74. data/spec/instructions/read_instruction_spec.rb +34 -0
  75. data/spec/instructions/rescmp_instruction_spec.rb +113 -0
  76. data/spec/instructions/return_instruction_spec.rb +28 -0
  77. data/spec/instructions/update_instruction_spec.rb +39 -0
  78. data/spec/instructions/value_instruction_spec.rb +27 -0
  79. data/spec/instructions/value_rom_instruction_spec.rb +170 -0
  80. data/spec/instructions/value_update_instruction_spec.rb +35 -0
  81. data/spec/quest_spec.rb +9 -0
  82. data/spec/representations/array_representation_spec.rb +29 -0
  83. data/spec/representations/hash_representation_spec.rb +29 -0
  84. data/spec/representations/literal_representation_spec.rb +10 -0
  85. data/spec/representations/output_representation_spec.rb +11 -0
  86. data/spec/representations/resource_representation_spec.rb +50 -0
  87. data/spec/resource_dsl_spec.rb +71 -0
  88. data/spec/runner_spec.rb +99 -0
  89. data/spec/spec_helper.rb +401 -0
  90. data/spec/subroutine_compiler_spec.rb +39 -0
  91. data/spec/taru_spec.rb +616 -0
  92. data/spec/top_dsl_spec.rb +68 -0
  93. data/tataru.gemspec +45 -0
  94. metadata +145 -27
  95. data/Rakefile +0 -8
  96. data/lib/tataru/default_resource_finder.rb +0 -10
  97. data/lib/tataru/execution_step.rb +0 -79
  98. data/lib/tataru/planner.rb +0 -93
  99. data/lib/tataru/requirements.rb +0 -67
  100. data/lib/tataru/requirements_dsl.rb +0 -33
  101. data/lib/tataru/resource.rb +0 -52
  102. data/lib/tataru/state.rb +0 -64
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tataru'
4
+
5
+ describe Tataru::Runner do
6
+ it 'can be made' do
7
+ runner = Tataru::Runner.new([])
8
+ end
9
+
10
+ it 'returns ended when ended' do
11
+ runner = Tataru::Runner.new([])
12
+ expect(runner).to be_ended
13
+ end
14
+
15
+ it 'returns not ended when not ended' do
16
+ runner = Tataru::Runner.new([Tataru::Instruction.new])
17
+ expect(runner).to_not be_ended
18
+ end
19
+
20
+ it 'returns ended when ended' do
21
+ runner = Tataru::Runner.new([Tataru::Instruction.new])
22
+ runner.memory.end = true
23
+ expect(runner).to be_ended
24
+ end
25
+
26
+ it 'returns ended when errored' do
27
+ runner = Tataru::Runner.new([Tataru::Instruction.new])
28
+ runner.memory.error = 'Something'
29
+ expect(runner).to be_ended
30
+ end
31
+
32
+ it 'sets memory error if instruction throws' do
33
+ inst1 = Tataru::Instruction.new
34
+ allow(inst1).to receive(:run) { raise 'hello' }
35
+
36
+ runner = Tataru::Runner.new([inst1])
37
+ runner.run_next
38
+
39
+ expect(runner).to be_ended
40
+ expect(runner.memory.error).to be_a RuntimeError
41
+ end
42
+
43
+ it 'runs instructions in order' do
44
+ inst1 = Tataru::Instruction.new
45
+ inst2 = Tataru::Instruction.new
46
+
47
+ runner = Tataru::Runner.new([
48
+ inst1, inst2
49
+ ])
50
+
51
+ expect(inst1).to receive(:run)
52
+ runner.run_next
53
+
54
+ expect(inst2).to receive(:run)
55
+ runner.run_next
56
+ end
57
+
58
+ it 'records resource instructions' do
59
+ inst1cls = Class.new(Tataru::Instructions::ResourceInstruction)
60
+ stub_const('TestInstruction', inst1cls)
61
+ inst1 = inst1cls.new
62
+
63
+
64
+ runner = Tataru::Runner.new([
65
+ inst1
66
+ ])
67
+
68
+ runner.memory.hash[:temp][:resource_name] = 'abcd'
69
+ runner.run_next
70
+
71
+ expect(runner.oplog).to eq [
72
+ {
73
+ operation: 'TEST',
74
+ resource: 'abcd'
75
+ }
76
+ ]
77
+ end
78
+
79
+ it 'ignores tataru instruction namespace' do
80
+ inst1cls = Class.new(Tataru::Instructions::ResourceInstruction)
81
+ stub_const('Tataru::Instructions::TestInstruction', inst1cls)
82
+ inst1 = inst1cls.new
83
+
84
+
85
+ runner = Tataru::Runner.new([
86
+ inst1
87
+ ])
88
+
89
+ runner.memory.hash[:temp][:resource_name] = 'defg'
90
+ runner.run_next
91
+
92
+ expect(runner.oplog).to eq [
93
+ {
94
+ operation: 'TEST',
95
+ resource: 'defg'
96
+ }
97
+ ]
98
+ end
99
+ end
@@ -0,0 +1,401 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require 'pry'
5
+ require 'active_support/testing/time_helpers'
6
+ require 'tataru'
7
+
8
+ RSpec.configure do |config|
9
+ config.include ActiveSupport::Testing::TimeHelpers
10
+ end
11
+
12
+ class TestEnvironment
13
+ include Singleton
14
+
15
+ attr_accessor :files, :servers, :ip_addresses
16
+
17
+ def initialize
18
+ clear!
19
+ end
20
+
21
+ def clear!
22
+ # ids decided by user
23
+ @domain_names = {}
24
+ # a resource with mutable fields
25
+ @load_balancers = {}
26
+ # a resource with outputs
27
+ @api_keys = {}
28
+
29
+ # a resource
30
+ @files = {}
31
+ # a resource that overlaps
32
+ @servers = []
33
+
34
+ # ids decided by server
35
+ @ip_addresses = {}
36
+ @server_to_ip_map = {}
37
+ end
38
+
39
+ def create_file(name, contents)
40
+ raise 'Duplicate file name' if @files.key? name
41
+
42
+ @files[name] = {
43
+ name: name,
44
+ contents: contents,
45
+ updated_at: Time.now.utc.to_s,
46
+ created_at: Time.now.utc.to_s
47
+ }
48
+ end
49
+
50
+ def update_file(name, contents)
51
+ raise "Nonexistent file '#{name}'" unless @files.key? name
52
+
53
+ @files[name][:contents] = contents
54
+ @files[name][:updated_at] = Time.now.utc.to_s
55
+ end
56
+
57
+ def delete_file(name)
58
+ raise "Nonexistent file '#{name}'" unless @files.key? name
59
+
60
+ @files.delete name
61
+ end
62
+
63
+ def exists_file?(name)
64
+ @files.key? name
65
+ end
66
+
67
+ def file(name)
68
+ raise "Nonexistent file '#{name}'" unless @files.key? name
69
+
70
+ @files[name]
71
+ end
72
+
73
+
74
+ def create_server(size)
75
+ id = @servers.count
76
+ @servers[id] = {
77
+ size: size,
78
+ created_at: Time.now.utc.to_s
79
+ }
80
+ "server#{id}"
81
+ end
82
+
83
+ def delete_server(server_id)
84
+ id = server_id.sub(/^server/, '').to_i
85
+ raise "Nonexistent server '#{server_id}'" if @servers[id].nil?
86
+
87
+ ip = @server_to_ip_map[server_id]
88
+ if ip != nil
89
+ raise "Cannot delete while connected to #{ip}"
90
+ end
91
+
92
+ @servers[id] = nil
93
+ end
94
+
95
+ def exists_server?(server_id)
96
+ id = server_id.sub(/^server/, '').to_i
97
+ @servers.key? id
98
+ end
99
+
100
+ def server(server_id)
101
+ id = server_id.sub(/^server/, '').to_i
102
+ raise "Nonexistent server '#{server_id}'" if @servers[id].nil?
103
+
104
+ @servers[id]
105
+ end
106
+
107
+ def create_ip(server_id)
108
+ id = server_id.sub(/^server/, '').to_i
109
+ raise "Nonexistent server '#{server_id}'" if @servers[id].nil?
110
+
111
+ (2..254).each do |i|
112
+ addr = "2.3.4.#{i}"
113
+ next if @ip_addresses.key? addr
114
+
115
+ return modify_ip(addr, server_id)
116
+ end
117
+
118
+ raise 'No more ips available'
119
+ end
120
+
121
+ def modify_ip(addr, server_id)
122
+ id = server_id.sub(/^server/, '').to_i
123
+ raise "Nonexistent server '#{server_id}'" if @servers[id].nil?
124
+ raise "Nonexistent IP #{addr}" if !@ip_addresses.key? addr
125
+
126
+ @ip_addresses[addr] = server_id
127
+ @server_to_ip_map[server_id] = addr
128
+ end
129
+
130
+ def delete_ip(addr)
131
+ raise "Nonexistent IP #{addr}" if !@ip_addresses.key? addr
132
+
133
+ server_id = @ip_addresses[addr]
134
+ @server_to_ip_map.delete(server_id)
135
+ @ip_addresses.delete(addr)
136
+ end
137
+ end
138
+
139
+ # base class of resource
140
+ class TestFileResource < Tataru::BaseResource
141
+ def create(params)
142
+ TestEnvironment.instance.create_file(params[:name], params[:contents])
143
+ @remote_id = params[:name]
144
+ end
145
+
146
+ def read(name_array)
147
+ results = {}
148
+ TestEnvironment.instance.file(@remote_id).each do |k, v|
149
+ results[k] = v if name_array.include? k
150
+ end
151
+ results
152
+ end
153
+
154
+ def update(params)
155
+ TestEnvironment.instance.update_file(@remote_id, params[:contents])
156
+ end
157
+
158
+ def delete
159
+ TestEnvironment.instance.delete_file(@remote_id)
160
+ end
161
+
162
+ def outputs
163
+ TestEnvironment.instance.file(@remote_id)
164
+ end
165
+
166
+ def create_complete?
167
+ # check if creation is complete
168
+ true
169
+ end
170
+
171
+ def update_complete?
172
+ # check if update is complete
173
+ true
174
+ end
175
+
176
+ def delete_complete?
177
+ # check if delete is complete
178
+ true
179
+ end
180
+ end
181
+
182
+ # description of a resource
183
+ class TestFileResourceDesc < Tataru::BaseResourceDesc
184
+ def resource_class
185
+ TestFileResource
186
+ end
187
+
188
+ def mutable_fields
189
+ [:contents]
190
+ end
191
+
192
+ def immutable_fields
193
+ [:name]
194
+ end
195
+
196
+ def required_fields
197
+ [:name]
198
+ end
199
+
200
+ def output_fields
201
+ [:created_at, :updated_at]
202
+ end
203
+
204
+ def needs_remote_id?
205
+ true
206
+ end
207
+
208
+ def delete_at_end?
209
+ false
210
+ end
211
+ end
212
+
213
+ # base class of resource
214
+ class TestServerResource < Tataru::BaseResource
215
+ def create(params)
216
+ @remote_id = TestEnvironment.instance.create_server(params[:size])
217
+ end
218
+
219
+ def read(name_array)
220
+ results = {}
221
+ TestEnvironment.instance.server(@remote_id).each do |k, v|
222
+ results[k] = v if name_array.include? k
223
+ end
224
+ results
225
+ end
226
+
227
+ def update(params)
228
+ end
229
+
230
+ def delete
231
+ TestEnvironment.instance.delete_server(@remote_id)
232
+ end
233
+
234
+ def outputs
235
+ TestEnvironment.instance.server(@remote_id)
236
+ end
237
+
238
+ def create_complete?
239
+ # check if creation is complete
240
+ true
241
+ end
242
+
243
+ def update_complete?
244
+ # check if update is complete
245
+ true
246
+ end
247
+
248
+ def delete_complete?
249
+ # check if delete is complete
250
+ true
251
+ end
252
+ end
253
+
254
+ # description of a resource
255
+ class TestServerResourceDesc < Tataru::BaseResourceDesc
256
+ def resource_class
257
+ TestServerResource
258
+ end
259
+
260
+ def mutable_fields
261
+ []
262
+ end
263
+
264
+ def immutable_fields
265
+ [:size]
266
+ end
267
+
268
+ def required_fields
269
+ [:size]
270
+ end
271
+
272
+ def output_fields
273
+ [:created_at]
274
+ end
275
+
276
+ def needs_remote_id?
277
+ true
278
+ end
279
+
280
+ def delete_at_end?
281
+ true
282
+ end
283
+ end
284
+
285
+ # string joiner
286
+ class StringJoinerResource < Tataru::BaseResource
287
+ attr_reader :remote_id
288
+
289
+ def initialize(remote_id)
290
+ @remote_id = remote_id
291
+ end
292
+
293
+ def create(params)
294
+ @remote_id = params[:strings].join("\n")
295
+ end
296
+
297
+ def outputs
298
+ {
299
+ result: @remote_id
300
+ }
301
+ end
302
+ end
303
+
304
+ # description of a StringJoinerResource
305
+ class StringJoinerResourceDesc < Tataru::BaseResourceDesc
306
+ def resource_class
307
+ StringJoinerResource
308
+ end
309
+
310
+ def immutable_fields
311
+ [:strings]
312
+ end
313
+
314
+ def output_fields
315
+ [:result]
316
+ end
317
+
318
+ def required_fields
319
+ [:strings]
320
+ end
321
+
322
+ def needs_remote_id?
323
+ true
324
+ end
325
+
326
+ def delete_at_end?
327
+ false
328
+ end
329
+ end
330
+
331
+ class TestIpAddressResource < Tataru::BaseResource
332
+ def create(params)
333
+ ip = TestEnvironment.instance.create_ip(params[:server_id])
334
+ @remote_id = ip
335
+ end
336
+
337
+ def read(name_array)
338
+ {
339
+ server_id: TestEnvironment.instance.ip_addresses[@remote_id]
340
+ }
341
+ end
342
+
343
+ def update(params)
344
+ TestEnvironment.instance.modify_ip(@remote_id, params[:server_id])
345
+ end
346
+
347
+ def delete
348
+ TestEnvironment.instance.delete_ip(@remote_id)
349
+ end
350
+
351
+ def outputs
352
+ {
353
+ server_id: TestEnvironment.instance.ip_addresses[@remote_id]
354
+ }
355
+ end
356
+
357
+ def create_complete?
358
+ # check if creation is complete
359
+ true
360
+ end
361
+
362
+ def update_complete?
363
+ # check if update is complete
364
+ true
365
+ end
366
+
367
+ def delete_complete?
368
+ # check if delete is complete
369
+ true
370
+ end
371
+ end
372
+
373
+ class TestIpAddressResourceDesc < Tataru::BaseResourceDesc
374
+ def resource_class
375
+ TestIpAddressResource
376
+ end
377
+
378
+ def mutable_fields
379
+ [:server_id]
380
+ end
381
+
382
+ def immutable_fields
383
+ []
384
+ end
385
+
386
+ def required_fields
387
+ [:server_id]
388
+ end
389
+
390
+ def output_fields
391
+ [:ip]
392
+ end
393
+
394
+ def needs_remote_id?
395
+ true
396
+ end
397
+
398
+ def delete_at_end?
399
+ false
400
+ end
401
+ end