elliotweiser / ansible-osx-command-line-tools

An Ansible role for installing OS X Command Line Tools
https://galaxy.ansible.com/elliotweiser/osx-command-line-tools/
MIT License
97 stars 42 forks source link

Thoughts on platform agnostic role? #42

Closed lhazlewood closed 6 years ago

lhazlewood commented 6 years ago

Hi there! Great role - thanks for providing this for the Mac community!

That said, I created this over the weekend because I had no idea your role existed already:

https://github.com/lhazlewood/ansible-role-xcode-clt

(I think the reason being is that I've always know this stuff as 'Xcode Command Line Tools' not 'OS X command line tools, so when I did a search for 'xcode' on galaxy.ansible.com I don't think your role came up. I've seen more than a few dotfiles-with-ansible projects and most always said "install Xcode command line tools first", so I thought I just had to create a role).

It wasn't a wasted effort for me since I'm new to ansible and that was my first role and I needed the learning experience.

Anyway, one of the techniques I picked up from perusing other authors' roles is some use include and only include when on the target OS. For example:

---
- include: macos.yml  # actually does idempotent xcode clt install
  when: ansible_os_family == 'Darwin'

This makes a lot of sense to me (with my still new ansible knowledge) because I'm attempting to make a 'take this machine and install everything a dev needs' role that works simultaneously on both mac and linux since I use both.

This allows the task to skip innocuously when not on mac os, but the same role can be referenced in the same 'dev machine' role and/or playbook.

Does this make sense? Or might there be another ansible best practice for targeting the same role for both mac and linux? If not, what are your thoughts on adding this technique to this role? Thanks again!

elliotweiser commented 6 years ago

Hi there! Great role - thanks for providing this for the Mac community!

You're welcome! Welcome to the Ansible community.

(I think the reason being is that I've always know this stuff as 'Xcode Command Line Tools' not 'OS X command line tools, so when I did a search for 'xcode' on galaxy.ansible.com I don't think your role came up. I've seen more than a few dotfiles-with-ansible projects and most always said "install Xcode command line tools first", so I thought I just had to create a role).

I hadn't considered that. Perhaps I should add the xcode tag to my meta/main.yml. Most of the time this role gets pulled in with Jeff Geerling's Homebrew role, so I haven't given it much thought.

Anyway, one of the techniques I picked up from perusing other authors' roles is some use include and only include when on the target OS.

Correct, that's a valid way to skip certain [collections of] tasks.

Just making sure I have the gist (feel free to correct me).

  1. You want to use this role inside a playbook that also runs against Linux hosts
  2. You are currently unable to do so.
  3. You want the role to gracefully skip the relevant installation tasks if not on MacOS instead of failing fast.

To address 1 and 2: Did you try using include_role? I believe that should respect the when directive.

https://docs.ansible.com/ansible/latest/modules/include_role_module.html

As for 3, I'm not sure I'm convinced. You're welcome to open a PR, which I'd be happy to consider.

lhazlewood commented 6 years ago

I found your role by looking at Jeff's requirements file ;)

Based on this, I will likely use that role, so this is probably a moot point, but the education process was helpful nonetheless.

As for your questions, 1 is correct, but I have no idea if this is a best practice or not. I found this helpful resource:

https://radeksprta.eu/make-ansible-playbook-distribution-agnostic/

and thought that if all roles were platform agnostic, it would reduce a lot of the conditional logic in playbook tasks on average. Based on that, yes, my request was for option 3 if this made sense. Since I'm still new to ansible, I don't know if this makes sense or is 'idiomatic' for ansible configuration.

In any event, I came across what I think is a related chicken and the egg problem - any idea how to solve the following StackOverflow question? It's not an issue for your role - but if you have any insight, I'd be grateful.

https://stackoverflow.com/questions/52044852/how-do-you-install-homebrew-with-ansible-on-mac-os-x-10-13-due-to-openssl-tls

Thanks again!

elliotweiser commented 6 years ago

As best as I can tell, it's all idiomatic Ansible. The question I think falls on who should own the responsibility of maintaining platform agnostic processes. For roles that install software that should be platform independent, e.g. Apache, Redis, Jenkins, etc., it makes sense to handle multiple platforms internally. However, for roles that only ever target one OS type, I don't think this applies.

I'm of the opinion that it shouldn't be the author or maintainer's concern to ensure that a platform-specific project is enabled to be executed in a platform-independent way. It should be up to the author/maintainer of the project who seeks to use that component in a way that is platform agnostic. Unless there is some documented Ansible best practice for role development that states "all roles should be platform agnostic", then I'd be hesitant to accept the premise.

