Hi folks, I want to ask for some advices regarding my topic.
I need to generate and deploy systemd units on remote host via pipeline
I came up with this solution, but I thinks it’s very bloated and a bit hard to read and maintain. It reads yml file and then transfer generated .service files to remote host
yml example
---
environments:
staging:
units:
- name: example
enabled: true
description: example
exec_start: example
production:
units:
- name: example
enabled: true
description: example
exec_start: example
pipeline stage
stage('Systemd Units Deployment') {
steps {
script {
sshagent(credentials: ["${BUILD_USER_SSH_CREDS}"]) {
def yamlData = readYaml file:'app/systemd_units.yaml'
def environmentData = yamlData.environments[BUILD_ENVIRONMENT]
def unitsInYaml = environmentData.units.collect { it.name }
def unixDate = sh(script: "date +%s", returnStdout: true).trim()
def tmpUnitsDir = "systemd_units_${unixDate}"
sh "mkdir ${tmpUnitsDir}"
def existingUnits = sh(script: "${SSH} ${BUILD_USER}@${SERVICE_FULL_NAME} 'ls /etc/systemd/user/*.service'", returnStdout: true).trim().split('\n').collect { it.split('/').last() }
def unitsToRemove = existingUnits.findAll { !unitsInYaml.contains(it) }
echoGreen("Deploying systemd units for environment: ${BUILD_ENVIRONMENT}")
unitsToRemove.each { unit ->
echoGreen("Removing systemd unit: ${unit} from /etc/systemd/user/")
sh """
${SSH} ${BUILD_USER}@${SERVICE_FULL_NAME} "
set -e
systemctl --user stop ${unit} || true && \
systemctl --user disable ${unit} || true && \
rm -f /etc/systemd/user/${unit} && \
systemctl --user daemon-reload
"
"""
}
environmentData.units.each { unit ->
def remoteCommand = "${SSH} ${BUILD_USER}@${SERVICE_FULL_NAME} 'cat /etc/systemd/user/${unit.name}' 2>/dev/null || echo ''"
def existingUnitContent = sh(script: remoteCommand, returnStdout: true).stripIndent()
if (unit.enabled == false) {
echoGreen("Removing systemd unit: ${unit.name} from /etc/systemd/user/")
sh """
${SSH} ${BUILD_USER}@${SERVICE_FULL_NAME} "
set -e
systemctl --user stop ${unit.name} || true && \
systemctl --user disable ${unit.name} || true && \
rm -f /etc/systemd/user/${unit.name} && \
systemctl --user daemon-reload
"
"""
} else {
def newUnitContent = """\
[Unit]
After=network.target
Description=${unit.description}
[Service]
Type=simple
ExecStart=${unit.exec_start}
Restart=always
[Install]
WantedBy=default.target
""".stripIndent()
if (existingUnitContent != newUnitContent) {
echoGreen("Adding/updating systemd unit: ${unit.name} in /etc/systemd/user/")
echo "Description: ${unit.description}"
echo "ExecStart: ${unit.exec_start}"
writeFile file: "${tmpUnitsDir}/${unit.name}", text: newUnitContent
sh """
scp -r ${tmpUnitsDir} ${BUILD_USER}@${SERVICE_FULL_NAME}:/tmp
${SSH} ${BUILD_USER}@${SERVICE_FULL_NAME} "
set -e
mv /tmp/${tmpUnitsDir}/${unit.name} /etc/systemd/user && \
systemctl --user daemon-reload && \
systemctl --user enable ${unit.name} && \
systemctl --user restart ${unit.name}
"
"""
} else {
echoGreen("Systemd unit ${unit.name} already up-to-date. Just restarting those.")
sh """
${SSH} ${BUILD_USER}@${SERVICE_FULL_NAME} "
set -e
systemctl --user restart ${unit.name}
"
"""
}
}
}
}
}
}
}
Maybe somebody can share their experience with such a task? Is my solution will work on long distances? Maybe there are some special software for that?