Kormi Web Solutions
Kormi Web Solutions

Reputation: 563

Git fatal error on trying to clone directly from Ansible

I'm using ansible (Trellis) to deploy my projects.

I have a repo on github.

This is my ansible code

- name: UPDATE - Clone project files
  become: yes
  # become_user: "{{ project.user.name | default(ansible_web_user) }}"
  git:
    repo: "{{ project.git.ssh }}"
    dest: "{{ project_root }}/shared/source"
    version: "{{ project.git.branch | default('master') }}"
    accept_hostkey: "{{ project.git.accept_hostkey | default(repo_accept_hostkey | default(true)) }}"
    force: yes
    # key_file: "/root/.ssh/id_rsa.pub"
  ignore_errors: false
  no_log: false
  register: git_clone

For some days this error has appeared for no apparent reason, nothing has changed

FAILED! => {"changed": false, "cmd": "/usr/bin/git ls-remote origin -h refs/heads/master", "msg": "fatal: 'origin' does not appear to be a git repository\nfatal: Could not read from remote repository.\n\nPlease make sure you have the correct access rights\nand the repository exists.", "rc": 128, "stderr": "fatal: 'origin' does not appear to be a git repository\nfatal: Could not read from remote repository.\n\nPlease make sure you have the correct access rights\nand the repository exists.\n", "stderr_lines": ["fatal: 'origin' does not appear to be a git repository", "fatal: Could not read from remote repository.", "", "Please make sure you have the correct access rights", "and the repository exists."], "stdout": "", "stdout_lines": []}

I've tried several solutions, even removing the forwardAgent and forcing the key_file directly into the git call. It still returns an error.

But if I connect via ssh to the target machine and try to do a git clone .... everything works.

I don't understand what the problem could be.

Upvotes: 4

Views: 5121

Answers (3)

ppar
ppar

Reputation: 600

Summary

I also ran into this a few months ago:

  • Use case: application being deployed using Ansible and git, with an invocation like:
      - name: "Git clone"
        git:
          repo: "ssh://[email protected]/somewhere/something.git"
          accept_hostkey: yes
          key_file: "/foo/bar/{{ deployment_name }}/.ssh/id_rsa"
          dest: "/foo/bar/{{ deployment_name }}/foofoo/barbar"
          version: "{{ my_version }}"
    
  • Symptoms:
    • An Ansible deployment running git suddenly stopped working (after an apt-get upgrade)
    • Running git manually in the same clone works normally, problem only appears under Ansible

The root cause seems to be that Ansible is running git as root (or become_user), while the git clone on disk is (on purpose) owned by someone else.

Also, the message "'origin' does not appear to be a git repository" from git is misleading.

Debugging

I had to resort to desperate measures to uncover this, though, namely replacing /usr/bin/git with:

#!/bin/bash
mkdir -p /tmp/git-db < /dev/null || exit 1
env        < /dev/null > /tmp/git-db/git.$$.env   2> /tmp/git-db/err
echo "$@"  < /dev/null > /tmp/git-db//git.$$.args 2> /tmp/git-db/err
pwd        < /dev/null > /tmp/git-db//git.$$.pwd  2> /tmp/git-db/err
id         < /dev/null > /tmp/git-db//git.$$.id   2> /tmp/git-db/err
#sleep 3600  < /dev/null                            2> /tmp/git-db/err
exec /usr/bin/git.real "$@"

Looking at the /tmp/git-db/git.*.id files (and ps with the sleep enabled) showed that ansible was running /usr/bin/git as root. Testing git as root on the gave a clue to the workaround OP already posted:

root@foo-app01:/data/www/foo/foobar# git status
fatal: unsafe repository ('/data/www/foo/foobar' is owned by someone else)
To add an exception for this directory, call:

        git config --global --add safe.directory /data/www/foo/foobar

Reproducing the git invocation that Ansible actually chokes on produced the same broken error message we've seen:

root@foo-app01:/data/www/foo/foobar# GIT_SSH_OPTS=-o StrictHostKeyChecking=no GIT_KEY=/data/www/foo/.ssh/id_rsa /usr/bin/git.real ls-remote origin -h refs/heads/master
fatal: 'origin' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Workaround

As OP already mentioned, whitelisting the directory in the target machine's git configuration works around the issue:

(EDIT: replaced "--add" with idempotent syntax. Using --add appends redundant lines to your /root/.gitconfig on every execution (see git-config(1)).

- name: "Patch /root/.gitconfig"
  # This invocation (without --add, with the dir name twice) is idempotent
  command: |-
    git config --global safe.directory /data/www/{{ foo }}/{{ bar}} /data/www/{{ foo }}/{{ bar}}

What should work, but doesn't

A more appropriate fix would be to execute git as the user that owns the git clone directory. This should be possible with become_user, but adding the incantations to the invocation has no effect. With ...

- name: "Git clone"
  become_user: foobar
  become: true
  git:
    repo: "ssh://[email protected]/somewhere/something.git"
    accept_hostkey: yes
    key_file: "/foo/bar/{{ deployment_name }}/.ssh/id_rsa"
    dest: "/foo/bar/{{ deployment_name }}/foofoo/barbar"
    version: "{{ my_version }}"

... ansible is still executing /usr/bin/git as root, evidenced by the wrapper above. This happens on ansible 2.9 and 6.2.0 (installed using pip).

Upvotes: 4

Kormi Web Solutions
Kormi Web Solutions

Reputation: 563

Adding

- name: UPDATE - Safe Directory
  command: git config --global --add safe.directory {{ project_root }}/shared/source
  check_mode: no

and editing

- name: UPDATE - Clone project files
  # become: yes
  # become_user: "{{ project.user.name | default(ansible_web_user) }}"
  git:
    repo: "{{ project.git.ssh }}"
    dest: "{{ project_root }}/shared/source"
    version: "{{ project.git.branch | default('master') }}"
    accept_hostkey: "{{ project.git.accept_hostkey | default(repo_accept_hostkey | default(true)) }}"
    force: yes
    key_file: "/root/.ssh/id_rsa"
    update: no
  ignore_errors: false
  no_log: false
  register: git_clone

I solve the problem ;)

Upvotes: 3

VonC
VonC

Reputation: 1326596

# key_file: "/root/.ssh/id_rsa.pub"

Note, the key_file attribute of the git Ansible module is supposed to reference a private key, not the public one.

But check first the value of {{ project.git.ssh }}, to make sure it is a valid GitHub SSH URL like [email protected]:me/myRepo. If not, or if empty, that would explain the fatal: 'origin' does not appear to be a git repository error message.

Upvotes: 0

Related Questions