Thanks for your interest in this role and the Homebrew role (for which I'm a co-maintainer). You have exquisite taste!

As for your stackoverflow question...

Hint: https://github.com/geerlingguy/ansible-role-homebrew/blob/master/.travis.yml#L19-L30

lhazlewood commented 6 years ago

Thanks for the reply! I can understand and respect the logic behind "that's not the role's concern". It would make things easier for playbook authors since they won't have to do conditionals, but I also understand such a thing isn't in scope for a Mac-specific role. Makes sense.

I'm super confused by your SO reply however ;)

Homebrew requires Command Line Tools to be installed first. But your code snippet shows using homebrew to upgrade OpenSSL. Upgraded Open SSL is required to interact with Ansible Galaxy to download this role and the homebrew role LOL.

Unless I'm missing something, this means that elliotweiser.osx-command-line-tools and geerlinguy.homebrew are not useful at all: If I had to install homebrew myself (which required me installing Xcode command line tools myself) then I don't need Ansible to do either, and these two roles will never be used to install either.

In other words, geerlinguy.homebrew would be used only for installing packages and the installation flow would never execute. Additionally elliotweiser.osx-command-line-tools would always skip as well since the CLT are always present. At that point there's no point in either logic/tasks being in the roles because they'll always be skipped. No?

Does that make sense? What am I missing?

elliotweiser commented 6 years ago

Unless I'm missing something, this means that elliotweiser.osx-command-line-tools and geerlinguy.homebrew are not useful at all

You are missing something.

You are assuming that the control node and the managed nodes are always the same (in this case localhost). That is generally not the case. In my experience, it is more common to use Ansible to manage the configuration of multiple remote hosts or perhaps virtual hosts. This is the specific use-case for which this role was intended, though it can be used to perform re-installs locally as well. I originally developed this role to configure a vanilla MacOS virtualbox image.

However, the Homebrew role still has utility even for the local-only use-case as it can be used to ensure a specific set of packages and casks are always installed. Successive runs of a playbook can ensure a desired end-state configuration. So the installation flow does execute, but it doesn't always change. This type of process is beneficial to run repeatedly to manage updates or to ensure that the desired state is already achieved, perhaps w/ --check.

In my experience, using Ansible to manage your local development laptop has a couple gotchas:

  1. Command-line tools are needed to install dependencies of Ansible (e.g. a C-compiler)
  2. OpenSSL version that's pre-baked into the system and used by the system Python are old.

Thus the 🐔 and 🥚 problems. Once you get past those issues, you can continue to manage your local system w/ Ansible.

lhazlewood commented 6 years ago

Ah, yes! Excellent distinction. I'm currently laser focused on a 'dotfiles'-like approach - e.g. "I just bought a Mac (or was given one by my employer) and I want to get the localhost from zero to development ready". That is control node == managed node.

And yes, I definitely agree that the homebrew role definitely makes sense for package installation even if you had to install homebrew yourself first.

Thanks so much for elucidating its benefit for the wider scope - that really makes sense.

That said, I will not be beaten! 😅 I will have my "run this one line command" solution to take a machine from nothing to fully ready with ansible soon enough. Thanks again!

lhazlewood commented 6 years ago

P.S. For context, most of this logic via bash is already done from something I've supported for a while now in https://github.com/ultimatedotfiles/strap if you're curious - I just want to remove as much bash as is possible and delegate to ansible for everything if I could.

Backstory: the referenced 'strap' project was becoming more and more complex, with yaml file support, etc, and then I came across ansible and I discovered I was building nearly the same thing, with ansible already having everything I needed while being far more established. I definitely don't want to reinvent the wheel, but instead modify strap to be the 'last mile' that gets me from zero to ansible without having to lift a finger. Fun stuff.

elliotweiser commented 6 years ago

Nice! I'd like to delve into that more! I'm glad to see someone else has taken the time to help make this easier 😄

Yeah it should totally be do-able with a single shell script. The bulk of it can live in an Ansible playbook, but the first-run initial setup would have to happen outside.

In case you were interested, I remembered answering a similar question here: https://github.com/geerlingguy/mac-dev-playbook/issues/50#issuecomment-305950747

Perhaps there are places where we can combine efforts 👍

lhazlewood commented 6 years ago

That'd be awesome - I'm happy to contribute/help in whatever way you think would be best for the ansible community. I'll get something working based on what I've learned today and then I'll ping you to see what makes the most sense.