active_job_k8s 0.2.0 → 1.0.0.pre.beta.1

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
  SHA256:
3
- metadata.gz: 57feaec27f10c9503c7e9455b30526d080b446eb9194f93a7a20e8830b3f3ceb
4
- data.tar.gz: a1447113bfcdae14dae4e870e859df4997ae1ab8d6a01dc3dd11351301a7a165
3
+ metadata.gz: d5b40e92ba26450d0cb797737e03552b8f89fea8dc1f4ae9da53d924b34e23ad
4
+ data.tar.gz: 6d30c4b30a4a1bf180e5617c8ce4582f27862d80a2ed2b1959dc1c57f782d123
5
5
  SHA512:
6
- metadata.gz: feb62f548aaeffade90f53014060463959c3d672d674f348a82474271291b2f7d00e3bb68a6398a26ff7a77de04b7d137df633ad42141bd1623fbc2b785024bf
7
- data.tar.gz: 203f78073d6ce7667ab48facf91262b6cab587142ce8afe1b557220e64dcd574ff093ee160e38e6f1eccbe1b4d23177718b524b0bd13eb548ce75282f35f133b
6
+ metadata.gz: a1f159b9d818fc7f1e94f19cd69ffa6288a19e453c444a1fc6ff5470613f46366b0a3a4cef266c488ae7062f0a93ff8872cced39182e0b0feda9f57c3de90318
7
+ data.tar.gz: 3042cee4f989340e528d5f2d153fc954489e43edd0c152fc32255ff717bdeeceb254db5db45c48740df401c0dda1eb5e58a3910ca44f507251bd1bfa3c7e9c51
@@ -21,11 +21,14 @@ jobs:
21
21
 
22
22
  runs-on: ubuntu-latest
23
23
  strategy:
24
+ fail-fast: false
24
25
  matrix:
25
- ruby-version: ['2.6', '2.7']
26
+ ruby-version: [ '2.7','3.0','3.1']
26
27
 
27
28
  steps:
28
29
  - uses: actions/checkout@v3
30
+ - name: Remove Gemfile.lock
31
+ run: rm -fr Gemfile.lock
29
32
  - name: Set up Ruby
30
33
  uses: ruby/setup-ruby@v1
31
34
  with:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # V 0.2.0
2
+ - change position of default manifest
3
+ - implementation of delayed job to be scheduled in a specific moment
4
+
1
5
  # V 0.1.0
2
6
  - first release as POC
3
7
  - base tests
data/Gemfile CHANGED
@@ -4,7 +4,7 @@ source "https://rubygems.org"
4
4
  gemspec
5
5
 
6
6
  gem "rails","~> 6.1"
7
- gem "rake", "~> 12.0"
7
+ gem "rake", "~> 13.0"
8
8
  gem "rspec", "~> 3.0"
9
9
 
10
10
  gem 'simplecov', require: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- active_job_k8s (0.1.0)
4
+ active_job_k8s (0.2.0)
5
+ http (>= 5.0)
5
6
  kubeclient (~> 4.0)
6
7
  rails (>= 6.0, < 8)
7
8
 
@@ -72,57 +73,71 @@ GEM
72
73
  builder (3.2.4)
73
74
  concurrent-ruby (1.1.10)
74
75
  crass (1.0.6)
76
+ date (3.3.3)
75
77
  diff-lcs (1.5.0)
76
78
  docile (1.4.0)
77
79
  domain_name (0.5.20190701)
78
80
  unf (>= 0.0.5, < 1.0.0)
79
- erubi (1.11.0)
81
+ erubi (1.12.0)
80
82
  ffi (1.15.5)
81
83
  ffi-compiler (1.0.1)
82
84
  ffi (>= 1.0.0)
83
85
  rake
84
86
  globalid (1.0.0)
85
87
  activesupport (>= 5.0)
