kerbi 0.0.1 → 0.0.2
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 +180 -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/root_handler.rb +32 -13
- data/lib/cli/state_handler.rb +95 -0
- data/lib/cli/values_handler.rb +4 -3
- data/lib/config/cli_schema.rb +299 -27
- data/lib/config/config_file.rb +60 -0
- data/lib/config/globals.rb +4 -0
- data/lib/config/run_opts.rb +150 -0
- data/lib/config/state_consts.rb +10 -0
- data/lib/kerbi.rb +31 -9
- data/lib/main/errors.rb +109 -0
- data/lib/main/mixer.rb +12 -8
- data/lib/mixins/cli_state_helpers.rb +136 -0
- data/lib/mixins/cm_backend_testing.rb +95 -0
- data/lib/mixins/entry_tag_logic.rb +183 -0
- data/lib/state/base_backend.rb +59 -0
- data/lib/state/config_map_backend.rb +119 -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 +77 -10
- 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/root_handler_spec.rb +99 -0
- data/spec/cli/state_handler_spec.rb +139 -0
- data/spec/cli/values_handler_spec.rb +17 -0
- data/spec/expectations/common/bad-tag.txt +1 -0
- data/spec/expectations/config/bad-set.txt +1 -0
- data/spec/expectations/config/set.txt +1 -0
- data/spec/expectations/config/show-default.yaml +6 -0
- data/spec/expectations/root/template-inlines.yaml +31 -0
- data/spec/expectations/root/template-production.yaml +31 -0
- data/spec/expectations/root/template-read-inlines.yaml +31 -0
- data/spec/expectations/root/template-read.yaml +31 -0
- data/spec/expectations/root/template-write.yaml +31 -0
- data/spec/expectations/root/template.yaml +31 -0
- data/spec/expectations/root/values.json +28 -0
- data/spec/expectations/state/delete.txt +1 -0
- data/spec/expectations/state/demote.txt +1 -0
- data/spec/expectations/state/init-already-existed.txt +2 -0
- data/spec/expectations/state/init-both-created.txt +2 -0
- data/spec/expectations/state/list.json +51 -0
- data/spec/expectations/state/list.txt +6 -0
- data/spec/expectations/state/list.yaml +35 -0
- data/spec/expectations/state/promote.txt +1 -0
- data/spec/expectations/state/prune-candidates.txt +1 -0
- data/spec/expectations/state/retag.txt +1 -0
- data/spec/expectations/state/set.txt +1 -0
- data/spec/expectations/state/show.json +13 -0
- data/spec/expectations/state/show.txt +13 -0
- data/spec/expectations/state/show.yaml +8 -0
- data/spec/expectations/state/status-all-working.txt +4 -0
- data/spec/expectations/state/status-not-provisioned.txt +4 -0
- data/spec/expectations/values/order-of-precedence.yaml +4 -0
- data/spec/main/configmap_backend_spec.rb +109 -0
- data/spec/main/state_entry_set_spec.rb +112 -0
- data/spec/main/state_entry_spec.rb +109 -0
- data/spec/spec_helper.rb +87 -1
- data/spec/utils/helm_spec.rb +1 -21
- 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 +114 -13
- 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,31 @@
|
|
1
|
+
apiVersion: v1
|
2
|
+
kind: Pod
|
3
|
+
metadata:
|
4
|
+
name: hello-kerbi
|
5
|
+
namespace: foo
|
6
|
+
annotations:
|
7
|
+
author: xavier
|
8
|
+
labels:
|
9
|
+
app: hello-kerbi
|
10
|
+
spec:
|
11
|
+
containers:
|
12
|
+
- name: main
|
13
|
+
image: nginx:alpine
|
14
|
+
|
15
|
+
---
|
16
|
+
|
17
|
+
apiVersion: v1
|
18
|
+
kind: Service
|
19
|
+
metadata:
|
20
|
+
name: hello-kerbi
|
21
|
+
namespace: foo
|
22
|
+
annotations:
|
23
|
+
author: xavier
|
24
|
+
labels:
|
25
|
+
app: hello-kerbi
|
26
|
+
spec:
|
27
|
+
type: ClusterIP
|
28
|
+
selector:
|
29
|
+
app: hello-kerbi
|
30
|
+
ports:
|
31
|
+
- port: 80
|
@@ -0,0 +1,28 @@
|
|
1
|
+
{
|
2
|
+
"centos": {
|
3
|
+
"pod": {
|
4
|
+
"image": "centos"
|
5
|
+
},
|
6
|
+
"service": {
|
7
|
+
"type": "ClusterIP"
|
8
|
+
}
|
9
|
+
},
|
10
|
+
|
11
|
+
"nginx": {
|
12
|
+
"pod": {
|
13
|
+
"image": "nginx"
|
14
|
+
},
|
15
|
+
"service": {
|
16
|
+
"type": "ClusterIP"
|
17
|
+
}
|
18
|
+
},
|
19
|
+
|
20
|
+
"debian": {
|
21
|
+
"pod": {
|
22
|
+
"image": "debian"
|
23
|
+
},
|
24
|
+
"service": {
|
25
|
+
"type": "ClusterIP"
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
Deleted state[two]. Remaining entries: 3
|
@@ -0,0 +1 @@
|
|
1
|
+
\e[0;32;49mUpdated state[[cand]-two].tag from two => [cand]-two\e[0m
|
@@ -0,0 +1,51 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"tag": "[cand]-four",
|
4
|
+
"message": null,
|
5
|
+
"created_at": "2003-01-01 00:00:00 +0000",
|
6
|
+
"values": {
|
7
|
+
},
|
8
|
+
"default_values": {
|
9
|
+
},
|
10
|
+
"overridden_keys": [
|
11
|
+
|
12
|
+
]
|
13
|
+
},
|
14
|
+
{
|
15
|
+
"tag": "[cand]-three",
|
16
|
+
"message": null,
|
17
|
+
"created_at": "2002-01-01 00:00:00 +0000",
|
18
|
+
"values": {
|
19
|
+
},
|
20
|
+
"default_values": {
|
21
|
+
},
|
22
|
+
"overridden_keys": [
|
23
|
+
|
24
|
+
]
|
25
|
+
},
|
26
|
+
{
|
27
|
+
"tag": "two",
|
28
|
+
"message": "message",
|
29
|
+
"created_at": "2001-01-01 00:00:00 +0000",
|
30
|
+
"values": {
|
31
|
+
},
|
32
|
+
"default_values": {
|
33
|
+
},
|
34
|
+
"overridden_keys": [
|
35
|
+
|
36
|
+
]
|
37
|
+
},
|
38
|
+
{
|
39
|
+
"tag": "one",
|
40
|
+
"message": null,
|
41
|
+
"created_at": "2000-01-01 00:00:00 +0000",
|
42
|
+
"values": {
|
43
|
+
"x": "x"
|
44
|
+
},
|
45
|
+
"default_values": {
|
46
|
+
},
|
47
|
+
"overridden_keys": [
|
48
|
+
"x"
|
49
|
+
]
|
50
|
+
}
|
51
|
+
]
|
@@ -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,4 @@
|
|
1
|
+
\e[1;39;49m1. Create Kubernetes client: \e[0m\e[1;32;49mSuccess\e[0m
|
2
|
+
\e[1;39;49m2. List cluster namespaces: \e[0m\e[1;32;49mSuccess\e[0m
|
3
|
+
\e[1;39;49m3. Target namespace kerbi-spec exists: \e[0m\e[1;32;49mSuccess\e[0m
|
4
|
+
\e[1;39;49m4. Resource kerbi-spec/cm/kerbi-state-tracker exists: \e[0m\e[1;32;49mSuccess\e[0m
|
@@ -0,0 +1,4 @@
|
|
1
|
+
\e[1;39;49m1. Create Kubernetes client: \e[0m\e[1;32;49mSuccess\e[0m
|
2
|
+
\e[1;39;49m2. List cluster namespaces: \e[0m\e[1;32;49mSuccess\e[0m
|
3
|
+
\e[1;39;49m3. Target namespace kerbi-spec exists: \e[0m\e[1;31;49mFailure\e[0m
|
4
|
+
\e[1;39;49m4. Resource kerbi-spec/cm/kerbi-state-tracker exists: \e[0m\e[1;31;49mFailure\e[0m
|
@@ -0,0 +1,109 @@
|
|
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::Consts::RESOURCE_NAME }
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
kmd("create ns #{namespace}")
|
10
|
+
kmd("delete cm #{cm_name} -n #{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) }
|
16
|
+
|
17
|
+
context "when the namespace does not exist" do
|
18
|
+
it "provisions accordingly" do
|
19
|
+
kmd("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
|
+
kmd("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
|
+
kmd("delete cm #{cm_name} -n #{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.read_write_ready?).to eq(true)
|
49
|
+
expect(backend.namespace_exists?).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
|
+
expect(result[:kind]).to eq('ConfigMap')
|
59
|
+
expect(result[:metadata][:name]).to eq('kerbi-state-tracker')
|
60
|
+
expect(result[:metadata][:namespace]).to eq('xyz')
|
61
|
+
expect(result[:data][:entries]).to eq("[]")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with some entries (for puts only, uncomment)" do
|
66
|
+
it "puts it" do
|
67
|
+
# entry = new_state("1", created_at: "2022-01-01T00:00:00+00:00")
|
68
|
+
# puts entry.to_h
|
69
|
+
# result = make_backend("xyz").template_resource([entry])
|
70
|
+
# puts result
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#namespace_exists?" do
|
76
|
+
context "when the namespace exists" do
|
77
|
+
it "returns true" do
|
78
|
+
expect(make_backend("default").namespace_exists?).to be_truthy
|
79
|
+
end
|
80
|
+
end
|
81
|
+
context "when the namespace does not exist" do
|
82
|
+
it "returns false" do
|
83
|
+
expect(make_backend("nope").namespace_exists?).to be_falsey
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "#apply_resource and #read_entries" do
|
89
|
+
let(:entries) do
|
90
|
+
[
|
91
|
+
new_state("one", message: "m-one", created_at: "2022-01-01T00:00:00+00:00"),
|
92
|
+
new_state("two", message: "m-two", created_at: "2022-02-01T00:00:00+00:00"),
|
93
|
+
]
|
94
|
+
end
|
95
|
+
|
96
|
+
it "creates a configmap with the right contents" do
|
97
|
+
subject = make_backend(namespace)
|
98
|
+
descriptor = subject.template_resource(entries)
|
99
|
+
subject.apply_resource(descriptor)
|
100
|
+
sleep(1)
|
101
|
+
actual = subject.send(:read_entries)
|
102
|
+
expect(actual.count).to eq(2)
|
103
|
+
|
104
|
+
actual_one = actual[0].values_at("tag", "message", "created_at")
|
105
|
+
expected_one = entries[0].to_h.values_at(:tag, :message, :created_at)
|
106
|
+
expect(actual_one).to eq(expected_one)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -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
|
data/spec/spec_helper.rb
CHANGED
@@ -5,6 +5,93 @@ SimpleCov.start
|
|
5
5
|
|
6
6
|
require_relative './../lib/kerbi'
|
7
7
|
|
8
|
+
def kmd(command)
|
9
|
+
opts = { err: File::NULL, out: File::NULL }
|
10
|
+
system("kubectl #{command} --context kind-kind", **opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [Kerbi::State::ConfigMapBackend]
|
14
|
+
def make_backend(namespace)
|
15
|
+
Kerbi::State::ConfigMapBackend.new(
|
16
|
+
Kerbi::Utils::K8sAuth.kube_config_bundle,
|
17
|
+
namespace
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def new_state(tag, dict={})
|
22
|
+
set = dict.delete(:state)
|
23
|
+
dict[:tag] = tag
|
24
|
+
Kerbi::State::Entry.from_dict(set, dict)
|
25
|
+
end
|
26
|
+
|
27
|
+
def new_state_set(bundles)
|
28
|
+
dicts = bundles.map { |kv| { tag: kv[0].to_s, **kv[1] } }
|
29
|
+
Kerbi::State::EntrySet.new(dicts)
|
30
|
+
end
|
31
|
+
|
32
|
+
def cli(command, escaped: false)
|
33
|
+
$stdout = StringIO.new
|
34
|
+
begin
|
35
|
+
command = command.split(" ") if command.is_a?(String)
|
36
|
+
Kerbi::Cli::RootHandler.start(command)
|
37
|
+
output = $stdout.string
|
38
|
+
$stdout = STDOUT
|
39
|
+
escaped ? output.gsub("\e", "\\e") : output
|
40
|
+
ensure
|
41
|
+
$stdout = STDOUT
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def load_exp_file(dir, file, ext)
|
46
|
+
path = "#{__dir__}/expectations/#{dir}/#{file}.#{ext}"
|
47
|
+
File.read(path)
|
48
|
+
end
|
49
|
+
|
50
|
+
def read_exp_file(dir, file, ext)
|
51
|
+
expected_str = load_exp_file(dir, file, ext)
|
52
|
+
if ext == 'json'
|
53
|
+
JSON.parse(expected_str)
|
54
|
+
elsif ext == 'yaml'
|
55
|
+
YAML.load_stream(expected_str)
|
56
|
+
else
|
57
|
+
expected_str.gsub(/\s+/, "")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def exp_cli_eq_file(cmd, dir, file, ext='txt')
|
62
|
+
actual_str = cli(cmd)
|
63
|
+
expected = read_exp_file(dir, file, ext)
|
64
|
+
|
65
|
+
if ext == 'json'
|
66
|
+
expect(JSON.parse(actual_str)).to eq(expected)
|
67
|
+
elsif ext == 'yaml'
|
68
|
+
actual = YAML.load_stream(actual_str)
|
69
|
+
expect(actual).to eq(expected)
|
70
|
+
else
|
71
|
+
actual = actual_str.gsub(/\s+/, "").gsub("\e", "\\e")
|
72
|
+
expect(actual).to eq(expected)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def hello_kerbi(cmd, namespace=nil)
|
77
|
+
target = "#{__dir__}/../examples/hello-kerbi"
|
78
|
+
cmd = "#{cmd} --project-root #{target}"
|
79
|
+
cmd = "#{cmd} --namespace #{namespace}" if namespace
|
80
|
+
cmd
|
81
|
+
end
|
82
|
+
|
83
|
+
def cmd_group_spec(cmd, dir, file, opts={})
|
84
|
+
(opts[:formats] || %w[yaml json table]).each do |format|
|
85
|
+
context "with --output-format #{format} #{opts[:context_append]}" do
|
86
|
+
it "echos the expected text" do
|
87
|
+
extension = format == 'table' ? "txt" : format
|
88
|
+
cmd_with_fmt = "#{cmd} -o #{format}"
|
89
|
+
exp_cli_eq_file(cmd_with_fmt, dir, file, extension)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
8
95
|
module Kerbi
|
9
96
|
module Testing
|
10
97
|
|
@@ -33,7 +120,6 @@ module Kerbi
|
|
33
120
|
system "rm -rf #{TEST_YAMLS_DIR}"
|
34
121
|
system "mkdir #{TEST_YAMLS_DIR}"
|
35
122
|
end
|
36
|
-
|
37
123
|
end
|
38
124
|
end
|
39
125
|
|