Skip to content

Commit

Permalink
Merge pull request #625 from sbt/wip/unify-maintainerscripts
Browse files Browse the repository at this point in the history
Unify maintainerScripts
  • Loading branch information
muuki88 committed Dec 13, 2015
2 parents 07290f5 + a38b34f commit 57c938d
Show file tree
Hide file tree
Showing 36 changed files with 567 additions and 279 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
${{header}}
${{loader-functions}}
${{control-functions}}

addGroup ${{daemon_group}} "${{daemon_group_gid}}"
addUser ${{daemon_user}} "${{daemon_user_uid}}" ${{daemon_group}} "${{app_name}} user-daemon" "${{daemon_shell}}"

${{chown-paths}}
# ------------------------------------------------------------------------------------
# ____ _ _ _
# / ___| ___ _ ____ _____ _ __ / \ _ __ ___| |__ ___| |_ _ _ _ __ ___
# \___ \ / _ \ '__\ \ / / _ \ '__| / _ \ | '__/ __| '_ \ / _ \ __| | | | '_ \ / _ \
# ___) | __/ | \ V / __/ | / ___ \| | | (__| | | | __/ |_| |_| | |_) | __/
# |____/ \___|_| \_/ \___|_| /_/ \_\_| \___|_| |_|\___|\__|\__, | .__/ \___|
# |___/|_|
# ------------------------------------------------------------------------------------

${{loader-functions}}
startService ${{app_name}} || echo "${{app_name}} could not be registered or started"
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
${{header}}
${{control-functions}}
# ------------------------------------------------------------------------------------
# ____ _ _ _
# / ___| ___ _ ____ _____ _ __ / \ _ __ ___| |__ ___| |_ _ _ _ __ ___
# \___ \ / _ \ '__\ \ / / _ \ '__| / _ \ | '__/ __| '_ \ / _ \ __| | | | '_ \ / _ \
# ___) | __/ | \ V / __/ | / ___ \| | | (__| | | | __/ |_| |_| | |_) | __/
# |____/ \___|_| \_/ \___|_| /_/ \_\_| \___|_| |_|\___|\__|\__, | .__/ \___|
# |___/|_|
# ------------------------------------------------------------------------------------

# Deleting user: ${{daemon_user}} and group: ${{daemon_group}}
case "$1" in
remove|failed-upgrade|abort-upgrade|abort-install|disappear)
;;
purge)
deleteUser ${{daemon_user}}
deleteGroup ${{daemon_group}}
;;
upgrade)
;;
*)
echo "postinst called with unknown argument \`\$1'" >&2
;;
esac
# empty
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
${{header}}
${{control-functions}}
# ------------------------------------------------------------------------------------
# ____ _ _ _
# / ___| ___ _ ____ _____ _ __ / \ _ __ ___| |__ ___| |_ _ _ _ __ ___
# \___ \ / _ \ '__\ \ / / _ \ '__| / _ \ | '__/ __| '_ \ / _ \ __| | | | '_ \ / _ \
# ___) | __/ | \ V / __/ | / ___ \| | | (__| | | | __/ |_| |_| | |_) | __/
# |____/ \___|_| \_/ \___|_| /_/ \_\_| \___|_| |_|\___|\__|\__, | .__/ \___|
# |___/|_|
# ------------------------------------------------------------------------------------

# empty
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
${{header}}
# ------------------------------------------------------------------------------------
# ____ _ _ _
# / ___| ___ _ ____ _____ _ __ / \ _ __ ___| |__ ___| |_ _ _ _ __ ___
# \___ \ / _ \ '__\ \ / / _ \ '__| / _ \ | '__/ __| '_ \ / _ \ __| | | | '_ \ / _ \
# ___) | __/ | \ V / __/ | / ___ \| | | (__| | | | __/ |_| |_| | |_) | __/
# |____/ \___|_| \_/ \___|_| /_/ \_\_| \___|_| |_|\___|\__|\__, | .__/ \___|
# |___/|_|
# ------------------------------------------------------------------------------------

${{loader-functions}}

stopService ${{app_name}} || echo "${{app_name}} wasn't even running!"
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ ${{header}}
${{control-functions}}

addGroup ${{daemon_group}} "${{daemon_group_gid}}"
addUser ${{daemon_user}} "${{daemon_user_uid}}" ${{daemon_group}} "${{app_name}} daemon-user" ${{daemon_shell}}
addUser ${{daemon_user}} "${{daemon_user_uid}}" ${{daemon_group}} "${{app_name}} daemon-user" "${{daemon_shell}}"

