kubes 0.4.7 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/docs/_docs/config/reference.md +1 -0
  4. data/docs/_docs/config/skip.md +1 -1
  5. data/docs/_docs/dsl/multiple-resources.md +3 -3
  6. data/docs/_docs/dsl/resources/job.md +62 -0
  7. data/docs/_docs/extra-env/dsl.md +2 -2
  8. data/docs/_docs/extra-env/yaml.md +1 -1
  9. data/docs/_docs/generators.md +41 -0
  10. data/docs/_docs/helpers.md +2 -2
  11. data/docs/_docs/helpers/google/service-account.md +8 -0
  12. data/docs/_docs/intro.md +3 -1
  13. data/docs/_docs/intro/docker-image.md +66 -0
  14. data/docs/_docs/layering/merge.md +1 -1
  15. data/docs/_docs/learn/dsl/delete.md +10 -2
  16. data/docs/_docs/learn/dsl/review-project.md +2 -2
  17. data/docs/_docs/learn/yaml/delete.md +10 -2
  18. data/docs/_docs/learn/yaml/review-project.md +2 -2
  19. data/docs/_docs/patterns/clock-web-worker.md +3 -3
  20. data/docs/_docs/patterns/migrations.md +1 -1
  21. data/docs/_docs/yaml.md +2 -2
  22. data/docs/_includes/commands.html +2 -2
  23. data/docs/_includes/sidebar.html +2 -0
  24. data/docs/_reference/kubes-delete.md +1 -1
  25. data/docs/_reference/kubes-exec.md +17 -1
  26. data/docs/_reference/kubes-init.md +2 -2
  27. data/docs/_reference/kubes-logs.md +2 -1
  28. data/docs/_reference/kubes-new.md +58 -0
  29. data/docs/_reference/kubes-prune.md +22 -0
  30. data/docs/reference.md +2 -0
  31. data/lib/kubes.rb +1 -0
  32. data/lib/kubes/cli.rb +9 -1
  33. data/lib/kubes/cli/build.rb +6 -0
  34. data/lib/kubes/cli/compile.rb +7 -0
  35. data/lib/kubes/cli/deploy.rb +1 -6
  36. data/lib/kubes/cli/exec.rb +5 -1
  37. data/lib/kubes/cli/help/exec.md +15 -0
  38. data/lib/kubes/cli/help/new.md +30 -0
  39. data/lib/kubes/cli/init.rb +1 -1
  40. data/lib/kubes/cli/new.rb +97 -0
  41. data/lib/kubes/cli/sequence.rb +1 -0
  42. data/lib/kubes/command.rb +7 -0
  43. data/lib/kubes/compiler.rb +19 -21
  44. data/lib/kubes/compiler/dsl/syntax/job.rb +217 -0
  45. data/lib/kubes/compiler/shared/helpers.rb +11 -2
  46. data/lib/kubes/compiler/shared/helpers/deprecated.rb +37 -0
  47. data/lib/kubes/config.rb +1 -1
  48. data/lib/kubes/core.rb +6 -0
  49. data/lib/kubes/docker/strategy/image_name.rb +1 -1
  50. data/lib/kubes/kubectl/batch.rb +0 -33
  51. data/lib/kubes/kubectl/ordering.rb +42 -0
  52. data/lib/kubes/version.rb +1 -1
  53. data/lib/templates/base/.kubes/config.rb.tt +1 -1
  54. data/lib/templates/base/.kubes/config/env/dev.rb +1 -1
  55. data/lib/templates/base/.kubes/config/env/prod.rb +1 -1
  56. data/lib/templates/dsl/.kubes/resources/web/deployment.rb +1 -1
  57. data/lib/templates/new/dsl/backend_config.rb +10 -0
  58. data/lib/templates/new/dsl/config_map.rb +5 -0
  59. data/lib/templates/new/dsl/daemon_set.rb +11 -0
  60. data/lib/templates/new/dsl/deployment.rb +4 -0
  61. data/lib/templates/new/dsl/ingress.rb +3 -0
  62. data/lib/templates/new/dsl/job.rb +2 -0
  63. data/lib/templates/new/dsl/managed_certificate.rb +2 -0
  64. data/lib/templates/new/dsl/namespace.rb +2 -0
  65. data/lib/templates/new/dsl/network_policy.rb +7 -0
  66. data/lib/templates/new/dsl/pod.rb +6 -0
  67. data/lib/templates/new/dsl/role.rb +4 -0
  68. data/lib/templates/new/dsl/role_binding.rb +7 -0
  69. data/lib/templates/new/dsl/secret.rb +5 -0
  70. data/lib/templates/new/dsl/service.rb +2 -0
  71. data/lib/templates/new/dsl/service_account.rb +1 -0
  72. data/lib/templates/new/yaml/backend_config.yaml +10 -0
  73. data/lib/templates/new/yaml/config_map.yaml +9 -0
  74. data/lib/templates/new/yaml/daemon_set.yaml +11 -0
  75. data/lib/templates/new/yaml/deployment.yaml +20 -0
  76. data/lib/templates/new/yaml/ingress.yaml +12 -0
  77. data/lib/templates/new/yaml/job.yaml +19 -0
  78. data/lib/templates/new/yaml/managed_certificate.yaml +7 -0
  79. data/lib/templates/new/yaml/namespace.yaml +6 -0
  80. data/lib/templates/new/yaml/network_policy.yaml +20 -0
  81. data/lib/templates/new/yaml/pod.yaml +11 -0
  82. data/lib/templates/new/yaml/role.yaml +13 -0
  83. data/lib/templates/new/yaml/role_binding.yaml +11 -0
  84. data/lib/templates/new/yaml/secret.yaml +9 -0
  85. data/lib/templates/new/yaml/service.yaml +14 -0
  86. data/lib/templates/new/yaml/service_account.yaml +4 -0
  87. data/lib/templates/yaml/.kubes/resources/base/all.yaml.tt +2 -0
  88. data/lib/templates/yaml/.kubes/resources/web/deployment.yaml.tt +1 -1
  89. data/spec/kubes/cli/prune_spec.rb +1 -0
  90. data/spec/kubes/compiler_spec.rb +5 -1
  91. metadata +41 -2