86
- http (4.4.1)
87
- addressable (~> 2.3)
88
+ http (5.1.1)
89
+ addressable (~> 2.8)
88
90
  http-cookie (~> 1.0)
89
91
  http-form_data (~> 2.2)
90
- http-parser (~> 1.2.0)
92
+ llhttp-ffi (~> 0.4.0)
91
93
  http-accept (1.7.0)
92
94
  http-cookie (1.0.5)
93
95
  domain_name (~> 0.5)
94
96
  http-form_data (2.3.0)
95
- http-parser (1.2.3)
96
- ffi-compiler (>= 1.0, < 2.0)
97
97
  i18n (1.12.0)
98
98
  concurrent-ruby (~> 1.0)
99
99
  jsonpath (1.1.2)
100
100
  multi_json
101
- kubeclient (4.10.1)
102
- http (>= 3.0, < 5.0)
101
+ kubeclient (4.11.0)
102
+ http (>= 3.0, < 6.0)
103
103
  jsonpath (~> 1.0)
104
104
  recursive-open-struct (~> 1.1, >= 1.1.1)
105
105
  rest-client (~> 2.0)
106
- loofah (2.19.0)
106
+ llhttp-ffi (0.4.0)
107
+ ffi-compiler (~> 1.0)
108
+ rake (~> 13.0)
109
+ loofah (2.19.1)
107
110
  crass (~> 1.0.2)
108
111
  nokogiri (>= 1.5.9)
109
- mail (2.7.1)
112
+ mail (2.8.0)
110
113
  mini_mime (>= 0.1.1)
114
+ net-imap
115
+ net-pop
116
+ net-smtp
111
117
  marcel (1.0.2)
112
118
  method_source (1.0.0)
113
119
  mime-types (3.4.1)
114
120
  mime-types-data (~> 3.2015)
115
121
  mime-types-data (3.2022.0105)
116
122
  mini_mime (1.1.2)
117
- minitest (5.16.3)
123
+ minitest (5.17.0)
118
124
  multi_json (1.15.0)
125
+ net-imap (0.3.4)
126
+ date
127
+ net-protocol
128
+ net-pop (0.1.2)
129
+ net-protocol
130
+ net-protocol (0.2.1)
131
+ timeout
132
+ net-smtp (0.3.3)
133
+ net-protocol
119
134
  netrc (0.11.0)
120
135
  nio4r (2.5.8)
121
- nokogiri (1.13.9-x86_64-linux)
136
+ nokogiri (1.13.10-x86_64-linux)
122
137
  racc (~> 1.4)
123
- public_suffix (5.0.0)
124
- racc (1.6.0)
125
- rack (2.2.4)
138
+ public_suffix (5.0.1)
139
+ racc (1.6.2)
140
+ rack (2.2.5)
126
141
  rack-test (2.0.2)
127
142
  rack (>= 1.3)
128
143
  rails (6.1.7)
@@ -143,15 +158,15 @@ GEM
143
158
  rails-dom-testing (2.0.3)
144
159
  activesupport (>= 4.2.0)
145
160
  nokogiri (>= 1.6)
146
- rails-html-sanitizer (1.4.3)
147
- loofah (~> 2.3)
161
+ rails-html-sanitizer (1.4.4)
162
+ loofah (~> 2.19, >= 2.19.1)
148
163
  railties (6.1.7)
149
164
  actionpack (= 6.1.7)
150
165
  activesupport (= 6.1.7)
151
166
  method_source
152
167
  rake (>= 12.2)
153
168
  thor (~> 1.0)
154
- rake (12.3.3)
169
+ rake (13.0.6)
155
170
  recursive-open-struct (1.1.3)
156
171
  rest-client (2.1.0)
157
172
  http-accept (>= 1.7.0, < 2.0)
@@ -159,20 +174,20 @@ GEM
159
174
  mime-types (>= 1.16, < 4.0)
160
175
  netrc (~> 0.8)
161
176
  rexml (3.2.5)
