Ansible: "Not a tty"

When running the Andible script in Gitlab’s CI/CD, I get the following message:

fatal: [local-test]: UNREACHABLE! => {
    "changed": false,
    "msg": "(25, 'Not a tty')",
    "unreachable": true
}

gitlab-ci.yml:

test:
  stage: test
  #needs: ["build"]
  before_script:
    - apk add --update git openssh ansible && rm -rf /var/cache/apk/*
    - git clone http://oauth2:$CLONE_TOKEN@xx.xx.xx.xx:xx/xx/xxx/qa/playbook.git
  script:
    - ls
    - echo $VERSION
    - docker images
    - ansible-playbook -vvvv -i playbook/automatic-tests/inventory.yml playbook/automatic-tests/start.yml

Full log:

$ ansible-playbook -vvvv -i playbook/automatic-tests/inventory.yml playbook/automatic-tests/start.yml
ansible-playbook [core 2.13.6]
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.10/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible-playbook
  python version = 3.10.10 (main, Feb  9 2023, 02:08:14) [GCC 12.2.1 20220924]
  jinja version = 3.1.2
  libyaml = True
No config file found; using defaults
setting up inventory plugins
host_list declined parsing /builds/xxx/xxx/qa/cicd-test/backend/playbook/automatic-tests/inventory.yml as it did not pass its verify_file() method
script declined parsing /builds/xxx/xxxx/qa/cicd-test/backend/playbook/automatic-tests/inventory.yml as it did not pass its verify_file() method
Parsed /builds/xxxx/xxxxx/qa/cicd-test/backend/playbook/automatic-tests/inventory.yml inventory source with yaml plugin
redirecting (type: modules) ansible.builtin.docker_network to community.docker.docker_network
Loading collection community.docker from /usr/lib/python3.10/site-packages/ansible_collections/community/docker
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_host_info to community.docker.docker_host_info
Loading callback plugin default of type stdout, v2.0 from /usr/lib/python3.10/site-packages/ansible/plugins/callback/default.py
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.
PLAYBOOK: start.yml ************************************************************
Positional arguments: playbook/automatic-tests/start.yml
verbosity: 4
connection: smart
timeout: 10
become_method: sudo
tags: ('all',)
inventory: ('/builds/xxxxxxx/xxxxx/qa/cicd-test/backend/playbook/automatic-tests/inventory.yml',)
forks: 5
1 plays in playbook/automatic-tests/start.yml
PLAY [Create base virtual network] *********************************************
TASK [Gathering Facts] *********************************************************
task path: /builds/xxxxx/xxxxxx/qa/cicd-test/backend/playbook/automatic-tests/start.yml:1
<xx.xx.xx.xx> ESTABLISH PARAMIKO SSH CONNECTION FOR USER: root on PORT 22 TO xx.xxx.xxx.xx
<xx.xxx.xx.xx> CONNECTION: pid 68 waiting for lock on 5
<xx.xx.xx.xx> CONNECTION: pid 68 acquired lock on 5
fatal: [local-test]: UNREACHABLE! => {
    "changed": false,
    "msg": "(25, 'Not a tty')",
    "unreachable": true
}
PLAY RECAP *********************************************************************
local-test                 : ok=0    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   
ERROR: Job failed: exit code 4

How to run Ansible properly in Gitlab pipeline?

I need to run ansible playbook in CI/CD Gitlab

Ansible needs ssh to be running, so if this is running within a docker container, and the docker container doesn’t have SSH then it cannot use ssh to connect to itself over eg localhost or whatever it is resolving in your inventory. Also your become_method most likely will also ask for a password, so you need to pass the password to the playbook.

If you are using gitlab.com and their shared runners you might have issues with this. You may have to create your own Gitlab Runner, disable shared runners, and add this to your project on gitlab.com to use it and ensure that the machine, or docker setup is going to allow you to ensure SSH daemon exists and is running.

2 Likes

When starting the tests in the before_script section, I install openssh. In the plaubook there is a password and login and that it is supposed to connect using paramiko. The playbook has been manually tested outside of the container and works fine. However, when it is run using CI/CD, the error described above already appears.

You mentioned it’s supposed to connect as user “paramiko”? However, your logs show it attempting to connect as the “root” user. So I’m guessing that something is not quite right with the Ansible inventory in that the user is not specified correctly. This link has similar issues and possible solution: SSH works, but ansible throws unreachable error · Issue #15321 · ansible/ansible · GitHub

This is my inventory file:

all:
 hosts:
  local-test:
   ansible_host: 10.xxx.xxx.xxx
   ansible_connection: paramiko
   ansible_user: root
   ansible_ssh_pass: xxxxxx

I managed to turn off gethering facts. Ansible jobs started until the network was created. It seems that every operation that needs to be performed on the target server ends with this error. In addition, it is now known that the connection is established correctly.

Log:

$ ansible-playbook -vvvv -i playbook/automatic-tests/inventory.yml playbook/automatic-tests/start.yml
ansible-playbook [core 2.13.6]
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.10/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible-playbook
  python version = 3.10.11 (main, Apr  6 2023, 01:16:54) [GCC 12.2.1 20220924]
  jinja version = 3.1.2
  libyaml = True
No config file found; using defaults
setting up inventory plugins
host_list declined parsing /xxxqa/cicd-test/backend/playbook/automatic-tests/inventory.yml as it did not pass its verify_file() method
script declined parsing /builds/xxx/qa/cicd-test/backend/playbook/automatic-tests/inventory.yml as it did not pass its verify_file() method
Parsed /builds/industry4/xxxx/playbook/automatic-tests/inventory.yml inventory source with yaml plugin
redirecting (type: modules) ansible.builtin.docker_network to community.docker.docker_network
Loading collection community.docker from /usr/lib/python3.10/site-packages/ansible_collections/community/docker
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_container to community.docker.docker_container
redirecting (type: modules) ansible.builtin.docker_host_info to community.docker.docker_host_info
Loading callback plugin default of type stdout, v2.0 from /usr/lib/python3.10/site-packages/ansible/plugins/callback/default.py
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.
PLAYBOOK: start.yml ************************************************************
Positional arguments: playbook/automatic-tests/start.yml
verbosity: 4
connection: smart
timeout: 10
become_method: sudo
tags: ('all',)
inventory: ('/builds/ixxxx/qa/cicd-test/backend/playbook/automatic-tests/inventory.yml',)
forks: 5
1 plays in playbook/automatic-tests/start.yml
PLAY [Create base virtual network] *********************************************
META: ran handlers
TASK [create_container : Print all available facts] ****************************
task path: /builds/inxxxxcicd-test/backend/playbook/automatic-tests/roles/create_container/tasks/main.yml:2
ok: [local-test] => {
    "ansible_facts": {}
}
TASK [create_container : print current playbook directory] *********************
task path: /builds/ixxxx/qa/cicd-test/backend/playbook/automatic-tests/roles/create_container/tasks/main.yml:5
ok: [local-test] => {
    "playbook_dir": "/builds/ixxxxx/qa/cicd-test/backend/playbook/automatic-tests"
}
TASK [create_container : include containers variables] *************************
task path: /xxxx/qa/cicd-test/backend/playbook/automatic-tests/roles/create_container/tasks/main.yml:8
ok: [local-test] => {
    "ansible_facts": {
        "run_backend": false,
        "run_brain": false,
        "run_broker": false,
        "run_cache": false,
        "run_click": false,
        "run_datahub": false,
        "run_db": true,
        "run_elastic": false,
        "run_flik": false,
        "run_frontend": false,
        "run_gatekeeper": false,
        "run_grafana": false,
        "run_jasper": false,
        "run_keeper": false,
        "run_keycloak": false,
        "run_mq": false,
        "run_nifi": false,
        "run_opcserver": false,
        "run_opendata": false,
        "run_portainer": false,
        "run_sparkscheduler": false,
        "run_toolbox": false,
        "run_userbrain": false
    },
    "ansible_included_var_files": [
        "/builds/xxxx/qa/cicd-test/backend/playbook/automatic-tests/run_containers.yml"
    ],
    "changed": false
}
TASK [create_container : include containers images variables] ******************
task path: /buildsxxxxx/qa/cicd-test/backend/playbook/automatic-tests/roles/create_container/tasks/main.yml:10
ok: [local-test] => {
    "ansible_facts": {
        "backend_image": "{{ container_registry }}backend:latest",
        "brain_image": "{{ container_registry }}brain:latest",
        "broker_image": "{{ container_registry }}broker:latest",
        "cache_image": "{{ container_registry }}cache:latest",
        "click_image": "{{ container_registry }}click:latest",
        "client": "test1",
        "container_registry": "{{ cr_addr }}/xxxxx-",
        "cr_addr": "cr-dev.apagroup.pl:10000",
        "datahub_image": "{{ container_registry }}datahub:latest",
        "db_image": "{{ container_registry }}db:latest",
        "docker_network_name": "nazca4",
        "elastic_image": "{{ container_registry }}elastic:latest",
        "flik1_image": "{{ container_registry }}flik1:latest",
        "flik2_image": "{{ container_registry }}flik2:latest",
        "frontend_image": "{{ container_registry }}frontend:latest",
        "gatekeeper_image": "{{ container_registry }}gatekeeper:latest",
        "grafana_image": "{{ container_registry }}grafana:latest",
        "ip": "xxxxxx",
        "jasper_image": "{{ container_registry }}jasper:latest",
        "keeper_image": "{{ container_registry }}keeper:latest",
        "keycloak_image": "{{ container_registry }}keycloak:latest",
        "mq_image": "{{ container_registry }}mq:latest",
        "nifi_image": "{{ container_registry }}nifi:latest",
        "opcserver_image": "{{ container_registry }}opcserver:latest",
        "opendata_image": "{{ container_registry }}opendata:latest",
        "sparkscheduler_image": "{{ container_registry }}sparkscheduler:latest",
        "toolbox_image": "{{ container_registry }}toolbox:latest",
        "userbrain_image": "{{ container_registry }}userbrain:latest"
    },
    "ansible_included_var_files": [
        "/builds/xxxxx/qa/cicd-test/backend/playbook/automatic-tests/images_containers.yml"
    ],
    "changed": false
}
TASK [create_container : Create a network nazca4] ******************************
task path: /builds/xxxxx/qa/cicd-test/backend/playbook/automatic-tests/roles/create_container/tasks/main.yml:12
redirecting (type: modules) ansible.builtin.docker_network to community.docker.docker_network
<xxx> ESTABLISH PARAMIKO SSH CONNECTION FOR USER: root on PORT 22 TO xxxxx
<xxxxx> CONNECTION: pid 57 waiting for lock on 5
<xxxxxx> CONNECTION: pid 57 acquired lock on 5
fatal: [local-test]: UNREACHABLE! => {
    "changed": false,
    "msg": "(25, 'Not a tty')",
    "unreachable": true
}
PLAY RECAP *********************************************************************
local-test                 : ok=4    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   
ERROR: Job failed: exit code 4