kubes 0.3.2 → 0.4.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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -0
  3. data/README.md +6 -5
  4. data/docs/_config.yml +1 -1
  5. data/docs/_docs/ci/cloudbuild.md +2 -0
  6. data/docs/_docs/config/args.md +10 -0
  7. data/docs/_docs/config/args/docker.md +19 -0
  8. data/docs/_docs/config/args/kubectl.md +19 -0
  9. data/docs/_docs/config/docker.md +4 -40
  10. data/docs/_docs/config/env.md +1 -1
  11. data/docs/_docs/config/hooks.md +10 -0
  12. data/docs/_docs/config/hooks/docker.md +70 -0
  13. data/docs/_docs/config/hooks/kubectl.md +83 -0
  14. data/docs/_docs/config/hooks/kubes.md +67 -0
  15. data/docs/_docs/config/hooks/ruby.md +74 -0
  16. data/docs/_docs/config/kubectl.md +3 -54
  17. data/docs/_docs/config/reference.md +20 -0
  18. data/docs/_docs/config/skip.md +58 -0
  19. data/docs/_docs/dsl/resources.md +1 -1
  20. data/docs/_docs/dsl/resources/backend_config.md +1 -1
  21. data/docs/_docs/intro.md +6 -3
  22. data/docs/_docs/learn/dsl/review-project.md +4 -2
  23. data/docs/_docs/learn/yaml/review-project.md +4 -2
  24. data/docs/_docs/{auto-context.md → misc/auto-context.md} +0 -0
  25. data/docs/_docs/{kustomize.md → misc/kustomize.md} +0 -0
  26. data/docs/_docs/misc/separate-steps.md +21 -0
  27. data/docs/_docs/patterns/migrations.md +121 -0
  28. data/docs/_includes/commands.html +2 -0
  29. data/docs/_includes/config/hooks/options.md +20 -0
  30. data/docs/_includes/sidebar.html +32 -10
  31. data/docs/_reference/kubes-exec.md +14 -6
  32. data/docs/_reference/kubes-init.md +1 -0
  33. data/docs/_reference/kubes-logs.md +1 -0
  34. data/docs/_sass/theme.scss +25 -1
  35. data/kubes.gemspec +3 -0
  36. data/lib/kubes.rb +3 -0
  37. data/lib/kubes/cli.rb +25 -6
  38. data/lib/kubes/cli/apply.rb +2 -1
  39. data/lib/kubes/cli/base.rb +11 -0
  40. data/lib/kubes/cli/compile.rb +8 -0
  41. data/lib/kubes/cli/delete.rb +1 -1
  42. data/lib/kubes/cli/exec.rb +37 -6
  43. data/lib/kubes/cli/get.rb +3 -2
  44. data/lib/kubes/cli/init.rb +39 -2
  45. data/lib/kubes/cli/logs.rb +50 -3
  46. data/lib/kubes/cli/prune.rb +95 -0
  47. data/lib/kubes/compiler.rb +11 -7
  48. data/lib/kubes/compiler/decorator/base.rb +7 -1
  49. data/lib/kubes/compiler/decorator/{resources/secret.rb → hashable.rb} +5 -4
  50. data/lib/kubes/compiler/decorator/hashable/field.rb +53 -0
  51. data/lib/kubes/compiler/decorator/hashable/storage.rb +19 -0
  52. data/lib/kubes/compiler/decorator/post.rb +77 -0
  53. data/lib/kubes/compiler/decorator/pre.rb +12 -0
  54. data/lib/kubes/compiler/strategy.rb +2 -2
  55. data/lib/kubes/compiler/strategy/base.rb +1 -1
  56. data/lib/kubes/compiler/strategy/result.rb +4 -6
  57. data/lib/kubes/config.rb +16 -11
  58. data/lib/kubes/docker/strategy/build/docker.rb +1 -1
  59. data/lib/kubes/docker/strategy/build/gcloud.rb +1 -1
  60. data/lib/kubes/docker/strategy/image_name.rb +1 -1
  61. data/lib/kubes/docker/strategy/push/docker.rb +1 -1
  62. data/lib/kubes/docker/strategy/push/gcloud.rb +1 -1
  63. data/lib/kubes/docker/strategy/utils.rb +1 -1
  64. data/lib/kubes/hooks/builder.rb +29 -15
  65. data/lib/kubes/hooks/concern.rb +10 -0
  66. data/lib/kubes/hooks/dsl.rb +2 -1
  67. data/lib/kubes/hooks/runner.rb +22 -0
  68. data/lib/kubes/kubectl.rb +21 -18
  69. data/lib/kubes/kubectl/batch.rb +8 -5
  70. data/lib/kubes/kubectl/{decider.rb → dispatcher.rb} +1 -1
  71. data/lib/kubes/kubectl/fetch/base.rb +13 -10
  72. data/lib/kubes/kubectl/fetch/deployment.rb +21 -11
  73. data/lib/kubes/kubectl/fetch/pods.rb +4 -15
  74. data/lib/kubes/kubectl/kustomize.rb +1 -1
  75. data/lib/kubes/kubectl/ordering.rb +12 -0
  76. data/lib/kubes/util/consider.rb +2 -1
  77. data/lib/kubes/util/sh.rb +1 -1
  78. data/lib/kubes/version.rb +1 -1
  79. data/lib/templates/dsl/.kubes/resources/base/all.rb.tt +6 -1
  80. data/lib/templates/dsl/.kubes/resources/shared/namespace.rb.tt +1 -1
  81. data/lib/templates/dsl/.kubes/resources/web/deployment.rb +1 -1
  82. data/lib/templates/yaml/.kubes/resources/base/all.yaml.tt +1 -1
  83. data/lib/templates/yaml/.kubes/resources/shared/namespace.yaml.tt +1 -1
  84. data/lib/templates/yaml/.kubes/resources/web/deployment.yaml.tt +1 -1
  85. data/spec/fixtures/decorators/deployment/both/envFrom.yaml +31 -0
  86. data/spec/fixtures/decorators/deployment/both/valueFrom.yaml +33 -0
  87. data/spec/fixtures/decorators/deployment/both/volumes.yaml +40 -0
  88. data/spec/fixtures/prune/capture.yaml +57 -0
  89. data/spec/fixtures/prune/fetch_items.yaml +268 -0
  90. data/spec/kubes/cli/prune_spec.rb +38 -0
  91. data/spec/kubes/compiler/decorator/{resources → post}/deployment_spec.rb +52 -6
  92. data/spec/kubes/compiler/decorator/{resources → post}/pod_spec.rb +2 -11
  93. metadata +56 -19
  94. data/lib/kubes/compiler/decorator.rb +0 -17
  95. data/lib/kubes/compiler/decorator/compile.rb +0 -12
  96. data/lib/kubes/compiler/decorator/resources/base.rb +0 -13
  97. data/lib/kubes/compiler/decorator/resources/container.rb +0 -76
  98. data/lib/kubes/compiler/decorator/resources/container/mapping.rb +0 -28
  99. data/lib/kubes/compiler/decorator/resources/deployment.rb +0 -10
  100. data/lib/kubes/compiler/decorator/resources/pod.rb +0 -10
  101. data/lib/kubes/compiler/decorator/write.rb +0 -14
  102. data/lib/kubes/docker/strategy/hooks.rb +0 -9
