Fábio Caramelo
Fábio Caramelo

Reputation: 149

Running Ansible playbook with ant commands in Jenkins

I'm making a playbook to automatize a environment installation. At the moment I'm testing some scripts made by a co-worker and I just want jenkins to run ant commands to check if the scripts structure are correct. This scripts are located in the target machine, since that we just want to test them and there is no need to copy files from a machine to another if the scripts are not correct.

In my Jenkins I configured the jdk and ant version recomended to deploy the requested environment after create a parameterized fresstyle job. My task to run is:

---
- name: compile all
  shell: ant all
  args:
    chdir: "{{ env_home }}/Project/scripts"

- name: Create project tables
  shell: ant create-project-tables
  args:
    chdir: "{{ env_home }}/Project/scripts"

This is the first role containing at least one ant command to run on target. Ho ever jenkins always returns

TASK [build_all : compile all] *****************************************
task path: /opt/testes/env-deployment/roles/build_all/tasks/main.yml:2
[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{ buildPrepaidAll }}
fatal: [srv1]: FAILED! => {"changed": true, "cmd": "ant all", "delta": "0:00:00.003675", "end": "2018-11-07 15:55:15.917745", "msg": "non-zero return code", "rc": 127, "start": "2018-11-07 15:55:15.914070", "stderr": "/bin/sh: ant: command not found", "stderr_lines": ["/bin/sh: ant: command not found"], "stdout": "", "stdout_lines": []}

Jenkins does not complain about anything else, just ant command not found and if I type ant all in the same folder the command runs

Upvotes: 1

Views: 2565

Answers (2)

masseyb
masseyb

Reputation: 4150

TL;DR

Use the Ant Plugin or make sure that the ant executable is available in the ansible runtime $PATH.

Ant Plugin solution

Add Invoke Ant as a Build step of in your jobs configuration (Jenkins Ant Plugin):

add an **Invoke Ant** build step to your Jenkins job configuration

configure the ***Invoke Ant** build step

build your job

Note: this example is running on master. The ant executable is that which is defined in the Global Tool Configuration. ant is not set in the jenkins users $PATH, jenkins uses the ant executable configured for the job.

Jenkins **Global Tool Configuration**

If Jenkins is configured to build on remote nodes and if the ant installation is not available in the same location defined in the Jenkins Global Tool Configuration you need to override the ant executable location in the Node Properties > Tool Locations of the node configuration ...

node configuration <code>ant</code> executable location override

node build with overridden <code>ant</code> executable location

Ansible solution

To understand this solution you need to understand the error. Ref. your (redacted) comment:

But ant is there. If I run ant in my target machine ant would give a error because there was no build.xml on the folder, but would work nontheless. And ant env variable is set and also available in PATH. But you gave me an idea. /if the target machine has all set including ant, env var and PATH, then might be the source of the bash_profile. ...

Ansible connections are non-interactive, you can see this in the debug trace when using -vvvv with your ansible commands, a redacted example:

<172.28.128.13> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/home/bmassey/.ansible/cp/881b67b3d5 172.28.128.13 '/bin/sh -c '...'

.bash_profile commands are not executed during non-interactive logins. From man bash:

An interactive shell is one started without non-option arguments (unless -s is specified) and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option.  PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.
...
When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.

You need to ensure that the ant executable is available in the ansible executables $PATH, how you do this is irrelevant, i.e. editing a profile from which commands are executed during non-interactive shell logins or setting the environment with ansible (https://docs.ansible.com/ansible/devel/user_guide/playbooks_environment.html)

- hosts: localhost
  environment:
    PATH: '/opt/ant/apache-ant-1.10.5/bin:{{ ansible_env.PATH }}'

Without ant in the ansible executables $PATH: no <code>ant</code> in <code>$PATH</code>

With ant in the ansible executables $PATH set using ansible's environment keyword:

---

- hosts: localhost
  environment:
  - PATH: '/opt/ant/apache-ant-1.10.5/bin:{{ ansible_env.PATH }}'
  tasks:
  - name: execute ant build
    local_action:
      module: shell
      args: ant
      chdir: "{{ ansible_env.HOME }}/workspace/example"
    register: ant_build

  - debug: var=ant_build.stdout_lines

with <code>ant</code> in <code>$PATH</code>

Slightly modified ansible-playbook executed through Jenkins with ant in the ansible executables $PATH set using ansible's environment keyword:

---

- hosts: localhost
  environment:
  - PATH: '/opt/ant/apache-ant-1.10.5/bin:{{ ansible_env.PATH }}'
  tasks:
  - name: execute ant build
    local_action:
      module: shell
      args: ant
      chdir: "{{ lookup('env', 'WORKSPACE') }}"
    register: ant_build
    ...

<code>jenkins</code> -> <code>ansible</code> -> <code>ant</code> execution

Upvotes: 1

F&#225;bio Caramelo
F&#225;bio Caramelo

Reputation: 149

Thankfully to masseyb I found the problem. In my target machine I have ant installed and created the ANT_HOME and added the ANT_HOME/bin to the PATH.

However because this is declared on bash_profile jenkins does not recognize the command because it does not make the source of bash profile, so I added source {{ ansible_env.HOME }}/.bash_profile && before the ant command so jenkins user can source the environment variables necessary to run the commands

Upvotes: 0

Related Questions