@@ -3,6 +3,7 @@ require 'thor'
3
3
  class Kubes::CLI
4
4
  class Sequence < Thor::Group
5
5
  include Thor::Actions
6
+ include Kubes::Logging
6
7
 
7
8
  private
8
9
  def logger
@@ -28,6 +28,8 @@ module Kubes
28
28
  class Command < Thor
29
29
  class << self
30
30
  def dispatch(m, args, options, config)
31
+ check_project!(args.first)
32
+
31
33
  # Allow calling for help via:
32
34
  # kubes command help
33
35
  # kubes command -h
@@ -54,6 +56,11 @@ module Kubes
54
56
  super
55
57
  end
56
58
 
59
+ def check_project!(command_name)
60
+ return if %w[init new].include?(command_name)
61
+ Kubes.check_project!
62
+ end
63
+
57
64
  # Override command_help to include the description at the top of the
58
65
  # long_description.
59
66
  def command_help(shell, command_name)
@@ -3,6 +3,7 @@ module Kubes
3
3
  include Kubes::Hooks::Concern
4
4
  include Kubes::Logging
5
5
  include Kubes::Util::Consider
6
+ include Kubes::Kubectl::Ordering
6
7
 
7
8
  def initialize(options={})
8
9
  @options = options
@@ -21,7 +22,9 @@ module Kubes
21
22
  end
22
23
  end
23
24
 
24
- puts "Compiled .kubes/resources files to .kubes/output" if show_compiled_message?
25
+ write_full
26
+
27
+ logger.info "Compiled .kubes/resources files to .kubes/output" if show_compiled_message?
25
28
  end
26
29
 
27
30
  def resources
@@ -34,24 +37,6 @@ module Kubes
34
37
  paths
35
38
  end
36
39
 
37
- # Only considering files 2 layers deep. So:
38
- #
39
- # Yes = web/deployment.yaml
40
- # No = web/deployment/dev.yaml
41
- #
42
- def process?(path)
43
- if Kubes.kustomize?
44
- File.file?(path)
45
- else
46
- consider?(path) && two_levels_deep?(path)
47
- end
48
- end
49
-
50
- def two_levels_deep?(path)
51
- rel_path = path.sub(%r{.*\.kubes/resources/},'')
52
- rel_path.split('/').size == 2
53
- end
54
-
55
40
  def write(result)
56
41
  result.decorate!(:post)
57
42
  filename, content = result.filename, result.content
@@ -64,12 +49,25 @@ module Kubes
64
49
  IO.write(dest, content)
65
50
  end
66
51
 
67
- pretty_dest = dest.sub("#{Kubes.root}/",'')
68
- logger.debug "Compiled #{pretty_dest}"
52
+ logger.debug "Compiled #{pretty(dest)}"
53
+ end
54
+
55
+ def write_full
56
+ full = sorted_files.inject([]) do |acc, file|
57
+ acc << IO.read(file)
58
+ end
59
+ content = full.join("\n")
60
+ path = "#{Kubes.root}/.kubes/output/full.yaml"
61
+ IO.write(path, content)
62
+ logger.debug "Compiled #{pretty(path)}"
69
63
  end