@@ -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
@@ -13,7 +13,8 @@ module Kubes::Hooks
13
13
  end
14
14
 
15
15
  def each_hook(type, name, props={})
16
- @hooks[type][name] = props
16
+ @hooks[type][name] ||= []
17
+ @hooks[type][name] << props
17
18
  end
18
19
  end
19
20
  end
@@ -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
@@ -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
- command = "kubectl #{@name} #{params}" # @name: apply or delete
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(command, options)
23
+ self.class.capture(args, options) # already includes kubectl
23
24
  else
24
- sh(command, options)
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
- kubectl = Kubes.config.kubectl
48
- exit_on_fail = kubectl.send("exit_on_fail_for_#{@name}")
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
@@ -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
- sorted_files.each do |file|
15
- if @options[:preview]
16
- logger.info " kubectl #{@name} -f #{file}"
17
- else
18
- Kubes::Kubectl.run(@name, @options.merge(file: file))
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
@@ -1,5 +1,5 @@
1
1
  class Kubes::Kubectl
2
- class Decider
2
+ class Dispatcher
3
3
  def initialize(name, options={})
4
4
  @name, @options = name.to_s, options
5
5
  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 fetch_items
13
- o = {
14
- capture: true,
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)
21
- data['items']
13
+ def fetch(kind)
14
+ return [] unless namespace
15
+ data = Kubes::Kubectl.capture("get #{kind} -o json -n #{namespace}")
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
@@ -1,31 +1,41 @@
1
1
  module Kubes::Kubectl::Fetch
