kerbi 0.0.1 → 0.0.5
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/lib/cli/base_handler.rb +194 -0
- data/lib/cli/base_serializer.rb +120 -0
- data/lib/cli/config_handler.rb +51 -0
- data/lib/cli/entry_serializers.rb +99 -0
- data/lib/cli/project_handler.rb +2 -2
- data/lib/cli/release_handler.rb +41 -0
- data/lib/cli/release_serializer.rb +46 -0
- data/lib/cli/root_handler.rb +34 -13
- data/lib/cli/state_handler.rb +88 -0
- data/lib/cli/values_handler.rb +4 -3
- data/{boilerplate → lib/code-gen/new-project}/Gemfile.erb +0 -0
- data/lib/code-gen/new-project/kerbifile.rb.erb +9 -0
- data/lib/code-gen/new-project/values.yaml.erb +1 -0
- data/lib/config/cli_schema.rb +343 -28
- data/lib/config/config_file.rb +60 -0
- data/lib/config/globals.rb +4 -0
- data/lib/config/run_opts.rb +162 -0
- data/lib/config/state_consts.rb +11 -0
- data/lib/kerbi.rb +35 -10
- data/lib/main/code_gen.rb +1 -1
- data/lib/main/errors.rb +115 -0
- data/lib/main/mixer.rb +20 -10
- data/lib/mixins/cli_state_helpers.rb +108 -0
- data/lib/mixins/cm_backend_testing.rb +109 -0
- data/lib/mixins/entry_tag_logic.rb +183 -0
- data/lib/state/base_backend.rb +93 -0
- data/lib/state/config_map_backend.rb +173 -0
- data/lib/state/entry.rb +173 -0
- data/lib/state/entry_set.rb +137 -0
- data/lib/state/metadata.yaml.erb +11 -0
- data/lib/state/mixers.rb +23 -0
- data/lib/state/resources.yaml.erb +17 -0
- data/lib/utils/cli.rb +108 -9
- data/lib/utils/helm.rb +10 -12
- data/lib/utils/k8s_auth.rb +87 -0
- data/lib/utils/misc.rb +36 -1
- data/lib/utils/mixing.rb +1 -1
- data/lib/utils/values.rb +13 -22
- data/spec/cli/config_handler_spec.rb +38 -0
- data/spec/cli/release_handler_spec.rb +127 -0
- data/spec/cli/root_handler_spec.rb +100 -0
- data/spec/cli/state_handler_spec.rb +108 -0
- data/spec/cli/values_handler_spec.rb +17 -0
- data/spec/fixtures/expectations/common/bad-tag.txt +1 -0
- data/spec/fixtures/expectations/config/bad-set.txt +1 -0
- data/spec/fixtures/expectations/config/set.txt +1 -0
- data/spec/fixtures/expectations/config/show-default.yaml +6 -0
- data/spec/fixtures/expectations/release/delete.txt +1 -0
- data/spec/fixtures/expectations/release/init-already-existed.txt +2 -0
- data/spec/fixtures/expectations/release/init-both-created.txt +2 -0
- data/spec/fixtures/expectations/release/list.txt +5 -0
- data/spec/fixtures/expectations/release/status-all-working.txt +5 -0
- data/spec/fixtures/expectations/release/status-data-unreadable.txt +5 -0
- data/spec/fixtures/expectations/release/status-not-provisioned.txt +5 -0
- data/spec/fixtures/expectations/root/template-inlines.yaml +31 -0
- data/spec/fixtures/expectations/root/template-production.yaml +31 -0
- data/spec/fixtures/expectations/root/template-read-inlines.yaml +31 -0
- data/spec/fixtures/expectations/root/template-read.yaml +31 -0
- data/spec/fixtures/expectations/root/template-write.yaml +31 -0
- data/spec/fixtures/expectations/root/template.yaml +31 -0
- data/spec/fixtures/expectations/root/values.json +28 -0
- data/spec/fixtures/expectations/state/delete.txt +1 -0
- data/spec/fixtures/expectations/state/demote.txt +1 -0
- data/spec/fixtures/expectations/state/list.json +51 -0
- data/spec/fixtures/expectations/state/list.txt +6 -0
- data/spec/fixtures/expectations/state/list.yaml +35 -0
- data/spec/fixtures/expectations/state/promote.txt +1 -0
- data/spec/fixtures/expectations/state/prune-candidates.txt +1 -0
- data/spec/fixtures/expectations/state/retag.txt +1 -0
- data/spec/fixtures/expectations/state/set.txt +1 -0
- data/spec/fixtures/expectations/state/show.json +13 -0
- data/spec/fixtures/expectations/state/show.txt +13 -0
- data/spec/fixtures/expectations/state/show.yaml +8 -0
- data/spec/fixtures/expectations/values/order-of-precedence.yaml +4 -0
- data/spec/main/configmap_backend_spec.rb +110 -0
- data/spec/main/project_code_gen_spec.rb +8 -2
- data/spec/main/state_entry_set_spec.rb +112 -0
- data/spec/main/state_entry_spec.rb +109 -0
- data/spec/mini-projects/hello-kerbi/common/metadata.yaml.erb +5 -0
- data/spec/mini-projects/hello-kerbi/consts.rb +5 -0
- data/spec/mini-projects/hello-kerbi/helpers.rb +8 -0
- data/spec/mini-projects/hello-kerbi/kerbifile.rb +18 -0
- data/spec/mini-projects/hello-kerbi/pod-and-service.yaml.erb +23 -0
- data/spec/mini-projects/hello-kerbi/values/production.yaml +2 -0
- data/spec/mini-projects/hello-kerbi/values/v2.yaml +2 -0
- data/spec/mini-projects/hello-kerbi/values/values.yaml +4 -0
- data/spec/spec_helper.rb +143 -1
- data/spec/utils/helm_spec.rb +89 -109
- data/spec/utils/k8s_auth_spec.rb +32 -0
- data/spec/utils/misc_utils_spec.rb +9 -0
- data/spec/utils/values_utils_spec.rb +12 -19
- metadata +143 -16
- data/boilerplate/kerbifile.rb.erb +0 -9
- data/boilerplate/values.yaml.erb +0 -1
- data/lib/cli/base.rb +0 -83
- data/lib/config/cli_opts.rb +0 -50
- data/lib/config/manager.rb +0 -36
- data/lib/main/state_manager.rb +0 -47
- data/lib/utils/kubectl.rb +0 -58
- data/spec/main/examples_spec.rb +0 -12
- data/spec/main/state_manager_spec.rb +0 -84
- data/spec/utils/state_utils.rb +0 -15
@@ -0,0 +1,6 @@
|
|
1
|
+
TAG MESSAGE ASSIGNMENTS OVERRIDES CREATED_AT
|
2
|
+
|
3
|
+
\e[0;33;49m[cand]-four\e[0m 0 0 2003-01-01 00:00:00 +0000
|
4
|
+
\e[0;33;49m[cand]-three\e[0m 0 0 2002-01-01 00:00:00 +0000
|
5
|
+
\e[0;34;49mtwo\e[0m message 0 0 2001-01-01 00:00:00 +0000
|
6
|
+
\e[0;34;49mone\e[0m 1 1 2000-01-01 00:00:00 +0000
|
@@ -0,0 +1,35 @@
|
|
1
|
+
tag: "[cand]-four"
|
2
|
+
message:
|
3
|
+
created_at: 2003-01-01 00:00:00.000000000 +00:00
|
4
|
+
values: {}
|
5
|
+
default_values: {}
|
6
|
+
overridden_keys: []
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
tag: "[cand]-three"
|
11
|
+
message:
|
12
|
+
created_at: 2002-01-01 00:00:00.000000000 +00:00
|
13
|
+
values: {}
|
14
|
+
default_values: {}
|
15
|
+
overridden_keys: []
|
16
|
+
|
17
|
+
---
|
18
|
+
|
19
|
+
tag: two
|
20
|
+
message: message
|
21
|
+
created_at: 2001-01-01 00:00:00.000000000 +00:00
|
22
|
+
values: {}
|
23
|
+
default_values: {}
|
24
|
+
overridden_keys: []
|
25
|
+
|
26
|
+
---
|
27
|
+
|
28
|
+
tag: one
|
29
|
+
message:
|
30
|
+
created_at: 2000-01-01 00:00:00.000000000 +00:00
|
31
|
+
values:
|
32
|
+
x: x
|
33
|
+
default_values: {}
|
34
|
+
overridden_keys:
|
35
|
+
- x
|
@@ -0,0 +1 @@
|
|
1
|
+
\e[0;32;49mUpdated state[four].tag from [cand]-four => four\e[0m
|
@@ -0,0 +1 @@
|
|
1
|
+
Pruned 2 state entries
|
@@ -0,0 +1 @@
|
|
1
|
+
\e[0;32;49mUpdated state[born-again].tag from two => born-again\e[0m
|
@@ -0,0 +1 @@
|
|
1
|
+
\e[0;32;49mUpdated state[two].message from message => new message\e[0m
|
@@ -0,0 +1,13 @@
|
|
1
|
+
--------------------------------------------
|
2
|
+
\e[1;39;49mTAG\e[0m \e[1;34;49mone\e[0m
|
3
|
+
--------------------------------------------
|
4
|
+
\e[1;39;49mMESSAGE\e[0m
|
5
|
+
--------------------------------------------
|
6
|
+
\e[1;39;49mCREATED_AT\e[0m 2000-01-01 00:00:00 +0000
|
7
|
+
--------------------------------------------
|
8
|
+
\e[1;39;49mVALUES\e[0m x: x
|
9
|
+
--------------------------------------------
|
10
|
+
\e[1;39;49mDEFAULT_VALUES\e[0m {}
|
11
|
+
--------------------------------------------
|
12
|
+
\e[1;39;49mOVERRIDDEN_KEYS\e[0m x
|
13
|
+
--------------------------------------------
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require_relative './../spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Kerbi::State::ConfigMapBackend do
|
4
|
+
|
5
|
+
let(:namespace) { "kerbi-spec" }
|
6
|
+
let(:cm_name) { Kerbi::State::ConfigMapBackend.mk_cm_name(namespace) }
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
create_ns(namespace)
|
10
|
+
delete_cm(cm_name, namespace)
|
11
|
+
# sleep(2) #ADD ME BACK IF WEIRD ERRORS... :/
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#provision_missing_resources" do
|
15
|
+
let(:backend) { make_backend(namespace, namespace) }
|
16
|
+
|
17
|
+
context "when the namespace does not exist" do
|
18
|
+
it "provisions accordingly" do
|
19
|
+
delete_ns(namespace)
|
20
|
+
expect(backend.read_write_ready?).to be_falsey
|
21
|
+
backend.provision_missing_resources
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when the namespace does exist" do
|
26
|
+
before :each do
|
27
|
+
create_ns(namespace)
|
28
|
+
expect(backend.read_write_ready?).to be_falsey
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when the configmap does not exist" do
|
32
|
+
it "provisions accordingly" do
|
33
|
+
backend.provision_missing_resources
|
34
|
+
delete_cm(cm_name, namespace)
|
35
|
+
backend.provision_missing_resources
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when the configmap does exist" do
|
40
|
+
it "provisions accordingly" do
|
41
|
+
backend.provision_missing_resources
|
42
|
+
backend.provision_missing_resources
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
after :each do
|
48
|
+
expect(backend.namespace_exists?).to eq(true)
|
49
|
+
expect(backend.read_write_ready?).to eq(true)
|
50
|
+
expect(backend.resource_exists?).to eq(true)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#template_resource" do
|
55
|
+
context "with 0 entries" do
|
56
|
+
it "outputs a descriptor with the right basic properties" do
|
57
|
+
result = make_backend("xyz").template_resource([])
|
58
|
+
metadata = (result || {})[:metadata] || {}
|
59
|
+
expect(result[:kind]).to eq('ConfigMap')
|
60
|
+
expect(metadata[:name]).to eq('kerbi-xyz-db')
|
61
|
+
expect(metadata[:namespace]).to eq('xyz')
|
62
|
+
expect(result[:data][:entries]).to eq("[]")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with some entries (for puts only, uncomment)" do
|
67
|
+
it "puts it" do
|
68
|
+
# entry = new_state("1", created_at: "2022-01-01T00:00:00+00:00")
|
69
|
+
# puts entry.to_h
|
70
|
+
# result = make_backend("xyz").template_resource([entry])
|
71
|
+
# puts result
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#namespace_exists?" do
|
77
|
+
context "when the namespace exists" do
|
78
|
+
it "returns true" do
|
79
|
+
expect(make_backend('', "default").namespace_exists?).to be_truthy
|
80
|
+
end
|
81
|
+
end
|
82
|
+
context "when the namespace does not exist" do
|
83
|
+
it "returns false" do
|
84
|
+
expect(make_backend('', "nope").namespace_exists?).to be_falsey
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "#apply_resource and #read_entries" do
|
90
|
+
let(:entries) do
|
91
|
+
[
|
92
|
+
new_state("one", message: "m-one", created_at: "2022-01-01T00:00:00+00:00"),
|
93
|
+
new_state("two", message: "m-two", created_at: "2022-02-01T00:00:00+00:00"),
|
94
|
+
]
|
95
|
+
end
|
96
|
+
|
97
|
+
it "creates a configmap with the right contents" do
|
98
|
+
subject = make_backend(namespace, namespace)
|
99
|
+
descriptor = subject.template_resource(entries)
|
100
|
+
subject.apply_resource(descriptor)
|
101
|
+
sleep(1)
|
102
|
+
actual = subject.send(:read_entries)
|
103
|
+
expect(actual.count).to eq(2)
|
104
|
+
|
105
|
+
actual_one = actual[0].values_at("tag", "message", "created_at")
|
106
|
+
expected_one = entries[0].to_h.values_at(:tag, :message, :created_at)
|
107
|
+
expect(actual_one).to eq(expected_one)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -7,6 +7,13 @@ RSpec.describe Kerbi::CodeGen::ProjectGenerator do
|
|
7
7
|
let(:project_name) { "test-project" }
|
8
8
|
let(:dir_path) { "#{root}/#{project_name}" }
|
9
9
|
|
10
|
+
subject do
|
11
|
+
Kerbi::CodeGen::ProjectGenerator.new(
|
12
|
+
project_name: project_name,
|
13
|
+
root_dir: root
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
10
17
|
before :each do
|
11
18
|
Kerbi::Testing.reset_test_yamls_dir
|
12
19
|
end
|
@@ -15,8 +22,7 @@ RSpec.describe Kerbi::CodeGen::ProjectGenerator do
|
|
15
22
|
let(:expected_files) { %w[Gemfile kerbifile.rb values.yaml] }
|
16
23
|
it "creates a new dir and writes the files" do
|
17
24
|
expect(File.exists?(dir_path)).to be_falsey
|
18
|
-
|
19
|
-
generator.run
|
25
|
+
subject.run
|
20
26
|
expect(File.exists?(dir_path)).to be_truthy
|
21
27
|
actual = Dir.entries(dir_path)
|
22
28
|
expect((expected_files - actual)).to be_empty
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require_relative './../spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Kerbi::State::EntrySet do
|
4
|
+
|
5
|
+
let(:set) do
|
6
|
+
new_state_set(
|
7
|
+
one: { created_at: Time.new(2000).to_s },
|
8
|
+
two: { created_at: Time.new(2001).to_s },
|
9
|
+
"[cand]-one".to_sym => { created_at: Time.new(2002).to_s },
|
10
|
+
"[cand]-two".to_sym => { created_at: Time.new(2003).to_s }
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:bad_set) do
|
15
|
+
new_state_set(
|
16
|
+
"".to_sym => { },
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#initialize" do
|
21
|
+
it "sorts DESC on created_at" do
|
22
|
+
expect(set.entries[0].tag).to eq("[cand]-two")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "validate!" do
|
27
|
+
context "when there are no errors" do
|
28
|
+
it "does not raise an error" do
|
29
|
+
set.validate!
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when there are errors" do
|
34
|
+
it "raises the right error" do
|
35
|
+
expect{
|
36
|
+
bad_set.validate!
|
37
|
+
}.to raise_exception(Kerbi::EntryValidationError)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#latest" do
|
43
|
+
it "returns the correct entry" do
|
44
|
+
expect(set.latest.tag).to eq("two")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#latest_candidate" do
|
49
|
+
it "returns the correct entry" do
|
50
|
+
expect(set.latest_candidate.tag).to eq("[cand]-two")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#candidates" do
|
55
|
+
it "returns the right entries" do
|
56
|
+
expected = %w[[cand]-two [cand]-one]
|
57
|
+
expect(set.candidates.map(&:tag)).to eq(expected)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#committed" do
|
62
|
+
it "returns the right entries" do
|
63
|
+
expected = %w[two one]
|
64
|
+
expect(set.committed.map(&:tag)).to eq(expected)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "#find_entry_for_read" do
|
69
|
+
context "when the substitutions work and the entry exists" do
|
70
|
+
it "returns the right entry" do
|
71
|
+
actual = set.find_entry_for_read("two")
|
72
|
+
expect(actual.tag).to eq("two")
|
73
|
+
|
74
|
+
actual = set.find_entry_for_read("@latest")
|
75
|
+
expect(actual.tag).to eq("two")
|
76
|
+
|
77
|
+
actual = set.find_entry_for_read("@candidate")
|
78
|
+
expect(actual.tag).to eq("[cand]-two")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when either the resolution fails or the entry does not exist" do
|
83
|
+
it "raises Kerbi::StateNotFoundError" do
|
84
|
+
expect {
|
85
|
+
set.find_entry_for_read("three")
|
86
|
+
}.to raise_exception(Kerbi::StateNotFoundError)
|
87
|
+
|
88
|
+
expect {
|
89
|
+
set.find_entry_for_read("not-@latest")
|
90
|
+
}.to raise_exception(Kerbi::StateNotFoundError)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#find_or_init_entry_for_write" do
|
96
|
+
it "returns the right entry" do
|
97
|
+
actual = set.find_or_init_entry_for_write("two")
|
98
|
+
expect(actual.tag).to eq("two")
|
99
|
+
|
100
|
+
actual = set.find_or_init_entry_for_write("@latest")
|
101
|
+
expect(actual.tag).to eq("two")
|
102
|
+
|
103
|
+
actual = set.find_or_init_entry_for_write("@candidate")
|
104
|
+
expect(actual.tag).to eq("[cand]-two")
|
105
|
+
|
106
|
+
actual = set.find_or_init_entry_for_write("@new-candidate")
|
107
|
+
expect(actual.tag).to_not eq("[cand]-two")
|
108
|
+
expect(actual.tag).to_not be_falsey
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require_relative './../spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Kerbi::State::Entry do
|
4
|
+
|
5
|
+
let(:subject_cls) { Kerbi::State::Entry }
|
6
|
+
let(:cand_prefix) { subject_cls::CANDIDATE_PREFIX }
|
7
|
+
|
8
|
+
let(:default_dict) do
|
9
|
+
{
|
10
|
+
tag: "tag",
|
11
|
+
message: "message",
|
12
|
+
values: {x: {y: "z"}},
|
13
|
+
default_values: {y: "z"},
|
14
|
+
created_at: "2020-01-02T03:04:00",
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#candiate? and #committed?" do
|
19
|
+
context "when it is a candidate" do
|
20
|
+
it "returns true for #candidate and false for #committed" do
|
21
|
+
expect(new_state("[cand]-one").candidate?).to be_truthy
|
22
|
+
expect(new_state("[cand]-one").committed?).to be_falsey
|
23
|
+
end
|
24
|
+
end
|
25
|
+
context "when it is a candidate" do
|
26
|
+
it "returns false for #candidate and true for #committed" do
|
27
|
+
expect(new_state("[cant]-one").candidate?).to be_falsey
|
28
|
+
expect(new_state("[cant]-one").committed?).to be_truthy
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#validate" do
|
34
|
+
context "when there is a tag error" do
|
35
|
+
it "finds validation errors" do
|
36
|
+
(state = new_state("")).validate
|
37
|
+
expect(state.valid?).to be_falsey
|
38
|
+
|
39
|
+
(state = new_state(" ")).validate
|
40
|
+
expect(state.valid?).to be_falsey
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when there are zero tag errors" do
|
45
|
+
it "finds validation errors" do
|
46
|
+
(state = new_state("a")).validate
|
47
|
+
expect(state.valid?).to be_truthy
|
48
|
+
|
49
|
+
(state = new_state("|")).validate
|
50
|
+
expect(state.valid?).to be_truthy
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#promote" do
|
56
|
+
context "when the entry is a candidate" do
|
57
|
+
it "removes the [cand]- flag" do
|
58
|
+
old = (state = new_state("#{cand_prefix}foo")).promote
|
59
|
+
expect(state.tag).to eq("foo")
|
60
|
+
expect(old).to eq("#{cand_prefix}foo")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when the entry is not a candidate" do
|
65
|
+
it "raises" do
|
66
|
+
expect {
|
67
|
+
new_state("foo").promote
|
68
|
+
}.to raise_exception(Kerbi::StateNotPromotable)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#demote" do
|
74
|
+
context "when the entry is committed" do
|
75
|
+
it "adds the [cand]- flag" do
|
76
|
+
old = (state = new_state("foo")).demote
|
77
|
+
expect(state.tag).to eq("#{cand_prefix}foo")
|
78
|
+
expect(old).to eq("foo")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when the entry is not a candidate" do
|
83
|
+
it "raises" do
|
84
|
+
expect {
|
85
|
+
new_state("#{cand_prefix}foo").demote
|
86
|
+
}.to raise_exception(Kerbi::StateNotDemotable)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe ".from_dict" do
|
92
|
+
it "parses the created_at timestamp correctly" do
|
93
|
+
entry = subject_cls.from_dict(nil, default_dict)
|
94
|
+
expected = Time.new(2020, 1, 2, 3, 4, 0)
|
95
|
+
expect(entry.created_at).to eq(expected)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#to_h" do
|
100
|
+
it "returns the right dict" do
|
101
|
+
entry = new_state("foo", default_dict)
|
102
|
+
actual = entry.to_h
|
103
|
+
actual.delete(:created_at)
|
104
|
+
expect = default_dict.deep_dup
|
105
|
+
expect.delete(:created_at)
|
106
|
+
expect(actual).to eq(expect)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'consts'
|
2
|
+
require_relative 'helpers'
|
3
|
+
|
4
|
+
module HelloKerbi
|
5
|
+
class Mixer < Kerbi::Mixer
|
6
|
+
include Helpers
|
7
|
+
|
8
|
+
locate_self __dir__
|
9
|
+
|
10
|
+
def mix
|
11
|
+
patched_with file("common/metadata") do
|
12
|
+
push file("pod-and-service")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Kerbi::Globals.mixers << HelloKerbi::Mixer
|
@@ -0,0 +1,23 @@
|
|
1
|
+
apiVersion: v1
|
2
|
+
kind: Pod
|
3
|
+
metadata:
|
4
|
+
name: <%= HelloKerbi::Consts::APP_NAME %>
|
5
|
+
namespace: <%= release_name %>
|
6
|
+
spec:
|
7
|
+
containers:
|
8
|
+
- name: main
|
9
|
+
image: <%= img2alpine(values[:pod][:image]) %>
|
10
|
+
|
11
|
+
---
|
12
|
+
|
13
|
+
apiVersion: v1
|
14
|
+
kind: Service
|
15
|
+
metadata:
|
16
|
+
name: <%= HelloKerbi::Consts::APP_NAME %>
|
17
|
+
namespace: <%= release_name %>
|
18
|
+
spec:
|
19
|
+
type: <%= values[:service][:type] %>
|
20
|
+
selector:
|
21
|
+
app: <%= HelloKerbi::Consts::APP_NAME %>
|
22
|
+
ports:
|
23
|
+
- port: 80
|
data/spec/spec_helper.rb
CHANGED
@@ -5,6 +5,149 @@ SimpleCov.start
|
|
5
5
|
|
6
6
|
require_relative './../lib/kerbi'
|
7
7
|
|
8
|
+
def run_opts
|
9
|
+
Kerbi::RunOpts.new({}, Kerbi::Consts::OptionDefaults::BASE)
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param [String] namespace
|
13
|
+
# @return [Kerbi::State::ConfigMapBackend]
|
14
|
+
def make_backend(release_name, namespace=nil)
|
15
|
+
auth_bundle = Kerbi::Utils::Cli.make_k8s_auth_bundle(run_opts)
|
16
|
+
Kerbi::State::ConfigMapBackend.new(auth_bundle, release_name, namespace)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Kubeclient::Client]
|
20
|
+
def make_kube_client(api_name)
|
21
|
+
auth_bundle = Kerbi::Utils::Cli.make_k8s_auth_bundle(run_opts)
|
22
|
+
Kubeclient::Client.new(
|
23
|
+
auth_bundle[:endpoint],
|
24
|
+
api_name,
|
25
|
+
**auth_bundle[:options]
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_ns(name)
|
30
|
+
dict = { metadata: { name: name } }
|
31
|
+
begin
|
32
|
+
#noinspection RubyResolve
|
33
|
+
make_kube_client("v1").create_namespace(dict)
|
34
|
+
rescue Kubeclient::HttpError
|
35
|
+
true
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete_cm(name, namespace)
|
40
|
+
begin
|
41
|
+
#noinspection RubyResolve
|
42
|
+
make_kube_client("v1").delete_config_map(name, namespace)
|
43
|
+
begin
|
44
|
+
sleep(1)
|
45
|
+
#noinspection RubyResolve
|
46
|
+
exists = client.get_config_map(name, namespace) rescue nil
|
47
|
+
end while exists
|
48
|
+
rescue Kubeclient::ResourceNotFoundError
|
49
|
+
true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def delete_ns(name)
|
54
|
+
begin
|
55
|
+
#noinspection RubyResolve
|
56
|
+
(client = make_kube_client("v1")).delete_namespace(name)
|
57
|
+
begin
|
58
|
+
sleep(1)
|
59
|
+
exists = client.get_namespace(name) rescue nil
|
60
|
+
end while exists
|
61
|
+
rescue Kubeclient::ResourceNotFoundError
|
62
|
+
true
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def corrupt_cm(backend)
|
67
|
+
cm_body = backend.template_resource([])
|
68
|
+
cm_body[:data][:entries] = "not json"
|
69
|
+
backend.send(:client).update_config_map(cm_body)
|
70
|
+
end
|
71
|
+
|
72
|
+
def new_state(tag, dict={})
|
73
|
+
set = dict.delete(:state)
|
74
|
+
dict[:tag] = tag
|
75
|
+
Kerbi::State::Entry.from_dict(set, dict)
|
76
|
+
end
|
77
|
+
|
78
|
+
def new_state_set(bundles)
|
79
|
+
dicts = bundles.map { |kv| { tag: kv[0].to_s, **kv[1] } }
|
80
|
+
Kerbi::State::EntrySet.new(dicts)
|
81
|
+
end
|
82
|
+
|
83
|
+
def cli(command, escaped: false)
|
84
|
+
$stdout = StringIO.new
|
85
|
+
begin
|
86
|
+
command = command.split(" ") if command.is_a?(String)
|
87
|
+
Kerbi::Cli::RootHandler.start(command)
|
88
|
+
output = $stdout.string
|
89
|
+
$stdout = STDOUT
|
90
|
+
escaped ? output.gsub("\e", "\\e") : output
|
91
|
+
ensure
|
92
|
+
$stdout = STDOUT
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def load_exp_file(dir, file, ext)
|
97
|
+
path = "#{__dir__}/fixtures/expectations/#{dir}/#{file}.#{ext}"
|
98
|
+
File.read(path)
|
99
|
+
end
|
100
|
+
|
101
|
+
def read_exp_file(dir, file, ext)
|
102
|
+
expected_str = load_exp_file(dir, file, ext)
|
103
|
+
if ext == 'json'
|
104
|
+
JSON.parse(expected_str)
|
105
|
+
elsif ext == 'yaml'
|
106
|
+
YAML.load_stream(expected_str)
|
107
|
+
else
|
108
|
+
expected_str.gsub(/\s+/, "")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def exp_cli_eq_file(cmd, dir, file, ext='txt')
|
113
|
+
actual_str = cli(cmd)
|
114
|
+
expected = read_exp_file(dir, file, ext)
|
115
|
+
|
116
|
+
if ext == 'json'
|
117
|
+
expect(JSON.parse(actual_str)).to eq(expected)
|
118
|
+
elsif ext == 'yaml'
|
119
|
+
actual = YAML.load_stream(actual_str) rescue 0
|
120
|
+
if actual != 0
|
121
|
+
expect(actual).to eq(expected)
|
122
|
+
else
|
123
|
+
puts actual_str
|
124
|
+
raise "CMD #{cmd} echoed non-YAML (above)"
|
125
|
+
end
|
126
|
+
else
|
127
|
+
actual = actual_str.gsub(/\s+/, "").gsub("\e", "\\e")
|
128
|
+
expect(actual).to eq(expected)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def hello_kerbi(cmd, namespace=nil)
|
133
|
+
target = "#{__dir__}/mini-projects/hello-kerbi"
|
134
|
+
cmd = "#{cmd} --project-root #{target}"
|
135
|
+
cmd = "#{cmd} --namespace #{namespace}" if namespace
|
136
|
+
cmd
|
137
|
+
end
|
138
|
+
|
139
|
+
def cmd_group_spec(cmd, dir, file, opts={})
|
140
|
+
(opts[:formats] || %w[yaml json table]).each do |format|
|
141
|
+
context "with --output-format #{format} #{opts[:context_append]}" do
|
142
|
+
it "echos the expected text" do
|
143
|
+
extension = format == 'table' ? "txt" : format
|
144
|
+
cmd_with_fmt = "#{cmd} -o #{format}"
|
145
|
+
exp_cli_eq_file(cmd_with_fmt, dir, file, extension)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
8
151
|
module Kerbi
|
9
152
|
module Testing
|
10
153
|
|
@@ -33,7 +176,6 @@ module Kerbi
|
|
33
176
|
system "rm -rf #{TEST_YAMLS_DIR}"
|
34
177
|
system "mkdir #{TEST_YAMLS_DIR}"
|
35
178
|
end
|
36
|
-
|
37
179
|
end
|
38
180
|
end
|
39
181
|
|