2024-11-16 22:50:41 -05:00
pipeline {
agent any
parameters {
2024-11-17 15:01:57 -05:00
string ( name: 'servicename' , description: "service name" )
2024-11-16 22:50:41 -05:00
string ( name: 'svcdesc' , description: "service description" )
2024-11-21 13:02:37 -05:00
string ( name: 'targetHost' , description: "system to live on" , defaultValue: "moloryb.lan" )
2024-11-19 11:49:50 -05:00
booleanParam ( name: 'database' , description: "service has a database" , defaultValue: true )
2024-11-17 15:01:57 -05:00
}
environment {
2024-11-21 13:02:37 -05:00
//pw_linuxserviceaccount=""
//pw_productiondatabase=""
//pw_developmentdatabase=""
//SUDOER=credentials('') //going to be set based on target host
2024-11-21 00:13:06 -05:00
SUDOERSSH = credentials ( '2c48e1a9-22b2-455c-9959-6b29e86d3fb5' )
2024-11-21 13:02:37 -05:00
JENKINS = credentials ( 'f1192e74-dfe0-402f-a189-703482d914fe' )
GITEATOKEN = credentials ( 'd0e86441-2157-405f-8539-a9a9010c6ecf' )
2024-11-17 15:01:57 -05:00
}
2024-11-16 22:50:41 -05:00
stages {
2024-11-17 16:02:56 -05:00
stage ( "environment setup" ) {
2024-11-16 22:50:41 -05:00
steps {
script {
2024-11-17 15:01:57 -05:00
if ( servicename . isEmpty ( ) ) {
error ( "servicename mandatory" )
}
if ( servicename . contains ( ' ' ) ) {
error ( "servicename cannot have spaces. try dashes." )
2024-11-16 22:50:41 -05:00
}
2024-11-17 16:02:56 -05:00
switch ( targetHost ) {
2024-11-19 11:49:50 -05:00
case "alloces.lan" :
2024-11-19 02:07:51 -05:00
SUDOER = credentials ( 'a674f816-2b35-4d60-ba60-7b66e86f3c5c' )
2024-11-21 00:13:06 -05:00
case "moloryb.lan" :
SUDOER = credentials ( '1f3b965e-bcc0-4074-99f2-b64dddbf7de7' )
2024-11-17 16:02:56 -05:00
break
default :
2024-11-19 11:49:50 -05:00
error ( "target host not recognized. btw: yes .lan, all lowercase." )
2024-11-17 16:02:56 -05:00
}
2024-11-19 11:49:50 -05:00
env . pw_linuxserviceaccount = sh ( returnStdout: true , script: "mktemp -u XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" )
2024-11-17 16:02:56 -05:00
echo env . pw_linuxserviceaccount
2024-11-19 11:49:50 -05:00
env . pw_productiondatabase = sh ( returnStdout: true , script: "mktemp -u XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" )
2024-11-17 16:02:56 -05:00
echo env . pw_productiondatabase
2024-11-19 11:49:50 -05:00
env . pw_developmentdatabase = sh ( returnStdout: true , script: "mktemp -u XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" )
2024-11-17 16:02:56 -05:00
echo env . pw_developmentdatabase
2024-11-16 22:50:41 -05:00
}
}
}
stage ( "gitea project" ) {
steps {
2024-11-17 16:02:56 -05:00
sh "" "
curl - X 'POST' \
2024-11-21 13:02:37 -05:00
'https://gitea.arg.rip/api/v1/repos/greyn/_template-service/generate' \
2024-11-17 16:02:56 -05:00
- H 'accept: application/json' \
2024-11-21 13:02:37 -05:00
- H 'Authorization: token ${env.GITEATOKEN}' \
2024-11-17 16:02:56 -05:00
- H 'Content-Type: application/json' \
- d ' {
2024-11-19 02:07:51 -05:00
"description" : "${svcdesc}" ,
"git_content" : true ,
"git_hooks" : true ,
"labels" : true ,
"name" : "${servicename}" ,
"owner" : "greyn" ,
"private" : false ,
"protected_branch" : true ,
"topics" : true ,
"webhooks" : true
} '
2024-11-17 16:02:56 -05:00
"" "
2024-11-19 02:07:51 -05:00
}
}
stage ( "jenkins pipeline" ) {
steps {
2024-11-21 13:02:37 -05:00
//the bad news is that it looks like it's not allowed to trigger just any old job remotely
//the good news is that this seems to pick it up pretty reliably
//sh """
// curl -X POST -L --user ${env.JENKINS_USR}:${env.JENKINS_PSW} \
// alloces.lan:8080/job/gitea.arg.rip/build
// """
2024-11-19 02:07:51 -05:00
timeout ( time: 5 , unit: 'MINUTES' ) {
sh "" "
strRes = ""
2024-11-21 13:02:37 -05:00
while [ - z "\$strRes" ] ;
2024-11-19 02:07:51 -05:00
do
sleep 5 ;
2024-11-27 15:39:21 -05:00
curl - X GET - s - u $ { env . JENKINS_USR } : '${env.JENKINS_PSW}' \
alloces . lan : 8080 /job/ gitea . arg . rip /api/ json > f . json
strRes = \ $ ( jq '.jobs' f . json | jq '.[] | select(.name==\"${env.servicename}\")' )
rm f . json
2024-11-19 02:07:51 -05:00
done
"" "
2024-11-17 23:25:14 -05:00
}
2024-12-01 19:02:17 -05:00
withCredentials ( [ sshUserPrivateKey ( credentialsId: 'f42347e9-e3b5-44af-a1af-c5e7b9775fee' , keyFileVariable: 'PK' ) ] ) {
sh "" " # ! /bin/ bash
2024-11-19 02:07:51 -05:00
2024-12-01 19:02:17 -05:00
# mkdir - p ~ / . ssh
# ssh - keyscan - t ed25519 gitea . arg . rip > > ~ /.ssh/ known_hosts
# cat ~ /.ssh/ known_hosts
# shit doesn ' t work . ssh in , git clone , get your shit set up for keys .
git - c core . sshCommand = "ssh -i '$PK'\" clone ssh: //git@gitea.arg.rip:8022/greyn/${servicename}.git
# fyi , future me: pushd is useless here , it pops out . Like it ' s loading a script and exiting .
2024-11-17 23:25:14 -05:00
"" "
2024-11-19 11:49:50 -05:00
script { //there's no "if" "step" so any "if" must be in a "script" step
2024-12-01 19:02:17 -05:00
if ( database ) {
sh "" " # ! /bin/ bash
2024-12-02 22:00:17 -05:00
2024-12-01 19:02:17 -05:00
pushd $ { servicename }
dbstartline = \ $ ( sed - n '/---dbstart---/=' Jenkinsfile )
dbendline = \ $ ( sed - n '/---dbend---/=' Jenkinsfile )
2024-12-02 22:00:17 -05:00
echo \ "yes db. \${dbstartline} and \${dbendline}\"
sed - ie \ "\${dbstartline}d;\${dbendline}d\" Jenkinsfile
2024-11-19 11:49:50 -05:00
databasecredsid = \ $ ( uuidgen )
2024-12-02 22:13:47 -05:00
urlGetData = \ "crumbIssuer/api/xml?xpath=concat\\(//crumbRequestField,\\" : \ \ ",//crumb\\)\"
echo "116"
2024-12-02 22:00:17 -05:00
echo \ "\${urlGetData}\"
2024-12-02 22:13:47 -05:00
echo "118"
echo \ 'curl -s \"http://${env.JENKINS_USR}:\\\'${env.JENKINS_PSW}\\\'@alloces.lan:8080/\${urlGetData}\"\'
2024-12-02 22:00:17 -05:00
echo "122"
2024-12-02 22:13:47 -05:00
curl - s \ "http://${env.JENKINS_USR}:\\\'${env.JENKINS_PSW}\\\'@alloces.lan:8080/\${urlGetData}\"
2024-12-02 22:00:17 -05:00
2024-12-02 22:13:47 -05:00
CRUMB = \ $ ( curl - s \ "http://${env.JENKINS_USR}:\\\'${env.JENKINS_PSW}\\\'@alloces.lan:8080/\${urlGetData}\" )
2024-12-01 19:02:17 -05:00
echo \ $CRUMB
2024-12-02 22:00:17 -05:00
curl - H \ $CRUMB - X POST \ "http://${env.JENKINS_USR}:'${env.JENKINS_PSW}'@alloces.lan:8080/job/gitea.arg.rip/job/${servicename}/credentials/store/folder/domain/greyn%20services/createCredentials\" \
2024-11-19 11:49:50 -05:00
- - data - urlencode ' json = {
"" : "0" ,
"credentials" : {
"scope" : "GLOBAL" ,
2024-12-01 19:02:17 -05:00
"id" : "\$databasecredsid" ,
2024-12-02 22:00:17 -05:00
"secret" : "\"Host=${targetHost};Database=${servicename};Username=${servicename};Password=${env.pw_productiondatabase};IncludeErrorDetail=true;\"" ,
2024-11-19 11:49:50 -05:00
"description" : "database connection string" ,
"\$class" : "com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl"
}
} '
2024-12-02 22:00:17 -05:00
sed - ie 's/productiondatabase_connectionString=creds/productiondatabase_connectionString=credentials(' \ $databasecredsid ')/\' Jenkinsfile
2024-11-19 11:49:50 -05:00
git add .
2024-12-02 22:00:17 -05:00
git commit - m \ "set up for database\"
2024-11-19 11:49:50 -05:00
"" "
}
else {
2024-12-01 19:02:17 -05:00
sh "" " # ! /bin/ bash
echo \ "no db\"
pushd $ { servicename }
2024-12-02 22:00:17 -05:00
sed - i '\${dbstartline},\${dbendline}d;' Jenkinsfile
2024-11-19 11:49:50 -05:00
git add .
git commit - m "stripped database lines"
"" "
}
2024-11-19 02:07:51 -05:00
sh "" "
2024-12-01 19:02:17 -05:00
usernameCredsId = \ $ ( uuidgen )
2024-11-19 02:07:51 -05:00
2024-12-01 19:02:17 -05:00
CRUMB = \ $ ( curl 'http://${env.JENKINS_USR}:${env.JENKINS_PSW}@alloces.lan:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)' )
echo \ $CRUMB
curl - H \ $CRUMB - X POST 'http://${env.JENKINS_USR}:${env.JENKINS_PSW}@alloces.lan:8080/job/gitea.arg.rip/job/${servicename}/credentials/store/folder/domain/greyn%20services/createCredentials' \
2024-11-19 02:07:51 -05:00
- - data - urlencode ' json = {
"" : "0" ,
"credentials" : {
"scope" : "GLOBAL" ,
2024-12-01 19:02:17 -05:00
"id" : "\$usernameCredsId" ,
2024-11-19 11:49:50 -05:00
"username" : "${servicename}" ,
"password" : "${env.pw_linuxserviceaccount}" ,
"description" : "service account login" ,
"\$class" : "com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl"
2024-11-19 02:07:51 -05:00
}
} '
2024-11-19 11:49:50 -05:00
certCredsId = \ $ ( uuidgen )
2024-11-19 02:07:51 -05:00
2024-11-19 11:49:50 -05:00
ssh - keygen - t ed25519 - f "${servicename}" - N ""
privatekeycontent = \ $ ( cat $ { servicename } ) )
pubkeycontent = \ $ ( cat $ { servicename } . pub ) )
CRUMB = \ $ ( url - s 'http://${env.JENKINS_USR}:${env.JENKINS_PSW}@alloces.lan:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)' )
2024-12-01 19:02:17 -05:00
echo \ $CRUMB
curl - H \ $CRUMB - X POST 'http://${env.JENKINS_USR}:${env.JENKINS_PSW}@alloces.lan:8080/job/gitea.arg.rip/job/${servicename}/credentials/store/folder/domain/greyn%20services/createCredentials' \
2024-11-19 11:49:50 -05:00
- - data - urlencode ' json = {
"" : "0" ,
"credentials" : {
"scope" : "GLOBAL" ,
2024-12-01 19:02:17 -05:00
"id" : "\$usernameCredsId" ,
2024-11-19 11:49:50 -05:00
"username" : "${servicename}" ,
"password" : "" ,
"privateKeySource" : {
2024-12-01 19:02:17 -05:00
"stapler-class" : "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey\$DirectEntryPrivateKeySource" ,
"privateKey" : "\$privatekeycontent" ,
2024-11-19 11:49:50 -05:00
} ,
"description" : "${servicename}" ,
"stapler-class" : "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
} ,
"description" : "service account ssh" ,
"\$class" : "com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey"
}
} '
privatekeycontent =
2024-11-19 02:07:51 -05:00
2024-11-19 11:49:50 -05:00
sed - i 's/linuxServiceAccount=creds/linuxServiceAccount=credentials(' $ { env . usernameCredsId } ')/' Jenkinsfile
sed - i 's/targetHost=string/targetHost="${targetHost}"/' Jenkinsfile
2024-11-19 02:07:51 -05:00
2024-11-19 11:49:50 -05:00
"" "
sh "" "
git push
popd
"" "
}
2024-11-17 16:02:56 -05:00
}
2024-11-17 15:01:57 -05:00
}
}
2024-11-16 22:50:41 -05:00
stage ( "service account" ) {
steps {
script {
2024-11-17 16:02:56 -05:00
sshagent ( [ SUDOERSSH ] )
{
2024-11-19 11:49:50 -05:00
sh "" "ssh -tt ${SUDOER_USR}@${targetHost} username=${servicename} password=${env.pw_linuxserviceaccount} pubkeycontent=${env.pubkeycontent} 'echo " $SUDOER_PSW " | sudo - Sv & & bash - s ' << ' ENDSSH '
2024-12-01 19:02:17 -05:00
useradd - m - s /bin/ bash \ $username
echo "\$username:\$password" | chpasswd
loginctl enable - linger \ $username
cd ~ /home/ \ $username
2024-11-19 02:07:51 -05:00
mkdir . ssh
pushd . ssh
2024-12-01 19:02:17 -05:00
echo \ $pubkeycontent > authorized_keys
2024-11-19 02:07:51 -05:00
popd
2024-12-01 19:02:17 -05:00
chown - R \ $username : \ $username . ssh
2024-11-17 16:02:56 -05:00
ENDSSH
2024-11-19 11:49:50 -05:00
"" "
2024-11-17 16:02:56 -05:00
}
2024-11-16 22:50:41 -05:00
}
}
}
2024-11-17 13:24:01 -05:00
stage ( "db init" ) {
when { expression { return params . database } }
steps {
//i'm pretty sure "update" with nothing will init?
//meaning we don't have to init, first update will init
script {
2024-11-17 16:02:56 -05:00
sshagent ( [ SUDOERSSH ] )
{
2024-11-19 11:49:50 -05:00
sh "" "ssh -tt SUDOER_USR@${targetHost} servicename=$servicename pw_productiondatabase=${env.pw_productiondatabase} pw_developmentdatabase=${env.pw_developmentdatabase} 'echo " $SUDOER_PSW " | sudo - Sv & & bash - s ' << ' ENDSSH '
2024-11-17 16:02:56 -05:00
sudo - u postgres psql & & bash - s < < 'ENDPSQL'
create database $servicename ;
create user $servicename with encrypted password '$pw_productiondatabase' ;
grant all privileges on database $servicename to $servicename ;
ENDPSQL
service_dev = "${servicename}_dev"
sudo - u postgres psql & & bash - s < < 'ENDPSQL'
2024-12-01 19:02:17 -05:00
create database \ $service_dev ;
create user \ $service_dev with encrypted password '\$pw_developmentdatabase' ;
grant all privileges on database \ $service_dev to \ $service_dev ;
2024-11-17 16:02:56 -05:00
ENDPSQL
2024-11-19 11:49:50 -05:00
ENDSSH "" "
2024-11-17 16:02:56 -05:00
}
2024-11-17 13:24:01 -05:00
}
}
}
2024-11-16 22:50:41 -05:00
stage ( "initial service setup" ) {
steps {
2024-11-19 02:07:51 -05:00
sshagent ( [ SUDOERSSH ] )
{
2024-12-01 19:02:17 -05:00
sh 'scp ${servicename}.service ${servicename}@${targetHost}:~/.config/systemd/user/${servicename}.service'
sh "" "ssh -tt $SUDOER_USR@${targetHost} servicename=${servicename} pw_productiondatabase=${env.pw_productiondatabase} pw_developmentdatabase=${env.pw_developmentdatabase} 'echo " $SUDOER_PSW " | sudo - Sv & & bash - s ' << ' ENDSSH '
2024-11-19 02:07:51 -05:00
sudo - u $ { servicename } & & bash - s < < 'ENDASSERVICE'
systemctl - - user daemon - reload
2024-12-01 19:02:17 -05:00
systemctl - - user enable $ { servicename } . service
2024-11-19 02:07:51 -05:00
ENDASSERVICE
2024-11-19 11:49:50 -05:00
ENDSSH "" "
2024-11-19 02:07:51 -05:00
}
2024-11-16 22:50:41 -05:00
}
}
2024-11-19 11:49:50 -05:00
}
post {
failure {
2024-11-21 13:02:37 -05:00
matrixSendMessage https: true , hostname: 'greyn.club' , port: 8448 , accessTokenCredentialsId: '040b63d1-2f14-4692-badb-114bddd7c5a5' , roomId: '!QmOCACetHdGDlNFsZP:greyn.club' , body: '1-click service failed :(' , formattedBody: "1-click service <b>failed</b> :("
2024-11-19 11:49:50 -05:00
}
success {
2024-11-21 13:02:37 -05:00
matrixSendMessage https: true , hostname: 'greyn.club' , port: 8448 , accessTokenCredentialsId: '040b63d1-2f14-4692-badb-114bddd7c5a5' , roomId: '!QmOCACetHdGDlNFsZP:greyn.club' , body: '1-click service success! go pick up the credentials!' , formattedBody: '1-click service success! go pick up the credentials!'
2024-11-19 11:49:50 -05:00
//TODO: archiveArtifacts the password data, then store them somewhere
2024-11-17 16:02:56 -05:00
}
2024-11-16 22:50:41 -05:00
}
}