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.
- 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: []
|