chef-licensing 0.7.5 → 1.0.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
  SHA256:
3
- metadata.gz: 1bc6490da547bbded96f9eae129f488d1be7178feae66dc02dad8acba71fff0b
4
- data.tar.gz: 16f191bd6102f08be159bb73c88f1e992657e829248b54ecdd0c5743982f65d2
3
+ metadata.gz: 5e5b5b44e654ed1893f1301c716881eb494bcfe486284269523e45e648f6efd9
4
+ data.tar.gz: bce944cdc127668e1b89ab4dde0aa1d11574a37c7958d5b3af6a33101b806ec1
5
5
  SHA512:
6
- metadata.gz: 873ad985ccfc6cf42478d5e0deceb001d85f6ed74d6b62b0bb9355db66da9ad7f707f5a3d1f2aa2cece612f688321757d8c406c331c8e8ab543d1c12fbe4b794
7
- data.tar.gz: 155632f6ced920a84a6700c58bad75534e34c85fbf10b4f262b5cea030fecb291de9e429e41b4108b17e97e6f3ba744bc8cefbb1b15729a43bf89e75a0e8656f
6
+ metadata.gz: 777458fc88ca4e0349697ca50c6da364dd966d15e72c1e5122b504ff8446437827665bd7e0390801e39b6b0d0e826a0c385d434597805459caf26df2f833eba2
7
+ data.tar.gz: cc705ff5a9d5a8f626e74169bb683fd16db9928782226be465669521d2d0a688d644947625cd6ad931ab1fc53a386799aa4e0033296beefa53832361a2956443
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.summary = %q{Chef License storage, generation, and entitlement}
13
13
  spec.description = %q{Ruby library to support CLI tools that use Progress Chef license storage, generation, and entitlement.}
14
14
  spec.homepage = "https://github.com/chef/chef-licensing"
15
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
15
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0")
16
16
 
17
17
  spec.metadata["homepage_uri"] = spec.homepage
18
18
  spec.metadata["source_code_uri"] = "https://github.com/chef/chef-licensing"
@@ -13,7 +13,7 @@ require_relative "licensing_service/local"
13
13
  module ChefLicensing
14
14
  class Config
15
15
  class << self
16
- attr_writer :license_server_url, :logger, :output, :license_server_url_check_in_file
16
+ attr_writer :license_server_url, :logger, :output, :license_server_url_check_in_file, :license_add_command, :license_list_command
17
17
 
18
18
  # is_local_license_service is used by context class
19
19
  attr_accessor :is_local_license_service, :chef_entitlement_id, :chef_product_name, :chef_executable_name
@@ -39,6 +39,14 @@ module ChefLicensing
39
39
  def output
40
40
  @output ||= STDOUT
41
41
  end
42
+
43
+ def license_add_command
44
+ @license_add_command ||= "license add"
45
+ end
46
+
47
+ def license_list_command
48
+ @license_list_command ||= "license list"
49
+ end
42
50
  end
43
51
  end
44
52
  end
@@ -25,9 +25,20 @@ module ChefLicensing
25
25
  current_context(options).license_keys
26
26
  end
27
27
 
28
+ # Return license context object via current context
29
+ def license(options = {})
30
+ current_context(options).license
31
+ end
32
+
33
+ # Set license context object via current context
34
+ # Example: ChefLicensing::Context.license = license_context_object
35
+ def license=(license)
36
+ current_context.license = license
37
+ end
38
+
28
39
  private
29
40
 
30
- def current_context(options)
41
+ def current_context(options = {})
31
42
  return @current_context if @current_context
32
43
 
33
44
  @current_context = context_based_on_state(options)
@@ -63,6 +74,16 @@ module ChefLicensing
63
74
  @state.license_keys
64
75
  end
65
76
 
77
+ # Get license context from local or global state
78
+ def license
79
+ @state.license
80
+ end
81
+
82
+ # Set license context from local or global state
83
+ def license=(license)
84
+ @state.license = license
85
+ end
86
+
66
87
  class State
67
88
  attr_accessor :context, :options
68
89
 
@@ -70,6 +91,20 @@ module ChefLicensing
70
91
  def license_keys
71
92
  raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
72
93
  end
