kubernetes-deploy 0.14.1 → 0.15.0

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: 2b7eaf966de6685ee13686190feda92f7d5e249c
4
- data.tar.gz: 7bc442ae69145779cd8965caababf22545a5d954
3
+ metadata.gz: 6f73fbf31b907e647a5c5fb9f37672cda04f2fbb
4
+ data.tar.gz: 37ff614545966a6aed17f814e71f244ec571c0de
5
5
  SHA512:
6
- metadata.gz: 983f99b3be92381d2838bc7b7cd4d9efd4220e9b13cd68d795d1d5523cd550d15effea7da8dc273d6dec8825e23372a63ff82a05e577ebcbdac0a3c2b9c2095b
7
- data.tar.gz: 28eb00deaa911348e3d27be549bcd0c788e8efc00977edd1c3986521b9e82367b06a8d80a258a371ec9dcd9d4b9dc7100d6e4856f0f98596fd2ab2b43dfd005b
6
+ metadata.gz: da6efb2e3f67dcb4e322559fb39deaa2d87606269cb1f1ab1f1609cc4a01d7af766e0bae0483a1ad448143de4f3db80a81938221a9bff6daefb4e475c0400d11
7
+ data.tar.gz: 5991bc3e2dc085d46c28ad3c11fc057cf9bbc79785cd2b92bef41b9d637e96b2b74650852ab7bdc574f1f3b8d55ea7a3513e94440fe360292c3dc876833b46f8
@@ -1,3 +1,10 @@
1
+ - name: 'Run Test Suite (:kubernetes: 1.10-latest)'
2
+ command: bin/ci
3
+ agents:
4
+ queue: minikube-ci
5
+ env:
6
+ LOGGING_LEVEL: 4
7
+ KUBERNETES_VERSION: v1.10-latest
1
8
  - name: 'Run Test Suite (:kubernetes: 1.9-latest)'
2
9
  command: bin/ci
3
10
  agents:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ### 0.15.0
