kubernetes-deploy 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b6813a027a20fd297012d9fbe53f9bf79ee711f4
4
- data.tar.gz: 68678d68902d9360939bf247844d7baa59bbe750
3
+ metadata.gz: c5451809e19cbb8f15e709ff0eab4787bcdc1c36
4
+ data.tar.gz: 2eaf109d80b3e11175ebd29cab21dd7419551583
5
5
  SHA512:
6
- metadata.gz: 43316a28fb61923fd1ea2fb2e623cc60d6793d98f71dd8f6380a3758eb5701a789efdd264a2c858a74e062fe698eb9a79f46415ed095757d0163652d3aa99887
7
- data.tar.gz: 41e6622be8c17256ff4a8e663fdaa340b4d87c9e727378a53caf29444b8e3e579c81302d7b7656f74ed6986c6051979df99fde329906377c1e28ec0684e7173a
6
+ metadata.gz: 3a7a97fe1b2c991f58ca8da5d77028d6de450517ed02f82f9fd8f5688f36095f85263eb667cb6444542c69d845bb7f20bb651e54da81851bab37f5d0ab1aed69
7
+ data.tar.gz: 8490ed13cba69329bb9f13acb9a6b3ddfffbba553cdc84c886d075060a49804ac11e3d8173db8d60c0bdf0e39ab2d96a2b066e723e960405369a9227fa2b9152
@@ -5,27 +5,27 @@ require 'shellwords'
5
5
  module KubernetesDeploy
6
6
  class KubernetesResource
7
7
 
8
- attr_reader :name, :namespace, :file
8
+ attr_reader :name, :namespace, :file, :context
9
9
  attr_writer :type, :deploy_started
10
10
 
11
11
  TIMEOUT = 5.minutes
12
12
 
13
- def self.for_type(type, name, namespace, file)
13
+ def self.for_type(type, name, namespace, context, file)
14
14
  case type
15
- when 'cloudsql' then Cloudsql.new(name, namespace, file)
16
- when 'configmap' then ConfigMap.new(name, namespace, file)
17
- when 'deployment' then Deployment.new(name, namespace, file)
18
- when 'pod' then Pod.new(name, namespace, file)
19
- when 'ingress' then Ingress.new(name, namespace, file)
20
- when 'persistentvolumeclaim' then PersistentVolumeClaim.new(name, namespace, file)
21
- when 'service' then Service.new(name, namespace, file)
22
- else self.new(name, namespace, file).tap { |r| r.type = type }
15
+ when 'cloudsql' then Cloudsql.new(name, namespace, context, file)
16
+ when 'configmap' then ConfigMap.new(name, namespace, context, file)
17
+ when 'deployment' then Deployment.new(name, namespace, context, file)
18
+ when 'pod' then Pod.new(name, namespace, context, file)
19
+ when 'ingress' then Ingress.new(name, namespace, context, file)
20
+ when 'persistentvolumeclaim' then PersistentVolumeClaim.new(name, namespace, context, file)
21
+ when 'service' then Service.new(name, namespace, context, file)
22
+ else self.new(name, namespace, context, file).tap { |r| r.type = type }
23
23
  end
24
24
  end
25
25
 
26
- def initialize(name, namespace, file)
26
+ def initialize(name, namespace, context, file)
27
27
  # subclasses must also set these
28
- @name, @namespace, @file = name, namespace, file
28
+ @name, @namespace, @context, @file = name, namespace, context, file
29
29
  end
30
30
 
31
31
  def id
@@ -92,7 +92,9 @@ module KubernetesDeploy
92
92
 
93
93
  def run_kubectl(*args)
94
94
  raise FatalDeploymentError, "Namespace missing for namespaced command" if namespace.blank?
95
- args = args.unshift("kubectl").push("--namespace=#{namespace}")
95
+ raise FatalDeploymentError, "Explicit context is required to run this command" if context.blank?
96
+ args = args.unshift("kubectl").push("--namespace=#{namespace}").push("--context=#{context}")
97
+
96
98
  KubernetesDeploy.logger.debug Shellwords.join(args)
97
99
  out, err, st = Open3.capture3(*args)
98
100
  KubernetesDeploy.logger.debug(out.shellescape)
@@ -2,8 +2,8 @@ module KubernetesDeploy
2
2
  class Cloudsql < KubernetesResource
