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,87 @@
|
|
1
|
+
module Kerbi
|
2
|
+
module Utils
|
3
|
+
|
4
|
+
##
|
5
|
+
# ALl *_bundle methods return a custom-schema hash
|
6
|
+
# that is to be used to create a Kubeclient::Client instance.
|
7
|
+
# See its constructor docs to understand.
|
8
|
+
# Underlying lib credit: https://github.com/ManageIQ/kubeclient
|
9
|
+
module K8sAuth
|
10
|
+
|
11
|
+
##
|
12
|
+
# Auth using config/credentials from a local kube context
|
13
|
+
# entry.
|
14
|
+
# See https://github.com/ManageIQ/kubeclient#kubeclientconfig
|
15
|
+
def self.kube_config_bundle(path: nil, name: nil)
|
16
|
+
path = path || default_kube_config_path
|
17
|
+
config = Kubeclient::Config.read(path)
|
18
|
+
context = config.context(name)
|
19
|
+
|
20
|
+
{
|
21
|
+
endpoint: context.api_endpoint,
|
22
|
+
options: {
|
23
|
+
ssl_options: context.ssl_options,
|
24
|
+
auth_options: context.auth_options
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Basic username password auth.
|
31
|
+
# See https://github.com/ManageIQ/kubeclient#authentication
|
32
|
+
def self.basic_auth_bundle(username:, password:)
|
33
|
+
{
|
34
|
+
endpoint: "https://localhost:8443/api",
|
35
|
+
options: {
|
36
|
+
auth_options: {
|
37
|
+
username: username,
|
38
|
+
password: password
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Auth using explicit bearer token for each request.
|
46
|
+
# See https://github.com/ManageIQ/kubeclient#authentication
|
47
|
+
def self.token_auth_bundle(bearer_token:)
|
48
|
+
{
|
49
|
+
endpoint: "https://localhost:8443/api",
|
50
|
+
options: {
|
51
|
+
auth_options: {
|
52
|
+
bearer_token: bearer_token
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Auth if kerbi is inside a Kubernetes cluster. Uses default
|
60
|
+
# credentials in pod's filesystem. Likely requires extra
|
61
|
+
# RBAC resources for that service account to exist, e.g
|
62
|
+
# a few Roles/ClusterRoles and RoleBinding/ClusterRoleBindings
|
63
|
+
# in order for CRUD methods to actually work.
|
64
|
+
# See https://github.com/ManageIQ/kubeclient#middleware
|
65
|
+
def self.in_cluster_auth_bundle
|
66
|
+
token_path = '/var/run/secrets/kubernetes.io/serviceaccount/token'
|
67
|
+
ca_crt_path = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
68
|
+
auth_options = { bearer_token_file: token_path }
|
69
|
+
|
70
|
+
ssl_options = {}
|
71
|
+
ssl_options[:ca_file] = ca_crt_path if File.exist?(ca_crt_path)
|
72
|
+
|
73
|
+
{
|
74
|
+
endpoint: "https://kubernetes.default.svc",
|
75
|
+
options: {
|
76
|
+
auth_options: auth_options,
|
77
|
+
ssl_options: ssl_options
|
78
|
+
}
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.default_kube_config_path
|
83
|
+
ENV['KUBECONFIG'] || "#{Dir.home}/.kube/config"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/utils/misc.rb
CHANGED
@@ -16,7 +16,7 @@ module Kerbi
|
|
16
16
|
# @return [Array] subset of candidate filenames that are real filenames
|
17
17
|
def self.real_files_for(*candidates)
|
18
18
|
candidates.select do |fname|
|
19
|
-
File.exists?(fname)
|
19
|
+
File.exists?(fname) && !Dir.exists?(fname)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -36,6 +36,41 @@ module Kerbi
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Credit: https://gist.github.com/henrik/146844
|
42
|
+
# @param [Hash] hash_a
|
43
|
+
# @param [Hash] hash_b
|
44
|
+
def self.deep_hash_diff(hash_a, hash_b)
|
45
|
+
(hash_a.keys | hash_b.keys).inject({}) do |diff, k|
|
46
|
+
if hash_a[k] != hash_b[k]
|
47
|
+
if hash_a[k].is_a?(Hash) && hash_b[k].is_a?(Hash)
|
48
|
+
diff[k] = deep_hash_diff(hash_a[k], hash_b[k])
|
49
|
+
else
|
50
|
+
diff[k] = [hash_a[k], hash_b[k]]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
diff
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Credit: https://stackoverflow.com/a/195894/11913562
|
59
|
+
# @param [Time] other
|
60
|
+
# @return [String]
|
61
|
+
def self.pretty_time_elapsed(other)
|
62
|
+
a = (Time.now - other).to_i
|
63
|
+
case a
|
64
|
+
when 0 then 'just now'
|
65
|
+
when 1 then 'a second ago'
|
66
|
+
when 2..59 then a.to_s+' seconds ago'
|
67
|
+
when 60..119 then 'a minute ago' #120 = 2 minutes
|
68
|
+
when 120..3540 then (a/60).to_i.to_s+' minutes ago'
|
69
|
+
when 3541..7100 then 'an hour ago' # 3600 = 1 hour
|
70
|
+
when 7101..82800 then ((a+99)/3600).to_i.to_s+' hours ago'
|
71
|
+
else other.to_s
|
72
|
+
end
|
73
|
+
end
|
39
74
|
end
|
40
75
|
end
|
41
76
|
end
|
data/lib/utils/mixing.rb
CHANGED
data/lib/utils/values.rb
CHANGED
@@ -4,8 +4,6 @@ module Kerbi
|
|
4
4
|
# Utilities module for all value loading functionality.
|
5
5
|
module Values
|
6
6
|
|
7
|
-
DEFAULT_VALUE_PATH = "values"
|
8
|
-
|
9
7
|
def self.from_files(fname_exprs, **opts)
|
10
8
|
final_paths = resolve_fname_exprs(fname_exprs, **opts)
|
11
9
|
load_yaml_files(final_paths)
|
@@ -21,16 +19,24 @@ module Kerbi
|
|
21
19
|
# @param [Hash] opts downstream options for file-loading methods
|
22
20
|
# @return [Array<String>] list of unique absolute filenames
|
23
21
|
def self.resolve_fname_exprs(fname_exprs, **opts)
|
24
|
-
final_exprs =
|
22
|
+
final_exprs = fname_exprs.uniq
|
25
23
|
final_exprs.map do |fname_expr|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
24
|
+
candidate_paths = values_paths(fname_expr, **opts)
|
25
|
+
path = Kerbi::Utils::Misc.real_files_for(*candidate_paths)[0]
|
26
|
+
raise_if_file_not_found(fname_expr, path, **opts)
|
30
27
|
path.presence
|
31
28
|
end.compact.uniq
|
32
29
|
end
|
33
30
|
|
31
|
+
def self.raise_if_file_not_found(fname_expr, path, **opts)
|
32
|
+
if fname_expr != 'values' && !path
|
33
|
+
raise Kerbi::ValuesFileNotFoundError.new(
|
34
|
+
fname_expr: fname_expr,
|
35
|
+
root: opts[:root]
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
34
40
|
##
|
35
41
|
# Loads the dicts from files pointed to by final_file_paths into
|
36
42
|
# memory, and returns the deep-merged hash in the order of the files.
|
@@ -54,21 +60,6 @@ module Kerbi
|
|
54
60
|
end
|
55
61
|
end
|
56
62
|
|
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
63
|
##
|
73
64
|
# Parses a single cli-level key-value assignment with the form
|
74
65
|
# foo.bar=baz. Raises an exception if the expression is malformed.
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative './../spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe "$ kerbi config [COMMAND]" do
|
4
|
+
|
5
|
+
before(:each) { Kerbi::ConfigFile.reset }
|
6
|
+
|
7
|
+
describe "$ kerbi config show" do
|
8
|
+
it "outputs the expected text" do
|
9
|
+
exp_cli_eq_file("config show", "config", "show-default", "yaml")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "$ kerbi config set [ATTR] [VALUE]" do
|
14
|
+
let(:cmd) { "config set namespace kerbi-spec" }
|
15
|
+
context "for a legal assignment" do
|
16
|
+
it "outputs the expected text and changes the value" do
|
17
|
+
exp_cli_eq_file(cmd, "config", "set", "txt")
|
18
|
+
new_value = Kerbi::ConfigFile.read["namespace"]
|
19
|
+
expect(new_value).to eq("kerbi-spec")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
context "for an illegal assignment" do
|
23
|
+
let(:cmd){ "config set bad-key fail" }
|
24
|
+
it "outputs the expected error message" do
|
25
|
+
exp_cli_eq_file(cmd, "config", "bad-set", "txt")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "$ kerbi config get [ATTR]" do
|
31
|
+
let(:cmd) { "config get namespace" }
|
32
|
+
it "outputs the expected text and changes the value" do
|
33
|
+
cli("config set namespace kerbi-spec")
|
34
|
+
expect(cli(cmd).gsub(/\s+/, "")).to eq("kerbi-spec")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require_relative './../spec_helper'
|
2
|
+
require 'io/console'
|
3
|
+
|
4
|
+
RSpec.describe "$ kerbi [COMMAND]" do
|
5
|
+
let(:namespace) { "kerbi-spec" }
|
6
|
+
let(:cm_name) { Kerbi::State::Consts::RESOURCE_NAME }
|
7
|
+
let(:exps_dir) { "root" }
|
8
|
+
let(:root_dir) { "#{__dir__}/../../examples/hello-kerbi" }
|
9
|
+
|
10
|
+
spec_bundles = [
|
11
|
+
["", "template"],
|
12
|
+
["-f production", "template-production"],
|
13
|
+
["-f production --set pod.image=ubuntu", "template-inlines"]
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
describe "$ kerbi template" do
|
17
|
+
|
18
|
+
context "without state" do
|
19
|
+
spec_bundles.each do |bundle|
|
20
|
+
context "with #{bundle[0].presence || "no args"}" do
|
21
|
+
it "echos the expected text" do
|
22
|
+
cmd = hello_kerbi("template foo #{bundle[0]}")
|
23
|
+
exp_cli_eq_file(cmd, "root", bundle[1], "yaml")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "with with state" do
|
30
|
+
|
31
|
+
let(:backend){ make_backend(namespace) }
|
32
|
+
|
33
|
+
before :each do
|
34
|
+
kmd("create ns #{namespace}")
|
35
|
+
kmd("delete cm #{cm_name} -n #{namespace}")
|
36
|
+
backend = make_backend(namespace)
|
37
|
+
backend.provision_missing_resources(quiet: true)
|
38
|
+
end
|
39
|
+
|
40
|
+
def exp_vals(which)
|
41
|
+
str_keyed_hash = read_exp_file("root", "values", "json")
|
42
|
+
str_keyed_hash.deep_symbolize_keys[which.to_sym]
|
43
|
+
end
|
44
|
+
|
45
|
+
def template_write_cmd(pod_image)
|
46
|
+
base_cmd = "template foo --set pod.image=#{pod_image} --write-state foo"
|
47
|
+
hello_kerbi(base_cmd, namespace)
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with writing" do
|
51
|
+
before :each do
|
52
|
+
cmd = template_write_cmd("centos")
|
53
|
+
exp_cli_eq_file(cmd, "root", "template-write", "yaml")
|
54
|
+
end
|
55
|
+
|
56
|
+
context "--write-state when the entry does not yet exist" do
|
57
|
+
it "creates a new entry with the expected values" do
|
58
|
+
entry = backend.entries[0]
|
59
|
+
expect(backend.entries.count).to eq(1)
|
60
|
+
expect(entry.tag).to eq("foo")
|
61
|
+
expect(entry.values).to eq(exp_vals("centos"))
|
62
|
+
expect(entry.default_values).to eq(exp_vals("nginx"))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "--write-state with an existing state entry" do
|
67
|
+
it "updates the existing entry with the expected values" do
|
68
|
+
cli(template_write_cmd("centos"))
|
69
|
+
cli(template_write_cmd("debian"))
|
70
|
+
expect(backend.entries.count).to eq(1)
|
71
|
+
entry = backend.entries[0]
|
72
|
+
expect(entry.tag).to eq("foo")
|
73
|
+
expect(entry.values).to eq(exp_vals("debian"))
|
74
|
+
expect(entry.default_values).to eq(exp_vals("nginx"))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "--read-state with an existing state entry" do
|
80
|
+
before(:each) { cli(template_write_cmd("centos")) }
|
81
|
+
|
82
|
+
context "without inline overrides" do
|
83
|
+
it "echos the expected text" do
|
84
|
+
cmd = hello_kerbi("template foo --read-state foo", namespace)
|
85
|
+
exp_cli_eq_file(cmd, "root", "template-read", "yaml")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "with inline overrides" do
|
90
|
+
it "echos the expected text, preferring the inline over the state" do
|
91
|
+
base = "template foo --read-state foo --set pod.image=busybox"
|
92
|
+
cmd = hello_kerbi(base, namespace)
|
93
|
+
exp_cli_eq_file(cmd, "root", "template-read-inlines", "yaml")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require_relative './../spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe "$ kerbi state [COMMAND]" do
|
4
|
+
|
5
|
+
let(:namespace) { "kerbi-spec" }
|
6
|
+
let(:cm_name) { Kerbi::State::Consts::RESOURCE_NAME }
|
7
|
+
let(:exps_dir) { "state" }
|
8
|
+
|
9
|
+
let(:set) do
|
10
|
+
new_state_set(
|
11
|
+
one: { values: {x: "x"}, created_at: Time.new(2000).to_s },
|
12
|
+
two: { message: "message", created_at: Time.new(2001).to_s },
|
13
|
+
"[cand]-three".to_sym => { created_at: Time.new(2002).to_s },
|
14
|
+
"[cand]-four".to_sym => { created_at: Time.new(2003).to_s }
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
before :each do
|
19
|
+
kmd("create ns #{namespace}")
|
20
|
+
kmd("delete cm #{cm_name} -n #{namespace}")
|
21
|
+
backend = make_backend(namespace)
|
22
|
+
configmap_dict = backend.template_resource(set.entries)
|
23
|
+
backend.apply_resource(configmap_dict)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "$ kerbi state init" do
|
27
|
+
let(:cmd) { "state init kerbi-spec" }
|
28
|
+
context "when resources already existed" do
|
29
|
+
it "echoes the correct text" do
|
30
|
+
exp_cli_eq_file(cmd, exps_dir, "init-already-existed")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when the resources did not exist" do
|
35
|
+
it "echoes the correct text" do
|
36
|
+
kmd("delete ns #{namespace}")
|
37
|
+
exp_cli_eq_file(cmd, exps_dir, "init-both-created")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "$ kerbi state status" do
|
43
|
+
let(:cmd) { "state status -n #{namespace}" }
|
44
|
+
context "when everything is ready" do
|
45
|
+
it "echoes the correct text" do
|
46
|
+
exp_cli_eq_file(cmd, exps_dir, "status-all-working")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when connected but resources not provisioned" do
|
51
|
+
it "echoes the correct text" do
|
52
|
+
kmd("delete ns #{namespace}")
|
53
|
+
exp_cli_eq_file(cmd, exps_dir, "status-not-provisioned")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "$ kerbi state list" do
|
59
|
+
cmd_group_spec("state list -n kerbi-spec", "state", "list")
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "$ kerbi state show [TAG]" do
|
63
|
+
cmd_group_spec(
|
64
|
+
"state show one -n kerbi-spec",
|
65
|
+
"state",
|
66
|
+
"show"
|
67
|
+
)
|
68
|
+
|
69
|
+
cmd_group_spec(
|
70
|
+
"state show @oldest -n kerbi-spec",
|
71
|
+
"state",
|
72
|
+
"show",
|
73
|
+
context_append: " using @oldest instead of a literal tag"
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "$ kerbi state retag [OLD_TAG] [NEW_TAG]" do
|
78
|
+
def make_cmd(old_tag)
|
79
|
+
"state retag #{old_tag} born-again -n #{namespace}"
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when the old tag exists" do
|
83
|
+
context "using a literal tag" do
|
84
|
+
it "echos the expected text" do
|
85
|
+
exp_cli_eq_file(make_cmd("two"), exps_dir, "retag")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "using @latest or @oldest" do
|
90
|
+
it "echos the expected text" do
|
91
|
+
exp_cli_eq_file(make_cmd("@latest"), exps_dir, "retag")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "when the old tag does not exist" do
|
97
|
+
it "echos the expected text" do
|
98
|
+
exp_cli_eq_file(make_cmd("bad-tag"), "common", "bad-tag")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "$ kerbi state promote" do
|
104
|
+
let(:cmd) { "state promote @candidate -n #{namespace}" }
|
105
|
+
it "echos the expected text" do
|
106
|
+
exp_cli_eq_file(cmd, exps_dir, "promote")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "$ kerbi state demote" do
|
111
|
+
let(:cmd) { "state demote @latest -n #{namespace}" }
|
112
|
+
it "echos the expected text" do
|
113
|
+
exp_cli_eq_file(cmd, exps_dir, "demote")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "$ kerbi state set" do
|
118
|
+
let(:easy_part) { "state set @latest message" }
|
119
|
+
let(:cmd) { easy_part.split(" ") + ["new message", "-n", namespace] }
|
120
|
+
it "echos the expected text" do
|
121
|
+
exp_cli_eq_file(cmd, exps_dir, "set")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "$ kerbi state delete" do
|
126
|
+
let(:cmd) { "state delete @latest -n #{namespace}" }
|
127
|
+
it "echos the expected text" do
|
128
|
+
exp_cli_eq_file(cmd, exps_dir, "delete")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "$ kerbi state prune-candidates" do
|
133
|
+
let(:cmd) { "state prune-candidates -n #{namespace}" }
|
134
|
+
it "echos the expected text" do
|
135
|
+
exp_cli_eq_file(cmd, exps_dir, "prune-candidates")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative './../spec_helper'
|
2
|
+
require 'io/console'
|
3
|
+
|
4
|
+
RSpec.describe "$ kerbi values [COMMAND]" do
|
5
|
+
let(:namespace) { "kerbi-spec" }
|
6
|
+
|
7
|
+
describe "$ kerbi values show" do
|
8
|
+
context "without state" do
|
9
|
+
it "respects --set > -f > defaults" do
|
10
|
+
base = "values show -f v2 -f production --set service.type=NodePort"
|
11
|
+
cmd = hello_kerbi(base)
|
12
|
+
exp_cli_eq_file(cmd, "values", "order-of-precedence", "yaml")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
\e[1;31;49mState given by tag bad-tag not found\e[0m
|
@@ -0,0 +1 @@
|
|
1
|
+
\e[1;31;49mIllegal config assignment. 'bad-key' not in ["state-backend", "namespace", "auth-type", "kube-config-context", "username", "password", "token"]\e[0m
|
@@ -0,0 +1 @@
|
|
1
|
+
\e[0;32;49mUpdated config[namespace] from => kerbi-spec\e[0m
|
@@ -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: ubuntu: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: LoadBalancer
|
28
|
+
selector:
|
29
|
+
app: hello-kerbi
|
30
|
+
ports:
|
31
|
+
- port: 80
|
@@ -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: LoadBalancer
|
28
|
+
selector:
|
29
|
+
app: hello-kerbi
|
30
|
+
ports:
|
31
|
+
- port: 80
|
@@ -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: busybox: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,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: centos: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,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: centos: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
|