simmer 1.0.0.pre.alpha.3 → 1.0.0.pre.alpha.4

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +5 -0
  4. data/lib/simmer.rb +103 -9
  5. data/lib/simmer/configuration.rb +7 -17
  6. data/lib/simmer/database.rb +10 -0
  7. data/lib/simmer/{util → database}/fixture.rb +7 -3
  8. data/lib/simmer/{util → database}/fixture_set.rb +10 -4
  9. data/lib/simmer/externals/aws_file_system.rb +30 -23
  10. data/lib/simmer/externals/mysql_database.rb +17 -10
  11. data/lib/simmer/externals/spoon_client.rb +5 -19
  12. data/lib/simmer/runner.rb +2 -2
  13. data/lib/simmer/specification/act.rb +1 -6
  14. data/lib/simmer/specification/assert/assertions/table.rb +1 -6
  15. data/lib/simmer/spoon_mock.rb +35 -0
  16. data/lib/simmer/suite.rb +49 -43
  17. data/lib/simmer/{session → suite}/reporter.rb +1 -1
  18. data/lib/simmer/{session → suite}/result.rb +1 -1
  19. data/lib/simmer/util.rb +0 -1
  20. data/lib/simmer/util/evaluator.rb +4 -5
  21. data/lib/simmer/util/record.rb +2 -0
  22. data/lib/simmer/util/record_set.rb +5 -1
  23. data/lib/simmer/util/resolver.rb +2 -2
  24. data/lib/simmer/util/yaml_reader.rb +9 -12
  25. data/lib/simmer/version.rb +1 -1
  26. data/spec/config/simmer.yaml.ci +7 -0
  27. data/spec/db/database.sql +1 -0
  28. data/spec/db/tables.sql +20 -0
  29. data/spec/db_helper.rb +26 -0
  30. data/spec/fixtures/agent_fixtures.yaml +14 -0
  31. data/spec/fixtures/configuration.yaml +11 -0
  32. data/spec/fixtures/noc_list.csv +3 -0
  33. data/spec/fixtures/specifications/load_noc_list.yaml +30 -0
  34. data/spec/fixtures/yaml_reader/bar.yaml +2 -0
  35. data/spec/fixtures/yaml_reader/baz/baz.yaml +2 -0
  36. data/spec/fixtures/yaml_reader/foo.yaml +2 -0
  37. data/spec/simmer/configuration_spec.rb +46 -0
  38. data/spec/simmer/database/fixture_set_spec.rb +75 -0
  39. data/spec/simmer/database/fixture_spec.rb +57 -0
  40. data/spec/simmer/externals/aws_file_system_spec.rb +75 -0
  41. data/spec/simmer/externals/mysql_database_spec.rb +79 -0
  42. data/spec/simmer/externals/spoon_client_spec.rb +67 -0
  43. data/spec/simmer/specification/act/params_spec.rb +38 -0
  44. data/spec/simmer/specification/act_spec.rb +37 -0
  45. data/spec/simmer/specification/assert_spec.rb +27 -0
  46. data/spec/simmer/specification/stage_spec.rb +32 -0
  47. data/spec/simmer/specification_spec.rb +28 -0
  48. data/spec/simmer/util/evaluator_spec.rb +82 -0
  49. data/spec/simmer/util/record_set_spec.rb +41 -0
  50. data/spec/simmer/util/record_spec.rb +218 -0
  51. data/spec/simmer/util/yaml_reader_spec.rb +49 -0
  52. data/spec/spec_helper.rb +21 -0
  53. metadata +60 -8
  54. data/lib/simmer/externals/spoon_client/mock.rb +0 -39
  55. data/lib/simmer/session.rb +0 -79
