pipeline { agent any // Define parameters parameters { string(name: 'host_ip', description: 'Target System Address') choice(name: 'new_hostname', choices: ['MC-Friendly', 'MC-NanoPi2a', 'MC-NanoPi2b', 'MC-NanoPi2c', 'MC-ZeroPi2', 'MC-RickyPi' ], description: 'Select Hostname for VPN config') // string(name: 'new_hostname', description: 'New Hostname, must match valid CN for VPN') booleanParam(name: 'onboard_pi', defaultValue: true, description: 'Check this option to onboard a new FriendlyElec Device') booleanParam(name: 'redirect_all', defaultValue: false, description: 'Redirect all traffic through VPN') } environment { ANSIBLE_FORCE_COLOR = '1' cosmos_password = credentials('cosmos_password') cosmos_root_password = credentials('cosmos_root_password') matt_public_key = credentials('matt_public_key') jenkins_public_key = credentials('jenkins_public_key') } options { ansiColor('xterm') } stages { stage('Inject Auth Key') { when { expression { params.onboard_pi } } steps { script{ // clear ssh keys echo "Target IP: ${params.host_ip}" sh """ ssh-keygen -f "/root/.ssh/known_hosts" -R "${params.host_ip}" """ sh """ echo Copy public key to pi home dir sshpass -p 'pi' ssh -o StrictHostKeyChecking=no pi@${params.host_ip} "echo ${env.jenkins_public_key} > /home/pi/authorized_keys" """ sh """ echo Make sure /root/.ssh exists sshpass -p 'pi' ssh -o StrictHostKeyChecking=no pi@${params.host_ip} "echo pi | sudo -S mkdir -p /root/.ssh/" """ sh """ echo Move public key to root sshpass -p 'pi' ssh -o StrictHostKeyChecking=no pi@${params.host_ip} "echo pi | sudo -S mv /home/pi/authorized_keys /root/.ssh/authorized_keys" """ sh """ echo Restrict permissions on file sshpass -p 'pi' ssh -o StrictHostKeyChecking=no pi@${params.host_ip} "echo pi | sudo -S chmod -R 600 /root/.ssh/" """ sh """ echo Set owner to root sshpass -p 'pi' ssh -o StrictHostKeyChecking=no pi@${params.host_ip} "echo pi | sudo -S chown -R root:root /root/.ssh/" """ } } } stage('Generate Inventory Files') { steps { // Generate the dynamic inventory files sh """ jenkins_group=\$(echo ${env.BUILD_USER_GROUPS} | sed 's/,/\\n/g' | grep Jenkins | head -n 1) jenkins_user=\$(echo ${env.BUILD_USER}) cd /var/jenkins_home/ansible chmod +x /var/jenkins_home/ansible/inventory/inventory.sh /var/jenkins_home/ansible/inventory/inventory.sh -s -g \$jenkins_group -u \$jenkins_user -i ${params.host_ip} vpn_ip=\$(cat /var/jenkins_home/ansible/roles/puck_vpn/vars/endpoints/${params.new_hostname}.yaml | grep remote_gateway | cut -d '"' -f 2) /var/jenkins_home/ansible/inventory/inventory.sh -s -g \$jenkins_group -u \$jenkins_user -i \$vpn_ip """ } } stage('Check for VPN') { steps { script { def ip = sh(script: "cat /var/jenkins_home/ansible/roles/puck_vpn/vars/endpoints/${params.new_hostname}.yaml | grep remote_gateway | cut -d '\"' -f 2", returnStdout: true).trim() echo "Detected IP: ${ip}" // Set it as an environment variable for later use env.TARGET_IP = ip def pingResult = sh(script: "ping -W .1 -i .1 -c 1 ${TARGET_IP}", returnStatus: true) // Set a variable in current build context currentBuild.description = (pingResult == 0) ? "Host is up" : "Host is down" env.HOST_UP = (pingResult == 0) ? "true" : "false" } } } stage('Ansible Playbook Pre-VPN') { when { expression { return env.HOST_UP != 'true' } } steps { //Run the cosmos-base ansible playbook // /workspace/ansible/playbooks/cosmos-base.yaml sh """ echo ${params.host_ip} hash=\$(echo -n ${params.host_ip} | md5sum | cut -c 1-8) inventory_file="/var/jenkins_home/ansible/.inv/inventory-\$hash.yml" cd /var/jenkins_home/ansible ansible-playbook -i \$inventory_file /var/jenkins_home/ansible/playbooks/puck_vpn.yaml \ --ssh-common-args='-o StrictHostKeyChecking=no' \ --extra-vars "new_hostname=${params.new_hostname} matt_public_key='${env.matt_public_key}' \ cosmos_password='${env.cosmos_password}' cosmos_root_password='${env.cosmos_root_password}' \ redirect_all=${params.redirect_all} " """ } } stage('Ansible Playbook Post-VPN') { steps { script { echo "Waiting for reboot" def ip = sh(script: "cat /var/jenkins_home/ansible/roles/puck_vpn/vars/endpoints/${params.new_hostname}.yaml | grep remote_gateway | cut -d '\"' -f 2", returnStdout: true).trim() echo "Detected IP: ${ip}" def timeoutSeconds = 300 // Total timeout: 5 minutes def waitInterval = 5 // Wait 5 seconds between pings def startTime = System.currentTimeMillis() def responded = false while ((System.currentTimeMillis() - startTime) < (timeoutSeconds * 1000)) { def status = sh(script: "ping -c 1 ${ip}", returnStatus: true) if (status == 0) { responded = true echo "IP ${ip} is now responding to ping." break } // echo "Waiting for ${ip} to respond to ping..." sleep(waitInterval) } } //Run the cosmos-base ansible playbook // /workspace/ansible/playbooks/cosmos-base.yaml sh """ vpn_ip=\$(cat /var/jenkins_home/ansible/roles/puck_vpn/vars/endpoints/${params.new_hostname}.yaml | grep remote_gateway | cut -d '"' -f 2) echo \$vpn_ip hash=\$(echo -n \$vpn_ip | md5sum | cut -c 1-8) inventory_file="/var/jenkins_home/ansible/.inv/inventory-\$hash.yml" cd /var/jenkins_home/ansible ansible-playbook -i \$inventory_file /var/jenkins_home/ansible/playbooks/puck_routing.yaml \ --ssh-common-args='-o StrictHostKeyChecking=no' """ } } } post { always { // Remove dynamic Inventory files sh """ hash=\$(echo -n "${params.host_ip}" | md5sum | cut -c 1-8) inventory_file="/var/jenkins_home/ansible/.inv/inventory-\$hash.yml" rm \$inventory_file vpn_ip=\$(cat /var/jenkins_home/ansible/roles/puck_vpn/vars/endpoints/${params.new_hostname}.yaml | grep remote_gateway | cut -d '"' -f 2) hash=\$(echo -n "\$vpn_ip" | md5sum | cut -c 1-8) inventory_file="/var/jenkins_home/ansible/.inv/inventory-\$hash.yml" rm \$inventory_file || true """ } } }