-
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
api: copy orchestration template #13053
Conversation
|
||
expect do | ||
run_post(orchestration_templates_url(test_ot.id), gen_request(:copy, :content => '')) | ||
end.to change(OrchestrationTemplateCfn, :count).by(2) |
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 test the http status and expected response as well here
@@ -144,6 +144,18 @@ def save_as_orderable! | |||
new_record? ? replace_with_old_template(old_template) : transfer_stacks(old_template) | |||
end | |||
|
|||
def deep_copy(new_attributes = {}) |
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.
not really sure this deep copy is needed since it's only dup-ing and updating the attributes
api_basic_authorize collection_action_identifier(:orchestration_templates, :copy) | ||
|
||
run_post(orchestration_templates_url(test_ot.id), gen_request(:copy)) | ||
expect(response.status).to eq(400) |
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.
just a suggestion, but this could also be written
expect(response).to have_http_status(:forbidden)
which is nice for readability 😄
@@ -125,4 +125,23 @@ | |||
expect(OrchestrationTemplate.exists?(hot.id)).to be_falsey | |||
end | |||
end | |||
|
|||
context 'orchestration template copy' do |
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 also add a test for copying multiple
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.
@cynepco3hahue can you also add tests for unhappy path for authorization for this feature?
9798578
to
6db0c32
Compare
@@ -94,6 +94,23 @@ def delete_resource(type, id = nil, _data = nil) | |||
delete_resource_action(klass, type, id) | |||
end | |||
|
|||
def copy_resource(type, id, data = {}) |
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 should be in app/controllers/api/orchestration_template_controller.rb
because it is specific to orchestration templates
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.
It looks pretty general, so I thought maybe it can be useful in the future if you want to add copy API for some entity.
What do you think?
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.
Not a bad idea - but that's a question for @abellotti or @imtayadeway 😃
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.
@cynepco3hahue I would make the same recommendation as per @jntullo - if it is needed for another resource we can always review that later, and there may be a better way of sharing that between API controllers without giving it to everyone in the base class
def copy_resource(type, id, data = {}) | ||
klass = collection_class(type) | ||
resource = resource_search(id, type, klass) | ||
attributes = data.dup |
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.
don't think you need to dup the data here since you're not manipulating it
if new_resource.respond_to? "#{attr}=" | ||
new_resource.send("#{attr}=", value) | ||
else | ||
raise ActiveModel::UnknownAttributeError.new(self, attr) |
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.
would not raise an UnknownAttributeError
since that'll be handled by the rescue below. Would just do a raise "uknown attribute #{attr}"
end | ||
new_resource.tap(&:save!) | ||
rescue => err | ||
raise BadRequestError, "Failed to copy orchestration template - #{err}" |
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.
If it stays in generic, will need to remove reference to orchestration template
eed9c95
to
bf7c315
Compare
klass = collection_class(type) | ||
resource = resource_search(id, type, klass) | ||
new_resource = resource.dup | ||
data.each do |attr, value| |
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.
Does new_resource.assign_attributes(data)
achieve the same effect?
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.
yes, thanks now it looks better
orchestration_templates_url(test_ot_1.id), | ||
gen_request(:copy, :content => test_content_1) | ||
) | ||
end.to change(OrchestrationTemplateCfn, :count).by(2) |
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 did it change by 2? Is it because the execution is where the lazy-evaluated test_ot_1
gets created? For this reason I think it's better to avoid let
s and create everything you are going to test in the setup phase in the body of the test. Duplication is OK in tests and can improve readability
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 will change it.
expect do | ||
run_post( | ||
orchestration_templates_url(test_ot_1.id), | ||
gen_request(:copy, :content => test_content_1) |
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 test doesn't make clear the value of this feature. Can you already exercise this behavior by creating an orchestration template (via POST/create) with the attributes specified?
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 believe it will save you from entering a new name, description and type. Also, we have the possibility to copy an orchestration template via UI, so it better to have such possibility via API.
I believe @chriskacerguis can explain the intention after this feature in the context of self-service.
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.
@cynepco3hahue that's fine, but you are essentially only exercising behavior we already have through POST/create in this test - can you update to verify the copying of existing attributes works?
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.
oh sure I will add it
raise "uknown attribute #{attr}" | ||
end | ||
end | ||
new_resource.tap(&:save!) |
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.
Is the tap
necessary?
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.
yes if you want to return the object
bf7c315
to
f65199c
Compare
api_basic_authorize collection_action_identifier(:orchestration_templates, :copy) | ||
|
||
expected = { | ||
'content' => test_content_1 |
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.
Can you verify that you don't get the id/href back of the original?
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 will add the verification for id, but adding verification for the href a little bit problematic, FactorGirl OrchestrationEntity does not have the href.
I believe to check only id's good enough for test purpose.
What do you think?
f65199c
to
0d92e65
Compare
@@ -125,4 +125,70 @@ | |||
expect(OrchestrationTemplate.exists?(hot.id)).to be_falsey | |||
end | |||
end | |||
|
|||
context 'orchestration template copy' do | |||
it 'copy template with the same content' do |
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.
Can you make these fully descriptive and full sentences (including the "it") so something like "it will not copy a template with no attributes specified" or similar...
|
||
context 'orchestration template copy' do | ||
it 'copy template with the same content' do | ||
test_ot_1 = FactoryGirl.create(:orchestration_template_cfn) |
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.
It should be clear that this is a test.... perhaps simply "orchestration_template" or "orchestration_template_1" for these variables?
it 'copy template with the same content' do | ||
test_ot_1 = FactoryGirl.create(:orchestration_template_cfn) | ||
|
||
api_basic_authorize collection_action_identifier(:orchestration_templates, :copy) |
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 be consistent with spacing can you try to group lines that belong to each phase of the test, i.e. all setup steps together, all execution steps, all verification steps, etc...
|
||
it 'copy single template with the different content' do | ||
test_ot_1 = FactoryGirl.create(:orchestration_template_cfn) | ||
test_content_1 = "{ 'Description': 'Test content 1' }\n" |
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 curious as to why this doesn't get deserialized by Rails when you call response.parsed_body
?
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 think it because we add new line in the orchestration template by intention(I can see it from code)
text.encode(:universal_newline => true).chomp.concat("\n")
0d92e65
to
067204e
Compare
@@ -125,4 +125,83 @@ | |||
expect(OrchestrationTemplate.exists?(hot.id)).to be_falsey | |||
end | |||
end | |||
|
|||
context 'orchestration template copy' do | |||
before do |
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.
before
s, like let
s, are best for details which are necessary but not relevant to understanding the behavior being exercised. Since both these objects are central, I'd resist the urge to DRY up here and allow a little duplication for the sake of readability
api_basic_authorize collection_action_identifier(:orchestration_templates, :copy) | ||
|
||
orchestration_template_2 = FactoryGirl.create(:orchestration_template_cfn) | ||
new_content_2 = "{ 'Description': 'Test content 2' }\n" |
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.
Again, I'm curious as to why this doesn't get parsed/deserialized. Does { "description" => "Test content 2" }
work?
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 think it because we add new line in the orchestration template by intention(I can see it from code)
text.encode(:universal_newline => true).chomp.concat("\n")
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.
Could this cause issues with consuming/parsing this API? @abellotti any thoughts here?
067204e
to
8206426
Compare
@imtayadeway @jntullo Can you please review again? |
1 similar comment
@imtayadeway @jntullo Can you please review again? |
def copy_resource(type, id, data = {}) | ||
klass = collection_class(type) | ||
resource = resource_search(id, type, klass) | ||
new_resource = resource.dup |
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.
rather than using .tap(&:save!)
below, you can just tap the whole thing.
resource.dup.tap do |new_resource|
new_resource.assign_attributes(data)
new_resource.save!
end
8206426
to
139fc1b
Compare
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.
minor changes requested, otherwise I'm 👍 with this. Thanks.
|
||
def copy_resource(type, id, data = {}) | ||
klass = collection_class(type) | ||
resource = resource_search(id, type, klass) |
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.
can combine the above 2 lines,
resource = resource_search(id, type, collection_class(type))
new_resource.save! | ||
end | ||
rescue => err | ||
raise BadRequestError, "Failed to copy #{klass} - #{err}" |
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.
would prefer english instead of klass/type.
... "Failed to copy orchestration template - #{err}"
@cynepco3hahue can you take care of pending requests above? Thanks! |
For the SSUI we need to have possibility to copy OrchestrationTemplate via API
139fc1b
to
d3aeb20
Compare
Checked commit cynepco3hahue@d3aeb20 with ruby 2.2.5, rubocop 0.37.2, and haml-lint 0.16.1 |
LGTM!! |
For the SSUI we need to have possibility to copy OrchestrationTemplate via API