3
3
  TIMEOUT = 5.minutes
4
4
 
5
- def initialize(name, namespace, file)
6
- @name, @namespace, @file = name, namespace, file
5
+ def initialize(name, namespace, context, file)
6
+ @name, @namespace, @context, @file = name, namespace, context, file
7
7
  end
8
8
 
9
9
  def sync
@@ -2,8 +2,8 @@ module KubernetesDeploy
2
2
  class ConfigMap < KubernetesResource
3
3
  TIMEOUT = 30.seconds
4
4
 
5
- def initialize(name, namespace, file)
6
- @name, @namespace, @file = name, namespace, file
5
+ def initialize(name, namespace, context, file)
6
+ @name, @namespace, @context, @file = name, namespace, context, file
7
7
  end
8
8
 
9
9
  def sync
@@ -2,8 +2,8 @@ module KubernetesDeploy
2
2
  class Deployment < KubernetesResource
3
3
  TIMEOUT = 15.minutes
4
4
 
5
- def initialize(name, namespace, file)
6
- @name, @namespace, @file = name, namespace, file
5
+ def initialize(name, namespace, context, file)
6
+ @name, @namespace, @context, @file = name, namespace, context, file
7
7
  end
8
8
 
9
9
  def sync
@@ -22,7 +22,7 @@ module KubernetesDeploy
22
22
  pods_json = JSON.parse(pod_list)["items"]
23
23
  pods_json.each do |pod_json|
24
24
  pod_name = pod_json["metadata"]["name"]
25
- pod = Pod.new(pod_name, namespace, nil, parent: "#{@name.capitalize} deployment")
25
+ pod = Pod.new(pod_name, namespace, context, nil, parent: "#{@name.capitalize} deployment")
26
26
  pod.deploy_started = @deploy_started
27
27
  pod.interpret_json_data(pod_json)
28
28
  pod.log_status
@@ -2,8 +2,8 @@ module KubernetesDeploy
2
2
  class Ingress < KubernetesResource
3
3
  TIMEOUT = 30.seconds
4
4
 
5
- def initialize(name, namespace, file)
6
- @name, @namespace, @file = name, namespace, file
5
+ def initialize(name, namespace, context, file)
6
+ @name, @namespace, @context, @file = name, namespace, context, file
7
7
  end
8
8
 
9
9
  def sync
@@ -2,8 +2,8 @@ module KubernetesDeploy
2
2
  class PersistentVolumeClaim < KubernetesResource
3
3
  TIMEOUT = 5.minutes
4
4
 
5
- def initialize(name, namespace, file)
6
- @name, @namespace, @file = name, namespace, file
5
+ def initialize(name, namespace, context, file)
6
+ @name, @namespace, @context, @file = name, namespace, context, file
7
7
  end
8
8
 
9
9
  def sync
@@ -3,8 +3,8 @@ module KubernetesDeploy
3
3
  TIMEOUT = 15.minutes
4
4
  SUSPICIOUS_CONTAINER_STATES = %w(ImagePullBackOff RunContainerError).freeze
5
5
 
6
- def initialize(name, namespace, file, parent: nil)
7
- @name, @namespace, @file, @parent = name, namespace, file, parent
6
+ def initialize(name, namespace, context, file, parent: nil)
7
+ @name, @namespace, @context, @file, @parent = name, namespace, context, file, parent
8
8
  @bare = !@parent
9
9
  end
10
10
 
@@ -40,7 +40,7 @@ module KubernetesDeploy
40
40
  elsif @phase == "Terminating"
41
41
  @status = @phase
42
42
  else
43
- ready_condition = pod_data["status"]["conditions"].find { |condition| condition["type"] == "Ready" }
43
+ ready_condition = pod_data["status"].fetch("conditions", []).find { |condition| condition["type"] == "Ready" }
44
44
  @ready = ready_condition.present? && (ready_condition["status"] == "True")
45
45
  @status = "#{@phase} (Ready: #{@ready})"
46
46
  end
@@ -2,8 +2,8 @@ module KubernetesDeploy
2
2
  class Service < KubernetesResource
3
3
  TIMEOUT = 15.minutes
4
4
 
5
- def initialize(name, namespace, file)
6
- @name, @namespace, @file = name, namespace, file
5
+ def initialize(name, namespace, context, file)
6
+ @name, @namespace, @context, @file = name, namespace, context, file
7
7
  end