94
+
95
+ # Get license context in local or global state
96
+ def license
97
+ if license_keys.empty?
98
+ @license ||= nil
99
+ else
100
+ @license ||= ChefLicensing.client(license_keys: license_keys)
101
+ end
102
+ end
103
+
104
+ # Set license context in local or global state
105
+ def license=(license)
106
+ @license ||= license
107
+ end
73
108
  end
74
109
 
75
110
  # Implement various behaviors, associated with a state of the Context.
@@ -0,0 +1,9 @@
1
+ require_relative "error"
2
+
3
+ module ChefLicensing
4
+ class UnsupportedContentType < Error
5
+ def message
6
+ super || "Unsupported content type"
7
+ end
8
+ end
9
+ end
@@ -133,6 +133,10 @@ module ChefLicensing
133
133
  status.eql?("Expired")
134
134
  end
135
135
 
136
+ def exhausted?
137
+ status.eql?("Exhausted")
138
+ end
139
+
136
140
  def active?
137
141
  status.eql?("Active")
138
142
  end
@@ -148,4 +152,4 @@ module ChefLicensing
148
152
  status.eql?("Active") && expiration_status.eql?("Expired") && ((1..7).include? number_of_days_in_expiration)
149
153
  end
150
154
  end
151
- end
155
+ end
@@ -69,20 +69,20 @@ interactions:
69
69
 
70
70
  trial_restriction_message:
71
71
  prompt_type: "say"
72
- messages:
73
- Please generate a Free Tier or Commercial License by running <%= input[:pastel].bold("#{ChefLicensing::Config.chef_executable_name} license add")%>.
72
+ messages: |
73
+ Please generate a Free Tier or Commercial License by running <%= input[:pastel].bold("#{ChefLicensing::Config.chef_executable_name} #{ChefLicensing::Config.license_add_command}")%>.
74
74
  paths: [exit_with_message]
75
75
 
76
76
  free_restriction_message:
77
77
  prompt_type: "say"
78
- messages:
79
- Please generate a Trial or Commercial License by running <%= input[:pastel].bold("#{ChefLicensing::Config.chef_executable_name} license add")%>.
78
+ messages: |
79
+ Please generate a Trial or Commercial License by running <%= input[:pastel].bold("#{ChefLicensing::Config.chef_executable_name} #{ChefLicensing::Config.license_add_command}")%>.
80
80
  paths: [exit_with_message]
81
81
 
82
82
  only_commercial_allowed_message:
83
83
  prompt_type: "say"
84
- messages:
85
- Please generate a Commercial License by running <%= input[:pastel].bold("#{ChefLicensing::Config.chef_executable_name} license add")%>.
84
+ messages: |
85
+ Please generate a Commercial License by running <%= input[:pastel].bold("#{ChefLicensing::Config.chef_executable_name} #{ChefLicensing::Config.license_add_command}")%>.
86
86
  paths: [exit_with_message]
87
87
 
88
88
  prompt_license_expired:
@@ -90,11 +90,13 @@ interactions:
90
90
  ------------------------------------------------------------
91
91
  <%= input[:pastel].yellow("! [WARNING]")%> <%= input[:license_type] %> License Expired
92
92
 
93
- Get a Commercial License to receive bug fixes, updates
94
- and new features.
95
- Get a Free Tier License to scan limited <%= input[:unit_measure] %>.
93
+ We hope you've been enjoying Chef <%= input[:chef_product_name] %>!
94
+ However, it seems like your license has expired.
96
95
 
97
- To get a new license, run <%= input[:pastel].bold("#{ChefLicensing::Config.chef_executable_name} license add")%>
96
+ Reach out to our sales team at <%= input[:pastel].underline.green("chef-sales@progress.com")%>
97
+ to move to commercial tier.
98
+
99
+ To get a new license, run <%= input[:pastel].bold("#{ChefLicensing::Config.chef_executable_name} #{ChefLicensing::Config.license_add_command}") %>
98
100
  and select a license type.
99
101
  ------------------------------------------------------------
100
102
  prompt_type: "say"
@@ -105,9 +107,11 @@ interactions:
105
107
  ------------------------------------------------------------
106
108
  <%= input[:pastel].yellow("! [WARNING]")%> <%= input[:license_type] %> License Expired
107
109
 