70
64
 
71
65
  def show_compiled_message?
72
66
  !%w[g ge get].include?(ARGV.first)
73
67
  end
68
+
69
+ def pretty(path)
70
+ path.sub("#{Kubes.root}/",'')
71
+ end
74
72
  end
75
73
  end
@@ -0,0 +1,217 @@
1
+ module Kubes::Compiler::Dsl::Syntax
2
+ class Job < Resource
3
+ fields :container, # <Object>
4
+ "matchLabels:hash", # <map[string]string>
5
+ :sidecar, # <Object>
6
+ :sidecar_name, # <string>
7
+ :sidecar_image, # <string>
8
+ :templateMetadata, # <Object>
9
+ :templateSpec # <Object>
10
+
11
+ # kubectl explain job.spec
12
+ fields :activeDeadlineSeconds, # <integer>
13
+ :backoffLimit, # <integer>
14
+ :completions, # <integer>
15
+ :manualSelector, # <boolean>
16
+ :parallelism, # <integer>
17
+ :selector, # <Object>
18
+ :template, # <Object> -required-
19
+ :ttlSecondsAfterFinished # <integer>
20
+
21
+
22
+ # kubectl explain job.spec.template.spec
23
+ fields :activeDeadlineSeconds, # <integer>
24
+ :affinity, # <Object>
25
+ :automountServiceAccountToken, # <boolean>
26
+ :containers, # <[]Object> -required-
27
+ :dnsConfig, # <Object>
28
+ :dnsPolicy, # <string>
29
+ :enableServiceLinks, # <boolean>
30
+ :ephemeralContainers, # <[]Object>
31
+ :hostAliases, # <[]Object>
32
+ :hostIPC, # <boolean>
33
+ :hostNetwork, # <boolean>
34
+ :hostPID, # <boolean>
35
+ :hostname, # <string>
36
+ :imagePullSecrets, # <[]Object>
37
+ :initContainers, # <[]Object>
38
+ :nodeName, # <string>
39
+ :nodeSelector, # <map[string]string>
40
+ :overhead, # <map[string]string>
41
+ :preemptionPolicy, # <string>
42
+ :priority, # <integer>
43
+ :priorityClassName, # <string>
44
+ :readinessGates, # <[]Object>
45
+ :restartPolicy, # <string>
46
+ :runtimeClassName, # <string>
47
+ :schedulerName, # <string>
48
+ :securityContext, # <Object>
49
+ :serviceAccount, # <string>
50
+ :serviceAccountName, # <string>
51
+ :shareProcessNamespace, # <boolean>
52
+ :subdomain, # <string>
53
+ :terminationGracePeriodSeconds,# <integer>
54
+ :tolerations, # <[]Object>
55
+ :topologySpreadConstraints, # <[]Object>
56
+ :volumes # <[]Object>
57
+
58
+ # kubectl explain deployment.spec.template.spec.containers
59
+ fields :args, # <[]string>
60
+ :command, # <[]string>
61
+ :env, # <[]Object>
62
+ :envFrom, # <[]Object>
63
+ :image, # <string>
64
+ :imagePullPolicy, # <string>
65
+ :lifecycle, # <Object>
66
+ :livenessProbe, # <Object>
67
+ :containerName, # <string> -required- (originally called name)
68
+ :ports, # <[]Object>
69
+ :readinessProbe, # <Object>
70
+ :resources, # <Object>
71
+ :securityContext, # <Object>
72
+ :startupProbe, # <Object>
73
+ :stdin, # <boolean>
74
+ :stdinOnce, # <boolean>
75
+ :terminationMessagePath, # <string>
76
+ :terminationMessagePolicy, # <string>
77
+ :tty, # <boolean>
78
+ :volumeDevices, # <[]Object>
79
+ :volumeMounts, # <[]Object>
80
+ :workingDir # <string>
81
+
82
+ # kubectl explain deployment.spec.template.spec.containers.ports
83
+ fields :containerPort, # <integer> -required-
84
+ :hostIP, # <string>
85
+ :hostPort, # <integer>
86
+ :portName, # <string> (originally called name)
87
+ :protocol # <string>
88
+
89
+ def default_apiVersion
90
+ "batch/v1"
91
+ end
92
+
93
+ def default_spec
94
+ {
95
+ activeDeadlineSeconds: activeDeadlineSeconds,
96
+ backoffLimit: backoffLimit,
97
+ completions: completions,
98
+ manualSelector: manualSelector,
99
+ parallelism: parallelism,
100
+ selector: selector,
101
+ template: template,
102
+ ttlSecondsAfterFinished: ttlSecondsAfterFinished,
103
+ }
104
+ end
105
+
106
+ def default_matchLabels
107
+ labels
108
+ end
109
+
110
+ def default_template
111
+ {
112
+ metadata: templateMetadata,
113
+ spec: templateSpec,
114
+ }
115
+ end
116
+
117
+ def default_templateSpec
118
+ {
119
+ activeDeadlineSeconds: activeDeadlineSeconds,
120
+ affinity: affinity,
121
+ automountServiceAccountToken: automountServiceAccountToken,
122
+ containers: containers,
123
+ dnsConfig: dnsConfig,
124
+ dnsPolicy: dnsPolicy,
125
+ enableServiceLinks: enableServiceLinks,
126
+ ephemeralContainers: ephemeralContainers,
127
+ hostAliases: hostAliases,
128
+ hostIPC: hostIPC,
129
+ hostNetwork: hostNetwork,
130
+ hostPID: hostPID,
131
+ hostname: hostname,
132
+ imagePullSecrets: imagePullSecrets,
133
+ initContainers: initContainers,
134
+ nodeName: nodeName,
135
+ nodeSelector: nodeSelector,
136
+ overhead: overhead,
137
+ preemptionPolicy: preemptionPolicy,
138
+ priority: priority,
139
+ priorityClassName: priorityClassName,
140
+ readinessGates: readinessGates,
141
+ restartPolicy: restartPolicy,
142
+ runtimeClassName: runtimeClassName,
143
+ schedulerName: schedulerName,
144
+ securityContext: securityContext,
145
+ serviceAccount: serviceAccount,
146
+ serviceAccountName: serviceAccountName,
147
+ shareProcessNamespace: shareProcessNamespace,
148
+ subdomain: subdomain,
149
+ terminationGracePeriodSeconds: terminationGracePeriodSeconds,
150
+ tolerations: tolerations,
151
+ topologySpreadConstraints: topologySpreadConstraints,
152
+ volumes: volumes,
153
+ }
154
+ end
155
+
156
+ def default_templateMetadata
157
+ { labels: labels }
158
+ end
159
+
160
+ def default_containers
161
+ [container, sidecar].compact
162
+ end
163
+
164
+ def default_sidecar
165
+ {
166
+ name: sidecar_name,
167
+ image: sidecar_image,
168
+ }
169
+ end
170
+
171
+ def default_sidecar_name
172
+ "sidecar" if sidecar_image # othewise will create invalid sidecar field w/o image
173
+ end
174
+
175
+ def default_container
176
+ {
177
+ args: args,
178
+ command: command,
179
+ env: env,
180
+ envFrom: envFrom,
181
+ image: image,
182
+ imagePullPolicy: imagePullPolicy,
183
+ lifecycle: lifecycle,
184
+ livenessProbe: livenessProbe,
185
+ name: containerName || name,
186
+ ports: ports,
187
+ readinessProbe: readinessProbe,
188
+ resources: resources,
189
+ securityContext: securityContext,
190
+ startupProbe: startupProbe,
191
+ stdin: stdin,
192
+ stdinOnce: stdinOnce,
193
+ terminationMessagePath: terminationMessagePath,
194
+ terminationMessagePolicy: terminationMessagePolicy,
195
+ tty: tty,
196
+ volumeDevices: volumeDevices,
197
+ volumeMounts: volumeMounts,
198
+ workingDir: workingDir,
199
+ }
200
+ end
201
+
202
+ def default_ports
203
+ [
204
+ containerPort: containerPort,
205
+ hostIP: hostIP,
206
+ hostPort: hostPort,
207
+ name: portName,
208
+ protocol: protocol,
209
+ ]
210
+ end
211
+
212
+ # Override command instead of default_command since we want to change a String to an Array
213
+ def command_reader
214
+ @command.is_a?(String) ? @command.split(' ') : @command # else assume Array
215
+ end
216
+ end
217
+ end
@@ -5,12 +5,21 @@ module Kubes::Compiler::Shared
5
5
  extend Kubes::Compiler::Dsl::Core::Fields
