chef-licensing 0.4.44 → 0.7.5

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
  SHA256:
3
- metadata.gz: daba1b4af5298de677c11ea6bdfa10fe560e94f3dc26ba60e68f887be5d3d187
4
- data.tar.gz: c45e92d1bba749e0aff95328df2b35bcba959022584cc07ad2e475f8a89be945
3
+ metadata.gz: 1bc6490da547bbded96f9eae129f488d1be7178feae66dc02dad8acba71fff0b
4
+ data.tar.gz: 16f191bd6102f08be159bb73c88f1e992657e829248b54ecdd0c5743982f65d2
5
5
  SHA512:
6
- metadata.gz: c0ff4a1cf85a1155badc2f18f1e31be42745c8952c495b87ab9af8067d13a3b2568e009c6a9bb0b1abf7812317994cf38d388c0220673e0a2027b590dbab26a8
7
- data.tar.gz: bf7296fdb8806695442b1b19d9968853984def094d126134e03774ec9bfed481cf8a66306848743a8b2c970f35b05dc6708583fe01a8222907435ce96da96ec2
6
+ metadata.gz: 873ad985ccfc6cf42478d5e0deceb001d85f6ed74d6b62b0bb9355db66da9ad7f707f5a3d1f2aa2cece612f688321757d8c406c331c8e8ab543d1c12fbe4b794
7
+ data.tar.gz: 155632f6ced920a84a6700c58bad75534e34c85fbf10b4f262b5cea030fecb291de9e429e41b4108b17e97e6f3ba744bc8cefbb1b15729a43bf89e75a0e8656f
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.version = ChefLicensing::VERSION
8
8
  spec.authors = ["Inspec Team"]
9
9
  spec.email = ["inspec@progress.com"]
10
- spec.license = "LicenseRef-LICENSE"
10
+ spec.license = "Apache-2.0"
11
11
 
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.}
@@ -30,6 +30,9 @@ Gem::Specification.new do |spec|
30
30
  spec.add_dependency "tty-prompt", "~> 0.23"
31
31
  spec.add_dependency "faraday", ">= 1", "< 3"
32
32
  spec.add_dependency "faraday-http-cache"
33
- spec.add_dependency "activesupport", "~> 7.0", ">= 7.0.4.2"
33
+ # Note: 7.1.0 does not defaults its cache_format_version to 7.1 but 6.1 instead which gives deprecation warnings
34
+ # Remove the version constraint when we can upgrade to 7.1.1 post stable release of Activesupport 7.1
35
+ # Similar issue with 7.0 existed: https://github.com/rails/rails/pull/45293
36
+ spec.add_dependency "activesupport", "~> 7.0", "< 7.1"
34
37
  spec.add_dependency "tty-spinner", "~> 0.9.3"
35
38
  end
@@ -0,0 +1,10 @@
1
+ require_relative "error"
2
+
3
+ module ChefLicensing
4
+ class InvalidFileFormatVersion < Error
5
+ def message
6
+ super || "Invalid File Format Version"
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,9 @@
1
+ require_relative "error"
2
+
3
+ module ChefLicensing
4
+ class LicenseFileCorrupted < Error
5
+ def message
6
+ super || "License file contents are corrupted"
7
+ end
8
+ end
9
+ end
@@ -7,13 +7,13 @@ interactions:
7
7
  License ID Validation
8
8
 
9
9
  To continue using Chef <%= input[:chef_product_name] %>, a license ID is required.
10
- (Free, Trial, or Commercial)
10
+ (Free Tier, Trial, or Commercial)
11
11
 
12
12
  If you generated a license previously, you might
13
13
  have received it in an email.
14
14
 
15
15
  If you are a commercial user, you can also find it in the
16
- <%= input[:pastel].underline.green("supportlink.chef.io")%> portal.
16
+ <%= input[:pastel].underline.green("https://community.progress.com/s/products/chef")%> portal.
17
17
  ------------------------------------------------------------
18
18
  prompt_type: "say"
19
19
  paths: [ask_if_user_has_license_id]
@@ -46,7 +46,7 @@ interactions:
46
46
  paths: [add_license_info_in_restriction_flow]
47
47
 
48
48
  free_license_already_exist_message:
49
- messages: "A Free License already exists with following details: \n"
49
+ messages: "A Free Tier License already exists with following details: \n"
50
50
  prompt_type: "say"
51
51
  paths: [add_license_info_in_restriction_flow]
52
52
 
@@ -70,7 +70,7 @@ interactions:
70
70
  trial_restriction_message:
71
71
  prompt_type: "say"
72
72
  messages:
73
- Please generate a Free or Commercial License by running <%= input[:pastel].bold("#{ChefLicensing::Config.chef_executable_name} license add")%>.
73
+ Please generate a Free Tier or Commercial License by running <%= input[:pastel].bold("#{ChefLicensing::Config.chef_executable_name} license add")%>.
74
74
  paths: [exit_with_message]
75
75
 
76
76
  free_restriction_message:
@@ -92,7 +92,7 @@ interactions:
92
92
 
93
93
  Get a Commercial License to receive bug fixes, updates
94
94
  and new features.
95
- Get a Free License to scan limited <%= input[:unit_measure] %>.
95
+ Get a Free Tier License to scan limited <%= input[:unit_measure] %>.
96
96
 
97
97
  To get a new license, run <%= input[:pastel].bold("#{ChefLicensing::Config.chef_executable_name} license add")%>
98
98
  and select a license type.
@@ -107,7 +107,7 @@ interactions:
107
107
 
108
108
  Get a Commercial License to receive bug fixes, updates
109
109
  and new features.
110
- Get a Free License to scan limited <%= input[:unit_measure] %>.
110
+ Get a Free Tier License to scan limited <%= input[:unit_measure] %>.
111
111
  ------------------------------------------------------------
112
112
  prompt_type: "say"
113
113
  paths: [fetch_license_id]
@@ -257,14 +257,14 @@ interactions:
257
257
  prompt_type: "select"
258
258
  messages: ["Select the type of license below and then enter user details\n" ,
259
259
  [
260
- "1. Free License\n Validity: Unlimited\n No. of units: 10 <%= input[:unit_measure] %>\n",
260
+ "1. Free Tier License\n Validity: Unlimited\n No. of units: 10 <%= input[:unit_measure] %>\n",
261
261
  "2. Commercial License\n",
262
262
  "3. Quit license generation"
263
263
  ]]
264
- paths: [free_license_disclaimer, commercial_license_selection, exit]
264
+ paths: [free_trial_license_selection, commercial_license_selection, exit]
265
265
  response_path_map:
