Skip to content

EC2: Properly handle disableApiStop in instance lifecycle #8610

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

Merged
merged 3 commits into from
Feb 20, 2025

Conversation

anisaoshafi
Copy link
Contributor

Hi moto team 👋🏼

I'm opening this PR to tacke these two issues:

  • The EC2 parameterDisableApiStop is not propagated when running an instance, instead uses default (DisableApiStop=False).
    This leads to inconsistencies when trying to create ec2 instances with localstack with terraform & pulumi, due to these changes not being stored in the instance so these IAC detect changes and modify the instance when running corresponding iac scripts.

  • On the other side, took advantage to throw the corresponding exception when trying to stop an ec2 instance that was created with DisableApiStop=True as that was not handled.

@@ -143,7 +144,7 @@ def __init__(
self.virtualization_type = ami.virtualization_type if ami else "paravirtual"
self.architecture = ami.architecture if ami else "x86_64"
self.root_device_name = ami.root_device_name if ami else None
self.disable_api_stop = False
self.disable_api_stop = kwargs.get("disable_api_stop", False)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make sure this is coerced to an actual boolean value? It's confusing that the default value is False but when you check if it's enabled you compare with == "true" instead of is True.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually followed the same approach as for disable_api_termination:

for some reason when I coerce disable_api_stop to bool with _convert_to_bool(), the test starts failing even though it should be straightforward 🤔
unless I'm doing sth wrong in the test or elsewhere. Could you please help me figure out if I'm missing sth?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This attribute is always coerced to a string, if supplied. If we want Moto to always handle this as a boolean, we need to make changes in quite a few places:

  1. run_instances() - that's the easiest one, as it can use _get_bool_param
  2. modify_instance_attribute(Attribute="disableApiStop", Value="false") - more difficult, as we currently treat all attributes (strings and booleans) the same
  3. modify_instance_attribute(DisableApiStop={"Value": True}) - same logic, different code path
  4. describe_instance_attribute - the response needs custom logic to convert True to 'true' and False to 'false' iff we're describing a boolean attribute

The last point was why you we're getting an error @anisaoshafi. boto3 expects a lower-case true in the responses, so if Moto returns <value>True</value>, boto3 interprets that as a False-value.

Now, ideally, if we're going to handle this attribute as a boolean, we should handle all boolean attributes as such. The other ones are: SourceDestCheck, DisableApiTermination, EbsOptimized, EnaSupport.

Which leads to another change:
5. Change describe_instances(filters=[{"Name": "source-dest-check", "Values": ["false"]}]) (and other boolean filters like it) to convert the incoming values

So in short - should it be a boolean? Yes absolutely. Do we want to do it as part of this PR? Probably not, because the list of changes is quite large, and I'm not sure if we have the test coverage for all corner cases. So I vote to merge this as-is for now, and classify this as techdebt.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pushed a commit with a few more assertions, just to verify all possible scenarios currently pass. This should come in handy if/when we tackle this techdebt.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the very thorough clarification, @bblommers. This seems like an interesting problem, and agree that it's out of the scope of this PR.

I really appreciate that you added the extra assertions 🙏🏼 hope all the checks pass, otherwise I can handle the needed adjustments 🤞🏼

@anisaoshafi anisaoshafi force-pushed the fix-ec2-disable-api-stop branch from 277badc to 68c71be Compare February 20, 2025 00:38
Copy link

codecov bot commented Feb 20, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.71%. Comparing base (9e8bc74) to head (b374b12).
Report is 2 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #8610   +/-   ##
=======================================
  Coverage   92.71%   92.71%           
=======================================
  Files        1242     1242           
  Lines      107614   107624   +10     
=======================================
+ Hits        99773    99783   +10     
  Misses       7841     7841           
Flag Coverage Δ
servertests 28.21% <50.00%> (+<0.01%) ⬆️
unittests 92.68% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@anisaoshafi anisaoshafi requested a review from bpandola February 20, 2025 09:34
@bblommers bblommers self-assigned this Feb 20, 2025
@bblommers bblommers force-pushed the fix-ec2-disable-api-stop branch from e962afd to b374b12 Compare February 20, 2025 12:48
Copy link
Collaborator

@bblommers bblommers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the checks pass, so this LGTM. Thanks for the PR @anisaoshafi, and welcome to Moto! 😄

@bblommers bblommers added this to the 5.0.29 milestone Feb 20, 2025
@bblommers bblommers merged commit d8a9bcc into getmoto:master Feb 20, 2025
56 checks passed
@anisaoshafi
Copy link
Contributor Author

All the checks pass, so this LGTM. Thanks for the PR @anisaoshafi, and welcome to Moto! 😄

Thanks a lot, Bert and Brian for the quick reviews and support in merging this! 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants