kubernetes-deploy 0.2.2 → 0.2.3

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 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