266
- "1. Free License\n Validity: Unlimited\n No. of units: 10 nodes\n": free_license_disclaimer
267
- "1. Free License\n Validity: Unlimited\n No. of units: 10 targets\n": free_license_disclaimer
266
+ "1. Free Tier License\n Validity: Unlimited\n No. of units: 10 nodes\n": free_trial_license_selection
267
+ "1. Free Tier License\n Validity: Unlimited\n No. of units: 10 targets\n": free_trial_license_selection
268
268
  "2. Commercial License\n": commercial_license_selection
269
269
  "3. Quit license generation": exit
270
270
 
@@ -276,10 +276,10 @@ interactions:
276
276
  "2. Commercial License\n",
277
277
  "3. Quit license generation"
278
278
  ]]
279
- paths: [trial_license_selection, commercial_license_selection, exit]
279
+ paths: [free_trial_license_selection, commercial_license_selection, exit]
280
280
  response_path_map:
281
- "1. Trial License\n Validity: 30 Days\n No. of units: Unlimited nodes\n": trial_license_selection
282
- "1. Trial License\n Validity: 30 Days\n No. of units: Unlimited targets\n": trial_license_selection
281
+ "1. Trial License\n Validity: 30 Days\n No. of units: Unlimited nodes\n": free_trial_license_selection
282
+ "1. Trial License\n Validity: 30 Days\n No. of units: Unlimited targets\n": free_trial_license_selection
283
283
  "2. Commercial License\n": commercial_license_selection
284
284
  "3. Quit license generation": exit
285
285
 
@@ -287,34 +287,41 @@ interactions:
287
287
  prompt_type: "select"
288
288
  messages: ["Select the type of license below and then enter user details\n" ,
289
289
  [
290
- "1. Free License\n Validity: Unlimited\n No. of units: 10 <%= input[:unit_measure] %>\n",
290
+ "1. Free Tier License\n Validity: Unlimited\n No. of units: 10 <%= input[:unit_measure] %>\n",
291
291
  "2. Trial License\n Validity: 30 Days\n No. of units: Unlimited <%= input[:unit_measure] %>\n",
292
292
  "3. Commercial License\n",
293
293
  "4. Quit license generation"
294
294
  ]]
295
- paths: [free_license_disclaimer, commercial_license_selection, trial_license_selection, exit]
295
+ paths: [free_trial_license_selection, commercial_license_selection, exit]
296
296
  response_path_map:
297
- "1. Free License\n Validity: Unlimited\n No. of units: 10 nodes\n": free_license_disclaimer
298
- "1. Free License\n Validity: Unlimited\n No. of units: 10 targets\n": free_license_disclaimer
299
- "2. Trial License\n Validity: 30 Days\n No. of units: Unlimited nodes\n": trial_license_selection
300
- "2. Trial License\n Validity: 30 Days\n No. of units: Unlimited targets\n": trial_license_selection
297
+ "1. Free Tier License\n Validity: Unlimited\n No. of units: 10 nodes\n": free_trial_license_selection
298
+ "1. Free Tier License\n Validity: Unlimited\n No. of units: 10 targets\n": free_trial_license_selection
299
+ "2. Trial License\n Validity: 30 Days\n No. of units: Unlimited nodes\n": free_trial_license_selection
300
+ "2. Trial License\n Validity: 30 Days\n No. of units: Unlimited targets\n": free_trial_license_selection
301
301
  "3. Commercial License\n": commercial_license_selection
302
302
  "4. Quit license generation": exit
303
303
 
304
- free_license_disclaimer:
305
- messages: '<%= input[:pastel].bold("A Free License can be used for personal, non-commercial use only.\n")%>'
306
- prompt_type: "warn"
307
- paths: [free_license_selection]
308
-
309
- free_license_selection:
310
- messages: "Type: Free License\n Validity: Unlimited\n No. of units: 10 <%= input[:unit_measure] %>\n"
311
- prompt_type: "silent"
312
- paths: [check_if_user_details_are_present]
304
+ # Note: The below link is specific to InSpec; as per PO there will be different link for other products.
305
+ # We need to update the link for other products once we have the link or update to a common link.
306
+ free_trial_license_selection:
307
+ messages: ["<%= input[:pastel].yellow(\"!\") %> Kindly complete the user registration at <%= input[:pastel].blue.underline.blue(\"https://www.chef.io/license-generation-free-trial\") %>\nOnce you submit the details, you will receive the license ID on the email id you provided.\n\nSelect an option",
308
+ [
309
+ Validate license now,
310
+ Quit and validate license later
311
+ ]
312
+ ]
313
+ prompt_type: "select"
314
+ paths: [validate_license_later_message, ask_for_license_id]
315
+ response_path_map:
316
+ "Validate license now": ask_for_license_id
317
+ "Quit and validate license later": validate_license_later_message
313
318
 
314
- trial_license_selection:
315
- messages: "Type: Trial License\n Validity: 30 days\n No. of units: Unlimited <%= input[:unit_measure] %>\n"
316
- prompt_type: "silent"
317
- paths: [check_if_user_details_are_present]
319
+ # TODO: Update the link for other ways to validate the license document.
320
+ validate_license_later_message:
321
+ messages: |
322
+ You can enter the license later on by selecting <%= input[:pastel].bold("'I already have a license ID'") %> when prompted for license.
323
+ To learn about more ways to enter the license, kindly visit <%= input[:pastel].blue.underline.blue("www.docs.chef.io") %>.
324
+ paths: [exit]
318
325
 
319
326
  commercial_license_selection:
320
327
  messages: ["Get in touch with the Sales Team by filling out the form available at <%= input[:pastel].blue.underline.blue(\"https://www.chef.io/contact-us\") %>\n",
@@ -323,213 +330,10 @@ interactions:
323
330
  prompt_type: "select"
324
331
  paths: [exit_with_message]
325
332
 
326
- check_if_user_details_are_present:
327
- action: are_user_details_present?
328
- paths: [ask_for_user_details, print_to_review_details]
329
- response_path_map:
330
- "true": "print_to_review_details"
331
- "false": "ask_for_user_details"
332
-
333
- ask_for_user_details:
334
- messages: |
335
- Please enter the following details:
336
- First Name, Last Name, Email, Company, Phone
337
-
338
- paths: [gather_user_first_name_for_license_generation]
339
-
340
- gather_user_first_name_for_license_generation:
341
- messages: "Enter First Name: "
342
- prompt_type: "ask"
343
- paths: [validate_user_first_name_for_license_generation]
344
-
345
- validate_user_first_name_for_license_generation:
346
- action: is_user_name_valid?
347
- paths: [gather_user_last_name_for_license_generation, user_first_name_validation_failure]
348
- response_path_map:
349
- "true": gather_user_last_name_for_license_generation
350
- "false": user_first_name_validation_failure
351
-
352
- user_first_name_validation_failure:
353
- messages: "Invalid name. It should contain only A-Z/a-z alphabets."
354
- prompt_type: "error"
355
- paths: [gather_user_first_name_for_license_generation]
356
-
357
- gather_user_last_name_for_license_generation:
358
- messages: "Enter Last Name: "
359
- prompt_type: "ask"
360
- paths: [validate_user_last_name_for_license_generation]
361
-
362
- validate_user_last_name_for_license_generation:
363
- action: is_user_name_valid?
364
- paths: [gather_user_email_for_license_generation, user_last_name_validation_failure]
365
- response_path_map:
366
- "true": gather_user_email_for_license_generation
367
- "false": user_last_name_validation_failure
368
-
369
- user_last_name_validation_failure:
370
- messages: "Invalid name. It should contain only A-Z/a-z alphabets."
371
- prompt_type: "error"
372
- paths: [gather_user_last_name_for_license_generation]
373
-
374
- gather_user_email_for_license_generation:
375
- messages: "Enter Email Address: "
376
- prompt_type: "ask"
377
- paths: [validate_user_email_for_license_generation]
378
-
379
- validate_user_email_for_license_generation:
380
- action: is_email_valid?
381
- paths: [gather_user_company_for_license_generation, user_email_validation_failure]
382
- response_path_map:
383
- "true": gather_user_company_for_license_generation
384
- "false": user_email_validation_failure
385
-
386
- user_email_validation_failure:
387
- messages: "Invalid email address."
388
- prompt_type: "error"
389
- paths: [gather_user_email_for_license_generation]
390
-
391
- gather_user_company_for_license_generation:
392
- messages: "Enter Company Name: "
393
- prompt_type: "ask"
394
- paths: [validate_user_company_name_for_license_generation]
395
-
396
- validate_user_company_name_for_license_generation:
397
- action: is_company_name_valid?
398
- paths: [gather_user_phone_no_for_license_generation, user_company_name_validation_failure]
399
- response_path_map:
400
- "true": gather_user_phone_no_for_license_generation
401
- "false": user_company_name_validation_failure
402
-
403
- user_company_name_validation_failure:
404
- messages: "Invalid company name. It should contain only A-Z/a-z alphabets, numbers or special characters."
405
- prompt_type: "error"
406
- paths: [gather_user_company_for_license_generation]
407
-
408
- gather_user_phone_no_for_license_generation:
409
- messages: "Enter phone number: "
410
- prompt_type: "ask"
411
- paths: [validate_user_phone_no]
412
-
413
- validate_user_phone_no:
414
- action: is_phone_no_valid?
415
- paths: [print_to_review_details, user_phone_no_validation_failure]
416
- response_path_map:
417
- "true": print_to_review_details
418
- "false": user_phone_no_validation_failure
419
-
420
- user_phone_no_validation_failure:
421
- messages: "Please enter a valid phone number."
422
- prompt_type: "error"
423
- paths: [gather_user_phone_no_for_license_generation]
424
-
425
- print_to_review_details:
426
- messages: |
427
- ------------------------------------------------------------
428
- Review the details below and confirm to proceed.
429
- ------------------------------------------------------------
430
- License Details
431
-
432
- <%= input[:free_license_selection] || input[:trial_license_selection] %>
433
- User Details
434
-
435
- First Name: <%= input[:gather_user_first_name_for_license_generation] %>
436
- Last Name: <%= input[:gather_user_last_name_for_license_generation] %>
437
- Email: <%= input[:gather_user_email_for_license_generation] %>
438
- Company: <%= input[:gather_user_company_for_license_generation] %>
439
- Phone number: <%= input[:gather_user_phone_no_for_license_generation] %>
440
- ------------------------------------------------------------
441
- prompt_type: "say"
442
- paths: [ask_for_review_confirmation]
443
-
444
- ask_for_review_confirmation:
445
- prompt_type: "select"
446
- messages: ["Please select", ["Confirm the details and proceed", "Reselect the license type", "Edit user details", "Quit the license generation process"]]
447
- paths: [pre_license_generation, clear_current_license_type_selection, ask_for_user_details, exit]
448
- response_path_map:
449
- "Confirm the details and proceed": pre_license_generation
450
- "Reselect the license type": clear_current_license_type_selection
451
- "Edit user details": ask_for_user_details
452
- "Quit the license generation process": exit
453
-
454
- clear_current_license_type_selection:
455
- action: clear_license_type_selection
456
- paths: [info_of_license_types]
457
-
458
- pre_license_generation:
459
- action: select_license_generation_based_on_type
460
- paths: [generate_free_license, generate_trial_license]
461
- response_path_map:
462
- "free": generate_free_license
463
- "trial": generate_trial_license
464
-
465
- generate_free_license:
466
- action: generate_free_license
467
- paths: [free_license_generation_success, license_generation_failure]
468
- response_path_map:
469
- "true": free_license_generation_success
470
- "false": license_generation_failure
471
-
472
- generate_trial_license:
473
- action: generate_trial_license
474
- paths: [trial_license_generation_success, license_generation_failure]
475
- response_path_map:
476
- "true": trial_license_generation_success
477
- "false": license_generation_failure
478
-
479
- free_license_generation_success:
480
- messages: |
481
- <%= input[:pastel].green("✔ [Success] License generated successfully") %>
482
-
483
- The license ID has been sent to <%= input[:gather_user_email_for_license_generation] %>.
484
- paths: [ask_for_license_id]
485
-
486
- trial_license_generation_success:
487
- messages: |
488
- <%= input[:pastel].green("✔ [Success] License generated successfully") %>
489
-
490
- The license ID has been sent to <%= input[:gather_user_email_for_license_generation] %>.
491
- paths: [ask_for_license_id]
492
-
493
333
  fetch_license_id:
494
334
  action: fetch_license_id
495
335
  paths: [exit]
496
336
 
497
- license_generation_failure:
498
- messages: "✖ [Error] License generation failed."
499
- prompt_type: "error"
500
- paths: [check_failure_reason]
501
-
502
- check_failure_reason:
503
- action: license_generation_rejected?
504
- paths: [fetch_license_failure_error_msg, fetch_license_failure_rejection_msg]
505
- response_path_map:
506
- "true": fetch_license_failure_rejection_msg
507
- "false": fetch_license_failure_error_msg
508
-
509
- fetch_license_failure_error_msg:
510
- action: fetch_license_failure_error_msg
511
- paths: [license_generation_with_errors]
512
-
513
- fetch_license_failure_rejection_msg:
514
- action: fetch_license_failure_rejection_msg
515
- paths: [license_generation_rejected]
516
-
517
- license_generation_rejected:
518
- messages: ["Your request for a license was denied for the following reason: <%= input[:fetch_license_failure_rejection_msg] %>. Please select one of the following options:", ["Try again", "Skip"]]
519
- prompt_type: "select"
520
- paths: [pre_license_generation, skip_message]
521
- response_path_map:
522
- "Try again": pre_license_generation
523
- "Skip": skip_message
524
-
525
- license_generation_with_errors:
526
- messages: ["\nAn error occurred while generating your license.\nError message: <%= input[:fetch_license_failure_error_msg] %>\n", ["Try again", "Skip"]]
527
- prompt_type: "select"
528
- paths: [pre_license_generation, skip_message]
529
- response_path_map:
530
- "Try again": pre_license_generation
531
- "Skip": skip_message
532
-
533
337
  exit:
534
338
  messages: ""
535
339
 
@@ -5,6 +5,10 @@ require "date"
5
5
  require "fileutils" unless defined?(FileUtils)
6
6
  require_relative "../license_key_fetcher"
7
7
  require_relative "../config"
8
+ require_relative "../exceptions/license_file_corrupted"
9
+ require_relative "license_file/v4"
10
+ require_relative "license_file/v3"
11
+ require_relative "../exceptions/invalid_file_format_version"
8
12
 
9
13
  module ChefLicensing
10
14
  class LicenseKeyFetcher
@@ -118,15 +122,15 @@ module ChefLicensing
118
122
 
119
123
  @contents = load_license_file(license_key_file_path)
120
124
 
125
+ # Two possible cases:
126
+ # 1. If contents is nil, load basic license data with the latest structure.
127
+ # 2. If contents is not nil, but the license server URL in contents is different from the system's,
128
+ # update the license server URL in contents and licenses.yaml file.
121
129
  if @contents.nil?
122
- @contents = {
123
- file_format_version: LICENSE_FILE_FORMAT_VERSION,
124
- license_server_url: license_server_url_from_system || license_server_url_from_config,
125
- }
126
- else
127
- if license_server_url_from_system && license_server_url_from_system != @contents[:license_server_url]
128
- @contents[:license_server_url] = license_server_url_from_system
129
- end
130
+ url = license_server_url_from_system || license_server_url_from_config
131
+ load_basic_license_data_to_contents(url, [])
132
+ elsif @contents && license_server_url_from_system && license_server_url_from_system != @contents[:license_server_url]
133
+ @contents[:license_server_url] = license_server_url_from_system
130
134
  end
131
135
 
132
136
  # Ensure the license server URL is returned to the caller in all cases
@@ -207,11 +211,27 @@ module ChefLicensing
207
211
 
208
212
  # only checking for major version for file format for breaking changes
209
213
  @contents ||= YAML.load(::File.read(path))
214
+
215
+ # raise error if the file_format_version key is missing
216
+ raise LicenseFileCorrupted.new("Unrecognized license file; :file_format_version missing.") unless @contents.key?(:file_format_version)
217
+
218
+ # Three possible cases after loading the license file contents:
219
+ # 1. If the file format version is the same as the current version (latest), verify the structure and return the contents.
220
+ # 2. If the file format version is different but supported, migrate the contents to the current version and return them.
221
+ # 3. If the file format version is different and not supported, raise an error.
210
222
  if major_version(@contents[:file_format_version]) == major_version(LICENSE_FILE_FORMAT_VERSION)
223
+ current_version_class_name = get_license_file_class(LICENSE_FILE_FORMAT_VERSION)
224
+ # we ignore any additional keys in the license file during verification
225
+ raise LicenseFileCorrupted.new("Invalid data found in the license file.") unless current_version_class_name.send(:verify_structure, @contents)
226
+
227
+ @contents
228
+ elsif license_file_class_exists?(@contents[:file_format_version])
229
+ @contents = migrate_license_file_content_to_current_version(@contents)
230
+ write_license_file(path) # update the license file contents to the latest version
211
231
  @contents
212
232
  else
213
233
  logger.debug "License File version #{@contents[:file_format_version]} not supported."
214
- raise LicenseKeyNotFetchedError.new("License File version #{@contents[:file_format_version]} not supported.")
234
+ raise ChefLicensing::InvalidFileFormatVersion.new("Unable to read licenses. License File version #{@contents[:file_format_version]} not supported.")
215
235
  end
216
236
  end
217
237
 
@@ -244,11 +264,7 @@ module ChefLicensing
244
264
 
245
265
  logger.debug "Loading license data to contents"
246
266
  if @contents.nil? || @contents.empty? # this case is likely to happen only during testing
247
- @contents = {
248
- file_format_version: LICENSE_FILE_FORMAT_VERSION,
249
- license_server_url: @license_server_url,
250
- licenses: [license_data],
251
- }
267
+ load_basic_license_data_to_contents(@license_server_url, [license_data])
252
268
  elsif @contents[:licenses].nil?
253
269
  @contents[:licenses] = [license_data]
254
270
  elsif fetch_license_keys(@contents[:licenses])&.include?(license_data[:license_key])
@@ -270,6 +286,38 @@ module ChefLicensing
270
286
  logger.debug "#{e.backtrace.join("\n\t")}"
271
287
  e
272
288
  end
289
+
290
+ # Returns the license file class for the given version.
291
+ def get_license_file_class(version)
292
+ Object.const_get("ChefLicensing::LicenseFile::V#{major_version(version)}")
293
+ end
294
+
295
+ # Returns true if the license file class for the given version exists.
296
+ def license_file_class_exists?(version)
297
+ Object.const_defined?("ChefLicensing::LicenseFile::V#{major_version(version)}")
298
+ end
299
+
300
+ # Loads the basic license data to contents in the current version's structure.
301
+ def load_basic_license_data_to_contents(url, license_data = [])
302
+ current_version_class_name = get_license_file_class(LICENSE_FILE_FORMAT_VERSION)
303
+ @contents = current_version_class_name.send(:load_primary_structure)
304
+ @contents[:file_format_version] = LICENSE_FILE_FORMAT_VERSION
305
+ @contents[:license_server_url] = url || ""
306
+ @contents[:licenses] = license_data
307
+ end
308
+
309
+ # Migrates the license file content to the current version and returns the migrated contents.
310
+ def migrate_license_file_content_to_current_version(contents)
311
+ logger.warn "License File version #{contents[:file_format_version]} is deprecated."
312
+ logger.warn "Automatically migrating license file to version #{LICENSE_FILE_FORMAT_VERSION}."
313
+ given_version_class_name = get_license_file_class(contents[:file_format_version])
314
+ # we ignore any additional keys in the license file during verification
315
+ raise LicenseFileCorrupted.new("Invalid data found in the license file.") unless given_version_class_name.send(:verify_structure, contents)
316
+
317
+ current_version_class_name = get_license_file_class(LICENSE_FILE_FORMAT_VERSION)
318
+ contents = current_version_class_name.send(:migrate_structure, contents, major_version(contents[:file_format_version]))
319
+ contents
320
+ end
273
321
  end
274
322
  end
275
323
  end
@@ -0,0 +1,63 @@
1
+ module ChefLicensing
2
+ module LicenseFile
3
+ class Base
4
+ EXPECTED_STRUCTURE = {
5
+ file_format_version: "0.0.0",
6
+ licenses: [
7
+ {
8
+ license_key: String,
9
+ license_type: Symbol,
10
+ update_time: String,
11
+ },
12
+ ],
13
+ }.freeze
14
+
15
+ # @param [Hash] data: The data to verify
16
+ # @param [Hash] expected_structure: The structure to verify against
17
+ # @return [Boolean] true if the data matches the expected structure, false otherwise
18
+ # @note This method ignores extra keys in the data that are not in the expected structure
19
+ def self.verify_structure(data, expected_structure = self::EXPECTED_STRUCTURE)
20
+ return false unless data.is_a?(Hash)
21
+
22
+ expected_structure.each do |key, value|
23
+ return false unless data.key?(key)
24
+
25
+ if value.is_a?(Hash)
26
+ return false unless verify_structure(data[key], value)
27
+ elsif value.is_a?(Array)
28
+ return false unless data[key].is_a?(Array)
29
+
30
+ data[key].each do |item|
31
+ return false unless verify_structure(item, value[0])
32
+ end
33
+ elsif value.is_a?(Class)
34
+ return false unless data[key].is_a?(value)
35
+ else
36
+ return false unless data[key] == value
37
+ end
38
+ end
39
+
40
+ true
41
+ end
42
+
43
+ # @return [Hash] The primary structure of the license file, without nested structures
44
+ def self.load_primary_structure
45
+ expected_structure_dup = self::EXPECTED_STRUCTURE.dup
46
+ expected_structure_dup[:licenses] = []
47
+ expected_structure_dup
48
+ end
49
+
50
+ # @return [Hash] The complete structure of the license file, including nested structures
51
+ def self.load_structure
52
+ self::EXPECTED_STRUCTURE
53
+ end
54
+
55
+ # @param [Hash] contents: The contents of the license file
56
+ # @param [Integer] version: The version of the license file
57
+ # @return [Hash] The contents of the license file after migration
58
+ def self.migrate_structure(contents, version)
59
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "base"
2
+
3
+ module ChefLicensing
4
+ module LicenseFile
5
+ class V3 < Base
6
+ LICENSE_FILE_FORMAT_VERSION = "3.0.0".freeze
7
+ EXPECTED_STRUCTURE = EXPECTED_STRUCTURE.merge({
8
+ file_format_version: V3::LICENSE_FILE_FORMAT_VERSION,
9
+ }).freeze
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,27 @@
1
+ require_relative "base"
2
+ require_relative "../../config"
3
+
4
+ module ChefLicensing
5
+ module LicenseFile
6
+ class V4 < Base
7
+ LICENSE_FILE_FORMAT_VERSION = "4.0.0".freeze
8
+
9
+ EXPECTED_STRUCTURE = EXPECTED_STRUCTURE.merge({
10
+ file_format_version: V4::LICENSE_FILE_FORMAT_VERSION,
11
+ license_server_url: String,
12
+ }).freeze
13
+
14
+ # @param [Hash] contents: The contents of the license file
15
+ # @param [Integer] version: The version of the license file
16
+ # @return [Hash] The contents of the license file after migration
17
+ def self.migrate_structure(contents, version)
18
+ # Backwards compatibility for version 3 license files
19
+ if version == 3
20
+ contents[:license_server_url] = ChefLicensing::Config.license_server_url || ""
21
+ contents[:file_format_version] = V4::LICENSE_FILE_FORMAT_VERSION
22
+ end
23
+ contents
24
+ end
25
+ end
26
+ end
27
+ end
@@ -71,7 +71,9 @@ module ChefLicensing
71
71
 
72
72
  unless @license_keys.empty?
73
73
  # Licenses expiration check
74
- if licenses_active?
74
+ # Client API possible errors will be handled in software entitlement check call (made after this)
75
+ # client_api_call_error is set to true when there is an error in licenses_active? call
76
+ if licenses_active? || client_api_call_error
75
77
  return @license_keys
76
78
  else
77
79
  # Prompts if the keys are expired or expiring
@@ -116,6 +118,7 @@ module ChefLicensing
116
118
  # Return keys if license keys are active and not expired or expiring
117
119
  # Return keys if there is any error in /client API call, and do not block the flow.
118
120
  # Client API possible errors will be handled in software entitlement check call (made after this)
121
+ # client_api_call_error is set to true when there is an error in licenses_active? call
119
122
  return @license_keys if (!@license_keys.empty? && licenses_active?) || client_api_call_error
120
123
 
121
124
  # Lowest priority is to interactively prompt if we have a TTY
@@ -283,7 +286,7 @@ module ChefLicensing
283
286
  def prompt_license_addition_restricted(license_type, existing_license_keys_in_file)
284
287
  logger.debug "License Key fetcher - prompting license addition restriction"
285
288
  # For trial license
286
- # TODO for free license
289
+ # TODO for Free Tier License
287
290
  config[:start_interaction] = :prompt_license_addition_restriction
288
291
  prompt_fetcher.config = config
289
292
  # Existing license keys are needed to show details of existing license of license type which is restricted.
@@ -294,7 +297,7 @@ module ChefLicensing
294
297
  def unrestricted_license_added?(new_keys, license_type)
295
298
  if license_restricted?(license_type)
296
299
  # Existing license keys of same license type are fetched to compare if old license key or a new one is added.
297
- # However, if user is trying to add free license, and user has active trial license, we fetch the trial license key
300
+ # However, if user is trying to add Free Tier License, and user has active trial license, we fetch the trial license key
298
301
  if license_type == :free && file_fetcher.user_has_active_trial_license?
299
302
  existing_license_keys_in_file = file_fetcher.fetch_license_keys_based_on_type(:trial)
300
303
  else
@@ -313,4 +316,4 @@ module ChefLicensing
313
316
  end
314
317
  end
315
318
  end
316
- end
319
+ end
@@ -28,8 +28,11 @@ module ChefLicensing
28
28
 
29
29
  licenses_metadata.each do |license|
30
30
  puts_bold "License Key : #{license.id}"
31
+ # Note: The license type is returned as "free" for Free Tier Licenses from the server.
32
+ # This is capitalized to "Free Tier" for display purposes as recommended by the product team.
33
+ license_type = license.license_type == "free" ? "Free Tier" : license.license_type.capitalize
31
34
  output.puts <<~LICENSE
32
- Type : #{license.license_type}
35
+ Type : #{license_type}
33
36
  Status : #{license.status}
34
37
  Expiration Date : #{license.expiration_date}
35
38
 
@@ -57,7 +60,10 @@ module ChefLicensing
57
60
  def display_overview
58
61
  output.puts "------------------------------------------------------------"
59
62
  licenses_metadata.each do |license|
60
- # Sets the validity text for a free license as "Unlimited" and displays the number of days for others.
63
+ # Note: The license type is returned as "free" for Free Tier Licenses from the server.
64
+ # This is capitalized to "Free Tier" for display purposes as recommended by the product team.
65
+ license_type = license.license_type == "free" ? "Free Tier" : license.license_type.capitalize
66
+ # Sets the validity text for a Free Tier License as "Unlimited" and displays the number of days for others.
61
67
  validity = if license.license_type == "free"
62
68
  "Unlimited"
63
69
  else
@@ -72,7 +78,7 @@ module ChefLicensing
72
78
  #{pastel.bold("License Details")}
73
79
  Asset Name : #{license.limits.first.software}
74
80
  License ID : #{license.id}
75
- Type : #{license.license_type.capitalize}
81
+ Type : #{license_type}
76
82
  Status : #{license.status.capitalize}
77
83
  Validity : #{validity}
78
84
  No. Of Units : #{num_of_units} #{unit_measure.capitalize.pluralize(num_of_units)}
@@ -22,6 +22,7 @@ module ChefLicensing
22
22
  }.freeze