108
- Get a Commercial License to receive bug fixes, updates
109
- and new features.
110
- Get a Free Tier License to scan limited <%= input[:unit_measure] %>.
110
+ We hope you've been enjoying Chef <%= input[:chef_product_name] %>!
111
+ However, it seems like your license has expired.
112
+
113
+ Reach out to our sales team at <%= input[:pastel].underline.green("chef-sales@progress.com")%>
114
+ to move to commercial tier.
111
115
  ------------------------------------------------------------
112
116
  prompt_type: "say"
113
117
  paths: [fetch_license_id]
@@ -195,12 +199,13 @@ interactions:
195
199
 
196
200
  validate_license_expiration:
197
201
  action: license_expiration_status?
198
- paths: [validation_success, prompt_license_about_to_expire, prompt_license_expired, prompt_license_expired_local_mode]
202
+ paths: [validation_success, prompt_license_about_to_expire, prompt_license_expired, prompt_license_expired_local_mode, prompt_license_exhausted]
199
203
  response_path_map:
200
204
  "active": validation_success
201
205
  "about_to_expire": prompt_license_about_to_expire
202
206
  "expired": prompt_license_expired
203
207
  "expired_in_local_mode": prompt_license_expired_local_mode
208
+ "exhausted_license": prompt_license_exhausted
204
209
 
205
210
  validation_success:
206
211
  messages: "✔ [Success] License validated successfully."
@@ -332,8 +337,50 @@ interactions:
332
337
 
333
338
  fetch_license_id:
334
339
  action: fetch_license_id
340
+ paths: [is_commercial_license]
341
+
342
+ is_commercial_license:
343
+ action: is_commercial_license?
344
+ response_path_map:
345
+ "true": exit
346
+ "false": warn_non_commercial_license
347
+ paths: [warn_non_commercial_license, exit]
348
+
349
+ warn_non_commercial_license:
350
+ messages: |
351
+ ------------------------------------------------------------
352
+ <%= input[:pastel].yellow("! [WARNING]")%> Non-Commercial License
353
+
354
+ You are using a <%= input[:license_type].downcase == "free" ? "free tier" : "trial" %> version - not meant for commercial usage.
355
+
356
+ If you are using it for commercial purposes, please reach
357
+ out to our sales team at <%= input[:pastel].underline.green("chef-sales@progress.com")%> to get
358
+ commercial license to be compliant with Progress Chef MLSA.
359
+ ------------------------------------------------------------
360
+ prompt_type: "say"
335
361
  paths: [exit]
336
362
 
363
+ prompt_license_exhausted:
364
+ messages: |
365
+ ------------------------------------------------------------
366
+ <%= input[:pastel].yellow("! [WARNING]")%> <%= input[:license_type].capitalize %> License Exhausted
367
+
368
+ We hope you've been enjoying Chef <%= input[:chef_product_name] %>!
369
+ However, it seems like you have exceeded your entitled usage limit on <%= input[:unit_measure] %>.
370
+
371
+ Reach out to our sales team at <%= input[:pastel].underline.green("chef-sales@progress.com")%>
372
+ to move to commercial-tier.
373
+ ------------------------------------------------------------
374
+ prompt_type: "say"
375
+ paths: [is_run_allowed_on_license_exhausted]
376
+
377
+ is_run_allowed_on_license_exhausted:
378
+ action: is_run_allowed_on_license_exhausted?
379
+ response_path_map:
380
+ "true": fetch_license_id
381
+ "false": exit
382
+ paths: [fetch_license_id, exit]
383
+
337
384
  exit:
338
385
  messages: ""
339
386
 
@@ -67,6 +67,15 @@ module ChefLicensing
67
67
  @active_trial_status
68
68
  end
69
69
 
70
+ def user_has_active_trial_or_free_license?
71
+ read_license_key_file
72
+ return false unless contents&.key?(:licenses)
73
+
74
+ all_license_keys = contents[:licenses].collect { |license| license[:license_key] }
75
+ license_obj = ChefLicensing.client(license_keys: all_license_keys)
76
+ (%w{trial free}.include? license_obj.license_type&.downcase) && license_obj.active?
77
+ end
78
+
70
79
  def fetch_allowed_license_types_for_addition
71
80
  license_types = %i{free trial commercial}
72
81
  existing_license_types = fetch_license_types
@@ -85,9 +85,9 @@ module ChefLicensing
85
85
  end
