Reworking a few AWS modules...looking for advice

Ahoy,
I’m new to this list, so apologies if I violate convention (let me know).

I’ve been working happily with Ansible for a while, but I’ve found many AWS modules behave in unexpected ways. Many are excellent, but there seems to be a consistency issue.

It’s become awkward enough that I just want to replace a few small parts, but I would like to architect them “The Right Way”, to avoid problems down the line, in the off-chance that they end up used by folks or even making it back to core somehow.

PLEASE give me some ideas / feedback on what would work best if you were designing the modules, or problems you’ve run into / solved if you already worked on them.

Current Problems

  1. Inconsistency w/ other ansible modules / conventions - e.g. many modules don’t offer ‘state’, ‘name’ and other common options
  2. Nonidempotency - some modules are nonidempotent without a clear reason why, or require you to hardcode a command/action rather than using state (e.g. rds module has command: create, command: replicate)
  3. Inconsistency between AWS modules (e.g. ec2 module allows creating attached volumes, but the volume options are different than provided ec2_vol module options)
  4. Inconsistency with AWS APIs / boto
  5. Inconsistency of module behavior internally for a module task, based on options set (e.g. running ec2 module with exact_count set dramatically changes how the task behaves)
  6. Feature gaps - fat modules focused on individual AWS products, seem to make it difficult to perform some actions involving relationships between products. It’s surprisingly difficult to do things like modify the security groups of a VPC instance, etc.
  7. Large, complex tasks - modules take a lot of options and do many things, leading to confusion, and return values for register variables end up chubby as well
  8. There isn’t really a good, unified way to target instances of products (like ec2 instances, ELB, etc) that already exist to perform actions on them or to relate them to other instances.

Ideas

Here’s my initial idea. Tell me if it’s dumb, and why.

  1. Start by stealing a few ideas from boto / cli to apply to new modules, such as Filter to select instances to apply tasks to
  2. Create a handful of small tasks that perform very specific functions, e.g. - ec2_security_group_assignment: state=present name=ssh-enabled tag_filter: [ Name: linux-boxes ]
  3. Always use ‘state’ / ‘name’ and other common features in modules if possible.
  4. Always do idempotent actions if possible.
  5. Use more tasks and smaller tasks. (e.g. require - ec2_instance_option: termination_protection=yes instead of providing it as option in ec2 module?).
  6. Any task that creates / destroys should have the smallest set of options possible, and more detailed configuration should require selection using instance id or filter or whatever.
  7. Eventually, maybe allow fat tasks to execute smaller tasks for convenience?

Caveats

  1. I’m not really totally happy with any options I have thought up for dealing with idempotency for AWS.
  2. It will take me forever to rewrite any useful number of AWS ansble modules. I have almost no time for it and would only be working on scratching the itches that bother me most. Also, I am still a bit baffled by some parts of boto since the switch to boto3
  3. I plan on releasing modules on github. I do not plan on trying to get them into ansible core.

Anyway, any better ideas for AWS modules?

Ahoy,
I’m new to this list, so apologies if I violate convention (let me know).

I’ve been working happily with Ansible for a while, but I’ve found many AWS modules behave in unexpected ways. Many are excellent, but there seems to be a consistency issue.

It’s become awkward enough that I just want to replace a few small parts, but I would like to architect them “The Right Way”, to avoid problems down the line, in the off-chance that they end up used by folks or even making it back to core somehow.

PLEASE give me some ideas / feedback on what would work best if you were designing the modules, or problems you’ve run into / solved if you already worked on them.

Current Problems

  1. Inconsistency w/ other ansible modules / conventions - e.g. many modules don’t offer ‘state’, ‘name’ and other common options
  2. Nonidempotency - some modules are nonidempotent without a clear reason why, or require you to hardcode a command/action rather than using state (e.g. rds module has command: create, command: replicate)
  3. Inconsistency between AWS modules (e.g. ec2 module allows creating attached volumes, but the volume options are different than provided ec2_vol module options)
  4. Inconsistency with AWS APIs / boto
  5. Inconsistency of module behavior internally for a module task, based on options set (e.g. running ec2 module with exact_count set dramatically changes how the task behaves)
  6. Feature gaps - fat modules focused on individual AWS products, seem to make it difficult to perform some actions involving relationships between products. It’s surprisingly difficult to do things like modify the security groups of a VPC instance, etc.
  7. Large, complex tasks - modules take a lot of options and do many things, leading to confusion, and return values for register variables end up chubby as well
  8. There isn’t really a good, unified way to target instances of products (like ec2 instances, ELB, etc) that already exist to perform actions on them or to relate them to other instances.