23
23
 
24
24
  CURRENT_ENDPOINT_VERSION = 2
25
+ REQUEST_LIMIT = 5
25
26
 
26
27
  def initialize
27
28
  raise MissingAPICredentialsError, "Missing credential in config: Set in block chef_license_server or use environment variable CHEF_LICENSE_SERVER or pass through argument --chef-license-server" if ChefLicensing::Config.license_server_url.nil?
@@ -33,14 +34,6 @@ module ChefLicensing
33
34
  invoke_get_api(self.class::END_POINTS[:VALIDATE], { licenseId: license, version: CURRENT_ENDPOINT_VERSION })
34
35
  end
35
36
 
36
- def generate_trial_license(payload)
37
- invoke_post_api(self.class::END_POINTS[:GENERATE_TRIAL_LICENSE], payload)
38
- end
39
-
40
- def generate_free_license(payload)
41
- invoke_post_api(self.class::END_POINTS[:GENERATE_FREE_LICENSE], payload)
42
- end
43
-
44
37
  def feature_by_name(payload)
45
38
  invoke_post_api(self.class::END_POINTS[:FEATURE_BY_NAME], payload)
46
39
  end
@@ -75,43 +68,71 @@ module ChefLicensing
75
68
 
76
69
  # a common method to handle the get API calls
