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

Dock Command does not install correctly, causing the dock commands to skip #79

Open
gregorskii opened this issue Jul 5, 2023 · 6 comments

Comments

@gregorskii
Copy link

I am finding that installing the fork of the brew package does not work on my machine as it seems to require the sudo password to link correctly. I have to remote desktop into the node uninstall the dockutil command and reinstall it with interactivity, when I do tha it prompts for my password and installs correctly.

Any ideas? Anyone experiencing this?

@supercoffee
Copy link

I also have the same issue. It seems that the install step when run by ansible downloads dockutil to /opt/homebrew/Caskroom but does not symlink it. Possibly the interactive password step is breaking something. Everything works as expected if I uninstall and reinstall dockutil from the machine's local terminal.

@supercoffee
Copy link

@gregorskii I think I've figured it out.

When installing homebrew casks via the homebrew role, the sudo password is specified as an ansible variable.

- name: Install configured cask applications.
      homebrew_cask:
        name: "{{ item.name | default(item) }}"
        state: present
        install_options: "{{ item.install_options | default('appdir=' + homebrew_cask_appdir) }}"
        accept_external_apps: "{{ homebrew_cask_accept_external_apps }}"
        sudo_password: "{{ ansible_become_password | default(omit) }}"
      loop: "{{ homebrew_cask_apps }}"
      notify:
        - Clear homebrew cache

However, when using the dock role to install dockutil, no sudo password is specified.

- name: Install dockutil.
  community.general.homebrew_cask:
    name: "{{ dockutil_homebrew_cask }}"
    state: present
  notify:
    - Clear homebrew cache
  when: dockutil_install
  tags: ['dock']