162
- rspec (3.11.0)
163
- rspec-core (~> 3.11.0)
164
- rspec-expectations (~> 3.11.0)
165
- rspec-mocks (~> 3.11.0)
166
- rspec-core (3.11.0)
167
- rspec-support (~> 3.11.0)
168
- rspec-expectations (3.11.1)
177
+ rspec (3.12.0)
178
+ rspec-core (~> 3.12.0)
179
+ rspec-expectations (~> 3.12.0)
180
+ rspec-mocks (~> 3.12.0)
181
+ rspec-core (3.12.0)
182
+ rspec-support (~> 3.12.0)
183
+ rspec-expectations (3.12.1)
169
184
  diff-lcs (>= 1.2.0, < 2.0)
170
- rspec-support (~> 3.11.0)
171
- rspec-mocks (3.11.1)
185
+ rspec-support (~> 3.12.0)
186
+ rspec-mocks (3.12.1)
172
187
  diff-lcs (>= 1.2.0, < 2.0)
173
- rspec-support (~> 3.11.0)
174
- rspec-support (3.11.1)
175
- simplecov (0.21.2)
188
+ rspec-support (~> 3.12.0)
189
+ rspec-support (3.12.0)
190
+ simplecov (0.22.0)
176
191
  docile (~> 1.1)
177
192
  simplecov-html (~> 0.11)
178
193
  simplecov_json_formatter (~> 0.1)
@@ -181,14 +196,15 @@ GEM
181
196
  simplecov (~> 0.19)
182
197
  simplecov-html (0.12.3)
183
198
  simplecov_json_formatter (0.1.4)
184
- sprockets (4.1.1)
199
+ sprockets (4.2.0)
185
200
  concurrent-ruby (~> 1.0)
186
- rack (> 1, < 3)
201
+ rack (>= 2.2.4, < 4)
187
202
  sprockets-rails (3.4.2)
188
203
  actionpack (>= 5.2)
189
204
  activesupport (>= 5.2)
190
205
  sprockets (>= 3.0.0)
191
206
  thor (1.2.1)
207
+ timeout (0.3.1)
192
208
  tzinfo (2.0.5)
193
209
  concurrent-ruby (~> 1.0)
194
210
  unf (0.1.4)
@@ -197,7 +213,7 @@ GEM
197
213
  websocket-driver (0.7.5)
198
214
  websocket-extensions (>= 0.1.0)
199
215
  websocket-extensions (0.1.5)
200
- zeitwerk (2.6.1)
216
+ zeitwerk (2.6.6)
201
217
 
202
218
  PLATFORMS
203
219
  x86_64-linux
@@ -205,7 +221,7 @@ PLATFORMS
205
221
  DEPENDENCIES
206
222
  active_job_k8s!
207
223
  rails (~> 6.1)
208
- rake (~> 12.0)
224
+ rake (~> 13.0)
209
225
  rspec (~> 3.0)
210
226
  simplecov
211
227
  simplecov-cobertura (~> 2.1.0)
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # ActiveJobK8s
1
+ # ActiveJobK8s [![Gem Version](https://badge.fury.io/rb/active_job_k8s.svg)](https://badge.fury.io/rb/active_job_k8s)
2
2
 
3
3
  WIP gem to make active job work with kubernetes jobs.
4
4
 
@@ -6,7 +6,7 @@ Roadmap for V1.0:
6
6
  - [x] ActiveJob.perform_later create a Job in k8s that will execute the job
7
7
  - [x] ActiveJob.perform_later with delay create a Job in k8s in suspended mode,
8
8
  a task will enable it as soon as the time is reached
9
- - [ ] Limiting the number of concurrent jobs (if there are more jobs they will be created in suspended mode)
9
+ - [x] Limiting the number of concurrent jobs (if there are more jobs they will be created in suspended mode)
10
10
 
11
11
  Future:
12
12
  - [ ] Metrics (because everyone like metrics)