77
70
  def invoke_get_api(endpoint, params = {})
78
- handle_get_connection do |connection|
79
- connection.get(endpoint, params).body
80
- end
71
+ response = invoke_api(ChefLicensing::Config.license_server_url.split(","), endpoint, :get, nil, params)
72
+ response.body
81
73
  end
82
74
 
83
75
  # a common method to handle the post API calls
84
76
  def invoke_post_api(endpoint, payload, headers = {})
85
- handle_post_connection do |connection|
86
- response = connection.post(endpoint) do |request|
87
- request.body = payload.to_json
88
- request.headers = headers
77
+ response = invoke_api(ChefLicensing::Config.license_server_url.split(","), endpoint, :post, payload, nil, headers)
78
+ raise RestfulClientError, format_error_from(response) unless response.success?
79
+
80
+ response.body
81
+ end
82
+
83
+ def invoke_api(urls, endpoint, http_method, payload = nil, params = {}, headers = {})
84
+ handle_connection = http_method == :get ? method(:handle_get_connection) : method(:handle_post_connection)
85
+ response = nil
86
+ attempted_urls = []
87
+
88
+ logger.warn "Only the first #{REQUEST_LIMIT} urls will be tried." if urls.size > REQUEST_LIMIT
89
+ urls.each_with_index do |url, i|
90
+ url = url.strip
91
+ attempted_urls << url
92
+ break if i == REQUEST_LIMIT - 1
93
+
94
+ logger.debug "Trying to connect to #{url}"
95
+ handle_connection.call(url) do |connection|
96
+ response = connection.send(http_method, endpoint) do |request|
97
+ request.body = payload.to_json if payload
98
+ request.params = params if params
99
+ request.headers = headers if headers
100
+ end
89
101
  end