86
86
  end
87
87
 
88
- # Scenario: When a user is prompted for license expiry and license is not yet renewed
89
- if %i{prompt_license_about_to_expire prompt_license_expired_local_mode}.include?(config[:start_interaction])
90
- # Not blocking any license type in case of expiry
88
+ # Expired trial licenses and exhausted free licenses will be blocked
89
+ # Not blocking commercial licenses
90
+ if license && ((!license.expired? && !license.exhausted?) || (license.license_type.downcase == "commercial"))
91
91
  return @license_keys
92
92
  end
93
93
 
@@ -119,7 +119,7 @@ module ChefLicensing
119
119
  # Return keys if there is any error in /client API call, and do not block the flow.
120
120
  # Client API possible errors will be handled in software entitlement check call (made after this)
121
121
  # client_api_call_error is set to true when there is an error in licenses_active? call
122
- return @license_keys if (!@license_keys.empty? && licenses_active?) || client_api_call_error
122
+ return @license_keys if (!@license_keys.empty? && licenses_active? && ChefLicensing::Context.license.license_type.downcase == "commercial") || client_api_call_error
123
123
 
124
124
  # Lowest priority is to interactively prompt if we have a TTY
125
125
  if config[:output].isatty
@@ -131,13 +131,19 @@ module ChefLicensing
131
131
  # If license type is not selected using TUI, assign it using API call to fetch type.
132
132
  prompt_fetcher.license_type ||= get_license_type(new_keys.first)
133
133
  persist_and_concat(new_keys, prompt_fetcher.license_type)
134
- return license_keys
134
+ license ||= ChefLicensing::Context.license
135
+ # Expired trial licenses and exhausted free licenses will be blocked
136
+ # Not blocking commercial licenses
137
+ if (!license&.expired? && !license&.exhausted?) || (license&.license_type&.downcase == "commercial")
138
+ return license_keys
139
+ end
135
140
  end
136
141
  end
137
142
 
138
- # Scenario: When a user is prompted for license expiry and license is not yet renewed
139
- if new_keys.empty? && %i{prompt_license_about_to_expire prompt_license_expired}.include?(config[:start_interaction])
140
- # Not blocking any license type in case of expiry
143
+ # Expired trial licenses and exhausted free licenses will be blocked
144
+ # Not blocking commercial licenses
145
+ license ||= ChefLicensing::Context.license
146
+ if new_keys.empty? && license && ((!license.expired? && !license.exhausted?) || (license.license_type.downcase == "commercial"))
141
147
  return @license_keys
142
148
  end
143
149
 
@@ -198,6 +204,7 @@ module ChefLicensing
198
204
  extra_info[:license_type] = license.license_type.capitalize
199
205
  extra_info[:number_of_days_in_expiration] = license.number_of_days_in_expiration
200
206
  extra_info[:license_expiration_date] = Date.parse(license.expiration_date).strftime("%a, %d %b %Y")
207
+ extra_info[:is_commercial] = license.license_type.downcase == "commercial"
201
208
  end
202
209
 
203
210
  unless info.empty? # ability to add info hash through arguments
@@ -215,6 +222,9 @@ module ChefLicensing
215
222
  # This call returns a license based on client logic
216
223
  # This API call is only made when multiple license keys are present or if client call was never done
217
224
  self.license = ChefLicensing.client(license_keys: @license_keys) if !license || @license_keys.count > 1
225
+
226
+ # Cache license context
227
+ ChefLicensing::Context.license = license
218
228
  # Intentional lag of 2 seconds when license is expiring or expired
219
229
  sleep 2 if license.expiring_or_expired?
220
230
  spinner.success # Stop the spinner
@@ -230,7 +240,13 @@ module ChefLicensing
230
240
  config[:start_interaction] = :prompt_license_about_to_expire
231
241
  prompt_fetcher.config = config
232
242
  false
243
+ elsif license.exhausted? && (license.license_type.downcase == "commercial" || license.license_type.downcase == "free")
244
+ config[:start_interaction] = :prompt_license_exhausted
245
+ prompt_fetcher.config = config
246
+ false
233
247
  else
248
+ # If license is not expired or expiring, return true. But if the license is not commercial, warn the user.
249
+ config[:start_interaction] = :warn_non_commercial_license unless license.license_type.downcase == "commercial"
234
250
  true
