Skip to content
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

Python deprecation in macOS 12.3 #70

Open
o0-o opened this issue Feb 14, 2022 · 11 comments
Open

Python deprecation in macOS 12.3 #70

o0-o opened this issue Feb 14, 2022 · 11 comments

Comments

@o0-o
Copy link

o0-o commented Feb 14, 2022

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
Copy link
Owner

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
Copy link
Author

o0-o commented Feb 14, 2022

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
Copy link

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
Copy link
Author

o0-o commented May 19, 2022

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

@elliotweiser
Copy link
Owner

@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 elliotweiser reopened this May 19, 2022
@elliotweiser
Copy link
Owner

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
Copy link

@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
Copy link
Author

o0-o commented May 24, 2022

@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
Copy link
Owner

@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
Copy link

semyonf commented Jan 10, 2024

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

@guruevi
Copy link

guruevi commented Nov 15, 2024

Note that if Python3 is not bootstrapped yet on your machine, ansible.builtin.script does not work, you need to use raw:

- hosts: "..."
  gather_facts: false
  tasks:
    - name: Connect raw and install CLT if necessary
      raw: "ls -l /Library/Developer/CommandLineTools || /bin/sh <(curl -s https://raw.githubusercontent.com/palantir/jamf-pro-scripts/refs/heads/main/scripts/Install%20Xcode%20Command%20Line%20Tools.sh)"

Check the Git URL for what it actually does and cache it on your own infra if you don't trust public URL.

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

No branches or pull requests

5 participants