2
+ *Bug Fixes*
3
+ - None
4
+
5
+ *Enhancements*
6
+ - Support for cronjob resource ([#206](https://github.com/Shopify/kubernetes-deploy/pull/206])).
7
+ - Make it possible to override the tool's hard timeout for one specific resource via the `kubernetes-deploy.shopify.io/timeout-override`
8
+ annotation ([#232](https://github.com/Shopify/kubernetes-deploy/pull/232)).
9
+ - Make it possible to modify how many replicas need to be updated and available before a deployment is considered
10
+ successful via the `kubernetes-deploy.shopify.io/required-rollout` annotation ([#208](https://github.com/Shopify/kubernetes-deploy/pull/208)).
11
+
1
12
  ### 0.14.1
2
13
  *Bug Fixes*
3
14
  - Make deployments whose pods crash because of CreateContainerConfigError fail fast in 1.8+ too (they would previously time out).
data/README.md CHANGED
@@ -39,6 +39,7 @@ This repo also includes related tools for [running tasks](#kubernetes-run) and [
39
39
  * [Installation](#installation)
40
40
  * [Usage](#usage)
41
41
  * [Using templates and variables](#using-templates-and-variables)
42
+ * [Customizing behaviour with annotations](#customizing-behaviour-with-annotations)
42
43
  * [Running tasks at the beginning of a deploy](#running-tasks-at-the-beginning-of-a-deploy)
43
44
  * [Deploying Kubernetes secrets (from EJSON)](#deploying-kubernetes-secrets-from-ejson)
44
45
 
@@ -120,6 +121,20 @@ All templates must be YAML formatted. You can also use ERB. The following local
120
121
  You can add additional variables using the `--bindings=BINDINGS` option. For example, `kubernetes-deploy my-app cluster1 --bindings=color=blue,size=large` will expose `color` and `size` in your templates.
121
122
 
122
123
 
124
+ ### Customizing behaviour with annotations
125
+ - `kubernetes-deploy.shopify.io/timeout-override`: Override the tool's hard timeout for one specific resource. Both full ISO8601 durations and the time portion of ISO8601 durations are valid. Value must be between 1 second and 24 hours.
126
+ - _Example values_: 45s / 3m / 1h / PT0.25H
127
+ - _Compatibility_: all resource types (Note: `Deployment` timeouts are based on `spec.progressDeadlineSeconds` if present, and that field has a default value as of the `apps/v1beta1` group version. Using this annotation will have no effect on `Deployment`s that time out with "Timeout reason: ProgressDeadlineExceeded".)
128
+ - `kubernetes-deploy.shopify.io/required-rollout`: Modifies how much of the rollout needs to finish
129
+ before the deployment is considered successful.
130
+ - _Compatibility_: Deployment
131
+ - `full`: The deployment is successful when all pods in the new `replicaSet` are ready.
132
+ - `none`: The deployment is successful as soon as the new `replicaSet` is created for the deployment.
133
+ - `maxUnavailable`: The deploy is successful when minimum availability is reached in the new `replicaSet`.
134
+ In other words, the number of new pods that must be ready is equal to `spec.replicas` - `strategy.RollingUpdate.maxUnavailable`
135
+ (converted from percentages by rounding up, if applicable). This option is only valid for deployments
136
+ that use the `RollingUpdate` strategy.
137
+
123
138
 
124
139
  ### Running tasks at the beginning of a deploy
125
140
 
@@ -28,6 +28,7 @@ require 'kubernetes-deploy/kubernetes_resource'
28
28
  topic
29
29
  bucket
30
30
  stateful_set
31
+ cron_job
31
32
  ).each do |subresource|
32
33
  require "kubernetes-deploy/kubernetes_resource/#{subresource}"
33
34
  end
@@ -65,18 +66,28 @@ module KubernetesDeploy
65
66
  # core/v1/ReplicationController -- superseded by deployments/replicasets
66
67
  # extensions/v1beta1/ReplicaSet -- managed by deployments
67
68
  # core/v1/Secret -- should not committed / managed by shipit
68
- PRUNE_WHITELIST = %w(
69
- core/v1/ConfigMap
70
- core/v1/Pod
71
- core/v1/Service
72
- batch/v1/Job
73
- extensions/v1beta1/DaemonSet
74
- extensions/v1beta1/Deployment
75
- apps/v1beta1/Deployment
76
- extensions/v1beta1/Ingress
77
- apps/v1beta1/StatefulSet
78
- autoscaling/v1/HorizontalPodAutoscaler
79
- ).freeze
69
+ def prune_whitelist
70
+ wl = %w(
71
+ core/v1/ConfigMap
72
+ core/v1/Pod
73
+ core/v1/Service
74
+ batch/v1/Job
75
+ extensions/v1beta1/DaemonSet
76
+ extensions/v1beta1/Deployment
77
+ apps/v1beta1/Deployment
78
+ extensions/v1beta1/Ingress
79
+ apps/v1beta1/StatefulSet
80
+ autoscaling/v1/HorizontalPodAutoscaler
81
+ )
82
+ if server_version >= Gem::Version.new('1.8.0')
83
+ wl << "batch/v1beta1/CronJob"
84
+ end
85
+ wl
86
+ end
87
+
88
+ def server_version
89
+ kubectl.server_version
90
+ end
80
91
 
81
92
  NOT_FOUND_ERROR = 'NotFound'
82
93
 
@@ -383,7 +394,7 @@ module KubernetesDeploy
383
394
 
384
395
  if prune
385
396
  command.push("--prune", "--all")
386
- PRUNE_WHITELIST.each { |type| command.push("--prune-whitelist=#{type}") }
397
+ prune_whitelist.each { |type| command.push("--prune-whitelist=#{type}") }
387
398
  end
388
399
 
389
400
  out, err, st = kubectl.run(*command, log_failure: false)
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KubernetesDeploy
4
+ ##
5
+ # This class is a less strict extension of ActiveSupport::Duration::ISO8601Parser.
6
+ # In addition to full ISO8601 durations, it can parse unprefixed ISO8601 time components (e.g. '1H').
7
+ # It is also case-insensitive.
8
+ # For example, this class considers the values "1H", "1h" and "PT1H" to be valid and equivalent.
9
+
10
+ class DurationParser
11
+ class ParsingError < ArgumentError; end
12
+
13
+ def initialize(value)
14
+ @iso8601_str = value.to_s.strip.upcase
15
+ end
16
+
17
+ def parse!
18
+ ActiveSupport::Duration.parse("PT#{@iso8601_str}") # By default assume it is just a time component
19
+ rescue ActiveSupport::Duration::ISO8601Parser::ParsingError
20
+ begin
21
+ ActiveSupport::Duration.parse(@iso8601_str)
22
+ rescue ActiveSupport::Duration::ISO8601Parser::ParsingError => e
23
+ raise ParsingError, e.message
24
+ end
25
+ end
26
+ end
27
+ end
@@ -28,6 +28,14 @@ module KubernetesDeploy
28
28
  )
29
29
  end
30
30
 
31
+ def build_batch_v1beta1_kubeclient(context)
32
+ _build_kubeclient(
33
+ api_version: "v1beta1",
34
+ context: context,
35
+ endpoint_path: "/apis/batch/"
36
+ )
37
+ end
38
+
31
39
  def build_policy_v1beta1_kubeclient(context)
32
40
  _build_kubeclient(
33
41
  api_version: "v1beta1",
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module KubernetesDeploy
3
+ class CronJob < KubernetesResource
4
+ TIMEOUT = 30.seconds
5
+
6
+ def sync
7
+ _, _err, st = kubectl.run("get", type, @name)
8
+ @status = st.success? ? "Available" : "Unknown"
9
+ @found = st.success?
10
+ end
11
+
12
+ def deploy_succeeded?
13
+ exists?
14
+ end
15
+
16
+ def deploy_failed?
17
+ !exists?
18
+ end
19
+
20
+ def timeout_message
21
+ UNUSUAL_FAILURE_MESSAGE
22
+ end
23
+
24
+ def exists?
25
+ @found
26
+ end
27
+ end
28
+ end
@@ -2,6 +2,9 @@
2
2
  module KubernetesDeploy
3
3
  class Deployment < KubernetesResource
4
4
  TIMEOUT = 7.minutes
5
+ REQUIRED_ROLLOUT_ANNOTATION = 'kubernetes-deploy.shopify.io/required-rollout'
6
+ REQUIRED_ROLLOUT_TYPES = %w(maxUnavailable full none).freeze
7
+ DEFAULT_REQUIRED_ROLLOUT = 'full'
5
8
 
6
9
  def sync
7
10
  raw_json, _err, st = kubectl.run("get", type, @name, "--output=json")
@@ -19,6 +22,7 @@ module KubernetesDeploy
19
22
  conditions = deployment_data.fetch("status", {}).fetch("conditions", [])
20
23
  @progress_condition = conditions.find { |condition| condition['type'] == 'Progressing' }
21
24
  @progress_deadline = deployment_data['spec']['progressDeadlineSeconds']
25
+ @max_unavailable = deployment_data.dig('spec', 'strategy', 'rollingUpdate', 'maxUnavailable')
22
26
  else # reset
23
27
  @latest_rs = nil
24
28
  @rollout_data = { "replicas" => 0 }
@@ -26,6 +30,7 @@ module KubernetesDeploy
26
30
  @progress_condition = nil
27
31
  @progress_deadline = @definition['spec']['progressDeadlineSeconds']
28
32
  @desired_replicas = -1
33
+ @max_unavailable = @definition.dig('spec', 'strategy', 'rollingUpdate', 'maxUnavailable')
29
34
  end
30
35
  end
31
36
 
@@ -43,10 +48,23 @@ module KubernetesDeploy
43
48
  def deploy_succeeded?
44
49
  return false unless @latest_rs.present?
45
50
 
46
- @latest_rs.deploy_succeeded? &&
47
- @latest_rs.desired_replicas == @desired_replicas && # latest RS fully scaled up
48
- @rollout_data["updatedReplicas"].to_i == @desired_replicas &&
49
- @rollout_data["updatedReplicas"].to_i == @rollout_data["availableReplicas"].to_i
51
+ case required_rollout
52
+ when 'full'
53
+ @latest_rs.deploy_succeeded? &&
54
+ @latest_rs.desired_replicas == @desired_replicas && # latest RS fully scaled up
55
+ @rollout_data["updatedReplicas"].to_i == @desired_replicas &&
56
+ @rollout_data["updatedReplicas"].to_i == @rollout_data["availableReplicas"].to_i
57
+ when 'none'
58
+ true
59
+ when 'maxUnavailable'
60
+ minimum_needed = min_available_replicas
61
+
62
+ @latest_rs.desired_replicas >= minimum_needed &&
63
+ @latest_rs.ready_replicas >= minimum_needed &&
64
+ @latest_rs.available_replicas >= minimum_needed
65
+ else
66
+ raise FatalDeploymentError, rollout_annotation_err_msg
67
+ end
50
68
  end
51
69
 
52
70
  def deploy_failed?
@@ -81,8 +99,29 @@ module KubernetesDeploy
81
99
  @found
82
100
  end
83
101
 
102
+ def validate_definition
103
+ super
104
+
105
+ unless REQUIRED_ROLLOUT_TYPES.include?(required_rollout)
106
+ @validation_errors << rollout_annotation_err_msg
107
+ end
108
+
109
+ strategy = @definition.dig('spec', 'strategy', 'type').to_s
110
+ if required_rollout.downcase == 'maxunavailable' && strategy.downcase != 'rollingupdate'
111
+ @validation_errors << "'#{REQUIRED_ROLLOUT_ANNOTATION}: #{required_rollout}' is incompatible "\
112
+ "with strategy '#{strategy}'"
113
+ end
114
+
115
+ @validation_errors.empty?
116
+ end
117
+
84
118
  private
85
119
 
120
+ def rollout_annotation_err_msg
121
+ "'#{REQUIRED_ROLLOUT_ANNOTATION}: #{required_rollout}' is invalid. "\
122
+ "Acceptable values: #{REQUIRED_ROLLOUT_TYPES.join(', ')}"
123
+ end
124
+
86
125
  def deploy_failing_to_progress?
87
126
  return false unless @progress_condition.present?
88
127
 
@@ -98,18 +137,22 @@ module KubernetesDeploy
98
137
  Time.parse(@progress_condition["lastUpdateTime"]).to_i >= (@deploy_started_at - 5.seconds).to_i
99
138
  end
100
139
 
101
- def find_latest_rs(deployment_data)
102
- label_string = deployment_data["spec"]["selector"]["matchLabels"].map { |k, v| "#{k}=#{v}" }.join(",")
140
+ def all_rs_data(match_labels)
141
+ label_string = match_labels.map { |k, v| "#{k}=#{v}" }.join(",")
103
142
  raw_json, _err, st = kubectl.run("get", "replicasets", "--output=json", "--selector=#{label_string}")
104
- return unless st.success?
143
+ return {} unless st.success?
144
+
145
+ JSON.parse(raw_json)["items"]
146
+ end
105
147
 
106
- all_rs_data = JSON.parse(raw_json)["items"]
148
+ def find_latest_rs(deployment_data)
107
149
  current_revision = deployment_data["metadata"]["annotations"]["deployment.kubernetes.io/revision"]
108
150
 
109
- latest_rs_data = all_rs_data.find do |rs|
151
+ latest_rs_data = all_rs_data(deployment_data["spec"]["selector"]["matchLabels"]).find do |rs|
110
152
  rs["metadata"]["ownerReferences"].any? { |ref| ref["uid"] == deployment_data["metadata"]["uid"] } &&
111
153
  rs["metadata"]["annotations"]["deployment.kubernetes.io/revision"] == current_revision
112
154
  end
155
+
113
156
  return unless latest_rs_data.present?
114
157
 
115
158
  rs = ReplicaSet.new(
@@ -123,5 +166,18 @@ module KubernetesDeploy
123
166
  rs.sync(latest_rs_data)
124
167
  rs
125
168
  end
169
+
170
+ def min_available_replicas
171
+ if @max_unavailable =~ /%/
172
+ (@desired_replicas * (100 - @max_unavailable.to_i) / 100.0).ceil
173
+ else
174
+ @desired_replicas - @max_unavailable.to_i
175
+ end
176
+ end
177
+
178
+ def required_rollout
179
+ @definition.dig('metadata', 'annotations', REQUIRED_ROLLOUT_ANNOTATION).presence ||
180
+ DEFAULT_REQUIRED_ROLLOUT
181
+ end
126
182
  end
127
183
  end
@@ -3,13 +3,15 @@ require 'kubernetes-deploy/kubernetes_resource/pod_set_base'
3
3
  module KubernetesDeploy
4
4
  class ReplicaSet < PodSetBase
5
5
  TIMEOUT = 5.minutes
6
- attr_reader :desired_replicas, :pods
6
+ attr_reader :desired_replicas, :ready_replicas, :available_replicas, :pods
7
7
 
8
8
  def initialize(namespace:, context:, definition:, logger:, parent: nil, deploy_started_at: nil)
9
9
  @parent = parent
10
10
  @deploy_started_at = deploy_started_at
11
11
  @rollout_data = { "replicas" => 0 }
12
12
  @desired_replicas = -1
13
+ @ready_replicas = -1
14
+ @available_replicas = -1
13
15
  @pods = []
14
16
  super(namespace: namespace, context: context, definition: definition, logger: logger)
15
17
  end
@@ -26,6 +28,8 @@ module KubernetesDeploy
26
28
  @rollout_data = { "replicas" => 0 }.merge(
27
29
  rs_data["status"].slice("replicas", "availableReplicas", "readyReplicas")
28
30
  )
31
+ @ready_replicas = @rollout_data['readyReplicas'].to_i
32
+ @available_replicas = @rollout_data["availableReplicas"].to_i
29
33
  @status = @rollout_data.map { |state_replicas, num| "#{num} #{state_replicas.chop.pluralize(num)}" }.join(", ")
30
34
  @pods = find_pods(rs_data)
31
35
  else # reset
@@ -34,6 +38,8 @@ module KubernetesDeploy
34
38
  @status = nil
35
39
  @pods = []
36
40
  @desired_replicas = -1
41
+ @ready_replicas = -1
42
+ @available_replicas = -1
37
43
  end
38
44
  end
39
45
 
@@ -6,7 +6,7 @@ require 'kubernetes-deploy/kubectl'
6
6
 
7
7
  module KubernetesDeploy
8
8
  class KubernetesResource
9
- attr_reader :name, :namespace, :context, :validation_error_msg
9
+ attr_reader :name, :namespace, :context
10
10
  attr_writer :type, :deploy_started_at
11
11
 
12
12
  TIMEOUT = 5.minutes
@@ -22,6 +22,8 @@ module KubernetesDeploy
22
22
  If you have reason to believe it will succeed, retry the deploy to continue to monitor the rollout.
23
23
  MSG
24
24
 
25
+ TIMEOUT_OVERRIDE_ANNOTATION = "kubernetes-deploy.shopify.io/timeout-override"
26
+
25
27
  def self.build(namespace:, context:, definition:, logger:)
26
28
  opts = { namespace: namespace, context: context, definition: definition, logger: logger }
27
29
  if KubernetesDeploy.const_defined?(definition["kind"])
@@ -39,9 +41,17 @@ module KubernetesDeploy
39
41
  end
40
42
 
41
43
  def timeout
44
+ return timeout_override if timeout_override.present?
42
45
  self.class.timeout
43
46
  end
44
47
 
48
+ def timeout_override
49
+ return @timeout_override if defined?(@timeout_override)
50
+ @timeout_override = DurationParser.new(timeout_annotation).parse!.to_i
51
+ rescue DurationParser::ParsingError
52
+ @timeout_override = nil
53
+ end
54
+
45
55
  def pretty_timeout_type
46
56
  "timeout: #{timeout}s"
47
57
  end
@@ -59,20 +69,26 @@ module KubernetesDeploy
59
69
  @logger = logger
60
70
  @definition = definition
61
71
  @statsd_report_done = false
62
- @validation_error_msg = nil
72
+ @validation_errors = []
63
73
  end
64
74
 
65
75
  def validate_definition
66
- @validation_error_msg = nil
76
+ @validation_errors = []
77
+ validate_timeout_annotation
78
+
67
79
  command = ["create", "-f", file_path, "--dry-run", "--output=name"]
68
80
  _, err, st = kubectl.run(*command, log_failure: false)
69
81
  return true if st.success?
70
- @validation_error_msg = err
82
+ @validation_errors << err
71
83
  false
72
84
  end
73
85
 
86
+ def validation_error_msg
87
+ @validation_errors.join("\n")
88
+ end
89
+
74
90
  def validation_failed?
75
- @validation_error_msg.present?
91
+ @validation_errors.present?
76
92
  end
77
93
 
78
94
  def id
@@ -277,6 +293,23 @@ module KubernetesDeploy
277
293
 
278
294
  private
279
295
 
296
+ def validate_timeout_annotation
297
+ return if timeout_annotation.nil?
298
+
299
+ override = DurationParser.new(timeout_annotation).parse!
300
+ if override <= 0
301
+ @validation_errors << "#{TIMEOUT_OVERRIDE_ANNOTATION} annotation is invalid: Value must be greater than 0"
302
+ elsif override > 24.hours
303
+ @validation_errors << "#{TIMEOUT_OVERRIDE_ANNOTATION} annotation is invalid: Value must be less than 24h"
304
+ end
305
+ rescue DurationParser::ParsingError => e
306
+ @validation_errors << "#{TIMEOUT_OVERRIDE_ANNOTATION} annotation is invalid: #{e}"
307
+ end
308
+
309
+ def timeout_annotation
310
+ @definition.dig("metadata", "annotations", TIMEOUT_OVERRIDE_ANNOTATION)
311
+ end
312
+
280
313
  def file
281
314
  @file ||= create_definition_tempfile
282
315
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module KubernetesDeploy
3
- VERSION = "0.14.1"
3
+ VERSION = "0.15.0"
4
4
  end
@@ -8,6 +8,7 @@ require 'active_support/core_ext/string/inflections'
8
8
  require 'active_support/core_ext/string/strip'
9
9
  require 'active_support/core_ext/hash/keys'
10
10
  require 'active_support/core_ext/array/conversions'
11
+ require 'active_support/duration'
11
12
  require 'colorized_string'
12
13
 
13
14
  require 'kubernetes-deploy/version'
@@ -17,6 +18,7 @@ require 'kubernetes-deploy/deploy_task'
17
18
  require 'kubernetes-deploy/statsd'
18
19
  require 'kubernetes-deploy/concurrency'
19
20
  require 'kubernetes-deploy/bindings_parser'
21
+ require 'kubernetes-deploy/duration_parser'
20
22
 
21
23
  module KubernetesDeploy
22
24
  KubernetesDeploy::StatsD.build
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.14.1
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katrina Verey
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2017-12-20 00:00:00.000000000 Z
12
+ date: 2018-01-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -227,6 +227,7 @@ files:
227
227
  - lib/kubernetes-deploy/concurrency.rb
228
228
  - lib/kubernetes-deploy/deferred_summary_logging.rb
229
229
  - lib/kubernetes-deploy/deploy_task.rb
230
+ - lib/kubernetes-deploy/duration_parser.rb
230
231
  - lib/kubernetes-deploy/ejson_secret_provisioner.rb
231
232
  - lib/kubernetes-deploy/errors.rb
232
233
  - lib/kubernetes-deploy/formatted_logger.rb
@@ -238,6 +239,7 @@ files:
238
239
  - lib/kubernetes-deploy/kubernetes_resource/bugsnag.rb
239
240
  - lib/kubernetes-deploy/kubernetes_resource/cloudsql.rb
240
241
  - lib/kubernetes-deploy/kubernetes_resource/config_map.rb
242
+ - lib/kubernetes-deploy/kubernetes_resource/cron_job.rb
241
243
  - lib/kubernetes-deploy/kubernetes_resource/daemon_set.rb
242
244
  - lib/kubernetes-deploy/kubernetes_resource/deployment.rb
243
245
  - lib/kubernetes-deploy/kubernetes_resource/elasticsearch.rb
@@ -287,7 +289,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
287
289
  version: '0'
288
290
  requirements: []
289
291
  rubyforge_project:
290
- rubygems_version: 2.5.2.1
292
+ rubygems_version: 2.6.14
291
293
  signing_key:
292
294
  specification_version: 4
293
295
  summary: Kubernetes deploy scripts