2
2
  class Deployment < Base
3
+ extend Memoist
4
+
3
5
  def metadata
4
- items = fetch_items
6
+ deployment['metadata'] if found
7
+ end
8
+
9
+ def spec
10
+ deployment['spec'] if found
11
+ end
12
+
13
+ def deployment
14
+ items = fetch(:deployment)
5
15
  # Not checking if deployment exists because kubes will error on `kubes get` from missing deployments already
6
16
  deployments = items.select { |i| i['kind'] == "Deployment" }
7
17
 
8
- if deployments.size > 1 && !@options[:name]
18
+ if !@options[:deployment] && !@options[:pod] && deployments.size > 1
9
19
  names = deployments.map { |d| d['metadata']['name'] }
10
20
  logger.info <<~EOL
11
21
  INFO: More than one deployment found.
12
22
  Deployment names: #{names.join(', ')}
13
23
  Using #{names.first}
14
- Note: You can specify the deployment to use with --name or -n
24
+ Note: You can specify the deployment to use with --deployment or -d
15
25
  EOL
16
26
  end
17
27
 
18
- deployment = find_deployment(deployments)
19
- unless deployment
20
- logger.error "ERROR: No deployment found".color(:red)
21
- exit 1
22
- end
23
- deployment['metadata']
28
+ find_deployment(deployments)
29
+ end
30
+ memoize :deployment
31
+
32
+ def found
33
+ !!deployment
24
34
  end
25
35
 
26
36
  def find_deployment(deployments)
27
- if @options[:name]
28
- deployments.find { |d| d['metadata']['name'] == @options[:name] }
37
+ if @options[:deployment]
38
+ deployments.find { |d| d['metadata']['name'] == @options[:deployment] }
29
39
  else
30
40
  deployments.first
31
41
  end
@@ -1,21 +1,10 @@
1
1
  module Kubes::Kubectl::Fetch
2
2
  class Pods < Base
3
- def show
4
- items = fetch_items
5
- # Not checking if deployment exists because kubes will error on `kubes get` from missing deployments already
6
- deployments = items.select { |i| i['kind'] == "Deployment" }
7
-
8
- deployments.each do |deployment|
9
- logger.info "Pods for deployment #{deployment['metadata']['name']}:".color(:green)
10
- show_for(deployment)
11
- end
12
- end
3
+ extend Memoist
13
4
 
14
- def show_for(deployment)
15
- metadata = deployment['metadata']
16
- labels = metadata['labels'].map { |k,v| "#{k}=#{v}" }.join(',')
17
- ns = metadata['namespace']
18
- sh("kubectl get pod -l #{labels} -n #{ns}")
5
+ def show
6
+ return unless namespace
7
+ sh("kubectl get pod -n #{namespace}")
19
8
  end
20
9
  end
21
10
  end
@@ -5,7 +5,7 @@ class Kubes::Kubectl
5
5
 
6
6
  def detect?
7
7
  expr = "#{Kubes.root}/.kubes/resources/**/*"
8
- !!Dir.glob(expr).detect { |p| p.include?("kustomization.yaml") }
8
+ !!Dir.glob(expr).detect { |p| p.include?("kustomization.y") } # allow for both .yml and .yaml to work
9
9
  end
10
10
  memoize :detect?
11
11
  end
@@ -12,9 +12,21 @@ class Kubes::Kubectl
12
12
 
13
13
  "#{role_i}/#{kind_i}"
14
14
  end
15
+
16
+ sorted = filter_files(sorted)
17
+
15
18
  @name == "delete" ? sorted.reverse : sorted
16
19
  end
17
20
 
21
+ def filter_files(sorted)
22
+ skip = Kubes.config.skip
23
+ skip += ENV['KUBES_SKIP'].split(' ') if ENV['KUBES_SKIP']
24
+ return sorted if skip.empty?
25
+ sorted.reject do |file|
26
+ skip.detect { |text| file.include?(text) }
27
+ end
28
+ end
29
+
18
30
  # type: kinds or roles
19
31
  # value: Examples: kind: deployment, role: web
20
32
  def index_for(type, value)
