chef-licensing 0.4.43
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +1 -0
- data/chef-licensing.gemspec +35 -0
- data/lib/chef-licensing/api/client.rb +39 -0
- data/lib/chef-licensing/api/describe.rb +62 -0
- data/lib/chef-licensing/api/license_feature_entitlement.rb +55 -0
- data/lib/chef-licensing/api/license_software_entitlement.rb +53 -0
- data/lib/chef-licensing/api/list_licenses.rb +30 -0
- data/lib/chef-licensing/api/parser/client.rb +100 -0
- data/lib/chef-licensing/api/parser/describe.rb +118 -0
- data/lib/chef-licensing/cli_flags/mixlib_cli.rb +28 -0
- data/lib/chef-licensing/cli_flags/thor.rb +21 -0
- data/lib/chef-licensing/config.rb +44 -0
- data/lib/chef-licensing/config_fetcher/arg_fetcher.rb +38 -0
- data/lib/chef-licensing/config_fetcher/env_fetcher.rb +21 -0
- data/lib/chef-licensing/context.rb +98 -0
- data/lib/chef-licensing/exceptions/client_error.rb +9 -0
- data/lib/chef-licensing/exceptions/describe_error.rb +9 -0
- data/lib/chef-licensing/exceptions/error.rb +4 -0
- data/lib/chef-licensing/exceptions/feature_not_entitled.rb +9 -0
- data/lib/chef-licensing/exceptions/invalid_license.rb +10 -0
- data/lib/chef-licensing/exceptions/license_generation_failed.rb +9 -0
- data/lib/chef-licensing/exceptions/license_generation_rejected.rb +7 -0
- data/lib/chef-licensing/exceptions/list_licenses_error.rb +12 -0
- data/lib/chef-licensing/exceptions/missing_api_credentials_error.rb +7 -0
- data/lib/chef-licensing/exceptions/restful_client_connection_error.rb +9 -0
- data/lib/chef-licensing/exceptions/restful_client_error.rb +9 -0
- data/lib/chef-licensing/exceptions/software_not_entitled.rb +9 -0
- data/lib/chef-licensing/license.rb +151 -0
- data/lib/chef-licensing/license_key_fetcher/base.rb +28 -0
- data/lib/chef-licensing/license_key_fetcher/chef_licensing_interactions.yaml +534 -0
- data/lib/chef-licensing/license_key_fetcher/file.rb +275 -0
- data/lib/chef-licensing/license_key_fetcher/prompt.rb +43 -0
- data/lib/chef-licensing/license_key_fetcher.rb +314 -0
- data/lib/chef-licensing/license_key_generator.rb +47 -0
- data/lib/chef-licensing/license_key_validator.rb +24 -0
- data/lib/chef-licensing/licensing_service/local.rb +29 -0
- data/lib/chef-licensing/list_license_keys.rb +142 -0
- data/lib/chef-licensing/restful_client/base.rb +139 -0
- data/lib/chef-licensing/restful_client/middleware/exceptions_handler.rb +16 -0
- data/lib/chef-licensing/restful_client/v1.rb +17 -0
- data/lib/chef-licensing/tui_engine/tui_actions.rb +238 -0
- data/lib/chef-licensing/tui_engine/tui_engine.rb +174 -0
- data/lib/chef-licensing/tui_engine/tui_engine_state.rb +62 -0
- data/lib/chef-licensing/tui_engine/tui_exceptions.rb +17 -0
- data/lib/chef-licensing/tui_engine/tui_interaction.rb +17 -0
- data/lib/chef-licensing/tui_engine/tui_prompt.rb +117 -0
- data/lib/chef-licensing/tui_engine.rb +2 -0
- data/lib/chef-licensing/version.rb +3 -0
- data/lib/chef-licensing.rb +70 -0
- metadata +191 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
require_relative "tui_exceptions"
|
2
|
+
require_relative "tui_interaction"
|
3
|
+
require_relative "tui_engine_state"
|
4
|
+
require_relative "tui_prompt"
|
5
|
+
require_relative "tui_actions"
|
6
|
+
require_relative "../config"
|
7
|
+
|
8
|
+
module ChefLicensing
|
9
|
+
class TUIEngine
|
10
|
+
|
11
|
+
INTERACTION_FILE_FORMAT_VERSION = "1.0.0".freeze
|
12
|
+
|
13
|
+
attr_accessor :interaction_data, :tui_interactions, :opts, :logger, :prompt_methods, :action_methods, :interaction_attributes, :traversed_interaction
|
14
|
+
|
15
|
+
def initialize(opts = {})
|
16
|
+
@opts = opts
|
17
|
+
@logger = ChefLicensing::Config.logger
|
18
|
+
@tui_interactions = {}
|
19
|
+
@traversed_interaction = []
|
20
|
+
initialization_of_engine(opts[:interaction_file])
|
21
|
+
@state = ChefLicensing::TUIEngine::TUIEngineState.new(@opts)
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_interaction(start_interaction_id = nil)
|
25
|
+
start_interaction_id ||= @tui_interactions.keys.first
|
26
|
+
current_interaction = @tui_interactions[start_interaction_id]
|
27
|
+
|
28
|
+
previous_interaction = nil
|
29
|
+
|
30
|
+
until current_interaction.nil? || current_interaction.id == :exit
|
31
|
+
@traversed_interaction << current_interaction.id
|
32
|
+
state.default_action(current_interaction)
|
33
|
+
previous_interaction = current_interaction
|
34
|
+
current_interaction = state.next_interaction_id.nil? ? nil : current_interaction.paths[state.next_interaction_id.to_sym]
|
35
|
+
end
|
36
|
+
|
37
|
+
# If the last interaction is not the exit interaction. Something went wrong in the flow.
|
38
|
+
# raise the message where the flow broke.
|
39
|
+
raise ChefLicensing::TUIEngine::IncompleteFlowException, "Something went wrong in the flow. The last interaction was #{previous_interaction&.id}." unless current_interaction&.id == :exit
|
40
|
+
|
41
|
+
state.default_action(current_interaction)
|
42
|
+
# remove the pastel key we used in tui engine state for styling and return the remaining parsed input
|
43
|
+
state.input.delete(:pastel)
|
44
|
+
state.input
|
45
|
+
end
|
46
|
+
|
47
|
+
def append_info_to_input(extra_info_hash)
|
48
|
+
state.append_info_to_input(extra_info_hash)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
attr_accessor :state
|
54
|
+
|
55
|
+
def initialization_of_engine(interaction_file)
|
56
|
+
raise ChefLicensing::TUIEngine::MissingInteractionFile, "No interaction file found. Please provide a valid file path to continue." unless interaction_file
|
57
|
+
|
58
|
+
@interaction_data = inflate_interaction_data(interaction_file)
|
59
|
+
verify_interaction_data
|
60
|
+
store_interaction_objects
|
61
|
+
build_interaction_path
|
62
|
+
logger.debug "TUI Engine initialized."
|
63
|
+
end
|
64
|
+
|
65
|
+
def inflate_interaction_data(interaction_file)
|
66
|
+
require "yaml" unless defined?(YAML)
|
67
|
+
YAML.load_file(interaction_file)
|
68
|
+
rescue => e
|
69
|
+
raise ChefLicensing::TUIEngine::BadInteractionFile, "Unable to load interaction file: #{interaction_file}.\n#{e.message}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def store_interaction_objects
|
73
|
+
unless major_version(@interaction_data[:file_format_version]) == major_version(INTERACTION_FILE_FORMAT_VERSION)
|
74
|
+
raise ChefLicensing::TUIEngine::UnsupportedInteractionFileFormat, "Unsupported interaction file format version.\nExpected #{INTERACTION_FILE_FORMAT_VERSION} but found #{@interaction_data[:file_format_version]}."
|
75
|
+
end
|
76
|
+
|
77
|
+
@interaction_data["interactions"].each do |k, opts|
|
78
|
+
opts.transform_keys!(&:to_sym)
|
79
|
+
opts.store(:id, k.to_sym)
|
80
|
+
@tui_interactions.store(k.to_sym, ChefLicensing::TUIEngine::TUIInteraction.new(opts))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_interaction_path
|
85
|
+
@interaction_data["interactions"].each do |k, opts|
|
86
|
+
current_interaction = @tui_interactions[k.to_sym]
|
87
|
+
opts.transform_keys!(&:to_sym)
|
88
|
+
paths = opts[:paths] || []
|
89
|
+
paths.each do |path|
|
90
|
+
current_interaction.paths.store(path.to_sym, @tui_interactions[path.to_sym])
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def verify_interaction_data
|
96
|
+
raise ChefLicensing::TUIEngine::BadInteractionFile, "The interaction file has no data." unless @interaction_data
|
97
|
+
|
98
|
+
raise ChefLicensing::TUIEngine::BadInteractionFile, "`file_format_version` key not found in yaml file." unless @interaction_data[:file_format_version]
|
99
|
+
|
100
|
+
raise ChefLicensing::TUIEngine::BadInteractionFile, "`interactions` key not found in yaml file." unless @interaction_data["interactions"]
|
101
|
+
|
102
|
+
@interaction_data["interactions"].each do |i_id, opts|
|
103
|
+
opts.transform_keys!(&:to_sym)
|
104
|
+
verify_interaction_purpose(i_id, opts)
|
105
|
+
opts.each do |k, val|
|
106
|
+
validate_interaction_attribute(i_id, k, val)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def verify_interaction_purpose(i_id, opts)
|
112
|
+
# An interaction must be either action or a prompt to display messages.
|
113
|
+
unless opts[:action] || opts[:messages]
|
114
|
+
raise ChefLicensing::TUIEngine::BadInteractionFile, "No action or messages found for interaction #{i_id}.\nAdd either action or messages to the interaction."
|
115
|
+
end
|
116
|
+
|
117
|
+
# Supporting both could lead ambiguous flow in response_path_map
|
118
|
+
if opts[:action] && opts[:messages]
|
119
|
+
warning_message = "Both `action` and `messages` keys found in yaml file for interaction #{i_id}.\n`response_path_map` keys would be considered response from messages and not action.\nYour yaml file may not work as expected."
|
120
|
+
warn warning_message
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def validate_interaction_attribute(i_id, k, val)
|
125
|
+
if is_valid_interaction_attribute?(k)
|
126
|
+
if k == :prompt_type && !is_valid_prompt_method?(val)
|
127
|
+
raise ChefLicensing::TUIEngine::BadInteractionFile, "Invalid value `#{val}` for `prompt_type` key in yaml file for interaction #{i_id}."
|
128
|
+
elsif k == :action && !is_valid_action_method?(val)
|
129
|
+
raise ChefLicensing::TUIEngine::BadInteractionFile, "Invalid value `#{val}` for `action` key in yaml file for interaction #{i_id}."
|
130
|
+
end
|
131
|
+
else
|
132
|
+
warning_message = "Invalid key `#{k}` found in yaml file for interaction #{i_id}.\nValid keys are #{@interaction_attributes.join(", ")}.\n#{k} will be ignored.\nYour yaml file may not work as expected."
|
133
|
+
warn warning_message
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def is_valid_prompt_method?(val)
|
138
|
+
@prompt_methods ||= begin
|
139
|
+
# Find the getter methods of TUIPrompt class
|
140
|
+
prompt_getter = ChefLicensing::TUIEngine::TUIPrompt.new.instance_variables.map { |var| var.to_s.delete("@").to_sym }
|
141
|
+
|
142
|
+
# Find the setter methods of TUIPrompt class
|
143
|
+
prompt_setter = prompt_getter.map { |attr| "#{attr}=".to_sym }
|
144
|
+
|
145
|
+
# Subtract the getter and setter of TUIPrompt class from the instance methods of TUIPrompt class
|
146
|
+
ChefLicensing::TUIEngine::TUIPrompt.instance_methods(false) - prompt_getter - prompt_setter
|
147
|
+
end
|
148
|
+
@prompt_methods.include?(val.to_sym)
|
149
|
+
end
|
150
|
+
|
151
|
+
def is_valid_action_method?(val)
|
152
|
+
@action_methods ||= begin
|
153
|
+
# Find the getter methods of TUIActions class
|
154
|
+
action_getter = ChefLicensing::TUIEngine::TUIActions.new.instance_variables.map { |var| var.to_s.delete("@").to_sym }
|
155
|
+
|
156
|
+
# Find the setter methods of TUIActions class
|
157
|
+
action_setter = action_getter.map { |attr| "#{attr}=".to_sym }
|
158
|
+
|
159
|
+
# Subtract the getter and setter of TUIActions class from the instance methods of TUIActions class
|
160
|
+
ChefLicensing::TUIEngine::TUIActions.instance_methods(false) - action_getter - action_setter
|
161
|
+
end
|
162
|
+
@action_methods.include?(val.to_sym)
|
163
|
+
end
|
164
|
+
|
165
|
+
def is_valid_interaction_attribute?(val)
|
166
|
+
@interaction_attributes ||= ChefLicensing::TUIEngine::TUIInteraction.new.instance_variables.map { |var| var.to_s.delete("@").to_sym }
|
167
|
+
@interaction_attributes.include?(val.to_sym)
|
168
|
+
end
|
169
|
+
|
170
|
+
def major_version(version)
|
171
|
+
Gem::Version.new(version).segments[0]
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require_relative "tui_prompt"
|
2
|
+
require_relative "tui_actions"
|
3
|
+
require "erb" unless defined?(Erb)
|
4
|
+
require_relative "../config"
|
5
|
+
require "pastel" unless defined?(Pastel)
|
6
|
+
|
7
|
+
module ChefLicensing
|
8
|
+
class TUIEngine
|
9
|
+
class TUIEngineState < Hash
|
10
|
+
attr_accessor :next_interaction_id, :input, :logger, :prompt, :tui_actions
|
11
|
+
|
12
|
+
def initialize(opts = {})
|
13
|
+
@input = {}
|
14
|
+
# store the pastel key for enabling styled messages in the yaml file
|
15
|
+
@input[:pastel] = Pastel.new
|
16
|
+
@logger = ChefLicensing::Config.logger
|
17
|
+
@prompt = ChefLicensing::TUIEngine::TUIPrompt.new(opts)
|
18
|
+
@tui_actions = ChefLicensing::TUIEngine::TUIActions.new(opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_action(interaction)
|
22
|
+
logger.debug "Default action called for interaction id: #{interaction.id}"
|
23
|
+
|
24
|
+
response = if interaction.messages
|
25
|
+
messages = render_messages(interaction.messages)
|
26
|
+
@prompt.send(interaction.prompt_type, messages, interaction.prompt_attributes)
|
27
|
+
elsif interaction.action
|
28
|
+
@tui_actions.send(interaction.action, @input)
|
29
|
+
end
|
30
|
+
|
31
|
+
@input.store(interaction.id, response)
|
32
|
+
logger.debug "Response for interaction #{interaction.id} is #{@input[interaction.id]}"
|
33
|
+
|
34
|
+
@next_interaction_id = if interaction.paths.size > 1
|
35
|
+
interaction.response_path_map[response.to_s]
|
36
|
+
elsif interaction.paths.size == 1
|
37
|
+
interaction.paths.keys.first
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def append_info_to_input(extra_info_hash)
|
42
|
+
@input.merge!(extra_info_hash)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def erb_result(message)
|
48
|
+
ERB.new(message).result_with_hash(input: input)
|
49
|
+
end
|
50
|
+
|
51
|
+
def render_messages(messages)
|
52
|
+
if messages.is_a?(String)
|
53
|
+
erb_result(messages)
|
54
|
+
elsif messages.is_a?(Array)
|
55
|
+
messages.map do |message|
|
56
|
+
render_messages(message)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "timeout" unless defined?(Timeout)
|
2
|
+
|
3
|
+
module ChefLicensing
|
4
|
+
class TUIEngine
|
5
|
+
class BadInteractionFile < StandardError; end
|
6
|
+
|
7
|
+
class PromptTimeout < Timeout::Error; end
|
8
|
+
|
9
|
+
class IncompleteFlowException < StandardError; end
|
10
|
+
|
11
|
+
class UnsupportedInteractionFileFormat < StandardError; end
|
12
|
+
|
13
|
+
class MissingInteractionFile < StandardError; end
|
14
|
+
|
15
|
+
class BadPromptInput < StandardError; end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ChefLicensing
|
2
|
+
class TUIEngine
|
3
|
+
class TUIInteraction
|
4
|
+
attr_accessor :id, :messages, :action, :paths, :prompt_type, :response_path_map, :prompt_attributes, :description
|
5
|
+
def initialize(opts = {})
|
6
|
+
@id = opts[:id]
|
7
|
+
@messages = opts[:messages]
|
8
|
+
@action = opts[:action]
|
9
|
+
@prompt_type = opts[:prompt_type] || "say"
|
10
|
+
@prompt_attributes = opts[:prompt_attributes] || {}
|
11
|
+
@response_path_map = opts[:response_path_map]
|
12
|
+
@paths = {}
|
13
|
+
@description = opts[:description] || ""
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require "timeout" unless defined?(Timeout)
|
2
|
+
require "tty-prompt"
|
3
|
+
require_relative "tui_exceptions"
|
4
|
+
require "erb" unless defined?(Erb)
|
5
|
+
require_relative "../config"
|
6
|
+
|
7
|
+
module ChefLicensing
|
8
|
+
class TUIEngine
|
9
|
+
class TUIPrompt
|
10
|
+
attr_accessor :output, :input, :logger, :tty_prompt
|
11
|
+
|
12
|
+
def initialize(opts = {})
|
13
|
+
@output = ChefLicensing::Config.output
|
14
|
+
@input = opts[:input] || STDIN
|
15
|
+
@logger = ChefLicensing::Config.logger
|
16
|
+
@tty_prompt = opts[:prompt] || TTY::Prompt.new(track_history: false, active_color: :bold, interrupt: :exit, output: output, input: input)
|
17
|
+
end
|
18
|
+
|
19
|
+
# yes prompts the user with a yes/no question and returns true if the user
|
20
|
+
# answers yes and false if the user answers no.
|
21
|
+
# prompt_attributes is added to extend the prompt in future.
|
22
|
+
def yes(messages, prompt_attributes)
|
23
|
+
message = Array(messages).first
|
24
|
+
@tty_prompt.yes?(message)
|
25
|
+
end
|
26
|
+
|
27
|
+
# say prints the given message to the output stream.
|
28
|
+
# default prompt_type of an interaction is say.
|
29
|
+
# prompt_attributes is added to extend the prompt in future.
|
30
|
+
def say(messages, prompt_attributes)
|
31
|
+
message = Array(messages).first
|
32
|
+
@tty_prompt.say(message)
|
33
|
+
end
|
34
|
+
|
35
|
+
# ok prints the given message to the output stream in green color.
|
36
|
+
# prompt_attributes is added to extend the prompt in future.
|
37
|
+
def ok(messages, prompt_attributes)
|
38
|
+
message = Array(messages).first
|
39
|
+
@tty_prompt.ok(message)
|
40
|
+
end
|
41
|
+
|
42
|
+
# warn prints the given message to the output stream in yellow color.
|
43
|
+
# prompt_attributes is added to extend the prompt in future.
|
44
|
+
def warn(messages, prompt_attributes)
|
45
|
+
message = Array(messages).first
|
46
|
+
@tty_prompt.warn(message)
|
47
|
+
end
|
48
|
+
|
49
|
+
# error prints the given message to the output stream in red color.
|
50
|
+
# prompt_attributes is added to extend the prompt in future.
|
51
|
+
def error(messages, prompt_attributes)
|
52
|
+
message = Array(messages).first
|
53
|
+
@tty_prompt.error(message)
|
54
|
+
end
|
55
|
+
|
56
|
+
# select prompts the user to select an option from a list of options.
|
57
|
+
# prompt_attributes is added to extend the prompt in future.
|
58
|
+
def select(messages, prompt_attributes)
|
59
|
+
header, choices_list = fetch_header_and_choices(messages, :select)
|
60
|
+
@tty_prompt.select(header, choices_list)
|
61
|
+
end
|
62
|
+
|
63
|
+
# enum_select prompts the user to select an option from a list of options.
|
64
|
+
# prompt_attributes is added to extend the prompt in future.
|
65
|
+
def enum_select(messages, prompt_attributes)
|
66
|
+
header, choices_list = fetch_header_and_choices(messages, :enum_select)
|
67
|
+
@tty_prompt.enum_select(header, choices_list)
|
68
|
+
end
|
69
|
+
|
70
|
+
# ask prompts the user to enter a value.
|
71
|
+
# prompt_attributes is added to extend the prompt in future.
|
72
|
+
def ask(messages, prompt_attributes)
|
73
|
+
message = Array(messages).first
|
74
|
+
@tty_prompt.ask(message)
|
75
|
+
end
|
76
|
+
|
77
|
+
# timeout_yes prompt wraps yes prompt with timeout.
|
78
|
+
# prompt_attributes is added to extend the prompt in future.
|
79
|
+
def timeout_yes(messages, prompt_attributes)
|
80
|
+
timeout_helper(messages, method(:yes), prompt_attributes)
|
81
|
+
end
|
82
|
+
|
83
|
+
def timeout_select(messages, prompt_attributes)
|
84
|
+
timeout_helper(messages, method(:select), prompt_attributes)
|
85
|
+
end
|
86
|
+
|
87
|
+
def silent(messages, prompt_attributes)
|
88
|
+
Array(messages).first
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def fetch_header_and_choices(messages, prompt_type)
|
94
|
+
unless messages.is_a?(Array) && messages.size > 1
|
95
|
+
raise ChefLicensing::TUIEngine::BadPromptInput, "messages for #{prompt_type} must be an array of size greater than 1"
|
96
|
+
end
|
97
|
+
|
98
|
+
header, *choices_list = messages
|
99
|
+
[header, choices_list]
|
100
|
+
end
|
101
|
+
|
102
|
+
def timeout_helper(messages, prompt_method, prompt_attributes)
|
103
|
+
prompt_attributes.transform_keys!(&:to_sym)
|
104
|
+
timeout_duration = prompt_attributes[:timeout_duration] || 60
|
105
|
+
Timeout.timeout(timeout_duration, PromptTimeout) do
|
106
|
+
prompt_method.call(messages, prompt_attributes)
|
107
|
+
rescue PromptTimeout
|
108
|
+
error(prompt_attributes[:timeout_message] || "Prompt Timeout", prompt_attributes)
|
109
|
+
@tty_prompt.unsubscribe(@tty_prompt.reader)
|
110
|
+
# TODO: Exit with a meaningful error code.
|
111
|
+
output.puts "Timed out!"
|
112
|
+
exit
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "chef-licensing/version"
|
2
|
+
require "chef-licensing/license_key_fetcher"
|
3
|
+
require "chef-licensing/config"
|
4
|
+
require "chef-licensing/api/describe"
|
5
|
+
require "chef-licensing/list_license_keys"
|
6
|
+
require "chef-licensing/exceptions/feature_not_entitled"
|
7
|
+
require "chef-licensing/exceptions/software_not_entitled"
|
8
|
+
require "chef-licensing/exceptions/client_error"
|
9
|
+
require "chef-licensing/api/client"
|
10
|
+
require "chef-licensing/license_key_fetcher/prompt"
|
11
|
+
|
12
|
+
module ChefLicensing
|
13
|
+
class << self
|
14
|
+
|
15
|
+
# @example
|
16
|
+
# ChefLicensing.configure do |config|
|
17
|
+
# config.licensing_server_url = 'LICENSE_SERVER'
|
18
|
+
# config.logger = Logger.new($stdout)
|
19
|
+
# end
|
20
|
+
def configure(&block)
|
21
|
+
yield(ChefLicensing::Config)
|
22
|
+
end
|
23
|
+
|
24
|
+
def check_feature_entitlement!(feature_name: nil, feature_id: nil)
|
25
|
+
# Checking for feature presence in license feature entitlements
|
26
|
+
license = client(license_keys: license_keys)
|
27
|
+
feature_entitlements = license.feature_entitlements.select { |feature| feature.id == feature_id || feature.name == feature_name }
|
28
|
+
if feature_entitlements.empty?
|
29
|
+
raise(ChefLicensing::FeatureNotEntitled)
|
30
|
+
else
|
31
|
+
true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def check_software_entitlement!
|
36
|
+
# If API call is not breaking that means license is entitled.
|
37
|
+
client(license_keys: license_keys)
|
38
|
+
true
|
39
|
+
rescue ChefLicensing::ClientError => e
|
40
|
+
# Checking specific text phrase for entitlement error
|
41
|
+
if e.message.match?(/not entitled/)
|
42
|
+
raise(ChefLicensing::SoftwareNotEntitled)
|
43
|
+
else
|
44
|
+
raise
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# @note no in-memory caching of the licenses so that it fetches updated licenses always
|
49
|
+
def license_keys
|
50
|
+
ChefLicensing::LicenseKeyFetcher.fetch
|
51
|
+
end
|
52
|
+
|
53
|
+
# @note fetch_and_persist is invoked by chef-products to fetch and persist the license keys
|
54
|
+
def fetch_and_persist
|
55
|
+
ChefLicensing::LicenseKeyFetcher.fetch_and_persist
|
56
|
+
end
|
57
|
+
|
58
|
+
def list_license_keys_info(opts = {})
|
59
|
+
ChefLicensing::ListLicenseKeys.display(opts)
|
60
|
+
end
|
61
|
+
|
62
|
+
def client(opts = {})
|
63
|
+
ChefLicensing::Api::Client.info(opts)
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_license
|
67
|
+
ChefLicensing::LicenseKeyFetcher.add_license
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
metadata
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chef-licensing
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.43
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Inspec Team
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-07-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: chef-config
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '15'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '15'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tty-prompt
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.23'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.23'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: faraday
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1'
|
48
|
+
- - "<"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '3'
|
51
|
+
type: :runtime
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '1'
|
58
|
+
- - "<"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: faraday-http-cache
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: activesupport
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '7.0'
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 7.0.4.2
|
85
|
+
type: :runtime
|
86
|
+
prerelease: false
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '7.0'
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 7.0.4.2
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: tty-spinner
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 0.9.3
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: 0.9.3
|
109
|
+
description: Ruby library to support CLI tools that use Progress Chef license storage,
|
110
|
+
generation, and entitlement.
|
111
|
+
email:
|
112
|
+
- inspec@progress.com
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- LICENSE
|
118
|
+
- chef-licensing.gemspec
|
119
|
+
- lib/chef-licensing.rb
|
120
|
+
- lib/chef-licensing/api/client.rb
|
121
|
+
- lib/chef-licensing/api/describe.rb
|
122
|
+
- lib/chef-licensing/api/license_feature_entitlement.rb
|
123
|
+
- lib/chef-licensing/api/license_software_entitlement.rb
|
124
|
+
- lib/chef-licensing/api/list_licenses.rb
|
125
|
+
- lib/chef-licensing/api/parser/client.rb
|
126
|
+
- lib/chef-licensing/api/parser/describe.rb
|
127
|
+
- lib/chef-licensing/cli_flags/mixlib_cli.rb
|
128
|
+
- lib/chef-licensing/cli_flags/thor.rb
|
129
|
+
- lib/chef-licensing/config.rb
|
130
|
+
- lib/chef-licensing/config_fetcher/arg_fetcher.rb
|
131
|
+
- lib/chef-licensing/config_fetcher/env_fetcher.rb
|
132
|
+
- lib/chef-licensing/context.rb
|
133
|
+
- lib/chef-licensing/exceptions/client_error.rb
|
134
|
+
- lib/chef-licensing/exceptions/describe_error.rb
|
135
|
+
- lib/chef-licensing/exceptions/error.rb
|
136
|
+
- lib/chef-licensing/exceptions/feature_not_entitled.rb
|
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
|
140
|
+
- lib/chef-licensing/exceptions/list_licenses_error.rb
|
141
|
+
- lib/chef-licensing/exceptions/missing_api_credentials_error.rb
|
142
|
+
- lib/chef-licensing/exceptions/restful_client_connection_error.rb
|
143
|
+
- lib/chef-licensing/exceptions/restful_client_error.rb
|
144
|
+
- lib/chef-licensing/exceptions/software_not_entitled.rb
|
145
|
+
- lib/chef-licensing/license.rb
|
146
|
+
- lib/chef-licensing/license_key_fetcher.rb
|
147
|
+
- lib/chef-licensing/license_key_fetcher/base.rb
|
148
|
+
- lib/chef-licensing/license_key_fetcher/chef_licensing_interactions.yaml
|
149
|
+
- lib/chef-licensing/license_key_fetcher/file.rb
|
150
|
+
- lib/chef-licensing/license_key_fetcher/prompt.rb
|
151
|
+
- lib/chef-licensing/license_key_generator.rb
|
152
|
+
- lib/chef-licensing/license_key_validator.rb
|
153
|
+
- lib/chef-licensing/licensing_service/local.rb
|
154
|
+
- lib/chef-licensing/list_license_keys.rb
|
155
|
+
- lib/chef-licensing/restful_client/base.rb
|
156
|
+
- lib/chef-licensing/restful_client/middleware/exceptions_handler.rb
|
157
|
+
- lib/chef-licensing/restful_client/v1.rb
|
158
|
+
- lib/chef-licensing/tui_engine.rb
|
159
|
+
- lib/chef-licensing/tui_engine/tui_actions.rb
|
160
|
+
- lib/chef-licensing/tui_engine/tui_engine.rb
|
161
|
+
- lib/chef-licensing/tui_engine/tui_engine_state.rb
|
162
|
+
- lib/chef-licensing/tui_engine/tui_exceptions.rb
|
163
|
+
- lib/chef-licensing/tui_engine/tui_interaction.rb
|
164
|
+
- lib/chef-licensing/tui_engine/tui_prompt.rb
|
165
|
+
- lib/chef-licensing/version.rb
|
166
|
+
homepage: https://github.com/chef/chef-licensing
|
167
|
+
licenses:
|
168
|
+
- LicenseRef-LICENSE
|
169
|
+
metadata:
|
170
|
+
homepage_uri: https://github.com/chef/chef-licensing
|
171
|
+
source_code_uri: https://github.com/chef/chef-licensing
|
172
|
+
post_install_message:
|
173
|
+
rdoc_options: []
|
174
|
+
require_paths:
|
175
|
+
- lib
|
176
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: 2.3.0
|
181
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ">="
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
requirements: []
|
187
|
+
rubygems_version: 3.3.7
|
188
|
+
signing_key:
|
189
|
+
specification_version: 4
|
190
|
+
summary: Chef License storage, generation, and entitlement
|
191
|
+
test_files: []
|