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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +5 -0
- data/lib/simmer.rb +103 -9
- data/lib/simmer/configuration.rb +7 -17
- data/lib/simmer/database.rb +10 -0
- data/lib/simmer/{util → database}/fixture.rb +7 -3
- data/lib/simmer/{util → database}/fixture_set.rb +10 -4
- data/lib/simmer/externals/aws_file_system.rb +30 -23
- data/lib/simmer/externals/mysql_database.rb +17 -10
- data/lib/simmer/externals/spoon_client.rb +5 -19
- data/lib/simmer/runner.rb +2 -2
- data/lib/simmer/specification/act.rb +1 -6
- data/lib/simmer/specification/assert/assertions/table.rb +1 -6
- data/lib/simmer/spoon_mock.rb +35 -0
- data/lib/simmer/suite.rb +49 -43
- data/lib/simmer/{session → suite}/reporter.rb +1 -1
- data/lib/simmer/{session → suite}/result.rb +1 -1
- data/lib/simmer/util.rb +0 -1
- data/lib/simmer/util/evaluator.rb +4 -5
- data/lib/simmer/util/record.rb +2 -0
- data/lib/simmer/util/record_set.rb +5 -1
- data/lib/simmer/util/resolver.rb +2 -2
- data/lib/simmer/util/yaml_reader.rb +9 -12
- data/lib/simmer/version.rb +1 -1
- data/spec/config/simmer.yaml.ci +7 -0
- data/spec/db/database.sql +1 -0
- data/spec/db/tables.sql +20 -0
- data/spec/db_helper.rb +26 -0
- data/spec/fixtures/agent_fixtures.yaml +14 -0
- data/spec/fixtures/configuration.yaml +11 -0
- data/spec/fixtures/noc_list.csv +3 -0
- data/spec/fixtures/specifications/load_noc_list.yaml +30 -0
- data/spec/fixtures/yaml_reader/bar.yaml +2 -0
- data/spec/fixtures/yaml_reader/baz/baz.yaml +2 -0
- data/spec/fixtures/yaml_reader/foo.yaml +2 -0
- data/spec/simmer/configuration_spec.rb +46 -0
- data/spec/simmer/database/fixture_set_spec.rb +75 -0
- data/spec/simmer/database/fixture_spec.rb +57 -0
- data/spec/simmer/externals/aws_file_system_spec.rb +75 -0
- data/spec/simmer/externals/mysql_database_spec.rb +79 -0
- data/spec/simmer/externals/spoon_client_spec.rb +67 -0
- data/spec/simmer/specification/act/params_spec.rb +38 -0
- data/spec/simmer/specification/act_spec.rb +37 -0
- data/spec/simmer/specification/assert_spec.rb +27 -0
- data/spec/simmer/specification/stage_spec.rb +32 -0
- data/spec/simmer/specification_spec.rb +28 -0
- data/spec/simmer/util/evaluator_spec.rb +82 -0
- data/spec/simmer/util/record_set_spec.rb +41 -0
- data/spec/simmer/util/record_spec.rb +218 -0
- data/spec/simmer/util/yaml_reader_spec.rb +49 -0
- data/spec/spec_helper.rb +21 -0
- metadata +60 -8
- data/lib/simmer/externals/spoon_client/mock.rb +0 -39
- data/lib/simmer/session.rb +0 -79
@@ -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,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
|