@@ -117,9 +117,8 @@ rules:
117
117
  verbs:
118
118
  - get
119
119
  - list
120
- - watch
121
120
  - create
122
- - delete
121
+ - patch
123
122
  ---
124
123
  kind: RoleBinding
125
124
  apiVersion: rbac.authorization.k8s.io/v1
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.summary = "ActiveJob adapter for kubernetes job"
10
10
  spec.homepage = "https://github.com/oniram88/active_job_k8s"
11
11
  spec.license = "MIT"
12
- spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
12
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
13
13
 
14
14
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
15
15
 
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.require_paths = ["lib"]
28
28
 
29
29
  spec.add_dependency 'kubeclient', '~> 4.0' #https://github.com/ManageIQ/kubeclient
30
+ spec.add_dependency 'http', '>= 5.0' # dipendenza di kubeclient, ma non si compila correttamente con versione di ruby > di 2.7
30
31
  spec.add_dependency 'rails', '>= 6.0', '<8'
31
32
 
32
33
  end
data/bin/setup CHANGED
@@ -5,7 +5,7 @@ set -vx
5
5
 
6
6
  bundle install
7
7
 
8
- # Prepariamo l'applicazione esempio
8
+ # Create dummy application
9
9
  rm -fr spec/dummy
10
10
  bundle exec rails new spec/dummy --skip-git --skip-javascript --skip-hotwire --skip-jbuilder --skip-test --skip-bootsnap --force
11
11
 
@@ -15,6 +15,7 @@ sed -i 's/2.7.4/>= 2.7.4/' spec/dummy/Gemfile
15
15
  sed -i '/end/i root "main#index"' spec/dummy/config/routes.rb
16
16
  sed -i '/root "main#index"/i get "create_job", to: "main#create_job", as: "create_job"' spec/dummy/config/routes.rb
17
17
  sed -i '/root "main#index"/i get "send_email", to: "main#send_email", as: "send_email"' spec/dummy/config/routes.rb
18
+ sed -i '/root "main#index"/i get "health", to: "main#health"' spec/dummy/config/routes.rb
18
19
 
19
20
  echo '
20
21
  class MainController < ApplicationController
@@ -36,6 +37,10 @@ class MainController < ApplicationController
36
37
  redirect_to root_path
37
38
  end
38
39
 
40
+ def health
41
+ head :ok
42
+ end
43
+
39
44
  def send_email
40
45
  SubscriptionMailer.notify.deliver_later
41
46
  redirect_to root_path
@@ -117,6 +122,7 @@ class HelloWorldJob < ApplicationJob
117
122
 
118
123
  def perform(*args)
119
124
  Rails.logger.debug "Hello World"
125
+ sleep (SecureRandom.random_number * 50).to_i # simulate operations
120
126
  FileUtils.touch(Rails.root.join("tmp","#{SecureRandom.hex}.test"))
121
127
  end
122
128
  end
@@ -146,7 +152,7 @@ RUN bundle install
146
152
 
147
153
  COPY . .
148
154
 
149
- CMD ["/bin/sh", "-ec", "bundle install && bundle exec rails s -b 0.0.0.0 -p 3000"]' > spec/dummy/Dockerfile
155
+ CMD ["/bin/sh", "-ec", "rm -fr /usr/src/app/spec/dummy/tmp/pids/* && bundle install && bundle exec rails s -b 0.0.0.0 -p 3000"]' > spec/dummy/Dockerfile
150
156
 
151
157
  docker build -t activejobk8s:0.1.0 spec/dummy/.
152
158
 
@@ -191,6 +197,12 @@ spec:
191
197
  volumeMounts:
192
198
  - mountPath: /usr/src/app
193
199
  name: application-volume
200
+ livenessProbe:
201
+ httpGet:
202
+ path: /health
203
+ port: 3000
204
+ initialDelaySeconds: 120
205
+ periodSeconds: 3
194
206
  volumes:
