kerbi 0.0.1

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.
@@ -0,0 +1,181 @@
1
+ module Kerbi
2
+ module Utils
3
+ module Mixing
4
+
5
+ ##
6
+ # Parses and interpolates YAML or JSON dicts and outputs
7
+ # their symbol-keyed Hash forms.
8
+ # @param [String] yaml_str plain yaml, json, or erb string
9
+ # @param [Hash] extras additional hash passed to ERB
10
+ # @return [Array<Hash>] list of inflated dicts
11
+ def self.yaml_str_to_dicts(yaml_str, opts={})
12
+ interpolated_yaml = self.interpolate_erb_string(yaml_str, **opts)
13
+ hashes = YAML.load_stream(interpolated_yaml)
14
+ self.clean_and_filter_dicts(hashes, **opts)
15
+ end
16
+
17
+ ##
18
+ # Loads a YAML/JSON/ERB file, parses it, interpolates it,
19
+ # and returns the resulting dicts.
20
+ # @param [String] fname simplified or absolute path of file
21
+ # @param [Hash] extras additional hash passed to ERB
22
+ # @return [Array<Hash>] list of res-hashes
23
+ def self.yaml_file_to_dicts(fname, opts={})
24
+ contents = File.read(fname)
25
+ begin
26
+ self.yaml_str_to_dicts(contents, **opts)
27
+ rescue Exception => e
28
+ STDERR.puts "Exception below from file #{fname}"
29
+ raise e
30
+ end
31
+ end
32
+
33
+ ##
34
+ # Performs ERB interpolation on an ERB string, and returns
35
+ # the interpolated string.
36
+ # @param [String] yaml_str contents of a yaml or yaml.erb
37
+ # @param [Hash] opts an additional hash available to ERB
38
+ # @return [String] the interpolated string
39
+ def self.interpolate_erb_string(yaml_str, opts={})
40
+ final_binding = opts[:src_binding] || binding
41
+ final_binding.local_variable_set(:extras, opts[:extras] || {})
42
+ ERB.new(yaml_str).result(final_binding)
43
+ end
44
+
45
+ ##
46
+ # Loads, interpolates, and parses all dicts found in all YAML/JSON/ERB
47
+ # files in a given directory.
48
+ # @param [String] dir relative or absolute path of the directory
49
+ # @param [Array<String>] file_blacklist list of filenames to avoid
50
+ # @return [Array<Hash>] array of processed dicts
51
+ def self.yamls_in_dir_to_dicts(pwd, dir, opts={})
52
+ file_blacklist = opts.delete(:file_blacklist)
53
+ blacklist = file_blacklist || []
54
+
55
+ dir ||= pwd
56
+ dir = "#{pwd}/#{dir}" if dir && pwd && dir.start_with?(".")
57
+ yaml_files = Dir["#{dir}/*.yaml"]
58
+ erb_files = Dir["#{dir}/*.yaml.erb"]
59
+
60
+ (yaml_files + erb_files).map do |fname|
61
+ is_blacklisted = blacklist.include?(File.basename(fname))
62
+ unless is_blacklisted
63
+ self.yaml_file_to_dicts(fname, **opts)
64
+ end
65
+ end.compact.flatten
66
+ end
67
+
68
+ ##
69
+ # Turns hashes into symbol-keyed hashes,
70
+ # and applies white/blacklisting based on filters supplied
71
+ # @param [Array<Hash>] dicts list of inflated hashes
72
+ # @param [Array<String>] white_rules list/single k8s res ID to whitelist
73
+ # @param [Array<String>] black_rules list/single k8s res ID to blacklist
74
+ # @return [Array<Hash>] list of clean and filtered hashes
75
+ def self.clean_and_filter_dicts(dicts, opts={})
76
+ white_rules = opts[:white_rules] || opts[:only]
77
+ black_rules = opts[:black_rules] || opts[:except]
78
+ _dicts = self.hash_to_cloned_hashes(dicts)
79
+ _dicts = _dicts.compact.map(&:deep_symbolize_keys).to_a
80
+ _dicts = self.select_res_dicts_whitelist(_dicts, white_rules)
81
+ _dicts = self.select_res_dicts_blacklist(_dicts, black_rules)
82
+ self.sanitize_res_dict_list(_dicts)
83
+ end
84
+
85
+ def self.sanitize_res_dict_list(res_dicts)
86
+ pushable_list = nil
87
+ if res_dicts.is_a?(Array)
88
+ pushable_list = res_dicts
89
+ elsif res_dicts.is_a?(Hash)
90
+ pushable_list = [res_dicts]
91
+ end
92
+
93
+ if pushable_list.present?
94
+ #noinspection RubyNilAnalysis
95
+ pushable_list.select do |item|
96
+ item.present? && item.is_a?(Hash)
97
+ end.map(&:deep_symbolize_keys).compact
98
+ else
99
+ []
100
+ end
101
+ end
102
+
103
+ ##
104
+ # @return [Array<Hash>] list of clean and filtered hashes
105
+ def self.hash_to_cloned_hashes(hashes)
106
+ if !hashes.is_a?(Array)
107
+ [hashes]
108
+ else
109
+ hashes
110
+ end
111
+ end
112
+
113
+ ##
114
+ # Returns res dicts that match one or more rules
115
+ # @param [Array<Hash>] res_dicts k8s res-hashes
116
+ # @param [Array<String>] rule_dicts list of simple k8s res-ids by which to filter
117
+ # @return [Array<Hash>] list of clean and filtered hashes
118
+ def self.select_res_dicts_whitelist(res_dicts, rule_dicts)
119
+ _res_dicts = res_dicts.compact.map(&:deep_symbolize_keys).to_a
120
+ return _res_dicts if (rule_dicts || []).compact.empty?
121
+ _res_dicts.select do |res_dict|
122
+ rule_dicts.any? do |rule_dict|
123
+ self.res_dict_matches_rule?(res_dict, rule_dict)
124
+ end
125
+ end
126
+ end
127
+
128
+ ##
129
+ # Returns res dicts that match zero rules
130
+ # @param [Array<Hash>] res_dicts k8s res-hashes
131
+ # @param [Array<String>] rule_dicts list of simple k8s res-ids by which to filter
132
+ # @return [Array<Hash>] list of clean and filtered hashes
133
+ def self.select_res_dicts_blacklist(res_dicts, rule_dicts)
134
+ _res_dicts = res_dicts.compact.map(&:deep_symbolize_keys).to_a
135
+ return _res_dicts if (rule_dicts || []).compact.empty?
136
+ _res_dicts.reject do |res_dict|
137
+ rule_dicts.any? do |rule_dict|
138
+ self.res_dict_matches_rule?(res_dict, rule_dict)
139
+ end
140
+ end
141
+ end
142
+
143
+ ##
144
+ # Checks whether a dict, assumed to be a Kubernetes resource,
145
+ # matches a kerbi resource selection rule.
146
+ # @param [Hash] res_dict the Kubernetes-style resource dict
147
+ # @param [Hash] rule_dict the kerbi resource selector dict
148
+ # @return [TrueClass, FalseClass] true if the selector selects the resource
149
+ def self.res_dict_matches_rule?(res_dict, rule_dict)
150
+ return false unless res_dict.is_a?(Hash)
151
+ return false unless res_dict.present?
152
+
153
+ return false unless rule_dict.is_a?(Hash)
154
+ return false unless rule_dict.present?
155
+
156
+ target_kind = rule_dict[:kind].presence
157
+ target_name = rule_dict[:name].presence
158
+ if !target_kind || self.str_cmp(target_kind, res_dict[:kind])
159
+ wild = !target_name || target_name == "*"
160
+ res_name = res_dict[:metadata]&.[](:name)
161
+ wild || self.str_cmp(target_name, res_name)
162
+ end
163
+ end
164
+
165
+ ##
166
+ # Checks whether the value matching string given in a kerbi
167
+ # resource selector dict matches the value of the attribute
168
+ # in the Kubernetes-style resource dict. Works by performing
169
+ # a regex check on the two values with a full stop e.g ^$.
170
+ # @param [String] rule_str the regex to test the candidate string
171
+ # @param [String] actual_str the candidate string being tested
172
+ # @return [TrueClass, FalseClass] true if the rule matches the input
173
+ def self.str_cmp(rule_str, actual_str)
174
+ final_regex = Regexp.new("^#{rule_str}$")
175
+ match_result = actual_str =~ final_regex
176
+ !match_result.nil?
177
+ end
178
+
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,133 @@
1
+ module Kerbi
2
+ module Utils
3
+ ##
4
+ # Utilities module for all value loading functionality.
5
+ module Values
6
+
7
+ DEFAULT_VALUE_PATH = "values"
8
+
9
+ def self.from_files(fname_exprs, **opts)
10
+ final_paths = resolve_fname_exprs(fname_exprs, **opts)
11
+ load_yaml_files(final_paths)
12
+ end
13
+
14
+ ##
15
+ # Resolves each filename expression given, returning an array
16
+ # of absolute paths. Automatically prepends the default values filename
17
+ # - values.yaml - to the list and does not complain if it does not exist.
18
+ # If two or more filename expressions resolve to the same absolute path,
19
+ # only one copy will be in the list.
20
+ # @param [Array<String>] fname_exprs cli-level values file path names
21
+ # @param [Hash] opts downstream options for file-loading methods
22
+ # @return [Array<String>] list of unique absolute filenames
23
+ def self.resolve_fname_exprs(fname_exprs, **opts)
24
+ final_exprs = [self::DEFAULT_VALUE_PATH, *fname_exprs].uniq
25
+ final_exprs.map do |fname_expr|
26
+ path = resolve_fname_expr(fname_expr, **opts)
27
+ if fname_expr != 'values' && !path
28
+ raise "Could not resolve file '#{fname_expr}'"
29
+ end
30
+ path.presence
31
+ end.compact.uniq
32
+ end
33
+
34
+ ##
35
+ # Loads the dicts from files pointed to by final_file_paths into
36
+ # memory, and returns the deep-merged hash in the order of the files.
37
+ # @param [Array<String>] final_file_paths absolute filenames
38
+ # of value assignment files
39
+ def self.load_yaml_files(final_file_paths)
40
+ final_file_paths.inject({}) do |whole, fname|
41
+ file_values = self.load_yaml_file(fname)
42
+ whole.deep_merge(file_values)
43
+ end
44
+ end
45
+
46
+ ##
47
+ # Parses and merges cli-level key-value assignments of the form
48
+ # foo.bar=baz.
49
+ # @param [Array<String>] inline_exprs e.g %w[foo=bar, foo.bar=baz]
50
+ def self.from_inlines(inline_exprs)
51
+ inline_exprs.inject({}) do |whole, str_assignment|
52
+ assignment = self.parse_inline_assignment(str_assignment)
53
+ whole.deep_merge(assignment)
54
+ end
55
+ end
56
+
57
+ ##
58
+ # Turns a user supplied values filename into a final, usable
59
+ # absolute filesystem path. This method calls the values_paths method,
60
+ # which assumes a kerbi directory structure.
61
+ # @param [String] expr
62
+ # @param [Hash] opts
63
+ # @return [?String] the absolute filename or nil if it does not exist
64
+ def self.resolve_fname_expr(expr, **opts)
65
+ candidate_paths = self.values_paths(expr, **opts)
66
+ candidate_paths.find do |candidate_path|
67
+ File.exists?(candidate_path) && \
68
+ !File.directory?(candidate_path)
69
+ end
70
+ end
71
+
72
+ ##
73
+ # Parses a single cli-level key-value assignment with the form
74
+ # foo.bar=baz. Raises an exception if the expression is malformed.
75
+ # @param [String] str_assign e.g foo=bar
76
+ # @return [Hash] corresponding symbol hash e.g {foo: bar}
77
+ def self.parse_inline_assignment(str_assign)
78
+ deep_key, value = str_assign.split("=")
79
+ raise "malformed assignment #{str_assign}" unless deep_key && value
80
+ assign_parts = deep_key.split(".") << value
81
+ assignment = assign_parts.reverse.inject{ |a, n| { n => a } }
82
+ assignment.deep_symbolize_keys
83
+ end
84
+
85
+ ##
86
+ # Loads and performs all interpolation operations on file, returns
87
+ # corresponding symbol hash of values. File is expected to contain
88
+ # one root element.
89
+ # @param [String] good_fname path of values file
90
+ #noinspection RubyResolve
91
+ # @return [Hash] corresponding value hash
92
+ def self.load_yaml_file(good_fname)
93
+ file_contents = File.read(good_fname)
94
+ interpolated = ErbWrapper.new.interpolate(file_contents)
95
+ YAML.load(interpolated).deep_symbolize_keys
96
+ end
97
+
98
+ #noinspection RubyLiteralArrayInspection
99
+ ##
100
+ # Returns all possible paths that a values filename might
101
+ # resolve to according to kerbi conventions. Does not check
102
+ # for file existence. The paths are ordered by similarity to
103
+ # the input expression, starting obviously with the input itself.
104
+ # @param [Object] fname cli-level filename expression for a values file
105
+ # @param [String] root optionally pass in project/mixer root dir
106
+ # @return [Array<String>] all possible paths
107
+ def self.values_paths(fname, root: nil)
108
+ if root.nil?
109
+ root = ''
110
+ else
111
+ root = "#{root}/" unless root.end_with?("/")
112
+ end
113
+ [
114
+ "#{root}#{fname}",
115
+ "#{root}#{fname}.yaml",
116
+ "#{root}#{fname}.json",
117
+ "#{root}#{fname}.yaml.erb",
118
+ "#{root}values/#{fname}",
119
+ "#{root}values/#{fname}.yaml.erb",
120
+ "#{root}values/#{fname}.yaml",
121
+ "#{root}values/#{fname}.json"
122
+ ]
123
+ end
124
+
125
+ class ErbWrapper
126
+ include Kerbi::Mixins::Mixer
127
+ def interpolate(file_cont)
128
+ ERB.new(file_cont).result(binding)
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,3 @@
1
+ dict: <%= embed({embedded: "scalar"}) %>
2
+ list: <%= embed_array(["item"]) %>
3
+ dict_list: <%= embed_array([{embedded: "item"}]) %>
@@ -0,0 +1,12 @@
1
+ require_relative './../spec_helper'
2
+ require_relative './../../examples/hello-kerbi/kerbifile'
3
+
4
+ RSpec.describe "Examples Directory" do
5
+ describe "The mixer" do
6
+ describe "#run" do
7
+ it "runs" do
8
+ # puts Kerbi::Globals.mixers.first.new({ }).run
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,126 @@
1
+ require_relative './../spec_helper'
2
+
3
+ class PatchTestOne < Kerbi::Mixer
4
+ def mix
5
+ patched_with({x: {y: "z"}}) do
6
+ push dict(x: {z: "y"})
7
+ end
8
+
9
+ push dict(x: {y: "z"})
10
+
11
+ patched_with({x: {y: "z", v: "k"}}) do
12
+ patched_with({x: {k: "v"}}) do
13
+ push dict(x: {z: "y"})
14
+ end
15
+ push dict(x: {z: "y"})
16
+ end
17
+ end
18
+ end
19
+
20
+ class PatchTestTwo < Kerbi::Mixer
21
+ def mix
22
+ patched_with({x: {y: "z", v: "k"}}) do
23
+ patched_with({x: {k: "v"}}) do
24
+ push dict(x: {z: "y"})
25
+ end
26
+ push dict(x: {z: "y"})
27
+ end
28
+ end
29
+ end
30
+
31
+ RSpec.describe Kerbi::Mixer do
32
+
33
+ subject { Kerbi::Mixer.new({}) }
34
+
35
+ before :each do
36
+ Kerbi::Testing.reset_test_yamls_dir
37
+ Kerbi::Mixer.locate_self Kerbi::Testing::TEST_YAMLS_DIR
38
+ end
39
+
40
+ describe "#patched_with" do
41
+ let(:mixer) { PatchTestOne.new({}) }
42
+ it "correctly patches output in the yielded block" do
43
+ expect(mixer.run.first).to eq({x: {z: "y", y: "z"}})
44
+ expect(mixer.patch_stack.count).to eq(0)
45
+ end
46
+
47
+ it "does not patch out-of-block dicts" do
48
+ expect(mixer.run[1]).to eq({x: {y: "z"}})
49
+ expect(mixer.patch_stack.count).to eq(0)
50
+ end
51
+
52
+ it "handles nested patches correctly" do
53
+ expect(mixer.run[2]).to eq({x: {z: "y", y: "z", v: "k", k: "v"}})
54
+ expect(mixer.patch_stack.count).to eq(0)
55
+
56
+ expect(mixer.run[3]).to eq({x: {z: "y", y: "z", v: "k"}})
57
+ expect(mixer.patch_stack.count).to eq(0)
58
+ end
59
+
60
+ it "does not affect calls that are themselves patches" do
61
+
62
+ end
63
+ end
64
+
65
+ describe "#push" do
66
+ let(:expected) { [{x: "y"}, {y: 'z'}] }
67
+ it "pushes" do
68
+ subject.push({x: "y"})
69
+ subject.push(nil)
70
+ subject.push([{y: 'z'}, "not-a-dict"])
71
+ expect(subject.output).to match_array(expected)
72
+ end
73
+ end
74
+
75
+ describe "#dict" do
76
+ it "returns the right result" do
77
+ result = subject.dict({foo: "bar"})
78
+ expect(result).to eq([{foo: "bar"}])
79
+ end
80
+ it "delegates to Utils::Mixing" do
81
+ expect(Kerbi::Utils::Mixing).to receive(:clean_and_filter_dicts)
82
+ subject.dict({foo: "bar"})
83
+ end
84
+ end
85
+
86
+ describe "#file" do
87
+ let(:values) { { foo: "zar" } }
88
+ subject { Kerbi::Mixer.new(values) }
89
+
90
+ it "works" do
91
+ Kerbi::Testing.reset_test_yamls_dir
92
+ Kerbi::Testing.make_yaml("foo.yaml", "foo: <%= values[:foo] %>")
93
+ result = subject.file("foo.yaml")
94
+ expect(result).to eq([{foo: "zar"}])
95
+ end
96
+ end
97
+
98
+ describe "#resolve_file_name" do
99
+ subject { Kerbi::Mixer }
100
+
101
+ context 'when fname is not a real file' do
102
+ it 'returns the assumed fully qualified name' do
103
+ expect(subject.resolve_file_name('bar')).to eq(nil)
104
+ end
105
+ end
106
+
107
+ context 'when fname is a real file' do
108
+ it 'returns the original fname'do
109
+ Kerbi::Testing.make_yaml('foo.yaml', {})
110
+ expected = "#{Kerbi::Testing::TEST_YAMLS_DIR}/foo.yaml"
111
+ expect(subject.resolve_file_name(expected)).to eq(expected)
112
+ expect(subject.resolve_file_name('foo')).to eq(expected)
113
+ expect(subject.resolve_file_name('foo.yaml')).to eq(expected)
114
+ end
115
+ end
116
+ end
117
+
118
+ describe ".locate_self" do
119
+ it "stores and later outputs the value" do
120
+ class Subclass < Kerbi::Mixer
121
+ locate_self 'foo'
122
+ end
123
+ expect(Subclass.new({}).class.pwd).to eq('foo')
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,25 @@
1
+ require_relative './../spec_helper'
2
+
3
+ RSpec.describe Kerbi::CodeGen::ProjectGenerator do
4
+
5
+ let(:klass) { Kerbi::CodeGen::ProjectGenerator }
6
+ let(:root) { Kerbi::Testing::TEST_YAMLS_DIR }
7
+ let(:project_name) { "test-project" }
8
+ let(:dir_path) { "#{root}/#{project_name}" }
9
+
10
+ before :each do
11
+ Kerbi::Testing.reset_test_yamls_dir
12
+ end
13
+
14
+ describe "#run" do
15
+ let(:expected_files) { %w[Gemfile kerbifile.rb values.yaml] }
16
+ it "creates a new dir and writes the files" do
17
+ expect(File.exists?(dir_path)).to be_falsey
18
+ generator = klass.new(project_name: project_name, root_dir: root)
19
+ generator.run
20
+ expect(File.exists?(dir_path)).to be_truthy
21
+ actual = Dir.entries(dir_path)
22
+ expect((expected_files - actual)).to be_empty
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,84 @@
1
+ # require_relative './../spec_helper'
2
+
3
+ # RSpec.describe Kerbi::StateManager do
4
+ #
5
+ # subject { Kerbi::StateManager.new }
6
+ #
7
+ # context = ENV['KERBI_RSPEC_K8S_CONTEXT'] || 'kind-kind'
8
+ #
9
+ # before :each do
10
+ # puts "KONTEXT #{context}"
11
+ # end
12
+ #
13
+ # describe "#patch" do
14
+ # context "when there is no entry for variables" do
15
+ #
16
+ # before :each do
17
+ # system(
18
+ # "kubectl delete cm state -n default --context #{context}",
19
+ # out: File::NULL,
20
+ # err: File::NULL
21
+ # )
22
+ # end
23
+ #
24
+ # it "patches the configmap" do
25
+ # argue("--context #{context} --set foo.bar=baz")
26
+ # old_values = subject.get_crt_vars
27
+ # expect(old_values).to eq({})
28
+ # subject.patch
29
+ # new_values = subject.get_crt_vars
30
+ # expect(new_values).to eq({foo: {bar: "baz"}})
31
+ # end
32
+ # end
33
+ #
34
+ # context "when there is an entry for variables" do
35
+ #
36
+ # before :each do
37
+ # system "kubectl delete cm state -n default --context #{context}"
38
+ # end
39
+ #
40
+ # it "patches the configmap" do
41
+ # argue("--context #{context} --set foo.bar=baz")
42
+ # subject.patch
43
+ #
44
+ # argue("--context #{context} --set foo.bar=car")
45
+ # subject.patch
46
+ #
47
+ # new_values = subject.get_crt_vars
48
+ # expect(new_values).to eq({foo: {bar: "car"}})
49
+ # end
50
+ #
51
+ # end
52
+ # end
53
+ #
54
+ # describe "#get_configmap" do
55
+ # context "when it does not exist" do
56
+ #
57
+ # before :each do
58
+ # system "kubectl delete cm state -n default --context #{context}"
59
+ # end
60
+ #
61
+ # it "returns the configmap as a hash" do
62
+ # argue("--context #{context}")
63
+ # result = subject.get_configmap(raise_on_er: false)
64
+ # expect(result).to be_nil
65
+ # end
66
+ # end
67
+ #
68
+ # context "when it does exist" do
69
+ # before :each do
70
+ # system "kubectl create cm state -n default --context #{context}"
71
+ # end
72
+ #
73
+ # it "returns the configmap as a hash" do
74
+ # argue("--context #{context}")
75
+ # result = subject.get_configmap
76
+ # expect(result).to_not be_nil
77
+ # must_have = { name: "state", namespace: "default" }
78
+ # expect(result[:metadata].slice(:name, :namespace)).to eq(must_have)
79
+ # end
80
+ # end
81
+ # end
82
+
83
+
84
+ # end
@@ -0,0 +1,55 @@
1
+ require_relative './../spec_helper'
2
+
3
+ RSpec.describe Kerbi::Mixins::Mixer do
4
+
5
+ subject { Kerbi::Mixer.new({}) }
6
+
7
+ describe "#embed" do
8
+ subject { Kerbi::EmbeddingMixerTest.new({}) }
9
+ let(:expected) do
10
+ {
11
+ dict: { embedded: "scalar" },
12
+ list: ["item"],
13
+ dict_list: [{ embedded: "item" }]
14
+ }
15
+ end
16
+
17
+ it "embeds the values correctly" do
18
+ result = subject.run
19
+ expect(result).to eq([expected])
20
+ end
21
+ end
22
+
23
+ describe "#b64enc" do
24
+ it "base 64 encodes the value" do
25
+ mixer = Kerbi::Mixer.new({})
26
+ result = mixer.b64enc("hello world")
27
+ expect(result).to eq("aGVsbG8gd29ybGQ=")
28
+ end
29
+ end
30
+
31
+ describe '#b64enc' do
32
+ context 'when the value is truthy' do
33
+ it 'returns the base64 encoding' do
34
+ expect(subject.b64enc('demo')).to eq("ZGVtbw==")
35
+ end
36
+ end
37
+ context 'when the value is blank or nil' do
38
+ it 'returns an empty string' do
39
+ expect(subject.b64enc('')).to eq('')
40
+ expect(subject.b64enc(nil)).to eq('')
41
+ end
42
+ end
43
+ end
44
+
45
+
46
+ end
47
+
48
+ module Kerbi
49
+ class EmbeddingMixerTest < Kerbi::Mixer
50
+ locate_self "#{Dir.pwd}/spec/fixtures"
51
+ def mix
52
+ push file("embedding")
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,39 @@
1
+ require 'tempfile'
2
+ require 'simplecov'
3
+
4
+ SimpleCov.start
5
+
6
+ require_relative './../lib/kerbi'
7
+
8
+ module Kerbi
9
+ module Testing
10
+
11
+ TEST_YAMLS_DIR = '/tmp/kerbi-yamls'
12
+
13
+ def self.make_yaml(fname, contents)
14
+ File.open(full_name = self.f_fname(fname), "w") do |f|
15
+ contents = YAML.dump(contents) if contents.is_a?(Hash)
16
+ f.write(contents)
17
+ end
18
+ full_name
19
+ end
20
+
21
+ def self.del_testfile(fname)
22
+ full_name = self.f_fname(fname)
23
+ if File.exists?(full_name)
24
+ File.delete(full_name)
25
+ end
26
+ end
27
+
28
+ def self.f_fname(fname)
29
+ "#{TEST_YAMLS_DIR}/#{fname}"
30
+ end
31
+
32
+ def self.reset_test_yamls_dir
33
+ system "rm -rf #{TEST_YAMLS_DIR}"
34
+ system "mkdir #{TEST_YAMLS_DIR}"
35
+ end
36
+
37
+ end
38
+ end
39
+