90
- raise RestfulClientError, format_error_from(response) unless response.success?
91
-
92
- response.body
102
+ # At this point, we have a successful connection
103
+ # Update the value of license server url in config
104
+ ChefLicensing::Config.license_server_url = url
105
+ logger.debug "Connection succeeded to #{url}"
106
+ break response
107
+ rescue RestfulClientConnectionError
108
+ logger.warn "Connection failed to #{url}"
109
+ rescue URI::InvalidURIError
110
+ logger.warn "Invalid URI #{url}"
93
111
  end
112
+
113
+ raise_restful_client_conn_error(attempted_urls) if response.nil?
114
+ response
94
115
  end
95
116
 
96
- def handle_get_connection
117
+ def handle_get_connection(url = nil)
97
118
  # handle faraday errors
98
- yield get_connection
119
+ yield get_connection(url)
99
120
  rescue Faraday::ClientError => e
100
121
  logger.debug "Restful Client Error #{e.message}"
101
122
  raise RestfulClientError, e.message
102
123
  end
103
124
 
104
- def handle_post_connection
125
+ def handle_post_connection(url = nil)
105
126
  # handle faraday errors
106
- yield post_connection
127
+ yield post_connection(url)
107
128
  rescue Faraday::ClientError => e
108
129
  logger.debug "Restful Client Error #{e.message}"
109
130
  raise RestfulClientError, e.message
110
131
  end
111
132
 
112
- def get_connection
133
+ def get_connection(url = nil)
113
134
  store = ::ActiveSupport::Cache.lookup_store(:file_store, Dir.tmpdir)
114
- Faraday.new(url: ChefLicensing::Config.license_server_url) do |config|
135
+ Faraday.new(url: url) do |config|
115
136
  config.request :json
116
137
  config.response :json, parser_options: { object_class: OpenStruct }
117
138
  config.use Faraday::HttpCache, shared_cache: false, logger: logger, store: store
@@ -120,8 +141,8 @@ module ChefLicensing
120
141
  end
121
142
  end
122
143
 
123
- def post_connection
124
- Faraday.new(url: ChefLicensing::Config.license_server_url) do |config|
144
+ def post_connection(url = nil)
145
+ Faraday.new(url: url) do |config|
125
146
  config.request :json