8
8
 
9
9
  def sync
@@ -26,6 +26,10 @@ module KubernetesDeploy
26
26
  PersistentVolumeClaim
27
27
  Pod
28
28
  )
29
+ PROTECTED_NAMESPACES = %w(
30
+ default
31
+ kube-system
32
+ )
29
33
 
30
34
  # Things removed from default prune whitelist:
31
35
  # core/v1/Namespace -- not namespaced
@@ -76,9 +80,9 @@ MSG
76
80
  phase_heading("Validating configuration")
77
81
  validate_configuration
78
82
 
79
- phase_heading("Configuring kubectl")
80
- set_kubectl_context
81
- validate_namespace
83
+ phase_heading("Identifying deployment target")
84
+ confirm_context_exists
85
+ confirm_namespace_exists
82
86
 
83
87
  phase_heading("Parsing deploy content")
84
88
  resources = discover_resources
@@ -127,7 +131,7 @@ MSG
127
131
  split_templates(filename) do |tempfile|
128
132
  resource_id = discover_resource_via_dry_run(tempfile)
129
133
  type, name = resource_id.split("/", 2) # e.g. "pod/web-198612918-dzvfb"
130
- resources << KubernetesResource.for_type(type, name, @namespace, tempfile)
134
+ resources << KubernetesResource.for_type(type, name, @namespace, @context, tempfile)
131
135
  KubernetesDeploy.logger.info "Discovered template for #{resource_id}"
132
136
  end
133
137
  end
@@ -217,6 +221,8 @@ MSG
217
221
 
218
222
  if @namespace.blank?
219
223
  errors << "Namespace must be specified"
224
+ elsif PROTECTED_NAMESPACES.include?(@namespace)
225
+ errors << "Refusing to deploy to protected namespace #{@namespace}"
220
226
  end
221
227
 
222
228
  if @context.blank?
@@ -263,7 +269,7 @@ MSG
263
269
  run_kubectl(*command)
264
270
  end
265
271
 
266
- def set_kubectl_context
272
+ def confirm_context_exists
267
273
  out, err, st = run_kubectl("config", "get-contexts", "-o", "name", namespaced: false, with_context: false)
268
274
  available_contexts = out.split("\n")
269
275
  if !st.success?
@@ -271,21 +277,24 @@ MSG
271
277
  elsif !available_contexts.include?(@context)
272
278
  raise FatalDeploymentError, "Context #{@context} is not available. Valid contexts: #{available_contexts}"
273
279
  end
280
+ KubernetesDeploy.logger.info("Context #{@context} found")
274
281
  end
275
282
 
276
- def validate_namespace
283
+ def confirm_namespace_exists
277
284
  _, _, st = run_kubectl("get", "namespace", @namespace, namespaced: false)
278
- raise FatalDeploymentError, "Failed to validate namespace #{@namespace}" unless st.success?
279
- KubernetesDeploy.logger.info("Namespace #{@namespace} validated")
285
+ raise FatalDeploymentError, "Namespace #{@namespace} not found" unless st.success?
286
+ KubernetesDeploy.logger.info("Namespace #{@namespace} found")
280
287
  end
281
288
 
282
289
  def run_kubectl(*args, namespaced: true, with_context: true)
283
290
  args = args.unshift("kubectl")
284
291
  if namespaced
292
+ raise FatalDeploymentError, "Namespace missing for namespaced command" if @namespace.blank?
285
293
  args.push("--namespace=#{@namespace}")
286
294
  end
287
295
 
288
296
  if with_context
297
+ raise FatalDeploymentError, "Explicit context is required to run this command" if @context.blank?
289
298
  args.push("--context=#{@context}")
290
299
  end
291
300
  KubernetesDeploy.logger.debug Shellwords.join(args)
@@ -1,3 +1,3 @@
1
1
  module KubernetesDeploy
2
- VERSION = "0.2.2"
2
+ VERSION = "0.2.3"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kubernetes-deploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kir Shatrov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2017-02-03 00:00:00.000000000 Z
13
+ date: 2017-02-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -116,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
116
  version: '0'
117
117
  requirements: []
118
118
  rubyforge_project:
119
- rubygems_version: 2.5.2
119
+ rubygems_version: 2.5.1
120
120
  signing_key:
121
121
  specification_version: 4
122
122
  summary: Kubernetes deploy scripts