6
6
  fields "name"
7
7
 
8
- def built_image
8
+ def docker_image
9
9
  return @options[:image] if @options[:image] # override
10
+ return Kubes.config.image if Kubes.config.image
11
+ built_image_helper
12
+ end
13
+
14
+ def built_image
15
+ Deprecated.new.built_image
16
+ built_image_helper
17
+ end
10
18
 
19
+ def built_image_helper
11
20
  path = Kubes.config.state.docker_image_path
12
21
  unless File.exist?(path)
13
- raise "Missing file with docker image built by kubes: #{path}. Try first running: kubes docker build"
22
+ raise Kubes::MissingDockerImage.new("Missing file with docker image built by kubes: #{path}. Try first running: kubes docker build")
14
23
  end
15
24
  IO.read(path)
16
25
  end
@@ -0,0 +1,37 @@
1
+ module Kubes::Compiler::Shared::Helpers
2
+ class Deprecated
3
+ def built_image
4
+ puts "DEPRECATED: built_image is deprecated, use docker_image helper instead.".color(:yellow)
5
+ print_source
6
+ end
7
+
8
+ def error_info
9
+ error_info = caller.find { |l| l.include?('.kubes/resources') }
10
+ path, line_number, _ = error_info.split(':')
11
+ {path: path, line_number: line_number}
12
+ end
13
+
14
+ def print_source
15
+ info = error_info
16
+ path = info[:path]
17
+ line_number = info[:line_number].to_i
18
+
19
+ pretty_path = path.sub("#{Kubes.root}/",'')
20
+ puts "Here's the line in #{pretty_path} that calls built_image:\n\n"
21
+
22
+ contents = IO.read(path)
23
+ content_lines = contents.split("\n")
24
+ context = 5 # lines of context
25
+ top, bottom = [line_number-context-1, 0].max, line_number+context-1
26
+ lpad = content_lines.size.to_s.size
27
+ content_lines[top..bottom].each_with_index do |line_content, index|
28
+ current_line = top+index+1
29
+ if current_line == line_number
30
+ printf("%#{lpad}d %s\n".color(:red), current_line, line_content)
31
+ else
32
+ printf("%#{lpad}d %s\n", current_line, line_content)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -32,7 +32,7 @@ module Kubes
32
32
 