@@ -0,0 +1,3 @@
1
+ call_sign,first,last
2
+ iron_man,Tony,Stark
3
+ hulk,Bruce,Banner
@@ -0,0 +1,30 @@
1
+ name: Declassify Users
2
+ stage:
3
+ files:
4
+ src: noc_list.csv
5
+ dest: input/noc_list.csv
6
+ fixtures:
7
+ - iron_man
8
+ - hulk
9
+ act:
10
+ name: load_noc_list
11
+ repository: top_secret
12
+ type: transformation
13
+ params:
14
+ files:
15
+ input_file: noc_list.csv
16
+ keys:
17
+ code: 'The secret code is: {codes.the_secret_one}'
18
+ assert:
19
+ assertions:
20
+ - type: table
21
+ name: agents
22
+ records:
23
+ - call_sign: iron_man
24
+ first: tony
25
+ last: stark
26
+ - call_sign: hulk
27
+ first: bruce
28
+ last: banner
29
+ - type: output
30
+ value: Decoding Agents
@@ -0,0 +1,2 @@
1
+ bar:
2
+ type: barby
@@ -0,0 +1,2 @@
1
+ baz:
2
+ type: bazzy
@@ -0,0 +1,2 @@
1
+ foo:
2
+ type: foofy
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ require 'spec_helper'
11
+
12
+ describe Simmer::Configuration do
13
+ let(:path) { File.join('configuration.yaml') }
14
+ let(:config) { yaml_fixture(path) }
15
+ let(:simmer_dir) { 'simmer' }
16
+
17
+ subject { described_class.new(config, simmer_dir) }
18
+
19
+ specify '#mysql_database_config resolves' do
20
+ expect(subject.mysql_database_config).to eq('mysql_database_key' => 'mysql_database_value')
21
+ end
22
+
23
+ specify '#aws_file_system_config resolves' do
24
+ expect(subject.aws_file_system_config).to eq('aws_file_system_key' => 'aws_file_system_value')
25
+ end
26
+
27
+ specify '#spoon_client_config resolves' do
28
+ expect(subject.spoon_client_config).to eq('spoon_client_key' => 'spoon_client_value')
29
+ end
30
+
31
+ specify '#tests_dir resolves' do
32
+ expect(subject.tests_dir).to eq(File.join(simmer_dir, 'specs'))
33
+ end
34
+
35
+ specify '#fixtures_dir resolves' do
36
+ expect(subject.fixtures_dir).to eq(File.join(simmer_dir, 'fixtures'))
37
+ end
38
+
39
+ specify '#files_dir resolves' do
40
+ expect(subject.files_dir).to eq(File.join(simmer_dir, 'files'))
41
+ end
42
+
43
+ specify '#results_dir resolves' do
44
+ expect(subject.results_dir).to eq(File.join(simmer_dir, 'results'))
45
+ end
46
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ require 'spec_helper'
11
+
12
+ describe Simmer::Database::FixtureSet do
13
+ let(:config) do
14
+ {
15
+ 'Some Fixture' => {
16
+ fields: {
17
+ first: 'Frank',
18
+ last: 'Rizzo'
19
+ },
20
+ table: 'users'
21
+ },
22
+ bozo: {
23
+ fields: {
24
+ first: 'Bozo',
25
+ last: 'The Clown'
26
+ },
27
+ table: 'users'
28
+ }
29
+ }
30
+ end
31
+
32
+ subject { described_class.new(config) }
33
+
34
+ describe '#get!' do
35
+ context 'when name is a string' do
36
+ it 'returns Fixture if name exists' do
37
+ name = 'Some Fixture'
38
+
39
+ expected = Simmer::Database::Fixture.make(config[name.to_s].merge(name: name))
40
+
41
+ expect(subject.get!(name)).to eq(expected)
42
+
43
+ name = 'bozo'
44
+
45
+ expected = Simmer::Database::Fixture.make(config[name.to_sym].merge(name: name))
46
+
47
+ expect(subject.get!(name)).to eq(expected)
48
+ end
49
+
50
+ it 'raises ArgumentError if name does not exist' do
51
+ expect { subject.get!(:doesnt_exist) }.to raise_error(ArgumentError)
52
+ end
53
+ end
54
+
55
+ context 'when name is a symbol' do
56
+ it 'returns Fixture if name exists' do
57
+ name = :'Some Fixture'
58
+
59
+ expected = Simmer::Database::Fixture.make(config[name.to_s].merge(name: name))
60
+
61
+ expect(subject.get!(name)).to eq(expected)
62
+
63
+ name = :bozo
64
+
65
+ expected = Simmer::Database::Fixture.make(config[name.to_sym].merge(name: name))
66
+
67
+ expect(subject.get!(name)).to eq(expected)
68
+ end
69
+
70
+ it 'raises ArgumentError if name does not exist' do
71
+ expect { subject.get!(:doesnt_exist) }.to raise_error(ArgumentError)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ require 'spec_helper'
11
+
12
+ describe Simmer::Database::Fixture do
13
+ let(:config) do
14
+ {
15
+ fields: {
16
+ first: 'Frank',
17
+ last: 'Rizzo'
18
+ },
19
+ name: 'Some Fixture',
20
+ table: 'users'
21
+ }
22
+ end
23
+
24
+ describe 'initialization' do
25
+ context 'when using acts_as_hashable' do
26
+ subject { described_class.make(config) }
27
+
28
+ it 'sets fields' do
29
+ expect(subject.fields).to eq(config[:fields])
30
+ end
31
+
32
+ it 'sets name' do
33
+ expect(subject.name).to eq(config[:name])
34
+ end
35
+
36
+ it 'sets table' do
37
+ expect(subject.table).to eq(config[:table])
38
+ end
39
+ end
40
+ end
41
+
42
+ describe 'equality' do
43
+ subject { described_class.new(config) }
44
+
45
+ specify '#== compares all attributes' do
46
+ subject2 = described_class.new(config)
47
+
48
+ expect(subject).to eq(subject2)
49
+ end
50
+
51
+ specify '#eql? compares all attributes' do
52
+ subject2 = described_class.new(config)
53
+
54
+ expect(subject).to eql(subject2)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ require 'spec_helper'
11
+
12
+ describe Simmer::Externals::AwsFileSystem do
13
+ let(:bucket_store) { {} }
14
+ let(:bucket_name) { 'test' }
15
+ let(:encryption) { 'AES256' }
16
+ let(:files_dir) { File.join('spec', 'fixtures') }
17
+ let(:specification_path) { File.join('specifications', 'load_noc_list.yaml') }
18
+ let(:specification_config) { yaml_fixture(specification_path).merge(path: specification_path) }
19
+ let(:specification) { Simmer::Specification.make(specification_config) }
20
+
21
+ let(:aws_s3_client_stub) do
22
+ Aws::S3::Client.new(stub_responses: true).tap do |client|
23
+ client.stub_responses(:get_object, lambda { |context|
24
+ obj = bucket_store[context.params[:key]]
25
+ obj || 'NoSuchKey'
26
+ })
27
+
28
+ client.stub_responses(:put_object, lambda { |context|
29
+ bucket_store[context.params[:key]] = { body: context.params[:body] }
30
+ {}
31
+ })
32
+
33
+ client.stub_responses(:list_objects, lambda { |_context|
34
+ contents = bucket_store.keys.map { |k| OpenStruct.new(key: k) }
35
+
36
+ OpenStruct.new(contents: contents)
37
+ })
38
+
39
+ client.stub_responses(:delete_objects, lambda { |context|
40
+ keys = context.params.dig(:delete, :objects).map { |k| k[:key] }
41
+
42
+ keys.each { |key| bucket_store.delete(key) }
43
+ })
44
+ end
45
+ end
46
+
47
+ subject { described_class.new(aws_s3_client_stub, bucket_name, encryption, files_dir) }
48
+
49
+ specify '#write transfers all files' do
50
+ subject.write!(specification)
51
+
52
+ expected = {
53
+ 'input/noc_list.csv' => {
54
+ body: "call_sign,first,last\niron_man,Tony,Stark\nhulk,Bruce,Banner\n"
55
+ }
56
+ }
57
+
58
+ expect(bucket_store).to eq(expected)
59
+ end
60
+
61
+ specify '#clean! deletes all files' do
62
+ aws_s3_client_stub.put_object(
63
+ body: 'Test File',
64
+ bucket: bucket_name,
65
+ key: 'test_key.txt',
66
+ server_side_encryption: encryption
67
+ )
68
+
69
+ subject.clean!
70
+
71
+ expected = {}
72
+
73
+ expect(bucket_store).to eq(expected)
74
+ end
75
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ require 'spec_helper'
11
+ require 'db_helper'
12
+
13
+ describe Simmer::Externals::MysqlDatabase do
14
+ let(:exclude_tables) { [] }
15
+ let(:raw_fixtures) { yaml_read('spec', 'fixtures', 'agent_fixtures.yaml') }
16
+ let(:fixture_set) { Simmer::Database::FixtureSet.new(raw_fixtures) }
17
+ let(:spec_path) { File.join('specifications', 'load_noc_list.yaml') }
18
+ let(:spec_config) { yaml_fixture(spec_path).merge(path: spec_path) }
19
+ let(:specification) { Simmer::Specification.make(spec_config) }
20
+
21
+ subject { described_class.new(db_helper_client, exclude_tables, fixture_set) }
22
+
23
+ before(:each) do
24
+ db_helper_clean_schema
25
+ end
26
+
27
+ specify '#seed! adds records' do
28
+ subject.seed!(specification)
29
+
30
+ actual = db_helper_client.query('SELECT * FROM agents ORDER BY call_sign').to_a
31
+
32
+ call_signs = actual.map { |r| r['call_sign'] }
33
+
34
+ expect(call_signs).to eq(%w[hulk iron_man])
35
+ end
36
+
37
+ specify '#clean! removes all records without worrying about foreign keys' do
38
+ db_helper_client.query("INSERT INTO agents (id, call_sign) VALUES (1, 'thor')")
39
+ db_helper_client.query("INSERT INTO notes (agent_id, note) VALUES (1, 'thor')")
40
+
41
+ agent_count = db_helper_client.query('SELECT * FROM agents').to_a.length
42
+ note_count = db_helper_client.query('SELECT * FROM notes').to_a.length
43
+
44
+ expect(agent_count).to eq(1)
45
+ expect(note_count).to eq(1)
46
+
47
+ table_count = subject.clean!
48
+
49
+ expect(table_count).to eq(2)
50
+ end
51
+
52
+ describe '#records' do
53
+ before(:each) do
54
+ db_helper_client.query("INSERT INTO agents (id, call_sign) VALUES (1, 'thor')")
55
+ db_helper_client.query("INSERT INTO agents (id, call_sign) VALUES (2, 'black_widow')")
56
+ end
57
+
58
+ specify 'when fields is empty' do
59
+ actual = subject.records(:agents)
60
+
61
+ expected = [
62
+ {
63
+ 'id' => 1,
64
+ 'call_sign' => 'thor',
65
+ 'first' => nil,
66
+ 'last' => nil
67
+ },
68
+ {
69
+ 'id' => 2,
70
+ 'call_sign' => 'black_widow',
71
+ 'first' => nil,
72
+ 'last' => nil
73
+ }
74
+ ]
75
+
76
+ expect(actual).to eq(expected)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright (c) 2020-present, Blue Marble Payroll, LLC
5
+ #
6
+ # This source code is licensed under the MIT license found in the
7
+ # LICENSE file in the root directory of this source tree.
8
+ #
9
+
10
+ require 'spec_helper'
11
+ require 'db_helper'
12
+
13
+ describe Simmer::Externals::SpoonClient do
14
+ class Mock
15
+ attr_reader :result
16
+
17
+ def initialize(result)
18
+ @result = result
19
+ end
20
+
21
+ def run(*)
22
+ raise Pdi::Spoon::KitchenError, OpenStruct.new(code: 1) if result == 'KitchenError'
23
+ raise Pdi::Spoon::PanError, OpenStruct.new(code: 1) if result == 'PanError'
24
+
25
+ Pdi::Executor::Result.new(result)
26
+ end
27
+ end
28
+
29
+ let(:files_dir) { File.join('spec', 'fixtures') }
30
+ let(:specification_path) { File.join('specifications', 'load_noc_list.yaml') }
31
+ let(:specification_config) { yaml_fixture(specification_path).merge(path: specification_path) }
32
+ let(:specification) { Simmer::Specification.make(specification_config) }
33
+
34
+ subject { described_class.new(files_dir, spoon) }
35
+
36
+ context 'when PDI executes successfully' do
37
+ let(:spoon) do
38
+ Mock.new(
39
+ args: [],
40
+ status: {
41
+ code: 0,
42
+ err: 'Some error output from PDI',
43
+ out: 'Some output from PDI',
44
+ pid: 123
45
+ }
46
+ )
47
+ end
48
+
49
+ specify '#run is called with the right arguments' do
50
+ expected_path = File.expand_path(File.join(files_dir, 'noc_list.csv'))
51
+
52
+ args = {
53
+ repository: 'top_secret',
54
+ name: 'load_noc_list',
55
+ params: {
56
+ 'input_file' => expected_path,
57
+ 'code' => 'The secret code is: '
58
+ },
59
+ type: 'transformation'
60
+ }
61
+
62
+ expect(spoon).to receive(:run).with(args)
63
+
64
+ subject.run(specification, simmer_config)
65
+ end
66
+ end
67
+ end