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

Python deprecation in macOS 12.3 #70

Open o0-o opened 2 years ago

o0-o commented 2 years ago

Apple is deprecating Python 2.7 in macOS 12.3.

https://developer.apple.com/documentation/macos-release-notes/macos-12_3-release-notes

I believe this means that no version of Python will be included with stock macOS going forward. Python 3 can be installed via Xcode or Homebrew (which of course itself depends on Xcode's CLI tools), but this creates a circular dependency in this Ansible role. Since it requires Python to be available and Python now requires CLI tools.

Afaik, the only way to address this is to refactor the entire role using the raw and/or script modules and avoid relying on any data from gather_facts/setup.

Do you have any desire to undertake this? I'm afraid the role will have no feasible use beyond macOS 12.3 otherwise (please correct me if I'm missing something here).

elliotweiser commented 2 years ago

Ansible runs on Python3 for both control node and managed nodes. If not set by default, it can be configured via ansible.cfg.

The circular dependency to which you refer has always existed. This role is mainly intended for configuring machines other than the control node (if run on the control node, nothing new should happen since command line tools should already be installed).

It is certainly possible that this role needs a refactor in light of major OS updates, but I don't think it'll be for the reason you described.

o0-o commented 2 years ago

My mistake. I was under the impression that Python 3 was completely missing from macOS but I see that I do have it at /usr/bin/python3. I think I was conflating it with BASH which only ships as version 3 for licensing reasons on macOS.

Please disregard and thank you for your time responding.

EiyuuZack commented 2 years ago

Hey @elliotweiser. According to this, Ansible doesn't do anything special to validate the Python is usable, it just checks that it is present. When a playbook is run against a fresh-out-of-the-box macOS 12.3+ target, interpreter discovery returns /usr/bin/python3, which is not a valid interpreter. It is only a shim that launches an installer that itself won't complete without GUI button-clicking.

This effectively creates a circular dependency if one wants to install the Xcode CLT first thing on a fresh-out-of-the-box macOS 12.3+.

Do you have any suggestions how we should go about this?

o0-o commented 2 years ago

It would need to be refactored to only use raw, script modules to configure the host until a legitimate Python interpreter is available.

elliotweiser commented 2 years ago

@EiyuuZack @o0-o I think I need a more detailed description of your use-case.

This role has never been intended for "same node" operation. To run Ansible against the local machine, Python must be installed and useable. On MacOS, that depends on the command-line tools being installed (thus, the circular dependency).

This role has only ever been intended to configure a machine that is NOT also the control node (virtual machine on same host, remote host over SSH, etc.). The remote Python used to dispatch Ansible commands has historically been Python 2.7 (I'm not sure if/when that might have changed). Nevertheless, it was always possible to reconfigure the remote executable to a Python 3 installation via the ansible.cfg, which should work because the entire Ansible codebase is Python 3 compatible. If the Python 3 installation that's provided on the remote machine is not even usable, then that's a different story and using raw to my recollection is the only way around it. I'd be happy to look into it if this is the only way forward, or alternatively, I'll accept pull-requests.

I'm curious to hear more about your respective use-cases.

elliotweiser commented 2 years ago

Come to think of it, as @EiyuuZack indicates, if simply attempting to use /usr/bin/python3 is enough to spawn GUI actions and effectively block the execution of the rest of the role, then yes, this'll have to be fixed in order to support OS 12.3+.

EiyuuZack commented 2 years ago

@elliotweiser apologies if I wasn't clear enough.

Starting with macOS 12.3, the only Python bundled with the OS is /usr/bin/python3, which only spawns a GUI to install CLT in order for Python 3 to be actually usable.

My use case is having a remote farm of Mac mini machines. After formatting a given host, I bootstrap it using Ansible via SSH. In my playbook, one of the first tasks is to install the CLT. That tasks now fails on macOS 12.3+ because there is no longer any usable remote Python executable until the CLT are installed, which is what I am attempting to do in the first place.

Hope this clears it for you.

o0-o commented 2 years ago

@elliotweiser I can work on this if you're open to a pull request.

I have written playbooks that relied on raw to bootstrap BSD/Linux hosts with Python before. The tasks file becomes significantly longer, but you can achieve effectively the same functionality. There are 2 approaches. I can either use a series of block/rescues or rely entirely on when. The first approach is much less noisy when run against a host that is already configured, but the 2nd might be easier to read.

elliotweiser commented 2 years ago

@EiyuuZack Definitely clears it up, thank you.

@o0-o Absolutely. Please feel free to submit a PR. This will free me up to look into setting up GH Actions for this project, which is long overdue.

semyonf commented 10 months ago

In case anyone needs a workaround for this, set gather_facts: false and use ansible.builtin.script with

#!/bin/bash

if ! pkgutil --pkg-info=com.apple.pkg.CLTools_Executables; then
    touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
    clt_label=$(softwareupdate -l | grep -B 1 -E 'Command Line Tools' | awk -F'*' '/^\*/ {print $2}' | sed 's/^ Label: //' | grep -iE '[0-9|.]' | sort | tail -n1)
    softwareupdate -i "$clt_label"
    rm /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
fi