Skip to content

Commit

Permalink
Merge pull request #131 from muuki88/wip/refactoring-templates
Browse files Browse the repository at this point in the history
Started refactoring of archetypes templates
  • Loading branch information
jsuereth committed Jan 22, 2014
2 parents 2397fc5 + 2145755 commit d7982dc
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 83 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
service ${{app_name}} stop || echo "${{app_name}} wasn't even running!"
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,67 @@ import java.net.URL
object JavaAppStartScript {

import ServerLoader._
import com.typesafe.sbt.packager.debian.DebianPlugin.Names._
val startScript = "start"

protected def upstartTemplateSource: URL = getClass.getResource("upstart-template")
protected def sysvinitTemplateSource: URL = getClass.getResource("sysvinit-template")
protected def postinstTemplateSource: URL = getClass.getResource("postinst-template")
protected def postinstSysvinitTemplateSource: URL = getClass.getResource("postinst-sysvinit-template")
protected def postrmSysvinitTemplateSource: URL = getClass.getResource("postrm-sysvinit-template")
protected def preremTemplateSource: URL = getClass.getResource("prerem-template")


def defaultStartScriptTemplate(loader: ServerLoader, defaultLocation: File): URL =
if(defaultLocation.exists) defaultLocation.toURI.toURL
else loader match {
case Upstart => upstartTemplateSource
case SystemV => sysvinitTemplateSource
}
private val upstartScripts = Seq(startScript, Postinst, Prerm)
private val systemvScripts = Seq(startScript, Postinst, Prerm, Postrm)

/**
* Generating the URL to the startScript template.
* 1. Looking in defaultLocation
* 2. Using default fallback
*
* @param loader - used, when no file in the defaultLocation
* @param defaultLocation - use if exists
*/
def defaultStartScriptTemplate(loader: ServerLoader, defaultLocation: File): URL =
if (defaultLocation.exists) defaultLocation.toURI.toURL
else templateUrl(startScript, loader) getOrElse sys.error("Default startscript not available for loader: " + loader)

def generatePrerm(appName: String, template: java.net.URL = preremTemplateSource): String =
TemplateWriter.generateScript(template, Seq("app_name" -> appName))

/**
* Generating the start script depending on the serverLoader.
*
* @param loader - which startup system
* @param replacements - default replacements
* @param template - if specified, it will override the default one
*/
def generateStartScript(
loader: ServerLoader,
replacements: Seq[(String, String)],
template: Option[URL] = None): Option[String] = generateTemplate(startScript, loader, replacements, template)

def generatePostrm(appName: String, loader: ServerLoader, template: Option[java.net.URL] = None): Option[String] =
(template, loader) match {
case (Some(template), _) => Option(TemplateWriter.generateScript(template, Seq("app_name" -> appName)))
case (_, SystemV) =>
Option(TemplateWriter.generateScript(postrmSysvinitTemplateSource, Seq("app_name" -> appName)))
case (_, _) => None
}
/**
*
* @param templateName - DebianPlugin.Names for maintainer scripts and "start"
* @param loader - which startup system
* @param replacements - default replacements
* @param template - if specified, it will override the default one
*/
def generateTemplate(
templateName: String,
loader: ServerLoader,
replacements: Seq[(String, String)],
template: Option[URL] = None): Option[String] = {

// use template orElse search for a default
val url = templateUrl(templateName, loader, template)

def generatePostinst(appName: String, loader: ServerLoader, template: Option[java.net.URL] = None): String =
(template, loader) match {
// User has overriden the default.
case (Some(template), _) => TemplateWriter.generateScript(template, Seq("app_name" -> appName))
case (_, Upstart) =>
TemplateWriter.generateScript(postinstTemplateSource, Seq("app_name" -> appName))
case (_, SystemV) =>
TemplateWriter.generateScript(postinstSysvinitTemplateSource, Seq("app_name" -> appName))
// if an url was found, create the script
url map { template =>
TemplateWriter generateScript (template, replacements)
}
}

def templateUrl(templateName: String, loader: ServerLoader, template: Option[URL] = None): Option[URL] = template orElse {
Option(loader match {
case Upstart if (upstartScripts contains templateName) =>
getClass getResource ("upstart/" + templateName + "-template")
case SystemV if (systemvScripts contains templateName) =>
getClass getResource ("systemv/" + templateName + "-template")
case _ => null
})
}

/**
*
Expand Down Expand Up @@ -82,11 +103,9 @@ object JavaAppStartScript {
"app_name" -> appName,
"app_main_class" -> appMainClass,
"app_classpath" -> appClasspath,
"daemon_user" -> daemonUser
)
"daemon_user" -> daemonUser)
}


object ServerLoader extends Enumeration {
type ServerLoader = Value
val Upstart, SystemV = Value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import sbt._
import sbt.Keys.{ target, mainClass, normalizedName, sourceDirectory }
import SbtNativePackager._
import com.typesafe.sbt.packager.linux.{ LinuxFileMetaData, LinuxPackageMapping, LinuxSymlink, LinuxPlugin }
import com.typesafe.sbt.packager.debian.DebianPlugin

/**
* This class contains the default settings for creating and deploying an archetypical Java application.
Expand All @@ -20,6 +21,7 @@ import com.typesafe.sbt.packager.linux.{ LinuxFileMetaData, LinuxPackageMapping,
object JavaServerAppPackaging {
import ServerLoader._
import LinuxPlugin.Users
import DebianPlugin.Names.{ Preinst, Postinst, Prerm, Postrm }

def settings: Seq[Setting[_]] = JavaAppPackaging.settings ++ debianSettings
protected def etcDefaultTemplateSource: java.net.URL = getClass.getResource("etc-default-template")
Expand All @@ -29,7 +31,7 @@ object JavaServerAppPackaging {
serverLoading := Upstart,
daemonUser := Users.Root,
// This one is begging for sbt 0.13 syntax...
debianStartScriptReplacements <<= (
debianScriptReplacements <<= (
maintainer in Debian, packageSummary in Debian, serverLoading in Debian, daemonUser in Debian, normalizedName,
sbt.Keys.version, defaultLinuxInstallLocation, mainClass in Compile, scriptClasspath)
map { (author, descr, loader, daemonUser, name, version, installLocation, mainClass, cp) =>
Expand All @@ -47,21 +49,15 @@ object JavaServerAppPackaging {
daemonUser = daemonUser)
},
// TODO - Default locations shouldn't be so hacky.

// === Startscript creation ===
linuxStartScriptTemplate in Debian <<= (serverLoading in Debian, sourceDirectory) map { (loader, dir) =>
JavaAppStartScript.defaultStartScriptTemplate(loader, dir / "templates" / "start")
},
debianMakeStartScript <<= (debianStartScriptReplacements, normalizedName, target in Universal, linuxStartScriptTemplate in Debian)
map makeDebianStartScript,
linuxEtcDefaultTemplate in Debian <<= sourceDirectory map { dir =>
val overrideScript = dir / "templates" / "etc-default"
if(overrideScript.exists) overrideScript.toURI.toURL
else etcDefaultTemplateSource
},
debianMakeEtcDefault <<= (normalizedName, target in Universal, serverLoading in Debian, linuxEtcDefaultTemplate in Debian)
map makeEtcDefaultScript,
linuxPackageMappings in Debian <++= (debianMakeEtcDefault, normalizedName) map { (conf, name) =>
conf.map(c => LinuxPackageMapping(Seq(c -> ("/etc/default/" + name))).withConfig()).toSeq
},
debianMakeStartScript <<= (target in Universal, serverLoading in Debian, debianScriptReplacements, linuxStartScriptTemplate in Debian)
map { (tmpDir, loader, replacements, template) =>
makeDebianMaintainerScript(JavaAppStartScript.startScript, Some(template))(tmpDir, loader, replacements)
},
linuxPackageMappings in Debian <++= (debianMakeStartScript, normalizedName, serverLoading in Debian)
map { (script, name, loader) =>
val (path, permissions) = loader match {
Expand All @@ -72,7 +68,21 @@ object JavaServerAppPackaging {
s <- script.toSeq
} yield LinuxPackageMapping(Seq(s -> path)).withPerms(permissions).withConfig()
},

// === etc config mapping ===
linuxEtcDefaultTemplate in Debian <<= sourceDirectory map { dir =>
val overrideScript = dir / "templates" / "etc-default"
if (overrideScript.exists) overrideScript.toURI.toURL
else etcDefaultTemplateSource
},
debianMakeEtcDefault <<= (normalizedName, target in Universal, serverLoading in Debian, linuxEtcDefaultTemplate in Debian)
map makeEtcDefaultScript,
linuxPackageMappings in Debian <++= (debianMakeEtcDefault, normalizedName) map { (conf, name) =>
conf.map(c => LinuxPackageMapping(Seq(c -> ("/etc/default/" + name))).withConfig()).toSeq
},
// TODO should we specify daemonGroup in configs?

// === logging directory mapping ===
linuxPackageMappings in Debian <+= (normalizedName, defaultLinuxLogsLocation, target in Debian, daemonUser in Debian) map {
(name, logsDir, target, user) =>
// create empty var/log directory
Expand All @@ -83,45 +93,22 @@ object JavaServerAppPackaging {
linuxPackageSymlinks in Debian <+= (normalizedName, defaultLinuxInstallLocation) map {
(name, install) => LinuxSymlink(install + "/" + name + "/logs", "/var/log/" + name)
},
// TODO - only make these if the upstart config exists...
debianMakePrermScript <<= (normalizedName, target in Universal) map makeDebianPrermScript,
debianMakePostrmScript <<= (normalizedName, target in Universal, serverLoading in Debian) map makeDebianPostrmScript,
debianMakePostinstScript <<= (normalizedName, target in Universal, serverLoading in Debian) map makeDebianPostinstScript)

private def makeDebianStartScript(
replacements: Seq[(String, String)], name: String, tmpDir: File, template: URL): Option[File] =
if (replacements.isEmpty) None
else {
val scriptBits = TemplateWriter.generateScript(template, replacements)
val script = tmpDir / "tmp" / "init" / name
IO.write(script, scriptBits)
Some(script)
}
// === Maintainer scripts ===
debianMakePreinstScript <<= (target in Universal, serverLoading in Debian, debianScriptReplacements) map makeDebianMaintainerScript(Preinst),
debianMakePostinstScript <<= (target in Universal, serverLoading in Debian, debianScriptReplacements) map makeDebianMaintainerScript(Postinst),
debianMakePrermScript <<= (target in Universal, serverLoading in Debian, debianScriptReplacements) map makeDebianMaintainerScript(Prerm),
debianMakePostrmScript <<= (target in Universal, serverLoading in Debian, debianScriptReplacements) map makeDebianMaintainerScript(Postrm))

protected def makeDebianPrermScript(name: String, tmpDir: File): Option[File] = {
val scriptBits = JavaAppStartScript.generatePrerm(name)
val script = tmpDir / "tmp" / "bin" / "debian-prerm"
IO.write(script, scriptBits)
Some(script)
}

protected def makeDebianPostrmScript(name: String, tmpDir: File, loader: ServerLoader): Option[File] = {
JavaAppStartScript.generatePostrm(name, loader) match {
case Some(scriptBits) =>
val script = tmpDir / "tmp" / "bin" / "debian-postrm"
IO.write(script, scriptBits)
Some(script)
case None => None
protected def makeDebianMaintainerScript(scriptName: String, template: Option[URL] = None)(
tmpDir: File, loader: ServerLoader, replacements: Seq[(String, String)]): Option[File] = {
JavaAppStartScript.generateTemplate(scriptName, loader, replacements, template) map { scriptBits =>
val script = tmpDir / "tmp" / "bin" / ("debian-" + scriptName)
IO.write(script, scriptBits)
script
}
}

protected def makeDebianPostinstScript(name: String, tmpDir: File, loader: ServerLoader): Option[File] = {
val scriptBits = JavaAppStartScript.generatePostinst(name, loader)
val script = tmpDir / "tmp" / "bin" / "debian-postinst"
IO.write(script, scriptBits)
Some(script)
}

protected def makeEtcDefaultScript(name: String, tmpDir: File, loader: ServerLoader, source: java.net.URL): Option[File] = {
loader match {
case Upstart => None
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/com/typesafe/sbt/packager/debian/Keys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ trait DebianKeys {
""".stripMargin)

val debianMakeStartScript = TaskKey[Option[File]]("makeStartScript", "Creates or discovers the start script used by this project")
val debianStartScriptReplacements = TaskKey[Seq[(String, String)]]("upstartScriptReplacements",
val debianScriptReplacements = TaskKey[Seq[(String, String)]]("upstartScriptReplacements",
"""|Replacements of template parameters used in the upstart script.
| Default supported templates:
| execScript - name of the script in /usr/bin
Expand Down

0 comments on commit d7982dc

Please sign in to comment.