235
251
  end
236
252
  rescue ChefLicensing::ClientError => e
@@ -274,8 +290,8 @@ module ChefLicensing
274
290
  end
275
291
 
276
292
  def get_license_type(license_key)
277
- self.license = ChefLicensing.client(license_keys: [license_key])
278
- license.license_type.downcase.to_sym
293
+ license_obj = ChefLicensing.client(license_keys: [license_key])
294
+ license_obj.license_type.downcase.to_sym
279
295
  end
280
296
 
281
297
  def license_restricted?(license_type)
@@ -300,16 +316,22 @@ module ChefLicensing
300
316
  # However, if user is trying to add Free Tier License, and user has active trial license, we fetch the trial license key
301
317
  if license_type == :free && file_fetcher.user_has_active_trial_license?
302
318
  existing_license_keys_in_file = file_fetcher.fetch_license_keys_based_on_type(:trial)
303
- else
319
+ elsif file_fetcher.user_has_active_trial_or_free_license?
320
+ # Handling license addition restriction scenarios only if the current license is an active license
304
321
  existing_license_keys_in_file = file_fetcher.fetch_license_keys_based_on_type(license_type)
305
322
  end
323
+
306
324
  # Only prompt when a new trial license is added
307
- unless existing_license_keys_in_file.last == new_keys.first
308
- # prompt the message that this addition of license is restricted.
309
- prompt_license_addition_restricted(license_type, existing_license_keys_in_file)
310
- return false
325
+ if existing_license_keys_in_file
326
+ unless existing_license_keys_in_file.last == new_keys.first
327
+ # prompt the message that this addition of license is restricted.
328
+ prompt_license_addition_restricted(license_type, existing_license_keys_in_file)
329
+ return false
330
+ end
311
331
  end
312
- true # license type is restricted but not the key since it is the same key hence returning true
332
+ # license addition should be restricted but it is not because the key is same as that of one user is trying to add
333
+ # license addition should be restricted but it is not because the license is expired and warning wont be handled by this restriction
334
+ true
313
335
  else
314
336
  persist_and_concat(new_keys, license_type)
315
337
  true
@@ -7,6 +7,7 @@ require_relative "../exceptions/restful_client_connection_error"
7
7
  require_relative "../exceptions/missing_api_credentials_error"
8
8
  require_relative "../config"
9
9
  require_relative "middleware/exceptions_handler"
10
+ require_relative "middleware/content_type_validator"
10
11
 
11
12
  module ChefLicensing
12
13
  module RestfulClient
@@ -137,6 +138,7 @@ module ChefLicensing
137
138
  config.response :json, parser_options: { object_class: OpenStruct }
138
139
  config.use Faraday::HttpCache, shared_cache: false, logger: logger, store: store
139
140
  config.use Middleware::ExceptionsHandler
141
+ config.use Middleware::ContentTypeValidator
140
142
  config.adapter Faraday.default_adapter
141
143
  end
142
144
  end
@@ -0,0 +1,24 @@
1
+ require "faraday/middleware"
2
+ require_relative "../../../chef-licensing/exceptions/unsupported_content_type"
3
+
4
+ module Middleware
5
+ class ContentTypeValidator < Faraday::Middleware
6
+ def call(env)
7
+ @app.call(env).on_complete do |response_env|
8
+ content_type = response_env[:response_headers]["content-type"]
9
+ body = response_env[:body]
10
+ # trim the body to 1000 characters to avoid printing a huge string in the error message
11
+ body = body[0..1000] if body.is_a?(String)
12
+ raise ChefLicensing::UnsupportedContentType, error_message(content_type, body) unless content_type == "application/json"
13
+ end
14
+ end
15
+
16
+ def error_message(content_type, body = nil)
17
+ <<~EOM
18
+ Expected 'application/json' content-type, but received '#{content_type}' from the licensing server.
19
+ Snippet of body: `#{body}`
20
+ Possible causes: Check for firewall restrictions, ensure proper server response, or seek support assistance.
21
+ EOM
22
+ end
23
+ end
24
+ end
@@ -43,6 +43,9 @@ module ChefLicensing
43
43
  def is_license_allowed?(input)
44
44
  client_api_call(license_id)
