kubes 0.3.5 → 0.4.0
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/CHANGELOG.md +14 -0
- data/README.md +6 -5
- data/docs/_docs/config/args.md +10 -0
- data/docs/_docs/config/args/docker.md +19 -0
- data/docs/_docs/config/{kubectl/args.md → args/kubectl.md} +2 -0
- data/docs/_docs/config/docker.md +4 -40
- data/docs/_docs/config/hooks.md +10 -0
- data/docs/_docs/config/hooks/docker.md +70 -0
- data/docs/_docs/config/hooks/kubectl.md +83 -0
- data/docs/_docs/config/hooks/kubes.md +67 -0
- data/docs/_docs/config/hooks/ruby.md +74 -0
- data/docs/_docs/config/kubectl.md +2 -2
- data/docs/_docs/config/reference.md +20 -0
- data/docs/_docs/config/skip.md +58 -0
- data/docs/_docs/dsl/resources.md +1 -1
- data/docs/_docs/intro.md +3 -1
- data/docs/_docs/patterns/migrations.md +121 -0
- data/docs/_includes/config/hooks/options.md +20 -0
- data/docs/_includes/sidebar.html +25 -12
- data/docs/_sass/theme.scss +25 -1
- data/lib/kubes/cli.rb +20 -5
- data/lib/kubes/cli/apply.rb +2 -1
- data/lib/kubes/cli/base.rb +11 -0
- data/lib/kubes/cli/delete.rb +1 -1
- data/lib/kubes/cli/exec.rb +37 -6
- data/lib/kubes/cli/get.rb +1 -1
- data/lib/kubes/cli/logs.rb +27 -3
- data/lib/kubes/cli/prune.rb +95 -0
- data/lib/kubes/compiler.rb +18 -7
- data/lib/kubes/compiler/decorator/base.rb +7 -1
- data/lib/kubes/compiler/decorator/{resources/secret.rb → hashable.rb} +5 -4
- data/lib/kubes/compiler/decorator/hashable/field.rb +53 -0
- data/lib/kubes/compiler/decorator/hashable/storage.rb +19 -0
- data/lib/kubes/compiler/decorator/post.rb +77 -0
- data/lib/kubes/compiler/decorator/pre.rb +12 -0
- data/lib/kubes/compiler/strategy.rb +2 -2
- data/lib/kubes/compiler/strategy/base.rb +1 -1
- data/lib/kubes/compiler/strategy/result.rb +4 -6
- data/lib/kubes/config.rb +16 -11
- data/lib/kubes/docker/strategy/build/docker.rb +1 -1
- data/lib/kubes/docker/strategy/build/gcloud.rb +1 -1
- data/lib/kubes/docker/strategy/image_name.rb +1 -1
- data/lib/kubes/docker/strategy/push/docker.rb +1 -1
- data/lib/kubes/docker/strategy/push/gcloud.rb +1 -1
- data/lib/kubes/docker/strategy/utils.rb +1 -1
- data/lib/kubes/hooks/builder.rb +29 -15
- data/lib/kubes/hooks/concern.rb +10 -0
- data/lib/kubes/hooks/dsl.rb +2 -1
- data/lib/kubes/hooks/runner.rb +22 -0
- data/lib/kubes/kubectl.rb +21 -18
- data/lib/kubes/kubectl/batch.rb +8 -5
- data/lib/kubes/kubectl/{decider.rb → dispatcher.rb} +1 -1
- data/lib/kubes/kubectl/fetch/base.rb +12 -9
- data/lib/kubes/kubectl/fetch/deployment.rb +12 -13
- data/lib/kubes/kubectl/fetch/pods.rb +4 -15
- data/lib/kubes/kubectl/kustomize.rb +1 -1
- data/lib/kubes/kubectl/ordering.rb +12 -0
- data/lib/kubes/util/consider.rb +2 -1
- data/lib/kubes/util/sh.rb +1 -1
- data/lib/kubes/version.rb +1 -1
- data/spec/fixtures/decorators/deployment/both/envFrom.yaml +31 -0
- data/spec/fixtures/prune/capture.yaml +57 -0
- data/spec/fixtures/prune/fetch_items.yaml +268 -0
- data/spec/kubes/cli/prune_spec.rb +38 -0
- data/spec/kubes/compiler/decorator/{resources → post}/deployment_spec.rb +25 -6
- data/spec/kubes/compiler/decorator/{resources → post}/pod_spec.rb +2 -11
- metadata +35 -19
- data/docs/_docs/config/kubectl/hooks.md +0 -39
- data/lib/kubes/compiler/decorator.rb +0 -17
- data/lib/kubes/compiler/decorator/compile.rb +0 -12
- data/lib/kubes/compiler/decorator/resources/base.rb +0 -13
- data/lib/kubes/compiler/decorator/resources/container.rb +0 -76
- data/lib/kubes/compiler/decorator/resources/container/mapping.rb +0 -28
- data/lib/kubes/compiler/decorator/resources/deployment.rb +0 -10
- data/lib/kubes/compiler/decorator/resources/pod.rb +0 -10
- data/lib/kubes/compiler/decorator/write.rb +0 -14
- data/lib/kubes/docker/strategy/hooks.rb +0 -9
@@ -11,7 +11,7 @@ class Kubes::Compiler
|
|
11
11
|
|
12
12
|
strategy = klass.new(@options.merge(path: @path)) # Dsl or Erb
|
13
13
|
result = strategy.run
|
14
|
-
result.
|
14
|
+
result.decorate!(:pre) # compile pre phase decoration
|
15
15
|
result
|
16
16
|
end
|
17
17
|
|
@@ -19,7 +19,7 @@ class Kubes::Compiler
|
|
19
19
|
ext = File.extname(@path)
|
20
20
|
case ext
|
21
21
|
when '.rb' then Dsl
|
22
|
-
when '.yaml' then Erb
|
22
|
+
when '.yaml','.yml' then Erb
|
23
23
|
else Pass
|
24
24
|
end
|
25
25
|
end
|
@@ -7,7 +7,7 @@ class Kubes::Compiler::Strategy
|
|
7
7
|
@path = options[:path]
|
8
8
|
|
9
9
|
@filename = @path.sub(%r{.*\.kubes/resources/},'') # IE: web/deployment.rb or web/deployment.yaml
|
10
|
-
@save_file = @filename.sub('.rb','.yaml')
|
10
|
+
@save_file = @filename.sub('.yml','.yaml').sub('.rb','.yaml')
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -11,12 +11,10 @@ class Kubes::Compiler::Strategy
|
|
11
11
|
@data.respond_to?(:read)
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
def write_decorate!
|
19
|
-
@data = Kubes::Compiler::Decorator::Write.new(@data).result
|
14
|
+
# decorate(:pre) or decorate(:post)
|
15
|
+
def decorate!(phase)
|
16
|
+
klass = "Kubes::Compiler::Decorator::#{phase.to_s.camelize}".constantize
|
17
|
+
@data = klass.new(@data).result
|
20
18
|
end
|
21
19
|
|
22
20
|
def content
|
data/lib/kubes/config.rb
CHANGED
@@ -11,31 +11,36 @@ module Kubes
|
|
11
11
|
def defaults
|
12
12
|
config = ActiveSupport::OrderedOptions.new
|
13
13
|
|
14
|
-
config.
|
15
|
-
config.state.docker_image_path = "#{Kubes.root}/.kubes/state/docker_image.txt"
|
14
|
+
config.auto_prune = true
|
16
15
|
|
17
|
-
config.
|
18
|
-
config.logger.level = ENV['KUBES_LOG_LEVEL'] || :info
|
16
|
+
config.builder = "docker" # IE: docker or gcloud
|
19
17
|
|
20
18
|
# Auto-switching options
|
21
19
|
config.kubectl = ActiveSupport::OrderedOptions.new
|
22
20
|
config.kubectl.context = nil
|
23
21
|
config.kubectl.context_keep = true # after switching context keep it
|
24
|
-
config.kubectl.exit_on_fail = nil # whether or not continue if the kubectl command fails
|
25
22
|
|
26
|
-
|
27
|
-
config.kubectl.
|
28
|
-
|
23
|
+
# whether or not continue if the kubectl command fails
|
24
|
+
config.kubectl.exit_on_fail = ActiveSupport::OrderedOptions.new
|
25
|
+
config.kubectl.exit_on_fail.apply = true # whether or not continue if the kubectl apply command fails
|
26
|
+
config.kubectl.exit_on_fail.delete = false # whether or not continue if the kubectl delete command fails
|
27
|
+
# Note: delete is a internal method to ActiveSupport::OrderedOptions so will have to access it with ['...']
|
29
28
|
|
30
29
|
config.kubectl.order = ActiveSupport::OrderedOptions.new
|
31
30
|
config.kubectl.order.roles = role_order
|
32
31
|
config.kubectl.order.kinds = kind_order
|
33
32
|
|
34
|
-
config.suffix_hash = true # append suffix has to ConfigMap and Secret
|
35
|
-
|
36
33
|
config.repo = nil # expected to be set by .kubes/config.rb
|
37
34
|
|
38
|
-
config.
|
35
|
+
config.logger = Logger.new($stdout)
|
36
|
+
config.logger.level = ENV['KUBES_LOG_LEVEL'] || :info
|
37
|
+
|
38
|
+
config.skip = []
|
39
|
+
|
40
|
+
config.state = ActiveSupport::OrderedOptions.new
|
41
|
+
config.state.docker_image_path = "#{Kubes.root}/.kubes/state/docker_image.txt"
|
42
|
+
|
43
|
+
config.suffix_hash = true # append suffix hash to ConfigMap and Secret
|
39
44
|
|
40
45
|
config
|
41
46
|
end
|
@@ -61,7 +61,7 @@ module Kubes::Docker::Strategy
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def custom
|
64
|
-
custom = Kubes::Args::Custom.new(@name, "#{Kubes.root}/.kubes/config/docker
|
64
|
+
custom = Kubes::Args::Custom.new(@name, "#{Kubes.root}/.kubes/config/args/docker.rb")
|
65
65
|
custom.build
|
66
66
|
custom
|
67
67
|
end
|
data/lib/kubes/hooks/builder.rb
CHANGED
@@ -4,39 +4,53 @@ module Kubes::Hooks
|
|
4
4
|
include Dsl
|
5
5
|
include DslEvaluator
|
6
6
|
include Kubes::Logging
|
7
|
-
include Kubes::Util::Sh
|
8
7
|
|
9
8
|
attr_accessor :name
|
10
|
-
def initialize(
|
11
|
-
@
|
12
|
-
@
|
9
|
+
def initialize(dsl_file, options={})
|
10
|
+
@dsl_file, @options = dsl_file, options # IE: .kubes/config/hooks/kubectl.rb
|
11
|
+
@output_file = options[:file] # IE: .kubes/output/web/service.yaml
|
12
|
+
@name = options[:name].to_s
|
13
13
|
@hooks = {before: {}, after: {}}
|
14
14
|
end
|
15
15
|
|
16
16
|
def build
|
17
|
-
return @hooks unless File.exist?(@
|
18
|
-
evaluate_file(@
|
17
|
+
return @hooks unless File.exist?(@dsl_file)
|
18
|
+
evaluate_file(@dsl_file)
|
19
19
|
@hooks.deep_stringify_keys!
|
20
20
|
end
|
21
21
|
memoize :build
|
22
22
|
|
23
23
|
def run_hooks
|
24
24
|
build
|
25
|
-
|
25
|
+
run_each_hook("before")
|
26
26
|
out = yield if block_given?
|
27
|
-
|
27
|
+
run_each_hook("after")
|
28
28
|
out
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
31
|
+
def run_each_hook(type)
|
32
|
+
hooks = @hooks.dig(type, @name.to_s) || []
|
33
|
+
hooks.each do |hook|
|
34
|
+
run_hook(type, hook)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def run_hook(type, hook)
|
39
|
+
return unless run?(hook)
|
34
40
|
|
35
|
-
|
36
|
-
|
41
|
+
command = File.basename(@dsl_file).sub('.rb','') # IE: kubes, kubectl, docker
|
42
|
+
id = "#{command} #{type} #{@name}"
|
43
|
+
on = " on: #{hook["on"]}" if hook["on"]
|
44
|
+
label = " label: #{hook["label"]}" if hook["label"]
|
45
|
+
logger.info "Running #{id} hook.#{on}#{label}"
|
46
|
+
logger.debug "Hook options: #{hook}"
|
47
|
+
Runner.new(hook).run
|
48
|
+
end
|
37
49
|
|
38
|
-
|
39
|
-
|
50
|
+
def run?(hook)
|
51
|
+
return false unless hook["execute"]
|
52
|
+
return true unless hook["on"]
|
53
|
+
@output_file.include?(hook["on"])
|
40
54
|
end
|
41
55
|
end
|
42
56
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Kubes::Hooks
|
2
|
+
module Concern
|
3
|
+
# options example: {:name=>"apply", :file=>".kubes/output/web/service.yaml"}
|
4
|
+
def run_hooks(file, options={}, &block)
|
5
|
+
hooks = Kubes::Hooks::Builder.new("#{Kubes.root}/.kubes/config/hooks/#{file}", options)
|
6
|
+
hooks.build # build hooks
|
7
|
+
hooks.run_hooks(&block)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/kubes/hooks/dsl.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Kubes::Hooks
|
2
|
+
class Runner
|
3
|
+
include Kubes::Util::Sh
|
4
|
+
include Kubes::Logging
|
5
|
+
|
6
|
+
def initialize(hook)
|
7
|
+
@hook = hook
|
8
|
+
@execute = @hook["execute"]
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
case @execute
|
13
|
+
when String
|
14
|
+
sh(@execute, exit_on_fail: @hook["exit_on_fail"])
|
15
|
+
when -> (e) { e.respond_to?(:public_instance_methods) && e.public_instance_methods.include?(:call) }
|
16
|
+
@execute.new.call
|
17
|
+
else
|
18
|
+
@execute.call
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/kubes/kubectl.rb
CHANGED
@@ -2,6 +2,7 @@ module Kubes
|
|
2
2
|
class Kubectl
|
3
3
|
extend Memoist
|
4
4
|
include Kubes::Util::Sh
|
5
|
+
include Kubes::Hooks::Concern
|
5
6
|
|
6
7
|
def initialize(name, options={})
|
7
8
|
@name, @options = name, options
|
@@ -14,24 +15,19 @@ module Kubes
|
|
14
15
|
options[:exit_on_fail] = exit_on_fail unless exit_on_fail.nil?
|
15
16
|
|
16
17
|
params = args.flatten.join(' ')
|
17
|
-
|
18
|
+
args = "#{@name} #{params}" # @name: apply or delete
|
18
19
|
|
19
20
|
switch_context do
|
20
|
-
run_hooks(@name) do
|
21
|
+
run_hooks("kubectl.rb", name: @name, file: @options[:file]) do
|
21
22
|
if options[:capture]
|
22
|
-
capture(
|
23
|
+
self.class.capture(args, options) # already includes kubectl
|
23
24
|
else
|
24
|
-
|
25
|
+
self.class.execute(args, options)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
30
|
-
def execute(args, options={})
|
31
|
-
command = "kubectl #{args}"
|
32
|
-
capture(command)
|
33
|
-
end
|
34
|
-
|
35
31
|
# Useful for kustomize mode
|
36
32
|
def validate!
|
37
33
|
return true unless Kubes.kustomize?
|
@@ -44,9 +40,8 @@ module Kubes
|
|
44
40
|
end
|
45
41
|
|
46
42
|
def exit_on_fail
|
47
|
-
|
48
|
-
|
49
|
-
exit_on_fail.nil? ? kubectl.exit_on_fail : exit_on_fail
|
43
|
+
return false if ENV['KUBES_EXIT_ON_FAIL'] == '0'
|
44
|
+
Kubes.config.kubectl.exit_on_fail[@name]
|
50
45
|
end
|
51
46
|
|
52
47
|
def switch_context(&block)
|
@@ -65,12 +60,6 @@ module Kubes
|
|
65
60
|
end
|
66
61
|
end
|
67
62
|
|
68
|
-
def run_hooks(name, &block)
|
69
|
-
hooks = Kubes::Hooks::Builder.new(name, "#{Kubes.root}/.kubes/config/kubectl/hooks.rb")
|
70
|
-
hooks.build # build hooks
|
71
|
-
hooks.run_hooks(&block)
|
72
|
-
end
|
73
|
-
|
74
63
|
def args
|
75
64
|
# base at end in case of redirection. IE: command > /path
|
76
65
|
custom.args + default.args
|
@@ -90,9 +79,23 @@ module Kubes
|
|
90
79
|
memoize :default
|
91
80
|
|
92
81
|
class << self
|
82
|
+
include Kubes::Util::Sh
|
93
83
|
def run(name, options={})
|
94
84
|
new(name, options).run
|
95
85
|
end
|
86
|
+
|
87
|
+
def execute(args, options={})
|
88
|
+
sh("kubectl #{args}", options)
|
89
|
+
end
|
90
|
+
|
91
|
+
def capture(args, options={})
|
92
|
+
resp = sh_capture("kubectl #{args}", options)
|
93
|
+
if args.include?('-o json')
|
94
|
+
JSON.load(resp) # data
|
95
|
+
else
|
96
|
+
resp
|
97
|
+
end
|
98
|
+
end
|
96
99
|
end
|
97
100
|
end
|
98
101
|
end
|
data/lib/kubes/kubectl/batch.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class Kubes::Kubectl
|
2
2
|
class Batch
|
3
|
+
include Kubes::Hooks::Concern
|
3
4
|
include Kubes::Logging
|
4
5
|
include Kubes::Util::Consider
|
5
6
|
include Ordering
|
@@ -11,11 +12,13 @@ class Kubes::Kubectl
|
|
11
12
|
def run
|
12
13
|
# @options[:preview] is really only used for kubectl delete
|
13
14
|
logger.info "Will run:" if @options[:preview]
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
run_hooks("kubes.rb", name: @name) do
|
16
|
+
sorted_files.each do |file|
|
17
|
+
if @options[:preview]
|
18
|
+
logger.info " kubectl #{@name} -f #{file}"
|
19
|
+
else
|
20
|
+
Kubes::Kubectl.run(@name, @options.merge(file: file))
|
21
|
+
end
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
@@ -2,6 +2,7 @@ require "json"
|
|
2
2
|
|
3
3
|
module Kubes::Kubectl::Fetch
|
4
4
|
class Base
|
5
|
+
extend Memoist
|
5
6
|
include Kubes::Logging
|
6
7
|
include Kubes::Util::Sh
|
7
8
|
|
@@ -9,16 +10,18 @@ module Kubes::Kubectl::Fetch
|
|
9
10
|
@options = options
|
10
11
|
end
|
11
12
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
output: "json",
|
16
|
-
show_command: false,
|
17
|
-
}
|
18
|
-
kubectl = Kubes::Kubectl.new(:get, @options.merge(o)) # kubes get -f .kubes/output
|
19
|
-
resp = kubectl.run
|
20
|
-
data = JSON.load(resp)
|
13
|
+
def fetch(kind)
|
14
|
+
return [] unless namespace
|
15
|
+
data = Kubes::Kubectl.capture("get #{kind} -o json -n #{namespace}")
|
21
16
|
data['items'] || [] # Note: When fetching only 1 resource, items is not part of structure
|
22
17
|
end
|
18
|
+
|
19
|
+
def namespace
|
20
|
+
path = ".kubes/output/shared/namespace.yaml"
|
21
|
+
return unless File.exist?(path)
|
22
|
+
data = Kubes::Kubectl.capture("get -f #{path} -o json")
|
23
|
+
data['metadata']['name']
|
24
|
+
end
|
25
|
+
memoize :namespace
|
23
26
|
end
|
24
27
|
end
|
@@ -3,40 +3,39 @@ module Kubes::Kubectl::Fetch
|
|
3
3
|
extend Memoist
|
4
4
|
|
5
5
|
def metadata
|
6
|
-
deployment['metadata']
|
6
|
+
deployment['metadata'] if found
|
7
7
|
end
|
8
8
|
|
9
9
|
def spec
|
10
|
-
deployment['spec']
|
10
|
+
deployment['spec'] if found
|
11
11
|
end
|
12
12
|
|
13
13
|
def deployment
|
14
|
-
items =
|
14
|
+
items = fetch(:deployment)
|
15
15
|
# Not checking if deployment exists because kubes will error on `kubes get` from missing deployments already
|
16
16
|
deployments = items.select { |i| i['kind'] == "Deployment" }
|
17
17
|
|
18
|
-
if
|
18
|
+
if !@options[:deployment] && !@options[:pod] && deployments.size > 1
|
19
19
|
names = deployments.map { |d| d['metadata']['name'] }
|
20
20
|
logger.info <<~EOL
|
21
21
|
INFO: More than one deployment found.
|
22
22
|
Deployment names: #{names.join(', ')}
|
23
23
|
Using #{names.first}
|
24
|
-
Note: You can specify the deployment to use with --
|
24
|
+
Note: You can specify the deployment to use with --deployment or -d
|
25
25
|
EOL
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
unless deployment
|
30
|
-
logger.error "ERROR: No deployment found".color(:red)
|
31
|
-
exit 1
|
32
|
-
end
|
33
|
-
deployment
|
28
|
+
find_deployment(deployments)
|
34
29
|
end
|
35
30
|
memoize :deployment
|
36
31
|
|
32
|
+
def found
|
33
|
+
!!deployment
|
34
|
+
end
|
35
|
+
|
37
36
|
def find_deployment(deployments)
|
38
|
-
if @options[:
|
39
|
-
deployments.find { |d| d['metadata']['name'] == @options[:
|
37
|
+
if @options[:deployment]
|
38
|
+
deployments.find { |d| d['metadata']['name'] == @options[:deployment] }
|
40
39
|
else
|
41
40
|
deployments.first
|
42
41
|
end
|