195
207
  - name: application-volume
196
208
  hostPath:
@@ -210,9 +222,8 @@ rules:
210
222
  verbs:
211
223
  - get
212
224
  - list
213
- - watch
214
225
  - create
215
- - delete
226
+ - patch
216
227
  ---
217
228
  kind: RoleBinding
218
229
  apiVersion: rbac.authorization.k8s.io/v1
data/bin/teardown ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ rm -fr spec/dummy
7
+ kind delete cluster -n active-job-cluster
@@ -11,17 +11,75 @@ module ActiveJobK8s
11
11
  #@return [Hash]
12
12
  attr_reader :default_manifest
13
13
 
14
- # @param [Hash{ kubeclient_context: Kubeclient::Config::Context, default_manifest: Hash }] opts
15
- def initialize(**opts)
16
- raise "No KubeClientContext given" if opts[:kubeclient_context].nil?
14
+ # @param [Kubeclient::Config::Context] kubeclient_context
15
+ # @param [Hash] default_manifest
16
+ # @param [Integer] max_concurrent_jobs default 5
17
+ def initialize(kubeclient_context:, default_manifest: {}, max_concurrent_jobs: 5)
17
18
  # or to use a specific context, by name:
18
- @kubeclient_context = opts[:kubeclient_context]
19
- @default_manifest = opts[:default_manifest] || {}
20
-
19
+ @kubeclient_context = kubeclient_context
20
+ @default_manifest = default_manifest
21
+ @max_concurrent_jobs = max_concurrent_jobs
21
22
  end
22
23
 
23
24
  def create_job(job, scheduled_at: nil)
24
25
 
26
+ ##
27
+ # Make the job scheduled_at if there are not enought slot available
28
+ if scheduled_at.nil? and active_jobs.length>=@max_concurrent_jobs
29
+ scheduled_at = Time.now
30
+ end
31
+ _create_job(job, scheduled_at: scheduled_at)
32
+ end
33
+
34
+ def self.execute_job
35
+ ActiveJob::Base.execute(JSON.parse(ENV['SERIALIZED_JOB']))
36
+ end
37
+
38
+ ##
39
+ # Un-suspend jobs if the `scheduled at` is outdated, limited to max allowed concurrent
40
+ def un_suspend_jobs
41
+
42
+ to_activate_jobs = @max_concurrent_jobs - active_jobs.size
43
+ to_activate_jobs = 0 if to_activate_jobs < 0
44
+ # ::Rails.logger.debug { "Slot liberi: #{to_activate_jobs} - Job attivi: #{active_jobs.size} - Job in attesa: #{suspended_jobs.length}" }
45
+ suspended_jobs.select { |sj|
46
+ scheduled_at = Time.at(sj.metadata.annotations.scheduled_at.to_f)
47
+ Time.now > scheduled_at and sj.spec.suspend
48
+ }.take(to_activate_jobs).each do |sj|
49
+ client.patch_job(sj.metadata.name, { spec: { suspend: false } }, sj.metadata.namespace).inspect
50
+ end
51
+ end
52
+
53
+ protected
54
+
55
+ def client
56
+ @client ||= Kubeclient::Client.new(@kubeclient_context.api_endpoint + '/apis/batch',
57
+ @kubeclient_context.api_version || 'v1',
58
+ ssl_options: @kubeclient_context.ssl_options,
59
+ auth_options: @kubeclient_context.auth_options)
60
+ end
61
+
62
+ private
63
+
64
+ ##
65
+ # Internal list of all suspended jobs
66
+ def suspended_jobs
67
+ client.get_jobs(namespace: kubeclient_context.namespace,
68
+ label_selector: "activeJobK8s=scheduled",
69
+ field_selector: 'status.successful!=1')
70
+ end
71
+
72
+ # @return [Array<Kubeclient::Resource>]
73
+ def active_jobs
74
+ client.get_jobs(namespace: kubeclient_context.namespace,
75
+ label_selector: "activeJobK8s",
76
+ field_selector: 'status.successful!=1').select do |j|
77
+ j.status.active.to_i == 1 and j.spec.suspend != "true"
78
+ end
79
+ end
80
+
81
+ def _create_job(job, scheduled_at: nil)
82
+
25
83
  serialized_job = JSON.dump(job.serialize)