33
33
  config.repo = nil # expected to be set by .kubes/config.rb
34
34
 
35
- config.logger = Logger.new($stdout)
35
+ config.logger = Logger.new($stderr)
36
36
  config.logger.level = ENV['KUBES_LOG_LEVEL'] || :info
37
37
 
38
38
  config.skip = []
@@ -28,5 +28,11 @@ module Kubes
28
28
  def kustomize?
29
29
  Kubectl::Kustomize.detect?
30
30
  end
31
+
32
+ def check_project!
33
+ return if File.exist?("#{Kubes.root}/.kubes/config.rb")
34
+ logger.error "ERROR: It doesnt look like this is a kubes project. Are you sure you are in a kubes project?".color(:red)
35
+ ENV['TS_TEST'] ? raise : exit(1)
36
+ end
31
37
  end
32
38
  end
@@ -30,7 +30,7 @@ module Kubes::Docker::Strategy
30
30
  return "tongueroo/demo-kubes:kubes-12345678" if ENV['TEST']
31
31
 
32
32
  unless File.exist?(image_state_path)
33
- puts "Unable to find #{image_state_path} which contains the last docker image name built with kubes build. Please run `kubes docker build` first."
33
+ logger.error "ERROR: Unable to find #{image_state_path} which contains the last docker image name built with kubes build. Please run `kubes docker build` first."
34
34
  exit 1
35
35
  end
36
36
  IO.read(image_state_path).strip
@@ -49,38 +49,5 @@ class Kubes::Kubectl
49
49
  end
50
50
  result
51
51
  end
52
-
53
- # kubes apply # {role: nil, resource: nil}
54
- # kubes apply clock # {role: "clock", resource: nil}
55
- # kubes apply clock deployment # {role: "clock", resource: "deployment"}
56
- def search_expr
57
- role, resource = @options[:role], @options[:resource]
58
- if role && resource
59
- "#{Kubes.root}/.kubes/output/#{role}/#{resource}.yaml"
60
- elsif role
61
- "#{Kubes.root}/.kubes/output/#{role}/*.yaml"
62
- else
63
- "#{Kubes.root}/.kubes/output/**/*.yaml"
64
- end
65
- end
66
-
67
- def files
68
- files = []
69
- Dir.glob(search_expr).each do |path|
70
- next unless process?(path)
71
- file = path.sub("#{Kubes.root}/", '')
72
- files << file
73
- end
74
- files
75
- end
76
-
77
- def process?(path)
78
- consider?(path) && two_levels_deep?(path)
79
- end
80
-
81
- def two_levels_deep?(path)
82
- rel_path = path.sub(%r{.*\.kubes/output/},'')
83
- rel_path.split('/').size == 2
84
- end
85
52
  end
86
53
  end