@@ -3,7 +3,8 @@ module Kubes::Util
3
3
  def consider?(path)
4
4
  File.file?(path) &&
5
5
  !path.include?('/resources/base') &&
6
- !path.include?('/base.yaml')
6
+ !path.include?('/base.yaml') &&
7
+ !path.include?('/base.yml')
7
8
  end
8
9
  end
9
10
  end
@@ -30,7 +30,7 @@ module Kubes::Util
30
30
  success
31
31
  end
32
32
 
33
- def capture(command, options={})
33
+ def sh_capture(command, options={})
34
34
  exit_on_fail = options[:exit_on_fail].nil? ? true : options[:exit_on_fail]
35
35
  logger.info "=> #{command}" if options[:show_command]
36
36
  out = `#{command}`.strip
@@ -1,3 +1,3 @@
1
1
  module Kubes
2
- VERSION = "0.3.2"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -1,2 +1,7 @@
1
- namespace "<%= app %>"
1
+ <%
2
+ unless namespace == "default"
3
+ namespace_line = %Q|namespace "#{namespace}"\n|
4
+ end
5
+ -%>
6
+ <%= namespace_line if namespace_line -%>
2
7
  labels(app: "<%= app %>")
@@ -1,2 +1,2 @@
1
- name "<%= app %>"
1
+ name "<%= namespace %>"
2
2
  labels(app: "<%= app %>")
@@ -1,7 +1,7 @@
1
1
  name "web"
2
2
  labels(role: "web")
3
3
 
4
- replicas 1
4
+ replicas 1 # overridden on a env basis
5
5
  image built_image # IE: user/<%= app %>:kubes-2020-06-13T19-55-16-43afc6e
6
6
 
7
7
  # revisionHistoryLimit 1 # uncomment to reduce old ReplicaSets, default is 10 https://bit.ly/3hqrzyP
@@ -1,2 +1,2 @@
1
1
  metadata:
2
- namespace: <%= app %>
2
+ namespace: <%= namespace %>
@@ -1,6 +1,6 @@
1
1
  apiVersion: v1
2
2
  kind: Namespace
3
3
  metadata:
4
- name: <%= app %>
4
+ name: <%= namespace %>
5
5
  labels:
6
6
  app: <%= app %>
@@ -5,7 +5,7 @@ metadata:
5
5
  labels:
6
6
  role: web
7
7
  spec:
8
- replicas: 1
8
+ replicas: 1 # overridden on a env basis
9
9
  selector:
10
10
  matchLabels:
11
11
  role: web
@@ -0,0 +1,31 @@
1
+ ---
2
+ metadata:
3
+ namespace: default
4
+ labels:
5
+ app: demo
6
+ role: web
7
+ name: demo-web
8
+ spec:
9
+ selector:
10
+ matchLabels:
11
+ app: demo
12
+ role: web
13
+ template:
14
+ metadata:
15
+ labels:
16
+ app: demo
17
+ role: web
18
+ spec:
19
+ containers:
20
+ - name: demo-web
21
+ image: gcr.io/project/demo-web:kubes-2020-06-23T00-07-54
22
+ envFrom:
23
+ - secretRef:
24
+ name: demo-secret
25
+ - configMapRef:
26
+ name: demo-config-map
27
+ - configMapRef:
28
+ name: demo-config-map-2
29
+ replicas: 1
30
+ apiVersion: apps/v1
31
+ kind: Deployment
@@ -0,0 +1,33 @@
1
+ ---
2
+ metadata:
3
+ namespace: default
4
+ labels:
5
+ app: demo
6
+ role: web
7
+ name: demo-web
8
+ spec:
9
+ selector:
10
+ matchLabels:
11
+ app: demo
12
+ role: web
13
+ template:
14
+ metadata:
15
+ labels:
16
+ app: demo
17
+ role: web
18
+ spec:
19
+ containers:
20
+ - name: demo-web
21
+ image: gcr.io/project/demo-web:kubes-2020-06-23T00-07-54
22
+ env:
23
+ - name: MYSQL_ROOT_PASSWORD
24
+ valueFrom:
25
+ configMapKeyRef:
26
+ name: demo-config-map
27
+ key: password
28
+ secretKeyRef:
29
+ name: demo-secret
30
+ key: password
31
+ replicas: 1
32
+ apiVersion: apps/v1
33
+ kind: Deployment