Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify maintainerScripts #625

Merged
merged 1 commit into from
Dec 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 / __/ | / ___ \| | | (__| | | | __/ |_| |_| | |_) | __/
# |____/ \___|_| \_/ \___|_| /_/ \_\_| \___|_| |_|\___|\__|\__, | .__/ \___|
# |___/|_|
# ------------------------------------------------------------------------------------
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, is this part of the server archetype?


${{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._
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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