When I first attempt to run the playbook with dockutil tasks on a remote machine, it hangs on the install step (presumably waiting for a sudo password that never gets inputted.
The second time I run the playbook, it skips over a bunch of items then fails with a cryptic permission error.

TASK [geerlingguy.mac.dock : See if TV is in the Dock.] *****************************************************************************************************************************************************************************
ok: [remote-mac.lan.example.com]

TASK [geerlingguy.mac.dock : Ensure Dock item TV is removed.] ***********************************************************************************************************************************************************************
skipping: [remote-mac.lan.example.com]

TASK [geerlingguy.mac.dock : Pause for 7 seconds between dock changes.] *************************************************************************************************************************************************************
skipping: [remote-mac.lan.example.com]

TASK [geerlingguy.mac.dock : Ensure required dock items exist.] *********************************************************************************************************************************************************************
included: /Users/myuser/.ansible/collections/ansible_collections/geerlingguy/mac/roles/dock/tasks/dock-add.yml for remote-mac.lan.example.com => (item={'name': 'Settings', 'path': '/Applications/System Settings.app/', 'pos': 2})
included: /Users/myuser/.ansible/collections/ansible_collections/geerlingguy/mac/roles/dock/tasks/dock-add.yml for remote-mac.lan.example.com => (item={'name': 'Firefox', 'path': '/Applications/Firefox.app/', 'pos': 3})
included: /Users/myuser/.ansible/collections/ansible_collections/geerlingguy/mac/roles/dock/tasks/dock-add.yml for remote-mac.lan.example.com => (item={'name': 'Firefox Developer Edition', 'path': '/Applications/Firefox Developer Edition.app/', 'pos': 4})
included: /Users/myuser/.ansible/collections/ansible_collections/geerlingguy/mac/roles/dock/tasks/dock-add.yml for remote-mac.lan.example.com => (item={'name': 'WebStorm', 'path': '/Applications/WebStorm.app/', 'pos': 5})
included: /Users/myuser/.ansible/collections/ansible_collections/geerlingguy/mac/roles/dock/tasks/dock-add.yml for remote-mac.lan.example.com => (item={'name': 'Datagrip', 'path': '/Applications/DataGrip.app/', 'pos': 7})
included: /Users/myuser/.ansible/collections/ansible_collections/geerlingguy/mac/roles/dock/tasks/dock-add.yml for remote-mac.lan.example.com => (item={'name': 'Iterm', 'path': '/Applications/Iterm.app/', 'pos': 8})
included: /Users/myuser/.ansible/collections/ansible_collections/geerlingguy/mac/roles/dock/tasks/dock-add.yml for remote-mac.lan.example.com => (item={'name': 'screenshots', 'path': '~/Pictures/screenshots/'})
included: /Users/myuser/.ansible/collections/ansible_collections/geerlingguy/mac/roles/dock/tasks/dock-add.yml for remote-mac.lan.example.com => (item={'name': 'Downloads', 'path': '~/Downloads/'})

TASK [geerlingguy.mac.dock : See if Dock item Settings exists.] *********************************************************************************************************************************************************************
ok: [remote-mac.lan.example.com]

TASK [geerlingguy.mac.dock : Get current dock section from output.] *****************************************************************************************************************************************************************
skipping: [remote-mac.lan.example.com]

TASK [geerlingguy.mac.dock : Ensure Dock item Settings exists.] *********************************************************************************************************************************************************************
fatal: [remote-mac.lan.example.com]: FAILED! => changed=false 
  cmd: dockutil --add '/Applications/System Settings.app/' --label Settings
  msg: '[Errno 13] Permission denied: b''dockutil'''
  rc: 13
  stderr: ''
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>

When I log into the remote machine locally, I see that homebrew shows dockutil as installed, but running dockutil results in "command not found" indicating that homebrew didn't finish installing it. (Presumably because the first run hung up on the sudo password step.)

If I uninstall and reinstall dockutil on the machine locally and input the sudo password, then the dock role runs correctly.

So, I think the workaround here is to install dockutil by adding it to homebrew_cask_apps installed by the homebrew role since that role correctly installs casks that require sudo. Also make sure to define ansible_become_password in your inventory (see related issue)

@glennbrown
Copy link

Wanted to provide an update, I forked the repo and tried to add the sudo_password option and for the life of me I cannot get it to work. It either still prompts for the password even when specifying --ask-become-pass, if I add ansible_become_password via a lookup it will install but it won't actually create the /usr/local/bin/dockutil entry.

However putting in the homebrew_cask_apps variable and running the homebrew role like @supercoffee said it works just fine.

@glennbrown
Copy link

glennbrown commented Dec 15, 2023

Took a break and I came back and compared the homebrew code again and noticed there was a become option in the block that was being executed. I have submitted PR #84 to fix it as long with a sleep for dock position settings.

Original Code:

- name: Install dockutil.
  community.general.homebrew_cask:
    name: "{{ dockutil_homebrew_cask }}"
    state: present
  notify:
    - Clear homebrew cache
  when: dockutil_install
  tags: ['dock']

Updated code

- name: Install dockutil
  become: "{{ (homebrew_user != ansible_user_id) | bool }}"
  become_user: "{{ homebrew_user }}"
  community.general.homebrew_cask:
    name: "{{ dockutil_homebrew_cask }}"
    state: present
  notify:
    - Clear homebrew cache
  when: dockutil_install
  tags: ['dock']

I still don't fully understand why this works fine but it does.

@Kylmakalle
Copy link

Kylmakalle commented Mar 11, 2024

It looks like pathfinding is a little different for Casks and normal brew utils.
For remote systems, there's a common flaw with the way macOS handles paths. In short, ansible uses /bin/sh and macOS does not read any startup files when accessed via ssh. It will not read any files even with /bin/bash/
Back in 2021 I've encountered the same issue with remote macs and the easiest solution was hardcoding the PATH.

Today, I'm interested in local setup and I don't follow geerlingguy/mac-dev-playbook where Jeff installs dotfiles with PATH first and then runs dock setup.

I've ended up with:

  1. Installing homebrew manually.
    Pre-installing homebrew also eliminates the Homebrew version check issue

  2. Setting brew path before running dock role. For Apple Silicon it will be eval "$(/opt/homebrew/bin/brew shellenv)"

  3. appending ~/.zprofile for future use of brew and utils installed via brew.

- name: Ensure .zprofile exists
  copy:
    content: ""
    dest: "/Users/{{ lookup('env', 'USER') }}/.zprofile"
    force: no

- name: Ensure brew path in ~/.zprofile
  lineinfile:
    state: present
    path: "/Users/{{ lookup('env', 'USER') }}/.zprofile"
    line: eval "$({{ (ansible_machine == 'arm64') | ternary('/opt/homebrew', '/usr/local') }}/bin/brew shellenv)"
  tags: ['homebrew']

or a shell script

echo "Installing brew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

echo "Updating ~/.zprofile ..."
if [[ "$(uname -m)" == "arm64" ]]
then
   (echo; echo 'eval "$(/opt/homebrew/bin/brew shellenv)"') >> "${HOME}/.zprofile"
   eval "$(/opt/homebrew/bin/brew shellenv)"
else
   (echo; echo 'eval "$(/usr/local/bin/brew shellenv)"') >> "${HOME}/.zprofile"
   eval "$(/usr/local/bin/brew shellenv)"
fi

@strombringer
Copy link

I ran into a similar issue (dockutils are not working with the dock role).

I've installed brew manually on the Mac, including setting the eval "$(/opt/homebrew/bin/brew shellenv)" line in ~/.zprofile (as per instructions from installing brew).

Running a playbook remotely with the dock role fails with this error:

  msg:
    changed: false
    cmd: dockutil --find 'App Store'
    failed: false
    failed_when_result: false
    msg: '[Errno 2] No such file or directory: b''dockutil'''
    rc: 2
    stderr: ''
    stderr_lines: []
    stdout: ''
    stdout_lines: []

My workaround:

Adding the homebrew paths manually to the PATH variable:
(Thanks @Kylmakalle for the link)

  environment:
    PATH: "/opt/homebrew/bin:/opt/homebrew/sbin:{{ ansible_env.PATH }}"

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