pythondockerjenkinsansiblejenkins-plugins

install ansible in official jenkins docker container without rebuild?


I've been setting up the official Jenkins docker container in my lab, and I'm installing Ansible (and also Python if possible) as plugins.

I've installed the Ansible plugin and I need to setup/install the binary. I'm trying to utilise the functionality to "Install plugin via script" which I think builds and installs at container runtime.

Any idea how I can achieve this?

I have seen many guides for rebuilding the container with Ansible installed inside, but is there any advice on how to use the function to install Ansible executable via the plugin?

I'm not looking to build a new container.


Solution

  • Well I figured it out. I'm no genius but I'm disappointed that nobody even tried to volunteer an answer, I see that increasingly more on this community, people responding with "WHY do you want to do this? Justify your reason?" rather than simply helping. Much smarter people than me, but eh.

    I hope this answer helps someone else.

    Anyway, I used the SSH Pipeline Steps Plugin to connect Jenkins to its own Docker host using SSH, and using Docker Exec, tell the Jenkins Container to install Ansible and Python3.

    I setup ssh Credentials in [Jenkins] > [Manage Jenkins] > [Manage Credentials] and add them there (I tried Keys but didn't work at first so I'll do that later so this is with user/password).

    Next I made sure to have the SSH Pipeline Steps Plugin installed. I also have the Startup Trigger Plugin to set this Pipeline to run at Jenkins startup, so it always runs nicely.

    If you edit line 47, you can add more packages than just Ansible. If you are using the Alpine version of the Jenkins container, be sure to use apk update && apk add ansible instead of using apt.

    You can also do this directly by running on your docker host: docker exec --user root Jenkins bash -c "command -v ansible >/dev/null 2>&1 || (apt update && apt install -y ansible)" but this is Jenkins SO WHY WOULD I NOT AUTOMATE IT.

    I setup a new 2-stage Jenkins Pipeline:

    //Setup Remote for SSH Pipeline Steps Plugin
    def remote = [:]
    remote.name = "dockerhost"
    remote.host = "dockerhost.local"
    remote.allowAnyHosts = true
    
    pipeline {
        agent any
        environment {
            //Declare Credentials for Remote
            SERVER_CREDS=credentials('dockerhost-ssh-pw')
        }
    
        stages {
            stage('Check Ansible Installation') {
                steps {
                    script {
                        //credentials for SSH Pipeline Steps Plugin
                        remote.user=env.SERVER_CREDS_USR
                        remote.password=env.SERVER_CREDS_PSW
                        //check if ansible is installed
                        echo "Checking if Ansible is installed on Jenkins..."
                        //check is marked to always return true, otherwise will stop pipeline
                        def response1 = sshCommand remote: remote, command: "docker exec --user root Jenkins which ansible || true"
                        // Store response1 in a global variable for later use
                        currentBuild.description = response1.trim()
                        echo "Response from Jenkins: ${response1}"
                    }
                }
            }
            stage('Installation State') {
                steps {
                    script {
                        //credentials for SSH Pipeline Steps Plugin
                        remote.user=env.SERVER_CREDS_USR
                        remote.password=env.SERVER_CREDS_PSW
                        // Use the output from the first stage
                        def stage1Response = currentBuild.description
                        
                        echo "If empty, not installed: ${stage1Response}"
    
                        // Conditional logic based on response
                        if (stage1Response == "/usr/bin/ansible") {
                            echo "Ansible is installed!"
                        } else {
                            echo "Unexpected response! Installing Ansible!"
                            def response2 = sshCommand remote: remote, command: 'docker exec --user root Jenkins bash -c "command -v ansible >/dev/null 2>&1 || (apt update && apt install -y ansible)"'
                        }
                        echo "Ansible Installed!"
                    }
                }
            }
        }
    }
    

    If this helped you, an upvote is appreciated. 👌