45
45
  self.license_type = get_license_type
46
+ # When user enters the license via TUI, we need to check if the license type is commercial to display warnings.
47
+ input[:is_commercial] = license_type == :commercial ? true : false
48
+ input[:license_type] = license_type
46
49
  if license_restricted?(license_type)
47
50
  # Existing license keys needs to be fetcher to show details of existing license of license type which is restricted.
48
51
  # However, if user is trying to add Free Tier License, and user has active trial license, we fetch the trial license key
@@ -66,15 +69,26 @@ module ChefLicensing
66
69
  input[:license_expiration_date] = Date.parse(license.expiration_date).strftime("%a, %d %b %Y")
67
70
  input[:number_of_days_in_expiration] = license.number_of_days_in_expiration
68
71
  "about_to_expire"
72
+ elsif license.exhausted? && (license.license_type.downcase == "commercial" || license.license_type.downcase == "free")
73
+ input[:license_type] = license.license_type
74
+ "exhausted_license"
69
75
  else
70
76
  "active"
71
77
  end
72
78
  end
73
79
 
80
+ def is_run_allowed_on_license_exhausted?(input)
81
+ input[:license_type].downcase == "commercial"
82
+ end
83
+
74
84
  def fetch_license_id(input)
75
85
  license_id
76
86
  end
77
87
 
88
+ def is_commercial_license?(input)
89
+ input[:is_commercial]
90
+ end
91
+
78
92
  def fetch_invalid_license_msg(input)
79
93
  invalid_license_msg
80
94
  end
@@ -1,3 +1,3 @@
1
1
  module ChefLicensing
2
- VERSION = "0.7.5".freeze
2
+ VERSION = "1.0.0".freeze
3
3
  end
@@ -8,6 +8,7 @@ require "chef-licensing/exceptions/software_not_entitled"
8
8
  require "chef-licensing/exceptions/client_error"
9
9
  require "chef-licensing/api/client"
10
10
  require "chef-licensing/license_key_fetcher/prompt"
11
+ require "chef-licensing/context"
11
12
 
12
13
  module ChefLicensing
13
14
  class << self
@@ -66,5 +67,9 @@ module ChefLicensing
66
67
  def add_license
67
68
  ChefLicensing::LicenseKeyFetcher.add_license
68
69
  end
70
+
71
+ def license_context
72
+ ChefLicensing::Context.license
73
+ end
69
74
  end
70
75
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-licensing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.5
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Inspec Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-10 00:00:00.000000000 Z
11
+ date: 2024-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-config
@@ -141,6 +141,7 @@ files:
141
141
  - lib/chef-licensing/exceptions/restful_client_connection_error.rb
142
142
  - lib/chef-licensing/exceptions/restful_client_error.rb
143
143
  - lib/chef-licensing/exceptions/software_not_entitled.rb
144
+ - lib/chef-licensing/exceptions/unsupported_content_type.rb
144
145
  - lib/chef-licensing/license.rb
145
146
  - lib/chef-licensing/license_key_fetcher.rb
146
147
  - lib/chef-licensing/license_key_fetcher/base.rb
@@ -154,6 +155,7 @@ files:
154
155
  - lib/chef-licensing/licensing_service/local.rb
155
156
  - lib/chef-licensing/list_license_keys.rb
156
157
  - lib/chef-licensing/restful_client/base.rb
158
+ - lib/chef-licensing/restful_client/middleware/content_type_validator.rb
157
159
  - lib/chef-licensing/restful_client/middleware/exceptions_handler.rb
158
160
  - lib/chef-licensing/restful_client/v1.rb
159
161
  - lib/chef-licensing/tui_engine.rb
@@ -178,14 +180,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
178
180
  requirements:
179
181
  - - ">="
180
182
  - !ruby/object:Gem::Version
181
- version: 2.3.0
183
+ version: 3.1.0
182
184
  required_rubygems_version: !ruby/object:Gem::Requirement
183
185
  requirements:
184
186
  - - ">="
185
187
  - !ruby/object:Gem::Version
186
188
  version: '0'
187
189
  requirements: []
188
- rubygems_version: 3.1.4
190
+ rubygems_version: 3.2.3
189
191
  signing_key:
190
192
  specification_version: 4
191
193
  summary: Chef License storage, generation, and entitlement