chef-licensing 0.4.43

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.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -0
  3. data/chef-licensing.gemspec +35 -0
  4. data/lib/chef-licensing/api/client.rb +39 -0
  5. data/lib/chef-licensing/api/describe.rb +62 -0
  6. data/lib/chef-licensing/api/license_feature_entitlement.rb +55 -0
  7. data/lib/chef-licensing/api/license_software_entitlement.rb +53 -0
  8. data/lib/chef-licensing/api/list_licenses.rb +30 -0
  9. data/lib/chef-licensing/api/parser/client.rb +100 -0
  10. data/lib/chef-licensing/api/parser/describe.rb +118 -0
  11. data/lib/chef-licensing/cli_flags/mixlib_cli.rb +28 -0
  12. data/lib/chef-licensing/cli_flags/thor.rb +21 -0
  13. data/lib/chef-licensing/config.rb +44 -0
  14. data/lib/chef-licensing/config_fetcher/arg_fetcher.rb +38 -0
  15. data/lib/chef-licensing/config_fetcher/env_fetcher.rb +21 -0
  16. data/lib/chef-licensing/context.rb +98 -0
  17. data/lib/chef-licensing/exceptions/client_error.rb +9 -0
  18. data/lib/chef-licensing/exceptions/describe_error.rb +9 -0
  19. data/lib/chef-licensing/exceptions/error.rb +4 -0
  20. data/lib/chef-licensing/exceptions/feature_not_entitled.rb +9 -0
  21. data/lib/chef-licensing/exceptions/invalid_license.rb +10 -0
  22. data/lib/chef-licensing/exceptions/license_generation_failed.rb +9 -0
  23. data/lib/chef-licensing/exceptions/license_generation_rejected.rb +7 -0
  24. data/lib/chef-licensing/exceptions/list_licenses_error.rb +12 -0
  25. data/lib/chef-licensing/exceptions/missing_api_credentials_error.rb +7 -0
  26. data/lib/chef-licensing/exceptions/restful_client_connection_error.rb +9 -0
  27. data/lib/chef-licensing/exceptions/restful_client_error.rb +9 -0
  28. data/lib/chef-licensing/exceptions/software_not_entitled.rb +9 -0
  29. data/lib/chef-licensing/license.rb +151 -0
  30. data/lib/chef-licensing/license_key_fetcher/base.rb +28 -0
  31. data/lib/chef-licensing/license_key_fetcher/chef_licensing_interactions.yaml +534 -0
  32. data/lib/chef-licensing/license_key_fetcher/file.rb +275 -0
  33. data/lib/chef-licensing/license_key_fetcher/prompt.rb +43 -0
  34. data/lib/chef-licensing/license_key_fetcher.rb +314 -0
  35. data/lib/chef-licensing/license_key_generator.rb +47 -0
  36. data/lib/chef-licensing/license_key_validator.rb +24 -0
  37. data/lib/chef-licensing/licensing_service/local.rb +29 -0
  38. data/lib/chef-licensing/list_license_keys.rb +142 -0
  39. data/lib/chef-licensing/restful_client/base.rb +139 -0
  40. data/lib/chef-licensing/restful_client/middleware/exceptions_handler.rb +16 -0
  41. data/lib/chef-licensing/restful_client/v1.rb +17 -0
  42. data/lib/chef-licensing/tui_engine/tui_actions.rb +238 -0
  43. data/lib/chef-licensing/tui_engine/tui_engine.rb +174 -0
  44. data/lib/chef-licensing/tui_engine/tui_engine_state.rb +62 -0
  45. data/lib/chef-licensing/tui_engine/tui_exceptions.rb +17 -0
  46. data/lib/chef-licensing/tui_engine/tui_interaction.rb +17 -0
  47. data/lib/chef-licensing/tui_engine/tui_prompt.rb +117 -0
  48. data/lib/chef-licensing/tui_engine.rb +2 -0
  49. data/lib/chef-licensing/version.rb +3 -0
  50. data/lib/chef-licensing.rb +70 -0
  51. metadata +191 -0