26
84
 
27
85
  manifest = (job.respond_to?(:manifest) and job.manifest.is_a?(Hash) and !job.manifest.empty?) ? job.manifest : default_manifest
@@ -44,7 +102,7 @@ module ActiveJobK8s
44
102
  container.args = ["active_job_k8s:run_job"]
45
103
  end
46
104
  end
47
- kube_job.spec.ttlSecondsAfterFinished = 300 #number of seconds the job will be erased
105
+ kube_job.spec.ttlSecondsAfterFinished = 300 # number of seconds the job will be erased
48
106
 
49
107
  kube_job.metadata.labels ||= {}
50
108
  if scheduled_at
@@ -57,39 +115,6 @@ module ActiveJobK8s
57
115
  client.create_job(kube_job)
58
116
  end
59
117
 
60
- def self.execute_job
61
- ActiveJob::Base.execute(JSON.parse(ENV['SERIALIZED_JOB']))
62
- end
63
-
64
- ##
65
- # Un-suspend jobs if the scheduled at is outdated
66
- def un_suspend_jobs
67
- suspended_jobs.each do |sj|
68
- scheduled_at = Time.at(sj.metadata.annotations.scheduled_at.to_f)
69
- if Time.now > scheduled_at and sj.spec.suspend
70
- client.patch_job(sj.metadata.name, { spec: { suspend: false } }, sj.metadata.namespace).inspect
71
- end
72
- end
73
- end
74
-
75
- protected
76
-
77
- def client
78
- @client ||= Kubeclient::Client.new(@kubeclient_context.api_endpoint + '/apis/batch',
79
- @kubeclient_context.api_version || 'v1',
80
- ssl_options: @kubeclient_context.ssl_options,
81
- auth_options: @kubeclient_context.auth_options)
82
- end
83
-
84
- private
85
-
86
- ##
87
- # Internal list of all suspended jobs
88
- def suspended_jobs
89
- client.get_jobs(namespace: kubeclient_context.namespace,
90
- label_selector: "activeJobK8s=scheduled",
91
- field_selector: 'status.successful!=1')
92
- end
93
118
  end
94
119
 
95
120
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveJobK8s
2
- VERSION = "0.2.0"
2
+ VERSION = "1.0.0-beta.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_job_k8s
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.0.0.pre.beta.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marino Bonetti
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-06 00:00:00.000000000 Z
11
+ date: 2023-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kubeclient
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: http
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '5.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '5.0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rails
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +80,7 @@ files:
66
80
  - bin/cluster.yaml
67
81
  - bin/console
68
82
  - bin/setup
83
+ - bin/teardown
69
84
  - lib/active_job/queue_adapters/k8s_adapter.rb
70
85
  - lib/active_job_k8s.rb
71
86
  - lib/active_job_k8s/railtie.rb
@@ -88,14 +103,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
88
103
  requirements:
89
104
  - - ">="
90
105
  - !ruby/object:Gem::Version
91
- version: 2.6.0
106
+ version: 2.7.0
92
107
  required_rubygems_version: !ruby/object:Gem::Requirement
93
108
  requirements:
94
- - - ">="
109
+ - - ">"
95
110
  - !ruby/object:Gem::Version
96
- version: '0'
111
+ version: 1.3.1
97
112
  requirements: []
98
- rubygems_version: 3.2.33
113
+ rubygems_version: 3.1.4
99
114
  signing_key:
100
115
  specification_version: 4
101
116
  summary: ActiveJob adapter for kubernetes job