126
147
  config.response :json, parser_options: { object_class: OpenStruct }
127
148
  config.use Middleware::ExceptionsHandler
@@ -134,6 +155,19 @@ module ChefLicensing
134
155
 
135
156
  error_details
136
157
  end
158
+
159
+ def raise_restful_client_conn_error(urls)
160
+ error_message = <<~EOM
161
+ Unable to connect to the licensing server. #{ChefLicensing::Config.chef_product_name} requires server communication to operate.
162
+ The following URL(s) were tried:\n#{
163
+ urls.each_with_index.map do |url, index|
164
+ "#{index + 1}. #{url}"
165
+ end.join("\n")
166
+ }
167
+ EOM
168
+
169
+ raise RestfulClientConnectionError, error_message
170
+ end
137
171
  end
138
172
  end
139
173
  end
@@ -8,9 +8,7 @@ module Middleware
8
8
  def call(env)
9
9
  @app.call(env)
10
10
  rescue Faraday::ConnectionFailed => e
11
- ChefLicensing::Config.logger.debug("Connection failed to #{ChefLicensing::Config.license_server_url} with error: #{e.message}")
12
- error_message = "Unable to connect to the licensing server at #{ChefLicensing::Config.license_server_url}.\nPlease check if the server is reachable and try again. #{ChefLicensing::Config.chef_product_name} requires server communication to operate."
13
- raise ChefLicensing::RestfulClientConnectionError, error_message
11
+ raise ChefLicensing::RestfulClientConnectionError, e.message
14
12
  end
15
13
  end
16
14
  end
@@ -6,8 +6,6 @@ module ChefLicensing
6
6
  class V1 < Base