${{chown-paths}}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
${{header}}
${{control-functions}}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
${{header}}
${{control-functions}}
3 changes: 2 additions & 1 deletion src/main/scala/com/typesafe/sbt/PackagerPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ object SbtNativePackager extends AutoPlugin {
packageDescription := name.value,
packageSummary := name.value,
packageName := normalizedName.value,
executableScriptName := normalizedName.value
executableScriptName := normalizedName.value,
maintainerScripts := Map()

)

Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/com/typesafe/sbt/packager/Keys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ trait NativePackagerKeys {

val executableScriptName = SettingKey[String]("executableScriptName", "Name of the executing script.")

val maintainerScripts = TaskKey[Map[String, Seq[String]]]("maintainerScripts", "Scripname to content lines")

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ object JavaAppPackaging extends AutoPlugin with JavaAppStartScript {
*/
val appIniLocation = "${app_home}/../conf/application.ini"

object autoImport extends JavaAppKeys
object autoImport extends JavaAppKeys with MaintainerScriptHelper

import JavaAppPackaging.autoImport._

Expand Down Expand Up @@ -131,6 +131,7 @@ object JavaAppPackaging extends AutoPlugin with JavaAppStartScript {
d.mkdirs()
LinuxPackageMapping(Seq(d -> (installLocation + "/" + name)), LinuxFileMetaData())
}

)

private def makeRelativeClasspathNames(mappings: Seq[(File, String)]): Seq[String] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ trait JavaAppKeys {
| APP_DEFINES - the defines to go into the app
| """.stripMargin
)

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ package archetypes
import sbt._
import sbt.Keys.{ target, mainClass, sourceDirectory, streams, javaOptions, run }
import SbtNativePackager.{ Debian, Rpm, Universal }
import packager.Keys.{ packageName }
import packager.Keys.{ packageName, maintainerScripts }
import linux.{ LinuxFileMetaData, LinuxPackageMapping, LinuxSymlink, LinuxPlugin }
import linux.LinuxPlugin.autoImport._
import debian.DebianPlugin
import debian.DebianPlugin.autoImport.{ debianMakePreinstScript, debianMakePostinstScript, debianMakePrermScript, debianMakePostrmScript }
import rpm.RpmPlugin
import rpm.RpmPlugin.autoImport.{ rpmPre, rpmPost, rpmPostun, rpmPreun, rpmScriptsDirectory, rpmDaemonLogFile }
import rpm.RpmPlugin.autoImport.{ rpmPre, rpmPost, rpmPostun, rpmPreun, rpmScriptsDirectory, rpmDaemonLogFile, RpmConstants }
import rpm.RpmPlugin.Names.RpmDaemonLogFileReplacement
import JavaAppPackaging.autoImport.{ bashScriptConfigLocation, bashScriptEnvConfigLocation }

Expand Down Expand Up @@ -105,18 +105,27 @@ object JavaServerAppPackaging extends AutoPlugin {
linuxScriptReplacements in Debian,
target in Universal,
serverLoading in Debian) map makeStartScript,
linuxPackageMappings <++= (packageName, linuxMakeStartScript, serverLoading, defaultLinuxStartScriptLocation, linuxStartScriptName) map startScriptMapping
linuxPackageMappings <++= (packageName, linuxMakeStartScript, serverLoading, defaultLinuxStartScriptLocation, linuxStartScriptName) map startScriptMapping,

// === Maintainer scripts ===
maintainerScripts := {
val scripts = (maintainerScripts in Debian).value
val replacements = (linuxScriptReplacements in Debian).value
val contentOf = getScriptContent(Debian, replacements) _

scripts ++ Map(
Preinst -> (scripts.getOrElse(Preinst, Nil) :+ contentOf(Preinst)),
Postinst -> (scripts.getOrElse(Postinst, Nil) :+ contentOf(Postinst)),
Prerm -> (scripts.getOrElse(Prerm, Nil) :+ contentOf(Prerm)),
Postrm -> (scripts.getOrElse(Postrm, Nil) :+ contentOf(Postrm))
)
}
)) ++ Seq(
// === Daemon User and Group ===
daemonUser in Debian <<= daemonUser in Linux,
daemonUserUid in Debian <<= daemonUserUid in Linux,
daemonGroup in Debian <<= daemonGroup in Linux,
daemonGroupGid in Debian <<= daemonGroupGid in Linux,
// === Maintainer scripts ===
debianMakePreinstScript <<= (target in Universal, serverLoading in Debian, linuxScriptReplacements) map makeMaintainerScript(Preinst),
debianMakePostinstScript <<= (target in Universal, serverLoading in Debian, linuxScriptReplacements) map makeMaintainerScript(Postinst),
debianMakePrermScript <<= (target in Universal, serverLoading in Debian, linuxScriptReplacements) map makeMaintainerScript(Prerm),
debianMakePostrmScript <<= (target in Universal, serverLoading in Debian, linuxScriptReplacements) map makeMaintainerScript(Postrm)
daemonGroupGid in Debian <<= daemonGroupGid in Linux
)
}

Expand Down Expand Up @@ -163,19 +172,7 @@ object JavaServerAppPackaging extends AutoPlugin {
linuxPackageMappings in Rpm <++= (packageName in Rpm, linuxMakeStartScript in Rpm, serverLoading in Rpm, defaultLinuxStartScriptLocation in Rpm, linuxStartScriptName in Rpm) map startScriptMapping,

// == Maintainer scripts ===
// TODO this is very basic - align debian and rpm plugin
rpmPre <<= (rpmScriptsDirectory, rpmPre, linuxScriptReplacements in Rpm, serverLoading in Rpm) apply {
(dir, pre, replacements, loader) => rpmScriptletContent(dir, Pre, replacements, pre)
},
rpmPost <<= (rpmScriptsDirectory, rpmPost, linuxScriptReplacements in Rpm, serverLoading in Rpm) apply {
(dir, post, replacements, loader) => rpmScriptletContent(dir, Post, replacements, post)
},
rpmPostun <<= (rpmScriptsDirectory, rpmPostun, linuxScriptReplacements in Rpm, serverLoading in Rpm) apply {
(dir, postun, replacements, loader) => rpmScriptletContent(dir, Postun, replacements, postun)
},
rpmPreun <<= (rpmScriptsDirectory, rpmPreun, linuxScriptReplacements in Rpm, serverLoading in Rpm) apply {
(dir, preun, replacements, loader) => rpmScriptletContent(dir, Preun, replacements, preun)
}
maintainerScripts in Rpm := rpmScriptletContents(rpmScriptsDirectory.value, (maintainerScripts in Rpm).value, (linuxScriptReplacements in Rpm).value)
)
}

Expand All @@ -186,10 +183,9 @@ object JavaServerAppPackaging extends AutoPlugin {
private[this] def defaultTemplateName(loader: ServerLoader, config: Configuration): String = (loader, config.name) match {
// SystemV has two different start scripts
case (SystemV, name) => s"start-$name-template"
case _ => "start-template"
case _ => "start-template"
}


private[this] def overrideTemplate(sourceDirectory: File, loader: ServerLoader, config: Configuration): Option[File] = {
Option(sourceDirectory / "templates" / config.name / loader.toString.toLowerCase)
}
Expand All @@ -204,7 +200,7 @@ object JavaServerAppPackaging extends AutoPlugin {
// Upstart cannot handle empty values
val (startOn, stopOn) = loader match {
case Upstart => (requiredStartFacilities.map("start on started " + _), requiredStopFacilities.map("stop on stopping " + _))
case _ => (requiredStartFacilities, requiredStopFacilities)
case _ => (requiredStartFacilities, requiredStopFacilities)
}
Seq(
"start_runlevels" -> startRunlevels.getOrElse(""),
Expand Down Expand Up @@ -264,16 +260,17 @@ object JavaServerAppPackaging extends AutoPlugin {
Some(script)
}

protected def makeMaintainerScript(
scriptName: String,
template: Option[URL] = None, archetype: String = ARCHETYPE, config: Configuration = Debian)(
tmpDir: File, loader: ServerLoader, replacements: Seq[(String, String)]): Option[File] = {
val scriptBits = JavaServerBashScript(scriptName, archetype, config, replacements, template) getOrElse {
sys.error(s"Couldn't load [$scriptName] for config [${config.name}] in archetype [$archetype]")
/**
*
* @param config for which plugin (Debian, Rpm)
* @param replacements for the placeholders
* @param scriptName that should be loaded
* @return script lines
*/
private[this] def getScriptContent(config: Configuration, replacements: Seq[(String, String)])(scriptName: String): String = {
JavaServerBashScript(scriptName, ARCHETYPE, config, replacements) getOrElse {
sys.error(s"Couldn't load [$scriptName] for config [${config.name}] in archetype [$ARCHETYPE]")
}
val script = tmpDir / "tmp" / "bin" / (config.name + scriptName)
IO.write(script, scriptBits)
Some(script)
}

/**
Expand All @@ -295,15 +292,44 @@ object JavaServerAppPackaging extends AutoPlugin {
Some(script)
}

protected def rpmScriptletContent(dir: File, script: String,
replacements: Seq[(String, String)], definedScript: Option[String], archetype: String = ARCHETYPE, config: Configuration = Rpm): Option[String] = {
val file = (dir / script)
val template = if (file exists) Some(file.toURI.toURL) else None
/**
*
*
* @param scriptDirectory
* @param scripts
* @param replacements
*/
protected def rpmScriptletContents(scriptDirectory: File, scripts: Map[String, Seq[String]], replacements: Seq[(String, String)]): Map[String, Seq[String]] = {
import RpmConstants._
val predefined = List(Pre, Post, Preun, Postun)
val predefinedScripts = predefined.foldLeft(scripts) {
case (scripts, script) =>
val userDefined = Option(scriptDirectory / script) collect {
case file if file.exists && file.isFile => file.toURI.toURL
}
// generate content
val content = JavaServerBashScript(script, ARCHETYPE, Rpm, replacements, userDefined).map {
script => TemplateWriter generateScriptFromString (script, replacements)
}.toSeq
// add new content
val newContent = scripts.getOrElse(script, Nil) ++ content.toSeq
scripts + (script -> newContent)
}

// used to override template
val rpmScripts = Option(scriptDirectory.listFiles) getOrElse Array.empty

val content = definedScript.map(_ + "\n").getOrElse("")
// remove all non files and already processed templates
rpmScripts.diff(predefined).filter(_.isFile).foldLeft(predefinedScripts) {
case (scripts, scriptlet) =>
val script = scriptlet.getName
val existingContent = scripts.getOrElse(script, Nil)

JavaServerBashScript(script, archetype, config, replacements, template) map {
case script => TemplateWriter generateScriptFromString (content + script, replacements)
val loadedContent = JavaServerBashScript(script, ARCHETYPE, Rpm, replacements, Some(scriptlet.toURI.toURL)).map {
script => TemplateWriter generateScriptFromString (script, replacements)
}.toSeq
// add the existing and loaded content
scripts + (script -> (existingContent ++ loadedContent))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.typesafe.sbt.packager.archetypes

import sbt._
import com.typesafe.sbt.SbtNativePackager.autoImport.maintainerScripts

/**
* == Maintainer Script Helper ==
*
* Provides utility methods to configure package maintainerScripts.
*/
trait MaintainerScriptHelper {

/**
* Use this method to override preexisting configurations with custom file
* definitions.
*
* @example {{{
* import DebianConstants._
* maintainerScripts in Debian := maintainerScriptsFromDirectory(
* sourceDirectory.value / DebianSource / DebianMaintainerScripts,
* Seq(Preinst, Postinst, Prerm, Postrm)
* )
* }}}
* @param dir from where to load files
* @param scripts - a list of script names that should be used
* @return filename to content mapping
*/
def maintainerScriptsFromDirectory(dir: File, scripts: Seq[String]): Map[String, Seq[String]] = {
scripts.map(dir / _)
.filter(_.exists)
.map { script =>
script.getName -> IO.readLines(script)
}.toMap
}

/**
* Use this method to append additional script content to specific maintainer scripts.
*
* @example Adding content from a string
* {{{
* import RpmConstants._
* maintainerScripts in Rpm := maintainerScriptsAppend((maintainerScripts in Rpm).value)(
* Pretrans -> "echo 'hello, world'",
* Post -> s"echo 'installing ${(packageName in Rpm).value}'"
* )
* }}}
*
*
* @param current maintainer scripts
* @param scripts scriptName -> scriptContent pairs
* @return maintainerScripts with appended `scripts`
* @see [[maintainerScriptsAppendFromFile]]
*/
def maintainerScriptsAppend(current: Map[String, Seq[String]] = Map.empty)(scripts: (String, String)*): Map[String, Seq[String]] = {
val appended = scripts.map {
case (key, script) => key -> (current.getOrElse(key, Seq.empty) :+ script)
}.toMap
current ++ appended
}

/**
* Use this method to append additional script content to specific maintainer scripts.
* Note that you won't have any scriptReplacements available.
*
* @example Adding content from a string
* {{{
* import RpmConstants._
* maintainerScripts in Rpm := maintainerScriptsAppendFromFile((maintainerScripts in Rpm).value)(
* Pretrans -> (sourceDirectory.value / "rpm" / "pretrans"),
* Post -> (sourceDirectory.value / "rpm" / "posttrans")
* )
* }}}
*
*
* @param current maintainer scripts
* @param scripts scriptName -> scriptFile pairs
* @return maintainerScripts with appended `scripts`
* @see [[maintainerScriptsAppend]] for pure strings where you can insert arbitrary settings and tasks values
*/
def maintainerScriptsAppendFromFile(current: Map[String, Seq[String]] = Map.empty)(scripts: (String, File)*): Map[String, Seq[String]] = {
val appended = scripts.map {
case (key, script) if script.exists && script.isFile => key -> (current.getOrElse(key, Seq.empty) ++ IO.readLines(script))
case (key, script) => sys.error(s"The maintainer script $key doesn't exist here: ${script.getAbsolutePath}")
}.toMap
current ++ appended
}

}
Loading

0 comments on commit 57c938d

Please sign in to comment.