Ideas

Here’s my initial idea. Tell me if it’s dumb, and why.

  1. Start by stealing a few ideas from boto / cli to apply to new modules, such as Filter to select instances to apply tasks to
  2. Create a handful of small tasks that perform very specific functions, e.g. - ec2_security_group_assignment: state=present name=ssh-enabled tag_filter: [ Name: linux-boxes ]
  3. Always use ‘state’ / ‘name’ and other common features in modules if possible.
  4. Always do idempotent actions if possible.
  5. Use more tasks and smaller tasks. (e.g. require - ec2_instance_option: termination_protection=yes instead of providing it as option in ec2 module?).
  6. Any task that creates / destroys should have the smallest set of options possible, and more detailed configuration should require selection using instance id or filter or whatever.
  7. Eventually, maybe allow fat tasks to execute smaller tasks for convenience?

Caveats

  1. I’m not really totally happy with any options I have thought up for dealing with idempotency for AWS.
  2. It will take me forever to rewrite any useful number of AWS ansble modules. I have almost no time for it and would only be working on scratching the itches that bother me most. Also, I am still a bit baffled by some parts of boto since the switch to boto3
  3. I plan on releasing modules on github. I do not plan on trying to get them into ansible core.

Anyway, any better ideas for AWS modules?

You’re really welcome to do as you choose if you don’t want to get your modules into core. That is the upside - the downside is fewer eyes, fewer contributions, and more work for you.
There has been a bit of a philosophical discussion about the approach you suggest on the new ecs_attribute module (https://github.com/ansible/ansible/pull/20618) - whether changing one property of a resource is desirable or whether we should model the resource as a whole.

I’m doing a lot more work on the AWS modules recently - I’m keen to ensure that we improve and augment the existing modules. Some of our modules are older than others (e.g. the RDS module needs a complete rewrite, which is in progress). I’m also keen to help anyone get modules that they need in, as long as they’re broadly useful.

I’m also happy for improvements that address legacy issues with modules - certainly any modules missing state or name should be considered a bug, some of which will be easier to fix than others (again, RDS needs a rewrite to get a useful version of state)

It’s surprisingly difficult to do things like modify the security groups of a VPC instance, etc.

It is? Is that because of flaws in the ec2 module and because you have to pass a bunch of parameters so as not to affect things in the instance other than the SG?

My closing thoughts are that the AWS modules aren’t perfect, and could be more consistent, because of the huge community behind them - but that’s their greatest strength too. In addition to work on new features and bug fixes, we’ll endeavour to improve consistency and perhaps even break up some of the more monolithic modules (e.g. ec2) along the lines of how ec2_vpc turned into lots of smaller ec2_vpc_ module. Any suggestions on that direction would be welcome.

Will

Hey Will,
Thanks for the response. I wasn’t intending to rag too hard on the AWS modules, as many are good (particularly newer ones), but it is clear that they grew pretty organically.
There are a couple of modules that I’ve essentially replaced with heavy use of blocks, when’s, and advanced queries to the aws cli using ‘command’ but this is very brittle and not very ansible-like, so these are the modules I’d like to just rewrite for my use.

I guess I’m looking for the answer to this question:
If you were to rewrite major AWS modules from scratch, what would you do differently? (in the broadest architectural sense).

Partially, I’m seeking advice because I don’t use too many AWS services, but I do heavily use ec2, s3, vpc, rds, security groups, autoscaling groups, cert manager, r53, ELB, ALB, data pipelines, and a few others, and I’m not sure if the same ideas that make sense on those modules make sense everywhere.
It’s likely that if I’m very happy with how the work turns out, I’d be interested in submitting a PR back to Ansible core, so I’d like to do things right just in case, since backwards compat is so important in Ansible. Also, if some are already being reworked, I’m very interested in following progress or helping.

Concerning your comment about modifying ec2 security groups, I don’t think it’s my fault. AFAIK, I cannot see any way to add or remove security groups to an instance after it is created. I’d love to hear otherwise!

If rewrites for major modules are already happening, or if some are planned, I’d love to help out. If you (or anyone) can point out where any of this is being discussed–IRC, other chats, PR’s, github users whose forks are used for discussions, whatever–I’d love to be around for it.

Thanks,
Jackson

We've been adding rules and normalizing module development to try to
keep a consistent interface, the problem is the existing modules
cannot easily be rewritten w/o breaking playbooks.