@@ -0,0 +1,24 @@
1
+ require_relative "restful_client/v1"
2
+ require_relative "exceptions/invalid_license"
3
+
4
+ module ChefLicensing
5
+ class LicenseKeyValidator
6
+ attr_reader :license
7
+
8
+ class << self
9
+ def validate!(license)
10
+ new(license).validate!
11
+ end
12
+ end
13
+
14
+ def initialize(license, restful_client: ChefLicensing::RestfulClient::V1)
15
+ @license = license || raise(ArgumentError, "Missing Params: `license`")
16
+ @restful_client = restful_client.new
17
+ end
18
+
19
+ def validate!
20
+ response = @restful_client.validate(license)
21
+ response.data || raise(ChefLicensing::InvalidLicense, response.message)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "../config"
2
+ require_relative "../api/list_licenses"
3
+ require_relative "../exceptions/list_licenses_error"
4
+
5
+ module ChefLicensing
6
+ class LicensingService
7
+ class Local
8
+ attr_reader :logger
9
+
10
+ class << self
11
+ def detected?
12
+ new.detected?
13
+ end
14
+ end
15
+
16
+ def detected?
17
+ return ChefLicensing::Config.is_local_license_service if ChefLicensing::Config.is_local_license_service
18
+
19
+ ChefLicensing::Api::ListLicenses.info
20
+ true
21
+ rescue ChefLicensing::ListLicensesError => e
22
+ # If API call returns 404, it is a global licensing service
23
+ return false if e.status_code == 404
24
+
25
+ raise(ChefLicensing::ListLicensesError.new("Error occured while fetching licenses #{e.message}", e.status_code))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,142 @@
1
+ require_relative "license_key_fetcher"
2
+ require_relative "api/describe"
3
+ require_relative "exceptions/describe_error"
4
+ require "pastel" unless defined?(Pastel)
5
+ require_relative "config"
6
+
7
+ module ChefLicensing
8
+ class ListLicenseKeys
9
+ def self.display(opts = {})
10
+ new(opts).display
11
+ end
12
+
13
+ def self.display_overview(opts = {})
14
+ new(opts).display_overview
15
+ end
16
+
17
+ def initialize(opts = {})
18
+ @logger = ChefLicensing::Config.logger
19
+ @output = ChefLicensing::Config.output
20
+ @pastel = Pastel.new
21
+ @license_keys = fetch_license_keys(opts)
22
+ @licenses_metadata = fetch_licenses_metadata
23
+ end
24
+
25
+ def display
26
+ output.puts "+------------ License Information ------------+"
27
+ output.puts "Total Licenses found: #{licenses_metadata.length}\n\n"
28
+
29
+ licenses_metadata.each do |license|
30
+ puts_bold "License Key : #{license.id}"
31
+ output.puts <<~LICENSE
32
+ Type : #{license.license_type}
33
+ Status : #{license.status}
34
+ Expiration Date : #{license.expiration_date}
35
+
36
+ LICENSE
37
+
38
+ iterate_attributes(license.software_entitlements, "Software Entitlements")
39
+ iterate_attributes(license.asset_entitlements, "Asset Entitlements")
40
+ iterate_attributes(license.feature_entitlements, "Feature Entitlements")
41
+
42
+ puts_bold "License Limits"
43
+ license.limits.each do |limit|
44
+ usage_limit = limit.usage_limit == -1 ? "Unlimited" : limit.usage_limit
45
+ output.puts <<~LIMIT
46
+ Usage Status : #{limit.usage_status}
47
+ Usage Limit : #{usage_limit}
48
+ Usage Measure : #{limit.usage_measure}
49
+ Used : #{limit.used}
50
+ Software : #{limit.software}
51
+ LIMIT
52
+ end
53
+ output.puts "+----------------------------------------------+"
54
+ end
55
+ end
56
+
57
+ def display_overview
58
+ output.puts "------------------------------------------------------------"
59
+ licenses_metadata.each do |license|
60
+ # Sets the validity text for a free license as "Unlimited" and displays the number of days for others.
61
+ validity = if license.license_type == "free"
62
+ "Unlimited"
63
+ else
64
+ # find the number of days left for the license to expire
65
+ days = (Date.parse(license.expiration_date) - Date.today).to_i
66
+ "#{days > 0 ? days : 0} #{"Day".pluralize(days)}"
67
+ end
68
+ num_of_units = license.limits&.first&.usage_limit || 0
69
+ num_of_units = num_of_units == -1 ? "Unlimited" : num_of_units
70
+ unit_measure = license.limits&.first&.usage_measure || "unit"
71
+ output.puts <<~LICENSE
72
+ #{pastel.bold("License Details")}
73
+ Asset Name : #{license.limits.first.software}
74
+ License ID : #{license.id}
75
+ Type : #{license.license_type.capitalize}
76
+ Status : #{license.status.capitalize}
77
+ Validity : #{validity}
78
+ No. Of Units : #{num_of_units} #{unit_measure.capitalize.pluralize(num_of_units)}
79
+ ------------------------------------------------------------
80
+ LICENSE
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ attr_reader :pastel, :output, :logger, :license_keys, :licenses_metadata
87
+
88
+ def display_info(component)
89
+ output.puts <<~INFO
90
+ ID : #{component.id}
91
+ Name : #{component.name}
92
+ Status : #{component.status}
93
+ Entitled : #{component.entitled}
94
+ INFO
95
+ output.puts "\n"
96
+ end
97
+
98
+ def iterate_attributes(component, header)
99
+ puts_bold header
100
+ puts "No #{header.downcase} found.\n\n" if component.empty?
101
+ component.each do |attribute|
102
+ display_info(attribute)
103
+ end
104
+ end
105
+
106
+ def puts_bold(title)
107
+ output.puts pastel.bold(title)
108
+ end
109
+
110
+ def fetch_license_keys(opts = {})
111
+ license_keys = opts[:license_keys] || ChefLicensing::LicenseKeyFetcher.fetch({ dir: opts[:dir] })
112
+
113
+ if license_keys.empty?
114
+ logger.debug "No license keys found on disk."
115
+ output.puts "No license keys found on disk."
116
+ exit
117
+ end
118
+ logger.debug "License keys fetched from disk: #{license_keys}"
119
+
120
+ license_keys
121
+ rescue ChefLicensing::LicenseKeyFetcher::LicenseKeyNotFetchedError => e
122
+ logger.debug "Error occured while fetching license keys from disk: #{e.message}"
123
+ output.puts "Error occured while fetching license keys from disk: #{e.message}"
124
+ # TODO: Exit with a non-zero status code
125
+ exit
126
+ end
127
+
128
+ def fetch_licenses_metadata
129
+ licenses_metadata = ChefLicensing::Api::Describe.list({
130
+ license_keys: license_keys,
131
+ })
132
+ logger.debug "License metadata fetched from server: #{licenses_metadata}"
133
+
134
+ licenses_metadata
135
+ rescue ChefLicensing::DescribeError => e
136
+ logger.debug "Error occured while fetching license information: #{e.message}"
137
+ output.puts "Error occured while fetching license information: #{e.message}"
138
+ # TODO: Exit with a non-zero status code
139
+ exit
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,139 @@
1
+ require "faraday" unless defined?(Faraday)
2
+ require "faraday/http_cache"
3
+ require "active_support"
4
+ require "tmpdir" unless defined?(Dir.mktmpdir)
5
+ require_relative "../exceptions/restful_client_error"
6
+ require_relative "../exceptions/restful_client_connection_error"
7
+ require_relative "../exceptions/missing_api_credentials_error"
8
+ require_relative "../config"
9
+ require_relative "middleware/exceptions_handler"
10
+
11
+ module ChefLicensing
12
+ module RestfulClient
13
+
14
+ # Base class to handle all License Server endpoints
15
+ class Base
16
+
17
+ END_POINTS = {
18
+ FEATURE_BY_NAME: "license-service/featurebyname",
19
+ FEATURE_BY_ID: "license-service/featurebyid",
20
+ ENTITLEMENT_BY_NAME: "license-service/entitlementbyname",
21
+ ENTITLEMENT_BY_ID: "license-service/entitlementbyid",
22
+ }.freeze
23
+
24
+ CURRENT_ENDPOINT_VERSION = 2
25
+
26
+ def initialize
27
+ 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?
28
+
29
+ @logger = ChefLicensing::Config.logger
30
+ end
31
+
32
+ def validate(license)
33
+ invoke_get_api(self.class::END_POINTS[:VALIDATE], { licenseId: license, version: CURRENT_ENDPOINT_VERSION })
34
+ end
35
+
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
+ def feature_by_name(payload)
45
+ invoke_post_api(self.class::END_POINTS[:FEATURE_BY_NAME], payload)
46
+ end
47
+
48
+ def feature_by_id(payload)
49
+ invoke_post_api(self.class::END_POINTS[:FEATURE_BY_ID], payload)
50
+ end
51
+
52
+ def entitlement_by_name(payload)
53
+ invoke_post_api(self.class::END_POINTS[:ENTITLEMENT_BY_NAME], payload)
54
+ end
55
+
56
+ def entitlement_by_id(payload)
57
+ invoke_post_api(self.class::END_POINTS[:ENTITLEMENT_BY_ID], payload)
58
+ end
59
+
60
+ def client(params = {})
61
+ invoke_get_api(self.class::END_POINTS[:CLIENT], { licenseId: params[:license_keys], entitlementId: params[:entitlement_id] })
62
+ end
63
+
64
+ def describe(params = {})
65
+ invoke_get_api(self.class::END_POINTS[:DESCRIBE], { licenseId: params[:license_keys], entitlementId: params[:entitlement_id] })
66
+ end
67
+
68
+ def list_licenses(params = {})
69
+ invoke_get_api(self.class::END_POINTS[:LIST_LICENSES])
70
+ end
71
+
72
+ private
73
+
74
+ attr_reader :logger
75
+
76
+ # a common method to handle the get API calls
77
+ def invoke_get_api(endpoint, params = {})
78
+ handle_get_connection do |connection|
79
+ connection.get(endpoint, params).body
80
+ end
81
+ end
82
+
83
+ # a common method to handle the post API calls
84
+ 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
89
+ end
90
+ raise RestfulClientError, format_error_from(response) unless response.success?
91
+
92
+ response.body
93
+ end
94
+ end
95
+
96
+ def handle_get_connection
97
+ # handle faraday errors
98
+ yield get_connection
99
+ rescue Faraday::ClientError => e
100
+ logger.debug "Restful Client Error #{e.message}"
101
+ raise RestfulClientError, e.message
102
+ end
103
+
104
+ def handle_post_connection
105
+ # handle faraday errors
106
+ yield post_connection
107
+ rescue Faraday::ClientError => e
108
+ logger.debug "Restful Client Error #{e.message}"
109
+ raise RestfulClientError, e.message
110
+ end
111
+
112
+ def get_connection
113
+ store = ::ActiveSupport::Cache.lookup_store(:file_store, Dir.tmpdir)
114
+ Faraday.new(url: ChefLicensing::Config.license_server_url) do |config|
115
+ config.request :json
116
+ config.response :json, parser_options: { object_class: OpenStruct }
117
+ config.use Faraday::HttpCache, shared_cache: false, logger: logger, store: store
118
+ config.use Middleware::ExceptionsHandler
119
+ config.adapter Faraday.default_adapter
120
+ end
121
+ end
122
+
123
+ def post_connection
124
+ Faraday.new(url: ChefLicensing::Config.license_server_url) do |config|
125
+ config.request :json
126
+ config.response :json, parser_options: { object_class: OpenStruct }
127
+ config.use Middleware::ExceptionsHandler
128
+ end
129
+ end
130
+
131
+ def format_error_from(response)
132
+ error_details = response.body&.data&.error
133
+ return response.reason_phrase unless error_details
134
+
135
+ error_details
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,16 @@
1
+ require "faraday" unless defined?(Faraday)
2
+ require "faraday/middleware"
3
+ require_relative "../../../chef-licensing/exceptions/restful_client_connection_error"
4
+
5
+ module Middleware
6
+ # Middleware that handles the exception handler for chef licensing
7
+ class ExceptionsHandler < Faraday::Middleware
8
+ def call(env)
9
+ @app.call(env)
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
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ require_relative "base"
2
+
3
+ module ChefLicensing
4
+ module RestfulClient
5
+ # Client that handles all License Server V1 endpoints
6
+ class V1 < Base
7
+ END_POINTS = END_POINTS.merge({
8
+ VALIDATE: "v1/validate",
9
+ GENERATE_TRIAL_LICENSE: "v1/trial",
10
+ GENERATE_FREE_LICENSE: "v1/free",
11
+ CLIENT: "v1/client",
12
+ DESCRIBE: "v1/desc",
13
+ LIST_LICENSES: "v1/listLicenses",
14
+ }).freeze
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,238 @@
1
+ require_relative "../license_key_validator"
2
+ require_relative "../license_key_generator"
3
+ require_relative "../exceptions/invalid_license"
4
+ require_relative "../exceptions/license_generation_failed"
5
+ require_relative "../exceptions/license_generation_rejected"
6
+ require_relative "../license_key_fetcher/base"
7
+ require_relative "../config"
8
+ require_relative "../context"
9
+ require_relative "../list_license_keys"
10
+ require "tty-spinner"
11
+
12
+ module ChefLicensing
13
+ class TUIEngine
14
+ class TUIActions
15
+ attr_accessor :logger, :output, :license_id, :error_msg, :rejection_msg, :invalid_license_msg, :license_type, :license
16
+ def initialize(opts = {})
17
+ @opts = opts
18
+ @logger = ChefLicensing::Config.logger
19
+ @output = ChefLicensing::Config.output
20
+ end
21
+
22
+ def is_license_with_valid_pattern?(input)
23
+ license_id = input[:ask_for_license_id]
24
+ input[:ask_for_license_id] = ChefLicensing::LicenseKeyFetcher::Base.verify_and_extract_license(license_id)
25
+ true
26
+ rescue ChefLicensing::LicenseKeyFetcher::Base::InvalidLicenseKeyFormat => e
27
+ output.puts e.message
28
+ logger.debug e.message
29
+ false
30
+ end
31
+
32
+ def is_license_valid_on_server?(input)
33
+ license_id = input[:ask_for_license_id]
34
+ spinner = TTY::Spinner.new(":spinner [Running] License validation in progress...", format: :dots, clear: true, output: output)
35
+ spinner.auto_spin # Start the spinner
36
+ is_valid = ChefLicensing::LicenseKeyValidator.validate!(license_id)
37
+ spinner.success # Stop the spinner
38
+ self.license_id = license_id
39
+ is_valid
40
+ rescue ChefLicensing::InvalidLicense => e
41
+ spinner.error # Stop the spinner
42
+ self.invalid_license_msg = e.message || "Something went wrong while validating the license"
43
+ false
44
+ end
45
+
46
+ def is_license_allowed?(input)
47
+ client_api_call(license_id)
48
+ self.license_type = get_license_type
49
+ if license_restricted?(license_type)
50
+ # 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
52
+ if license_type == :free && LicenseKeyFetcher::File.user_has_active_trial_license?(@opts)
53
+ existing_license_keys_in_file = LicenseKeyFetcher::File.fetch_license_keys_based_on_type(:trial, @opts)
54
+ else
55
+ existing_license_keys_in_file = LicenseKeyFetcher::File.fetch_license_keys_based_on_type(license_type, @opts)
56
+ end
57
+ self.license_id = existing_license_keys_in_file.last
58
+ false
59
+ else
60
+ true
61
+ end
62
+ end
63
+
64
+ def license_expiration_status?(input)
65
+ get_license(license_id)
66
+ if license.expired? || license.have_grace?
67
+ ChefLicensing::Context.local_licensing_service? ? "expired_in_local_mode" : "expired"
68
+ elsif license.about_to_expire?
69
+ input[:license_expiration_date] = Date.parse(license.expiration_date).strftime("%a, %d %b %Y")
70
+ input[:number_of_days_in_expiration] = license.number_of_days_in_expiration
71
+ "about_to_expire"
72
+ else
73
+ "active"
74
+ end
75
+ end
76
+
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
+ def fetch_license_id(input)
105
+ license_id
106
+ end
107
+
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
+ def fetch_invalid_license_msg(input)
134
+ invalid_license_msg
135
+ end
136
+
137
+ def display_license_info(inputs)
138
+ ChefLicensing::ListLicenseKeys.display_overview({ license_keys: [license_id] })
139
+ end
140
+
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
+ def set_license_info(input)
156
+ self.license_id = input[:license_id]
157
+ self.license_type = input[:license_type]
158
+ end
159
+
160
+ def determine_restriction_type(input)
161
+ if license_type == :free && LicenseKeyFetcher::File.user_has_active_trial_license?(@opts)
162
+ "active_trial_restriction"
163
+ else
164
+ "#{license_type}_restriction"
165
+ end
166
+ end
167
+
168
+ def fetch_license_type_restricted(inputs)
169
+ if license_restricted?(:trial) && license_restricted?(:free)
170
+ "trial_and_free"
171
+ elsif license_restricted?(:trial)
172
+ "trial"
173
+ else
174
+ "free"
175
+ end
176
+ end
177
+
178
+ def filter_license_type_options(inputs)
179
+ if (license_restricted?(:trial) && license_restricted?(:free)) || LicenseKeyFetcher::File.user_has_active_trial_license?(@opts)
180
+ "ask_for_commercial_only"
181
+ elsif license_restricted?(:trial)
182
+ "ask_for_license_except_trial"
183
+ elsif license_restricted?(:free)
184
+ "ask_for_license_except_free"
185
+ else
186
+ "ask_for_all_license_type"
187
+ end
188
+ end
189
+
190
+ private
191
+
192
+ attr_accessor :opts
193
+
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
+ def get_license(license_key)
217
+ spinner = TTY::Spinner.new(":spinner [Running] License validation in progress...", format: :dots, clear: true, output: output)
218
+ spinner.auto_spin # Start the spinner
219
+ client_api_call(license_key)
220
+ spinner.success # Stop the spinner
221
+ end
222
+
223
+ def client_api_call(license_key)
224
+ self.license ||= ChefLicensing.client(license_keys: [license_key])
225
+ end
226
+
227
+ def get_license_type
228
+ license.license_type.downcase.to_sym
229
+ end
230
+
231
+ def license_restricted?(license_type)
232
+ file_fetcher = LicenseKeyFetcher::File.new(@opts)
233
+ allowed_license_types = file_fetcher.fetch_allowed_license_types_for_addition
234
+ !(allowed_license_types.include? license_type)
235
+ end
236
+ end
237
+ end
238
+ end