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-12-03 01:47:52 -05:00
SUDOER_ALLOCES = credentials ( 'a674f816-2b35-4d60-ba60-7b66e86f3c5c' )
SUDOER_MOLORYB = credentials ( '1f3b965e-bcc0-4074-99f2-b64dddbf7de7' )
SUDOERSSHID = '2c48e1a9-22b2-455c-9959-6b29e86d3fb5'
SUDOERSSH = credentials ( '2c48e1a9-22b2-455c-9959-6b29e86d3fb5' )
JENKINS = credentials ( '68391381-e095-4b47-b956-d23055b0808e' )
2024-11-21 13:02:37 -05:00
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-12-03 01:47:52 -05:00
SUDOER_USR = SUDOER_ALLOCES_USR
SUDOER_PSW = SUDOER_ALLOCES_PSW
2024-11-21 00:13:06 -05:00
case "moloryb.lan" :
2024-12-03 01:47:52 -05:00
SUDOER_USR = SUDOER_MOLORYB_USR
SUDOER_PSW = SUDOER_MOLORYB_PSW
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-12-03 00:21:42 -05:00
env . pw_linuxserviceaccount = sh ( returnStdout: true , script: "mktemp -u XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) . trim ( )
2024-11-17 16:02:56 -05:00
echo env . pw_linuxserviceaccount
2024-12-03 00:21:42 -05:00
env . pw_productiondatabase = sh ( returnStdout: true , script: "mktemp -u XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) . trim ( )
2024-11-17 16:02:56 -05:00
echo env . pw_productiondatabase
2024-12-03 00:21:42 -05:00
env . pw_developmentdatabase = sh ( returnStdout: true , script: "mktemp -u XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) . trim ( )
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-12-03 00:21:42 -05:00
# curl - X GET $ { env . JENKINS_USR } : $ { env . JENKINS_PSW } @alloces.lan : 8080 /job/ gitea . arg . rip /api/ json
curl - X GET - s $ { env . JENKINS_USR } : $ { env . JENKINS_PSW } @alloces.lan : 8080 /job/ gitea . arg . rip /api/ json > f . json
2024-11-27 15:39:21 -05:00
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-03 00:21:42 -05:00
echo \ "yes db.\"
2024-12-02 22:00:17 -05:00
2024-12-03 00:21:42 -05:00
sed - i \ "\${dbstartline}d;\${dbendline}d\" Jenkinsfile
2024-11-19 11:49:50 -05:00
databasecredsid = \ $ ( uuidgen )
2024-12-03 00:21:42 -05:00
httpBasicAuth = \ "http://${env.JENKINS_USR}:${env.JENKINS_PSW}@alloces.lan:8080/\"
echo \ "\${httpBasicAuth}\"
urlGetData = \ "crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\\" : \ \ ",//crumb)\"
CRUMB = \ $ ( curl - s - c cookies . txt \ "\${httpBasicAuth}\${urlGetData}\" )
echo "crumb anyway. \$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/_/createCredentials\" \
2024-11-19 11:49:50 -05:00
- - data - urlencode ' json = {
"" : "0" ,
"credentials" : {
"scope" : "GLOBAL" ,
2024-12-03 00:21:42 -05:00
"id" : "'" \ $databasecredsid "'" ,
"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-03 00:21:42 -05:00
sed - i 's/productiondatabase_connectionString=creds/productiondatabase_connectionString=credentials(' \ $databasecredsid ')/\' Jenkinsfile
2024-11-19 11:49:50 -05:00
2024-12-03 01:47:52 -05:00
rm cookies . txt
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-12-03 01:47:52 -05:00
sh "" " # ! /bin/ bash
pushd $ { servicename }
2024-11-19 02:07:51 -05:00
2024-12-01 19:02:17 -05:00
usernameCredsId = \ $ ( uuidgen )
2024-11-19 02:07:51 -05:00
2024-12-03 01:47:52 -05:00
CRUMB = \ $ ( curl - c cookies . txt 'http://${env.JENKINS_USR}:${env.JENKINS_PSW}@alloces.lan:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)' )
echo \ $CRUMB
2024-12-03 00:21:42 -05:00
curl - X POST 'http://${env.JENKINS_USR}:${env.JENKINS_PSW}@alloces.lan:8080/job/gitea.arg.rip/job/${servicename}/credentials/store/folder/domain/_/createCredentials' \
2024-11-19 02:07:51 -05:00
- - data - urlencode ' json = {
"" : "0" ,
"credentials" : {
"scope" : "GLOBAL" ,
2024-12-03 01:47:52 -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-12-03 01:47:52 -05:00
# you git cloned $ { servicename } . that ' s why it "already exists" .
ssh - keygen - t ed25519 - f "${servicename}-ssh" - N ""
# chmod 600 \ "${servicename}-ssh\"
# chmod 600 \ "${servicename}-ssh.pub\"
privatekeycontent = \ $ ( cat $ { servicename } - ssh )
pubkeycontent = \ $ ( cat $ { servicename } - ssh . pub )
CRUMB = \ $ ( curl - s 'http://${env.JENKINS_USR}:${env.JENKINS_PSW}@alloces.lan:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)' )
echo \ $CRUMB
2024-12-03 00:21:42 -05:00
curl - X POST 'http://${env.JENKINS_USR}:${env.JENKINS_PSW}@alloces.lan:8080/job/gitea.arg.rip/job/${servicename}/credentials/store/folder/domain/_/createCredentials' \
2024-11-19 11:49:50 -05:00
- - data - urlencode ' json = {
"" : "0" ,
"credentials" : {
"scope" : "GLOBAL" ,
2024-12-03 01:47:52 -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-12-03 01:47:52 -05:00
rm cookies . txt
git - c core . sshCommand = "ssh -i '$PK'\" push
2024-11-19 11:49:50 -05:00
"" "
}
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-12-03 01:47:52 -05:00
withCredentials ( [ sshUserPrivateKey ( credentialsId: env . SUDOERSSHID , keyFileVariable: 'PK' ) ] )
2024-11-17 16:02:56 -05:00
{
2024-12-03 01:47:52 -05:00
sh "" " # ! /bin/ bash
ssh - keyscan - t ed25519 $ { targetHost } > > ~ /.ssh/ known_hosts
ssh - i \ "${PK}\" -tt ${SUDOER_USR}@${targetHost} username=${servicename} password=${env.pw_linuxserviceaccount} pubkeycontent=${env.pubkeycontent} 'echo " $ { SUDOER_PSW } " | sudo - Sv & & bash - s ' << ' ENDSSH '
useradd - m - s /bin/ bash \ $username
echo "\$username:\$password" | chpasswd
loginctl enable - linger \ $username
cd ~ /home/ \ $username
mkdir . ssh
pushd . ssh
echo \ $pubkeycontent > authorized_keys
popd
chown - R \ $username : \ $username . ssh
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-12-03 01:47:52 -05:00
withCredentials ( [ sshUserPrivateKey ( credentialsId: env . SUDOERSSHID , keyFileVariable: 'PK' ) ] )
2024-11-17 16:02:56 -05:00
{
2024-12-03 01:47:52 -05:00
sh "" " # ! /bin/ bash
ssh - keyscan - t ed25519 $ { targetHost } > > ~ /.ssh/ known_hosts
ssh - i \ "${PK}\" -tt ${SUDOER_USR}@${targetHost} servicename=${servicename} pw_productiondatabase=${env.pw_productiondatabase} pw_developmentdatabase=${env.pw_developmentdatabase} 'echo " $SUDOER_PSW " | sudo - Sv & & bash - s ' << ' ENDSSH '
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'
create database \ $service_dev ;
create user \ $service_dev with encrypted password '\$pw_developmentdatabase' ;
grant all privileges on database \ $service_dev to \ $service_dev ;
ENDPSQL
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
}
}