7
7
  END_POINTS = END_POINTS.merge({
8
8
  VALIDATE: "v1/validate",
9
- GENERATE_TRIAL_LICENSE: "v1/trial",
10
- GENERATE_FREE_LICENSE: "v1/free",
11
9
  CLIENT: "v1/client",
12
10
  DESCRIBE: "v1/desc",
13
11
  LIST_LICENSES: "v1/listLicenses",
@@ -1,8 +1,5 @@
1
1
  require_relative "../license_key_validator"
2
- require_relative "../license_key_generator"
3
2
  require_relative "../exceptions/invalid_license"
4
- require_relative "../exceptions/license_generation_failed"
5
- require_relative "../exceptions/license_generation_rejected"
6
3
  require_relative "../license_key_fetcher/base"
7
4
  require_relative "../config"
8
5
  require_relative "../context"
@@ -48,7 +45,7 @@ module ChefLicensing
48
45
  self.license_type = get_license_type
49
46
  if license_restricted?(license_type)
50
47
  # Existing license keys needs to be fetcher to show details of existing license of license type which is restricted.
51
- # However, if user is trying to add free license, and user has active trial license, we fetch the trial license key
48
+ # However, if user is trying to add Free Tier License, and user has active trial license, we fetch the trial license key
52
49
  if license_type == :free && LicenseKeyFetcher::File.user_has_active_trial_license?(@opts)
53
50
  existing_license_keys_in_file = LicenseKeyFetcher::File.fetch_license_keys_based_on_type(:trial, @opts)
54
51
  else
@@ -74,62 +71,10 @@ module ChefLicensing
74
71
  end
75
72
  end
76
73
 
77
- def is_user_name_valid?(input)
78
- user_name = input[:gather_user_last_name_for_license_generation] || input[:gather_user_first_name_for_license_generation]
79
- (user_name =~ /\A[a-zA-Z]{1,16}\Z/) == 0
80
- end
81
-
82
- def is_email_valid?(input)
83
- (input[:gather_user_email_for_license_generation] =~ URI::MailTo::EMAIL_REGEXP) == 0
84
- end
85
-
86
- def is_company_name_valid?(input)
87
- (input[:gather_user_company_for_license_generation] =~ /\A[a-zA-Z0-9][a-zA-Z0-9\W_]{2,15}\z/) == 0
88
- end
89
-
90
- def is_phone_no_valid?(input)
91
- # No validation
92
- # Optional field
93
- true
94
- end
95
-
96
- def generate_trial_license(input)
97
- generate_license(input, :trial)
98
- end
99
-
100
- def generate_free_license(input)
101
- generate_license(input, :free)
102
- end
103
-
104
74
  def fetch_license_id(input)
105
75
  license_id
106
76
  end
107
77
 
108
- def fetch_license_failure_error_msg(input)
109
- error_msg
110
- end
111
-
112
- def fetch_license_failure_rejection_msg(input)
113
- rejection_msg
114
- end
115
-
116
- def select_license_generation_based_on_type(inputs)
117
- if inputs.key? :free_license_selection
118
- inputs[:license_type] = :free
119
- "free"
120
- elsif inputs.key? :trial_license_selection
121
- inputs[:license_type] = :trial
122
- "trial"
123
- else
124
- inputs[:license_type] = :commercial
125
- "commercial"
126
- end
127
- end
128
-
129
- def license_generation_rejected?(inputs)
130
- !!rejection_msg
131
- end
132
-
133
78
  def fetch_invalid_license_msg(input)
134
79
  invalid_license_msg
135
80
  end
@@ -138,20 +83,6 @@ module ChefLicensing
138
83
  ChefLicensing::ListLicenseKeys.display_overview({ license_keys: [license_id] })
139
84
  end
140
85
 
141
- def clear_license_type_selection(inputs)
142
- inputs.delete(:free_license_selection)
143
- inputs.delete(:trial_license_selection)
144
- inputs.delete(:commercial_license_selection)
145
- end
146
-
147
- def are_user_details_present?(inputs)
148
- inputs.key?(:gather_user_first_name_for_license_generation) &&
149
- inputs.key?(:gather_user_last_name_for_license_generation) &&
150
- inputs.key?(:gather_user_email_for_license_generation) &&
151
- inputs.key?(:gather_user_company_for_license_generation) &&
152
- inputs.key?(:gather_user_phone_no_for_license_generation)
153
- end
154
-
155
86
  def set_license_info(input)
156
87
  self.license_id = input[:license_id]
157
88
  self.license_type = input[:license_type]
@@ -191,28 +122,6 @@ module ChefLicensing
191
122
 
192
123
  attr_accessor :opts
193
124
 
194
- def generate_license(inputs, license_type)
195
- spinner = TTY::Spinner.new(":spinner [Running] License generation in progress...", format: :dots, clear: true, output: output)
196
- spinner.auto_spin # Start the spinner
197
- self.license_id = ChefLicensing::LicenseKeyGenerator.send("generate_#{license_type}_license!",
198
- first_name: inputs[:gather_user_first_name_for_license_generation],
199
- last_name: inputs[:gather_user_last_name_for_license_generation],
200
- email_id: inputs[:gather_user_email_for_license_generation],
201
- product: ChefLicensing::Config.chef_product_name&.capitalize,
202
- company: inputs[:gather_user_company_for_license_generation],
203
- phone: inputs[:gather_user_phone_no_for_license_generation])
204
- spinner.success # Stop the spinner
205
- true
206
- rescue ChefLicensing::LicenseGenerationFailed => e
207
- spinner.error # Stop the spinner
208
- self.error_msg = e.message
209
- false
210
- rescue ChefLicensing::LicenseGenerationRejected => e
211
- spinner.error # Stop the spinner
212
- self.rejection_msg = e.message
213
- false
214
- end
215
-
216
125
  def get_license(license_key)
217
126
  spinner = TTY::Spinner.new(":spinner [Running] License validation in progress...", format: :dots, clear: true, output: output)
218
127
  spinner.auto_spin # Start the spinner
@@ -1,3 +1,3 @@
1
1
  module ChefLicensing
2
- VERSION = "0.4.44".freeze
2
+ VERSION = "0.7.5".freeze
3
3
  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.4.44
4
+ version: 0.7.5
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-07-11 00:00:00.000000000 Z
11
+ date: 2023-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef-config
@@ -79,9 +79,9 @@ dependencies:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '7.0'
82
- - - ">="
82
+ - - "<"
83
83
  - !ruby/object:Gem::Version
84
- version: 7.0.4.2
84
+ version: '7.1'
85
85
  type: :runtime
86
86
  prerelease: false
87
87
  version_requirements: !ruby/object:Gem::Requirement
@@ -89,9 +89,9 @@ dependencies:
89
89
  - - "~>"
90
90
  - !ruby/object:Gem::Version
91
91
  version: '7.0'
92
- - - ">="
92
+ - - "<"
93
93
  - !ruby/object:Gem::Version
94
- version: 7.0.4.2
94
+ version: '7.1'
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: tty-spinner
97
97
  requirement: !ruby/object:Gem::Requirement
@@ -114,7 +114,6 @@ executables: []
114
114
  extensions: []
115
115
  extra_rdoc_files: []
116
116
  files:
117
- - LICENSE
118
117
  - chef-licensing.gemspec
119
118
  - lib/chef-licensing.rb
120
119
  - lib/chef-licensing/api/client.rb
@@ -134,9 +133,9 @@ files:
134
133
  - lib/chef-licensing/exceptions/describe_error.rb
135
134
  - lib/chef-licensing/exceptions/error.rb
136
135
  - lib/chef-licensing/exceptions/feature_not_entitled.rb
136
+ - lib/chef-licensing/exceptions/invalid_file_format_version.rb
137
137
  - lib/chef-licensing/exceptions/invalid_license.rb
138
- - lib/chef-licensing/exceptions/license_generation_failed.rb
139
- - lib/chef-licensing/exceptions/license_generation_rejected.rb
138
+ - lib/chef-licensing/exceptions/license_file_corrupted.rb
140
139
  - lib/chef-licensing/exceptions/list_licenses_error.rb
141
140
  - lib/chef-licensing/exceptions/missing_api_credentials_error.rb
142
141
  - lib/chef-licensing/exceptions/restful_client_connection_error.rb
@@ -147,8 +146,10 @@ files:
147
146
  - lib/chef-licensing/license_key_fetcher/base.rb
148
147
  - lib/chef-licensing/license_key_fetcher/chef_licensing_interactions.yaml
149
148
  - lib/chef-licensing/license_key_fetcher/file.rb
149
+ - lib/chef-licensing/license_key_fetcher/license_file/base.rb
150
+ - lib/chef-licensing/license_key_fetcher/license_file/v3.rb
151
+ - lib/chef-licensing/license_key_fetcher/license_file/v4.rb
150
152
  - lib/chef-licensing/license_key_fetcher/prompt.rb
151
- - lib/chef-licensing/license_key_generator.rb
152
153
  - lib/chef-licensing/license_key_validator.rb
153
154
  - lib/chef-licensing/licensing_service/local.rb
154
155
  - lib/chef-licensing/list_license_keys.rb
@@ -165,7 +166,7 @@ files:
165
166
  - lib/chef-licensing/version.rb
166
167
  homepage: https://github.com/chef/chef-licensing
167
168
  licenses:
168
- - LicenseRef-LICENSE
169
+ - Apache-2.0
169
170
  metadata:
170
171
  homepage_uri: https://github.com/chef/chef-licensing
171
172
  source_code_uri: https://github.com/chef/chef-licensing
data/LICENSE DELETED
@@ -1 +0,0 @@
1
- Proprietary code. All rights reserved.
@@ -1,9 +0,0 @@
1
- require_relative "error"
2
-
3
- module ChefLicensing
4
- class LicenseGenerationFailed < Error
5
- def message
6
- super || "License Generation Failed"
7
- end
8
- end
9
- end
@@ -1,7 +0,0 @@
1
- module ChefLicensing
2
- class LicenseGenerationRejected < Error
3
- def message
4
- super || "License Generation Rejected"
5
- end
6
- end
7
- end
@@ -1,47 +0,0 @@
1
- require_relative "restful_client/v1"
2
- require_relative "exceptions/license_generation_failed"
3
-
4
- module ChefLicensing
5
- class LicenseKeyGenerator
6
- attr_reader :payload
7
-
8
- class << self
9
- # @param [Hash] KWARGS keys accepted are [first_name, last_name, email_id, product, company, phone]
10
- def generate_trial_license!(kwargs)
11
- new(kwargs).generate_trial_license!
12
- end
13
-
14
- def generate_free_license!(kwargs)
15
- new(kwargs).generate_free_license!
16
- end
17
- end
18
-
19
- def initialize(kwargs, restful_client: ChefLicensing::RestfulClient::V1)
20
- # TODO: validate kwargs
21
- @payload = build_payload_from(kwargs)
22
- @restful_client = restful_client.new
23
- end
24
-
25
- def generate_trial_license!
26
- response = @restful_client.generate_trial_license(payload)
27
- # need some logic around delivery
28
- # how the delivery is decided?
29
- response.licenseId
30
- rescue RestfulClientError => e
31
- raise ChefLicensing::LicenseGenerationFailed, e.message
32
- end
33
-
34
- def generate_free_license!
35
- response = @restful_client.generate_free_license(payload)
36
- response.licenseId
37
- rescue RestfulClientError => e
38
- raise ChefLicensing::LicenseGenerationFailed, e.message
39
- end
40
-
41
- private
42
-
43
- def build_payload_from(kwargs)
44
- kwargs.slice(:first_name, :last_name, :email_id, :product, :company, :phone)
45
- end
46
- end
47
- end