-
Notifications
You must be signed in to change notification settings - Fork 897
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create service template with Ansible Tower after first creating a new job template #13896
Create service template with Ansible Tower after first creating a new job template #13896
Conversation
cc - @bdunne, @gmcculloug |
@miq-bot add_label euwe/no |
@@ -1,5 +1,5 @@ | |||
class ServiceTemplateAnsiblePlaybook < ServiceTemplateGeneric | |||
def self.default_provisioning_entry_point(_service_type) | |||
def self.default_provisioning_entry_point(_service_type = nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to change
c81518e
to
41c824c
Compare
Hash.new.tap do |hash| | ||
[:provision, :retirement, :reconfigure].each do |action| | ||
next unless config_info[action] | ||
hash[action.to_sym] = { :configuration_template => create_job_template("#{service_name}_#{action}", description, config_info[action], auth_user) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
action
is already a symbol. For the job template name we may need to add a random number to ensure the uniqueness.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bzwei - Do we have a standard procedure for generating a random number? My original thought was something like rand(100)
but wasn't sure if that gives us enough permutations.
# tower = playbook.manager | ||
def self.create_job_templates(service_name, description, config_info, auth_user) | ||
{}.tap do |hash| | ||
[:provision, :retirement, :reconfigure].each do |action| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[:provision, :retirement, :reconfigure].each_with_object({}) do |action, hash|
{}.tap do |hash| | ||
[:provision, :retirement, :reconfigure].each do |action| | ||
next unless config_info[action] | ||
hash[action.to_sym] = { :configuration_template => create_job_template("#{service_name}_#{action}", description, config_info[action], auth_user) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
action is already a symbol
{}.tap do |hash| | ||
[:provision, :retirement, :reconfigure].each do |action| | ||
next unless config_info[action] | ||
hash[action.to_sym] = { :configuration_template => create_job_template("#{service_name}_#{action}", description, config_info[action], auth_user) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the job template name we need to add a random number to make the name unique. I prefer to make it a postfix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we instead use something like "ManageIQ_Service_#{service.id}_#{action}"? I don't think we should pick any random number.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating job template is the first step. We don't have any id at this stage. Having the service name as part of job template name is better for debugging. If we don't want random number we could try sequential number until the tower no longer rejects. Random number is probably better for performance's sake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer a GUID, and then you can also make sure the same GUID is in the database table in a guid column?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not against adding the name
of the ServiceTemplate
for troubleshooting purposes, but it isn't unique, therefore we can't use it to guarantee uniqueness, which is why I suggest using the records id
. Is there a reason we can't create an empty ServiceTemplate
(to be updated later in the process) before we create the Job Templates, just for the purpose of obtaining the unique id
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or is there some other thing we can tie to? Like a service request id or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bdunne Is there a race condition with refresh with that? That is, if you create a service template, then later refresh comes along, could it delete it out from underneath you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Fryguy ServiceTemplate is our concept, it isn't backed by a provider or updated on refresh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is how the job template looks like MIQ-PLAYBOOK-DEMO_PROVISION_HD2G8J13
, the last segment _HD2G8J13
is auto generated by a random algorithm. It looks good to me. This is just a hidden name, not meaningful to user but could be helpful for debugging.
I am OK to use UUID, just think appending to an existing name make it looks too long; or we could use UUID alone for the name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using the ID or UUID of the service_template make sense to me since they are already part of the model. (Remember that with a region id the ID value will be almost as long as the UUID.) But if the name length is not a problem in Tower then I do not think we should be too concerned with it here.
If this is the only thing blocking this PR can we open an issue (and/or pivotal story) to address it in a followup PR. From a discussion with @syncrou it sounds like creating the service_template first will require changes to another existing PR as well.
:ask_limit_on_launch => true, | ||
:ask_inventory_on_launch => true, | ||
:ask_credential_on_launch => true | ||
}.merge(info.slice(:extra_vars)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:extra_vars
hash needs to be converted to JSON string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good.
Hash.new.tap do |hash| | ||
[:provision, :retirement, :reconfigure].each do |action| | ||
next unless config_info[action] | ||
hash[action.to_sym] = { :configuration_template => create_job_template("#{service_name}_#{action}", description, config_info[action], auth_user) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the .to_sym
on action is necessary since it's already a symbol.
{}.tap do |hash| | ||
[:provision, :retirement, :reconfigure].each do |action| | ||
next unless config_info[action] | ||
hash[action.to_sym] = { :configuration_template => create_job_template("#{service_name}_#{action}", description, config_info[action], auth_user) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the action.to_sym
needs the to_sym
since action is already a symbol
# tower = playbook.manager | ||
def self.create_job_templates(service_name, description, config_info, auth_user) | ||
{}.tap do |hash| | ||
[:provision, :retirement, :reconfigure].each do |action| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer [:provision, :retirement, :reconfigure].each_with_object do |action, hash|
to avoid tapping the hash above.
info = catalog_item_options[:config_info][:provision] | ||
_tower, params = described_class.build_parameter_list(name, description, info) | ||
|
||
expect(params[:name]).to eq name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be a single expectation like:
expect(params).to have_attributes(
:name => name,
:description => description,
...etc...
)
This change allows for a Queued refresh after building the JobTemplate in the provider https://www.pivotaltracker.com/story/show/137306185
Accept an auth_user or default to 'system' as a backup Always call my_zone https://www.pivotaltracker.com/story/show/137306185
41c824c
to
f3e8adc
Compare
expect(params).to have_attributes( | ||
:name => name, | ||
:description => description, | ||
:extra_vars => nil, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should do a compact
to remove nil
s.
end | ||
private_class_method :create_job_template |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all the methods you added should be private
[:provision, :retirement, :reconfigure].each_with_object({}) do |action, hash| | ||
next unless config_info[action] | ||
job_template_name = unique_job_template_name(service_name, action) | ||
hash[action] = { :configuration_template => create_job_template(job_template_name.to_s, description, config_info[action], auth_user) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.to_s
is redundant
97423f8
to
aa5896e
Compare
private_class_method :build_parameter_list | ||
|
||
def self.unique_job_template_name(service_name, action) | ||
"#{service_name}_#{action}_#{rand(36**8).to_s(36)}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment from earlier was lost on change: #13896 (comment)
The question was which of the following is best:
- random value (made up from a number - current code here)
- random UUID
- something else that's unique but identifiable, like service_template_id.
@bdunne I believe you wanted 3, but there were questions on what is available. Can you elaborate a bit? Also, if service_template_id is available, is that sufficient for uniqueness? That is, is there a 1:1 between a service template and the job template? If so, I'd prefer 3 as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
service_template_id is not available here. The goal is to have a unique name. Combining the name with a random value/UUID, the chance of collision is minimal if not absolutely 0. If we cannot guarantee the service_template_id to be unique due to region or database reset, the chance of collision is even bigger.
Either way the issue is not a major concern for this PR.
a763d81
to
86e76c6
Compare
@@ -2,21 +2,23 @@ class ManageIQ::Providers::AnsibleTower::AutomationManager::ConfigurationScript | |||
module ApiCreate | |||
def create_in_provider(manager_id, params) | |||
manager = ExtManagementSystem.find(manager_id) | |||
raise "authentication status is not ok" unless manager.authentication_status_ok? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this? Shouldn't with_provider_connection
raise and if that somehow got through, shouldn't create!
raise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is discovered through test. You can reproduce and try a better solution. I have a valid tower but the authentication_status_ok?
returns false because the appliance (dev machine) was disconnected from VPN before. The job template can be created successfully because it does not check for authentication status, but refresh cannot pass through. The created job template is useless because we cannot get it in VMDB.
We can attempt to sync the current authentication status. This line can be a temporary solution before we implement a better way.
86e76c6
to
c81dbcb
Compare
Checked commits syncrou/manageiq@4d57beb~...c81dbcb with ruby 2.2.6, rubocop 0.47.1, and haml-lint 0.20.0 |
@bdunne, @gmcculloug - All requested changes are in. Can we hit the magic green button? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 LGTM
https://www.pivotaltracker.com/story/show/137306185