kubes 0.3.2 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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